add json parsing of lists and maps
This commit is contained in:
parent
7471093f67
commit
025c8125fa
16 changed files with 210 additions and 20 deletions
135
json.c
135
json.c
|
@ -67,6 +67,7 @@ Json * parse_number(FILE *stream, int sign) {
|
|||
break;
|
||||
default:
|
||||
if (c != EOF) ungetc(c, stream);
|
||||
if (den == 0) den = 1;
|
||||
json = malloc(sizeof(Json));
|
||||
json->type = NUMBER;
|
||||
json->value.number = sign * num * 1.0 / den;
|
||||
|
@ -104,15 +105,109 @@ Json * parse_string(FILE *stream) {
|
|||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Json * parse_list(FILE *stream) { return NULL; /* TODO */ }
|
||||
Json * parse_map(FILE *stream) { return NULL; /* TODO */ }
|
||||
Json * parse_list(FILE *stream) {
|
||||
char c;
|
||||
Json * json;
|
||||
ArrayList * values = list();
|
||||
int expect_comma = 0;
|
||||
while ((c = getc(stream)) != EOF) {
|
||||
switch (c) {
|
||||
case ']':
|
||||
json = malloc(sizeof(Json));
|
||||
json->type = LIST;
|
||||
json->value.list = values;
|
||||
return json;
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '\t':
|
||||
break;
|
||||
case ',':
|
||||
if (expect_comma) {
|
||||
expect_comma = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ungetc(c, stream);
|
||||
json = json_parse(stream);
|
||||
add_list(values, (void *) json);
|
||||
expect_comma = 1;
|
||||
}
|
||||
}
|
||||
fold_list(values, NULL, free_listitem);
|
||||
free_list(values);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum map_state { MKEY, MCOLON, MVALUE, MCOMMA };
|
||||
|
||||
Json * parse_map(FILE *stream) {
|
||||
char c;
|
||||
Json * json = NULL;
|
||||
char * key = NULL;
|
||||
SortedMap * values = map();
|
||||
enum map_state s = MKEY;
|
||||
while ((c = getc(stream)) != EOF) {
|
||||
switch (s) {
|
||||
case MKEY:
|
||||
switch (c) {
|
||||
case ' ': case '\n': case '\t': break;
|
||||
case '}':
|
||||
json = malloc(sizeof(Json));
|
||||
json->type = MAP;
|
||||
json->value.map = values;
|
||||
return json;
|
||||
case '"':
|
||||
json = parse_string(stream);
|
||||
key = json->value.string;
|
||||
free(json);
|
||||
json = NULL;
|
||||
s = MCOLON;
|
||||
}
|
||||
break;
|
||||
case MCOLON:
|
||||
switch (c) {
|
||||
case ' ': case '\n': case '\t': break;
|
||||
case ':':
|
||||
s = MVALUE;
|
||||
}
|
||||
break;
|
||||
case MVALUE:
|
||||
switch (c) {
|
||||
case ' ': case '\n': case '\t': break;
|
||||
default:
|
||||
ungetc(c, stream);
|
||||
json = json_parse(stream);
|
||||
values = put_map(values, key, (void *) json);
|
||||
json = NULL;
|
||||
s = MCOMMA;
|
||||
}
|
||||
break;
|
||||
case MCOMMA:
|
||||
switch (c) {
|
||||
case ' ': case '\n': case '\t': break;
|
||||
case ',':
|
||||
s = MKEY;
|
||||
break;
|
||||
case '}':
|
||||
json = malloc(sizeof(Json));
|
||||
json->type = MAP;
|
||||
json->value.map = values;
|
||||
return json;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fold_map(values, NULL, free_mappair);
|
||||
free_map(values);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Json * json_parse(FILE *stream) {
|
||||
char c;
|
||||
Json * json = NULL;
|
||||
while ((c = getc(stream)) != EOF) {
|
||||
switch (c) {
|
||||
case '{':
|
||||
|
@ -149,7 +244,11 @@ Json * json_parse(FILE *stream) {
|
|||
fprintf(stderr, "encountered char: '%c'", c);
|
||||
}
|
||||
}
|
||||
return json;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print_string(FILE *stream, char *string) {
|
||||
fprintf(stream, "\"%s\"", string);
|
||||
}
|
||||
|
||||
struct printacc {
|
||||
|
@ -159,7 +258,12 @@ struct printacc {
|
|||
|
||||
void * json_print_map(void * voidacc, char *key, void *value) {
|
||||
struct printacc *acc = (struct printacc *) voidacc;
|
||||
|
||||
if (acc->index++ > 0) {
|
||||
fprintf(acc->stream, ", ");
|
||||
}
|
||||
print_string(acc->stream, key);
|
||||
fprintf(acc->stream, ": ");
|
||||
json_print((Json *) value, acc->stream);
|
||||
return acc;
|
||||
}
|
||||
|
||||
|
@ -174,7 +278,7 @@ void json_print(Json *this, FILE *stream) {
|
|||
fprintf(stream, this->value.boolean == 0 ? "false" : "true");
|
||||
break;
|
||||
case STRING:
|
||||
fprintf(stream, "\"%s\"", this->value.string);
|
||||
print_string(stream, this->value.string);
|
||||
break;
|
||||
case NUMBER:
|
||||
fprintf(stream, "%f", this->value.number);
|
||||
|
@ -193,12 +297,23 @@ void json_print(Json *this, FILE *stream) {
|
|||
case MAP:
|
||||
fprintf(stream, "{");
|
||||
acc.stream = stream;
|
||||
fold_map((void *) &acc, this->value.map, json_print_map);
|
||||
fold_map(this->value.map, (void *) &acc, json_print_map);
|
||||
fprintf(stream, "}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void * json_freelist(void *acc, int index, void *item) {
|
||||
json_free((Json *) item);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * json_freemap(void *acc, char *key, void *value) {
|
||||
free(key);
|
||||
json_free((Json *) value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void json_free(Json *this) {
|
||||
switch (this->type) {
|
||||
case NIL:
|
||||
|
@ -209,10 +324,12 @@ void json_free(Json *this) {
|
|||
free(this->value.string);
|
||||
break;
|
||||
case LIST:
|
||||
/* TODO */
|
||||
fold_list(this->value.list, NULL, json_freelist);
|
||||
free_list(this->value.list);
|
||||
break;
|
||||
case MAP:
|
||||
/* TODO */
|
||||
fold_map(this->value.map, NULL, json_freemap);
|
||||
free_map(this->value.map);
|
||||
break;
|
||||
}
|
||||
free(this);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue