code wiki / _hdl_build / nx_opc.nx
nx_opc.nx source
↩ module page · 119 lines · 6079 B
1// nx_opc.nx -- shared sovereign OPC (Open Packaging Conventions) ZIP framer + part reader. Every OOXML format
2// (.docx, .xlsx, .pptx) is an OPC package = a ZIP of XML parts; this is the ONE ZIP implementation they share
3// (DRY keystone). opc_write frames parts as a STORED-method ZIP with real CRC-32s -> a file Word/Excel/unzip
4// opens; opc_read_part materializes a named part's raw bytes (STORED copy, or DEFLATE inflate via nx_deflate,
5// so it reads what Word/Excel actually produce). Reuses nx_crc32 (standard ISO-HDLC = exactly ZIP's CRC) +
6// nx_zip_header (LFH/EOCD parser) + nx_deflate (inflate). license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_crc32.nx"
9import "nx_zip_header.nx"
10import "nx_deflate.nx"
11const K_MAGIC_8388624: i64 = 8388624
12const K_MAGIC_1980: i64 = 1980
13
14func opc_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15func opc_copy(dst: *u8, off: i64, src: *u8, n: i64) -> i64 { var i: i64=0; while i<n { dst[off+i]=src[i]; i=i+1 } return off+n }
16func opc_put_u16(buf: *u8, off: i64, v: i64) -> i64 { buf[off]=(v & 0xff) as u8; buf[off+1]=((v>>8) & 0xff) as u8; return off+2 }
17func opc_put_u32(buf: *u8, off: i64, v: i64) -> i64 { buf[off]=(v & 0xff) as u8; buf[off+1]=((v>>8)&0xff) as u8; buf[off+2]=((v>>16)&0xff) as u8; buf[off+3]=((v>>24)&0xff) as u8; return off+4 }
18func opc_region_eq(buf: *u8, off: i64, len: i64, s: *u8) -> i64 {
19 if opc_strlen(s)!=len { return 0 }
20 var k: i64=0; while k<len { if buf[off+k]!=s[k] { return 0 } k=k+1 } return 1
21}
22
23// frame `count` parts as a STORED-method ZIP at path. names[i]=*u8 (NUL-term), datap[i]=*u8, lens[i]=i64.
24// returns total bytes written (or <0).
25func opc_write(path: *u8, names: *i64, datap: *i64, lens: *i64, count: i64) -> i64 {
26 let out: *u8=sys_mmap(K_MAGIC_8388624)
27 let lfhoff: *i64=sys_mmap(8*256) as *i64
28 let crcs: *i64=sys_mmap(8*256) as *i64
29 var off: i64=0
30 var i: i64=0
31 while i<count {
32 lfhoff[i]=off
33 let nm: *u8=names[i] as *u8; let dp: *u8=datap[i] as *u8; let dl: i64=lens[i]
34 let crc: i64=nx_crc32(dp, dl); crcs[i]=crc
35 let nl: i64=opc_strlen(nm)
36 off=opc_put_u32(out, off, 0x04034b50) // local file header sig
37 off=opc_put_u16(out, off, 20) // version needed
38 off=opc_put_u16(out, off, 0) // flag
39 off=opc_put_u16(out, off, 0) // method = STORED
40 off=opc_put_u16(out, off, 0) // mod time
41 off=opc_put_u16(out, off, 0x21) // mod date = K_MAGIC_1980-01-01 (valid)
42 off=opc_put_u32(out, off, crc)
43 off=opc_put_u32(out, off, dl) // compressed size (== uncompressed for stored)
44 off=opc_put_u32(out, off, dl) // uncompressed size
45 off=opc_put_u16(out, off, nl)
46 off=opc_put_u16(out, off, 0) // extra len
47 off=opc_copy(out, off, nm, nl)
48 off=opc_copy(out, off, dp, dl)
49 i=i+1
50 }
51 let cdoff: i64=off
52 i=0
53 while i<count {
54 let nm: *u8=names[i] as *u8; let dl: i64=lens[i]; let nl: i64=opc_strlen(nm)
55 off=opc_put_u32(out, off, 0x02014b50) // central directory header sig
56 off=opc_put_u16(out, off, 20) // version made by
57 off=opc_put_u16(out, off, 20) // version needed
58 off=opc_put_u16(out, off, 0) // flag
59 off=opc_put_u16(out, off, 0) // method
60 off=opc_put_u16(out, off, 0) // time
61 off=opc_put_u16(out, off, 0x21) // date
62 off=opc_put_u32(out, off, crcs[i])
63 off=opc_put_u32(out, off, dl)
64 off=opc_put_u32(out, off, dl)
65 off=opc_put_u16(out, off, nl)
66 off=opc_put_u16(out, off, 0) // extra
67 off=opc_put_u16(out, off, 0) // comment
68 off=opc_put_u16(out, off, 0) // disk number start
69 off=opc_put_u16(out, off, 0) // internal attrs
70 off=opc_put_u32(out, off, 0) // external attrs
71 off=opc_put_u32(out, off, lfhoff[i]) // rel offset of local header
72 off=opc_copy(out, off, nm, nl)
73 i=i+1
74 }
75 let cdsize: i64=off-cdoff
76 off=opc_put_u32(out, off, 0x06054b50) // EOCD sig
77 off=opc_put_u16(out, off, 0) // disk
78 off=opc_put_u16(out, off, 0) // cd start disk
79 off=opc_put_u16(out, off, count) // entries this disk
80 off=opc_put_u16(out, off, count) // entries total
81 off=opc_put_u32(out, off, cdsize)
82 off=opc_put_u32(out, off, cdoff)
83 off=opc_put_u16(out, off, 0) // comment len
84 let fd: i64=sys_openat_wr(path, 0x1a4)
85 if fd<0 { return 0-1 }
86 sys_write(fd, out, off)
87 sys_close(fd)
88 return off
89}
90
91// extract a named OPC part's RAW bytes (STORED copy or DEFLATE inflate) into out; return length (or <0)
92func opc_read_part(path: *u8, want: *u8, out: *u8, cap: i64) -> i64 {
93 let szp: *i64=sys_mmap(16) as *i64
94 let buf: *u8=sys_read_file(path, szp)
95 if (buf as i64)==0 { return 0-1 }
96 let n: i64=szp[0]
97 let h: *ZipLocalHeader=sys_mmap(256) as *ZipLocalHeader
98 var found: i64=0-1
99 var fmethod: i64=0; var fpayload: i64=0; var fcsize: i64=0
100 var off: i64=0
101 while off+4<=n {
102 if zip_read_u32(buf, off)!=0x04034b50 { off=n } else {
103 if zip_parse_lfh(buf, n, off, h)!=0 { off=n } else {
104 if opc_region_eq(buf, h.name_off, h.name_len, want)==1 {
105 fmethod=h.method; fpayload=off+h.header_len; fcsize=h.compressed_size; found=1; off=n
106 } else { off=off+h.header_len+h.compressed_size }
107 }
108 }
109 }
110 if found<0 { return 0-2 }
111 if fmethod==0 { var i: i64=0; while i<fcsize { if i<cap { out[i]=buf[fpayload+i] } i=i+1 } return fcsize }
112 if fmethod==8 {
113 let r: *NxDeflateResult=nx_deflate_inflate(((buf as i64)+fpayload) as *u8, fcsize, cap)
114 if (r as i64)==0 { return 0-3 }
115 if r.error_code!=NX_DEF_OK { return 0-4 }
116 var i: i64=0; while i<r.output_size { out[i]=r.output_data[i]; i=i+1 } return r.output_size
117 }
118 return 0-5
119}