#include <json-c/json.h>
#endif
+#include <libubox/list.h>
+
#include "lexer.h"
#include "parser.h"
#include "matcher.h"
+
+struct match_item {
+ struct json_object *jsobj;
+ struct list_head list;
+};
+
static struct json_object *
parse_json(FILE *fd, const char *source, const char **error)
{
}
static void
-export_value(struct json_object *jsobj, const char *prefix)
+export_value(struct list_head *matches, const char *prefix)
{
int n, len;
bool first = true;
+ struct match_item *item;
+
+ if (list_empty(matches))
+ return;
if (prefix)
{
- switch (json_object_get_type(jsobj))
+ printf("export %s=", prefix);
+
+ list_for_each_entry(item, matches, list)
{
- case json_type_object:
- printf("export %s=", prefix);
- json_object_object_foreach(jsobj, key, val)
+ switch (json_object_get_type(item->jsobj))
{
- if (!val)
- continue;
+ case json_type_object:
+ ; /* a label can only be part of a statement */
+ json_object_object_foreach(item->jsobj, key, val)
+ {
+ if (!val)
+ continue;
- if (!first)
- printf("\\ ");
+ if (!first)
+ printf("\\ ");
- print_string(key);
- first = false;
- }
- printf("; ");
- break;
+ print_string(key);
+ first = false;
+ }
+ break;
- case json_type_array:
- printf("export %s=", prefix);
- for (n = 0, len = json_object_array_length(jsobj); n < len; n++)
- {
+ case json_type_array:
+ for (n = 0, len = json_object_array_length(item->jsobj);
+ n < len; n++)
+ {
+ if (!first)
+ printf("\\ ");
+
+ printf("%d", n);
+ first = false;
+ }
+ break;
+
+ case json_type_boolean:
if (!first)
printf("\\ ");
+ printf("%d", json_object_get_boolean(item->jsobj));
+ break;
- printf("%d", n);
- first = false;
- }
- printf("; ");
- break;
-
- case json_type_boolean:
- printf("export %s=%d; ", prefix, json_object_get_boolean(jsobj));
- break;
+ case json_type_int:
+ if (!first)
+ printf("\\ ");
+ printf("%d", json_object_get_int(item->jsobj));
+ break;
- case json_type_int:
- printf("export %s=%d; ", prefix, json_object_get_int(jsobj));
- break;
+ case json_type_double:
+ if (!first)
+ printf("\\ ");
+ printf("%f", json_object_get_double(item->jsobj));
+ break;
- case json_type_double:
- printf("export %s=%f; ", prefix, json_object_get_double(jsobj));
- break;
+ case json_type_string:
+ if (!first)
+ printf("\\ ");
+ print_string(json_object_get_string(item->jsobj));
+ break;
- case json_type_string:
- printf("export %s=", prefix);
- print_string(json_object_get_string(jsobj));
- printf("; ");
- break;
+ case json_type_null:
+ break;
+ }
- case json_type_null:
- break;
+ first = false;
}
+
+ printf("; ");
}
else
{
- printf("%s\n", json_object_to_json_string(jsobj));
+ list_for_each_entry(item, matches, list)
+ printf("%s\n", json_object_to_json_string(item->jsobj));
}
}
static void
-export_type(struct json_object *jsobj, const char *prefix)
+export_type(struct list_head *matches, const char *prefix)
{
+ bool first = true;
+ struct match_item *item;
const char *types[] = {
"null",
"boolean",
"string"
};
+ if (list_empty(matches))
+ return;
+
if (prefix)
- printf("export %s=%s; ", prefix, types[json_object_get_type(jsobj)]);
+ printf("export %s=", prefix);
+
+ list_for_each_entry(item, matches, list)
+ {
+ if (!first)
+ printf("\\ ");
+
+ printf("%s", types[json_object_get_type(item->jsobj)]);
+ first = false;
+ }
+
+ if (prefix)
+ printf("; ");
else
- printf("%s\n", types[json_object_get_type(jsobj)]);
+ printf("\n");
+}
+
+static void
+match_cb(struct json_object *res, void *priv)
+{
+ struct list_head *h = priv;
+ struct match_item *i = calloc(1, sizeof(*i));
+
+ if (i)
+ {
+ i->jsobj = res;
+ list_add_tail(&i->list, h);
+ }
}
static bool
filter_json(int opt, struct json_object *jsobj, char *expr)
{
struct jp_state *state;
- struct json_object *res = NULL;
const char *prefix = NULL;
+ struct list_head matches;
+ struct match_item *item, *tmp;
+ struct json_object *res = NULL;
state = jp_parse(expr);
goto out;
}
- res = jp_match(state->path, jsobj);
+ INIT_LIST_HEAD(&matches);
- if (res)
- {
- prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
+ res = jp_match(state->path, jsobj, match_cb, &matches);
+ prefix = (state->path->type == T_LABEL) ? state->path->str : NULL;
- switch (opt)
- {
- case 't':
- export_type(res, prefix);
- break;
+ switch (opt)
+ {
+ case 't':
+ export_type(&matches, prefix);
+ break;
- default:
- export_value(res, prefix);
- break;
- }
+ default:
+ export_value(&matches, prefix);
+ break;
}
+ list_for_each_entry_safe(item, tmp, &matches, list)
+ free(item);
+
out:
if (state)
jp_free(state);