code wiki / _hdl_build / nx_html_table.nx

nx_html_table.nx source

↩ module page · 109 lines · 4590 B

1// nx_html_table.nx -- SOVEREIGN HTML TABLE extractor: the reusable "access it properly" rung for ingesting 2// tabular data from any science body's HTML (CIAAW, NIST, BIPM, ...) WITHOUT grep -- it parses the table 3// STRUCTURE (rows x cells) and decodes entities through the proven nx_html_decode_entities. Composes the 4// existing sovereign HTML stack; hardware-rung-up (fetch[TLS]->tokenize->THIS->typed-extract->seg_store). 5// 6// API (reusable): 7// ht_find_open(html, n, pos, tag) -> index of next "<tag" (case-insens, tag-boundary checked), -1 8// ht_next_row(html, n, pos, rs_out, re_out) -> content [rs,re) of the next <tr>; returns next-pos or -1 9// ht_cell(html, rs, re, col, out, cap) -> extract the col-th <td> cell as clean text (tags stripped, 10// entities decoded). 1 found / 0 absent. 11// No JS, no 3rd-party parser. license_tier: ORIGINAL 12import "nx_syscalls.nx" 13import "nx_html_entities.nx" 14 15func ht_lc(b: u8) -> u8 { if b >= (65 as u8) { if b <= (90 as u8) { return (b + 32) as u8 } } return b } 16 17// does html[p..] begin with "<tag" (case-insensitive) followed by a tag boundary? 18func ht_is_open(html: *u8, n: i64, p: i64, tag: *u8) -> i64 { 19 if p >= n { return 0 } 20 if html[p] != (60 as u8) { return 0 } // '<' 21 var i: i64 = 0 22 while tag[i] != (0 as u8) { 23 if p + 1 + i >= n { return 0 } 24 if ht_lc(html[p + 1 + i]) != ht_lc(tag[i]) { return 0 } 25 i = i + 1 26 } 27 if p + 1 + i >= n { return 0 } 28 let c: u8 = html[p + 1 + i] 29 if c == (32 as u8) { return 1 } 30 if c == (62 as u8) { return 1 } // '>' 31 if c == (9 as u8) { return 1 } // tab 32 if c == (10 as u8) { return 1 } // newline 33 if c == (13 as u8) { return 1 } 34 if c == (47 as u8) { return 1 } // '/' 35 return 0 36} 37func ht_find_open(html: *u8, n: i64, pos: i64, tag: *u8) -> i64 { 38 var p: i64 = pos 39 while p < n { if ht_is_open(html, n, p, tag) == 1 { return p } p = p + 1 } 40 return 0 - 1 41} 42// find "</tag>" at/after pos (case-insensitive); return its start index or -1. 43func ht_find_close(html: *u8, n: i64, pos: i64, tag: *u8) -> i64 { 44 var p: i64 = pos 45 while p + 1 < n { 46 if html[p] == (60 as u8) { if html[p+1] == (47 as u8) { // "</" 47 var i: i64 = 0; var ok: i64 = 1 48 while tag[i] != (0 as u8) { 49 if p + 2 + i >= n { ok = 0; break } 50 if ht_lc(html[p+2+i]) != ht_lc(tag[i]) { ok = 0; break } 51 i = i + 1 52 } 53 if ok == 1 { return p } 54 } } 55 p = p + 1 56 } 57 return 0 - 1 58} 59// index just after the next '>' from pos. 60func ht_after_gt(html: *u8, n: i64, pos: i64) -> i64 { 61 var p: i64 = pos 62 while p < n { if html[p] == (62 as u8) { return p + 1 } p = p + 1 } 63 return n 64} 65 66// clean text of html[a..b): strip tags, decode entities, into out. returns length. 67func ht_text(html: *u8, a: i64, b: i64, out: *u8, cap: i64) -> i64 { 68 let tmp: *u8 = sys_mmap(cap + 16) 69 var k: i64 = 0; var p: i64 = a 70 while p < b { 71 if html[p] == (60 as u8) { // '<' -> skip the whole tag 72 while p < b { if html[p] == (62 as u8) { p = p + 1; break } p = p + 1 } 73 } else { if k < cap - 1 { tmp[k] = html[p]; k = k + 1 } p = p + 1 } 74 } 75 tmp[k] = 0 as u8 76 let m: i64 = nx_html_decode_entities(tmp, 0, k, out, cap) 77 out[m] = 0 as u8 78 return m 79} 80 81// extract the col-th <td> cell of row [rs,re) as clean text. 1/0. 82func ht_cell(html: *u8, rs: i64, re: i64, col: i64, out: *u8, cap: i64) -> i64 { 83 var p: i64 = rs; var c: i64 = 0 84 while p < re { 85 let td: i64 = ht_find_open(html, re, p, "td" as *u8) 86 if td < 0 { return 0 } 87 let cs: i64 = ht_after_gt(html, re, td) 88 let tdc: i64 = ht_find_close(html, re, cs, "td" as *u8) 89 var ce: i64 = re 90 if tdc >= 0 { ce = tdc } 91 if c == col { ht_text(html, cs, ce, out, cap); return 1 } 92 c = c + 1 93 p = ce + 1 94 } 95 return 0 96} 97 98// content [rs,re) of the next <tr> at/after pos. returns next scan pos, or -1 if none. 99func ht_next_row(html: *u8, n: i64, pos: i64, rs_out: *i64, re_out: *i64) -> i64 { 100 let tr: i64 = ht_find_open(html, n, pos, "tr" as *u8) 101 if tr < 0 { return 0 - 1 } 102 let cs: i64 = ht_after_gt(html, n, tr) 103 let trc: i64 = ht_find_close(html, n, cs, "tr" as *u8) 104 var ce: i64 = n 105 if trc >= 0 { ce = trc } 106 rs_out[0] = cs 107 re_out[0] = ce 108 return ce + 1 109}