add json printing and parsing (of strings)
This commit is contained in:
parent
563b1b0c5a
commit
a13c6ecb3a
150
json.c
Normal file
150
json.c
Normal 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
21
json.h
Normal 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
|
3
makefile
3
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
166
sortedmap.c
166
sortedmap.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
10
sortedmap.h
10
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
|
||||
|
Loading…
Reference in New Issue
Block a user