Compare commits

..

2 Commits

Author SHA1 Message Date
0358baf60d rewrite endian header to not interfere with the endian system header.
the system header is inconsistently available across platforms.
This header provides the same functionality for less of the cost,
overriding the system macros.
2025-07-16 09:34:56 +02:00
4728846985 write a function for skipping to the next NBT tag 2025-07-15 13:51:23 +02:00
2 changed files with 14 additions and 54 deletions

View File

@@ -11,11 +11,6 @@ static inline u16 nbt_strlen(u8 const *restrict buf) {
return be16toh(*(u16 *)(buf));
}
/* returns the length of an array from a specific location in the buffer */
static inline i32 nbt_arrlen(u8 const *restrict buf) {
return be32toh(*(i32 *)(buf));
}
/* compares the string in `buf` to `matstr`.
* returns `=0` if equal, `>0` if buf is greater, `<0` if matstr is greater. */
static int nbt_cmpstr(char const *restrict matstr, u8 const *restrict buf) {
@@ -29,60 +24,29 @@ static int nbt_cmpstr(char const *restrict matstr, u8 const *restrict buf) {
return strncmp(str, matstr, len);
}
/* gets the tag size of primitive types, returns `>0` on success, `<0` on failure */
int nbt_prim_tagsize(u8 tag) {
switch (tag) {
case NBT_I8: return 1;
case NBT_I16: return 2;
case NBT_I32: return 4;
case NBT_I64: return 8;
case NBT_F32: return 4;
case NBT_F64: return 8;
default: return -1;
}
}
/* 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;
static u8 const *nbt_nexttag(u8 *buf) {
u8 const *nxt = NULL;
uint mems = 0;
switch (*buf) {
case NBT_I8:
case NBT_I16:
case NBT_I32:
case NBT_I64:
case NBT_F32:
case NBT_F64:
nxt += nbt_prim_tagsize(*buf);
return nxt;
case NBT_ARR_I64:
mems += sizeof(i64) - sizeof(i32);
case NBT_ARR_I32:
mems += sizeof(i32) - sizeof(i8);
case NBT_I8: nxt = buf + 1 + 1; break; // add 1 for the tag size here, since the constant can be precomputed
case NBT_I16: nxt = buf + 1 + 2; break;
case NBT_I32: nxt = buf + 1 + 4; break;
case NBT_I64: nxt = buf + 1 + 8; break;
case NBT_F32: nxt = buf + 1 + 4; break;
case NBT_F64: nxt = buf + 1 + 8; break;
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:
mems = nbt_prim_tagsize(*nxt);
if (mems > 0) {
nxt += 1;
nxt += mems * nbt_arrlen(nxt);
return nxt;
}
// let case escape to `default` when `mems` `≤0`
case NBT_STR: break;
case NBT_LIST: break;
case NBT_ARR_I32: break;
case NBT_ARR_I64: break;
default: return NULL; // failure on compound/end tags; these require more nuanced logic
}
return nxt + nbt_strlen(buf + 1);
}
int nbt_proc(void **restrict datout, u8 const *restrict buf, size_t len) {

View File

@@ -2,9 +2,6 @@
// Licensed under the MIT Licence. See LICENSE for details
#pragma once
#if __has_include(<endian.h>)
#include <endian.h>
#else
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define le16toh(x) __uint16_identity(x)
#define le32toh(x) __uint32_identity(x)
@@ -34,4 +31,3 @@
#else
#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc)
#endif
#endif