testing
This commit is contained in:
commit
00c8865910
9 changed files with 486 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bin
|
26
Makefile
Normal file
26
Makefile
Normal file
|
@ -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)
|
44
src/lib.c
Normal file
44
src/lib.c
Normal file
|
@ -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;
|
||||||
|
}
|
12
src/lib.h
Normal file
12
src/lib.h
Normal file
|
@ -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);
|
15
src/main.c
Normal file
15
src/main.c
Normal file
|
@ -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);
|
||||||
|
}
|
98
src/stream.c
Normal file
98
src/stream.c
Normal file
|
@ -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;
|
||||||
|
}
|
22
src/stream.h
Normal file
22
src/stream.h
Normal file
|
@ -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);
|
195
src/tag.c
Normal file
195
src/tag.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
73
src/tag.h
Normal file
73
src/tag.h
Normal file
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue