code wiki / (root) / nx_find.nx

nx_find.nx source

↩ module page · 220 lines · 6549 B

1// nx_find.nx -- S5 stone of NISHI_SHELL_REPLACEMENT_ROADMAP.md. 2// 3// Canonical: this is the substrate-wide canonical file-tree walk + 4// filter primitive per [[feedback-bits-up-shell-replace-linux- 5// brother-tools]]. Composes nx_dir + nx_string_ops + nx_grep. 6// Replaces the bash `find` / `ls | xargs grep` patterns scattered 7// across substrate audit scripts. S6 will add recursive walks + 8// gitignore-aware exclusions (fd 2017 style); this S5 first stone 9// ships the per-level filter primitives that the recursive walker 10// composes. 11// 12// API (all pure-function over caller-provided NxDirRow arrays; 13// no syscalls in the LOGIC layer; caller composes nx_dir_list to 14// populate rows then runs filters): 15// 16// nx_find_filter_suffix(rows, n_rows, suffix, n_suffix, out_flags) -> i64 17// For each row, sets out_flags[i] = 1 iff name ends with suffix. 18// Returns count of kept rows. 19// 20// nx_find_filter_prefix(rows, n_rows, prefix, n_prefix, out_flags) -> i64 21// For each row, sets out_flags[i] = 1 iff name starts with prefix. 22// Returns count of kept rows. 23// 24// nx_find_filter_regular_files(rows, n_rows, out_flags) -> i64 25// For each row, sets out_flags[i] = 1 iff dtype == NX_DT_REG. 26// Returns count of kept rows. 27// 28// nx_find_filter_skip_dotlike(rows, n_rows, out_flags) -> i64 29// For each row, sets out_flags[i] = 1 iff NOT is_dotlike. 30// 31// nx_find_intersect(a, b, n, out_flags) -> i64 32// out_flags[i] = a[i] AND b[i]. Composes multiple filters. 33// 34// nx_find_count_kept(flags, n) -> i64 35// Sum of 1s in flags array. 36// 37// nx_find_nth_kept_index(flags, n, k) -> i64 38// Returns the index of the k-th kept row (0-based), or -1 if 39// k exceeds count. Lets the caller iterate kept rows without 40// allocating a separate index list. 41// 42// Composes: 43// [[NISHI_SHELL_REPLACEMENT_ROADMAP]] S5 (this is the stone) 44// nx_dir.nx (NxDirRow + NX_DT_* constants; SHIPPED) 45// nx_string_ops.nx (nx_str_starts_with + nx_str_ends_with; SHIPPED) 46// [[feedback-bits-up-shell-replace-linux-brother-tools]] (cardinal) 47// [[feedback-no-tool-proliferation-bit-level]] (one canonical for 48// file-tree filtering; future recursive + gitignore composers 49// all compose this) 50 51// nx_safety_envelope: 52// intended_use: "canonical file-tree filter primitive; 53// per-row predicates (suffix / prefix / 54// regular / not-dotlike) + intersection; 55// S6+ recursive walker composes this" 56// sil_target: SIL2 57// evidence: [kat_suffix_filter, 58// kat_prefix_filter, 59// kat_regular_file_filter, 60// kat_dotlike_skip, 61// kat_intersect_compose, 62// kat_count_kept, 63// kat_nth_kept_index] 64// hazard_register: [bug-tape-flags-array-overrun, 65// bug-tape-empty-suffix-matches-all, 66// bug-tape-intersect-mismatched-lengths] 67// verdict: NOT_YET_EVALUATED 68 69import "nx_syscalls.nx" 70import "nx_string_ops.nx" 71import "nx_dir.nx" 72 73// ===== Per-row suffix filter ====================================== 74 75func nx_find_filter_suffix( 76 rows: *NxDirRow, 77 n_rows: i64, 78 suffix: *u8, 79 n_suffix: i64, 80 out_flags: *i64 81) -> i64 { 82 var i: i64 = 0 83 var kept: i64 = 0 84 while i < n_rows { 85 let row: *NxDirRow = nx_dir_row_at(rows, i) 86 out_flags[i] = 0 87 if n_suffix > 0 { 88 if nx_str_ends_with(row.name_ptr, row.name_len, suffix, n_suffix) == 1 { 89 out_flags[i] = 1 90 kept = kept + 1 91 } 92 } 93 i = i + 1 94 } 95 return kept 96} 97 98// ===== Per-row prefix filter ====================================== 99 100func nx_find_filter_prefix( 101 rows: *NxDirRow, 102 n_rows: i64, 103 prefix: *u8, 104 n_prefix: i64, 105 out_flags: *i64 106) -> i64 { 107 var i: i64 = 0 108 var kept: i64 = 0 109 while i < n_rows { 110 let row: *NxDirRow = nx_dir_row_at(rows, i) 111 out_flags[i] = 0 112 if n_prefix > 0 { 113 if nx_str_starts_with(row.name_ptr, row.name_len, prefix, n_prefix) == 1 { 114 out_flags[i] = 1 115 kept = kept + 1 116 } 117 } 118 i = i + 1 119 } 120 return kept 121} 122 123// ===== Regular-file filter ======================================== 124 125func nx_find_filter_regular_files( 126 rows: *NxDirRow, 127 n_rows: i64, 128 out_flags: *i64 129) -> i64 { 130 var i: i64 = 0 131 var kept: i64 = 0 132 while i < n_rows { 133 let row: *NxDirRow = nx_dir_row_at(rows, i) 134 out_flags[i] = 0 135 if row.dtype == NX_DT_REG { 136 out_flags[i] = 1 137 kept = kept + 1 138 } 139 i = i + 1 140 } 141 return kept 142} 143 144// ===== Skip-dotlike filter ======================================== 145 146func nx_find_filter_skip_dotlike( 147 rows: *NxDirRow, 148 n_rows: i64, 149 out_flags: *i64 150) -> i64 { 151 var i: i64 = 0 152 var kept: i64 = 0 153 while i < n_rows { 154 let row: *NxDirRow = nx_dir_row_at(rows, i) 155 out_flags[i] = 0 156 if row.is_dotlike != 1 { 157 out_flags[i] = 1 158 kept = kept + 1 159 } 160 i = i + 1 161 } 162 return kept 163} 164 165// ===== Intersection of flag arrays ================================ 166// 167// out_flags[i] = a[i] AND b[i]. Caller composes multiple filters 168// without allocating a temporary keep-list. 169 170func nx_find_intersect( 171 a: *i64, 172 b: *i64, 173 n: i64, 174 out_flags: *i64 175) -> i64 { 176 var i: i64 = 0 177 var kept: i64 = 0 178 while i < n { 179 if a[i] == 1 { 180 if b[i] == 1 { 181 out_flags[i] = 1 182 kept = kept + 1 183 } else { 184 out_flags[i] = 0 185 } 186 } else { 187 out_flags[i] = 0 188 } 189 i = i + 1 190 } 191 return kept 192} 193 194// ===== Count + iterate kept rows ================================== 195 196func nx_find_count_kept(flags: *i64, n: i64) -> i64 { 197 var i: i64 = 0 198 var kept: i64 = 0 199 while i < n { 200 if flags[i] == 1 { kept = kept + 1 } 201 i = i + 1 202 } 203 return kept 204} 205 206// Returns the index of the k-th (0-based) kept row, or -1 if k 207// exceeds the kept count. 208func nx_find_nth_kept_index(flags: *i64, n: i64, k: i64) -> i64 { 209 if k < 0 { return -1 } 210 var i: i64 = 0 211 var seen: i64 = 0 212 while i < n { 213 if flags[i] == 1 { 214 if seen == k { return i } 215 seen = seen + 1 216 } 217 i = i + 1 218 } 219 return -1 220}