modify the array bytelength function to get the bytelength of a single tag.

This commit is contained in:
2025-07-23 16:31:08 +02:00
parent 2daeb9823c
commit fd8db02e77
2 changed files with 33 additions and 52 deletions

View File

@@ -29,60 +29,12 @@ 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. */
static u8 const *nbt_nexttag(u8 const *restrict buf) {
u8 const *nxt = buf + 1;
nxt += nbt_strlen(nxt) + 2;
i32 tmp;
switch (*buf) {
case NBT_I8: __attribute__((fallthrough));
case NBT_I16: __attribute__((fallthrough));
case NBT_I32: __attribute__((fallthrough));
case NBT_I64: __attribute__((fallthrough));
case NBT_F32: __attribute__((fallthrough));
case NBT_F64:
tmp = nbt_primsize(*buf);
return (tmp >= 0) ? (nxt + tmp) : 0;
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;
}
default: return NULL; // failure on compound/end tags; these require more nuanced logic
}
static u8 const *nbt_nexttag(u8 const *restrict buf, u16 naml) {
size_t len = nbt_tagdatlen(buf);
if (!len) return NULL; // TODO: compound tags should be handled here
return buf + naml + len + 3;
}
int nbt_proc(void **restrict datout, u8 const *restrict buf, size_t len) {
@@ -112,6 +64,33 @@ int nbt_primsize(u8 tag) {
}
}
size_t nbt_tagdatlen(u8 const *restrict buf) {
size_t mems = 0;
switch (*buf) {
case NBT_I8: __attribute__((fallthrough));
case NBT_I16: __attribute__((fallthrough));
case NBT_I32: __attribute__((fallthrough));
case NBT_F32: __attribute__((fallthrough));
case NBT_I64: __attribute__((fallthrough));
case NBT_F64:
mems = nbt_primsize(*buf);
return -(mems >= 0) & mems;
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) + 4;
case NBT_STR: return nbt_strlen(buf) + 2;
case NBT_LIST:
mems = nbt_primsize(*buf);
if (mems > 0) return mems * nbt_arrlen(buf + 1) + 5;
return 0;
default: return 0;
}
}
int nbt_isprim(u8 tag) {
switch (tag) {
case NBT_I8: __attribute__((fallthrough));

View File

@@ -40,6 +40,8 @@ int nbt_proc(void **restrict datout, u8 const *restrict buf, size_t len);
* returns a boolean value. */
atrb_const int nbt_isprim(u8 tag);
/* gets the byte size of an NBT tag's data (excluding id and name), returns `0` upon error. */
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);