- 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 上限/ 启动清孤儿/续读角标/封面首图。
69 lines
3.1 KiB
C
69 lines
3.1 KiB
C
/* 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 */
|