add json printing and parsing (of strings)

This commit is contained in:
Felix Van der Jeugt 2022-11-02 00:05:01 +01:00
parent 563b1b0c5a
commit a13c6ecb3a
No known key found for this signature in database
GPG Key ID: 58B209295023754D
6 changed files with 277 additions and 81 deletions

150
json.c Normal file
View File

@ -0,0 +1,150 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

21
json.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -2,77 +2,65 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
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;
}
}

View File

@ -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