fixed array parsing and windows support
This commit is contained in:
parent
d2fe432828
commit
018442a445
|
@ -1,3 +1,3 @@
|
||||||
New-Item -ItemType Directory -Force -Path ./bin/
|
New-Item -ItemType Directory -Force -Path ./bin/
|
||||||
|
|
||||||
gcc -Wall -o ./bin/compile ./src/*.c ./src/parsers/*.c
|
gcc -Wall -o ./bin/compile ./src/*.c ./src/parsers/*.c -lm
|
||||||
|
|
2
build.sh
2
build.sh
|
@ -1,3 +1,3 @@
|
||||||
mkdir -p ./bin/
|
mkdir -p ./bin/
|
||||||
|
|
||||||
gcc -Wall -o ./bin/compile ./src/*.c ./src/parsers/*.c
|
gcc -Wall -o ./bin/compile ./src/*.c ./src/parsers/*.c -lm
|
||||||
|
|
26
src/main.c
26
src/main.c
|
@ -81,6 +81,7 @@ int main(int argc, char **argv) {
|
||||||
fread(buf, 1, length, input_file);
|
fread(buf, 1, length, input_file);
|
||||||
buf[length] = '\0';
|
buf[length] = '\0';
|
||||||
|
|
||||||
|
// parse the file
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
JsonObject *json = json_parse(buf, &offset);
|
JsonObject *json = json_parse(buf, &offset);
|
||||||
if (json == NULL) {
|
if (json == NULL) {
|
||||||
|
@ -88,20 +89,19 @@ int main(int argc, char **argv) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("title: %s\n", (char*)json_get(json, "title"));
|
printf("title: %s\n", (char*)((JsonObject*)json_get(json, "title"))->value);
|
||||||
printf("type: %s\n", (char*)json_get(json, "type"));
|
printf("type: %s\n", (char*)((JsonObject*)json_get(json, "type"))->value);
|
||||||
printf("year: %.0f\n", *(float*)json_get(json, "year"));
|
printf("year: %.0f\n", *(float*)((JsonObject*)json_get(json, "year"))->value);
|
||||||
printf("artwork: %s\n", (char*)json_get(json, "artwork"));
|
printf("artwork: %s\n", (char*)((JsonObject*)json_get(json, "artwork"))->value);
|
||||||
printf("buylink: %s\n", (char*)json_get(json, "buylink"));
|
printf("buylink: %s\n", (char*)((JsonObject*)json_get(json, "buylink"))->value);
|
||||||
|
|
||||||
JsonArrayItem *links = json_get(json, "links");
|
JsonObject *links = (JsonObject*)json_get(json, "links");
|
||||||
size_t i = 0;
|
for (size_t i = 0; i < links->length; i++) {
|
||||||
while (links != NULL) {
|
char path[256];
|
||||||
JsonObject *link = links->value;
|
sprintf(path, "links.%zu.title", i);
|
||||||
printf("links.%zu.title: %s\n", i, (char*)json_get(link, "title"));
|
printf("%s: %s\n", path, (char*)((JsonObject*)json_get(json, path))->value);
|
||||||
printf("links.%zu.url: %s\n", i, (char*)json_get(link, "url"));
|
sprintf(path, "links.%zu.url", i);
|
||||||
links = links->next;
|
printf("%s: %s\n", path, (char*)((JsonObject*)json_get(json, path))->value);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#define SKIP_WHITESPACE while ((data[i] == ' ' || data[i] == '\t' || data[i] == '\n') && data[i] != '\0') i++
|
#define SKIP_WHITESPACE while ((data[i] == ' ' || data[i] == '\t' || data[i] == '\n') && data[i] != '\0') i++
|
||||||
|
|
||||||
|
void *parse_value(JsonType *type, char *data, size_t *offset);
|
||||||
|
|
||||||
void json_log(const char *error, char *data, size_t index) {
|
void json_log(const char *error, char *data, size_t index) {
|
||||||
int cur = 0;
|
int cur = 0;
|
||||||
int line_num = 0;
|
int line_num = 0;
|
||||||
|
@ -40,41 +42,33 @@ void json_log(const char *error, char *data, size_t index) {
|
||||||
fprintf(stderr, "^\n\n");
|
fprintf(stderr, "^\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayItem *parse_array(char *data, size_t *offset);
|
JsonObject *parse_array(char *data, size_t *offset) {
|
||||||
void *parse_value(JsonType *type, char *data, size_t *offset);
|
|
||||||
|
|
||||||
JsonArrayItem *parse_array(char *data, size_t *offset) {
|
|
||||||
size_t i = *offset + 1;
|
size_t i = *offset + 1;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
JsonArrayItem *head = NULL;
|
JsonObject *head = NULL;
|
||||||
|
JsonObject *tail = NULL;
|
||||||
while (data[i] != '\0' && data[i] != ']') {
|
while (data[i] != '\0' && data[i] != ']') {
|
||||||
void *item_value = NULL;
|
JsonObject *item_value = NULL;
|
||||||
JsonType type = -1;
|
JsonType type = -1;
|
||||||
|
|
||||||
item_value = parse_value(&type, data, &i);
|
item_value = parse_value(&type, data, &i);
|
||||||
if (item_value == NULL) return NULL;
|
if (item_value == NULL) return NULL;
|
||||||
|
|
||||||
if (type == object) {
|
item_value->name = malloc(sizeof(char) * (count < 10 ? 2 : (int)ceil(log10(count)) + 1));
|
||||||
JsonObject *obj = item_value;
|
sprintf(item_value->name, "%zu", count);
|
||||||
|
|
||||||
if (obj->name != NULL) free(obj->name);
|
|
||||||
obj->name = malloc(sizeof(char) * log10(count) + 1);
|
|
||||||
sprintf(obj->name, "%zu", count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
head = malloc(sizeof(JsonArrayItem));
|
head = item_value;
|
||||||
((JsonArrayItem*)head)->value = item_value;
|
tail = item_value;
|
||||||
} else {
|
} else {
|
||||||
JsonArrayItem *last = head;
|
tail->next = item_value;
|
||||||
while (last->next != NULL) last = last->next;
|
tail = tail->next;
|
||||||
last->next = malloc(sizeof(JsonArrayItem));
|
|
||||||
last->next->value = item_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SKIP_WHITESPACE;
|
SKIP_WHITESPACE;
|
||||||
// skip comma, if there is one
|
// skip comma, if there is one
|
||||||
if (data[i] == ',') i++;
|
if (data[i] == ',') i++;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[i] == '\0') {
|
if (data[i] == '\0') {
|
||||||
|
@ -244,6 +238,14 @@ JsonObject *json_parse(char *data, size_t *offset) {
|
||||||
obj->name = name;
|
obj->name = name;
|
||||||
obj->type = type;
|
obj->type = type;
|
||||||
obj->value = value;
|
obj->value = value;
|
||||||
|
if (type == array) {
|
||||||
|
obj->children = value;
|
||||||
|
JsonObject *child = obj->children;
|
||||||
|
while (child != NULL) {
|
||||||
|
obj->length++;
|
||||||
|
child = child->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// append new object to root's children
|
// append new object to root's children
|
||||||
|
@ -274,18 +276,22 @@ void *json_get(JsonObject *obj, const char *query) {
|
||||||
if (obj == NULL) return NULL;
|
if (obj == NULL) return NULL;
|
||||||
|
|
||||||
size_t cur = 0;
|
size_t cur = 0;
|
||||||
JsonType searching_type = object;
|
JsonType searching_type = obj->type;
|
||||||
|
|
||||||
while (query[cur] != '\0') {
|
while (query[cur] != '\0') {
|
||||||
size_t attr_len = 0;
|
size_t attr_name_len = 0;
|
||||||
while (query[cur + attr_len] != '\0' && query[cur + attr_len] != '.') attr_len++;
|
while (query[cur + attr_name_len] != '\0' && query[cur + attr_name_len] != '.') attr_name_len++;
|
||||||
char attr[attr_len];
|
char attr_name[attr_name_len];
|
||||||
memcpy(attr, query + cur * sizeof(char), attr_len * sizeof(char));
|
memcpy(attr_name, query + cur * sizeof(char), attr_name_len * sizeof(char) + 1);
|
||||||
|
attr_name[attr_name_len] = '\0';
|
||||||
|
|
||||||
if (searching_type == object) {
|
if (searching_type == object) {
|
||||||
obj = obj->children;
|
obj = obj->children;
|
||||||
|
if (obj == NULL) {
|
||||||
|
fprintf(stderr, "error: attribute `%s` does not have any children\n", obj->name);
|
||||||
|
}
|
||||||
while (obj != NULL) {
|
while (obj != NULL) {
|
||||||
if (strcmp(obj->name, attr) == 0) {
|
if (strcmp(obj->name, attr_name) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
obj = obj->next;
|
obj = obj->next;
|
||||||
|
@ -295,16 +301,16 @@ void *json_get(JsonObject *obj, const char *query) {
|
||||||
if (searching_type == array) {
|
if (searching_type == array) {
|
||||||
size_t to_i = 0;
|
size_t to_i = 0;
|
||||||
size_t cur = 0;
|
size_t cur = 0;
|
||||||
while (cur < attr_len) {
|
while (cur < attr_name_len) {
|
||||||
if (attr[cur] < '0' || attr[cur] > '9') {
|
if (attr_name[cur] < '0' || attr_name[cur] > '9') {
|
||||||
fprintf(stderr, "error: attempt to index array with attribute name (%s)\n", attr);
|
fprintf(stderr, "error: attribute `%s` does not exist in array `%s`\n", attr_name, obj->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
to_i = (to_i * 10) + (attr[cur] - '0');
|
to_i = (to_i * 10) + (attr_name[cur] - '0');
|
||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayItem *item = obj->value;
|
JsonObject *item = obj->children;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (item != NULL && i < to_i) {
|
while (item != NULL && i < to_i) {
|
||||||
item = item->next;
|
item = item->next;
|
||||||
|
@ -312,25 +318,25 @@ void *json_get(JsonObject *obj, const char *query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
fprintf(stderr, "error: index %zu out of bounds for array %s\n", to_i, attr);
|
fprintf(stderr, "error: index %zu out of bounds for array `%s`\n", to_i, attr_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = item->value;
|
obj = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
fprintf(stderr, "error: %s does not exist in json object\n", query);
|
fprintf(stderr, "error: `%s` does not exist in json object\n", query);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cur += attr_len;
|
cur += attr_name_len;
|
||||||
if (query[cur] == '.') {
|
if (query[cur] == '.') {
|
||||||
searching_type = obj->type;
|
searching_type = obj->type;
|
||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj->value;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void json_free(JsonObject *object) {
|
void json_free(JsonObject *object) {
|
||||||
|
@ -344,17 +350,7 @@ void json_free(JsonObject *object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object->name != NULL) free(object->name);
|
if (object->name != NULL) free(object->name);
|
||||||
if (object->value != NULL) {
|
if (object->value != NULL) free(object->value);
|
||||||
if (object->type == array) {
|
|
||||||
while (object->value != NULL) {
|
|
||||||
JsonArrayItem *old = object->value;
|
|
||||||
json_free(old->value);
|
|
||||||
object->value = old->next;
|
|
||||||
free(old);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(object->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(object);
|
free(object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,12 @@ typedef struct JsonObject {
|
||||||
char *name;
|
char *name;
|
||||||
JsonType type;
|
JsonType type;
|
||||||
void *value;
|
void *value;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
struct JsonObject *children;
|
struct JsonObject *children;
|
||||||
struct JsonObject *next;
|
struct JsonObject *next;
|
||||||
} JsonObject;
|
} JsonObject;
|
||||||
|
|
||||||
typedef struct JsonArrayItem {
|
|
||||||
JsonObject *value;
|
|
||||||
struct JsonArrayItem *next;
|
|
||||||
} JsonArrayItem;
|
|
||||||
|
|
||||||
JsonObject *json_parse(char *data, size_t *offset);
|
JsonObject *json_parse(char *data, size_t *offset);
|
||||||
void *json_get(JsonObject *object, const char *child_name);
|
void *json_get(JsonObject *object, const char *child_name);
|
||||||
void json_free(JsonObject *object);
|
void json_free(JsonObject *object);
|
||||||
|
|
Loading…
Reference in a new issue