X-Git-Url: https://git.librecmc.org/?p=oweals%2Fjsonpath.git;a=blobdiff_plain;f=main.c;h=e4902d9c9a11744bd993be9908bb28ef9f0b1108;hp=7d232c5f656b21d80cdec72294192055823d176f;hb=691f1065ad33b5d53d342e8705a37563d9ebb8b5;hpb=325454c60f282994cf79c69d49edbcea53f2e924 diff --git a/main.c b/main.c index 7d232c5..e4902d9 100644 --- a/main.c +++ b/main.c @@ -99,10 +99,38 @@ print_string(const char *s) } static void -export_value(struct list_head *matches, const char *prefix) +print_separator(const char *sep, int *sc, int sl) +{ + if (*sc > 0) + { + switch (sep[(*sc - 1) % sl]) + { + case '"': + printf("'\"'"); + break; + + case '\'': + printf("\"'\""); + break; + + case ' ': + printf("\\ "); + break; + + default: + printf("%c", sep[(*sc - 1) % sl]); + } + } + + (*sc)++; +} + +static void +export_value(struct list_head *matches, const char *prefix, const char *sep, + int limit) { int n, len; - bool first = true; + int sc = 0, sl = strlen(sep); struct match_item *item; if (list_empty(matches)) @@ -114,6 +142,9 @@ export_value(struct list_head *matches, const char *prefix) list_for_each_entry(item, matches, list) { + if (limit-- <= 0) + break; + switch (json_object_get_type(item->jsobj)) { case json_type_object: @@ -123,11 +154,8 @@ export_value(struct list_head *matches, const char *prefix) if (!val) continue; - if (!first) - printf("\\ "); - + print_separator(sep, &sc, sl); print_string(key); - first = false; } break; @@ -135,43 +163,34 @@ export_value(struct list_head *matches, const char *prefix) for (n = 0, len = json_object_array_length(item->jsobj); n < len; n++) { - if (!first) - printf("\\ "); - + print_separator(sep, &sc, sl); printf("%d", n); - first = false; } break; case json_type_boolean: - if (!first) - printf("\\ "); + print_separator(sep, &sc, sl); printf("%d", json_object_get_boolean(item->jsobj)); break; case json_type_int: - if (!first) - printf("\\ "); + print_separator(sep, &sc, sl); printf("%d", json_object_get_int(item->jsobj)); break; case json_type_double: - if (!first) - printf("\\ "); + print_separator(sep, &sc, sl); printf("%f", json_object_get_double(item->jsobj)); break; case json_type_string: - if (!first) - printf("\\ "); + print_separator(sep, &sc, sl); print_string(json_object_get_string(item->jsobj)); break; case json_type_null: break; } - - first = false; } printf("; "); @@ -179,12 +198,33 @@ export_value(struct list_head *matches, const char *prefix) else { list_for_each_entry(item, matches, list) - printf("%s\n", json_object_to_json_string(item->jsobj)); + { + if (limit-- <= 0) + break; + + switch (json_object_get_type(item->jsobj)) + { + case json_type_object: + case json_type_array: + case json_type_boolean: + case json_type_int: + case json_type_double: + printf("%s\n", json_object_to_json_string(item->jsobj)); + break; + + case json_type_string: + printf("%s\n", json_object_get_string(item->jsobj)); + break; + + case json_type_null: + break; + } + } } } static void -export_type(struct list_head *matches, const char *prefix) +export_type(struct list_head *matches, const char *prefix, int limit) { bool first = true; struct match_item *item; @@ -209,6 +249,9 @@ export_type(struct list_head *matches, const char *prefix) if (!first) printf("\\ "); + if (limit-- <= 0) + break; + printf("%s", types[json_object_get_type(item->jsobj)]); first = false; } @@ -232,8 +275,60 @@ match_cb(struct json_object *res, void *priv) } } +static void +print_error(struct jp_state *state, char *expr) +{ + int i; + bool first = true; + + fprintf(stderr, "Syntax error: "); + + switch (state->error_code) + { + case -4: + fprintf(stderr, "Unexpected character\n"); + break; + + case -3: + fprintf(stderr, "String or label literal too long\n"); + break; + + case -2: + fprintf(stderr, "Invalid escape sequence\n"); + break; + + case -1: + fprintf(stderr, "Unterminated string\n"); + break; + + default: + for (i = 0; i < sizeof(state->error_code) * 8; i++) + { + if (state->error_code & (1 << i)) + { + fprintf(stderr, + first ? "Expecting %s" : " or %s", tokennames[i]); + + first = false; + } + } + + fprintf(stderr, "\n"); + break; + } + + fprintf(stderr, "In expression %s\n", expr); + fprintf(stderr, "Near here ----"); + + for (i = 0; i < state->error_pos; i++) + fprintf(stderr, "-"); + + fprintf(stderr, "^\n"); +} + static bool -filter_json(int opt, struct json_object *jsobj, char *expr) +filter_json(int opt, struct json_object *jsobj, char *expr, const char *sep, + int limit) { struct jp_state *state; const char *prefix = NULL; @@ -243,11 +338,14 @@ filter_json(int opt, struct json_object *jsobj, char *expr) state = jp_parse(expr); - if (!state || state->error) + if (!state) { - fprintf(stderr, "In expression '%s': %s\n", - expr, state ? state->error : "Out of memory"); - + fprintf(stderr, "Out of memory\n"); + goto out; + } + else if (state->error_code) + { + print_error(state, expr); goto out; } @@ -259,11 +357,11 @@ filter_json(int opt, struct json_object *jsobj, char *expr) switch (opt) { case 't': - export_type(&matches, prefix); + export_type(&matches, prefix, limit); break; default: - export_value(&matches, prefix); + export_value(&matches, prefix, sep, limit); break; } @@ -279,12 +377,12 @@ out: int main(int argc, char **argv) { - int opt, rv = 0; + int opt, rv = 0, limit = 0x7FFFFFFF; FILE *input = stdin; struct json_object *jsobj = NULL; - const char *jserr = NULL, *source = NULL; + const char *jserr = NULL, *source = NULL, *separator = " "; - while ((opt = getopt(argc, argv, "i:s:e:t:q")) != -1) + while ((opt = getopt(argc, argv, "i:s:e:t:F:l:q")) != -1) { switch (opt) { @@ -306,6 +404,15 @@ int main(int argc, char **argv) source = optarg; break; + case 'F': + if (optarg && *optarg) + separator = optarg; + break; + + case 'l': + limit = atoi(optarg); + break; + case 't': case 'e': if (!jsobj) @@ -322,7 +429,7 @@ int main(int argc, char **argv) } } - if (!filter_json(opt, jsobj, optarg)) + if (!filter_json(opt, jsobj, optarg, separator, limit)) rv = 1; break; @@ -337,7 +444,7 @@ out: if (jsobj) json_object_put(jsobj); - if (input != stdin) + if (input && input != stdin) fclose(input); return rv;