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 cffab7a..1e76614 100644 --- a/src/dat/nbt.h +++ b/src/dat/nbt.h @@ -41,6 +41,20 @@ struct nbt_path { i16 len; // specifies the length of the NBT elements }; +/* 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); @@ -55,9 +69,6 @@ atrb_pure atrb_nonnull(1) const u8 *nbt_nexttag(const u8 *restrict buf, u16 naml * 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_pure size_t nbt_tagdatlen(const u8 *buf); - /* gets the tag size of primitive types, returns `>0` on success, `<0` on failure */ atrb_const int nbt_primsize(u8 tag);