code wiki / _hdl_build / nx_galx_tags.nx

nx_galx_tags.nx source

↩ module page · 321 lines · 14969 B

1// nx_galx_tags.nx -- sovereign tag store for the gallery (media-manager migration: tags were missing). 2// Tags live in an append-only log knowledge/status/galx_tags.log, one op per line: 3// <id>\t<tag>\t<v>\n (v=1 add, v=0 remove) -- LAST-WINS per (id,tag), mirrors galx_hidden.log. 4// Reading replays the log to the CURRENT tag set. Append-only = rule-13 additive (history preserved). no main. 5// Tags are assumed pre-sanitised by the POST handler (alnum + space/dash, no quotes/tabs/newlines), so the 6// JSON emitters don't escape. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8const K_MAGIC_16384: i64 = 16384 9const K_MAGIC_65536: i64 = 65536 10const K_MAGIC_4096: i64 = 4096 11const K_MAGIC_1048576: i64 = 1048576 12const K_MAGIC_2097152: i64 = 2097152 13 14// parse the unsigned int in buf[s..e); 0 if none. 15func tg_pint(buf: *u8, s: i64, e: i64) -> i64 { 16 var v: i64 = 0; var p: i64 = s 17 while p < e { let c: i64 = buf[p] as i64; if c < 48 { p = e } else { if c > 57 { p = e } else { v = v*10+(c-48); p = p+1 } } } 18 return v 19} 20// byte-range equality. 21func tg_eqn(a: *u8, ao: i64, alen: i64, b: *u8, bo: i64, blen: i64) -> i64 { 22 if alen != blen { return 0 } 23 var i: i64 = 0 24 while i < alen { if a[ao+i] != b[bo+i] { return 0 } i = i + 1 } 25 return 1 26} 27func tg_emit_u(out: *u8, o: i64, v: i64) -> i64 { 28 if v == 0 { out[o] = 48 as u8; return o + 1 } 29 let t: *u8 = sys_mmap(28); var m: i64 = v; var k: i64 = 0 30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 31 var j: i64 = k; var oo: i64 = o 32 while j > 0 { j = j - 1; out[oo] = t[j]; oo = oo + 1 } 33 return oo 34} 35// locate the two tabs of a log line [ls..le); writes them to t1p/t2p (-1 if absent). returns 1 if both found. 36func tg_tabs(log: *u8, ls: i64, le: i64, t1p: *i64, t2p: *i64) -> i64 { 37 var t1: i64 = 0 - 1; var t2: i64 = 0 - 1; var p: i64 = ls 38 while p < le { if log[p]==(9 as u8) { if t1 < 0 { t1 = p } else { if t2 < 0 { t2 = p } } } p = p + 1 } 39 t1p[0] = t1; t2p[0] = t2 40 if t1 >= 0 { if t2 >= 0 { return 1 } } 41 return 0 42} 43// emit JSON ["tag",...] of the CURRENT tags for `id` (last-wins, v=1). returns bytes written. 44func tg_tags_for_id(log: *u8, sz: i64, id: i64, out: *u8) -> i64 { 45 let tbuf: *u8 = sys_mmap(K_MAGIC_16384) 46 let toff: *i64 = sys_mmap(8*512) as *i64 47 let tlen: *i64 = sys_mmap(8*512) as *i64 48 let tvv: *i64 = sys_mmap(8*512) as *i64 49 let t1p: *i64 = sys_mmap(16) as *i64 50 let t2p: *i64 = sys_mmap(16) as *i64 51 var nt: i64 = 0; var tb: i64 = 0 52 var i: i64 = 0; var ls: i64 = 0 53 while i <= sz { 54 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 55 if nl == 1 { 56 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 57 let t1: i64 = t1p[0]; let t2: i64 = t2p[0] 58 let lid: i64 = tg_pint(log, ls, t1) 59 if lid == id { 60 let ts: i64 = t1 + 1; let tl: i64 = t2 - ts 61 let v: i64 = tg_pint(log, t2 + 1, i) 62 var found: i64 = 0 - 1; var t: i64 = 0 63 while t < nt { if tg_eqn(tbuf, toff[t], tlen[t], log, ts, tl) == 1 { found = t; t = nt } else { t = t + 1 } } 64 if found >= 0 { tvv[found] = v } else { if nt < 512 { if tb + tl < K_MAGIC_16384 { 65 toff[nt] = tb; var k: i64 = 0; while k < tl { tbuf[tb] = log[ts+k]; tb = tb + 1; k = k + 1 } 66 tlen[nt] = tl; tvv[nt] = v; nt = nt + 1 67 } } } 68 } 69 } } 70 ls = i + 1 71 } 72 i = i + 1 73 } 74 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 75 var first: i64 = 1; var t: i64 = 0 76 while t < nt { 77 if tvv[t] == 1 { 78 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 79 out[o] = 34 as u8; o = o + 1 80 var k: i64 = 0; while k < tlen[t] { out[o] = tbuf[toff[t]+k]; o = o + 1; k = k + 1 } 81 out[o] = 34 as u8; o = o + 1 82 } 83 t = t + 1 84 } 85 out[o] = 93 as u8; o = o + 1 86 return o 87} 88// emit JSON [id,...] of videos CURRENTLY tagged (tag,taglen) (last-wins, v=1, ascending by first-seen). 89func tg_ids_for_tag(log: *u8, sz: i64, tag: *u8, taglen: i64, out: *u8) -> i64 { 90 let ids: *i64 = sys_mmap(8*K_MAGIC_65536) as *i64 91 let vvs: *i64 = sys_mmap(8*K_MAGIC_65536) as *i64 92 let t1p: *i64 = sys_mmap(16) as *i64 93 let t2p: *i64 = sys_mmap(16) as *i64 94 var nid: i64 = 0 95 var i: i64 = 0; var ls: i64 = 0 96 while i <= sz { 97 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 98 if nl == 1 { 99 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 100 let t1: i64 = t1p[0]; let t2: i64 = t2p[0] 101 let ts: i64 = t1 + 1; let tl: i64 = t2 - ts 102 if tg_eqn(log, ts, tl, tag, 0, taglen) == 1 { 103 let lid: i64 = tg_pint(log, ls, t1) 104 let v: i64 = tg_pint(log, t2 + 1, i) 105 var found: i64 = 0 - 1; var t: i64 = 0 106 while t < nid { if ids[t] == lid { found = t; t = nid } else { t = t + 1 } } 107 if found >= 0 { vvs[found] = v } else { if nid < K_MAGIC_65536 { ids[nid] = lid; vvs[nid] = v; nid = nid + 1 } } 108 } 109 } } 110 ls = i + 1 111 } 112 i = i + 1 113 } 114 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 115 var first: i64 = 1; var t: i64 = 0 116 while t < nid { 117 if vvs[t] == 1 { 118 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 119 o = tg_emit_u(out, o, ids[t]) 120 } 121 t = t + 1 122 } 123 out[o] = 93 as u8; o = o + 1 124 return o 125} 126// emit JSON ["tag",...] of the CURRENTLY-applied distinct tags (first-seen order; a tag removed from every 127// video is excluded via the tg_ids_for_tag non-empty check). The all-tags picker; clicking filters via /api/tagged. 128func tg_all_tags(log: *u8, sz: i64, out: *u8) -> i64 { 129 let tbuf: *u8 = sys_mmap(K_MAGIC_65536) 130 let toff: *i64 = sys_mmap(8*K_MAGIC_4096) as *i64 131 let tlen: *i64 = sys_mmap(8*K_MAGIC_4096) as *i64 132 let t1p: *i64 = sys_mmap(16) as *i64 133 let t2p: *i64 = sys_mmap(16) as *i64 134 var nt: i64 = 0; var tb: i64 = 0 135 var i: i64 = 0; var ls: i64 = 0 136 while i <= sz { 137 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 138 if nl == 1 { 139 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 140 let ts: i64 = t1p[0] + 1; let tl: i64 = t2p[0] - ts 141 var found: i64 = 0 - 1; var t: i64 = 0 142 while t < nt { if tg_eqn(tbuf, toff[t], tlen[t], log, ts, tl) == 1 { found = t; t = nt } else { t = t + 1 } } 143 if found < 0 { if nt < K_MAGIC_4096 { if tb + tl < K_MAGIC_65536 { 144 toff[nt] = tb; var k: i64 = 0; while k < tl { tbuf[tb] = log[ts+k]; tb = tb + 1; k = k + 1 } 145 tlen[nt] = tl; nt = nt + 1 146 } } } 147 } } 148 ls = i + 1 149 } 150 i = i + 1 151 } 152 let tmp: *u8 = sys_mmap(K_MAGIC_1048576) 153 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 154 var first: i64 = 1; var tt: i64 = 0 155 while tt < nt { 156 let il: i64 = tg_ids_for_tag(log, sz, ((tbuf as i64)+toff[tt]) as *u8, tlen[tt], tmp) 157 if il > 2 { 158 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 159 out[o] = 34 as u8; o = o + 1 160 var k: i64 = 0; while k < tlen[tt] { out[o] = tbuf[toff[tt]+k]; o = o + 1; k = k + 1 } 161 out[o] = 34 as u8; o = o + 1 162 } 163 tt = tt + 1 164 } 165 out[o] = 93 as u8; o = o + 1 166 return o 167} 168// format a tag op line "<id>\t<tag>\t<v>\n" into buf; returns length. 169func tg_op_line(buf: *u8, id: i64, tag: *u8, taglen: i64, v: i64) -> i64 { 170 var o: i64 = tg_emit_u(buf, 0, id) 171 buf[o] = 9 as u8; o = o + 1 172 var k: i64 = 0; while k < taglen { buf[o] = tag[k]; o = o + 1; k = k + 1 } 173 buf[o] = 9 as u8; o = o + 1 174 if v == 0 { buf[o] = 48 as u8 } else { buf[o] = 49 as u8 } o = o + 1 175 buf[o] = 10 as u8; o = o + 1 176 return o 177} 178// ---- STRING-KEYED variants (the id is an arbitrary string: an int video lineno OR a 69-char image cid) ---- 179// These subsume the integer ones (an int id "5" is a valid string id), so videos AND images can share ONE 180// store. Added alongside (non-breaking) so the proven int path + the live gallery are untouched until migrated. 181func tg_op_line_s(buf: *u8, idp: *u8, idlen: i64, tag: *u8, taglen: i64, v: i64) -> i64 { 182 var o: i64 = 0 183 var c: i64 = 0; while c < idlen { buf[o] = idp[c]; o = o + 1; c = c + 1 } 184 buf[o] = 9 as u8; o = o + 1 185 var k: i64 = 0; while k < taglen { buf[o] = tag[k]; o = o + 1; k = k + 1 } 186 buf[o] = 9 as u8; o = o + 1 187 if v == 0 { buf[o] = 48 as u8 } else { buf[o] = 49 as u8 } o = o + 1 188 buf[o] = 10 as u8; o = o + 1 189 return o 190} 191// emit JSON ["tag",...] of the CURRENT tags for the string id (idp,idlen) (last-wins, v=1). 192func tg_tags_for_id_s(log: *u8, sz: i64, idp: *u8, idlen: i64, out: *u8) -> i64 { 193 let tbuf: *u8 = sys_mmap(K_MAGIC_16384) 194 let toff: *i64 = sys_mmap(8*512) as *i64 195 let tlen: *i64 = sys_mmap(8*512) as *i64 196 let tvv: *i64 = sys_mmap(8*512) as *i64 197 let t1p: *i64 = sys_mmap(16) as *i64 198 let t2p: *i64 = sys_mmap(16) as *i64 199 var nt: i64 = 0; var tb: i64 = 0 200 var i: i64 = 0; var ls: i64 = 0 201 while i <= sz { 202 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 203 if nl == 1 { 204 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 205 let t1: i64 = t1p[0]; let t2: i64 = t2p[0] 206 if tg_eqn(log, ls, t1 - ls, idp, 0, idlen) == 1 { 207 let ts: i64 = t1 + 1; let tl: i64 = t2 - ts 208 let v: i64 = tg_pint(log, t2 + 1, i) 209 var found: i64 = 0 - 1; var t: i64 = 0 210 while t < nt { if tg_eqn(tbuf, toff[t], tlen[t], log, ts, tl) == 1 { found = t; t = nt } else { t = t + 1 } } 211 if found >= 0 { tvv[found] = v } else { if nt < 512 { if tb + tl < K_MAGIC_16384 { 212 toff[nt] = tb; var k: i64 = 0; while k < tl { tbuf[tb] = log[ts+k]; tb = tb + 1; k = k + 1 } 213 tlen[nt] = tl; tvv[nt] = v; nt = nt + 1 214 } } } 215 } 216 } } 217 ls = i + 1 218 } 219 i = i + 1 220 } 221 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 222 var first: i64 = 1; var t: i64 = 0 223 while t < nt { 224 if tvv[t] == 1 { 225 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 226 out[o] = 34 as u8; o = o + 1 227 var k: i64 = 0; while k < tlen[t] { out[o] = tbuf[toff[t]+k]; o = o + 1; k = k + 1 } 228 out[o] = 34 as u8; o = o + 1 229 } 230 t = t + 1 231 } 232 out[o] = 93 as u8; o = o + 1 233 return o 234} 235// emit JSON ["id",...] (QUOTED string ids) of items CURRENTLY carrying the tag (last-wins, dedup by id string). 236func tg_ids_for_tag_s(log: *u8, sz: i64, tag: *u8, taglen: i64, out: *u8) -> i64 { 237 let ibuf: *u8 = sys_mmap(K_MAGIC_2097152) 238 let ioff: *i64 = sys_mmap(8*K_MAGIC_65536) as *i64 239 let ilen: *i64 = sys_mmap(8*K_MAGIC_65536) as *i64 240 let ivv: *i64 = sys_mmap(8*K_MAGIC_65536) as *i64 241 let t1p: *i64 = sys_mmap(16) as *i64 242 let t2p: *i64 = sys_mmap(16) as *i64 243 var nid: i64 = 0; var ib: i64 = 0 244 var i: i64 = 0; var ls: i64 = 0 245 while i <= sz { 246 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 247 if nl == 1 { 248 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 249 let t1: i64 = t1p[0]; let t2: i64 = t2p[0] 250 let ts: i64 = t1 + 1; let tl: i64 = t2 - ts 251 if tg_eqn(log, ts, tl, tag, 0, taglen) == 1 { 252 let idl: i64 = t1 - ls 253 let v: i64 = tg_pint(log, t2 + 1, i) 254 var found: i64 = 0 - 1; var t: i64 = 0 255 while t < nid { if tg_eqn(ibuf, ioff[t], ilen[t], log, ls, idl) == 1 { found = t; t = nid } else { t = t + 1 } } 256 if found >= 0 { ivv[found] = v } else { if nid < K_MAGIC_65536 { if ib + idl < K_MAGIC_2097152 { 257 ioff[nid] = ib; var k: i64 = 0; while k < idl { ibuf[ib] = log[ls+k]; ib = ib + 1; k = k + 1 } 258 ilen[nid] = idl; ivv[nid] = v; nid = nid + 1 259 } } } 260 } 261 } } 262 ls = i + 1 263 } 264 i = i + 1 265 } 266 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 267 var first: i64 = 1; var t: i64 = 0 268 while t < nid { 269 if ivv[t] == 1 { 270 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 271 out[o] = 34 as u8; o = o + 1 272 var k: i64 = 0; while k < ilen[t] { out[o] = ibuf[ioff[t]+k]; o = o + 1; k = k + 1 } 273 out[o] = 34 as u8; o = o + 1 274 } 275 t = t + 1 276 } 277 out[o] = 93 as u8; o = o + 1 278 return o 279} 280// CURRENT distinct tags via the STRING-keyed current-check (correct for image cids: the int tg_all_tags 281// collapses every cid to id 0, mishandling a multi-cid same-tag removal). /api/alltags uses this. 282func tg_all_tags_s(log: *u8, sz: i64, out: *u8) -> i64 { 283 let tbuf: *u8 = sys_mmap(K_MAGIC_65536) 284 let toff: *i64 = sys_mmap(8*K_MAGIC_4096) as *i64 285 let tlen: *i64 = sys_mmap(8*K_MAGIC_4096) as *i64 286 let t1p: *i64 = sys_mmap(16) as *i64 287 let t2p: *i64 = sys_mmap(16) as *i64 288 var nt: i64 = 0; var tb: i64 = 0 289 var i: i64 = 0; var ls: i64 = 0 290 while i <= sz { 291 var nl: i64 = 0; if i == sz { nl = 1 } else { if log[i]==(10 as u8) { nl = 1 } } 292 if nl == 1 { 293 if i > ls { if tg_tabs(log, ls, i, t1p, t2p) == 1 { 294 let ts: i64 = t1p[0] + 1; let tl: i64 = t2p[0] - ts 295 var found: i64 = 0 - 1; var t: i64 = 0 296 while t < nt { if tg_eqn(tbuf, toff[t], tlen[t], log, ts, tl) == 1 { found = t; t = nt } else { t = t + 1 } } 297 if found < 0 { if nt < K_MAGIC_4096 { if tb + tl < K_MAGIC_65536 { 298 toff[nt] = tb; var k: i64 = 0; while k < tl { tbuf[tb] = log[ts+k]; tb = tb + 1; k = k + 1 } 299 tlen[nt] = tl; nt = nt + 1 300 } } } 301 } } 302 ls = i + 1 303 } 304 i = i + 1 305 } 306 let tmp: *u8 = sys_mmap(K_MAGIC_1048576) 307 var o: i64 = 0; out[o] = 91 as u8; o = o + 1 308 var first: i64 = 1; var tt: i64 = 0 309 while tt < nt { 310 let il: i64 = tg_ids_for_tag_s(log, sz, ((tbuf as i64)+toff[tt]) as *u8, tlen[tt], tmp) 311 if il > 2 { 312 if first == 0 { out[o] = 44 as u8; o = o + 1 } first = 0 313 out[o] = 34 as u8; o = o + 1 314 var k: i64 = 0; while k < tlen[tt] { out[o] = tbuf[toff[tt]+k]; o = o + 1; k = k + 1 } 315 out[o] = 34 as u8; o = o + 1 316 } 317 tt = tt + 1 318 } 319 out[o] = 93 as u8; o = o + 1 320 return o 321}