From e1cb560df05fef91e4e8547ee98788deded20da7 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 9 Aug 2026 22:19:29 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E5=AF=B9=E8=B1=A1=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E5=90=8E=E7=A8=B3=E5=AE=9A=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OopInheritTest 全部类补类体字段声明(x/y/r/w/h/health/battery 等), 保证父类字段展平与 GEP 偏移正确 - 多个测试适配 i8* 指针比较语义(== 指针地址比较改 string.strcmp) - 删除 ZlibTest/__zlib 旧实现与 find.py 调试脚本 - 更新 TODO 与 TestProject --- TODO | 3 +- Test/DictTest/App/main.vp | 7 +- Test/EqTest/App/main.vp | 13 +- Test/FakeDuckTest/App/main.vp | 44 +- Test/HashTableTest/App/main.vp | 7 +- Test/IterTest/App/main.vp | 3 +- Test/JsonTest/App/main.vp | 26 +- Test/LLvmLiteTest/App/main.vp | 32 +- Test/NoVTableTest/App/main.vp | 1 - Test/OopInheritTest/App/main.vp | 23 + Test/PointerTest/App/main.vp | 16 +- Test/StringIterTest/App/main.vp | 8 +- Test/ZlibTest/App/__zlib/__init__.vp | 0 Test/ZlibTest/App/__zlib/pyzlib.vp | 549 --------------- Test/ZlibTest/App/__zlib/test_pyzlib.vp | 877 ------------------------ Test/ZlibTest/App/__zlib/zchecksum.vp | 90 --- Test/ZlibTest/App/__zlib/zdef.vp | 269 -------- Test/ZlibTest/App/__zlib/zdeflate.vp | 429 ------------ Test/ZlibTest/App/__zlib/zhuff.vp | 353 ---------- Test/ZlibTest/App/__zlib/zinflate.vp | 454 ------------ TestProject/App/main.vp | 22 +- a.vp | 27 + find.py | 163 ----- 23 files changed, 151 insertions(+), 3265 deletions(-) delete mode 100644 Test/ZlibTest/App/__zlib/__init__.vp delete mode 100644 Test/ZlibTest/App/__zlib/pyzlib.vp delete mode 100644 Test/ZlibTest/App/__zlib/test_pyzlib.vp delete mode 100644 Test/ZlibTest/App/__zlib/zchecksum.vp delete mode 100644 Test/ZlibTest/App/__zlib/zdef.vp delete mode 100644 Test/ZlibTest/App/__zlib/zdeflate.vp delete mode 100644 Test/ZlibTest/App/__zlib/zhuff.vp delete mode 100644 Test/ZlibTest/App/__zlib/zinflate.vp create mode 100644 a.vp delete mode 100644 find.py diff --git a/TODO b/TODO index c359d22..91b4a0a 100644 --- a/TODO +++ b/TODO @@ -43,4 +43,5 @@ TPV 再次支持泛型能力检查和字节序 TPV 避免虚类问题,参见 ast/base.vp:224行 TPV 虚类判断问题,参见 ast/parser.vp:2037行 -替换式实现注入猴子,带有含函数指针检测和函数指针还原 \ No newline at end of file +替换式实现注入猴子,带有含函数指针检测和函数指针还原 + diff --git a/Test/DictTest/App/main.vp b/Test/DictTest/App/main.vp index c580522..d2ef803 100644 --- a/Test/DictTest/App/main.vp +++ b/Test/DictTest/App/main.vp @@ -98,9 +98,10 @@ def main() -> CInt | CExport: city: str = city_p lang: str = lang_p stdio.printf("name=%s city=%s lang=%s\n", name, city, lang) - testcheck.check(name == "Alice", "dict str name OK", "dict str name FAILED") - testcheck.check(city == "Beijing", "dict str city OK", "dict str city FAILED") - testcheck.check(lang == "TransPyC", "dict str lang OK", "dict str lang FAILED") + # i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp + testcheck.check(string.strcmp(name, "Alice") == 0, "dict str name OK", "dict str name FAILED") + testcheck.check(string.strcmp(city, "Beijing") == 0, "dict str city OK", "dict str city FAILED") + testcheck.check(string.strcmp(lang, "TransPyC") == 0, "dict str lang OK", "dict str lang FAILED") # === Test 7: dict[str] 迭代 === testcheck.section("Test 7: dict 迭代 (str values)") diff --git a/Test/EqTest/App/main.vp b/Test/EqTest/App/main.vp index ba3db77..865cf91 100644 --- a/Test/EqTest/App/main.vp +++ b/Test/EqTest/App/main.vp @@ -19,18 +19,19 @@ def main() -> CInt | CExport: s1: str = "hello" s2: str = "hello" s3: str = "world" - testcheck.check(s1 == s2, "str == str (same value) OK", "str == str (same value) FAILED") - testcheck.check(not (s1 == s3), "str != str (diff value) OK", "str != str (diff value) FAILED") + # i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp + testcheck.check(string.strcmp(s1, s2) == 0, "str == str (same value) OK", "str == str (same value) FAILED") + testcheck.check(string.strcmp(s1, s3) != 0, "str != str (diff value) OK", "str != str (diff value) FAILED") # === Test 2: str != str === testcheck.section("Test 2: str != str") - testcheck.check(s1 != s3, "str != str (diff) OK", "str != str (diff) FAILED") - testcheck.check(not (s1 != s2), "str == str (same) via != OK", "str == str (same) via != FAILED") + testcheck.check(string.strcmp(s1, s3) != 0, "str != str (diff) OK", "str != str (diff) FAILED") + testcheck.check(string.strcmp(s1, s2) == 0, "str == str (same) via != OK", "str == str (same) via != FAILED") # === Test 3: str == 字面量 === testcheck.section("Test 3: str == literal") - testcheck.check(s1 == "hello", "str == literal OK", "str == literal FAILED") - testcheck.check(not (s1 == "world"), "str != literal OK", "str != literal FAILED") + testcheck.check(string.strcmp(s1, "hello") == 0, "str == literal OK", "str == literal FAILED") + testcheck.check(string.strcmp(s1, "world") != 0, "str != literal OK", "str != literal FAILED") # === Test 4: str is str 地址比较 === testcheck.section("Test 4: str is str address compare") diff --git a/Test/FakeDuckTest/App/main.vp b/Test/FakeDuckTest/App/main.vp index 6dc24dc..ead0e0b 100644 --- a/Test/FakeDuckTest/App/main.vp +++ b/Test/FakeDuckTest/App/main.vp @@ -116,9 +116,9 @@ def main() -> CInt | CExport: p1: str = parts[1] p2: str = parts[2] stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", p0, p1, p2) - testcheck.check(p0 == "a", "split[0]=='a' OK", "split[0] FAILED") - testcheck.check(p1 == "b", "split[1]=='b' OK", "split[1] FAILED") - testcheck.check(p2 == "c", "split[2]=='c' OK", "split[2] FAILED") + testcheck.check(string.strcmp(p0, "a") == 0, "split[0]=='a' OK", "split[0] FAILED") + testcheck.check(string.strcmp(p1, "b") == 0, "split[1]=='b' OK", "split[1] FAILED") + testcheck.check(string.strcmp(p2, "c") == 0, "split[2]=='c' OK", "split[2] FAILED") # Test 2: 空字符串分割 testcheck.section("Test 2: 无分隔符 'hello'") @@ -129,7 +129,7 @@ def main() -> CInt | CExport: stdio.printf("split('hello', ',') len=%lu\n", n2) testcheck.check(n2 == 1, "no-delim len OK (1)", "no-delim len FAILED expect 1") h0: str = parts2.get(0) - testcheck.check(h0 == "hello", "no-delim[0]=='hello' OK", "no-delim[0] FAILED") + testcheck.check(string.strcmp(h0, "hello") == 0, "no-delim[0]=='hello' OK", "no-delim[0] FAILED") # Test 3: 连续分隔符 testcheck.section("Test 3: 连续分隔符 'a,,b'") @@ -143,9 +143,9 @@ def main() -> CInt | CExport: e1: str = parts3.get(1) e2: str = parts3.get(2) stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", e0, e1, e2) - testcheck.check(e0 == "a", "consec[0]=='a' OK", "consec[0] FAILED") - testcheck.check(e1 == "", "consec[1]=='' OK", "consec[1] FAILED") - testcheck.check(e2 == "b", "consec[2]=='b' OK", "consec[2] FAILED") + testcheck.check(string.strcmp(e0, "a") == 0, "consec[0]=='a' OK", "consec[0] FAILED") + testcheck.check(string.strcmp(e1, "") == 0, "consec[1]=='' OK", "consec[1] FAILED") + testcheck.check(string.strcmp(e2, "b") == 0, "consec[2]=='b' OK", "consec[2] FAILED") # Test 4: 空字符串 testcheck.section("Test 4: 空字符串 ''") @@ -168,9 +168,9 @@ def main() -> CInt | CExport: w1: str = parts5[1] w2: str = parts5[2] stdio.printf("words[0]='%s' [1]='%s' [2]='%s'\n", w0, w1, w2) - testcheck.check(w0 == "hello", "space[0]=='hello' OK", "space[0] FAILED") - testcheck.check(w1 == "world", "space[1]=='world' OK", "space[1] FAILED") - testcheck.check(w2 == "foo", "space[2]=='foo' OK", "space[2] FAILED") + testcheck.check(string.strcmp(w0, "hello") == 0, "space[0]=='hello' OK", "space[0] FAILED") + testcheck.check(string.strcmp(w1, "world") == 0, "space[1]=='world' OK", "space[1] FAILED") + testcheck.check(string.strcmp(w2, "foo") == 0, "space[2]=='foo' OK", "space[2] FAILED") # Test 6: 多字符分隔符 '::' testcheck.section("Test 6: 多字符分隔符 '::' on 'a::b::c'") @@ -184,9 +184,9 @@ def main() -> CInt | CExport: m1: str = parts6[1] m2: str = parts6[2] stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", m0, m1, m2) - testcheck.check(m0 == "a", "multi-colon[0]=='a' OK", "multi-colon[0] FAILED") - testcheck.check(m1 == "b", "multi-colon[1]=='b' OK", "multi-colon[1] FAILED") - testcheck.check(m2 == "c", "multi-colon[2]=='c' OK", "multi-colon[2] FAILED") + testcheck.check(string.strcmp(m0, "a") == 0, "multi-colon[0]=='a' OK", "multi-colon[0] FAILED") + testcheck.check(string.strcmp(m1, "b") == 0, "multi-colon[1]=='b' OK", "multi-colon[1] FAILED") + testcheck.check(string.strcmp(m2, "c") == 0, "multi-colon[2]=='c' OK", "multi-colon[2] FAILED") # Test 7: 多字符分隔符 ', ' (逗号+空格) testcheck.section("Test 7: 多字符分隔符 ', ' on 'hello, world, foo'") @@ -200,9 +200,9 @@ def main() -> CInt | CExport: cs1: str = parts7[1] cs2: str = parts7[2] stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", cs0, cs1, cs2) - testcheck.check(cs0 == "hello", "comma-space[0]=='hello' OK", "comma-space[0] FAILED") - testcheck.check(cs1 == "world", "comma-space[1]=='world' OK", "comma-space[1] FAILED") - testcheck.check(cs2 == "foo", "comma-space[2]=='foo' OK", "comma-space[2] FAILED") + testcheck.check(string.strcmp(cs0, "hello") == 0, "comma-space[0]=='hello' OK", "comma-space[0] FAILED") + testcheck.check(string.strcmp(cs1, "world") == 0, "comma-space[1]=='world' OK", "comma-space[1] FAILED") + testcheck.check(string.strcmp(cs2, "foo") == 0, "comma-space[2]=='foo' OK", "comma-space[2] FAILED") # Test 8: 多字符分隔符在首尾 testcheck.section("Test 8: 多字符分隔符首尾 '::a::b::'") @@ -217,10 +217,10 @@ def main() -> CInt | CExport: ed2: str = parts8[2] ed3: str = parts8[3] stdio.printf("parts[0]='%s' [1]='%s' [2]='%s' [3]='%s'\n", ed0, ed1, ed2, ed3) - testcheck.check(ed0 == "", "edge[0]=='' OK", "edge[0] FAILED") - testcheck.check(ed1 == "a", "edge[1]=='a' OK", "edge[1] FAILED") - testcheck.check(ed2 == "b", "edge[2]=='b' OK", "edge[2] FAILED") - testcheck.check(ed3 == "", "edge[3]=='' OK", "edge[3] FAILED") + testcheck.check(string.strcmp(ed0, "") == 0, "edge[0]=='' OK", "edge[0] FAILED") + testcheck.check(string.strcmp(ed1, "a") == 0, "edge[1]=='a' OK", "edge[1] FAILED") + testcheck.check(string.strcmp(ed2, "b") == 0, "edge[2]=='b' OK", "edge[2] FAILED") + testcheck.check(string.strcmp(ed3, "") == 0, "edge[3]=='' OK", "edge[3] FAILED") # === with 上下文自动注入测试 === testcheck.section("Test 9: with 上下文自动注入 __mbuddy__") @@ -237,12 +237,12 @@ def main() -> CInt | CExport: # upper() 不需要手动设置 __mbuddy__ w_upper: str = w_str.upper() stdio.printf("with upper('WithTest') = %s\n", w_upper) - testcheck.check(w_upper == "WITHTEST", "with upper OK", "with upper FAILED") + testcheck.check(string.strcmp(w_upper, "WITHTEST") == 0, "with upper OK", "with upper FAILED") # lower() 不需要手动设置 __mbuddy__ w_lower: str = w_str.lower() stdio.printf("with lower('WithTest') = %s\n", w_lower) - testcheck.check(w_lower == "withtest", "with lower OK", "with lower FAILED") + testcheck.check(string.strcmp(w_lower, "withtest") == 0, "with lower OK", "with lower FAILED") # split() 不需要手动设置 __mbuddy__ w_split_str: str = "x,y,z" diff --git a/Test/HashTableTest/App/main.vp b/Test/HashTableTest/App/main.vp index fe01ad1..ad5b050 100644 --- a/Test/HashTableTest/App/main.vp +++ b/Test/HashTableTest/App/main.vp @@ -116,9 +116,10 @@ def main() -> CInt | CExport: city: str = city_p lang: str = lang_p stdio.printf("name=%s city=%s lang=%s\n", name, city, lang) - testcheck.check(name == "Alice", "ht str name OK", "ht str name FAILED") - testcheck.check(city == "Beijing", "ht str city OK", "ht str city FAILED") - testcheck.check(lang == "TransPyC", "ht str lang OK", "ht str lang FAILED") + # i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp + testcheck.check(string.strcmp(name, "Alice") == 0, "ht str name OK", "ht str name FAILED") + testcheck.check(string.strcmp(city, "Beijing") == 0, "ht str city OK", "ht str city FAILED") + testcheck.check(string.strcmp(lang, "TransPyC") == 0, "ht str lang OK", "ht str lang FAILED") # === Test 9: 扩容测试 === testcheck.section("Test 9: 扩容测试 (>16 个元素)") diff --git a/Test/IterTest/App/main.vp b/Test/IterTest/App/main.vp index 7ff01a7..7b063ee 100644 --- a/Test/IterTest/App/main.vp +++ b/Test/IterTest/App/main.vp @@ -39,7 +39,8 @@ def test_strcpy_for_in(): p[0] = ch p += 1 p[0] = 0 - testcheck.check(buf == "test", "strcpy for-in (result=test)", "strcpy for-in (cmp mismatch)") + # i8* == 是指针地址比较(C-Like 语义),字符串内容比较需显式 strcmp + testcheck.check(string.strcmp(buf, "test") == 0, "strcpy for-in (result=test)", "strcpy for-in (cmp mismatch)") import w32.win32memory diff --git a/Test/JsonTest/App/main.vp b/Test/JsonTest/App/main.vp index b396c7b..a355f17 100644 --- a/Test/JsonTest/App/main.vp +++ b/Test/JsonTest/App/main.vp @@ -41,7 +41,7 @@ def test_construct(pool: memhub.MemPool | t.CPtr): # string v7: json.JsonValue | t.CPtr = json.string_val(pool, "hello") testcheck.check(v7.is_string(), "string is_string", "string is_string") - testcheck.check(v7.as_string() == "hello", "string == hello", "string == hello") + testcheck.check(string.strcmp(v7.as_string(), "hello") == 0, "string == hello", "string == hello") # array v8: json.JsonValue | t.CPtr = json.array(pool) @@ -78,7 +78,7 @@ def test_build_structures(pool: memhub.MemPool | t.CPtr): # Python风格取值:obj["key"] name_val: json.JsonValue | t.CPtr = obj["name"] - testcheck.check(name_val != None and name_val.as_string() == "Viper", "obj['name']==Viper", "obj['name']==Viper") + testcheck.check(name_val != None and string.strcmp(name_val.as_string(), "Viper") == 0, "obj['name']==Viper", "obj['name']==Viper") ver_val: json.JsonValue | t.CPtr = obj["version"] testcheck.check(ver_val != None and ver_val.as_int() == 1, "obj['version']==1", "obj['version']==1") missing: json.JsonValue | t.CPtr = obj["missing"] @@ -108,7 +108,7 @@ def test_parse(pool: memhub.MemPool | t.CPtr): # 解析字符串 v4: json.JsonValue | t.CPtr = json.parse(pool, '"hello world"') testcheck.check(v4.is_string(), "parse string is_string", "parse string is_string") - testcheck.check(v4.as_string() == "hello world", "parse string == hello world", "parse string == hello world") + testcheck.check(string.strcmp(v4.as_string(), "hello world") == 0, "parse string == hello world", "parse string == hello world") # 解析布尔 v5: json.JsonValue | t.CPtr = json.parse(pool, "true") @@ -148,7 +148,7 @@ def test_write(pool: memhub.MemPool | t.CPtr): # 写整数 v1: json.JsonValue | t.CPtr = json.int_val(pool, 42) s1: t.CChar | t.CPtr = json.write(pool, v1, False) - testcheck.check(s1 == "42", "write int 42", "write int 42") + testcheck.check(string.strcmp(s1, "42") == 0, "write int 42", "write int 42") # 写字符串 v2: json.JsonValue | t.CPtr = json.string_val(pool, "hello") @@ -158,16 +158,16 @@ def test_write(pool: memhub.MemPool | t.CPtr): # 写布尔 v3: json.JsonValue | t.CPtr = json.bool_val(pool, True) s3: t.CChar | t.CPtr = json.write(pool, v3, False) - testcheck.check(s3 == "true", "write bool true", "write bool true") + testcheck.check(string.strcmp(s3, "true") == 0, "write bool true", "write bool true") v4: json.JsonValue | t.CPtr = json.bool_val(pool, False) s4: t.CChar | t.CPtr = json.write(pool, v4, False) - testcheck.check(s4 == "false", "write bool false", "write bool false") + testcheck.check(string.strcmp(s4, "false") == 0, "write bool false", "write bool false") # 写 null v5: json.JsonValue | t.CPtr = json.null(pool) s5: t.CChar | t.CPtr = json.write(pool, v5, False) - testcheck.check(s5 == "null", "write null", "write null") + testcheck.check(string.strcmp(s5, "null") == 0, "write null", "write null") # 写数组 arr: json.JsonValue | t.CPtr = json.array(pool) @@ -175,7 +175,7 @@ def test_write(pool: memhub.MemPool | t.CPtr): json.array_append(pool, arr, json.int_val(pool, 2)) json.array_append(pool, arr, json.int_val(pool, 3)) s6: t.CChar | t.CPtr = json.write(pool, arr, False) - testcheck.check(s6 == "[1,2,3]", "write array [1,2,3]", "write array [1,2,3]") + testcheck.check(string.strcmp(s6, "[1,2,3]") == 0, "write array [1,2,3]", "write array [1,2,3]") # 写对象 obj: json.JsonValue | t.CPtr = json.object(pool) @@ -198,7 +198,7 @@ def test_nested(pool: memhub.MemPool | t.CPtr): # Python风格取值:root["name"] name: json.JsonValue | t.CPtr = root["name"] - testcheck.check(name != None and name.as_string() == "Viper", "root['name']==Viper", "root['name']==Viper") + testcheck.check(name != None and string.strcmp(name.as_string(), "Viper") == 0, "root['name']==Viper", "root['name']==Viper") # root["version"] ver: json.JsonValue | t.CPtr = root["version"] @@ -208,14 +208,14 @@ def test_nested(pool: memhub.MemPool | t.CPtr): feat: json.JsonValue | t.CPtr = root["features"] testcheck.check(feat != None and feat.is_array(), "root['features'] is_array", "root['features'] is_array") testcheck.check(feat != None and len(feat) == 3, "root['features'] len()==3", "root['features'] len()==3") - testcheck.check(feat != None and feat.get_item(0).as_string() == "fast", "root['features'][0]==fast", "root['features'][0]==fast") - testcheck.check(feat != None and feat.get_item(2).as_string() == "portable", "root['features'][2]==portable", "root['features'][2]==portable") + testcheck.check(feat != None and string.strcmp(feat.get_item(0).as_string(), "fast") == 0, "root['features'][0]==fast", "root['features'][0]==fast") + testcheck.check(feat != None and string.strcmp(feat.get_item(2).as_string(), "portable") == 0, "root['features'][2]==portable", "root['features'][2]==portable") # root["nested"] 对象 nested: json.JsonValue | t.CPtr = root["nested"] testcheck.check(nested != None and nested.is_object(), "root['nested'] is_object", "root['nested'] is_object") nk: json.JsonValue | t.CPtr = nested["key"] if nested != None else None - testcheck.check(nk != None and nk.as_string() == "value", "root['nested']['key']==value", "root['nested']['key']==value") + testcheck.check(nk != None and string.strcmp(nk.as_string(), "value") == 0, "root['nested']['key']==value", "root['nested']['key']==value") nn: json.JsonValue | t.CPtr = nested["num"] if nested != None else None testcheck.check(nn != None and nn.as_int() == 99, "root['nested']['num']==99", "root['nested']['num']==99") @@ -241,7 +241,7 @@ def test_mpool_reuse(): # 第二次使用(内存复用) v2: json.JsonValue | t.CPtr = json.string_val(pool, "reused") - testcheck.check(v2.as_string() == "reused", "reuse round2 string==reused", "reuse round2 string==reused") + testcheck.check(string.strcmp(v2.as_string(), "reused") == 0, "reuse round2 string==reused", "reuse round2 string==reused") # 重置后再解析 pool.reset() diff --git a/Test/LLvmLiteTest/App/main.vp b/Test/LLvmLiteTest/App/main.vp index 9395df2..a8c2c17 100644 --- a/Test/LLvmLiteTest/App/main.vp +++ b/Test/LLvmLiteTest/App/main.vp @@ -24,7 +24,7 @@ def test_type_print(pool: memhub.MemPool | t.CPtr): ty_i32: llvmlite.LLVMType | t.CPtr = core.Int32() buf[0] = 0 core.PrintType(buf, 64, ty_i32) - testcheck.check(buf == "i32", + testcheck.check(string.strcmp(buf, "i32") == 0, "Int32 -> i32", "Int32 fail") @@ -32,7 +32,7 @@ def test_type_print(pool: memhub.MemPool | t.CPtr): ty_ptr: llvmlite.LLVMType | t.CPtr = core.Ptr(ty_i32) buf[0] = 0 core.PrintType(buf, 64, ty_ptr) - testcheck.check(buf == "i32*", + testcheck.check(string.strcmp(buf, "i32*") == 0, "Ptr(Int32) -> i32*", "Ptr fail") @@ -40,7 +40,7 @@ def test_type_print(pool: memhub.MemPool | t.CPtr): ty_void: llvmlite.LLVMType | t.CPtr = core.Void() buf[0] = 0 core.PrintType(buf, 64, ty_void) - testcheck.check(buf == "void", + testcheck.check(string.strcmp(buf, "void") == 0, "Void -> void", "Void fail") @@ -48,7 +48,7 @@ def test_type_print(pool: memhub.MemPool | t.CPtr): ty_i64: llvmlite.LLVMType | t.CPtr = core.Int64() buf[0] = 0 core.PrintType(buf, 64, ty_i64) - testcheck.check(buf == "i64", + testcheck.check(string.strcmp(buf, "i64") == 0, "Int64 -> i64", "Int64 fail") @@ -68,7 +68,7 @@ def test_value_print(pool: memhub.MemPool | t.CPtr): val42: llvmlite.Value | t.CPtr = mcore.ConstInt32(42) buf[0] = 0 mcore.PrintValue(buf, 64, val42) - testcheck.check(buf == "i32 42", + testcheck.check(string.strcmp(buf, "i32 42") == 0, "ConstInt(42) -> i32 42", "ConstInt fail") @@ -78,7 +78,7 @@ def test_value_print(pool: memhub.MemPool | t.CPtr): val_ssa: llvmlite.Value | t.CPtr = mcore.SSAValue(ty_i32, name_ssa) buf[0] = 0 mcore.PrintValue(buf, 64, val_ssa) - testcheck.check(buf == "i32 %0", + testcheck.check(string.strcmp(buf, "i32 %0") == 0, "SSAValue(%0) -> i32 %0", "SSAValue fail") @@ -293,7 +293,7 @@ def test_array_type(pool: memhub.MemPool | t.CPtr): ty_arr: llvmlite.LLVMType | t.CPtr = core.Array(ty_i32, 4) buf[0] = 0 core.PrintType(buf, 128, ty_arr) - testcheck.check(buf == "[4 x i32]", + testcheck.check(string.strcmp(buf, "[4 x i32]") == 0, "Array(i32,4) -> [4 x i32]", "Array fail") @@ -303,7 +303,7 @@ def test_array_type(pool: memhub.MemPool | t.CPtr): ty_nested: llvmlite.LLVMType | t.CPtr = core.Array(ty_inner, 2) buf[0] = 0 core.PrintType(buf, 128, ty_nested) - testcheck.check(buf == "[2 x [3 x i8]]", + testcheck.check(string.strcmp(buf, "[2 x [3 x i8]]") == 0, "nested array -> [2 x [3 x i8]]", "nested array fail") @@ -328,7 +328,7 @@ def test_struct_type(pool: memhub.MemPool | t.CPtr): ty_struct: llvmlite.LLVMType | t.CPtr = core.Struct(head, 2) buf[0] = 0 core.PrintType(buf, 128, ty_struct) - testcheck.check(buf == "{i32, i8*}", + testcheck.check(string.strcmp(buf, "{i32, i8*}") == 0, "struct {i32, i8*}", "struct fail") @@ -336,7 +336,7 @@ def test_struct_type(pool: memhub.MemPool | t.CPtr): ty_empty: llvmlite.LLVMType | t.CPtr = core.Struct(None, 0) buf[0] = 0 core.PrintType(buf, 128, ty_empty) - testcheck.check(buf == "{}", + testcheck.check(string.strcmp(buf, "{}") == 0, "empty struct -> {}", "empty struct fail") @@ -361,7 +361,7 @@ def test_func_type(pool: memhub.MemPool | t.CPtr): ty_func: llvmlite.LLVMType | t.CPtr = core.Func(ty_i32, head, 2) buf[0] = 0 core.PrintType(buf, 128, ty_func) - testcheck.check(buf == "i32 (i32, i8*)", + testcheck.check(string.strcmp(buf, "i32 (i32, i8*)") == 0, "func type -> i32 (i32, i8*)", "func type fail") @@ -370,7 +370,7 @@ def test_func_type(pool: memhub.MemPool | t.CPtr): ty_func_void: llvmlite.LLVMType | t.CPtr = core.Func(ty_void, None, 0) buf[0] = 0 core.PrintType(buf, 128, ty_func_void) - testcheck.check(buf == "void ()", + testcheck.check(string.strcmp(buf, "void ()") == 0, "void func -> void ()", "void func fail") @@ -431,7 +431,7 @@ def test_float_types(pool: memhub.MemPool | t.CPtr): ty_half: llvmlite.LLVMType | t.CPtr = core.Half() buf[0] = 0 core.PrintType(buf, 128, ty_half) - testcheck.check(buf == "half", + testcheck.check(string.strcmp(buf, "half") == 0, "Half -> half", "Half fail") @@ -439,7 +439,7 @@ def test_float_types(pool: memhub.MemPool | t.CPtr): ty_float: llvmlite.LLVMType | t.CPtr = core.Float() buf[0] = 0 core.PrintType(buf, 128, ty_float) - testcheck.check(buf == "float", + testcheck.check(string.strcmp(buf, "float") == 0, "Float -> float", "Float fail") @@ -447,7 +447,7 @@ def test_float_types(pool: memhub.MemPool | t.CPtr): ty_double: llvmlite.LLVMType | t.CPtr = core.Double() buf[0] = 0 core.PrintType(buf, 128, ty_double) - testcheck.check(buf == "double", + testcheck.check(string.strcmp(buf, "double") == 0, "Double -> double", "Double fail") @@ -455,7 +455,7 @@ def test_float_types(pool: memhub.MemPool | t.CPtr): ty_fp128: llvmlite.LLVMType | t.CPtr = core.FP128() buf[0] = 0 core.PrintType(buf, 128, ty_fp128) - testcheck.check(buf == "fp128", + testcheck.check(string.strcmp(buf, "fp128") == 0, "FP128 -> fp128", "FP128 fail") diff --git a/Test/NoVTableTest/App/main.vp b/Test/NoVTableTest/App/main.vp index 6e83389..ececb00 100644 --- a/Test/NoVTableTest/App/main.vp +++ b/Test/NoVTableTest/App/main.vp @@ -399,7 +399,6 @@ def test_sprintf_vararg(): class GSListNode[T]: Next: T | t.CPtr - @t.NoVTable class GSList[T]: Head: T | t.CPtr diff --git a/Test/OopInheritTest/App/main.vp b/Test/OopInheritTest/App/main.vp index 29801ec..10f0f1d 100644 --- a/Test/OopInheritTest/App/main.vp +++ b/Test/OopInheritTest/App/main.vp @@ -11,6 +11,9 @@ import testcheck @t.CVTable class Shape: + x: CFloat64T + y: CFloat64T + def __init__(self, x: CFloat64T, y: CFloat64T): self.x = x self.y = y @@ -23,6 +26,8 @@ class Shape: @t.CVTable class Circle(Shape): + r: CFloat64T + def __init__(self, x: CFloat64T, y: CFloat64T, r: CFloat64T): self.x = x self.y = y @@ -41,6 +46,9 @@ class Circle(Shape): @t.CVTable class Rect(Shape): + w: CFloat64T + h: CFloat64T + def __init__(self, x: CFloat64T, y: CFloat64T, w: CFloat64T, h: CFloat64T): self.x = x self.y = y @@ -129,6 +137,10 @@ class Vec3: @t.CVTable class Dog: + name_val: CInt + health: CInt32T + bark_power: CInt32T + def __init__(self, name_val: CInt, bark_power: CInt32T): self.name_val = name_val self.health = CInt32T(100) @@ -147,6 +159,10 @@ class Dog: @t.CVTable class Cat: + name_val: CInt + health: CInt32T + lives: CInt32T + def __init__(self, name_val: CInt, lives: CInt32T): self.name_val = name_val self.health = CInt32T(80) @@ -199,6 +215,9 @@ class Transform: @t.CVTable class Vehicle: + speed: CInt32T + fuel: CInt32T + def __init__(self, speed: CInt32T): self.speed = speed self.fuel = CInt32T(100) @@ -212,6 +231,8 @@ class Vehicle: @t.CVTable class Car(Vehicle): + doors: CInt32T + def __init__(self, speed: CInt32T, doors: CInt32T): self.speed = speed self.fuel = CInt32T(100) @@ -221,6 +242,8 @@ class Car(Vehicle): @t.CVTable class ElectricCar(Car): + battery: CInt32T + def __init__(self, speed: CInt32T, doors: CInt32T, battery: CInt32T): self.speed = speed self.fuel = CInt32T(100) diff --git a/Test/PointerTest/App/main.vp b/Test/PointerTest/App/main.vp index 93bbd22..648c8fa 100644 --- a/Test/PointerTest/App/main.vp +++ b/Test/PointerTest/App/main.vp @@ -24,7 +24,7 @@ def test_global_write_no_decl(): # 注意:这里故意不声明 global,测试编译器行为 # 如果 _g_val 在此函数之前被读取过,赋值会修改全局变量 # 如果 _g_val 在此函数中首次被赋值,会创建局部变量 - _g_val = 99 # 这应该创建一个局部变量 + _g_val: int = 99 # 这应该创建一个局部变量 def test_global_ptr(): global _g_ptr @@ -41,8 +41,9 @@ def test_global_ptr_no_decl(): # _g_ptr 在 test_global_ptr 中已被赋值(有 global) # 这里读取 _g_ptr 然后赋值 — 读取会将全局变量加入 Gen.variables # 所以后续赋值应该修改全局变量 - old: t.CUInt32T | t.CPtr = _g_ptr # 读取 -> 加入 Gen.variables - _g_ptr = None # 因为之前读取过,这应该修改全局变量 + # TPV 行为改变:读取不会使后续开始修改全局 + old: t.CUInt32T | t.CPtr = _g_ptr # 读取 -> 不加入 Gen.variables + _g_ptr: int = None # 因为之前读取过,这应该修改全局变量 # --- Test 2: 指针算术和数组索引 --- @@ -209,10 +210,10 @@ def main() -> t.CInt | t.CExport: l[0] = i print(l) - u: t.CArray[t.CUInt64T | t.BigEndian, 2] = [0x4141414141414141, 0x0000000000000000] - for i in c.Addr(u): - # l[0] = i - stdio.printf("0x%llx\n", i) + #u: t.CArray[t.CUInt64T | t.BigEndian, 2] = [0x4141414141414141, 0x0000000000000000] + #for i in c.Addr(u): + # # l[0] = i + # stdio.printf("0x%llx\n", i) k: t.CArray[t.CChar, 12] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'] for i in k: @@ -222,6 +223,7 @@ def main() -> t.CInt | t.CExport: # Test 1: global 声明 testcheck.section("Test 1: global declaration") + global _g_val _g_val = 0 test_global_write() stdio.printf("After test_global_write(): _g_val = %d (expect 42)\n", _g_val) diff --git a/Test/StringIterTest/App/main.vp b/Test/StringIterTest/App/main.vp index 8a5645c..de476e8 100644 --- a/Test/StringIterTest/App/main.vp +++ b/Test/StringIterTest/App/main.vp @@ -37,7 +37,7 @@ def test_string_ascii_sum(): def test_manual_strcpy(): testcheck.section("Test 3: manual strcpy via pointers") src: t.CChar | t.CPtr = "Test" - dst: list[t.CChar, 32] = [0] + dst: t.CArray[t.CChar, 32] = [0] sp: t.CChar | t.CPtr = src dp: t.CChar | t.CPtr = c.Addr(dst) while c.Deref(sp) != 0: @@ -52,7 +52,7 @@ def test_manual_strcpy(): # ============================================================ def test_ptr_offset_compare(): testcheck.section("Test 4: pointer offset and compare") - arr: list[t.CInt, 5] = [0] + arr: t.CArray[t.CInt, 5] = [0] for i in range(5): arr[i] = i * 10 p: t.CInt | t.CPtr = c.Addr(arr) @@ -82,7 +82,7 @@ def test_manual_strlen(): def test_reverse_string_ptr(): testcheck.section("Test 6: reverse string via pointer") src: t.CChar | t.CPtr = "abcd" - dst: list[t.CChar, 32] = [0] + dst: t.CArray[t.CChar, 32] = [0] # Find end of src p: t.CChar | t.CPtr = src length: t.CInt = 0 @@ -117,7 +117,7 @@ def test_double_pointer(): # ============================================================ def test_ptr_arithmetic(): testcheck.section("Test 8: pointer arithmetic") - arr: list[t.CInt, 8] = [0] + arr: t.CArray[t.CInt, 8] = [0] for i in range(8): arr[i] = (i + 1) * (i + 1) p: t.CInt | t.CPtr = c.Addr(arr) diff --git a/Test/ZlibTest/App/__zlib/__init__.vp b/Test/ZlibTest/App/__zlib/__init__.vp deleted file mode 100644 index e69de29..0000000 diff --git a/Test/ZlibTest/App/__zlib/pyzlib.vp b/Test/ZlibTest/App/__zlib/pyzlib.vp deleted file mode 100644 index e495e6d..0000000 --- a/Test/ZlibTest/App/__zlib/pyzlib.vp +++ /dev/null @@ -1,549 +0,0 @@ -from stdint import * -import zdeflate -import zinflate -import zchecksum -import zdef -import zhuff -import stdlib -import string -import t, c - - -# ============================================================ -# Constants - matching Python zlib module names and values -# ============================================================ - -# Compression levels -Z_NO_COMPRESSION: t.CDefine = 0 -Z_BEST_SPEED: t.CDefine = 1 -Z_BEST_COMPRESSION: t.CDefine = 9 -Z_DEFAULT_COMPRESSION: t.CDefine = (-1) - -# Compression methods -DEFLATED: t.CDefine = 8 - -# Flush modes -Z_NO_FLUSH: t.CDefine = 0 -Z_PARTIAL_FLUSH: t.CDefine = 1 -Z_SYNC_FLUSH: t.CDefine = 2 -Z_FULL_FLUSH: t.CDefine = 3 -Z_FINISH: t.CDefine = 4 -Z_BLOCK: t.CDefine = 5 -Z_TREES: t.CDefine = 6 - -# Strategies -Z_DEFAULT_STRATEGY: t.CDefine = 0 -Z_FILTERED: t.CDefine = 1 -Z_HUFFMAN_ONLY: t.CDefine = 2 -Z_RLE: t.CDefine = 3 -Z_FIXED: t.CDefine = 4 - -# Return codes -Z_OK: t.CDefine = 0 -Z_STREAM_END: t.CDefine = 1 -Z_NEED_DICT: t.CDefine = 2 -Z_ERRNO: t.CDefine = (-1) -Z_STREAM_ERROR: t.CDefine = (-2) -Z_DATA_ERROR: t.CDefine = (-3) -Z_MEM_ERROR: t.CDefine = (-4) -Z_BUF_ERROR: t.CDefine = (-5) -Z_VERSION_ERROR: t.CDefine = (-6) - -# Window / Buffer constants -MAX_WBITS: t.CDefine = 15 -DEF_BUF_SIZE: t.CDefine = 16384 -DEF_MEM_LEVEL: t.CDefine = 8 - -# Version -ZLIB_VERSION: t.CDefine = "1.3.2" - -pyzlib_error_msg: t.CArray[t.CChar, 512] = "" -pyzlib_error_code_val: t.CInt = 0 - -# ============================================================ -# Structures -# ============================================================ -@t.Object -class Compress: - stream: VOIDPTR - is_initialized: t.CInt - is_finished: t.CInt - level: t.CInt - method: t.CInt - wbits: t.CInt - memLevel: t.CInt - strategy: t.CInt - zdict: BYTEPTR - zdict_len: t.CSizeT - last_pos: t.CSizeT - input_buf: BYTEPTR - input_buf_len: t.CSizeT - input_buf_cap: t.CSizeT - header_written: t.CInt - - def compress(self, - data: BYTEPTR, data_len: t.CSizeT, - out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - if self.is_finished: - set_error(Z_STREAM_ERROR, "compress object already finished") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - if data_len == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - while self.input_buf_len + data_len > self.input_buf_cap: - self.input_buf_cap *= 2 - new_buf: BYTEPTR = BYTEPTR(realloc(self.input_buf, self.input_buf_cap)) - if not new_buf: - set_error(Z_MEM_ERROR, "out of memory") - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - self.input_buf = new_buf - memcpy(self.input_buf + self.input_buf_len, data, data_len) - self.input_buf_len += data_len - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def flush(self, mode: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - if mode == Z_FINISH: - if not self.header_written: - self.header_written = 1 - input_data: BYTEPTR = self.input_buf - input_len: t.CSizeT = self.input_buf_len - if input_len == 0: - s.writer.write_bits(1, 1) - s.writer.write_bits(1, 2) - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - lit_tree.encode_symbol(256, c.Addr(s.writer)) - else: - s.adler = zchecksum.zchecksum_adler32(input_data, input_len, 1) - s.compress_block(input_data, input_len, 1) - s.is_finished = 1 - if s.wbits >= 0: - s.writer.align() - adler: t.CUInt32T = s.adler - s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF - s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF - s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF - s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF - s.writer.byte_pos += 4 - self.is_finished = 1 - total: t.CSizeT = s.writer.total() - result: BYTEPTR = BYTEPTR(malloc(total)) - if result: memcpy(result, s.writer.buf, total) - c.Set(c.Deref(out_len), total) - free(self.input_buf) - self.input_buf = None - self.input_buf_len = 0 - self.input_buf_cap = 0 - return result - elif mode == Z_SYNC_FLUSH or mode == Z_FULL_FLUSH: - input_data: BYTEPTR = self.input_buf - input_len: t.CSizeT = self.input_buf_len - if input_len > 0: - s.adler = zchecksum.zchecksum_adler32(input_data, input_len, s.adler) - s.compress_block(input_data, input_len, 0) - self.input_buf_len = 0 - s.writer.write_bits(0, 1) - s.writer.write_bits(0, 2) - s.writer.align() - prev_pos: t.CSizeT = self.last_pos - total: t.CSizeT = s.writer.total() - delta: t.CSizeT = total - prev_pos - self.last_pos = s.writer.byte_pos - if delta == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - result: BYTEPTR = BYTEPTR(malloc(delta)) - if result: memcpy(result, s.writer.buf + prev_pos, delta) - c.Set(c.Deref(out_len), delta) - return result - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def copy(self) -> Compress | t.CPtr: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "compress object not initialized") - return None - copy_obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__()) - if not copy_obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - copy_obj.stream = s.copy() - if not copy_obj.stream: - free(copy_obj) - set_error(Z_MEM_ERROR, "out of memory") - return None - copy_obj.is_initialized = 1 - copy_obj.is_finished = self.is_finished - copy_obj.level = self.level - copy_obj.method = self.method - copy_obj.wbits = self.wbits - copy_obj.memLevel = self.memLevel - copy_obj.strategy = self.strategy - copy_obj.last_pos = self.last_pos - copy_obj.header_written = self.header_written - if self.input_buf and self.input_buf_len > 0: - copy_obj.input_buf = BYTEPTR(calloc(1, self.input_buf_cap)) - if copy_obj.input_buf: - memcpy(copy_obj.input_buf, self.input_buf, self.input_buf_len) - copy_obj.input_buf_cap = self.input_buf_cap - copy_obj.input_buf_len = self.input_buf_len - else: - copy_obj.input_buf = BYTEPTR(calloc(1, 256)) - copy_obj.input_buf_cap = 256 - copy_obj.input_buf_len = 0 - if self.zdict and self.zdict_len > 0: - copy_obj.zdict = clone_bytes(self.zdict, self.zdict_len) - copy_obj.zdict_len = self.zdict_len - return copy_obj - - def delete(self): - if self.is_initialized and self.stream: - s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换 - s.destroy() - free(self.zdict) - free(self.input_buf) - free(self) - - def __del__(self): - self.delete() - - -@t.Object -class Decompress: - stream: VOIDPTR - is_initialized: t.CInt - eof: t.CInt - wbits: t.CInt - zdict: BYTEPTR - zdict_len: t.CSizeT - _unused_data: BYTEPTR - _unused_data_len: t.CSizeT - _unused_data_cap: t.CSizeT - _unconsumed_tail: BYTEPTR - _unconsumed_tail_len: t.CSizeT - _unconsumed_tail_cap: t.CSizeT - input_buf: BYTEPTR - input_buf_len: t.CSizeT - input_buf_cap: t.CSizeT - - def decompress(self, data: BYTEPTR, data_len: t.CSizeT, - max_length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - if self.eof: - if data and data_len > 0: - append_bytes(c.Addr(self._unused_data), c.Addr(self._unused_data_len), - c.Addr(self._unused_data_cap), data, data_len) - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - self._unconsumed_tail_len = 0 - if data and data_len > 0: - append_bytes(c.Addr(self.input_buf), c.Addr(self.input_buf_len), - c.Addr(self.input_buf_cap), data, data_len) - if self.input_buf_len == 0: - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - s: zinflate.zinflate_stream | t.CPtr = zinflate.zinflate_create(self.wbits) - if not s: - set_error(Z_MEM_ERROR, "out of memory") - return None - if self.zdict and self.zdict_len > 0: - s.set_dictionary(self.zdict, self.zdict_len) - out: t.CUInt8T | t.CPtr = None - err: t.CInt = s.decompress(self.input_buf, self.input_buf_len, - max_length, c.Addr(out), out_len) - if err != 0: - s.destroy() - set_error(Z_DATA_ERROR, "decompression failed") - return None - if s.is_finished: - self.eof = 1 - if s.input_pos < s.input_len: - append_bytes(c.Addr(self._unused_data), c.Addr(self._unused_data_len), - c.Addr(self._unused_data_cap), - s.input_data + s.input_pos, - s.input_len - s.input_pos) - self.input_buf_len = 0 - else: - consumed: t.CSizeT = s.input_pos - if consumed < self.input_buf_len: - remaining: t.CSizeT = self.input_buf_len - consumed - memmove(self.input_buf, self.input_buf + consumed, remaining) - self.input_buf_len = remaining - else: - self.input_buf_len = 0 - s.destroy() - return out - - def flush(self, length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - c.Set(c.Deref(out_len), 0) - return BYTEPTR(calloc(1, 1)) - - def copy(self) -> Decompress | t.CPtr: - if not self.is_initialized: - set_error(Z_STREAM_ERROR, "decompress object not initialized") - return None - copy_obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__()) - if not copy_obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - copy_obj.is_initialized = 1 - copy_obj.eof = self.eof - copy_obj.wbits = self.wbits - if self.zdict and self.zdict_len > 0: - copy_obj.zdict = clone_bytes(self.zdict, self.zdict_len) - copy_obj.zdict_len = self.zdict_len - if self._unused_data and self._unused_data_len > 0: - copy_obj._unused_data = clone_bytes(self._unused_data, self._unused_data_len) - copy_obj._unused_data_len = self._unused_data_len - copy_obj._unused_data_cap = self._unused_data_len - if self._unconsumed_tail and self._unconsumed_tail_len > 0: - copy_obj._unconsumed_tail = clone_bytes(self._unconsumed_tail, self._unconsumed_tail_len) - copy_obj._unconsumed_tail_len = self._unconsumed_tail_len - copy_obj._unconsumed_tail_cap = self._unconsumed_tail_len - if self.input_buf and self.input_buf_len > 0: - copy_obj.input_buf = clone_bytes(self.input_buf, self.input_buf_len) - copy_obj.input_buf_len = self.input_buf_len - copy_obj.input_buf_cap = self.input_buf_cap - else: - copy_obj.input_buf = BYTEPTR(calloc(1, 256)) - copy_obj.input_buf_cap = 256 - copy_obj.input_buf_len = 0 - return copy_obj - - def delete(self): - free(self.zdict) - free(self._unused_data) - free(self._unconsumed_tail) - free(self.input_buf) - free(self) - - def unused_data(self, length: t.CSizeT | t.CPtr) -> BYTEPTR: - #if not self: - # if length: - # c.Set(c.Deref(length), 0) - # return None - if length: - c.Set(c.Deref(length), self._unused_data_len) - return self._unused_data - - def unconsumed_tail(self, length: t.CSizeT | t.CPtr) -> BYTEPTR: - #if not self: - # if length: - # c.Set(c.Deref(length), 0) - # return None - if length: - c.Set(c.Deref(length), self._unconsumed_tail_len) - return self._unconsumed_tail - -# def eof(self) -> t.CInt: -# # if not obj: return 0 -# return self.eof - - - -def set_error(code: int, msg: str): - global pyzlib_error_code_val, pyzlib_error_msg - pyzlib_error_code_val = code - if msg: - strncpy(pyzlib_error_msg, msg, pyzlib_error_msg.__sizeof__() - 1) - pyzlib_error_msg[pyzlib_error_msg.__sizeof__() - 1] = '\0' - else: - pyzlib_error_msg[0] = '\0' - -def clone_bytes(src: BYTEPTR, length: t.CSizeT) -> BYTEPTR: - if not src or length == 0: return None - dst: BYTEPTR = BYTEPTR(malloc(length)) - if dst: memcpy(dst, src, length) - return dst - -def append_bytes(buf: BYTE | t.CPtr[t.CPtr], length: t.CSizeT | t.CPtr, cap: t.CSizeT | t.CPtr, - data: BYTEPTR, data_len: t.CSizeT) -> t.CInt: - if not data or data_len == 0: return 0 - needed: t.CSizeT = c.Deref(length) + data_len - if needed > c.Deref(cap): - new_cap: t.CSizeT = c.Deref(cap) * 2 - if new_cap < needed: new_cap = needed - new_buf: BYTEPTR = BYTEPTR(realloc(c.Deref(buf), new_cap)) - if not new_buf: return -1 - c.Set(c.Deref(buf), new_buf) - c.Set(c.Deref(cap), new_cap) - memcpy(c.Deref(buf) + c.Deref(length), data, data_len) - c.Set(c.Deref(length), c.Deref(length) + data_len) - return 0 - - -def shrink_to_fit(buf: BYTEPTR, length: t.CSizeT) -> BYTEPTR: - if length == 0: - free(buf) - return BYTEPTR(calloc(1, 1)) - result: BYTEPTR = BYTEPTR(realloc(buf, length)) - return result if result else buf - - -def runtime_version() -> str: - return ZLIB_VERSION - -def get_error() -> str: - return pyzlib_error_msg - -def get_error_code() -> t.CInt: - return pyzlib_error_code_val - -def clear_error(): - global pyzlib_error_msg, pyzlib_error_code_val - pyzlib_error_msg[0] = '\0' - pyzlib_error_code_val = 0 - -def compress(data: BYTEPTR, data_len: t.CSizeT, - level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not data and data_len > 0: - set_error(Z_STREAM_ERROR, "data is None but data_len > 0") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: - actual_wbits = -MAX_WBITS - raw_result: UINT8PTR = zdeflate.zdeflate_one_shot(data, data_len, level, actual_wbits, out_len) - if not raw_result: - set_error(Z_DATA_ERROR, "compression failed") - return None - if wbits > MAX_WBITS: - gzip_len: t.CSizeT = 10 + c.Deref(out_len) + 8 - gzip_buf: BYTEPTR = BYTEPTR(malloc(gzip_len)) - if not gzip_buf: - free(raw_result) - set_error(Z_MEM_ERROR, "out of memory") - return None - pos: t.CSizeT = 0 - gzip_buf[pos + 0] = 0x1F - gzip_buf[pos + 1] = 0x8B - gzip_buf[pos + 2] = 0x08 - gzip_buf[pos + 3] = 0x00 - gzip_buf[pos + 4] = 0x00 - gzip_buf[pos + 5] = 0x00 - gzip_buf[pos + 6] = 0x00 - gzip_buf[pos + 7] = 0x00 - gzip_buf[pos + 8] = 0x00 - gzip_buf[pos + 9] = 0xFF - pos += 10 - - memcpy(gzip_buf + pos, raw_result, c.Deref(out_len)) - pos += c.Deref(out_len) - free(raw_result) - - crc: t.CUInt32T = zchecksum.zchecksum_crc32(data, data_len, 0) - gzip_buf[pos + 0] = (crc) & 0xFF - gzip_buf[pos + 1] = (crc >> 8) & 0xFF - gzip_buf[pos + 2] = (crc >> 16) & 0xFF - gzip_buf[pos + 3] = (crc >> 24) & 0xFF - gzip_buf[pos + 4] = (data_len) & 0xFF - gzip_buf[pos + 5] = (data_len >> 8) & 0xFF - gzip_buf[pos + 6] = (data_len >> 16) & 0xFF - gzip_buf[pos + 7] = (data_len >> 24) & 0xFF - pos += 8 - c.Set(c.Deref(out_len), pos) - return shrink_to_fit(gzip_buf, pos) - return shrink_to_fit(raw_result, c.Deref(out_len)) - - -def decompress(data: BYTEPTR, data_len: t.CSizeT, - wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR: - if not data and data_len > 0: - set_error(Z_STREAM_ERROR, "data is None but data_len > 0") - return None - if not out_len: - set_error(Z_STREAM_ERROR, "out_len is None") - return None - result: UINT8PTR = zinflate.zinflate_one_shot(data, data_len, wbits, bufsize, out_len) - if not result: - set_error(Z_DATA_ERROR, "decompression failed") - return None - return shrink_to_fit(result, c.Deref(out_len)) - -def compressobj(level: t.CInt, method: t.CInt, wbits: t.CInt, - memLevel: t.CInt, strategy: t.CInt, - zdict: BYTEPTR, zdict_len: t.CSizeT) -> Compress | t.CPtr: - obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__()) - if not obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: actual_wbits = wbits - 16 - s: zdeflate.zdeflate_stream | t.CPtr = zdeflate.zdeflate_create(level, actual_wbits, memLevel, strategy) - if not s: - free(obj) - set_error(Z_MEM_ERROR, "out of memory") - return None - obj.stream = s - obj.is_initialized = 1 - obj.level = level - obj.method = method - obj.wbits = wbits - obj.memLevel = memLevel - obj.strategy = strategy - obj.input_buf = BYTEPTR(calloc(1, 256)) - obj.input_buf_cap = 256 - obj.input_buf_len = 0 - obj.header_written = 0 - if zdict and zdict_len > 0: - s.set_dictionary(zdict, zdict_len) - obj.zdict = clone_bytes(zdict, zdict_len) - obj.zdict_len = zdict_len - return obj - - -def decompressobj(wbits: t.CInt, zdict: BYTEPTR, zdict_len: t.CSizeT) -> Decompress | t.CPtr: - obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__()) - if not obj: - set_error(Z_MEM_ERROR, "out of memory") - return None - actual_wbits: t.CInt = wbits - if wbits > MAX_WBITS: actual_wbits = wbits - 16 - obj.stream = None - obj.is_initialized = 1 - obj.wbits = actual_wbits - if zdict and zdict_len > 0: - obj.zdict = clone_bytes(zdict, zdict_len) - obj.zdict_len = zdict_len - obj.input_buf = BYTEPTR(calloc(1, 256)) - obj.input_buf_cap = 256 - obj.input_buf_len = 0 - return obj - -def zlib_adler32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong: - return zchecksum.zchecksum_adler32(data, length, UINT32(value)) - -def zlib_crc32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong: - return zchecksum.zchecksum_crc32(data, length, UINT32(value)) - - diff --git a/Test/ZlibTest/App/__zlib/test_pyzlib.vp b/Test/ZlibTest/App/__zlib/test_pyzlib.vp deleted file mode 100644 index 3d572bc..0000000 --- a/Test/ZlibTest/App/__zlib/test_pyzlib.vp +++ /dev/null @@ -1,877 +0,0 @@ -from stdint import * -import pyzlib -import zhuff -import zdef -from stdio import printf -import stdlib -from string import strlen -import string -import t, c - - -test_passed: t.CInt = 0 -test_failed: t.CInt = 0 -def check(name: str, condition: t.CInt, detail: str): - global test_passed, test_failed - if condition: - test_passed += 1 - printf(" [PASS] %s\n", name) - else: - test_failed += 1 - printf(" [FAIL] %s -- %s\n", name, detail if detail else "") - -def print_hex_test(data: BYTEPTR, length: t.CSizeT, max_show: t.CSizeT): - if not data or length == 0: - printf("(empty)\n") - return - show: t.CSizeT = max_show if (length > max_show) else length - i: t.CSizeT - for i in range(show): - printf("%02X ", data[i]) - if length > max_show: - printf("... (%zu bytes total)", length) - printf("\n") - -def print_separator(): - printf(" -------------------------------------------\n") - -def section_header(title: str): - printf("\n+-- %s --+\n", title) - -def section_footer(): - printf("+--------------------------------------------+\n") - -# ============================================================ - -def test_version(): - section_header("Version Info") - - ver: str = pyzlib.ZLIB_VERSION - printf(" ZLIB_VERSION (compile-time) : %s\n", ver) - check("ZLIB_VERSION not None", ver != None, "version string is None") - check("ZLIB_VERSION not empty", strlen(ver) > 0, "version string is empty") - - runtime_ver: str = pyzlib.runtime_version() - printf(" ZLIB_RUNTIME_VERSION : %s\n", runtime_ver) - check("runtime version not None", runtime_ver != None, "runtime version is None") - check("runtime version not empty", strlen(runtime_ver) > 0, "runtime version is empty") - - section_footer() - - -def test_compress_decompress(): - section_header("compress / decompress") - - inp: str = "Hello, World! This is a test of zlib compression and decompression." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("compress returns non-None", compressed != None, "compress returned None") - check("compress output size > 0", out_length > 0, "compressed size is 0") - check("compress output produced", out_length > 0, "compressed size is 0") - - printf(" Compressed (%zu bytes): ", out_length) - print_hex_test(compressed, out_length, 32) - printf(" Compression ratio: %.1f%%\n", t.CDouble(out_length) / input_length * 100) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress returns non-None", decompressed != None, "decompress returned None") - check("decompress output size matches input", dec_length == input_length, "size mismatch") - check("decompress output matches input", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - - printf(" Decompressed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(decompressed)) - - free(compressed) - free(decompressed) - section_footer() - - -def test_compress_levels(): - section_header("Compression Levels") - - inp: str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - - c0: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_NO_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 0 compress OK", c0 != None, "level 0 returned None") - printf(" Level 0 (Z_NO_COMPRESSION): %zu bytes\n", out_length) - length0: t.CSizeT = out_length - free(c0) - - c1: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_BEST_SPEED, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 1 compress OK", c1 != None, "level 1 returned None") - printf(" Level 1 (Z_BEST_SPEED) : %zu bytes\n", out_length) - free(c1) - - c6: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level -1 compress OK", c6 != None, "default level returned None") - printf(" Level -1 (DEFAULT) : %zu bytes\n", out_length) - free(c6) - - c9: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_BEST_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("level 9 compress OK", c9 != None, "level 9 returned None") - printf(" Level 9 (Z_BEST_COMPRESS) : %zu bytes\n", out_length) - length9: t.CSizeT = out_length - free(c9) - - check("level 9 smaller than level 0", length9 < length0, "level 9 not smaller than level 0") - - section_footer() - - -def test_compressobj(): - section_header("compressobj (incremental)") - - part1: str = "Hello, " - part2: str = "World!" - printf(" Part 1: \"%s\"\n", part1) - printf(" Part 2: \"%s\"\n", part2) - - out_length: t.CSizeT = 0 - - s: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - check("compressobj created", s != None, "compressobj is None") - print_separator() - - c1: BYTEPTR = s.compress(BYTEPTR(part1), strlen(part1), c.Addr(out_length)) - check("compress part1 OK", c1 != None, "compress part1 failed") - printf(" Compressed part1: %zu bytes -> ", out_length) - print_hex_test(c1, out_length, 16) - total: t.CSizeT = out_length - all: BYTEPTR = None - if out_length > 0 and c1: - all = BYTEPTR(malloc(total)) - if all: memcpy(all, c1, out_length) - free(c1) - - c2: BYTEPTR = s.compress(BYTEPTR(part2), - strlen(part2), c.Addr(out_length)) - check("compress part2 OK", c2 != None, "compress part2 failed") - printf(" Compressed part2: %zu bytes -> ", out_length) - print_hex_test(c2, out_length, 16) - if out_length > 0 and c2: - new_all: BYTEPTR = BYTEPTR(realloc(all, total + out_length)) - if new_all: - all = new_all - memcpy(all + total, c2, out_length) - total += out_length - free(c2) - - c3: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush (Z_FINISH) OK", c3 != None, "flush failed") - printf(" Flush result : %zu bytes -> ", out_length) - print_hex_test(c3, out_length, 16) - if out_length > 0 and c3: - new_all: BYTEPTR = realloc(all, total + out_length) # 隐式转换 - if new_all: - all = new_all - memcpy(all + total, c3, out_length) - total += out_length - free(c3) - - print_separator() - - if all: - dec_length: t.CSizeT = 0 - dec: BYTEPTR = pyzlib.decompress(all, total, pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress incremental OK", dec != None, "decompress returned None") - check("decompress incremental size", dec != None and dec_length == strlen(part1) + strlen(part2), "size mismatch") - check("decompress incremental content", - dec != None and memcmp(dec, "Hello, World!", dec_length) == 0, "content mismatch") - if dec: - printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - free(all) - - s.delete() # del s - section_footer() - -def test_decompressobj(): - section_header("decompressobj") - - inp: str = "Test data for decompress object." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - check("decompressobj created", d != None, "decompressobj is None") - check("eof is false initially", d.eof == 0, "eof should be 0") - print_separator() - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(compressed, out_length, - 0, c.Addr(dec_length)) - check("decompress OK", dec != None, "decompress returned None") - check("decompress size", dec != None and dec_length == input_length, "size mismatch") - check("decompress content", dec != None and memcmp(dec, inp, input_length) == 0, "content mismatch") - check("eof is true after stream end", d.eof == 1, "eof should be 1") - - if dec: - printf(" Decompressed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(dec)) - printf(" eof = %d\n", d.eof) - - free(dec) - free(compressed) - d.delete() - section_footer() - -def test_decompressobj_max_length(): - section_header("decompressobj max_length") - - inp: str = "This is a longer string for testing max_length parameter in decompress." - input_length: t.CSizeT = strlen(inp) - printf(" Input (%zu bytes): \"%s\"\n", input_length, inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(compressed, out_length, - 10, c.Addr(dec_length)) - check("max_length decompress OK", dec != None, "decompress returned None") - check("max_length limits output", dec_length <= 10, "output exceeded max_length") - if dec: - printf(" First chunk (max_length=10): \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - - tail_length: t.CSizeT = 0 - tail: BYTEPTR = d.unconsumed_tail(c.Addr(tail_length)) - check("unconsumed_tail exists", tail != None or tail_length == 0, "no unconsumed_tail") - printf(" unconsumed_tail: %zu bytes remaining\n", tail_length) - printf(" eof = %d\n", d.eof) - - if tail_length > 0 or not d.eof: - flushed: BYTEPTR = d.flush(pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("flush after max_length OK", flushed != None, "flush returned None") - if flushed: printf(" Flushed (%zu bytes): \"%.*s\"\n", dec_length, t.CInt(dec_length), str(flushed)) - free(flushed) - - printf(" eof after flush = %d\n", d.eof) - - d.delete() - free(compressed) - section_footer() - - -def test_decompressobj_unused_data(): - section_header("decompressobj unused_data") - - inp: str = "Hello" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - total_length: t.CSizeT = out_length + 5 - combined: BYTEPTR = BYTEPTR(malloc(total_length)) - memcpy(combined, compressed, out_length) - memcpy(combined + out_length, "EXTRA", 5) - free(compressed) - printf(" Combined (compressed + \"EXTRA\"): %zu bytes\n", total_length) - - d: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - - dec_length: t.CSizeT = 0 - dec: BYTEPTR = d.decompress(combined, total_length, - 0, c.Addr(dec_length)) - check("decompress with extra OK", dec != None, "decompress returned None") - check("eof after stream end", d.eof == 1, "eof should be 1") - if dec: - printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(dec), dec_length) - free(dec) - - print_separator() - - unused_length: t.CSizeT = 0 - unused: BYTEPTR = d.unused_data(c.Addr(unused_length)) - check("unused_data exists", unused != None and unused_length > 0, "no unused_data") - check("unused_data is EXTRA", unused_length == 5 and unused != None and memcmp(unused, "EXTRA", 5) == 0, "unused_data mismatch") - printf(" unused_data (%zu bytes): \"%.*s\"\n", unused_length, t.CInt(unused_length), str(unused)) - - d.delete() - free(combined) - section_footer() - - -def test_compress_copy(): - section_header("Compress.copy()") - - inp: str = "Copy test data for compress object" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - c1: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - c1.compress(BYTEPTR(inp), input_length, c.Addr(out_length)) - printf(" Original: compressed %zu bytes so far\n", out_length) - - c2: pyzlib.Compress | t.CPtr = c1.copy() - check("compress copy OK", c2 != None, "copy returned None") - printf(" Copied compressobj\n") - - print_separator() - - f1: BYTEPTR = c1.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush original OK", f1 != None, "flush original failed") - length1: t.CSizeT = out_length - printf(" Original flush: %zu bytes\n", length1) - free(f1) - - f2: BYTEPTR = c2.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush copy OK", f2 != None, "flush copy failed") - length2: t.CSizeT = out_length - printf(" Copy flush : %zu bytes\n", length2) - free(f2) - - check("copy produces same output", length1 == length2, "output lengthgths differ") - - c1.delete() - c2.delete() - section_footer() - - -def test_decompress_copy(): - section_header("Decompress.copy()") - - inp: str = "Decompress copy test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\"\n", inp) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - printf(" Compressed: %zu bytes\n", out_length) - - d1: pyzlib.Decompress | t.CPtr = pyzlib.decompressobj(pyzlib.MAX_WBITS, None, 0) - d2: pyzlib.Decompress | t.CPtr = d1.copy() - check("decompress copy OK", d2 != None, "copy returned None") - printf(" Copied decompressobj\n") - - print_separator() - - dec_length1: t.CSizeT = 0 - dec_length2: t.CSizeT = 0 - dec1: BYTEPTR = d1.decompress(compressed, out_length, - 0, c.Addr(dec_length1)) - dec2: BYTEPTR = d2.decompress(compressed, out_length, - 0, c.Addr(dec_length2)) - check("decompress copy output size", dec_length1 == dec_length2, "sizes differ") - check("decompress copy output content", - dec1 and dec2 and memcmp(dec1, dec2, dec_length1) == 0, "content differs") - - if dec1: printf(" Original: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length1), str(dec1), dec_length1) - if dec2: printf(" Copy : \"%.*s\" (%zu bytes)\n", t.CInt(dec_length2), str(dec2), dec_length2) - - free(dec1) - free(dec2) - free(compressed) - d1.delete() - d2.delete() - section_footer() - - -def test_adler32(): - section_header("adler32 checksum") - - checksum: ULONG = pyzlib.zlib_adler32(BYTEPTR("Hello"), 5, 1) - printf(" adler32(\"Hello\") = 0x%08lX (%lu)\n", checksum, checksum) - check("adler32 returns non-zero", checksum != 0, "checksum is 0") - - incremental: ULONG = pyzlib.zlib_adler32(BYTEPTR("Hel"), 3, 1) - printf(" adler32(\"Hel\") = 0x%08lX\n", incremental) - incremental = pyzlib.zlib_adler32(BYTEPTR("lo"), 2, incremental) - printf(" adler32(\"lo\", prev) = 0x%08lX\n", incremental) - check("adler32 incremental matches one-shot", incremental == checksum, "incremental != one-shot") - printf(" Incremental == One-shot: %s\n", "YES" if incremental == checksum else "NO") - - section_footer() - - -def test_crc32(): - section_header("crc32 checksum") - - checksum: ULONG = pyzlib.zlib_crc32(BYTEPTR("Hello"), 5, 0) - printf(" crc32(\"Hello\") = 0x%08lX (%lu)\n", checksum, checksum) - check("crc32 returns non-zero", checksum != 0, "checksum is 0") - - incremental: ULONG = pyzlib.zlib_crc32(BYTEPTR("Hel"), 3, 0) - printf(" crc32(\"Hel\") = 0x%08lX\n", incremental) - incremental = pyzlib.zlib_crc32(BYTEPTR("lo"), 2, incremental) - printf(" crc32(\"lo\", prev) = 0x%08lX\n", incremental) - check("crc32 incremental matches one-shot", incremental == checksum, "incremental != one-shot") - printf(" Incremental == One-shot: %s\n", "YES" if incremental == checksum else "NO") - - section_footer() - - -def test_empty_compress(): - section_header("Empty data compress/decompress") - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(""), 0, - pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.MAX_WBITS, c.Addr(out_length)) - check("compress empty OK", compressed != None, "compress empty returned None") - check("compress empty output > 0", out_length > 0, "compressed empty is 0 bytes") - printf(" Empty input compressed: %zu bytes (header only)\n", out_length) - printf(" Hex: ") - print_hex_test(compressed, out_length, 32) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("decompress empty OK", decompressed != None, "decompress empty returned None") - check("decompress empty size == 0", dec_length == 0, "decompressed size != 0") - printf(" Decompressed back: %zu bytes\n", dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_gzip_format(): - section_header("Gzip format (wbits=31)") - - inp: str = "Gzip format test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\" (%zu bytes)\n", inp, input_length) - - gzip_wbits: t.CInt = pyzlib.MAX_WBITS + 16 - printf(" wbits = MAX_WBITS + 16 = %d\n", gzip_wbits) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, gzip_wbits, c.Addr(out_length)) - check("gzip compress OK", compressed != None, "gzip compress failed") - printf(" Gzip compressed: %zu bytes\n", out_length) - printf(" Header bytes: ") - print_hex_test(compressed, 4 if (out_length > 4) else out_length, 4) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - gzip_wbits, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("gzip decompress OK", decompressed != None, "gzip decompress failed") - check("gzip decompress size", dec_length == input_length, "size mismatch") - check("gzip decompress content", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - if decompressed: printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(decompressed), dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_raw_deflate(): - section_header("Raw deflate (wbits=-15)") - - inp: str = "Raw deflate test" - input_length: t.CSizeT = strlen(inp) - printf(" Input: \"%s\" (%zu bytes)\n", inp, input_length) - - raw_wbits: t.CInt = -pyzlib.MAX_WBITS - printf(" wbits = -MAX_WBITS = %d\n", raw_wbits) - - out_length: t.CSizeT = 0 - compressed: BYTEPTR = pyzlib.compress(BYTEPTR(inp), input_length, - pyzlib.Z_DEFAULT_COMPRESSION, raw_wbits, c.Addr(out_length)) - check("raw deflate compress OK", compressed != None, "raw deflate compress failed") - printf(" Raw compressed: %zu bytes\n", out_length) - - dec_length: t.CSizeT = 0 - decompressed: BYTEPTR = pyzlib.decompress(compressed, out_length, - raw_wbits, pyzlib.DEF_BUF_SIZE, c.Addr(dec_length)) - check("raw deflate decompress OK", decompressed != None, "raw deflate decompress failed") - check("raw deflate decompress size", dec_length == input_length, "size mismatch") - check("raw deflate decompress content", decompressed != None and memcmp(decompressed, inp, input_length) == 0, "content mismatch") - if decompressed: printf(" Decompressed: \"%.*s\" (%zu bytes)\n", t.CInt(dec_length), str(decompressed), dec_length) - - free(compressed) - free(decompressed) - section_footer() - - -def test_zdict(): - section_header("Preset dictionary (zdict)") - - dict: str = "common words that appear frequently in the data" - inp: str = "common words that appear frequently" - input_length: t.CSizeT = strlen(inp) - printf(" Dictionary: \"%s\" (%zu bytes)\n", dict, strlen(dict)) - printf(" Input : \"%s\" (%zu bytes)\n", inp, input_length) - - out_length: t.CSizeT = 0 - s: pyzlib.Compress | t.CPtr = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, - BYTEPTR(dict), strlen(dict)) - check("compressobj with zdict OK", s != None, "compressobj with zdict failed") - - comp_data: BYTEPTR = s.compress(BYTEPTR(inp), - input_length, c.Addr(out_length)) - check("compress with zdict OK", comp_data != None, "compress with zdict failed") - printf(" Compressed with zdict: %zu bytes\n", out_length) - free(comp_data) - - flush_data: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - check("flush with zdict OK", flush_data != None, "flush with zdict failed") - printf(" Flush: %zu bytes\n", out_length) - free(flush_data) - - print_separator() - - total_comp: t.CSizeT = out_length - s.delete() - - s = pyzlib.compressobj(pyzlib.Z_DEFAULT_COMPRESSION, pyzlib.DEFLATED, - pyzlib.MAX_WBITS, pyzlib.DEF_MEM_LEVEL, - pyzlib.Z_DEFAULT_STRATEGY, None, 0) - comp_no_dict: BYTEPTR = s.compress(BYTEPTR(inp), - input_length, c.Addr(out_length)) - flush_no_dict: BYTEPTR = s.flush(pyzlib.Z_FINISH, c.Addr(out_length)) - no_dict_total: t.CSizeT = 0 - if comp_no_dict: no_dict_total += out_length - if flush_no_dict: no_dict_total += out_length - printf(" Without zdict: ~%zu bytes compressed\n", no_dict_total) - printf(" With zdict : %zu bytes compressed\n", total_comp) - free(comp_no_dict) - free(flush_no_dict) - s.delete() - - section_footer() - - -def test_huffman_tree(): - section_header("Huffman tree construction") - - printf(" --- Fixed Huffman tree (literal/lengthgth) ---\n") - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - - check("fixed lit tree count == 288", lit_tree.count == 288, "count mismatch") - check("fixed lit tree max_bits == 9", lit_tree.max_bits == 9, "max_bits mismatch") - - has_8bit: t.CInt = 0 - has_9bit: t.CInt = 0 - has_7bit: t.CInt = 0 - for i in range(143 + 1): - if lit_tree.codes[i].bits == 8: - has_8bit += 1 - for i in range(143 + 1, 255 + 1): - if lit_tree.codes[i].bits == 9: - has_9bit += 1 - for i in range(255 + 1, 279 + 1): - if lit_tree.codes[i].bits == 7: - has_7bit += 1 - check("0-143 are 8-bit", has_8bit == 144, "wrong count") - check("144-255 are 9-bit", has_9bit == 112, "wrong count") - check("256-279 are 7-bit", has_7bit == 24, "wrong count") - - printf(" 0-143: %d codes with 8 bits\n", has_8bit) - printf(" 144-255: %d codes with 9 bits\n", has_9bit) - printf(" 256-279: %d codes with 7 bits\n", has_7bit) - printf(" 280-287: 8-bit (end-of-block 256 = 7-bit)\n") - printf(" EOB (256): code=0x%X, bits=%d\n", lit_tree.codes[256].code, lit_tree.codes[256].bits) - - printf("\n --- Fixed Huffman tree (distance) ---\n") - dist_tree = zhuff.zhuff_tree() - dist_tree.build_fixed_dist_tree() - - check("fixed dist tree count == 32", dist_tree.count == 32, "count mismatch") - check("fixed dist tree max_bits == 5", dist_tree.max_bits == 5, "max_bits mismatch") - - all_5bit: t.CInt = 1 - for i in range(32): - if dist_tree.codes[i].bits != 5: - all_5bit = 0 - check("all 32 distance codes are 5-bit", all_5bit, "not all 5-bit") - printf(" All 32 distance codes: 5 bits each\n") - - printf("\n --- Dynamic Huffman tree from frequencies ---\n") - freqs: t.CArray[t.CInt, 256] - memset(freqs, 0, freqs.__sizeof__()) - freqs['A'] = 50 - freqs['B'] = 25 - freqs['C'] = 12 - freqs['D'] = 6 - freqs['E'] = 3 - freqs['F'] = 1 - freqs[256] = 1 - - dyn_tree = zhuff.zhuff_tree() - dyn_tree.build_codes(freqs, 257, 15) - - check("dynamic tree count == 257", dyn_tree.count == 257, "count mismatch") - check("dynamic tree max_bits <= 15", dyn_tree.max_bits <= 15, "max_bits overflow") - - total_codes: t.CInt = 0 - max_length_found: t.CInt = 0 - for i in range(257): - if dyn_tree.codes[i].bits > 0: - total_codes += 1 - if dyn_tree.codes[i].bits > max_length_found: - max_length_found = dyn_tree.codes[i].bits - check("dynamic tree has 7 active codes", total_codes == 7, "wrong active count") - check("dynamic tree max code lengthgth found <= 15", max_length_found <= 15, "code lengthgth overflow") - - printf(" Frequencies: A=50, B=25, C=12, D=6, E=3, F=1, EOB=1\n") - printf(" Active codes: %d, max code lengthgth: %d\n", total_codes, max_length_found) - - printf(" Code assignments:\n") - names: t.CArray[str, None] = ["A","B","C","D","E","F"] # 一个都æ˜?char* 的数ç»? - syms: t.CArray[t.CInt, None] = ['A','B','C','D','E','F'] - for i in range(6): - printf(" '%s' (freq=%3d): code=0x%04X, bits=%d\n", - names[i], freqs[syms[i]], - dyn_tree.codes[syms[i]].code, - dyn_tree.codes[syms[i]].bits) - - - - printf(" EOB (freq=1): code=0x%04X, bits=%d\n", - dyn_tree.codes[256].code, dyn_tree.codes[256].bits) - a_bits: t.CInt = dyn_tree.codes['A'].bits - f_bits: t.CInt = dyn_tree.codes['F'].bits - check("high-freq symbol has shorter code", a_bits <= f_bits, "A should be <= F") - printf(" High-freq 'A' (%d bits) <= low-freq 'F' (%d bits): %s\n", - a_bits, f_bits, "YES" if (a_bits <= f_bits) else "NO") - - printf("\n --- Huffman encode/decode roundtrip ---\n") - freqs: t.CArray[t.CInt, 288] - memset(freqs, 0, freqs.__sizeof__()) - freqs['H'] = 10 - freqs['e'] = 8 - freqs['l'] = 20 - freqs['o'] = 8 - freqs[' '] = 5 - freqs['W'] = 3 - freqs['r'] = 5 - freqs['d'] = 3 - freqs['!'] = 2 - freqs[256] = 1 - - enc_tree = zhuff.zhuff_tree() - enc_tree.build_codes(freqs, 257, 15) - - dec_tree = zhuff.zhuff_decode_tree() - dec_tree.build_decode_tree(c.Addr(enc_tree)) - - writer = zdef.zbit_writer() - - symbols: t.CArray[t.CInt, None] = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 256] - num_symbols: t.CInt = 13 - - for i in range(num_symbols): - enc_tree.encode_symbol(symbols[i], c.Addr(writer)) - - reader = zdef.zbit_reader() - reader.buf = writer.buf - reader.length = writer.byte_pos + (1 if (writer.bit_pos > 0) else 0) - reader.byte_pos = 0 - reader.bit_pos = 0 - - roundtrip_ok: t.CInt = 1 - for i in range(num_symbols): - decoded: t.CInt = dec_tree.decode_symbol(c.Addr(reader)) - if decoded != symbols[i]: - roundtrip_ok = 0 - printf(" MISMATCH at symbol %d: expected %d, got %d\n", i, symbols[i], decoded) - break - check("encode/decode roundtrip matches", roundtrip_ok, "roundtrip failed") - printf(" Encoded %d symbols into %zu bytes, decoded all correctly\n", - num_symbols, writer.byte_pos + (1 if (writer.bit_pos > 0) else 0)) - - free(writer.buf) - - printf("\n --- Overflow handling (many symbols, limited max_bits) ---\n") - freqs: t.CArray[t.CInt, 256] - for i in range(256): - freqs[i] = 1 - freqs[256] = 1 - - tree = zhuff.zhuff_tree() - tree.build_codes(freqs, 257, 15) - - overflow_ok: t.CInt = 1 - for i in range(257): - if tree.codes[i].bits > 15 or tree.codes[i].bits < 0: - overflow_ok = 0 - break - check("all code lengthgths <= 15 with 257 symbols", overflow_ok, "code lengthgth overflow") - - bl_count: t.CArray[t.CInt, 16] = [0] - for i in range(257): - if tree.codes[i].bits > 0: - bl_count[tree.codes[i].bits] += 1 - printf(" Code lengthgth distribution (257 equal-freq symbols, max_bits=15):\n") - for i in range(1, 15 + 1): - if bl_count[i] > 0: - printf(" %2d bits: %3d codes\n", i, bl_count[i]) - - dt = zhuff.zhuff_decode_tree() - dt.build_decode_tree(c.Addr(tree)) - - w = zdef.zbit_writer() - tree.encode_symbol(0, c.Addr(w)) - tree.encode_symbol(128, c.Addr(w)) - tree.encode_symbol(255, c.Addr(w)) - tree.encode_symbol(256, c.Addr(w)) - - r = zdef.zbit_reader() - r.buf = w.buf - r.length = w.byte_pos + (1 if (w.bit_pos > 0) else 0) - r.byte_pos = 0 - r.bit_pos = 0 - - s0: t.CInt = dt.decode_symbol(c.Addr(r)) - s1: t.CInt = dt.decode_symbol(c.Addr(r)) - s2: t.CInt = dt.decode_symbol(c.Addr(r)) - s3: t.CInt = dt.decode_symbol(c.Addr(r)) - - check("overflow roundtrip: symbol 0", s0 == 0, "decode mismatch") - check("overflow roundtrip: symbol 128", s1 == 128, "decode mismatch") - check("overflow roundtrip: symbol 255", s2 == 255, "decode mismatch") - check("overflow roundtrip: symbol 256 (EOB)", s3 == 256, "decode mismatch") - - free(w.buf) - - - printf("\n --- Kraft inequality check ---\n") - freqs: t.CArray[t.CInt, 256] - memset(freqs, 0, freqs.__sizeof__()) - freqs['X'] = 100 - freqs['Y'] = 50 - freqs['Z'] = 25 - freqs[256] = 1 - - tree = zhuff.zhuff_tree() - tree.build_codes(freqs, 257, 15) - - kraft_sum: t.CDouble = 0.0 - for i in range(257): - if tree.codes[i].bits > 0: - kraft_sum += 1.0 / (t.CDouble(ULONGLONG(1) << tree.codes[i].bits)) - check("Kraft inequality: sum <= 1.0", kraft_sum <= 1.0 + 1e-9, "Kraft violated") - printf(" Kraft sum = %.10f (must be <= 1.0)\n", kraft_sum) - - section_footer() - - -def test_error_handling(): - section_header("Error handling") - - out_length: t.CSizeT = 0 - printf(" Trying to decompress garbage data...\n") - - result: BYTEPTR = pyzlib.decompress(BYTEPTR("garbage"), 7, - pyzlib.MAX_WBITS, pyzlib.DEF_BUF_SIZE, c.Addr(out_length)) - check("decompress garbage returns None", result == None, "should have returned None") - printf(" Error code : %d\n", pyzlib.get_error_code()) - printf(" Error message: \"%s\"\n", pyzlib.get_error()) - check("error message set", strlen(pyzlib.get_error()) > 0, "error message is empty") - check("error code is set", pyzlib.get_error_code() != pyzlib.Z_OK, "error code is Z_OK") - - print_separator() - - pyzlib.clear_error() - check("clear error clears code", pyzlib.get_error_code() == 0, "error code not cleared") - printf(" After clear: code=%d, msg=\"%s\"\n", pyzlib.get_error_code(), pyzlib.get_error()) - - section_footer() - - -def test_constants(): - section_header("Constants") - printf(" Compression Levels:\n") - printf(" Z_NO_COMPRESSION = %d\n", pyzlib.Z_NO_COMPRESSION) - printf(" Z_BEST_SPEED = %d\n", pyzlib.Z_BEST_SPEED) - printf(" Z_BEST_COMPRESSION = %d\n", pyzlib.Z_BEST_COMPRESSION) - printf(" Z_DEFAULT_COMPRESSION = %d\n", pyzlib.Z_DEFAULT_COMPRESSION) - printf(" Methods:\n") - printf(" DEFLATED = %d\n", pyzlib.DEFLATED) - printf(" Flush Modes:\n") - printf(" Z_NO_FLUSH = %d\n", pyzlib.Z_NO_FLUSH) - printf(" Z_PARTIAL_FLUSH = %d\n", pyzlib.Z_PARTIAL_FLUSH) - printf(" Z_SYNC_FLUSH = %d\n", pyzlib.Z_SYNC_FLUSH) - printf(" Z_FULL_FLUSH = %d\n", pyzlib.Z_FULL_FLUSH) - printf(" Z_FINISH = %d\n", pyzlib.Z_FINISH) - printf(" Z_BLOCK = %d\n", pyzlib.Z_BLOCK) - printf(" Z_TREES = %d\n", pyzlib.Z_TREES) - printf(" Strategies:\n") - printf(" Z_DEFAULT_STRATEGY = %d\n", pyzlib.Z_DEFAULT_STRATEGY) - printf(" Z_FILTERED = %d\n", pyzlib.Z_FILTERED) - printf(" Z_HUFFMAN_ONLY = %d\n", pyzlib.Z_HUFFMAN_ONLY) - printf(" Z_RLE = %d\n", pyzlib.Z_RLE) - printf(" Z_FIXED = %d\n", pyzlib.Z_FIXED) - printf(" Return Codes:\n") - printf(" Z_OK = %d\n", pyzlib.Z_OK) - printf(" Z_STREAM_END = %d\n", pyzlib.Z_STREAM_END) - printf(" Z_NEED_DICT = %d\n", pyzlib.Z_NEED_DICT) - printf(" Z_ERRNO = %d\n", pyzlib.Z_ERRNO) - printf(" Z_STREAM_ERROR = %d\n", pyzlib.Z_STREAM_ERROR) - printf(" Z_DATA_ERROR = %d\n", pyzlib.Z_DATA_ERROR) - printf(" Z_MEM_ERROR = %d\n", pyzlib.Z_MEM_ERROR) - printf(" Z_BUF_ERROR = %d\n", pyzlib.Z_BUF_ERROR) - printf(" Z_VERSION_ERROR = %d\n", pyzlib.Z_VERSION_ERROR) - printf(" Window / Buffer:\n") - printf(" MAX_WBITS = %d\n", pyzlib.MAX_WBITS) - printf(" DEF_BUF_SIZE = %d\n", pyzlib.DEF_BUF_SIZE) - printf(" DEF_MEM_LEVEL = %d\n", pyzlib.DEF_MEM_LEVEL) - section_footer() - - -def main123456() -> t.CInt: - printf("==============================================\n") - printf(" Python zlib - C Implementation Tests\n") - printf("==============================================\n") - - test_constants() - test_version() - test_compress_decompress() - test_compress_levels() - test_compressobj() - test_decompressobj() - test_decompressobj_max_length() - test_decompressobj_unused_data() - # test_compress_copy() # skip: heap corruption - # test_decompress_copy() # skip: heap corruption - test_adler32() - test_crc32() - test_empty_compress() - test_gzip_format() - test_raw_deflate() - test_zdict() - # test_huffman_tree() # skip: heap corruption from earlier tests - test_error_handling() - - printf("\n==============================================\n") - printf(" Results: %d passed, %d failed\n", test_passed, test_failed) - printf("==============================================\n") - - return 1 if test_failed > 0 else 0 - diff --git a/Test/ZlibTest/App/__zlib/zchecksum.vp b/Test/ZlibTest/App/__zlib/zchecksum.vp deleted file mode 100644 index 7c2d644..0000000 --- a/Test/ZlibTest/App/__zlib/zchecksum.vp +++ /dev/null @@ -1,90 +0,0 @@ -from stdint import * -import t, c - - -def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt32T: - a: t.CUInt32T = (init >> 0) & 0xFFFF - b: t.CUInt32T = (init >> 16) & 0xFFFF - if not data or length == 0: - return init - i: t.CSizeT - for i in range(length): - a = (a + data[i]) % 65521 - b = (b + a) % 65521 - return (b << 16) | a - -crc32_table: t.CArray[t.CUInt32T, 256] = [ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBBBD6, 0xACBCCB40, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7D49, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDede9EC5, 0x47D7897F, 0x30D0B8E9, - 0xBDDA8B1C, 0xCADD8B8A, 0x53D3903A, 0x24D4C2AC, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -] - -def zchecksum_crc32(data: UINT8PTR, length: t.CSizeT, init: t.CUInt32T) -> t.CUInt32T: - crc: t.CUInt32T = init ^ 0xFFFFFFFF - if not data or length == 0: return init - i: t.CSizeT - for i in range(length): - crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8) - return crc ^ 0xFFFFFFFF - diff --git a/Test/ZlibTest/App/__zlib/zdef.vp b/Test/ZlibTest/App/__zlib/zdef.vp deleted file mode 100644 index efb39dc..0000000 --- a/Test/ZlibTest/App/__zlib/zdef.vp +++ /dev/null @@ -1,269 +0,0 @@ -from stdint import * -import stddef -import string -import stdlib -import t, c - - -# ============================================================ -# DEFLATE / zlib constants -# ============================================================ -ZDEFLATE_WINDOW_BITS: t.CDefine = 15 -ZDEFLATE_WINDOW_SIZE: t.CDefine = (1 << ZDEFLATE_WINDOW_BITS) -ZDEFLATE_WINDOW_MASK: t.CDefine = (ZDEFLATE_WINDOW_SIZE - 1) - -ZDEFLATE_MIN_MATCH: t.CDefine = 3 -ZDEFLATE_MAX_MATCH: t.CDefine = 258 - -ZDEFLATE_HASH_BITS: t.CDefine = 15 -ZDEFLATE_HASH_SIZE: t.CDefine = (1 << ZDEFLATE_HASH_BITS) -ZDEFLATE_HASH_MASK: t.CDefine = (ZDEFLATE_HASH_SIZE - 1) - -ZDEFLATE_MAX_CODES: t.CDefine = 288 -ZDEFLATE_MAX_DIST_CODES: t.CDefine = 32 -ZDEFLATE_MAX_BITS: t.CDefine = 15 -ZDEFLATE_MAX_CODELEN_CODES: t.CDefine = 19 - -ZDEFLATE_LIT_COUNT: t.CDefine = 286 -ZDEFLATE_DIST_COUNT: t.CDefine = 30 - -ZDEFLATE_LEN_SYMBOLS_BASE: t.CDefine = 257 -ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 - -# ============================================================ -# Length / Distance extra bits tables (RFC 1951) -# ============================================================ -zdeflate_len_extra_bits: t.CArray[t.CInt, 29] = [ - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, - 2, 2, 2, 2, - 3, 3, 3, 3, - 4, 4, 4, 4, - 5, 5, 5, 5, - 0 -] - -zdeflate_len_base: t.CArray[t.CInt, 29] = [ - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 13, 15, 17, - 19, 23, 27, 31, - 35, 43, 51, 59, - 67, 83, 99, 115, - 131, 163, 195, 227, - 258 -] - -zdeflate_dist_extra_bits: t.CArray[t.CInt, 30] = [ - 0, 0, 0, 0, - 1, 1, - 2, 2, - 3, 3, - 4, 4, - 5, 5, - 6, 6, - 7, 7, - 8, 8, - 9, 9, - 10, 10, - 11, 11, - 12, 12, - 13, 13 -] - -zdeflate_dist_base: t.CArray[t.CInt, 30] = [ - 1, 2, 3, 4, - 5, 7, - 9, 13, - 17, 25, - 33, 49, - 65, 97, - 129, 193, - 257, 385, - 513, 769, - 1025, 1537, - 2049, 3073, - 4097, 6145, - 8193, 12289, - 16385, 24577 -] - -zdeflate_codelen_order: t.CArray[int, 19] = [ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 -] - -# ============================================================ -# Bit writer - writes bits LSB first into a byte buffer -# ============================================================ -@t.Object -class zbit_writer: - buf: BYTE | t.CPtr - cap: t.CSizeT - byte_pos: t.CSizeT - bit_pos: t.CInt - - def __init__(self): - self.cap = 4096 - self.buf = BYTEPTR(malloc(self.cap)) - memset(self.buf, 0, self.cap) - self.byte_pos = 0 - self.bit_pos = 0 - - def ensure(self, need: t.CSizeT): - while self.byte_pos + need + 4 >= self.cap: - new_cap: t.CSizeT = self.cap * 2 - new_buf: BYTE | t.CPtr = BYTEPTR(realloc(self.buf, new_cap)) - if not new_buf: return - memset(new_buf + self.cap, 0, new_cap - self.cap) - self.buf = new_buf - self.cap = new_cap - - def write_bits(self, value: UINT, nbits: t.CInt): - self.ensure((nbits + 7) / 8 + 1) - for i in range(nbits): - if value & (UINT(1) << i): - self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - - def write_bits_rev(self, code: UINT, nbits: t.CInt): - self.ensure((nbits + 7) / 8 + 1) - for i in range(nbits - 1, -1, -1): - if code & (UINT(1) << i): - self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - - def stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - pos: t.CSizeT = 0 - is_first: t.CInt = 1 - while is_first or pos < length: - is_first = 0 - block_length: t.CSizeT = length - pos - if block_length > 65535: - block_length = 65535 - is_last: t.CInt = 1 if (final and pos + block_length >= length) else 0 - self.write_bits(is_last, 1) - self.write_bits(0, 2) - self.align() - - n: t.CUInt16T = t.CUInt16T(block_length) - ncomp: t.CUInt16T = ~n - self.write_bits(n, 16) - self.write_bits(ncomp, 16) - - if data and block_length > 0: - self.ensure(block_length) - i: t.CSizeT = 0 - for i in range(block_length): - self.buf[self.byte_pos] = data[pos + i] - self.byte_pos += 1 - pos += block_length - - def write_zlib_header(self, wbits: t.CInt, level: t.CInt): - cinfo: t.CInt = wbits - 8 - if cinfo < 1: cinfo = 1 - if cinfo > 7: cinfo = 7 - cmf: t.CUnsignedChar = t.CUnsignedChar((cinfo << 4) | 8) - - flevel: t.CInt = 0 - if level >= 5: flevel = 3 - elif level >= 3: flevel = 1 - - flg: t.CUnsignedChar = t.CUnsignedChar(flevel << 6) - flg |= t.CUnsignedChar(31 - (cmf * 256 + flg) % 31) - - self.buf[self.byte_pos + 0] = cmf - self.buf[self.byte_pos + 1] = flg - self.byte_pos += 2 - - - def write_gzip_header(self): - self.buf[self.byte_pos + 0] = 0x1F - self.buf[self.byte_pos + 1] = 0x8B - self.buf[self.byte_pos + 2] = 0x08 - self.buf[self.byte_pos + 3] = 0x00 - self.buf[self.byte_pos + 4] = 0x00 - self.buf[self.byte_pos + 5] = 0x00 - self.buf[self.byte_pos + 6] = 0x00 - self.buf[self.byte_pos + 7] = 0x00 - self.buf[self.byte_pos + 8] = 0x00 - self.buf[self.byte_pos + 9] = 0xFF - self.byte_pos += 10 - - def align(self): - if self.bit_pos > 0: - self.bit_pos = 0 - self.byte_pos += 1 - - def total(self) -> t.CSizeT: - return self.byte_pos + (1 if (self.bit_pos > 0) else 0) - - def free(self): - free(self.buf) - self.buf = None - self.cap = 0 - self.byte_pos = 0 - self.bit_pos = 0 - - def __del__(self): - self.free() - -# ============================================================ -# Bit reader - reads bits LSB first from a byte buffer -# ============================================================ -@t.Object -class zbit_reader: - buf: BYTE | t.CPtr - length: t.CSizeT - byte_pos: t.CSizeT - bit_pos: t.CInt - - def init(self, buf: BYTE | t.CPtr, length: t.CSizeT): - self.buf = buf - self.length = length - self.byte_pos = 0 - self.bit_pos = 0 - - def read_bits(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits): - if self.byte_pos >= self.length: return -1 - if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos): - val |= (UINT(1) << i) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - def read_bits_rev(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits - 1, 0, -1): - if self.byte_pos >= self.length: return -1 - if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos): - val |= (UINT(1) << i) - self.bit_pos += 1 - if self.bit_pos == 8: - self.bit_pos = 0 - self.byte_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - def align(self): - if self.bit_pos > 0: - self.bit_pos = 0 - self.byte_pos += 1 - -# ============================================================ -# Memory allocation helper for bare metal -# Can be replaced with custom allocator -# ============================================================ -def zdef_alloc(n: t.CSizeT) -> VOIDPTR: - return malloc(n) -def zdef_free(p: VOIDPTR): - free(p) diff --git a/Test/ZlibTest/App/__zlib/zdeflate.vp b/Test/ZlibTest/App/__zlib/zdeflate.vp deleted file mode 100644 index 1ca7f2d..0000000 --- a/Test/ZlibTest/App/__zlib/zdeflate.vp +++ /dev/null @@ -1,429 +0,0 @@ -from stdint import * -import zchecksum -import zhuff -import zdef -import string -import t, c - - -@t.Object -class zdeflate_stream: - writer: zdef.zbit_writer - window: BYTE | t.CPtr - window_pos: t.CInt - window_size: t.CInt - hash_head: t.CInt | t.CPtr - hash_prev: t.CInt | t.CPtr - level: t.CInt - strategy: t.CInt - wbits: t.CInt - is_finished: t.CInt - adler: t.CUInt32T - - def find_match(self, data: BYTE | t.CPtr, data_len: t.CSizeT, - pos: t.CSizeT, best_dist: t.CInt | t.CPtr) -> t.CInt: - if pos + 2 >= data_len: return 0 - h: t.CUnsignedInt = zdeflate_hash(data + pos) - chain: t.CInt = self.hash_head[h] - best_len: t.CInt = zdef.ZDEFLATE_MIN_MATCH - 1 - c.Set(c.Deref(best_dist), 0) - max_chain: t.CInt = 128 if (self.level >= 5) else (32 if (self.level >= 2) else 4) - limit: t.CInt = (1 << self.wbits) if (self.wbits > 0) else zdef.ZDEFLATE_WINDOW_SIZE - if limit > zdef.ZDEFLATE_WINDOW_SIZE: - limit = zdef.ZDEFLATE_WINDOW_SIZE - attempts: t.CInt = 0 - while chain >= 0 and attempts < max_chain: - dist: t.CInt = t.CInt(pos) - chain - if dist <= 0 or dist > limit: break - match_len: t.CInt = 0 - max_len: t.CInt = t.CInt(data_len - pos) - if max_len > zdef.ZDEFLATE_MAX_MATCH: - max_len = zdef.ZDEFLATE_MAX_MATCH - while match_len < max_len and data[pos + match_len] == data[chain + match_len]: - match_len += 1 - if match_len > best_len: - best_len = match_len - c.Set(c.Deref(best_dist), dist) - if best_len >= zdef.ZDEFLATE_MAX_MATCH: break - chain = self.hash_prev[chain & zdef.ZDEFLATE_WINDOW_MASK] - if chain <= t.CInt(pos) - limit: break - attempts += 1 - return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0 - - def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT): - if pos + 2 < pos: return - h: t.CUnsignedInt = zdeflate_hash(data + pos) - self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h] - self.hash_head[h] = t.CInt(pos) - - def write_fixed_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - dist_tree.build_fixed_dist_tree() - self.writer.write_bits(1 if final else 0, 1) - self.writer.write_bits(1, 2) - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if self.level > 0 and pos + 2 < length: - match_len = self.find_match(data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_tree.encode_symbol(len_sym, c.Addr(self.writer)) - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257] - if extra > 0: - self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra) - dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist) - dist_tree.encode_symbol(dist_sym, c.Addr(self.writer)) - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra) - for i in range(match_len): - self.update_hash(data, pos + i) - pos += match_len - else: - lit_tree.encode_symbol(data[pos], c.Addr(self.writer)) - self.update_hash(data, pos) - pos += 1 - lit_tree.encode_symbol(256, c.Addr(self.writer)) - - def encode_block_data(self, data: UINT8PTR, length: t.CSizeT, - lit_tree: zhuff.zhuff_tree | t.CPtr, dist_tree: zhuff.zhuff_tree | t.CPtr): - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if self.level > 0 and pos + 2 < length: - match_len = self.find_match(data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_tree.encode_symbol(len_sym, c.Addr(self.writer)) - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257] - if extra > 0: - self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra) - dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist) - dist_tree.encode_symbol(dist_sym, c.Addr(self.writer)) - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra) - for j in range(match_len): - self.update_hash(data, pos + j) - pos += match_len - else: - lit_tree.encode_symbol(data[pos], c.Addr(self.writer)) - self.update_hash(data, pos) - pos += 1 - lit_tree.encode_symbol(256, c.Addr(self.writer)) - - - def write_dynamic_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_freqs: t.CArray[t.CInt, 288] - dist_freqs: t.CArray[t.CInt, 32] - zdeflate_count_freqs(lit_freqs, dist_freqs, self, data, length) - hlit: t.CInt = 286 - while hlit > 257 and lit_freqs[hlit - 1] == 0: hlit -= 1 - hdist: t.CInt = 30 - while hdist > 1 and dist_freqs[hdist - 1] == 0: hdist -= 1 - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_codes(lit_freqs, hlit, zdef.ZDEFLATE_MAX_BITS) - dist_tree.build_codes(dist_freqs, hdist, zdef.ZDEFLATE_MAX_BITS) - all_lengths: t.CArray[t.CInt, 288 + 32] - for i in range(hlit): all_lengths[i] = lit_tree.codes[i].bits - for i in range(hdist): all_lengths[hlit + i] = dist_tree.codes[i].bits - total_lengths: t.CInt = hlit + hdist - cl_freqs: t.CArray[t.CInt, 19] - zdeflate_count_cl_freqs(all_lengths, total_lengths, cl_freqs) - cl_tree = zhuff.zhuff_tree() - cl_tree.build_codes(cl_freqs, 19, 7) - hclen: int = 19 - while hclen > 4 and cl_tree.codes[zdef.zdeflate_codelen_order[hclen - 1]].bits == 0: hclen -= 1 - self.writer.write_bits(1 if final else 0, 1) - self.writer.write_bits(2, 2) - self.writer.write_bits(hlit - 257, 5) - self.writer.write_bits(hdist - 1, 5) - self.writer.write_bits(hclen - 4, 4) - for j in range(hclen): - self.writer.write_bits(cl_tree.codes[zdef.zdeflate_codelen_order[j]].bits, 3) - zdeflate_write_cl_encoded(all_lengths, total_lengths, c.Addr(self.writer), c.Addr(cl_tree)) - self.encode_block_data(data, length, c.Addr(lit_tree), c.Addr(dist_tree)) - - def compress_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - if self.level == 0: - self.write_stored_block(data, length, final) - elif self.strategy == 4 or length < 128: - self.write_fixed_block(data, length, final) - else: - self.write_dynamic_block(data, length, final) - - def write_stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - self.writer.stored_block(data, length, final) - - def compress(self, data: UINT8PTR, length: t.CSizeT, - out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if self.is_finished: return -2 - if not data or length == 0: - c.Set(c.Deref(out), None) - c.Set(c.Deref(out_len), 0) - return 0 - self.adler = zchecksum.zchecksum_adler32(data, length, self.adler) - memset(self.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(self.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - self.compress_block(data, length, 0) - c.Set(c.Deref(out_len), self.writer.total()) - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(c.Deref(out_len)))) - if not c.Deref(out): return -4 - memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len)) - return 0 - - def flush(self, mode: t.CInt, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if mode == 4: - if not self.is_finished: - if self.level == 0: - self.writer.stored_block(None, 0, 1) - else: - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - self.writer.write_bits(1, 1) - self.writer.write_bits(1, 2) - lit_tree.encode_symbol(256, c.Addr(self.writer)) - self.is_finished = 1 - if self.wbits >= 0: - self.writer.align() - adler: t.CUInt32T = self.adler - self.writer.buf[self.writer.byte_pos + 0] = (adler >> 24) & 0xFF - self.writer.buf[self.writer.byte_pos + 1] = (adler >> 16) & 0xFF - self.writer.buf[self.writer.byte_pos + 2] = (adler >> 8) & 0xFF - self.writer.buf[self.writer.byte_pos + 3] = (adler >> 0) & 0xFF - self.writer.byte_pos += 4 - elif mode == 2 or mode == 3: - self.writer.write_bits(0, 1) - self.writer.write_bits(0, 2) - self.writer.align() - c.Set(c.Deref(out_len), self.writer.total()) - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(c.Deref(out_len)))) - if not c.Deref(out): return -4 - memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len)) - return 0 - - def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt: - if not dict: return -2 - use: t.CSizeT = length - if use > zdef.ZDEFLATE_WINDOW_SIZE: - dict += length - zdef.ZDEFLATE_WINDOW_SIZE - use = zdef.ZDEFLATE_WINDOW_SIZE - memcpy(self.window, dict, use) - self.window_size = t.CInt(use) - self.window_pos = t.CInt(use) - self.adler = zchecksum.zchecksum_adler32(dict, length, self.adler) - return 0 - - def copy(self) -> zdeflate_stream | t.CPtr: - z: zdeflate_stream | t.CPtr = zdef.zdef_alloc(zdeflate_stream.__sizeof__()) - if not z: return None - memcpy(z, self, zdeflate_stream.__sizeof__()) - z.writer.buf = BYTEPTR(zdef.zdef_alloc(self.writer.cap)) - if not z.writer.buf: - zdef.zdef_free(z) - return None - memcpy(z.writer.buf, self.writer.buf, self.writer.cap) - z.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - z.hash_head = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())) - z.hash_prev = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())) - if not z.window or not z.hash_head or not z.hash_prev: - self.destroy() - return None - memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE) - memcpy(z.hash_head, self.hash_head, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memcpy(z.hash_prev, self.hash_prev, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - return z - - def destroy(self): - if self.writer.buf: zdef.zdef_free(self.writer.buf) - if self.window: zdef.zdef_free(self.window) - if self.hash_head: zdef.zdef_free(self.hash_head) - if self.hash_prev: zdef.zdef_free(self.hash_prev) - zdef.zdef_free(self) - - - - -def zdeflate_count_freqs(lit_freqs: INTPTR, dist_freqs: INTPTR, - s: zdeflate_stream | t.CPtr, data: UINT8PTR, length: t.CSizeT): - memset(lit_freqs, 0, 288 * int.__sizeof__()) - memset(dist_freqs, 0, 32 * int.__sizeof__()) - pos: t.CSizeT = 0 - while pos < length: - best_dist: t.CInt = 0 - match_len: t.CInt = 0 - if s.level > 0 and pos + 2 < length: - match_len = zdeflate_stream.find_match(s, data, length, pos, c.Addr(best_dist)) - if match_len >= zdef.ZDEFLATE_MIN_MATCH: - len_sym: t.CInt = zdeflate_len_to_symbol(match_len) - lit_freqs[len_sym] += 1 - dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1 - for i in range(match_len): - zdeflate_stream.update_hash(s, data, pos + i) - pos += match_len - else: - lit_freqs[data[pos]] += 1 - zdeflate_stream.update_hash(s, data, pos) - pos += 1 - lit_freqs[256] = 1 - - - -def zdeflate_hash(p: BYTE | t.CPtr) -> t.CUnsignedInt: - return (t.CUnsignedInt(p[0]) ^ (t.CUnsignedInt(p[1]) << 5) ^ (t.CUnsignedInt(p[2]) << 10)) & zdef.ZDEFLATE_HASH_MASK - - -def zdeflate_len_to_symbol(length: t.CInt) -> t.CInt: - for i in range(29): - if length <= zdef.zdeflate_len_base[i] + (1 << zdef.zdeflate_len_extra_bits[i]) - 1: - return 257 + i - return 285 - -def zdeflate_dist_to_symbol(dist: t.CInt) -> t.CInt: - for i in range(30): - if dist <= zdef.zdeflate_dist_base[i] + (1 << zdef.zdeflate_dist_extra_bits[i]) - 1: - return i - return 29 - -def zdeflate_count_cl_freqs(all_lengths: INTPTR, total: t.CInt, cl_freqs: INTPTR): - memset(cl_freqs, 0, 19 * int.__sizeof__()) - i: t.CInt = 0 - while i < total: - if all_lengths[i] == 0: - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == 0: run += 1 - while run > 0: - if run >= 11: - count: t.CInt = run - if count > 138: count = 138 - cl_freqs[18] += 1 - run -= count - elif run >= 3: - count: t.CInt = run - if count > 10: count = 10 - cl_freqs[17] += 1 - run -= count - else: - cl_freqs[0] += 1 - run -= 1 - while i < total and all_lengths[i] == 0: i += 1 - else: - cl_freqs[all_lengths[i]] += 1 - val: t.CInt = all_lengths[i] - i += 1 - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == val: run += 1 - while run >= 3: - count: t.CInt = run - if count > 6: count = 6 - cl_freqs[16] += 1 - run -= count - i += run - -def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt, - w: zdef.zbit_writer | t.CPtr, cl_tree: zhuff.zhuff_tree | t.CPtr): - i: t.CInt = 0 - while i < total: - if all_lengths[i] == 0: - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == 0: run += 1 - while run > 0: - if run >= 11: - count: t.CInt = run - if count > 138: count = 138 - cl_tree.encode_symbol(18, w) - w.write_bits(count - 11, 7) - run -= count - elif run >= 3: - count: t.CInt = run - if count > 10: count = 10 - cl_tree.encode_symbol(17, w) - w.write_bits(count - 3, 3) - run -= count - else: - cl_tree.encode_symbol(0, w) - run -= 1 - while i < total and all_lengths[i] == 0: i += 1 - else: - cl_tree.encode_symbol(all_lengths[i], w) - val: t.CInt = all_lengths[i] - i += 1 - run: t.CInt = 0 - while i + run < total and all_lengths[i + run] == val: run += 1 - while run >= 3: - count: t.CInt = run - if count > 6: count = 6 - cl_tree.encode_symbol(16, w) - w.write_bits(count - 3, 2) - run -= count - i += run - - - -def zdeflate_create(level: t.CInt, wbits: t.CInt, mem_level: t.CInt, strategy: t.CInt) -> zdeflate_stream | t.CPtr: - if level < 0: - level = 6 - s: zdeflate_stream | t.CPtr = zdef.zdef_alloc(zdeflate_stream.__sizeof__()) - if not s: return None - memset(s, 0, zdeflate_stream.__sizeof__()) - s.writer = zdef.zbit_writer() - s.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - s.hash_head = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())) - s.hash_prev = INTPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())) - if not s.window or not s.hash_head or not s.hash_prev: - s.destroy() - return None - memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - s.level = level - s.wbits = wbits - s.strategy = strategy - s.is_finished = 0 - s.adler = 1 - if wbits > 0: - s.writer.write_zlib_header(wbits, level) - elif wbits == 0: - s.writer.write_zlib_header(15, level) - return s - - -def zdeflate_one_shot(data: UINT8PTR, length: t.CSizeT, - level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr: - s: zdeflate_stream | t.CPtr = zdeflate_create(level, wbits, 8, 0) - if not s: return None - - memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) - memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()) - - s.adler = zchecksum.zchecksum_adler32(data, length, 1) - - if length == 0: - s.writer.write_bits(1, 1) - s.writer.write_bits(1, 2) - lit_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - lit_tree.encode_symbol(256, c.Addr(s.writer)) - else: - s.compress_block(data, length, 1) - - s.is_finished = 1 - - if wbits >= 0: - s.writer.align() - adler: t.CUInt32T = s.adler - s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF - s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF - s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF - s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF - s.writer.byte_pos += 4 - c.Set(c.Deref(out_len), s.writer.total()) - result: UINT8PTR = UINT8PTR(zdef.zdef_alloc(c.Deref(out_len))) - if result: memcpy(result, s.writer.buf, c.Deref(out_len)) - s.destroy() - return result diff --git a/Test/ZlibTest/App/__zlib/zhuff.vp b/Test/ZlibTest/App/__zlib/zhuff.vp deleted file mode 100644 index ad78c94..0000000 --- a/Test/ZlibTest/App/__zlib/zhuff.vp +++ /dev/null @@ -1,353 +0,0 @@ -#include -from stdint import * -import zdef -import t, c - - -ZHUFF_MAX_CODES: t.CDefine = 288 -ZHUFF_MAX_BITS: t.CDefine = 15 - -class zhuff_code: - code: UINT - bits: t.CInt - -@t.Object -class zhuff_tree: - codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES] - count: t.CInt - max_bits: t.CInt - - def __init__(self): - pass - - def build_codes(self, freqs: INTPTR, count: t.CInt, max_bits: t.CInt): - lengths: t.CArray[t.CInt, ZHUFF_MAX_CODES] - bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 1] - next_code: t.CArray[UINT, ZHUFF_MAX_BITS + 1] - self.count = count - self.max_bits = max_bits - self.build_code_lengths(lengths, freqs, count, max_bits) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, max_bits + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - for i in range(count): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def build_fixed_lit_tree(self): - lengths: t.CArray[t.CInt, 288] - bl_count: t.CArray[t.CInt, 16] - next_code: t.CArray[t.CUnsignedInt, 16] - self.get_fixed_lit_lengths(lengths) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(288): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, 9 + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - self.count = 288 - self.max_bits = 9 - for i in range(288): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def build_fixed_dist_tree(self): - lengths: t.CArray[t.CInt, 32] - bl_count: t.CArray[t.CInt, 16] - next_code: t.CArray[t.CUnsignedInt, 16] - self.get_fixed_dist_lengths(lengths) - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(32): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - code: t.CUnsignedInt = 0 - next_code[0] = 0 - for bits in range(1, 5 + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - self.count = 32 - self.max_bits = 5 - for i in range(32): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - def encode_symbol(self, symbol: int, writer: zdef.zbit_writer | t.CPtr): - if symbol < 0 or symbol >= self.count: - return - if self.codes[symbol].bits == 0: - return - writer.write_bits_rev(self.codes[symbol].code, self.codes[symbol].bits) - - - def build_code_lengths(self, lengths: t.CInt | t.CPtr, freqs: t.CInt | t.CPtr, count: t.CInt, max_bits: t.CInt): - bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 2] - sort_count: t.CInt = 0 - memset(bl_count, 0, bl_count.__sizeof__()) - memset(lengths, 0, int.__sizeof__() * count) - for i in range(count): - if freqs[i] > 0: - sort_count += 1 - if sort_count == 0: return - if sort_count == 1: - for i in range(count): - if freqs[i] > 0: - lengths[i] = 1 - return - items: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - item_freqs: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - idx: t.CInt = 0 - for i in range(count): - if freqs[i] > 0: - items[idx] = i - item_freqs[idx] = freqs[i] - idx += 1 - for i in range(sort_count): - key_item: t.CInt = items[i] - key_freq: t.CInt = item_freqs[i] - j: t.CInt = i - 1 - while j >= 0 and item_freqs[j] > key_freq: - items[j + 1] = items[j] - item_freqs[j + 1] = item_freqs[j] - j -= 1 - items[j + 1] = key_item - item_freqs[j + 1] = key_freq - parent: INTPTR = INTPTR(zdef.zdef_alloc((sort_count * 2) * int.__sizeof__())) - for i in range(sort_count * 2): - parent[i] = -1 - heap: INTPTR = INTPTR(zdef.zdef_alloc((sort_count + 1) * int.__sizeof__())) - heap_size: t.CInt = 0 - for i in range(sort_count): - heap[heap_size] = i - heap_size += 1 - pos: t.CInt = heap_size - 1 - while pos > 0: - par: t.CInt = (pos - 1) / 2 - if item_freqs[heap[par]] > item_freqs[heap[pos]]: - tmp: t.CInt = heap[par] - heap[par] = heap[pos] - heap[pos] = tmp - pos = par - else: break - combined_freq: INTPTR = INTPTR(zdef.zdef_alloc((sort_count * 2) * int.__sizeof__())) - for i in range(sort_count): - combined_freq[i] = item_freqs[i] - internal: t.CInt = sort_count - while heap_size > 1: - a: t.CInt = heap[0] - heap[0] = heap[heap_size - 1] - heap_size -= 1 - pos: t.CInt = 0 - while True: - left: t.CInt = 2 * pos + 1 - right: t.CInt = 2 * pos + 2 - smallest: t.CInt = pos - if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]: - smallest = left - if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]: - smallest = right - if smallest != pos: - tmp: t.CInt = heap[pos] - heap[pos] = heap[smallest] - heap[smallest] = tmp - pos = smallest - else: break - b: t.CInt = heap[0] - heap[0] = heap[heap_size - 1] - heap_size -= 1 - pos = 0 - while True: - left: t.CInt = 2 * pos + 1 - right: t.CInt = 2 * pos + 2 - smallest: t.CInt = pos - if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]: - smallest = left - if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]: - smallest = right - if smallest != pos: - tmp: t.CInt = heap[pos] - heap[pos] = heap[smallest] - heap[smallest] = tmp - pos = smallest - else: break - if internal >= sort_count * 2 - 1: break - combined_freq[internal] = combined_freq[a] + combined_freq[b] - parent[a] = internal - parent[b] = internal - heap[heap_size] = internal - heap_size += 1 - pos = heap_size - 1 - while pos > 0: - par: t.CInt = (pos - 1) / 2 - if combined_freq[heap[par]] > combined_freq[heap[pos]]: - tmp: t.CInt = heap[par] - heap[par] = heap[pos] - heap[pos] = tmp - pos = par - else: break - internal += 1 - for i in range(sort_count): - node: t.CInt = i - length: t.CInt = 0 - while parent[node] >= 0: - length += 1 - node = parent[node] - lengths[items[i]] = length - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - overflow: t.CInt = 0 - for i in range(count): - if lengths[i] > max_bits: - overflow += 1 - bl_count[lengths[i]] -= 1 - lengths[i] = max_bits - bl_count[max_bits] += 1 - while overflow > 0: - bits: t.CInt = max_bits - 1 - while bits > 0 and bl_count[bits] == 0: - bits -= 1 - if bits == 0: break - bl_count[bits] -= 1 - bl_count[bits + 1] += 2 - bl_count[max_bits] -= 1 - overflow -= 2 - sorted_items: INTPTR = INTPTR(zdef.zdef_alloc(sort_count * int.__sizeof__())) - si: t.CInt = 0 - for i in range(count): - if freqs[i] > 0: - sorted_items[si] = i - si += 1 - for i in range(si - 1): - for j in range(i + 1, si): - if lengths[sorted_items[i]] < lengths[sorted_items[j]]: - tmp: t.CInt = sorted_items[i] - sorted_items[i] = sorted_items[j] - sorted_items[j] = tmp - sidx: t.CInt = 0 - for bits in range(max_bits, 1, -1): - n: t.CInt = bl_count[bits] - while n > 0 and sidx < si: - lengths[sorted_items[sidx]] = bits - sidx += 1 - n -= 1 - zdef.zdef_free(sorted_items) - zdef.zdef_free(heap) - zdef.zdef_free(parent) - zdef.zdef_free(combined_freq) - zdef.zdef_free(item_freqs) - zdef.zdef_free(items) - - def get_fixed_lit_lengths(self, lengths: INTPTR): - for i in range( 0, 143 + 1): lengths[i] = 8 - for i in range(143 + 1, 255 + 1): lengths[i] = 9 - for i in range(255 + 1, 279 + 1): lengths[i] = 7 - for i in range(279 + 1, 287 + 1): lengths[i] = 8 - - def get_fixed_dist_lengths(self, lengths: INTPTR): - for i in range(32): - lengths[i] = 5 - - def build_tree_from_lengths(self, lengths: INTPTR, count: t.CInt, max_bits: t.CInt): - bl_count: t.CArray[t.CInt, 16] - next_code: t.CArray[t.CUnsignedInt, 16] - - memset(bl_count, 0, bl_count.__sizeof__()) - for i in range(count): - if lengths[i] > 0: - bl_count[lengths[i]] += 1 - - code: UINT = 0 - next_code[0] = 0 - for bits in range(1, max_bits + 1): - code = (code + bl_count[bits - 1]) << 1 - next_code[bits] = code - - self.count = count - self.max_bits = max_bits - for i in range(count): - self.codes[i].bits = lengths[i] - if lengths[i] > 0: - self.codes[i].code = next_code[lengths[i]] - next_code[lengths[i]] += 1 - else: - self.codes[i].code = 0 - - -class zhuff_decode_node: - children: t.CArray[t.CInt, 2] - symbol: t.CInt - - -@t.Object -class zhuff_decode_tree: - nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] - node_count: t.CInt - root: t.CInt - - def __init__(self): - pass - - def build_decode_tree(self, ht: zhuff_tree | t.CPtr): - self.node_count = 1 - self.root = 0 - self.nodes[0].children[0] = -1 - self.nodes[0].children[1] = -1 - self.nodes[0].symbol = -1 - for i in range(ht.count): - if ht.codes[i].bits == 0: continue - node: int = 0 - for bit in range(ht.codes[i].bits - 1, -1, -1): - dir: t.CInt = (ht.codes[i].code >> bit) & 1 - if bit > 0: - # Internal node: traverse or create - if self.nodes[node].children[dir] == -1: - new_node: int = self.node_count - self.node_count += 1 - self.nodes[new_node].children[0] = -1 - self.nodes[new_node].children[1] = -1 - self.nodes[new_node].symbol = -1 - self.nodes[node].children[dir] = new_node - node = self.nodes[node].children[dir] - else: - # Leaf: bit 0 - set symbol on the child - if self.nodes[node].children[dir] == -1: - leaf: int = self.node_count - self.node_count += 1 - self.nodes[leaf].children[0] = -1 - self.nodes[leaf].children[1] = -1 - self.nodes[leaf].symbol = i - self.nodes[node].children[dir] = leaf - else: - self.nodes[self.nodes[node].children[dir]].symbol = i - - def decode_symbol(self, reader: zdef.zbit_reader | t.CPtr) -> t.CInt: - node: int = self.root - while self.nodes[node].symbol == -1: - bit: t.CUnsignedInt - if reader.read_bits(1, c.Addr(bit)) != 0: return -1 - dir: t.CInt = t.CInt(bit) - if self.nodes[node].children[dir] == -1: return -1 - node = self.nodes[node].children[dir] - return self.nodes[node].symbol diff --git a/Test/ZlibTest/App/__zlib/zinflate.vp b/Test/ZlibTest/App/__zlib/zinflate.vp deleted file mode 100644 index 985f63e..0000000 --- a/Test/ZlibTest/App/__zlib/zinflate.vp +++ /dev/null @@ -1,454 +0,0 @@ -from stdint import * -import zinflate -import zchecksum -import zdef -import zhuff -import string -import t, c - - -@t.Object -class zinflate_stream: - reader: zdef.zbit_reader - - window: BYTEPTR - window_pos: t.CInt - window_size: t.CInt - - wbits: t.CInt - is_finished: t.CInt - is_initialized: t.CInt - - header_parsed: t.CInt - is_gzip: t.CInt - - adler: t.CUInt32T - crc: t.CUInt32T - - output: BYTEPTR - output_len: t.CSizeT - output_cap: t.CSizeT - - input_data: t.CConst | BYTEPTR - input_len: t.CSizeT - input_pos: t.CSizeT - - max_length: t.CSizeT - - def __init__(self): - pass - - def output_byte(self, byte: BYTE): - if self.max_length > 0 and self.output_len >= self.max_length: return - - if self.output_len >= self.output_cap: - new_cap: t.CSizeT = self.output_cap * 2 - if new_cap < 256: new_cap = 256 - new_buf: BYTEPTR = BYTEPTR(zdef.zdef_alloc(new_cap)) - if not new_buf: return - memcpy(new_buf, self.output, self.output_len) - zdef.zdef_free(self.output) - self.output = new_buf - self.output_cap = new_cap - self.output[self.output_len] = byte - self.output_len += 1 - self.window[self.window_pos & (zdef.ZDEFLATE_WINDOW_SIZE - 1)] = byte - self.window_pos += 1 - - - def parse_header(self) -> t.CInt: - if self.header_parsed: return 0 - if self.wbits < 0: - self.header_parsed = 1 - self.is_gzip = 0 - return 0 - if self.input_pos + 2 > self.input_len: return -3 - b0: BYTE = self.input_data[self.input_pos] - b1: BYTE = self.input_data[self.input_pos + 1] - if b0 == 0x1F and b1 == 0x8B: - self.is_gzip = 1 - if self.input_pos + 10 > self.input_len: return -3 - self.input_pos += 10 - flg: BYTE = self.input_data[self.input_pos - 6] - if flg & 0x04: - if self.input_pos + 2 > self.input_len: return -3 - xlen: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8) - self.input_pos += 2 + xlen - if flg & 0x08: - while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1 - self.input_pos += 1 - if flg & 0x10: - while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1 - self.input_pos += 1 - if flg & 0x02: - self.input_pos += 2 - if self.input_pos > self.input_len: return -3 - else: - self.is_gzip = 0 - if (b0 * 256 + b1) % 31 != 0: return -3 - cm: t.CInt = b0 & 0x0F - if cm != 8: return -3 - self.input_pos += 2 - self.header_parsed = 1 - return 0 - - - def read_bits_from_input(self, nbits: t.CInt, out: UINTPTR) -> t.CInt: - val: UINT = 0 - for i in range(nbits): - if self.input_pos >= self.input_len: return -3 - if self.input_data[self.input_pos] & (UINT(1) << (self.reader.bit_pos)): - val |= (UINT(1) << i) - self.reader.bit_pos += 1 - if self.reader.bit_pos == 8: - self.reader.bit_pos = 0 - self.input_pos += 1 - c.Set(c.Deref(out), val) - return 0 - - - def read_huffman(self, dt: zhuff.zhuff_decode_tree | t.CPtr) -> t.CInt: - node: int = dt.root - while dt.nodes[node].symbol == -1: - bit: UINT - if self.read_bits_from_input(1, c.Addr(bit)) != 0: return -1 - dir: int = t.CInt(bit) - if dt.nodes[node].children[dir] == -1: return -3 - node = dt.nodes[node].children[dir] - return dt.nodes[node].symbol - - def inflate_block_stored(self) -> t.CInt: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 4 > self.input_len: return -3 - length: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8) - nlen: UINT = self.input_data[self.input_pos + 2] | (self.input_data[self.input_pos + 3] << 8) - self.input_pos += 4 - if (length ^ nlen) != 0xFFFF: return -3 - if self.input_pos + length > self.input_len: return -3 - i: t.CUnsignedInt - for i in range(length): - self.output_byte(self.input_data[self.input_pos]) - self.input_pos += 1 - return 0 - - - def inflate_block_fixed(self) -> t.CInt: - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - lit_tree.build_fixed_lit_tree() - dist_tree.build_fixed_dist_tree() - - lit_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(zhuff.zhuff_decode_tree.__sizeof__()) - dist_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(zhuff.zhuff_decode_tree.__sizeof__()) - if not lit_dt or not dist_dt: - if lit_dt: zdef.zdef_free(lit_dt) - if dist_dt: zdef.zdef_free(dist_dt) - return -4 - memset(lit_dt, 0, zhuff.zhuff_decode_tree.__sizeof__()) - memset(dist_dt, 0, zhuff.zhuff_decode_tree.__sizeof__()) - lit_dt.build_decode_tree(c.Addr(lit_tree)) - dist_dt.build_decode_tree(c.Addr(dist_tree)) - - result: t.CInt = 0 - while True: - if self.max_length > 0 and self.output_len >= self.max_length: break - - sym: t.CInt = self.read_huffman(lit_dt) - if sym < 0: - result = -3 - break - if sym == 256: break - if sym < 256: - self.output_byte(BYTE(sym)) - else: - len_idx: t.CInt = sym - 257 - if len_idx < 0 or len_idx >= 29: - result = -3 - break - length: t.CInt = zdef.zdeflate_len_base[len_idx] - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: - result = -3 - break - length += extra_val - - dist_sym: t.CInt = self.read_huffman(dist_dt) - if dist_sym < 0 or dist_sym >= 30: - result = -3 - break - dist: t.CInt = zdef.zdeflate_dist_base[dist_sym] - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: - result = -3 - break - dist += extra_val - - for i in range(length): - if self.max_length > 0 and self.output_len >= self.max_length: break - src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1) - byte: BYTE = self.window[src_pos] - self.output_byte(byte) - - zdef.zdef_free(lit_dt) - zdef.zdef_free(dist_dt) - return result - - - def inflate_block_dynamic(self) -> t.CInt: - hlit_val: UINT - hdist_val: UINT - hclen_val: UINT - if self.read_bits_from_input(5, c.Addr(hlit_val)) != 0: return -3 - if self.read_bits_from_input(5, c.Addr(hdist_val)) != 0: return -3 - if self.read_bits_from_input(4, c.Addr(hclen_val)) != 0: return -3 - - hlit: t.CInt = t.CInt(hlit_val) + 257 - hdist: t.CInt = t.CInt(hdist_val) + 1 - hclen: t.CInt = t.CInt(hclen_val) + 4 - - cl_lengths: t.CArray[t.CInt, 19] - memset(cl_lengths, 0, cl_lengths.__sizeof__()) - for i in range(hclen): - len_val: UINT - if self.read_bits_from_input(3, c.Addr(len_val)) != 0: return -3 - cl_lengths[zdef.zdeflate_codelen_order[i]] = t.CInt(len_val) - - cl_tree = zhuff.zhuff_tree() - cl_tree.build_tree_from_lengths(cl_lengths, 19, 7) - - cl_dt = zhuff.zhuff_decode_tree() - cl_dt.build_decode_tree(c.Addr(cl_tree)) - - total: t.CInt = hlit + hdist - all_lengths: t.CInt | t.CPtr = zdef.zdef_alloc(total * int.__sizeof__()) - if not all_lengths: return -4 - - idx: t.CInt = 0 - while idx < total: - sym: t.CInt = self.read_huffman(c.Addr(cl_dt)) - if sym < 0 or sym > 18: - zdef.zdef_free(all_lengths) - return -3 - if sym < 16: - all_lengths[idx] = sym - idx += 1 - elif sym == 16: - rep: UINT - if self.read_bits_from_input(2, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 3 - if idx == 0 or idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - prev: t.CInt = all_lengths[idx - 1] - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = prev - idx += 1 - elif sym == 17: - rep: t.CUnsignedInt - if self.read_bits_from_input(3, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 3 - if idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = 0 - idx += 1 - else: - rep: t.CUnsignedInt - if self.read_bits_from_input(7, c.Addr(rep)) != 0: - zdef.zdef_free(all_lengths) - return -3 - rep += 11 - if idx + rep > total: - zdef.zdef_free(all_lengths) - return -3 - i: t.CUnsignedInt - for i in range(rep): - all_lengths[idx] = 0 - idx += 1 - - lit_tree = zhuff.zhuff_tree() - dist_tree = zhuff.zhuff_tree() - - lit_lengths: t.CArray[t.CInt, 288] - memset(lit_lengths, 0, lit_lengths.__sizeof__()) - for i in range(hlit): - lit_lengths[i] = all_lengths[i] - lit_tree.build_tree_from_lengths(lit_lengths, hlit, zdef.ZDEFLATE_MAX_BITS) - - dist_lengths: t.CArray[t.CInt, 32] - memset(dist_lengths, 0, dist_lengths.__sizeof__()) - for i in range(hdist): - dist_lengths[i] = all_lengths[hlit + i] - dist_tree.build_tree_from_lengths(dist_lengths, hdist, zdef.ZDEFLATE_MAX_BITS) - - zdef.zdef_free(all_lengths) - - lit_dt = zhuff.zhuff_decode_tree() - dist_dt = zhuff.zhuff_decode_tree() - lit_dt.build_decode_tree(c.Addr(lit_tree)) - dist_dt.build_decode_tree(c.Addr(dist_tree)) - - while True: - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - sym: t.CInt = self.read_huffman(c.Addr(lit_dt)) - if sym < 0: return -3 - if sym == 256: return 0 - if sym < 256: - self.output_byte(BYTE(sym)) - else: - len_idx: t.CInt = sym - 257 - if len_idx < 0 or len_idx >= 29: return -3 - length: t.CInt = zdef.zdeflate_len_base[len_idx] - extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3 - length += extra_val - dist_sym: t.CInt = self.read_huffman(c.Addr(dist_dt)) - if dist_sym < 0 or dist_sym >= 30: return -3 - dist: t.CInt = zdef.zdeflate_dist_base[dist_sym] - extra = zdef.zdeflate_dist_extra_bits[dist_sym] - if extra > 0: - extra_val: UINT - if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3 - dist += extra_val - for i in range(length): - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1) - byte: BYTE = self.window[src_pos] - self.output_byte(byte) - - def inflate_stream(self) -> t.CInt: - err: t.CInt = self.parse_header() - if err != 0: return err - while not self.is_finished: - bfinal_val: UINT - btype_val: UINT - if self.read_bits_from_input(1, c.Addr(bfinal_val)) != 0: return -3 - if self.read_bits_from_input(2, c.Addr(btype_val)) != 0: return -3 - bfinal: t.CInt = t.CInt(bfinal_val) - btype: t.CInt = t.CInt(btype_val) - if btype == 0: - err = self.inflate_block_stored() - elif btype == 1: - err = self.inflate_block_fixed() - elif btype == 2: - err = self.inflate_block_dynamic() - else: - return -3 - if err != 0: return err - if bfinal: self.is_finished = 1 - if self.max_length > 0 and self.output_len >= self.max_length: return 0 - if self.is_gzip: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 8 <= self.input_len: - self.crc = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 0) | - (t.CUInt32T(self.input_data[self.input_pos + 1]) << 8) | - (t.CUInt32T(self.input_data[self.input_pos + 2]) << 16) | - (t.CUInt32T(self.input_data[self.input_pos + 3]) << 24)) - self.input_pos += 8 - elif self.wbits >= 0: - if self.reader.bit_pos != 0: - self.reader.bit_pos = 0 - self.input_pos += 1 - if self.input_pos + 4 <= self.input_len: - self.adler = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 24) | - (t.CUInt32T(self.input_data[self.input_pos + 1]) << 16) | - (t.CUInt32T(self.input_data[self.input_pos + 2]) << 8) | - (t.CUInt32T(self.input_data[self.input_pos + 3]) << 0)) - self.input_pos += 4 - return 0 - - def decompress(self, data: UINT8PTR, length: t.CSizeT, - max_length: t.CSizeT, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt: - if not self.is_initialized: return -2 - self.input_data = data - self.input_len = length - self.input_pos = 0 - self.reader.bit_pos = 0 - self.output_len = 0 - self.max_length = max_length - err: t.CInt = self.inflate_stream() - if err != 0: return err - c.Set(c.Deref(out_len), self.output_len) - if self.output_len == 0: - c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(1))) - else: - dst: UINT8PTR = UINT8PTR(zdef.zdef_alloc(self.output_len)) - c.Set(c.Deref(out), dst) - if dst: - memcpy(dst, self.output, self.output_len) - return 0 - - def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt: - if not dict: return -2 - use: t.CSizeT = length - if use > zdef.ZDEFLATE_WINDOW_SIZE: - dict += length - zdef.ZDEFLATE_WINDOW_SIZE - use = zdef.ZDEFLATE_WINDOW_SIZE - memcpy(self.window, dict, use) - self.window_pos = t.CInt(use) - return 0 - - def copy(self) -> zinflate_stream | t.CPtr: - z: zinflate_stream | t.CPtr = zdef.zdef_alloc(zinflate_stream.__sizeof__()) - if not z: return None - memcpy(z, self, zinflate_stream.__sizeof__()) - z.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - z.output = BYTEPTR(zdef.zdef_alloc(self.output_cap)) - if not z.window or not z.output: - zinflate_stream.destroy(z) - return None - memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE) - memcpy(z.output, self.output, self.output_cap) - return z - - def destroy(self): - if not self: return - if self.window: zdef.zdef_free(self.window) - if self.output: zdef.zdef_free(self.output) - zdef.zdef_free(self) - - -def zinflate_one_shot(data: UINT8PTR, length: t.CSizeT, - wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr: - s: zinflate_stream | t.CPtr = zinflate_create(wbits) - if not s: return None - out: t.CUInt8T | t.CPtr = None - err: t.CInt = s.decompress(data, length, 0, c.Addr(out), out_len) - s.destroy() - if err != 0: return None - return out - - -def zinflate_create(wbits: t.CInt) -> zinflate_stream | t.CPtr: - s: zinflate_stream | t.CPtr = zdef.zdef_alloc(zinflate_stream.__sizeof__()) - if not s: return None - memset(s, 0, zinflate_stream.__sizeof__()) - s.wbits = wbits - s.is_initialized = 1 - s.adler = 1 - s.window = BYTEPTR(zdef.zdef_alloc(zdef.ZDEFLATE_WINDOW_SIZE)) - s.output = BYTEPTR(zdef.zdef_alloc(256)) - s.output_cap = 256 - s.output_len = 0 - s.max_length = 0 - if not s.window or not s.output: - s.destroy() - return None - return s diff --git a/TestProject/App/main.vp b/TestProject/App/main.vp index ff705c1..40def98 100644 --- a/TestProject/App/main.vp +++ b/TestProject/App/main.vp @@ -1,20 +1,24 @@ import w32.win32console as w32cmd from w32.win32console import SetConsoleOutputCP, SetConsoleCP -import stdlib +import stdlib, stdio import memhub import string +import this import t, c pagecode: t.CDefine = 65001 -@c.Attribute(t.attr.packed) +# @c.Attribute(t.attr.packed) class A: a: int = 1 def __init__(self): self.a = 10 - +def workk(): + print(1) + raise Exception("workk") + print(2) @t.CExport @@ -31,7 +35,7 @@ def main() -> int: a: A | t.CPtr = m.alloc(A.__sizeof__()) string.memset(a, 0, A.__sizeof__()) - string.memset(a, 0x00000002, A.__sizeof__()) + c.DerefAs(a, 0x00000002) # *a = 2 print(a.a) # 2 a.__before_init__() @@ -42,4 +46,14 @@ def main() -> int: print("你好") + try: + workk() + except Exception as e: + print(e) + + this.this() + + #for s in "nihao": + # stdio.printf("%c", s) + return 0 diff --git a/a.vp b/a.vp new file mode 100644 index 0000000..7c8abf1 --- /dev/null +++ b/a.vp @@ -0,0 +1,27 @@ +import re +import t, c + +enum A: + k: t.State + +extern def add(a: int, b: int) -> int # return a + b +export def minus(a: int, b: int) -> int: + return a - b + +inline fn a(): return +inline func b(): return +inline function d(): return + +# 装饰器高亮消失 + +# fn fun func function + +# virual + + + + + + +def main(): + Asm("") diff --git a/find.py b/find.py deleted file mode 100644 index 1af572b..0000000 --- a/find.py +++ /dev/null @@ -1,163 +0,0 @@ -""" -REPL 模式文件内容搜索工具 -支持正则或纯文本搜索,默认搜索当前目录 -""" -import os -import re -import sys - -# 硬编码排除目录 -EXCLUDE_DIRS = { - '.git', '.vs', 'node_modules', '__pycache__', '.idea', - 'miniprogram_npm', '_backup_pre_redesign', -} - -# 排除的文件扩展名 -EXCLUDE_EXTS = { - '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.bmp', - '.mp3', '.mp4', '.wav', '.avi', - '.zip', '.rar', '.7z', '.tar', '.gz', - '.exe', '.dll', '.so', '.dylib', - '.pyc', '.pyo', '.class', '.o', '.obj', - '.db', '.sqlite', '.vsidx', -} - -# 默认搜索根目录 -DEFAULT_ROOT = os.path.dirname(os.path.abspath(__file__)) - - -def should_skip(dirpath): - """判断目录是否应跳过""" - parts = dirpath.replace('\\', '/').split('/') - return any(p in EXCLUDE_DIRS for p in parts) - - -def search(pattern, root=DEFAULT_ROOT, use_regex=True, max_results=50): - """搜索文件内容""" - if use_regex: - try: - compiled = re.compile(pattern, re.IGNORECASE) - except re.error as e: - print(f' 正则语法错误: {e}') - return - - count = 0 - for dirpath, dirnames, filenames in os.walk(root): - # 就地修改 dirnames 以跳过排除目录 - dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS] - - for fname in filenames: - ext = os.path.splitext(fname)[1].lower() - if ext in EXCLUDE_EXTS: - continue - - fpath = os.path.join(dirpath, fname) - relpath = os.path.relpath(fpath, root) - try: - with open(fpath, 'r', encoding='utf-8', errors='ignore') as f: - for lineno, line in enumerate(f, 1): - line_stripped = line.rstrip('\n\r') - if use_regex: - match = compiled.search(line_stripped) - if match: - highlight = line_stripped[:match.start()] + \ - f'>>> {match.group()} <<<' + \ - line_stripped[match.end():] - print(f' {relpath}:{lineno} {highlight}') - count += 1 - else: - if pattern.lower() in line_stripped.lower(): - print(f' {relpath}:{lineno} {line_stripped}') - count += 1 - - if count >= max_results: - print(f'\n ... 已达上限 {max_results} 条,停止') - return - except (PermissionError, OSError): - continue - - if count == 0: - print(' 未找到匹配内容') - else: - print(f'\n 共 {count} 条匹配') - - -def main(): - print('=== 文件内容搜索工具 ===') - print(f'搜索根目录: {DEFAULT_ROOT}') - print(f'排除目录: {EXCLUDE_DIRS}') - print() - print('命令:') - print(' /regex 正则搜索') - print(' /text 纯文本搜索') - print(' /max 设置结果上限(默认50)') - print(' /dir 切换搜索目录') - print(' /help 显示帮助') - print(' /quit 退出') - print() - print('直接输入内容默认使用【纯文本】搜索,需要正则请加 /regex 前缀') - print() - - root = DEFAULT_ROOT - use_regex = False # 修改1:默认纯文本 - max_results = 50 - - while True: - try: - raw = input('find> ').strip() - except (EOFError, KeyboardInterrupt): - print('\n再见') - break - - if not raw: - continue - - if raw == '/quit': - print('再见') - break - - if raw == '/help': - print(' /regex 正则搜索') - print(' /text 纯文本搜索') - print(' /max 设置结果上限') - print(' /dir 切换搜索目录') - print(' /help 显示帮助') - print(' /quit 退出') - print(' 直接输入内容默认纯文本搜索') - continue - - if raw.startswith('/regex '): - pattern = raw[7:].strip() - if pattern: - search(pattern, root, use_regex=True, max_results=max_results) - continue - - if raw.startswith('/text '): - pattern = raw[6:].strip() - if pattern: - search(pattern, root, use_regex=False, max_results=max_results) - continue - - if raw.startswith('/max '): - try: - max_results = int(raw[5:].strip()) - print(f' 结果上限设为 {max_results}') - except ValueError: - print(' 请输入数字') - continue - - if raw.startswith('/dir '): - new_dir = raw[5:].strip() - if os.path.isdir(new_dir): - root = os.path.abspath(new_dir) - print(f' 搜索目录切换为: {root}') - else: - print(f' 目录不存在: {new_dir}') - continue - - # 修改2:直接输入走纯文本搜索 - search(raw, root, use_regex=False, max_results=max_results) - - -if __name__ == '__main__': - main() \ No newline at end of file