ludic.ui: reading a sheet gives back what no rule keeps - lss_strip writes into bytes of its own, a rule's selector and body texts, its selector pieces, each declaration's piece and raw key and value slices, a @keyframes or @media body and a keyframes reader freed once parsed (a kept tpl_words result, a keyframes name and a @media condition never)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
beebbd0bc1
commit
88580ca319
3 changed files with 70 additions and 24 deletions
|
|
@ -23,15 +23,23 @@ function an_read(ui_st: mut UiState, name: string, body: string, err: []string)
|
||||||
while r.err == "" {
|
while r.err == "" {
|
||||||
rd_ws(r)
|
rd_ws(r)
|
||||||
if r.i >= len(r.s) { break }
|
if r.i >= len(r.s) { break }
|
||||||
let stop = tpl_words(lss_upto(r, 123))
|
let sr = lss_upto(r, 123)
|
||||||
let decls = lss_decls(lss_upto(r, 125), err)
|
let stop = tpl_words(sr)
|
||||||
|
let db = lss_upto(r, 125)
|
||||||
|
let decls = lss_decls(db, err)
|
||||||
var at = el_num(stop) / 100.0
|
var at = el_num(stop) / 100.0
|
||||||
if stop == "from" { at = 0.0 }
|
if stop == "from" { at = 0.0 }
|
||||||
if stop == "to" { at = 1.0 }
|
if stop == "to" { at = 1.0 }
|
||||||
push(k.stops, at)
|
push(k.stops, at)
|
||||||
push(k.rules, decls)
|
push(k.rules, decls)
|
||||||
|
unsafe { # the stop and its body are read, never kept
|
||||||
|
if not tpl_clean(sr) { free(stop) }
|
||||||
|
free(sr)
|
||||||
|
free(db)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
push(ui_st.an_frames, k)
|
push(ui_st.an_frames, k)
|
||||||
|
unsafe { free(r) }
|
||||||
}
|
}
|
||||||
function an_find(ui_st: UiState, name: string) -> UiKeyframes {
|
function an_find(ui_st: UiState, name: string) -> UiKeyframes {
|
||||||
for i in 0 .. len(ui_st.an_frames) {
|
for i in 0 .. len(ui_st.an_frames) {
|
||||||
|
|
|
||||||
|
|
@ -51,13 +51,17 @@ function lss_block(ui_st: mut UiState, f: UiFile, src: string, md: UiMedia, err:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if rd_op(r, "@keyframes") {
|
if rd_op(r, "@keyframes") {
|
||||||
let name = lss_upto(r, 123)
|
let name = lss_upto(r, 123) # kept: the keyframes' name may be this very text
|
||||||
an_read(ui_st, name, lss_upto(r, 125), err)
|
let kb = lss_upto(r, 125)
|
||||||
|
an_read(ui_st, name, kb, err)
|
||||||
|
unsafe { free(kb) }
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if rd_op(r, "@media") {
|
if rd_op(r, "@media") {
|
||||||
let cond = md_parse(lss_upto(r, 123))
|
let cond = md_parse(lss_upto(r, 123))
|
||||||
lss_block(ui_st, f, lss_upto(r, 125), cond, err)
|
let mb = lss_upto(r, 125)
|
||||||
|
lss_block(ui_st, f, mb, cond, err)
|
||||||
|
unsafe { free(mb) }
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let sels = lss_upto(r, 123)
|
let sels = lss_upto(r, 123)
|
||||||
|
|
@ -65,6 +69,10 @@ function lss_block(ui_st: mut UiState, f: UiFile, src: string, md: UiMedia, err:
|
||||||
let at = len(f.own)
|
let at = len(f.own)
|
||||||
lss_rule(f, sels, body, err)
|
lss_rule(f, sels, body, err)
|
||||||
for i in at .. len(f.own) { f.own[i].md = md }
|
for i in at .. len(f.own) { f.own[i].md = md }
|
||||||
|
unsafe { # a rule keeps what it parsed, never the text it was sliced from
|
||||||
|
free(sels)
|
||||||
|
free(body)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if r.err != "" { push(err, r.err) }
|
if r.err != "" { push(err, r.err) }
|
||||||
unsafe { free(r) } # the reader only: its text is the caller's
|
unsafe { free(r) } # the reader only: its text is the caller's
|
||||||
|
|
@ -95,20 +103,25 @@ function lss_upto(r: UiRd, c: int) -> string {
|
||||||
}
|
}
|
||||||
function lss_strip(src: string) -> string {
|
function lss_strip(src: string) -> string {
|
||||||
if not lss_has_comment(src) { return src } # no comment: nothing to strip, nothing made
|
if not lss_has_comment(src) { return src } # no comment: nothing to strip, nothing made
|
||||||
var out = ""
|
# written once into bytes of its own (lss_text frees them): joined a piece at a time, every
|
||||||
var at = 0
|
# comment left the text so far behind
|
||||||
|
var p: pointer = null
|
||||||
|
unsafe { p = bytes(len(src) + 1) }
|
||||||
|
var n = 0
|
||||||
var i = 0
|
var i = 0
|
||||||
while i + 1 < len(src) {
|
while i < len(src) {
|
||||||
if src[i] == 47 and src[i + 1] == 42 {
|
if i + 1 < len(src) and src[i] == 47 and src[i + 1] == 42 {
|
||||||
out = out + src[at..i]
|
|
||||||
var j = i + 2
|
var j = i + 2
|
||||||
while j + 1 < len(src) and not (src[j] == 42 and src[j + 1] == 47) { j += 1 }
|
while j + 1 < len(src) and not (src[j] == 42 and src[j + 1] == 47) { j += 1 }
|
||||||
i = j + 2
|
i = j + 2
|
||||||
at = i
|
} else {
|
||||||
} else { i += 1 }
|
unsafe { p[n] = src[i] }
|
||||||
|
n += 1
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if at < len(src) { out = out + src[at..len(src)] }
|
unsafe { p[n] = 0 }
|
||||||
return out
|
return p
|
||||||
}
|
}
|
||||||
function lss_has_comment(src: string) -> bool {
|
function lss_has_comment(src: string) -> bool {
|
||||||
for i in 0 .. len(src) - 1 {
|
for i in 0 .. len(src) - 1 {
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,23 @@ function lss_rule(f: UiFile, sels: string, body: string, err: []string) -> void
|
||||||
let each = lss_split(sels, 44)
|
let each = lss_split(sels, 44)
|
||||||
for i in 0 .. len(each) {
|
for i in 0 .. len(each) {
|
||||||
let sel = tpl_words(each[i])
|
let sel = tpl_words(each[i])
|
||||||
if len(sel) == 0 { continue }
|
if len(sel) > 0 { lss_rule_add(f, decls, sel, err) }
|
||||||
let r = new UiRule
|
unsafe { # a selector keeps its parsed parts, never its text
|
||||||
r.keys = decls.keys
|
if not tpl_clean(each[i]) { free(sel) }
|
||||||
r.vals = decls.vals
|
free(each[i])
|
||||||
r.sel = sel_parse(sel, err)
|
|
||||||
if r.sel != null {
|
|
||||||
r.spec = sel_spec(r.sel)
|
|
||||||
push(f.own, r)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
unsafe { free(each) }
|
||||||
|
}
|
||||||
|
function lss_rule_add(f: UiFile, decls: UiRule, sel: string, err: []string) -> void {
|
||||||
|
let r = new UiRule
|
||||||
|
r.keys = decls.keys
|
||||||
|
r.vals = decls.vals
|
||||||
|
r.sel = sel_parse(sel, err)
|
||||||
|
if r.sel != null {
|
||||||
|
r.spec = sel_spec(r.sel)
|
||||||
|
push(f.own, r)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# `key: value; key: value`, a rule's body or a style="..." attribute
|
# `key: value; key: value`, a rule's body or a style="..." attribute
|
||||||
function lss_decls(body: string, err: []string) -> UiRule {
|
function lss_decls(body: string, err: []string) -> UiRule {
|
||||||
|
|
@ -31,8 +38,11 @@ function lss_decls(body: string, err: []string) -> UiRule {
|
||||||
if len(tpl_words(d)) > 0 { push(err, `"{tpl_words(d)}" is not a property: value`) }
|
if len(tpl_words(d)) > 0 { push(err, `"{tpl_words(d)}" is not a property: value`) }
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
push(r.keys, tpl_words(d[0..colon]))
|
lss_decl_add(r, d, colon, err)
|
||||||
push(r.vals, tpl_value(tpl_words(d[colon + 1..len(d)]), err))
|
}
|
||||||
|
unsafe { # the pieces the declarations were sliced from
|
||||||
|
for i in 0 .. len(decls) { free(decls[i]) }
|
||||||
|
free(decls)
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
@ -70,3 +80,18 @@ function sheet_add(sh: UiSheet, r: UiRule) -> void {
|
||||||
}
|
}
|
||||||
sh.rules[i] = r
|
sh.rules[i] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# one `key: value` into the rule: the key kept as read (a clean slice is its own words), the
|
||||||
|
# value parsed (its expression copies what it keeps), and the slices nothing keeps given back
|
||||||
|
function lss_decl_add(r: UiRule, d: string, colon: int, err: []string) -> void {
|
||||||
|
let kr: string = d[0..colon]
|
||||||
|
push(r.keys, tpl_words(kr))
|
||||||
|
if not tpl_clean(kr) { unsafe { free(kr) } }
|
||||||
|
let vr: string = d[colon + 1..len(d)]
|
||||||
|
let vt = tpl_words(vr)
|
||||||
|
push(r.vals, tpl_value(vt, err))
|
||||||
|
unsafe {
|
||||||
|
if not tpl_clean(vr) { free(vt) }
|
||||||
|
free(vr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue