diff options
author | Freya Murphy <freya@freyacat.org> | 2023-12-14 18:08:16 -0500 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2023-12-14 18:08:16 -0500 |
commit | 00c88659104ce423959151ff6f3f96f6537a6d68 (patch) | |
tree | c2745a95c2b7f15f69f8bfcaa85e0b12626f6142 /src | |
download | nbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.tar.gz nbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.tar.bz2 nbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.zip |
testing
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.c | 44 | ||||
-rw-r--r-- | src/lib.h | 12 | ||||
-rw-r--r-- | src/main.c | 15 | ||||
-rw-r--r-- | src/stream.c | 98 | ||||
-rw-r--r-- | src/stream.h | 22 | ||||
-rw-r--r-- | src/tag.c | 195 | ||||
-rw-r--r-- | src/tag.h | 73 |
7 files changed, 459 insertions, 0 deletions
diff --git a/src/lib.c b/src/lib.c new file mode 100644 index 0000000..7f077ba --- /dev/null +++ b/src/lib.c @@ -0,0 +1,44 @@ +#include "lib.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +__attribute__((__noreturn__)) +static void die() { + exit(1); +} + +void error_and_die(char *format, ...) { + va_list list; + va_start(list, format); + + vfprintf(stderr, format, list); + + die(); +} + +__attribute__((__noreturn__, format(printf, 1, 2))) +void perror_and_die(char *format, ...) { + va_list list; + va_start(list, format); + + vfprintf(stderr, format, list); + perror(": "); + + die(); +} + +void *xalloc(size_t amount) { + void *res = malloc(amount); + if (res == NULL) + error_and_die("failed to allocate memory"); + return res; +} + +void *xrealloc(void *ptr, size_t amount) { + void *res = realloc(ptr, amount); + if (res == NULL) + error_and_die("failed to allocate memory"); + return res; +} diff --git a/src/lib.h b/src/lib.h new file mode 100644 index 0000000..c007187 --- /dev/null +++ b/src/lib.h @@ -0,0 +1,12 @@ +#pragma once + +#include <stddef.h> + +__attribute__((__noreturn__, format(printf, 1, 2))) +void error_and_die(char *format, ...); + +__attribute__((__noreturn__, format(printf, 1, 2))) +void perror_and_die(char *format, ...); + +void *xalloc(size_t amount); +void *xrealloc(void *ptr, size_t amount); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..077085c --- /dev/null +++ b/src/main.c @@ -0,0 +1,15 @@ +#include "tag.h" +#include "lib.h" + +int main (int argc, char** argv) { + + stream_t stream = stream_open(argv[1], "rb"); + + tag_t tag; + tag_read(&tag, &stream, true); + + if (tag.type != TAG_COMPOUND) + error_and_die("root tag is not of type compound"); + + stream_close(&stream); +} diff --git a/src/stream.c b/src/stream.c new file mode 100644 index 0000000..1993df6 --- /dev/null +++ b/src/stream.c @@ -0,0 +1,98 @@ +#include "stream.h" +#include "lib.h" + +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +stream_t stream_open(char *path, char* mode) { + stream_t stream; + + if (strcmp("-", path) == 0) { + stream.__file = stdin; + stream.__alloc = false; + } + + stream.__file = fopen(path, mode); + stream.__alloc = true; + + if (stream.__file == NULL) { + perror_and_die("cannot read '%s'", path); + }; + + return stream; +} + +void stream_close(stream_t *stream) { + if (stream->__alloc) + fclose(stream->__file); +} + +bool stream_read(stream_t *stream, void *res, size_t amount) { + size_t read; + read = fread(res, 1, amount, stream->__file); + + if (read == 0) { + if (feof(stream->__file)) + return false; + else + perror_and_die("cannot read open stream"); + } + + return true; +} + +bool stream_read_i8(stream_t *stream, int8_t *res) { + if (stream_read(stream, res, 1) == false) + return false; + return true; +} + +bool stream_read_i16(stream_t *stream, int16_t *res) { + if (stream_read(stream, res, 2) == false) + return false; + *res = ntohs(*res); + return true; +} + +bool stream_read_i32(stream_t *stream, int32_t *res) { + if (stream_read(stream, res, 4) == false) + return false; + *res = ntohl(*res); + return true; +} + +static uint64_t ntohll(uint64_t ll) { + if (htons(20) == 20) + return ll; + + union { uint64_t ll; uint8_t c[8]; } out = {0}; + union { uint64_t ll; uint8_t c[8]; } in = {ll}; + + for (int i = 0; i < 8; i++) + out.c[7-i] = in.c[i]; + + return out.ll; +} + +bool stream_read_i64(stream_t *stream, int64_t *res) { + if (stream_read(stream, res, 8) == false) + return false; + *res = ntohll(*res); + return true; +} + +bool stream_read_u16(stream_t *stream, uint16_t *res) { + if (stream_read(stream, res, 2) == false) + return false; + *res = ntohs(*res); + return true; +} + +bool stream_read_u32(stream_t *stream, uint32_t *res) { + if (stream_read(stream, res, 4) == false) + return false; + *res = ntohl(*res); + return true; +} diff --git a/src/stream.h b/src/stream.h new file mode 100644 index 0000000..e9fd920 --- /dev/null +++ b/src/stream.h @@ -0,0 +1,22 @@ +#pragma once + +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> + +typedef struct { + FILE *__file; + bool __alloc; +} stream_t; + +stream_t stream_open(char *path, char* mode); +void stream_close(stream_t *stream); +bool stream_read(stream_t *stream, void *res, size_t amount); + +bool stream_read_i8(stream_t *stream, int8_t *res); +bool stream_read_i16(stream_t *stream, int16_t *res); +bool stream_read_i32(stream_t *stream, int32_t *res); +bool stream_read_i64(stream_t *stream, int64_t *res); + +bool stream_read_u16(stream_t *stream, uint16_t *res); +bool stream_read_u32(stream_t *stream, uint32_t *res); diff --git a/src/tag.c b/src/tag.c new file mode 100644 index 0000000..ded1c07 --- /dev/null +++ b/src/tag.c @@ -0,0 +1,195 @@ +#include "tag.h" +#include "lib.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +bool tag_read_header(tag_t *tag, stream_t *stream, bool named) { + bool ok = true; + + if (stream_read_i8(stream, &tag->type) == false) + return false; + + if (tag->type == TAG_END) + named = false; + + if (named) { + if (stream_read_u16(stream, &tag->name_len) == false) + return false; + } else { + tag->name_len = 0; + } + + if (tag->name_len < 1) { + tag->name = ""; + } else { + tag->name = xalloc(tag->name_len); + ok = stream_read(stream, &tag->name, tag->name_len); + } + + if (!ok) + return false; + + return true; +} + + +static bool tag_read_byte_array(tagdata_t *data, stream_t *stream) { + if (stream_read_i32(stream, &data->b_arr.size) == false) + return false; + data->b_arr.data = xalloc(data->b_arr.size * sizeof(int8_t)); + for (int32_t i = 0; i < data->b_arr.size; i++) + if (stream_read_i8(stream, &data->b_arr.data[i]) == false) + return false; + return true; +} + +static bool tag_read_int_array(tagdata_t *data, stream_t *stream) { + if (stream_read_i32(stream, &data->i_arr.size) == false) + return false; + data->i_arr.data = xalloc(data->i_arr.size * sizeof(int32_t)); + for (int32_t i = 0; i < data->i_arr.size; i++) + if (stream_read_i32(stream, &data->i_arr.data[i]) == false) + return false; + return true; +} + +static bool tag_read_long_array(tagdata_t *data, stream_t *stream) { + if (stream_read_i32(stream, &data->l_arr.size) == false) + return false; + data->l_arr.data = xalloc(data->l_arr.size * sizeof(int64_t)); + for (int32_t i = 0; i < data->l_arr.size; i++) + if (stream_read_i64(stream, &data->l_arr.data[i]) == false) + return false; + return true; +} + +static bool tag_read_string(tagdata_t *data, stream_t *stream) { + if (stream_read_u16(stream, &data->string.size) == false) + return false; + data->string.data = xalloc(data->string.size); + if (stream_read(stream, &data->string.data, data->string.size) == false) + return false; + return true; +} + +static bool tag_read_list(tagdata_t *data, stream_t *stream) { + if (stream_read_i8(stream, &data->list.type) == false) + return false; + if (stream_read_i32(stream, &data->list.size) == false) + return false; + if (data->list.size <= 0) { + data->list.tags = NULL; + return true; + } else if (data->list.type == 0) { + // tag end is not allowed to be used with non empty list + return false; + } + data->list.tags = xalloc(data->list.size * sizeof(tag_t)); + for (int32_t i = 0; i < data->list.size; i++) { + tag_t tag; + tag.type = data->list.type; + tag.name = ""; + tag.name_len = 0; + if (tag_read_data(&tag, stream) == false) + return false; + data->list.tags[i] = tag; + } + return true; +} + +static bool tag_read_compound(tagdata_t *data, stream_t *stream) { + printf("entering tag read compound\n"); + int32_t size = 0; + int32_t capacity = 8; + tag_t *tags = xalloc(capacity * sizeof(tag_t)); + + while (1) { + + tag_t tag; + + if (tag_read_header(&tag, stream, true) == false) + return false; + + if (tag.type == TAG_END) + break; + + if (tag_read_data(&tag, stream) == false) + return false; + + if (size == capacity) { + capacity *= 2; + tags = xrealloc(tags, capacity * sizeof(tag_t)); + } + + tags[size++] = tag; + } + + data->compound.size = size; + data->compound.tags = xalloc(size * sizeof(tag_t)); + memcpy(data->compound.tags, tags, size * sizeof(tag_t)); + free(tags); + + printf("returning from tag read compound\n"); + return true; +} + +bool tag_read_data(tag_t *tag, stream_t *stream) { + printf("READING THE FUCKING DATA!!!!\n"); + void *p = NULL; + printf("%p\n", (void*)&p); + bool ok = true; + + switch (tag->type) { + case TAG_END: + // tag has no data + break; + case TAG_BYTE: + ok = stream_read_i8(stream, &tag->data.b); + break; + case TAG_SHORT: + ok = stream_read_i16(stream, &tag->data.s); + break; + case TAG_FLOAT: + case TAG_INT: + ok = stream_read_i32(stream, &tag->data.i); + break; + case TAG_DOUBLE: + case TAG_LONG: + ok = stream_read_i64(stream, &tag->data.l); + break; + case TAG_BYTE_ARRAY: + ok = tag_read_byte_array(&tag->data, stream); + break; + case TAG_STRING: + ok = tag_read_string(&tag->data, stream); + break; + case TAG_LIST: + ok = tag_read_list(&tag->data, stream); + break; + case TAG_COMPOUND: + printf("TAG OWO TAG OWO\n"); + ok = tag_read_compound(&tag->data, stream); + printf("TAG OWO TAG OWO PART 2\n"); + break; + case TAG_INT_ARRAY: + ok = tag_read_int_array(&tag->data, stream); + break; + case TAG_LONG_ARRAY: + ok = tag_read_long_array(&tag->data, stream); + break; + break; + }; + printf("read tag: %d\n", tag->type); + return ok; +} + +bool tag_read(tag_t *tag, stream_t *stream, bool named) { + memset(tag, 0, sizeof(tag_t)); + if (tag_read_header(tag, stream, named) == false) + return false; + if (tag_read_data(tag, stream) == false) + return false; + return true; +} + diff --git a/src/tag.h b/src/tag.h new file mode 100644 index 0000000..7fd0b4e --- /dev/null +++ b/src/tag.h @@ -0,0 +1,73 @@ +#pragma once + +#include "stream.h" + +#include <stdint.h> +#include <stdbool.h> +#include <arpa/inet.h> +#include <string.h> +#include <unistd.h> + +typedef enum: int8_t { + TAG_END = 0, + TAG_BYTE = 1, + TAG_SHORT = 2, + TAG_INT = 3, + TAG_LONG = 4, + TAG_FLOAT = 5, + TAG_DOUBLE = 6, + TAG_BYTE_ARRAY = 7, + TAG_STRING = 8, + TAG_LIST = 9, + TAG_COMPOUND = 10, + TAG_INT_ARRAY = 11, + TAG_LONG_ARRAY = 12 +} tagtype_t ; + +struct tag_t; + +typedef union { + int8_t b; + int16_t s; + int32_t i; + int64_t l; + float f; + double d; + struct { + int32_t size; + int8_t *data; + } b_arr; + struct { + uint16_t size; + char *data; + } string; + struct { + tagtype_t type; + int32_t size; + struct tag_t *tags; + } list; + struct { + int32_t size; + struct tag_t *tags; + } compound; + struct { + int32_t size; + int32_t *data; + } i_arr; + struct { + int32_t size; + int64_t *data; + } l_arr; +} tagdata_t; + +typedef struct tag_t { + tagtype_t type; + tagdata_t data; + uint16_t name_len; + char *name; +} tag_t; + +bool tag_read_header(tag_t *tag, stream_t *stream, bool named); +bool tag_read_data(tag_t *tag, stream_t *stream); +bool tag_read(tag_t *tag, stream_t *stream, bool named); + |