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}