diff options
Diffstat (limited to 'scriptbase_json_query.c')
-rw-r--r-- | scriptbase_json_query.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/scriptbase_json_query.c b/scriptbase_json_query.c new file mode 100644 index 0000000..e413b3e --- /dev/null +++ b/scriptbase_json_query.c @@ -0,0 +1,213 @@ +/** + * part of Hydrilla + * Routines that perform queries on in-memory scriptbase and return results in + * the form of JSON strings. + * + * Copyright (C) 2021 Wojtek Kosior + * Redistribution terms are gathered in the `copyright' file. + */ + +#include <errno.h> + +#include "scriptbase.h" + +#define ADD_COMPONENT(object, key, construct, adder) \ + new = cJSON_Create##construct; \ + if (!new) \ + goto free_json; \ + adder(object, key, new) + +#define ADD_TO_OBJECT(object, key, construct) \ + ADD_COMPONENT(object, key, construct, cJSON_AddItemToObject) + +#define ADD_KEY(key, construct) ADD_TO_OBJECT(json, key, construct) + +#define ARRAY_ADDER(object, key, var) cJSON_AddItemToArray(object, var) + +#define ADD_TO_ARRAY(object, construct) \ + ADD_COMPONENT(object, dummy, construct, ARRAY_ADDER) + +char *get_script_json(const char *name, struct scriptbase *base) +{ + const struct script *script; + cJSON *json, *new; + char *printed = NULL; + + script = get_script(name, base); + if (!script || !script->filled) + return NULL; + + json = cJSON_CreateObject(); + if (!json) + goto free_json; + + ADD_KEY("name", String(script->name)); + ADD_KEY("location", String(script->location)); + ADD_KEY("sha256", String(script->sha256)); + + printed = cJSON_Print(json); + +free_json: + cJSON_Delete(json); + + if (!printed) + errno = ENOMEM; + + return printed; +} + +char *get_bag_json(const char *name, struct scriptbase *base) +{ + const struct bag *bag; + cJSON *json, *new, *components, *current_component; + struct component_ref *ref; + char type_prefix[] = "\0"; + char *printed = NULL; + + bag = get_bag(name, base); + if (!bag || !bag->filled) + return NULL; + + json = cJSON_CreateObject(); + if (!json) + goto free_json; + + ADD_KEY("name", String(bag->name)); + ADD_KEY("components", Array()); + components = new; + + for (ref = bag->components; ref; ref = ref->next) { + ADD_TO_ARRAY(components, Array()); + current_component = new; + type_prefix[0] = ref->component_type[0]; + ADD_TO_ARRAY(current_component, String(type_prefix)); + /* name is at the same offset in struct bag and struct script */ + ADD_TO_ARRAY(current_component, + String(ref->component.bag->name)); + } + + printed = cJSON_Print(json); + +free_json: + cJSON_Delete(json); + + if (!printed) + errno = ENOMEM; + + return printed; +} + +cJSON *page_to_cJSON(const struct page *page) +{ + cJSON *json, *new, *payload; + char type_prefix[] = "\0"; + + json = cJSON_CreateObject(); + if (!json) + goto free_json; + + ADD_KEY("pattern", String(page->pattern)); + if (!page->payload.any) + goto skip_payload; + ADD_KEY("payload", Array()); + payload = new; + type_prefix[0] = page->payload_type[0]; + ADD_TO_ARRAY(payload, String(type_prefix)); + /* name is at the same offset in struct bag and struct script */ + ADD_TO_ARRAY(payload, String(page->payload.bag->name)); + +skip_payload: + return json; + +free_json: + cJSON_Delete(json); + + errno = ENOMEM; + + return NULL; +} + +char *get_pattern_json(const char *pattern, struct scriptbase *base) +{ + const struct page *page; + cJSON *json; + char *printed = NULL; + + page = get_pattern(pattern, base); + if (!page) + return NULL; + + json = page_to_cJSON(page); + if (!json) + return NULL; + + printed = cJSON_Print(json); + cJSON_Delete(json); + + if (!printed) + errno = ENOMEM; + + return printed; +} + +struct page_array_building { + cJSON *page_array; + bool OOM_error; +}; + +int lookup_callback(struct page *page, void *data) +{ + struct page_array_building *building = data; + cJSON *page_json; + + page_json = page_to_cJSON(page); + if (!page_json) { + building->OOM_error = true; + return -1; + } + + cJSON_AddItemToArray(building->page_array, page_json); + + return 0; +} + +#include <stdio.h> +char *get_page_query_json(const char *url, struct scriptbase *base) +{ + struct page_array_building building = {NULL, false}; + char *printed = NULL; + int result = -2; + + building.page_array = cJSON_CreateArray(); + if (!building.page_array) + goto free_json; + + result = lookup_url(url, base, lookup_callback, &building); + + printf("lookup returned value is %d\n", result); + + if (building.OOM_error) + result = -2; + if (result < 0) + goto free_json; + + printed = cJSON_Print(building.page_array); + if (!printed) + result = -2; + +free_json: + cJSON_Delete(building.page_array); + + switch (result) { + case 0: + break; + case -1: + case -3: + errno = EINVAL; + break; + case -2: + errno = ENOMEM; + } + + return printed; +} |