From 962f5efdf1af9f07395c28df7a2181733e3e5125 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Sat, 3 Feb 2024 16:58:23 -0600 Subject: add lists --- src/nbt/nbt.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/nbt/nbt.c (limited to 'src/nbt/nbt.c') diff --git a/src/nbt/nbt.c b/src/nbt/nbt.c new file mode 100644 index 0000000..5948bce --- /dev/null +++ b/src/nbt/nbt.c @@ -0,0 +1,207 @@ +#include "../nbt.internal.h" +#include "nbt.h" +#include "src/nbt.internal.h" + +#include +#include +#include + +nbt_tag_t *nbt__new_val(nbt_type_t type) +{ + nbt_tag_t *tag = calloc(1, sizeof(nbt_tag_t)); + if (!tag) return NULL; + + tag->ref = 1; + tag->type = type; + return tag; +} + +nbt_tag_t *nbt_byte(nbt_byte_t b) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_BYTE); + if (!tag) return NULL; + + tag->value.nbt_byte = b; + return tag; +} + +nbt_tag_t *nbt_short(nbt_short_t s) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_SHORT); + if (!tag) return NULL; + + tag->value.nbt_short = s; + return tag; +} + +nbt_tag_t *nbt_int(nbt_int_t i) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_INT); + if (!tag) return NULL; + + tag->value.nbt_int = i; + return tag; +} + +nbt_tag_t *nbt_long(nbt_long_t l) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_LONG); + if (!tag) return NULL; + + tag->value.nbt_long = l; + return tag; +} + +nbt_tag_t *nbt_float(nbt_float_t f) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_FLOAT); + if (!tag) return NULL; + + tag->value.nbt_float = f; + return tag; +} + +nbt_tag_t *nbt_double(nbt_double_t d) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_DOUBLE); + if (!tag) return NULL; + + tag->value.nbt_byte = d; + return tag; +} + +#define NBT__BUFCOPY_BODY(_tl, _tu, _te, _inbuf, _inlen) \ +{ \ + static nbt_tag_t nbt__single_empty_ ## _tl = { \ + .ref = SIZE_MAX, \ + .type = NBT_TAG_ ## _tu, \ + .value = { .nbt_ ## _tl = { .len = 0, .data = NULL } } \ + }; \ + \ + if (!(_inlen)) return &nbt__single_empty_ ## _tl; \ + \ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_ ## _tu); \ + if (!tag) return NULL; \ + \ + _te *buf = calloc(_inlen, sizeof(_te)); \ + if (!buf) goto cleanup; \ + \ + memcpy(buf, _inbuf, (_inlen) * sizeof(_te)); \ + tag->value.nbt_ ## _tl.len = _inlen; \ + tag->value.nbt_ ## _tl.data = buf; \ + \ + return tag; \ + \ +cleanup: \ + free(tag); \ + return NULL; \ +} + +nbt_tag_t *nbt_byte_array(const nbt_byte_t *bytes, nbt_size_t length) + NBT__BUFCOPY_BODY(byte_array, BYTE_ARRAY, nbt_byte_t, bytes, length) + +nbt_tag_t *nbt_string(const char *c_str) +{ + return nbt_stringn(c_str, strlen(c_str)); +} + +nbt_tag_t *nbt_stringn(const char *c_str, nbt_size_t length) + NBT__BUFCOPY_BODY(string, STRING, char, c_str, length) + +nbt_tag_t *nbt_list(void) +{ + return nbt_listn(0); +} + +nbt_tag_t *nbt_listn(nbt_size_t cap) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_LIST); + if (!tag) return NULL; + if (!cap) cap = 16; + + tag->value.nbt_list.len = 0; + tag->value.nbt_list.cap = cap; + + nbt_tag_t **tags = calloc(cap, sizeof(nbt_tag_t *)); + if (!tags) goto cleanup; + + tag->value.nbt_list.ptags = tags; + + return tag; + +cleanup: + free(tag); + return NULL; +} + +nbt_tag_t *nbt_compound(void) +{ + return nbt_compoundn(0); +} + +nbt_tag_t *nbt_compoundn(nbt_size_t cap) +{ + nbt_tag_t *tag = nbt__new_val(NBT_TAG_COMPOUND); + if (!tag) return NULL; + + tag->value.nbt_compound.hash = nbt__ht_create(cap); + if (!tag->value.nbt_compound.hash) goto cleanup; + + return tag; + +cleanup: + free(tag); + return NULL; +} + +nbt_tag_t *nbt_int_array(const nbt_int_t *ints, nbt_size_t length) + NBT__BUFCOPY_BODY(int_array, INT_ARRAY, nbt_int_t, ints, length) + +nbt_tag_t *nbt_long_array(const nbt_long_t *longs, nbt_size_t length) + NBT__BUFCOPY_BODY(long_array, LONG_ARRAY, nbt_long_t, longs, length); + +void nbt_decref(nbt_tag_t *tag) +{ + if (!tag) return; + if (tag->ref == SIZE_MAX) return; + + --tag->ref; + if (!tag->ref) nbt__tag_free(tag); +} + +nbt_tag_t *nbt_incref(nbt_tag_t *tag) +{ + if (tag->ref != SIZE_MAX) ++tag->ref; + return tag; +} + +void nbt__tag_free(nbt_tag_t *tag) +{ + if (!tag) return; + switch (tag->type) { + case NBT_TAG_BYTE_ARRAY: + free(tag->value.nbt_byte_array.data); + break; + case NBT_TAG_STRING: + free(tag->value.nbt_string.data); + break; + case NBT_TAG_INT_ARRAY: + free(tag->value.nbt_int_array.data); + break; + case NBT_TAG_LONG_ARRAY: + free(tag->value.nbt_long_array.data); + break; + case NBT_TAG_LIST: + nbt_list_clear(tag); + free(tag->value.nbt_list.ptags); + break; + case NBT_TAG_COMPOUND: + nbt_compound_clear(tag); + nbt__ht_free(tag->value.nbt_compound.hash); + break; + default: + break; + } + + free(tag); +} -- cgit v1.2.3-70-g09d2