From 1052dcaac9c9820b7775109f6656f64beb238a32 Mon Sep 17 00:00:00 2001 From: Quinn Date: Thu, 7 Aug 2025 12:06:53 +0200 Subject: [PATCH] add functions for incrementing to the next tag --- src/dat/nbt.c | 59 +++++++++++++++++++++++++++++++++++++-------------- src/dat/nbt.h | 21 ++++++++++++------ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/dat/nbt.c b/src/dat/nbt.c index 95773b9..db52bca 100644 --- a/src/dat/nbt.c +++ b/src/dat/nbt.c @@ -33,7 +33,44 @@ int nbt_primsize(u8 tag) { } } -size_t nbt_tagdatlen(const u8 *restrict buf) { +const u8 *nbt_nextcompound(const u8 *restrict cdat) { + return NULL; +} + +const u8 *nbt_nextlist(const u8 *restrict ldat) { + const u8 *ptr = ldat + 5; + i32 len = be32toh(*(u32 *)(ldat + 1)); + + switch (*ldat) { + case NBT_I8: + case NBT_I16: + case NBT_I32: + case NBT_I64: + case NBT_F32: + case NBT_F64: + return ptr + nbt_primsize(*ldat) * len; + + // loop for each compound, whilst `ptr` isn't `NULL` + case NBT_COMPOUND: { + for (u32 i = 0; i < (u32)len && ptr; i++) { + ptr = nbt_nextcompound(ptr); + } + return ptr; + } + + // TODO: implement list/array/string handling + case NBT_STR: + case NBT_ARR_I8: + case NBT_ARR_I32: + case NBT_ARR_I64: + case NBT_LIST: + default: + return NULL; + } +} + +const u8 *nbt_nexttag(const u8 *restrict buf, u16 naml) { + const u8 *ptr = buf + naml + 3; size_t mems = 0; switch (*buf) { @@ -43,29 +80,19 @@ size_t nbt_tagdatlen(const u8 *restrict buf) { case NBT_F32: case NBT_I64: case NBT_F64: - mems = nbt_primsize(*buf); - return -(mems >= 0) & mems; + return ptr + nbt_primsize(*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 * (i32)be32toh(*(u32 *)(buf)) + 4; + case NBT_ARR_I8: return ptr + ++mems * (i32)be32toh(*(u32 *)(ptr)) + 4; - case NBT_STR: return be16toh(*(u16 *)buf) + 2; + case NBT_STR: return ptr + be16toh(*(u16 *)(ptr)) + 2; + case NBT_LIST: return nbt_nextlist(ptr); - case NBT_LIST: - mems = nbt_primsize(*buf); - if (mems > 0) return mems * (i32)be32toh(*(u32 *)(buf + 1)) + 5; - return 0; - default: return 0; + default: return NULL; } } -const u8 *nbt_nexttag(const u8 *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; -} - // TODO: not actually doing anything /* readies the output data for export, returns the new buffer position, or `NULL` upon an error (may be out of bounds) */ static const u8 *nbt_proctag(const u8 *restrict buf, u16 slen) { diff --git a/src/dat/nbt.h b/src/dat/nbt.h index 41bfbd5..e3941d2 100644 --- a/src/dat/nbt.h +++ b/src/dat/nbt.h @@ -48,18 +48,25 @@ CONST int nbt_primsize(u8 tag); * returns a boolean value. */ CONST int nbt_isprim(u8 tag); +/* searches for the end of a compound tag without processing data, the final pointer is returned. + * `NULL` is returned upon failure, the otherwise returned pointer is not guaranteed to be valid. + * `cdat` is assumed to be the start of the **compound tag's data**. */ +PURE NONNULL((1)) const u8 *nbt_nextcompound(const u8 *restrict cdat); + +/* searches for the end of a list tag without processing data, the final pointer is returned. + * `NULL` is returned upon failure, the otherwise returned pointer is not guaranteed to be valid. + * `ldat` is assumed to be the start of the **list tag's data.** */ +PURE NONNULL((1)) const u8 *nbt_nextlist(const u8 *restrict ldat); + +/* searches for the end of a named tag without processing data, the final pointer is returned. + * `NULL` is returned upon failure, the otherwise returned pointer is not guaranteed to be valid. */ +PURE NONNULL((1)) const u8 *nbt_nexttag(const u8 *restrict buf, u16 naml); + /* returns the name length of a specific tag. `buf` is the pointer to start of the tag */ atrb_pure atrb_nonnull(1) static inline u16 nbt_namelen(const u8 *restrict buf) { assert(*buf != NBT_END); return be16toh(*(u16 *)(buf + 1)); } -/* returns the (expected) pointer of the tag following this one. - * `NULL` is returned if anything went wrong. */ -atrb_pure atrb_nonnull(1) const u8 *nbt_nexttag(const u8 *restrict buf, u16 naml); - -/* gets the byte size of an NBT tag's data (excluding id and name), returns `0` upon error. */ -atrb_pure size_t nbt_tagdatlen(const u8 *buf); - /* 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, const u8 *restrict buf, size_t len);