code wiki / _hdl_build / nx_json_lib.nx

nx_json_lib.nx source

↩ module page · 75 lines · 3443 B

1// nx_json_lib.nx -- minimal SOVEREIGN JSON field reader (no jq, no shell, no 3rd-party). Built for 2// the work-journal: extract "transcript_path" from a Claude-Code hook's stdin JSON and scan tool_use 3// blocks out of the session transcript .jsonl. NOT a full JSON parser -- it linearly finds 4// "key":"value" string fields and literal anchors, which is exactly what capture needs and is robust 5// to the harness's compact (space-free) emission. De-escapes backslash sequences and neutralizes any 6// TAB/NL/CR so an extracted value can never tear the TSV work-journal line. 7// Sovereign: imports nx_syscalls only. license_tier: ORIGINAL 8import "nx_syscalls.nx" 9 10func jx_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 11 12// first index of NUL-term `pat` in buf[start..n), or -1. 13func jx_find(buf: *u8, n: i64, start: i64, pat: *u8) -> i64 { 14 let pl: i64 = jx_len(pat) 15 if pl == 0 { return 0 - 1 } 16 var i: i64 = start 17 if i < 0 { i = 0 } 18 while i + pl <= n { 19 var j: i64 = 0 20 var ok: i64 = 1 21 while j < pl { if buf[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } 22 if ok == 1 { return i } 23 i = i + 1 24 } 25 return 0 - 1 26} 27 28// copy a JSON string value starting at vstart (the byte right after the opening quote) into out, 29// de-escaping backslashes and forcing TAB/NL/CR -> space (TSV-safe), bounded by outcap-1, NUL-term. 30// returns index just past the closing quote, or -1 if unterminated within buf. 31func jx_copy_str(buf: *u8, n: i64, vstart: i64, out: *u8, outcap: i64) -> i64 { 32 var i: i64 = vstart 33 var o: i64 = 0 34 while i < n { 35 let c: i64 = buf[i] as i64 36 if c == 92 { // backslash escape 37 if i + 1 < n { 38 var e: i64 = buf[i + 1] as i64 39 if e == 116 { e = 32 } // \t -> space 40 if e == 110 { e = 32 } // \n -> space 41 if e == 114 { e = 32 } // \r -> space 42 if o < outcap - 1 { out[o] = e as u8; o = o + 1 } 43 i = i + 2 44 } else { i = i + 1 } 45 } else { 46 if c == 34 { out[o] = 0 as u8; return i + 1 } // closing quote 47 var cc: i64 = c 48 if cc == 9 { cc = 32 } 49 if cc == 10 { cc = 32 } 50 if cc == 13 { cc = 32 } 51 if o < outcap - 1 { out[o] = cc as u8; o = o + 1 } 52 i = i + 1 53 } 54 } 55 out[o] = 0 as u8 56 return 0 - 1 57} 58 59// find `"key":"` at/after `start`, copy its string value into out. returns index past the value's 60// closing quote, or -1 if not found. `key` is the bare name (no quotes); harness JSON is compact. 61func jx_get_str(buf: *u8, n: i64, start: i64, key: *u8, out: *u8, outcap: i64) -> i64 { 62 let kl: i64 = jx_len(key) 63 let needle: *u8 = sys_mmap(kl + 8) 64 var o: i64 = 0 65 needle[o] = 34 as u8; o = o + 1 // " 66 var i: i64 = 0 67 while key[i] != (0 as u8) { needle[o] = key[i]; o = o + 1; i = i + 1 } 68 needle[o] = 34 as u8; o = o + 1 // " 69 needle[o] = 58 as u8; o = o + 1 // : 70 needle[o] = 34 as u8; o = o + 1 // " 71 needle[o] = 0 as u8 72 let at: i64 = jx_find(buf, n, start, needle) 73 if at < 0 { return 0 - 1 } 74 return jx_copy_str(buf, n, at + o, out, outcap) // o = needle length; value starts after it 75}