Pārlūkot izejas kodu

cli: gather all found items through a callback function

Jo-Philipp Wich 10 gadi atpakaļ
vecāks
revīzija
2163483050
1 mainītis faili ar 117 papildinājumiem un 58 dzēšanām
  1. 117 58
      main.c

+ 117 - 58
main.c

@@ -25,10 +25,18 @@
 	#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)
 {
@@ -91,75 +99,95 @@ print_string(const char *s)
 }
 
 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",
@@ -170,18 +198,48 @@ export_type(struct json_object *jsobj, const char *prefix)
 		"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);
 
@@ -193,24 +251,25 @@ filter_json(int opt, struct json_object *jsobj, char *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);