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 50 additions and 46 deletions

View File

@@ -1,9 +1,9 @@
#include "nbt.h"
#include <endian.h>
#include <stddef.h>
#include <string.h>
#include "../util/compat/endian.h"
#include "../util/types.h"
/* returns the string length from a specific location in the buffer */
@@ -24,6 +24,31 @@ static int nbt_cmpstr(char const *restrict matstr, u8 const *restrict buf) {
return strncmp(str, matstr, len);
}
/* 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 *buf) {
u8 const *nxt = NULL;
switch (*buf) {
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:
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) {
// first byte should be a compound tag

View File

@@ -2,53 +2,32 @@
// Licensed under the MIT Licence. See LICENSE for details
#pragma once
#include <stdint.h>
#include "../atrb.h"
#include "../types.h"
/* little endian */
atrb_const static inline u16 le16ton(u16); // converts little-endian (LE) encoding to native for a 16 bit integer. (NOOP if native is LE)
atrb_const static inline u32 le32ton(u32); // converts little-endian (LE) encoding to native for a 32 bit integer. (NOOP if native is LE)
atrb_const static inline u64 le64ton(u64); // converts little-endian (LE) encoding to native for a 64 bit integer. (NOOP if native is LE)
atrb_const static inline u16 ntole16(u16); // converts native encoding to little-endian (LE) for a 16 bit integer. (NOOP if native is LE)
atrb_const static inline u32 ntole32(u32); // converts native encoding to little-endian (LE) for a 32 bit integer. (NOOP if native is LE)
atrb_const static inline u64 ntole64(u64); // converts native encoding to little-endian (LE) for a 64 bit integer. (NOOP if native is LE)
/* big endian */
atrb_const static inline u16 be16ton(u16); // converts big-endian (BE) encoding to native for a 16 bit integer. (NOOP if native is BE)
atrb_const static inline u32 be32ton(u32); // converts big-endian (BE) encoding to native for a 32 bit integer. (NOOP if native is BE)
atrb_const static inline u64 be64ton(u64); // converts big-endian (BE) encoding to native for a 64 bit integer. (NOOP if native is BE)
atrb_const static inline u16 ntobe16(u16); // converts native encoding to big-endian (BE) for a 16 bit integer. (NOOP if native is BE)
atrb_const static inline u32 ntobe32(u32); // converts native encoding to big-endian (BE) for a 32 bit integer. (NOOP if native is BE)
atrb_const static inline u64 ntobe64(u64); // converts native encoding to big-endian (BE) for a 64 bit integer. (NOOP if native is BE)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u16 le16ton(u16 x) { return x; }
u32 le32ton(u32 x) { return x; }
u64 le64ton(u64 x) { return x; }
u16 ntole16(u16 x) { return x; }
u32 ntole32(u32 x) { return x; }
u64 ntole64(u64 x) { return x; }
u16 be16ton(u16 x) { return __builtin_bswap16(x); }
u32 be32ton(u32 x) { return __builtin_bswap32(x); }
u64 be64ton(u64 x) { return __builtin_bswap64(x); }
u16 ntobe16(u16 x) { return __builtin_bswap16(x); }
u32 ntobe32(u32 x) { return __builtin_bswap32(x); }
u64 ntobe64(u64 x) { return __builtin_bswap64(x); }
#define le16toh(x) __uint16_identity(x)
#define le32toh(x) __uint32_identity(x)
#define le64toh(x) __uint64_identity(x)
#define htole16(x) __uint16_identity(x)
#define htole32(x) __uint32_identity(x)
#define htole64(x) __uint64_identity(x)
#define be16toh(x) __builtin_bswap16(x)
#define be32toh(x) __builtin_bswap32(x)
#define be64toh(x) __builtin_bswap64(x)
#define htobe16(x) __builtin_bswap16(x)
#define htobe32(x) __builtin_bswap32(x)
#define htobe64(x) __builtin_bswap64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u16 le16ton(u16 x) { __builtin_bswap16(x); }
u32 le32ton(u32 x) { __builtin_bswap32(x); }
u64 le64ton(u64 x) { __builtin_bswap64(x); }
u16 ntole16(u16 x) { __builtin_bswap16(x); }
u32 ntole32(u32 x) { __builtin_bswap32(x); }
u64 ntole64(u64 x) { __builtin_bswap64(x); }
u16 be16ton(u16 x) { return x; }
u32 be32ton(u32 x) { return x; }
u64 be64ton(u64 x) { return x; }
u16 ntobe16(u16 x) { return x; }
u32 ntobe32(u32 x) { return x; }
u64 ntobe64(u64 x) { return x; }
#define le16toh(x) __builtin_bswap16(x)
#define le32toh(x) __builtin_bswap32(x)
#define le64toh(x) __builtin_bswap64(x)
#define htole16(x) __builtin_bswap16(x)
#define htole32(x) __builtin_bswap32(x)
#define htole64(x) __builtin_bswap64(x)
#define be16toh(x) __uint16_identity(x)
#define be32toh(x) __uint32_identity(x)
#define be64toh(x) __uint64_identity(x)
#define htobe16(x) __uint16_identity(x)
#define htobe32(x) __uint32_identity(x)
#define htobe64(x) __uint64_identity(x)
#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