code wiki / (root) / nx_url_params.nx

nx_url_params.nx source

↩ module page · 147 lines · 4605 B

1// nx_url_params.nx -- bits-up URL query-string parser for the Nishi 2// test harness arc. Mirrors what nishi-host.js does today in JS: 3// extracting `?v=N` from a URL string for sovereign version pinning. 4// 5// Scope: only what the test driver needs. No URL-encoding, no 6// fragment handling, no multi-value params (those are queued via 7// the full nishi-browser arc). 8 9import "nx_syscalls.nx" 10 11struct NxUrlParam { 12 found: i64, // 1 if param present 13 val_off: i64, // offset of value within URL string 14 val_len: i64 // byte length of value 15} 16 17func _up_strlen(s: *u8) -> i64 { 18 var n: i64 = 0 19 while s[n] != 0 { n = n + 1 } 20 return n 21} 22 23func _up_byte_eq(a: *u8, ao: i64, b: *u8, bo: i64, n: i64) -> i64 { 24 var i: i64 = 0 25 while i < n { 26 if a[ao + i] != b[bo + i] { return 0 } 27 i = i + 1 28 } 29 return 1 30} 31 32// Scan a key-delimiter (one of '=' '&' '#') or end. Returns position 33// of the delimiter, or url_len if none. 34func _up_scan_key_end(url: *u8, url_len: i64, start: i64) -> i64 { 35 var p: i64 = start 36 while p < url_len { 37 let b: i64 = url[p] as i64 38 if b == 61 { return p } 39 if b == 38 { return p } 40 if b == 35 { return p } 41 p = p + 1 42 } 43 return p 44} 45 46// Scan a value-delimiter (one of '&' '#') or end. 47func _up_scan_val_end(url: *u8, url_len: i64, start: i64) -> i64 { 48 var p: i64 = start 49 while p < url_len { 50 let b: i64 = url[p] as i64 51 if b == 38 { return p } 52 if b == 35 { return p } 53 p = p + 1 54 } 55 return p 56} 57 58// Find the start of the query string ('?'). Returns offset just past 59// the '?' or -1 if none. 60func nx_url_query_start(url: *u8, url_len: i64) -> i64 { 61 var i: i64 = 0 62 while i < url_len { 63 if url[i] == 63 { return i + 1 } // '?' 64 if url[i] == 35 { return -1 } // '#' before '?' -> no query 65 i = i + 1 66 } 67 return -1 68} 69 70// Parse a single named param from the URL. Single-exit pattern -- 71// accumulate into out_found / out_val_off / out_val_len cells, then 72// pack into the result struct at function-end. NishiLang's scope 73// tracker loses an outer-scope struct pointer when an early-return 74// appears inside a nested-then-closed `if` block, so we sidestep it. 75func nx_url_param_get(url: *u8, url_len: i64, name: *u8) -> *NxUrlParam { 76 let out_found: *i64 = sys_mmap(8) as *i64 77 let out_val_off: *i64 = sys_mmap(8) as *i64 78 let out_val_len: *i64 = sys_mmap(8) as *i64 79 out_found[0] = 0 80 out_val_off[0] = -1 81 out_val_len[0] = 0 82 83 let qs_start: i64 = nx_url_query_start(url, url_len) 84 let nlen: i64 = _up_strlen(name) 85 var done: i64 = 0 86 if qs_start < 0 { done = 1 } 87 if nlen == 0 { done = 1 } 88 89 var pos: i64 = qs_start 90 while done == 0 { 91 if pos >= url_len { done = 1 } 92 if done == 0 { 93 let kstart: i64 = pos 94 let kend: i64 = _up_scan_key_end(url, url_len, kstart) 95 let klen: i64 = kend - kstart 96 var matched: i64 = 0 97 if klen == nlen { 98 if _up_byte_eq(url, kstart, name, 0, nlen) == 1 { matched = 1 } 99 } 100 var vstart: i64 = kend 101 var vend: i64 = kend 102 if kend < url_len { 103 if url[kend] == 61 { 104 vstart = kend + 1 105 vend = _up_scan_val_end(url, url_len, vstart) 106 } 107 } 108 if matched == 1 { 109 out_found[0] = 1 110 out_val_off[0] = vstart 111 out_val_len[0] = vend - vstart 112 done = 1 113 } 114 if done == 0 { 115 if vend >= url_len { done = 1 } 116 if done == 0 { 117 if url[vend] == 35 { done = 1 } 118 if done == 0 { pos = vend + 1 } 119 } 120 } 121 } 122 } 123 124 let r: *NxUrlParam = sys_mmap(24) as *NxUrlParam 125 r.found = out_found[0] 126 r.val_off = out_val_off[0] 127 r.val_len = out_val_len[0] 128 return r 129} 130 131// Convenience: parse a decimal integer value (positive only). Returns 132// -1 if param missing or non-numeric. 133func nx_url_param_int(url: *u8, url_len: i64, name: *u8) -> i64 { 134 let p: *NxUrlParam = nx_url_param_get(url, url_len, name) 135 if p.found != 1 { return -1 } 136 if p.val_len <= 0 { return -1 } 137 var acc: i64 = 0 138 var i: i64 = 0 139 while i < p.val_len { 140 let b: i64 = url[p.val_off + i] as i64 141 if b < 48 { return -1 } 142 if b > 57 { return -1 } 143 acc = acc * 10 + (b - 48) 144 i = i + 1 145 } 146 return acc 147}