Files
MeowOS-SDK/tuku/logic/reader/page_cache.h
T
AskaEth 562cc44931 feat(tuku): CBZ 档案册集成——档案页源/书库列册/解压缓存
- logic/reader/archive_source.c:档案册页源实现 M6 mr_book 契约
  (mz_open/mz_count/mz_entry_at/mz_read_alloc),条目自然序 + 图片后缀 +
  路径安全(`..`/绝对路径/反斜杠/隐藏段/内嵌 NUL)+ 单页尺寸上限过滤;
  meta 按需解压只读图片头(不落缓存,结果按页记忆);mr_book_open_auto
  统一目录册/档案册开册,翻页与条漫两套消费代码零改动。
- logic/reader/page_cache.c/h:解压页落 MeowData/<pkg>/cache,LRU 64 页或
  32MiB,启动清 mrpage_* 孤儿,写入 .part + rename;与缩略图缓存同目录、
  前缀隔离;互斥量保护,解码/缩略图线程可并发。
- logic/library.c/h:扫描直接子文件里的 .cbz/.zip 成册(行=文件名+页数,
  点入直接阅读);档案探测由调用方注入(logic 不依赖 zip 容器),不注入时
  与 M7 行为逐字一致;册间衔接兄弟表=含图目录∪含页档案册,同列自然序。
  条目构造/副标题/角标/兄弟判据拆成小函数,便于 M13 书库重写拼接。
- ui/library:档案册行 + 封面缩略图(解压档内首图)、扫描注入探测、缓存
  目录统一由 page_cache 推导(一份规则)。
- ui/reader:open_book 走 mr_book_open_auto;跨册衔接纳入档案册。
- build_tuku.sh 补 zip/archive/cache 源与 sysroot zlib 头(zip.c include
  <zlib.h>);run_tests.sh 纳入 zip+cbz 用例;run_webtoon_tests.sh 的宿主
  集成构建补新源与 -lz;.gitignore 同步测试产物。
- test/test_cbz.c(267 项断言)+ make_cbz_samples.py 真实 cbz 夹具:
  列档/自然序/解压字节 CRC/路径安全/坏档与 zip 炸弹容错/LRU 与 32MiB 上限/
  启动清孤儿/续读角标/封面首图。
2026-11-05 11:58:12 +08:00

69 lines
3.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* logic/reader/page_cache.h — 档案册解压页的磁盘缓存(纯 C,不依赖 SDK)。
*
* 为什么需要磁盘缓存:SDK 的图像解码入口只吃文件路径(meow_img_load_file_dim),
* 而 zip 里的页是压缩流。档案页源在 open(i) 时把条目解压成缓存文件,再用同一个
* 解码回调按路径解码——两种阅读模式(翻页/条漫)与目录册走完全相同的代码路径。
*
* 目录与上限(纪律):
* - 目录 = <数据目录>/cache(数据目录形如 .../MeowData/os.meow.picobrowser/data,
* 与缩略图缓存同目录;文件名统一前缀 mrpage_,与缩略图 *.bmp 互不影响);
* - 上限 = 64 页 或 32MiB,先到者触发 LRU 淘汰(按最近使用计数);
* - mr_cache_init() 首次成功时清掉上一进程遗留的 mrpage_*(孤儿页);
* - 写入走 "<name>.part" + rename,进程崩溃不会留下半个缓存文件。
*
* 键 = 档案路径 + 档案 mtime/size + 条目名 + 页下标:档案被替换(mtime/size 变)或
* 同名条目重复出现时不会命中旧内容。文件名保留图片扩展名(解码入口按扩展名区分
* JPEG 的「解码期缩解」路径)。
*
* 线程:内部互斥量;可在解码线程/缩略图线程/主线程并发调用。
* 纯 C:宿主测试可直接编译(见 tuku/test/test_cbz.c)。
*/
#ifndef MR_PAGE_CACHE_H
#define MR_PAGE_CACHE_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MR_CACHE_MAX_PAGES 64
#define MR_CACHE_MAX_BYTES (32LL * 1024 * 1024)
#define MR_CACHE_PREFIX "mrpage_"
#define MR_CACHE_DIR_MAX 200
#define MR_CACHE_FILE_MAX 256
/* 数据目录 → 缓存目录(纯字符串):末尾的 "data" 段替换为 "cache"。
* 例:/…/MeowData/os.meow.picobrowser/data → /…/MeowData/os.meow.picobrowser/cache。
* 成功 0;参数非法/缓冲不足 -1。 */
int mr_cache_dir_from_data(const char *data_dir, char *out, int outsz);
/* 建立/切换缓存目录并清孤儿。0=可用;-1=不可用(之后 store/touch 均失败)。
* 同一目录重复调用为无操作(不会删掉正在用的页)。 */
int mr_cache_init(const char *data_dir);
/* 释放索引(不删文件);测试用。可重复调用。 */
void mr_cache_shutdown(void);
int mr_cache_ready(void);
const char *mr_cache_dir(void); /* 未初始化返回空串 */
/* 计算某页缓存文件路径(不碰磁盘)。扩展名取自 entry 名(未知时 .img)。 */
int mr_cache_path(const char *archive, long long mtime, long long size,
const char *entry, int page_index, char *out, int outsz);
/* 缓存命中:文件在索引里(或磁盘上存在)则刷新 LRU 并返回 1,否则 0。 */
int mr_cache_touch(const char *path);
/* 写入缓存并纳入 LRU;1=成功。len==0 视为失败(空页没有解码价值)。 */
int mr_cache_store(const char *path, const void *data, size_t len);
/* 观测(宿主测试断言 LRU 纪律用):当前索引页数 / 字节数。 */
int mr_cache_count(void);
long long mr_cache_bytes(void);
#ifdef __cplusplus
}
#endif
#endif /* MR_PAGE_CACHE_H */