code wiki / (root) / nx_string_ops_test.nx

nx_string_ops_test.nx source

↩ module page · 139 lines · 5493 B

1// nx_string_ops_test.nx -- smoke for the 16-primitive byte-buffer family. 2 3import "nx_syscalls.nx" 4import "nx_tier.nx" 5import "nx_essentials.nx" 6import "nx_string_ops.nx" 7 8func _fill(buf: *u8, s: *u8, n: nx_int) -> nx_int { 9 var i: nx_int = 0 10 while i < n { 11 buf[i] = s[i] 12 i = i + 1 13 } 14 return 0 15} 16 17func main() -> nx_int { 18 let buf: *u8 = sys_mmap(64) 19 20 // === Family 1: scan + length ==================================== 21 // buf = "hello world" 22 _fill(buf, "hello world" as *u8, 11) 23 // nx_str_len reads until 0; populate buf[11]=0 first. 24 buf[11] = 0 25 if nx_str_len(buf) != 11 { return 1 } 26 27 // index_of 28 if nx_str_index_of(buf, 11, 32) != 5 { return 2 } // space at 5 29 if nx_str_index_of(buf, 11, 108) != 2 { return 3 } // 'l' at 2 30 if nx_str_index_of(buf, 11, 122) != 0 - 1 { return 4 } // 'z' not present 31 if nx_str_index_of(buf, 0, 104) != 0 - 1 { return 5 } // empty 32 // last_index_of 33 if nx_str_last_index_of(buf, 11, 108) != 9 { return 6 } // last 'l' at 9 (world's l) 34 if nx_str_last_index_of(buf, 11, 122) != 0 - 1 { return 7 } 35 36 // === Family 2: equality / prefix / suffix / find ================ 37 let other: *u8 = sys_mmap(32) 38 _fill(other, "hello world" as *u8, 11) 39 if nx_str_equals(buf, 11, other, 11) != 1 { return 10 } 40 _fill(other, "hello mars " as *u8, 11) 41 if nx_str_equals(buf, 11, other, 11) != 0 { return 11 } 42 if nx_str_equals(buf, 11, other, 10) != 0 { return 12 } // diff length 43 44 if nx_str_starts_with(buf, 11, "hello" as *u8, 5) != 1 { return 20 } 45 if nx_str_starts_with(buf, 11, "world" as *u8, 5) != 0 { return 21 } 46 if nx_str_starts_with(buf, 11, "" as *u8, 0) != 1 { return 22 } // empty prefix matches 47 48 if nx_str_ends_with(buf, 11, "world" as *u8, 5) != 1 { return 30 } 49 if nx_str_ends_with(buf, 11, "hello" as *u8, 5) != 0 { return 31 } 50 if nx_str_ends_with(buf, 11, "" as *u8, 0) != 1 { return 32 } 51 52 if nx_str_find(buf, 11, "world" as *u8, 5) != 6 { return 40 } 53 if nx_str_find(buf, 11, "hello" as *u8, 5) != 0 { return 41 } 54 if nx_str_find(buf, 11, "mars" as *u8, 4) != 0 - 1 { return 42 } 55 if nx_str_find(buf, 11, "" as *u8, 0) != 0 { return 43 } // empty needle at 0 56 57 // === Family 3: slice + trim ===================================== 58 let dst: *u8 = sys_mmap(16) 59 if nx_str_slice_copy(buf, 6, 11, dst, 16) != 5 { return 50 } 60 if dst[0] != 119 { return 51 } // 'w' 61 if dst[4] != 100 { return 52 } // 'd' 62 63 if nx_str_slice_copy(buf, 0, 5, dst, 16) != 5 { return 53 } 64 if dst[0] != 104 { return 54 } // 'h' 65 66 // capacity too small 67 if nx_str_slice_copy(buf, 0, 10, dst, 5) != 0 { return 55 } 68 69 // Trim: " hi " 70 _fill(buf, " hi " as *u8, 6) 71 if nx_str_trim_left(buf, 6) != 2 { return 60 } 72 if nx_str_trim_right(buf, 6) != 4 { return 61 } 73 // All whitespace 74 _fill(buf, " " as *u8, 4) 75 if nx_str_trim_left(buf, 4) != 4 { return 62 } 76 if nx_str_trim_right(buf, 4) != 0 { return 63 } 77 78 // === Family 4: parse + format =================================== 79 _fill(buf, "12345" as *u8, 5) 80 if nx_str_parse_int(buf, 5) != 12345 { return 70 } 81 _fill(buf, "-42" as *u8, 3) 82 if nx_str_parse_int(buf, 3) != 0 - 42 { return 71 } 83 _fill(buf, "+7" as *u8, 2) 84 if nx_str_parse_int(buf, 2) != 7 { return 72 } 85 _fill(buf, "0" as *u8, 1) 86 if nx_str_parse_int(buf, 1) != 0 { return 73 } 87 // Empty -> 0 88 if nx_str_parse_int(buf, 0) != 0 { return 74 } 89 90 // format_int 91 let fbuf: *u8 = sys_mmap(32) 92 let nf: nx_int = nx_str_format_int(12345, fbuf, 32) 93 if nf != 5 { return 80 } 94 if fbuf[0] != 49 { return 81 } // '1' 95 if fbuf[4] != 53 { return 82 } // '5' 96 97 let nf_neg: nx_int = nx_str_format_int(0 - 42, fbuf, 32) 98 if nf_neg != 3 { return 83 } 99 if fbuf[0] != 45 { return 84 } // '-' 100 if fbuf[1] != 52 { return 85 } // '4' 101 if fbuf[2] != 50 { return 86 } // '2' 102 103 let nf_zero: nx_int = nx_str_format_int(0, fbuf, 32) 104 if nf_zero != 1 { return 87 } 105 if fbuf[0] != 48 { return 88 } // '0' 106 107 // Capacity too small 108 if nx_str_format_int(12345, fbuf, 4) != 0 { return 89 } 109 110 // === Family 5: classify ========================================= 111 if nx_str_is_empty(buf, 0) != 1 { return 100 } 112 if nx_str_is_empty(buf, 1) != 0 { return 101 } 113 114 _fill(buf, "12345" as *u8, 5) 115 if nx_str_is_all_digits(buf, 5) != 1 { return 110 } 116 _fill(buf, "12a45" as *u8, 5) 117 if nx_str_is_all_digits(buf, 5) != 0 { return 111 } 118 _fill(buf, " \t " as *u8, 5) 119 if nx_str_is_all_whitespace(buf, 5) != 1 { return 120 } 120 _fill(buf, " x " as *u8, 5) 121 if nx_str_is_all_whitespace(buf, 5) != 0 { return 121 } 122 123 // === Family 6: hash ============================================= 124 _fill(buf, "hello" as *u8, 5) 125 let h1: nx_int = nx_str_hash_fnv1a(buf, 5) 126 _fill(buf, "hello" as *u8, 5) 127 let h2: nx_int = nx_str_hash_fnv1a(buf, 5) 128 if h1 != h2 { return 130 } // determinism 129 130 _fill(buf, "world" as *u8, 5) 131 let h3: nx_int = nx_str_hash_fnv1a(buf, 5) 132 if h1 == h3 { return 131 } // different content -> different hash (very likely) 133 134 // Empty buf hash is the FNV offset basis. 135 let h_empty: nx_int = nx_str_hash_fnv1a(buf, 0) 136 if h_empty != nx_fnv1a_offset_basis() { return 132 } 137 138 return 0 139}