commit 00c88659104ce423959151ff6f3f96f6537a6d68 Author: Freya Murphy Date: Thu Dec 14 18:08:16 2023 -0500 testing diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..25b86d2 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +BIN = bin +OUT = $(BIN)/out + +SRC = $(shell find src -type f -name "*.c") +OBJ = $(patsubst %.c,$(BIN)/%.o, $(SRC)) + +CCFLAGS = -Isrc -std=c2x -Wall -Wextra -pedantic -O0 -g +LDFLAGS = + +CC = gcc +LD = gcc + +.PHONY: build + +build: $(OUT) + +$(OBJ): $(BIN)/%.o : %.c + @mkdir -p $(@D) + $(CC) -c $(CCFLAGS) -o $@ $< + +$(OUT): $(OBJ) $(ASM_OBJ) + @mkdir -p $(@D) + $(LD) -o $(OUT) $(OBJ) $(LDFLAGS) + +clean: + rm -fr $(BIN) 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 +#include +#include + +__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 + +__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 +#include +#include +#include + +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 +#include +#include + +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 +#include +#include + +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 +#include +#include +#include +#include + +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); +