aboutsummaryrefslogtreecommitdiff
path: root/scriptbase_json_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'scriptbase_json_query.c')
-rw-r--r--scriptbase_json_query.c213
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;
+}