summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2023-12-14 18:08:16 -0500
committerFreya Murphy <freya@freyacat.org>2023-12-14 18:08:16 -0500
commit00c88659104ce423959151ff6f3f96f6537a6d68 (patch)
treec2745a95c2b7f15f69f8bfcaa85e0b12626f6142 /src
downloadnbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.tar.gz
nbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.tar.bz2
nbtvis-00c88659104ce423959151ff6f3f96f6537a6d68.zip
testing
Diffstat (limited to 'src')
-rw-r--r--src/lib.c44
-rw-r--r--src/lib.h12
-rw-r--r--src/main.c15
-rw-r--r--src/stream.c98
-rw-r--r--src/stream.h22
-rw-r--r--src/tag.c195
-rw-r--r--src/tag.h73
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);
+