From a13c6ecb3ace102d76a7403de0a7f68b05334252 Mon Sep 17 00:00:00 2001 From: Felix Van der Jeugt Date: Wed, 2 Nov 2022 00:05:01 +0100 Subject: [PATCH] add json printing and parsing (of strings) --- json.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++ json.h | 21 +++++++ makefile | 3 +- planarbot.c | 8 ++- sortedmap.c | 166 ++++++++++++++++++++++++++++------------------------ sortedmap.h | 10 +++- 6 files changed, 277 insertions(+), 81 deletions(-) create mode 100644 json.c create mode 100644 json.h diff --git a/json.c b/json.c new file mode 100644 index 0000000..92ad903 --- /dev/null +++ b/json.c @@ -0,0 +1,150 @@ +#include +#include +#include + +#include "json.h" +#include "sortedmap.h" +#include "arraylist.h" + +/* TODO */ +Json * parse_map(FILE *stream) { return NULL; /* TODO */ } +Json * parse_list(FILE *stream) { return NULL; /* TODO */ } + +Json * parse_string(FILE *stream) { + int i = 0, cap = 10; + char * buffer = calloc(cap, sizeof(char)); + char c; + int escaped = 0; + Json * json; + while ((c = getc(stream)) != EOF) { + printf("char: %c, buffer: %s, i: %d\n", c, buffer, i); + switch (c) { + case '\\': + escaped = 1; + break; + case '"': + if (!escaped) { + json = malloc(sizeof(Json)); + json->type = STRING; + json->value.string = calloc(i + 1, sizeof(char)); + memcpy(json->value.string, buffer, i); + free(buffer); + return json; + } + default: + if (i == cap) { + cap *= 2; + buffer = realloc(buffer, cap * sizeof(char)); + } + buffer[i++] = c; + } + } + return NULL; +} + +Json * parse_true(FILE *stream) { return NULL; /* TODO */ } +Json * parse_false(FILE *stream) { return NULL; /* TODO */ } +Json * parse_number(FILE *stream, char first) { return NULL; /* TODO */ } + +Json * json_parse(FILE *stream) { + char c; + Json * json = NULL; + while ((c = getc(stream)) != EOF) { + switch (c) { + case '{': + return parse_map(stream); + case '[': + return parse_list(stream); + case '"': + return parse_string(stream); + case 't': + return parse_true(stream); + case 'f': + return parse_false(stream); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return parse_number(stream, c); + case ' ': + case '\n': + case '\t': + break; /* whitespace */ + default: + fprintf(stderr, "encountered char: '%c'", c); + } + } + return json; +} + +struct printacc { + FILE *stream; + int index; +}; + +void * json_print_map(void * voidacc, char *key, void *value) { + struct printacc *acc = (struct printacc *) voidacc; + + return acc; +} + +void json_print(Json *this, FILE *stream) { + int i; + struct printacc acc = { NULL, 0 }; + switch (this->type) { + case BOOLEAN: + fprintf(stream, this->value.boolean == 0 ? "false" : "true"); + break; + case STRING: + fprintf(stream, "\"%s\"", this->value.string); + break; + case NUMBER: + fprintf(stream, "%f", this->value.number); + break; + case LIST: + fprintf(stream, "["); + if (this->value.list->size > 0) { + json_print((Json *) get_list(this->value.list, 0), stream); + for(i = 1; i < this->value.list->size; i++) { + fprintf(stream, ", "); + json_print((Json *) get_list(this->value.list, i), stream); + } + } + fprintf(stream, "]"); + break; + case MAP: + fprintf(stream, "{"); + acc.stream = stream; + fold_map((void *) &acc, this->value.map, json_print_map); + fprintf(stream, "}"); + break; + } +} + +void json_free(Json *this) { + switch (this->type) { + case BOOLEAN: + /* TODO */ + break; + case STRING: + /* TODO */ + free(this->value.string); + break; + case NUMBER: + /* TODO */ + break; + case LIST: + /* TODO */ + break; + case MAP: + /* TODO */ + break; + } + free(this); +} diff --git a/json.h b/json.h new file mode 100644 index 0000000..c868ac8 --- /dev/null +++ b/json.h @@ -0,0 +1,21 @@ +#ifndef JSON_HEADER +#define JSON_HEADER +#include "sortedmap.h" +#include "arraylist.h" +enum jsontype { BOOLEAN, STRING, NUMBER, LIST, MAP }; + +typedef struct json { + enum jsontype type; + union { + int boolean; + char * string; + double number; + ArrayList * list; + SortedMap * map; + } value; +} Json; + +Json * json_parse(FILE *stream); +void json_print(Json *this, FILE *stream); +void json_free(Json *this); +#endif diff --git a/makefile b/makefile index 8567105..c5b5bbf 100644 --- a/makefile +++ b/makefile @@ -3,10 +3,11 @@ CFLAGS += -g -Wall -Werror -pedantic -ansi all: planarbot inputfile valgrind ./planarbot < inputfile -planarbot: planarbot.o arraylist.o sortedmap.o +planarbot: planarbot.o arraylist.o sortedmap.o json.o planarbot.o: arraylist.h arraylist.o: arraylist.h sortedmap.o: sortedmap.h +json.o: json.h arraylist.h sortedmap.h clean: rm -f *.o planarbot diff --git a/planarbot.c b/planarbot.c index a752384..abd2bbc 100644 --- a/planarbot.c +++ b/planarbot.c @@ -4,9 +4,11 @@ #include "arraylist.h" #include "sortedmap.h" +#include "json.h" #define BUF 20 +/* struct LIST { ArrayList * (*init)(); void (*add)(ArrayList *, void *); @@ -14,6 +16,7 @@ struct LIST { void (*freeitems)(ArrayList *); void (*free)(ArrayList *); } LIST = { list, add_list, get_list, free_listitems, free_list }; +*/ typedef struct planet { int ship_count; @@ -59,7 +62,7 @@ int read_planet(ArrayList *planets) { sscanf(owner, "%d", &planet->owner); } print_planet(planet); - LIST.add(planets, planet); + add_list(planets, planet); return 0; } @@ -107,6 +110,7 @@ void free_gamestate(Gamestate *this) { } int main(int argc, char **argv) { + Json * json = json_parse(stdin); Gamestate *gamestate; SortedMap *test; @@ -121,5 +125,7 @@ int main(int argc, char **argv) { printf("%s\n", (char *) get_map(test, "awer")); print_map(test); free_map(test); + json_print(json, stdout); + json_free(json); return 0; } diff --git a/sortedmap.c b/sortedmap.c index fd86fd1..2e80a6d 100644 --- a/sortedmap.c +++ b/sortedmap.c @@ -2,77 +2,65 @@ #include #include #include - -struct intern { - enum nodetype type; - char * key; - struct node * left; - struct node * right; -}; - -struct leaf { - enum nodetype type; - char * key; - void * value; -}; - SortedMap * map() { - return NULL; + SortedMap *this = malloc(sizeof(SortedMap)); + this->type = EMPTY; + this->key = NULL; + return this; } void * get_map(SortedMap *this, char *key) { - if (this == NULL) return NULL; - if (this->type == LEAF) { - if (strcmp(key, this->key) == 0) return ((struct leaf *) this)->value; + switch (this->type) { + case EMPTY: return NULL; - } else { + case LEAF: + if (strcmp(key, this->key) == 0) return this->content.value; + return NULL; + case INTERN: if (strcmp(key, this->key) <= 0) { - return get_map(((struct intern *) this)->left, key); + return get_map(this->content.children.l, key); } else { - return get_map(((struct intern *) this)->right, key); + return get_map(this->content.children.r, key); } + default: + return NULL; } } SortedMap * put_map(SortedMap *this, char *key, void *value) { - struct leaf *leaf, *newleaf; - struct intern *intern; - int cmp; - - if (this == NULL) { - struct leaf *leaf = malloc(sizeof(struct leaf)); + SortedMap *leaf, *intern; + int cmp = this->key != NULL ? strcmp(key, this->key) : 0; + switch (this->type) { + case EMPTY: + this->type = LEAF; + this->key = key; + this->content.value = value; + return this; + case LEAF: + if (cmp == 0) { + this->content.value = value; + return this; + } + leaf = malloc(sizeof(SortedMap)); leaf->type = LEAF; leaf->key = key; - leaf->value = value; - return (SortedMap *) leaf; - } else { - cmp = strcmp(key, this->key); - if (this->type == LEAF) { - leaf = (struct leaf*) this; - if (cmp == 0) { - leaf->value = value; - return (SortedMap *) leaf; - } - newleaf = malloc(sizeof(struct leaf)); - newleaf->type = LEAF; - newleaf->key = key; - newleaf->value = value; - intern = malloc(sizeof(struct intern)); - intern->type = INTERN; - intern->key = leaf->key; - intern->left = (struct node*) (cmp < 0 ? newleaf : leaf); - intern->right = (struct node*) (cmp < 0 ? leaf : newleaf); - return (SortedMap *) intern; + leaf->content.value = value; + intern = malloc(sizeof(SortedMap)); + intern->type = INTERN; + intern->key = this->key; + intern->content.children.l = cmp < 0 ? leaf : this; + intern->content.children.r = cmp < 0 ? this : leaf; + return intern; + case INTERN: + if (cmp <= 0) { + this->content.children.l = put_map(this->content.children.l, key, value); + return this; } else { - intern = (struct intern*) this; - if (cmp <= 0) { - intern->left = put_map(intern->left, key, value); - return (SortedMap *) intern; - } else { - intern->right = put_map(intern->right, key, value); - return (SortedMap *) intern; - } + this->content.children.r = put_map(this->content.children.r, key, value); + return this; } + default: + return NULL; } } @@ -82,42 +70,64 @@ void print_indent_(int indent) { } void print_map_(SortedMap *this, int indent) { - if (this->type == LEAF) { - struct leaf *leaf = (struct leaf*) this; + switch (this->type) { + case EMPTY: + printf("empty\n"); + break; + case LEAF: print_indent_(indent); - printf("%s: %s\n", leaf->key, (char *) leaf->value); - } else { - struct intern *intern = (struct intern*) this; - print_map_(intern->left, indent + 1); + printf("%s: %s\n", this->key, (char *) this->content.value); + break; + case INTERN: + print_map_(this->content.children.r, indent + 1); print_indent_(indent); - printf("%s\n", intern->key); - print_map_(intern->right, indent + 1); + printf("%s\n", this->key); + print_map_(this->content.children.l, indent + 1); + break; } } void print_map(SortedMap *this) { - if (this == NULL) printf("empty\n"); - else print_map_(this, 0); + print_map_(this, 0); +} + +void * fold_map(SortedMap *this, void * init, void * (*f)(void * acc, char *key, void *value)) { + switch (this->type) { + case EMPTY: + return init; + case LEAF: + return f(init, this->key, this->content.value); + case INTERN: + return fold_map(fold_map(init, this->content.children.l, f), this->content.children.r, f); + default: + return NULL; + } } void free_mapvalues(SortedMap *this) { - if (this == NULL) return; - else if (this->type == LEAF) free(((struct leaf*) this)->value); - else { - struct intern *intern = (struct intern*) this; - free_mapvalues(intern->left); - free_mapvalues(intern->right); + switch (this->type) { + case EMPTY: + break; + case LEAF: + free(this->content.value); + break; + case INTERN: + free_mapvalues(this->content.children.l); + free_mapvalues(this->content.children.r); + break; } } void free_map(SortedMap *this) { - struct intern *intern; - if (this == NULL) return; - else if (this->type == LEAF) free(this); - else { - intern = (struct intern*) this; - free_map(intern->left); - free_map(intern->right); + switch (this->type) { + case EMPTY: + case LEAF: free(this); + break; + case INTERN: + free_map(this->content.children.l); + free_map(this->content.children.r); + free(this); + break; } } diff --git a/sortedmap.h b/sortedmap.h index 2644cea..ec457a0 100644 --- a/sortedmap.h +++ b/sortedmap.h @@ -1,16 +1,24 @@ #ifndef SORTED_MAP #define SORTED_MAP -enum nodetype { LEAF, INTERN }; +enum nodetype { EMPTY, LEAF, INTERN }; typedef struct node { enum nodetype type; char * key; + union { + struct children { + struct node * l; + struct node * r; + } children; + void * value; + } content; } SortedMap; SortedMap * map(); void * get_map(SortedMap *this, char *key); SortedMap * put_map(SortedMap *this, char *key, void *value); void print_map(SortedMap *this); +void * fold_map(SortedMap *this, void * init, void * (*f)(void * acc, char *key, void *value)); void free_mapvalues(SortedMap *this); void free_map(SortedMap *this); #endif