fixed array parsing and windows support

This commit is contained in:
ari melody 2024-07-11 14:41:47 +01:00
parent d2fe432828
commit 018442a445
Signed by: ari
GPG key ID: CF99829C92678188
5 changed files with 58 additions and 66 deletions

View file

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

View file

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

View file

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

View file

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

View file

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