From 13e1ceddfcc51d482e5bc2957564bb3f38d35814 Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 23 Jul 2025 16:40:13 +0200 Subject: [PATCH] update `nbt_proc` function, still inoperable --- src/dat/nbt.c | 55 +++++++++++++++++++++++++++++++++++++++++++++------ src/dat/nbt.h | 8 +++++++- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/dat/nbt.c b/src/dat/nbt.c index bc8b017..0f07f5e 100644 --- a/src/dat/nbt.c +++ b/src/dat/nbt.c @@ -1,5 +1,6 @@ #include "nbt.h" +#include #include #include @@ -68,14 +69,56 @@ static u8 const *nbt_proctag(u8 const *restrict buf, u16 slen) { return ptr + nbt_primsize(*buf); } -int nbt_proc(void **restrict datout, u8 const *restrict buf, size_t len) { - // ignore the first tag + its name, so we start with the juicy data - uint tmp = nbt_strlen(buf + 1) + 3; - buf += tmp; - len -= tmp; +/* finds which of `pats` is equivalent to `cmp`, assumes `cmp` is `≥len` bytes long */ +static char const *getpat(struct nbt_path const *restrict pats, uint npats, i16 dpt, char const *restrict cmp, u16 len) { + for (uint i = 0; i < npats; i++) { + if (strncmp(pats[i].pat[dpt], cmp, len) == 0) + return pats[i].pat[dpt]; + } + return NULL; +} + +// TODO: make the user do the looping +int nbt_proc(struct nbt_path const *restrict pats, uint npats, u8 const *restrict buf, size_t len) { + // ensure first and last tag(s) are valid + if (buf[0] != NBT_COMPOUND || buf[len - 1] != NBT_END) + return 1; + + i16 dpt = 0; + i16 mdpt = 0; + + // acquire the maximum depth that we'll need to go (exclusive) + for (uint i = 0; i < npats; i++) { + int tmp = pats[i].len - mdpt; + mdpt += -(tmp > 0) & tmp; + } + assert(mdpt > 0); + + // storing the segments of the current path + char const *cpat[mdpt - 1]; + memset((void *)cpat, 0, mdpt - 1); + + // looping through the different tags + u8 const *ptr = buf + nbt_strlen(buf + 1) + 3; + while (ptr < (buf + len) && dpt >= 0) { + u16 naml = nbt_strlen(ptr + 1); + char const *mat = getpat(pats, npats, dpt, (char *)(ptr + 3), naml); + cpat[dpt] = mat; + + if (mat) { + switch (*ptr) { + case NBT_END: dpt--; break; + case NBT_COMPOUND: dpt++; break; + default: ptr = nbt_proctag(ptr, naml); break; + } + } else { + ptr = nbt_nexttag(ptr, naml); + if (!ptr) return 1; + } + } // TODO: finish function - return 0; + return !dpt; } int nbt_primsize(u8 tag) { diff --git a/src/dat/nbt.h b/src/dat/nbt.h index d13122b..64892de 100644 --- a/src/dat/nbt.h +++ b/src/dat/nbt.h @@ -34,7 +34,10 @@ enum nbt_tagid { NBT_ARR_I64 = 0x0C, // starts with a i32, denoting size, followed by the u32 data }; -int nbt_proc(void **restrict datout, u8 const *restrict buf, size_t len); +struct nbt_path { + char const **restrict pat; // specifies the NBT path components as separate elements + i16 len; // specifies the length of the NBT elements +}; /* checks whether the tag is a primitive data tag. (not recommended for filtering tags, use a `switch`) * returns a boolean value. */ @@ -45,3 +48,6 @@ atrb_const size_t nbt_tagdatlen(u8 const *buf); /* gets the tag size of primitive types, returns `>0` on success, `<0` on failure */ atrb_const int nbt_primsize(u8 tag); + +/* processes the uncompressed `NBT` data in `buf`, with a size of `len`. */ +atrb_nonnull(1, 3) int nbt_proc(struct nbt_path const *restrict paths, uint npaths, u8 const *restrict buf, size_t len);