diff --git a/src/dat/nbt.c b/src/dat/nbt.c index f8baa56..1a6d7bd 100644 --- a/src/dat/nbt.c +++ b/src/dat/nbt.c @@ -7,6 +7,59 @@ #include "../util/compat/endian.h" #include "../util/types.h" +int nbt_isprim(u8 tag) { + switch (tag) { + case NBT_I8: + case NBT_I16: + case NBT_I32: + case NBT_F32: + case NBT_I64: + case NBT_F64: + return 1; + default: + return 0; + } +} + +int nbt_primsize(u8 tag) { + switch (tag) { + case NBT_I8: return 1; + case NBT_I16: return 2; + case NBT_I32: // fall through + case NBT_F32: return 4; + case NBT_I64: // fall through + case NBT_F64: return 8; + default: return -1; + } +} + +size_t nbt_tagdatlen(const u8 *restrict buf) { + size_t mems = 0; + + switch (*buf) { + case NBT_I8: + case NBT_I16: + case NBT_I32: + case NBT_F32: + case NBT_I64: + 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 * (i32)be32toh(*(u32 *)(buf)) + 4; + + case NBT_STR: return be16toh(*(u16 *)buf) + 2; + + case NBT_LIST: + mems = nbt_primsize(*buf); + if (mems > 0) return mems * (i32)be32toh(*(u32 *)(buf + 1)) + 5; + return 0; + default: return 0; + } +} + 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 @@ -95,56 +148,3 @@ int nbt_proc(struct nbt_path const *restrict pats, uint npats, const u8 *restric // TODO: finish function return !dpt; } - -int nbt_primsize(u8 tag) { - switch (tag) { - case NBT_I8: return 1; - case NBT_I16: return 2; - case NBT_I32: // fall through - case NBT_F32: return 4; - case NBT_I64: // fall through - case NBT_F64: return 8; - default: return -1; - } -} - -size_t nbt_tagdatlen(const u8 *restrict buf) { - size_t mems = 0; - - switch (*buf) { - case NBT_I8: - case NBT_I16: - case NBT_I32: - case NBT_F32: - case NBT_I64: - 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 * (i32)be32toh(*(u32 *)(buf)) + 4; - - case NBT_STR: return be16toh(*(u16 *)buf) + 2; - - case NBT_LIST: - mems = nbt_primsize(*buf); - if (mems > 0) return mems * (i32)be32toh(*(u32 *)(buf + 1)) + 5; - return 0; - default: return 0; - } -} - -int nbt_isprim(u8 tag) { - switch (tag) { - case NBT_I8: - case NBT_I16: - case NBT_I32: - case NBT_F32: - case NBT_I64: - case NBT_F64: - return 1; - default: - return 0; - } -} diff --git a/src/dat/nbt.h b/src/dat/nbt.h index cffab7a..41bfbd5 100644 --- a/src/dat/nbt.h +++ b/src/dat/nbt.h @@ -41,6 +41,13 @@ struct nbt_path { i16 len; // specifies the length of the NBT elements }; +/* gets the tag size of primitive types, returns `>0` on success, `<0` on failure */ +CONST int nbt_primsize(u8 tag); + +/* checks whether the tag is a primitive data tag. (not recommended for filtering tags, use a `switch`) + * returns a boolean value. */ +CONST int nbt_isprim(u8 tag); + /* 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); @@ -51,15 +58,8 @@ atrb_pure atrb_nonnull(1) static inline u16 nbt_namelen(const u8 *restrict buf) * `NULL` is returned if anything went wrong. */ atrb_pure atrb_nonnull(1) const u8 *nbt_nexttag(const u8 *restrict buf, u16 naml); -/* checks whether the tag is a primitive data tag. (not recommended for filtering tags, use a `switch`) - * 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); - /* 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);