From 2daeb9823c14d6c40812952badc2ab6f184b180b Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 23 Jul 2025 14:37:23 +0200 Subject: [PATCH] add a function to get an NBT array bytelength --- src/dat/nbt.c | 57 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/dat/nbt.c b/src/dat/nbt.c index 4dbf88b..161a104 100644 --- a/src/dat/nbt.c +++ b/src/dat/nbt.c @@ -29,6 +29,26 @@ static int nbt_cmpstr(char const *restrict matstr, u8 const *restrict buf) { return strncmp(str, matstr, len); } +/* acquires the array's byte size (excluding name + size spec) + * returns `0` upon failure */ +static size_t nbt_arrbsize(u8 const *restrict buf) { + i32 mems = 0; + + switch (*buf) { + case NBT_ARR_I64: mems += sizeof(i64) - sizeof(i32); __attribute__((fallthrough)); + case NBT_ARR_I32: mems += sizeof(i32) - sizeof(i8); __attribute__((fallthrough)); + case NBT_ARR_I8: return +mems * nbt_arrlen(buf); // mems+1 multiplied by the array length + + case NBT_STR: return nbt_strlen(buf); + + case NBT_LIST: + mems = nbt_primsize(*buf); + if (mems > 0) return mems * nbt_arrlen(buf + 1); + return 0; + default: return 0; + } +} + /* returns the (expected) pointer of the tag following this one. * `NBT_COMPOUND` and `NBT_END` tags are not valid for this function and should be handled separately. * `NULL` is returned if anything went wrong. */ @@ -36,7 +56,7 @@ static u8 const *nbt_nexttag(u8 const *restrict buf) { u8 const *nxt = buf + 1; nxt += nbt_strlen(nxt) + 2; - uint mems = 0; + i32 tmp; switch (*buf) { case NBT_I8: __attribute__((fallthrough)); case NBT_I16: __attribute__((fallthrough)); @@ -44,29 +64,22 @@ static u8 const *nbt_nexttag(u8 const *restrict buf) { case NBT_I64: __attribute__((fallthrough)); case NBT_F32: __attribute__((fallthrough)); case NBT_F64: - nxt += nbt_primsize(*buf); - return nxt; + tmp = nbt_primsize(*buf); + return (tmp >= 0) ? (nxt + tmp) : 0; - case NBT_ARR_I64: - mems += sizeof(i64) - sizeof(i32); - case NBT_ARR_I32: - mems += sizeof(i32) - sizeof(i8); - case NBT_ARR_I8: - mems += 1; - nxt += mems * nbt_arrlen(nxt); - return nxt; - case NBT_STR: - nxt += nbt_strlen(nxt); - return nxt; + case NBT_LIST: nxt += 5; break; + case NBT_STR: nxt += 2; break; + case NBT_ARR_I8: __attribute__((fallthrough)); + case NBT_ARR_I32: __attribute__((fallthrough)); + case NBT_ARR_I64: nxt += 4; break; + + default: return NULL; // failure on compound/end tags; these require more nuanced logic + } + + tmp = nbt_arrbsize(buf); + return (tmp >= 0) ? (nxt + tmp) : NULL; +} - case NBT_LIST: - mems = nbt_primsize(*nxt); - if (mems > 0) { - nxt += 1; - nxt += mems * nbt_arrlen(nxt); - return nxt; - } - // let case escape to `default` when `mems` `≤0` default: return NULL; // failure on compound/end tags; these require more nuanced logic }