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/
|
||||
|
||||
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/
|
||||
|
||||
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);
|
||||
buf[length] = '\0';
|
||||
|
||||
// parse the file
|
||||
size_t offset = 0;
|
||||
JsonObject *json = json_parse(buf, &offset);
|
||||
if (json == NULL) {
|
||||
|
@ -88,20 +89,19 @@ int main(int argc, char **argv) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("title: %s\n", (char*)json_get(json, "title"));
|
||||
printf("type: %s\n", (char*)json_get(json, "type"));
|
||||
printf("year: %.0f\n", *(float*)json_get(json, "year"));
|
||||
printf("artwork: %s\n", (char*)json_get(json, "artwork"));
|
||||
printf("buylink: %s\n", (char*)json_get(json, "buylink"));
|
||||
printf("title: %s\n", (char*)((JsonObject*)json_get(json, "title"))->value);
|
||||
printf("type: %s\n", (char*)((JsonObject*)json_get(json, "type"))->value);
|
||||
printf("year: %.0f\n", *(float*)((JsonObject*)json_get(json, "year"))->value);
|
||||
printf("artwork: %s\n", (char*)((JsonObject*)json_get(json, "artwork"))->value);
|
||||
printf("buylink: %s\n", (char*)((JsonObject*)json_get(json, "buylink"))->value);
|
||||
|
||||
JsonArrayItem *links = json_get(json, "links");
|
||||
size_t i = 0;
|
||||
while (links != NULL) {
|
||||
JsonObject *link = links->value;
|
||||
printf("links.%zu.title: %s\n", i, (char*)json_get(link, "title"));
|
||||
printf("links.%zu.url: %s\n", i, (char*)json_get(link, "url"));
|
||||
links = links->next;
|
||||
i++;
|
||||
JsonObject *links = (JsonObject*)json_get(json, "links");
|
||||
for (size_t i = 0; i < links->length; i++) {
|
||||
char path[256];
|
||||
sprintf(path, "links.%zu.title", i);
|
||||
printf("%s: %s\n", path, (char*)((JsonObject*)json_get(json, path))->value);
|
||||
sprintf(path, "links.%zu.url", i);
|
||||
printf("%s: %s\n", path, (char*)((JsonObject*)json_get(json, path))->value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#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) {
|
||||
int cur = 0;
|
||||
int line_num = 0;
|
||||
|
@ -40,41 +42,33 @@ void json_log(const char *error, char *data, size_t index) {
|
|||
fprintf(stderr, "^\n\n");
|
||||
}
|
||||
|
||||
JsonArrayItem *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) {
|
||||
JsonObject *parse_array(char *data, size_t *offset) {
|
||||
size_t i = *offset + 1;
|
||||
size_t count = 0;
|
||||
JsonArrayItem *head = NULL;
|
||||
JsonObject *head = NULL;
|
||||
JsonObject *tail = NULL;
|
||||
while (data[i] != '\0' && data[i] != ']') {
|
||||
void *item_value = NULL;
|
||||
JsonObject *item_value = NULL;
|
||||
JsonType type = -1;
|
||||
|
||||
item_value = parse_value(&type, data, &i);
|
||||
if (item_value == NULL) return NULL;
|
||||
|
||||
if (type == object) {
|
||||
JsonObject *obj = item_value;
|
||||
|
||||
if (obj->name != NULL) free(obj->name);
|
||||
obj->name = malloc(sizeof(char) * log10(count) + 1);
|
||||
sprintf(obj->name, "%zu", count);
|
||||
}
|
||||
item_value->name = malloc(sizeof(char) * (count < 10 ? 2 : (int)ceil(log10(count)) + 1));
|
||||
sprintf(item_value->name, "%zu", count);
|
||||
|
||||
if (head == NULL) {
|
||||
head = malloc(sizeof(JsonArrayItem));
|
||||
((JsonArrayItem*)head)->value = item_value;
|
||||
head = item_value;
|
||||
tail = item_value;
|
||||
} else {
|
||||
JsonArrayItem *last = head;
|
||||
while (last->next != NULL) last = last->next;
|
||||
last->next = malloc(sizeof(JsonArrayItem));
|
||||
last->next->value = item_value;
|
||||
tail->next = item_value;
|
||||
tail = tail->next;
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE;
|
||||
// skip comma, if there is one
|
||||
if (data[i] == ',') i++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (data[i] == '\0') {
|
||||
|
@ -244,6 +238,14 @@ JsonObject *json_parse(char *data, size_t *offset) {
|
|||
obj->name = name;
|
||||
obj->type = type;
|
||||
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
|
||||
|
@ -274,18 +276,22 @@ void *json_get(JsonObject *obj, const char *query) {
|
|||
if (obj == NULL) return NULL;
|
||||
|
||||
size_t cur = 0;
|
||||
JsonType searching_type = object;
|
||||
JsonType searching_type = obj->type;
|
||||
|
||||
while (query[cur] != '\0') {
|
||||
size_t attr_len = 0;
|
||||
while (query[cur + attr_len] != '\0' && query[cur + attr_len] != '.') attr_len++;
|
||||
char attr[attr_len];
|
||||
memcpy(attr, query + cur * sizeof(char), attr_len * sizeof(char));
|
||||
size_t attr_name_len = 0;
|
||||
while (query[cur + attr_name_len] != '\0' && query[cur + attr_name_len] != '.') attr_name_len++;
|
||||
char attr_name[attr_name_len];
|
||||
memcpy(attr_name, query + cur * sizeof(char), attr_name_len * sizeof(char) + 1);
|
||||
attr_name[attr_name_len] = '\0';
|
||||
|
||||
if (searching_type == object) {
|
||||
obj = obj->children;
|
||||
if (obj == NULL) {
|
||||
fprintf(stderr, "error: attribute `%s` does not have any children\n", obj->name);
|
||||
}
|
||||
while (obj != NULL) {
|
||||
if (strcmp(obj->name, attr) == 0) {
|
||||
if (strcmp(obj->name, attr_name) == 0) {
|
||||
break;
|
||||
}
|
||||
obj = obj->next;
|
||||
|
@ -295,16 +301,16 @@ void *json_get(JsonObject *obj, const char *query) {
|
|||
if (searching_type == array) {
|
||||
size_t to_i = 0;
|
||||
size_t cur = 0;
|
||||
while (cur < attr_len) {
|
||||
if (attr[cur] < '0' || attr[cur] > '9') {
|
||||
fprintf(stderr, "error: attempt to index array with attribute name (%s)\n", attr);
|
||||
while (cur < attr_name_len) {
|
||||
if (attr_name[cur] < '0' || attr_name[cur] > '9') {
|
||||
fprintf(stderr, "error: attribute `%s` does not exist in array `%s`\n", attr_name, obj->name);
|
||||
return NULL;
|
||||
}
|
||||
to_i = (to_i * 10) + (attr[cur] - '0');
|
||||
to_i = (to_i * 10) + (attr_name[cur] - '0');
|
||||
cur++;
|
||||
}
|
||||
|
||||
JsonArrayItem *item = obj->value;
|
||||
JsonObject *item = obj->children;
|
||||
size_t i = 0;
|
||||
while (item != NULL && i < to_i) {
|
||||
item = item->next;
|
||||
|
@ -312,25 +318,25 @@ void *json_get(JsonObject *obj, const char *query) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
obj = item->value;
|
||||
obj = item;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
cur += attr_len;
|
||||
cur += attr_name_len;
|
||||
if (query[cur] == '.') {
|
||||
searching_type = obj->type;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
|
||||
return obj->value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
void json_free(JsonObject *object) {
|
||||
|
@ -344,17 +350,7 @@ void json_free(JsonObject *object) {
|
|||
}
|
||||
|
||||
if (object->name != NULL) free(object->name);
|
||||
if (object->value != NULL) {
|
||||
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);
|
||||
}
|
||||
if (object->value != NULL) free(object->value);
|
||||
|
||||
free(object);
|
||||
}
|
||||
|
|
|
@ -14,16 +14,12 @@ typedef struct JsonObject {
|
|||
char *name;
|
||||
JsonType type;
|
||||
void *value;
|
||||
size_t length;
|
||||
|
||||
struct JsonObject *children;
|
||||
struct JsonObject *next;
|
||||
} JsonObject;
|
||||
|
||||
typedef struct JsonArrayItem {
|
||||
JsonObject *value;
|
||||
struct JsonArrayItem *next;
|
||||
} JsonArrayItem;
|
||||
|
||||
JsonObject *json_parse(char *data, size_t *offset);
|
||||
void *json_get(JsonObject *object, const char *child_name);
|
||||
void json_free(JsonObject *object);
|
||||
|
|
Loading…
Reference in a new issue