fix(reader): txt编码误判(UTF-8前窗截断判GB18030致乱码) + build_index无持久化(整本重排慢/UI阻塞卡) — ①rd_utf8_sample_ok结尾不完整序列按合法(中间非法仍拒,GBK不误判,新增t13回归) ②索引落盘MeowData/os.meow.reader/index/*.idx(失效键size/mtime/font/fs/ls/wh/enc,命中秒开,原子写+强自检弃坏缓存,编码/字号/行距重排重写) 重开<0.3s/首开建cache; test_reader_core 72-0, 0warning

This commit is contained in:
AskaEth committed 2026-11-04 19:47:10 +08:00
1 parent 68710d7ed8
commit a64ae06eb6
5 files changed
+257 -4

No files matched your search

+20 -1
View File
@@ -322,10 +322,29 @@ static void t12(void)
remove(path);
}
/* t13 — 大 UTF-8 书编码检测:前 64KB 窗口恰在多字节字符中间截断时仍判 UTF-8。
* 复现 M6.42《这游戏》乱码:rdtxt_probe 读前 64KB → rd_enc_detect 严格 UTF-8 校验因末尾
* 半个汉字失败 → 落入 GB18030 兜底 → 全书按 GB18030 解码 → 乱码。此处必须判回 UTF-8。 */
static void t13(void)
{
uint8_t buf[65536];
const uint8_t cjk[] = { 0xE4, 0xBD, 0xA0 }; /* 「你」= 3 字节 CJK */
size_t o = 0;
while (o + 3 <= 65535) { memcpy(buf + o, cjk, 3); o += 3; } /* o == 65535 */
buf[o] = 0xE4; /* 末尾 1 字节 = 半个汉字(3 字节序列被 64KB 窗口切断) */
size_t len = o + 1; /* 65536:rdtxt_probe 读满 64KB */
CHECK(len == 65536, "t13 len");
CHECK(rd_utf8_validate(buf, len) == 0, "t13 strict rejects trailing truncation");
CHECK(rd_enc_detect(buf, len, NULL) == RD_ENC_UTF8, "t13 detect utf8 despite mid-char cut");
/* 对照:GBK 仍须判 GB18030(样本宽容不得误伤 GBK) */
const uint8_t gbk[] = { 0xC4, 0xE3, 0xBA, 0xC3 };
CHECK(rd_enc_detect(gbk, sizeof gbk, NULL) == RD_ENC_GB18030, "t13 gbk still gb18030");
}
int main(void)
{
t1(); t2(); t3(); t4(); t5();
t6(); t7(); t8(); t9(); t10(); t11(); t12();
t6(); t7(); t8(); t9(); t10(); t11(); t12(); t13();
printf("test_reader_core: %d pass, %d fail\n", g_pass, g_fail);
return g_fail ? 1 : 0;
}