From 3d10d02620a0e587d765f6042ab05f530b201c39 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Thu, 14 Dec 2023 19:38:55 -0500 Subject: [PATCH] initial stable --- Makefile | 8 ++++ src/main.c | 13 +++++- src/stream.c | 3 +- src/tag.h | 2 +- src/tag_print.c | 95 +++++++++++++++++++++++++++++++++++++++ src/{tag.c => tag_read.c} | 29 +++++++----- 6 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 src/tag_print.c rename src/{tag.c => tag_read.c} (91%) diff --git a/Makefile b/Makefile index 25b86d2..9613a70 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ BIN = bin OUT = $(BIN)/out +INS = /usr/local/bin/nbtvis SRC = $(shell find src -type f -name "*.c") OBJ = $(patsubst %.c,$(BIN)/%.o, $(SRC)) @@ -22,5 +23,12 @@ $(OUT): $(OBJ) $(ASM_OBJ) @mkdir -p $(@D) $(LD) -o $(OUT) $(OBJ) $(LDFLAGS) +run: + $(OUT) + +install: + cp $(OUT) $(INS) + chown root: $(INS) + clean: rm -fr $(BIN) diff --git a/src/main.c b/src/main.c index 077085c..fec6d06 100644 --- a/src/main.c +++ b/src/main.c @@ -1,15 +1,24 @@ #include "tag.h" #include "lib.h" +#include int main (int argc, char** argv) { + if (argc != 2) { + printf("usage: nbtvis file.nbt\n"); + return 0; + } + stream_t stream = stream_open(argv[1], "rb"); tag_t tag; - tag_read(&tag, &stream, true); + if (tag_read(&tag, &stream, true) == false) + error_and_die("failed to read tag\n"); if (tag.type != TAG_COMPOUND) - error_and_die("root tag is not of type compound"); + error_and_die("root tag is not of type compound\n"); + + tag_print(&tag); stream_close(&stream); } diff --git a/src/stream.c b/src/stream.c index 1993df6..622fafa 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1,6 +1,7 @@ #include "stream.h" #include "lib.h" +#include #include #include #include @@ -34,7 +35,7 @@ bool stream_read(stream_t *stream, void *res, size_t amount) { read = fread(res, 1, amount, stream->__file); if (read == 0) { - if (feof(stream->__file)) + if (feof(stream->__file) || errno == 0) return false; else perror_and_die("cannot read open stream"); diff --git a/src/tag.h b/src/tag.h index 7fd0b4e..93eff64 100644 --- a/src/tag.h +++ b/src/tag.h @@ -70,4 +70,4 @@ typedef struct 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); - +void tag_print(const tag_t *tag); diff --git a/src/tag_print.c b/src/tag_print.c new file mode 100644 index 0000000..9612698 --- /dev/null +++ b/src/tag_print.c @@ -0,0 +1,95 @@ +#include "tag.h" +#include +#include + +__attribute__((format(printf, 2, 3))) +static void printi(int depth, const char *format, ...) { + for (int i = 0; i < depth; i++) + printf("\t"); + va_list list; + va_start(list, format); + vprintf(format, list); +} + +static void tag_print_impl(const tag_t *tag, int depth); + +static void tag_print_data(const tag_t *tag, int depth) { + switch (tag->type) { + case TAG_BYTE: + printf("%hhd", tag->data.b); + break; + case TAG_SHORT: + printf("%hd", tag->data.s); + break; + case TAG_INT: + printf("%d", tag->data.i); + break; + case TAG_LONG: + printf("%ld", tag->data.l); + break; + case TAG_FLOAT: + printf("%f", tag->data.f); + break; + case TAG_DOUBLE: + printf("%lf", tag->data.d); + break; + case TAG_BYTE_ARRAY: + printf("["); + for (int32_t i = 0; i < tag->data.b_arr.size; i++) + printf("%hhd,", tag->data.b_arr.data[i]); + printf("\b]"); + break; + case TAG_STRING: + if (tag->data.string.size > 1) + printf("\"%.*s\"", tag->data.string.size, tag->data.string.data); + else + printf("\"\""); + break; + case TAG_LIST: + printf("[\n"); + for (int32_t i = 0; i < tag->data.list.size; i++) { + if (i != 0) printf(",\n"); + tag_print_impl(&tag->data.list.tags[i], depth + 1); + } + printf("\n"); + printi(depth, "]"); + break; + case TAG_COMPOUND: + printf("{\n"); + for (int32_t i = 0; i < tag->data.compound.size; i++) { + if (i != 0) printf(",\n"); + tag_print_impl(&tag->data.compound.tags[i], depth + 1); + } + printf("\n"); + printi(depth, "}"); + break; + case TAG_INT_ARRAY: + printi(depth, "["); + for (int32_t i = 0; i < tag->data.i_arr.size; i++) + printf("%d,", tag->data.i_arr.data[i]); + printf("\b]"); + break; + case TAG_LONG_ARRAY: + printf("["); + for (int32_t i = 0; i < tag->data.l_arr.size; i++) + printf("%ld,", tag->data.l_arr.data[i]); + printf("\b]"); + break; + case TAG_END: + break; + } +} + +static void tag_print_impl(const tag_t *tag, int depth) { + if (tag->name_len > 0) { + printi(depth, "\"%.*s\":\t", tag->name_len, tag->name); + } else { + for (int i = 0; i < depth; i++) printf("\t"); + } + tag_print_data(tag, depth); +} + +void tag_print(const tag_t *tag) { + tag_print_impl(tag, 0); + printf("\n"); +} diff --git a/src/tag.c b/src/tag_read.c similarity index 91% rename from src/tag.c rename to src/tag_read.c index ded1c07..5f43e7c 100644 --- a/src/tag.c +++ b/src/tag_read.c @@ -24,7 +24,7 @@ bool tag_read_header(tag_t *tag, stream_t *stream, bool named) { tag->name = ""; } else { tag->name = xalloc(tag->name_len); - ok = stream_read(stream, &tag->name, tag->name_len); + ok = stream_read(stream, tag->name, tag->name_len); } if (!ok) @@ -37,6 +37,10 @@ bool tag_read_header(tag_t *tag, stream_t *stream, bool named) { static bool tag_read_byte_array(tagdata_t *data, stream_t *stream) { if (stream_read_i32(stream, &data->b_arr.size) == false) return false; + if (data->b_arr.size == 0) { + data->b_arr.data = NULL; + return true; + } 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) @@ -47,6 +51,10 @@ static bool tag_read_byte_array(tagdata_t *data, stream_t *stream) { static bool tag_read_int_array(tagdata_t *data, stream_t *stream) { if (stream_read_i32(stream, &data->i_arr.size) == false) return false; + if (data->i_arr.size == 0) { + data->i_arr.data = NULL; + return true; + } 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) @@ -57,6 +65,10 @@ static bool tag_read_int_array(tagdata_t *data, stream_t *stream) { static bool tag_read_long_array(tagdata_t *data, stream_t *stream) { if (stream_read_i32(stream, &data->l_arr.size) == false) return false; + if (data->l_arr.size == 0) { + data->l_arr.data = NULL; + return true; + } 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) @@ -67,8 +79,12 @@ static bool tag_read_long_array(tagdata_t *data, stream_t *stream) { static bool tag_read_string(tagdata_t *data, stream_t *stream) { if (stream_read_u16(stream, &data->string.size) == false) return false; + if (data->string.size < 1) { + data->string.data = NULL; + return true; + } data->string.data = xalloc(data->string.size); - if (stream_read(stream, &data->string.data, data->string.size) == false) + if (stream_read(stream, data->string.data, data->string.size) == false) return false; return true; } @@ -99,7 +115,6 @@ static bool tag_read_list(tagdata_t *data, stream_t *stream) { } 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)); @@ -130,14 +145,9 @@ static bool tag_read_compound(tagdata_t *data, stream_t *stream) { 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) { @@ -168,9 +178,7 @@ bool tag_read_data(tag_t *tag, stream_t *stream) { 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); @@ -180,7 +188,6 @@ bool tag_read_data(tag_t *tag, stream_t *stream) { break; break; }; - printf("read tag: %d\n", tag->type); return ok; }