code wiki / _hdl_build / nx_ad_emitter_registry.nx

nx_ad_emitter_registry.nx source

↩ module page · 130 lines · 6496 B

1// nx_ad_emitter_registry.nx -- LIB: the BUILDER'S LEARNED CATALOG. Every emitter we build (an accent, an 2// animation, a theme, a size) is TAUGHT to the builder by registering it here as DATA; the builder reads the 3// catalog to offer those emitters, and a GROW loop (nx_ad_emitter_grow) generates new ones and registers them 4// -- so the builder keeps growing its own emitters (the emitter-of-emitters loop, in the ad domain). 5// 6// Data-driven (rule 11), append-only + idempotent (rule 10/13). One row per emitter: 7// kind<TAB>id<TAB>label<TAB>template kind in {size, theme, accent, animation}. 8// `template` = the DATA to emit that block (SVG for an accent, a CSS @keyframes+rule for an animation, 9// pipe-joined colors for a theme, WxH for a size). SAFETY (enforced by the gate): a registered template may 10// NEVER contain a <script or src= -> the growing library stays sovereign (0 third-party JS / 0 external fetch) 11// BY CONSTRUCTION. Functions take a `path` so they are hermetically testable; ER_PATH is the live catalog. 12// (TSV registry for inspectability now; seg-store migration = the doctrine follow-on.) license_tier: ORIGINAL 13import "nx_syscalls.nx" 14 15const ER_PATH: *u8 = "knowledge/registry/ad_emitters.tsv" 16const ER_MAXTPL: i64 = 2048 17 18func er_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 19 20// copy the idx-th TAB-field of line[0..linelen) into out (NUL-terminated). returns 1. 21func er_field(line: *u8, linelen: i64, idx: i64, out: *u8) -> i64 { 22 var f: i64 = 0; var i: i64 = 0 23 while f < idx { if i < linelen { if line[i] == (9 as u8) { f = f + 1 } i = i + 1 } else { f = idx; i = linelen } } 24 var o: i64 = 0; var stop: i64 = 0 25 while i < linelen { if stop == 0 { if line[i] == (9 as u8) { stop = 1 } } if stop == 0 { out[o] = line[i]; o = o + 1 } i = i + 1 } 26 out[o] = 0 as u8; return 1 27} 28 29// 1 if a row in `path` has field0==kind AND field1==id. 30func er_present(path: *u8, kind: *u8, id: *u8) -> i64 { 31 let lp: *i64 = sys_mmap(16) as *i64; lp[0] = 0 32 let data: *u8 = sys_read_file(path, lp) 33 if (data as i64) == 0 { return 0 } 34 let n: i64 = lp[0] 35 let f0: *u8 = sys_mmap(64); let f1: *u8 = sys_mmap(128) 36 var i: i64 = 0; var ls: i64 = 0; var found: i64 = 0 37 while i < n { 38 if data[i] == (10 as u8) { 39 let line: *u8 = ((data as i64) + ls) as *u8 40 er_field(line, i - ls, 0, f0); er_field(line, i - ls, 1, f1) 41 if er_streq(f0, kind) == 1 { if er_streq(f1, id) == 1 { found = 1 } } 42 ls = i + 1 43 } 44 i = i + 1 45 } 46 return found 47} 48 49// TEACH one emitter into `path`: register kind/id/label/template if absent. 1 newly-taught, 0 already-known. 50func er_register(path: *u8, kind: *u8, id: *u8, label: *u8, template: *u8) -> i64 { 51 if er_present(path, kind, id) == 1 { return 0 } 52 let line: *u8 = sys_mmap(ER_MAXTPL + 512); var o: i64 = 0 53 var i: i64 = 0; while kind[i] != (0 as u8) { line[o] = kind[i]; o = o + 1; i = i + 1 } line[o] = 9 as u8; o = o + 1 54 i = 0; while id[i] != (0 as u8) { line[o] = id[i]; o = o + 1; i = i + 1 } line[o] = 9 as u8; o = o + 1 55 i = 0; while label[i] != (0 as u8) { line[o] = label[i]; o = o + 1; i = i + 1 } line[o] = 9 as u8; o = o + 1 56 i = 0; while template[i] != (0 as u8) { line[o] = template[i]; o = o + 1; i = i + 1 } line[o] = 10 as u8; o = o + 1 57 let fd: i64 = sys_openat_append(path, 420) 58 if fd < 0 { return 0 - 1 } 59 sys_write(fd, line, o); sys_close(fd) 60 return 1 61} 62 63// count emitters of a kind in `path`. 64func er_count(path: *u8, kind: *u8) -> i64 { 65 let lp: *i64 = sys_mmap(16) as *i64; lp[0] = 0 66 let data: *u8 = sys_read_file(path, lp) 67 if (data as i64) == 0 { return 0 } 68 let n: i64 = lp[0] 69 let f0: *u8 = sys_mmap(64) 70 var i: i64 = 0; var ls: i64 = 0; var c: i64 = 0 71 while i < n { 72 if data[i] == (10 as u8) { er_field(((data as i64) + ls) as *u8, i - ls, 0, f0); if er_streq(f0, kind) == 1 { c = c + 1 } ls = i + 1 } 73 i = i + 1 74 } 75 return c 76} 77 78// fetch the idx-th emitter of a kind in `path` -> out_id/out_label/out_template. 1 if found, 0 if not. 79func er_get(path: *u8, kind: *u8, idx: i64, out_id: *u8, out_label: *u8, out_template: *u8) -> i64 { 80 let lp: *i64 = sys_mmap(16) as *i64; lp[0] = 0 81 let data: *u8 = sys_read_file(path, lp) 82 if (data as i64) == 0 { return 0 } 83 let n: i64 = lp[0] 84 let f0: *u8 = sys_mmap(64) 85 var i: i64 = 0; var ls: i64 = 0; var c: i64 = 0; var got: i64 = 0 86 while i < n { 87 if data[i] == (10 as u8) { 88 let line: *u8 = ((data as i64) + ls) as *u8; let ll: i64 = i - ls 89 er_field(line, ll, 0, f0) 90 if er_streq(f0, kind) == 1 { 91 if c == idx { if got == 0 { er_field(line, ll, 1, out_id); er_field(line, ll, 2, out_label); er_field(line, ll, 3, out_template); got = 1 } } 92 c = c + 1 93 } 94 ls = i + 1 95 } 96 i = i + 1 97 } 98 return got 99} 100 101// find the row with field0==kind AND field1==id -> copy field3 (template) into out_template. 1 found, 0 not. 102func er_lookup(path: *u8, kind: *u8, id: *u8, out_template: *u8) -> i64 { 103 let lp: *i64 = sys_mmap(16) as *i64; lp[0] = 0 104 let data: *u8 = sys_read_file(path, lp) 105 if (data as i64) == 0 { return 0 } 106 let n: i64 = lp[0] 107 let f0: *u8 = sys_mmap(64); let f1: *u8 = sys_mmap(128) 108 var i: i64 = 0; var ls: i64 = 0; var got: i64 = 0 109 while i < n { 110 if data[i] == (10 as u8) { 111 let line: *u8 = ((data as i64) + ls) as *u8; let ll: i64 = i - ls 112 er_field(line, ll, 0, f0); er_field(line, ll, 1, f1) 113 if er_streq(f0, kind) == 1 { if er_streq(f1, id) == 1 { if got == 0 { er_field(line, ll, 3, out_template); got = 1 } } } 114 ls = i + 1 115 } 116 i = i + 1 117 } 118 return got 119} 120 121// SAFETY: 1 if a template is sovereign-safe (no <script and no src= -> 0 third-party JS / 0 external fetch). 122func er_template_safe(template: *u8) -> i64 { 123 var i: i64 = 0 124 while template[i] != (0 as u8) { 125 if template[i] == (60 as u8) { if template[i+1] == (115 as u8) { if template[i+2] == (99 as u8) { if template[i+3] == (114 as u8) { return 0 } } } } // "<scr" 126 if template[i] == (115 as u8) { if template[i+1] == (114 as u8) { if template[i+2] == (99 as u8) { if template[i+3] == (61 as u8) { return 0 } } } } // "src=" 127 i = i + 1 128 } 129 return 1 130}