code wiki / (root) / nx_compare_scope_lib.nx

nx_compare_scope_lib.nx source

↩ module page · 86 lines · 3275 B

1// Allocation-free validation for an explicitly selected Compare domain. 2// No I/O or mutation. Byte lengths describe accessible caller-owned buffers. 3const CSCOPE_INVALID: i64 = 0 - 1 4const CSCOPE_LF: i64 = 10 5const CSCOPE_CR: i64 = 13 6const CSCOPE_COMMENT: i64 = 35 7const CSCOPE_DASH: i64 = 45 8const CSCOPE_UNDERSCORE: i64 = 95 9const CSCOPE_ZERO: i64 = 48 10const CSCOPE_NINE: i64 = 57 11const CSCOPE_LOWER_A: i64 = 97 12const CSCOPE_LOWER_Z: i64 = 122 13 14func cscope_name_char(c: i64) -> i64 { 15 if c >= CSCOPE_ZERO { if c <= CSCOPE_NINE { return 1 } } 16 if c >= CSCOPE_LOWER_A { if c <= CSCOPE_LOWER_Z { return 1 } } 17 if c == CSCOPE_DASH { return 1 } 18 if c == CSCOPE_UNDERSCORE { return 1 } 19 return 0 20} 21 22// name is a NUL-terminated argv string, or has at least max_len+1 accessible 23// bytes. The extra byte distinguishes an exact-bound name from a long prefix. 24// max_len is a caller-owned path-capacity bound, not a policy hidden here. 25func cscope_validate_name(name: *u8, max_len: i64) -> i64 { 26 if (name as i64) == 0 { return CSCOPE_INVALID } 27 if max_len <= 0 { return CSCOPE_INVALID } 28 var i: i64 = 0 29 while i < max_len { 30 if name[i] == (0 as u8) { 31 if i == 0 { return CSCOPE_INVALID } 32 return i 33 } 34 if cscope_name_char(name[i] as i64) == 0 { return CSCOPE_INVALID } 35 i = i + 1 36 } 37 if name[i] != (0 as u8) { return CSCOPE_INVALID } 38 return i 39} 40 41// Counts exact selected entries: 0 means unknown, 1 admits membership, 42// >1 means ambiguous duplicate selection, -1 means malformed input. 43// Blank lines and column-zero # comments are ignored. LF, CRLF and an 44// unterminated final domain line are supported. Other whitespace cannot match. 45// Unrelated lines are never executed and do not block the selected domain. 46// Embedded NUL anywhere makes the file ambiguous to downstream C-string 47// consumers, so reject it even in comments. Duplicate unrelated lines are safe. 48func cscope_roster_count(roster: *u8, n: i64, name: *u8, name_len: i64) -> i64 { 49 if (roster as i64) == 0 { return CSCOPE_INVALID } 50 if n < 0 { return CSCOPE_INVALID } 51 if (name as i64) == 0 { return CSCOPE_INVALID } 52 if name_len <= 0 { return CSCOPE_INVALID } 53 var ni: i64 = 0 54 while ni < name_len { 55 if cscope_name_char(name[ni] as i64) == 0 { return CSCOPE_INVALID } 56 ni = ni + 1 57 } 58 var bi: i64 = 0 59 while bi < n { 60 if roster[bi] == (0 as u8) { return CSCOPE_INVALID } 61 bi = bi + 1 62 } 63 var count: i64 = 0 64 var p: i64 = 0 65 while p < n { 66 var e: i64 = p 67 while e < n { if roster[e] == (CSCOPE_LF as u8) { break } e = e + 1 } 68 var end: i64 = e 69 if e < n { if end > p { if roster[end-1] == (CSCOPE_CR as u8) { end = end - 1 } } } 70 if end > p { 71 if roster[p] != (CSCOPE_COMMENT as u8) { 72 var i: i64 = p 73 var equal: i64 = 1 74 if end-p != name_len { equal = 0 } 75 while i < end { 76 if equal == 1 { if roster[i] != name[i-p] { equal = 0 } } 77 i = i + 1 78 } 79 if equal == 1 { count = count + 1 } 80 } 81 } 82 if e == n { p = n } else { p = e + 1 } 83 } 84 return count 85} 86