Merge branch 'lang/foundations' into lang/nav

This commit is contained in:
Orkun ÇAKILKAYA 2026-09-27 22:26:11 +03:00
commit f1153f59a2
3 changed files with 42 additions and 2 deletions

View file

@ -163,7 +163,11 @@ function gltf_load(render3d_st: mut Render3dState, dir: string, file: string, no
render3d_st.gltf_dir = dir
let text = Fs.read_text(dir + "/" + file)
if text == null { print(`gltf: cannot read {dir}/{file}`); return null }
# the last file's tree goes first (it is read only until the next load: ludic.anim's read.ludic),
# and the text once parsed - nothing gives memory back on its own (plan 23 of maroon-lake)
if render3d_st.gltf_doc != null { Json.free(render3d_st.gltf_doc) }
render3d_st.gltf_doc = Json.parse(text)
free(text)
let buffers = value_get(render3d_st.gltf_doc, "buffers")
let bin_uri = value_as_str(value_get(value_at(buffers, 0), "uri"))
render3d_st.gltf_bin = file_open(dir + "/" + bin_uri, "rb")

View file

@ -478,10 +478,12 @@ namespace Value {
alias as_int(value) = value_as_int
alias as_float(value) = value_as_float
alias as_str(value) = value_as_str
alias free(value) = value_free
}
namespace Json {
alias encode(value) = json_encode
alias parse(text) = json_parse
alias free(value) = json_free
}
namespace Xml {
alias parse(text) = xml_parse

View file

@ -166,9 +166,23 @@ function jp_skip_ws(p: JP) -> void {
function json_parse(s: pointer) -> Val {
let p = new JP
p.s = s; p.i = 0; p.n = len(s)
return jp_value(p)
let v = jp_value(p)
free(p)
return v
}
# Let a parsed tree go once what it describes is built: every node and its lists. Its strings stay -
# a caller may keep a name it read out of the tree - and a tree put together by hand, which may share
# a node or hold a literal, is not for this (Ludic has no collector; plan 23 of maroon-lake).
function value_free(v: Val) -> void {
if v == null { return }
for i in 0 .. len(v.kids) { value_free(v.kids[i]) }
free(v.kids)
free(v.keys)
free(v)
}
function json_free(v: Val) -> void { value_free(v) }
function jp_value(p: JP) -> Val {
jp_skip_ws(p)
if p.i >= p.n { return value_null() }
@ -182,9 +196,29 @@ function jp_value(p: JP) -> Val {
return jp_number(p)
}
# read a quoted string (cursor on the opening quote) -> the unescaped contents.
# read a quoted string (cursor on the opening quote) -> the unescaped contents. One allocation for a
# string with no escape in it: built a character at a time, every step was a string never freed
function jp_string(p: JP) -> string {
p.i += 1 # skip opening quote
let a = p.i
while p.i < p.n {
let c = p.s[p.i]
if c == '"' {
let out = p.s[a..p.i]
p.i += 1
return out
}
if c == '\\' {
p.i = a
return jp_string_esc(p)
}
p.i += 1
}
return p.s[a..p.n]
}
# the same with escapes in it, the rare case, a character at a time
function jp_string_esc(p: JP) -> string {
var out = ""
while p.i < p.n {
let c = p.s[p.i]