27 const uint8_t *restrict
const payload,
28 const void *
const end,
29 const uint8_t payload_type
31 switch (payload_type) {
33 case CLOD_NBT_INT8:
return 1;
34 case CLOD_NBT_INT16:
return 2;
35 case CLOD_NBT_INT32:
return 4;
36 case CLOD_NBT_INT64:
return 8;
37 case CLOD_NBT_FLOAT32:
return 4;
38 case CLOD_NBT_FLOAT64:
return 8;
39 case CLOD_NBT_INT8_ARRAY: {
40 if (available(payload, end) < 4)
return 0;
41 const size_t size = (size_t)bei32_dec(payload);
42 if (available(payload, end) < 4 + size)
return 0;
45 case CLOD_NBT_INT32_ARRAY: {
46 if (available(payload, end) < 4)
return 0;
47 const size_t size = (size_t)bei32_dec(payload) * 4;
48 if (available(payload, end) < 4 + size)
return 0;
51 case CLOD_NBT_INT64_ARRAY: {
52 if (available(payload, end) < 4)
return 0;
53 const size_t size = (size_t)bei32_dec(payload) * 8;
54 if (available(payload, end) < 4 + size)
return 0;
57 case CLOD_NBT_STRING: {
58 if (available(payload, end) < 2)
return 0;
59 const size_t size = (size_t)beu16_dec(payload);
60 if (available(payload, end) < 2 + size)
return 0;
64 if (available(payload, end) < 5)
return 0;
65 if (payload[0] == CLOD_NBT_ZERO)
return 5;
66 if (!type_valid(payload[0]))
return 0;
67 const size_t length = (size_t)bei32_dec(payload + 1);
69 for (
size_t i = 0; i < length; i++) {
71 if (elem_size == 0)
return 0;
76 case CLOD_NBT_COMPOUND: {
79 while (available(payload, end) >= size + 3) {
80 if (!type_valid(payload[size]))
break;
81 const size_t name_size = beu16_dec(payload + size + 1);
82 if (available(payload, end) < size + 3 + name_size)
return 0;
86 if (available(payload, end) < size + 1)
return 0;
87 if (payload[size] == CLOD_NBT_ZERO)
return size + 1;
95 if (available(tag, end) < 3)
return 0;
96 if (!type_valid(tag[0]))
return 0;
97 const size_t name_size = beu16_dec(tag + 1);
98 if (available(tag, end) < 3 + name_size)
return 0;
119 const uint8_t *
const restrict payload,
120 const void *
const end,
121 const uint8_t payload_type,
124 switch (payload_type) {
125 case CLOD_NBT_COMPOUND: {
126 if (iter->
payload ==
nullptr) {
128 iter->
tag = (uint8_t*)payload;
134 if (available(iter->
tag, end) < 1)
goto iter_fail;
135 if (iter->
tag[0] == CLOD_NBT_ZERO) {
139 iter->
type = CLOD_NBT_ZERO;
144 if (!tag_payload)
goto iter_fail;
146 if (payload_size == 0)
goto iter_fail;
149 iter->
size = (size_t)(tag_payload - iter->
tag) + payload_size;
153 case CLOD_NBT_LIST: {
154 if (iter->
payload ==
nullptr) {
155 if (available(payload, end) < 5)
goto iter_fail;
157 iter->
payload = (uint8_t*)payload;
158 iter->
type = payload[0];
164 if (iter->
index >= (uint32_t)bei32_dec(payload + 1)) {
168 iter->
type = CLOD_NBT_ZERO;
173 if (payload_size == 0)
goto iter_fail;
174 iter->
size = payload_size;
177 case CLOD_NBT_STRING: {
178 if (iter->
payload ==
nullptr) {
179 if (available(payload, end) < 2)
goto iter_fail;
181 iter->
payload = (uint8_t*)payload;
183 iter->
type = CLOD_NBT_INT8;
189 if (iter->
index >= beu16_dec(payload)) {
193 iter->
type = CLOD_NBT_ZERO;
198 case CLOD_NBT_INT8_ARRAY: {
199 if (iter->
payload ==
nullptr) {
200 if (available(payload, end) < 4)
goto iter_fail;
202 iter->
payload = (uint8_t*)payload;
204 iter->
type = CLOD_NBT_INT8;
210 if (iter->
index >= (uint32_t)bei32_dec(payload)) {
214 iter->
type = CLOD_NBT_ZERO;
219 case CLOD_NBT_INT32_ARRAY: {
220 if (iter->
payload ==
nullptr) {
221 if (available(payload, end) < 4)
goto iter_fail;
223 iter->
payload = (uint8_t*)payload;
225 iter->
type = CLOD_NBT_INT32;
231 if (iter->
index >= (uint32_t)bei32_dec(payload)) {
235 iter->
type = CLOD_NBT_ZERO;
240 case CLOD_NBT_INT64_ARRAY: {
241 if (iter->
payload ==
nullptr) {
242 if (available(payload, end) < 4)
goto iter_fail;
244 iter->
payload = (uint8_t*)payload;
246 iter->
type = CLOD_NBT_INT64;
252 if (iter->
index >= (uint32_t)bei32_dec(payload)) {
256 iter->
type = CLOD_NBT_ZERO;
261 default:
return false;
282 uint8_t *restrict compound,
288 if (!type_valid(
type))
return nullptr;
289 const size_t elem_size = 3 + (size_t)name.
len + type_zero_size(
type);
291 *free -= (ptrdiff_t)elem_size;
300 if (!iter.
tag)
return nullptr;
301 *free -= (ptrdiff_t)elem_size;
307 memmove(iter.
tag + elem_size, iter.
tag, available(iter.
tag, *end) - elem_size);
310 beu16_enc(iter.
tag + 1, (uint16_t)name.
len);
311 memcpy(iter.
tag + 3, name.
ptr, (
size_t)name.
len);
312 memset(iter.
tag + 3 + name.
len, 0, type_zero_size(
type));
314 *end = *(uint8_t**)end + elem_size;
337 uint8_t *restrict list,
341 const uint32_t length
344 *free -= (ptrdiff_t)(length * type_zero_size(
type));
347 if (available(list, *end) < 5)
return false;
349 if (list[0] !=
type) {
351 const size_t new_size = 5 + length * type_zero_size(
type);
352 if (old_size == 0)
return false;
354 const ptrdiff_t delta = (ptrdiff_t)new_size - (ptrdiff_t)old_size;
356 if (*free < 0)
return false;
358 memmove(list + new_size, list + old_size, available(list, *end) - old_size);
359 memset(list, 0, new_size);
361 bei32_enc(list + 1, (int32_t)length);
362 *end = *(uint8_t**)end + delta;
366 const uint32_t old_length = (uint32_t)bei32_dec(list + 1);
368 if (old_length < length) {
370 const size_t append_size = type_zero_size(list[0]) * (length - old_length);
372 *free -= (ptrdiff_t)append_size;
373 if (*free < 0)
return false;
375 memmove(list + old_size + append_size, list + old_size, available(list, *end) - old_size - append_size);
376 memset(list + old_size, 0, append_size);
377 bei32_enc(list + 1, (int32_t)length);
379 *end = *(uint8_t**)end + append_size;
383 if (old_length > length) {
385 uint8_t *truncate =
nullptr;
389 if (!iter.
tag || !truncate)
return false;
391 memmove(truncate, iter.
tag, available(iter.
tag, *end));
392 bei32_enc(list + 1, (int32_t)length);
393 *free += iter.
tag - truncate;
394 *end = *(uint8_t**)end - (iter.
tag - truncate);
uint8_t * clod_nbt_compound_add(uint8_t *restrict compound, const void **end, ptrdiff_t *free, const struct clod_string name, const uint8_t type)
bool clod_nbt_list_resize(uint8_t *restrict list, const uint8_t **end, ptrdiff_t *free, uint8_t type, const uint32_t length)