summaryrefslogtreecommitdiffstats
path: root/comm/third_party/json-c/json_visit.c
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/json-c/json_visit.c')
-rw-r--r--comm/third_party/json-c/json_visit.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/comm/third_party/json-c/json_visit.c b/comm/third_party/json-c/json_visit.c
new file mode 100644
index 0000000000..fb16fa6fa6
--- /dev/null
+++ b/comm/third_party/json-c/json_visit.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016 Eric Haszlakiewicz
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+#include <stdio.h>
+
+#include "config.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_visit.h"
+#include "linkhash.h"
+
+static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
+ size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg);
+
+int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc, void *userarg)
+{
+ int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg);
+ switch (ret)
+ {
+ case JSON_C_VISIT_RETURN_CONTINUE:
+ case JSON_C_VISIT_RETURN_SKIP:
+ case JSON_C_VISIT_RETURN_POP:
+ case JSON_C_VISIT_RETURN_STOP: return 0;
+ default: return JSON_C_VISIT_RETURN_ERROR;
+ }
+}
+static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
+ size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg)
+{
+ int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);
+ switch (userret)
+ {
+ case JSON_C_VISIT_RETURN_CONTINUE: break;
+ case JSON_C_VISIT_RETURN_SKIP:
+ case JSON_C_VISIT_RETURN_POP:
+ case JSON_C_VISIT_RETURN_STOP:
+ case JSON_C_VISIT_RETURN_ERROR: return userret;
+ default:
+ fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n",
+ userret);
+ return JSON_C_VISIT_RETURN_ERROR;
+ }
+
+ switch (json_object_get_type(jso))
+ {
+ case json_type_null:
+ case json_type_boolean:
+ case json_type_double:
+ case json_type_int:
+ case json_type_string:
+ // we already called userfunc above, move on to the next object
+ return JSON_C_VISIT_RETURN_CONTINUE;
+
+ case json_type_object:
+ {
+ json_object_object_foreach(jso, key, child)
+ {
+ userret = _json_c_visit(child, jso, key, NULL, userfunc, userarg);
+ if (userret == JSON_C_VISIT_RETURN_POP)
+ break;
+ if (userret == JSON_C_VISIT_RETURN_STOP ||
+ userret == JSON_C_VISIT_RETURN_ERROR)
+ return userret;
+ if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
+ userret != JSON_C_VISIT_RETURN_SKIP)
+ {
+ fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n",
+ userret);
+ return JSON_C_VISIT_RETURN_ERROR;
+ }
+ }
+ break;
+ }
+ case json_type_array:
+ {
+ size_t array_len = json_object_array_length(jso);
+ size_t ii;
+ for (ii = 0; ii < array_len; ii++)
+ {
+ json_object *child = json_object_array_get_idx(jso, ii);
+ userret = _json_c_visit(child, jso, NULL, &ii, userfunc, userarg);
+ if (userret == JSON_C_VISIT_RETURN_POP)
+ break;
+ if (userret == JSON_C_VISIT_RETURN_STOP ||
+ userret == JSON_C_VISIT_RETURN_ERROR)
+ return userret;
+ if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
+ userret != JSON_C_VISIT_RETURN_SKIP)
+ {
+ fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n",
+ userret);
+ return JSON_C_VISIT_RETURN_ERROR;
+ }
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n",
+ json_object_get_type(jso));
+ return JSON_C_VISIT_RETURN_ERROR;
+ }
+
+ // Call userfunc for the second type on container types, after all
+ // members of the container have been visited.
+ // Non-container types will have already returned before this point.
+
+ userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
+ switch (userret)
+ {
+ case JSON_C_VISIT_RETURN_SKIP:
+ case JSON_C_VISIT_RETURN_POP:
+ // These are not really sensible during JSON_C_VISIT_SECOND,
+ // but map them to JSON_C_VISIT_CONTINUE anyway.
+ // FALLTHROUGH
+ case JSON_C_VISIT_RETURN_CONTINUE: return JSON_C_VISIT_RETURN_CONTINUE;
+ case JSON_C_VISIT_RETURN_STOP:
+ case JSON_C_VISIT_RETURN_ERROR: return userret;
+ default:
+ fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n",
+ userret);
+ return JSON_C_VISIT_RETURN_ERROR;
+ }
+ // NOTREACHED
+}