1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <sys/param.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <jansson.h>
10 #include <errno.h>
11 #include <sys/types.h>
12
13 // MIT licensed, (c) 2011 Kyle Keen <keenerd@gmail.com>
14
15 /*
16 build with gcc -o jshon jshon.c -ljansson
17
18 stdin is always json
19 stdout is always json (except for -u, -t, -l, -k)
20
21 -P -> detect and ignore JSONP wrapper, if present
22 -S -> sort keys when writing objects
23 -Q -> quiet, suppress stderr
24 -V -> enable slower/safer pass-by-value
25 -C -> continue through errors
26 -F path -> read from file instead of stdin
27 -I -> change file in place, requires -F
28 -0 -> null delimiters
29
30 -t(ype) -> str, object, list, number, bool, null
31 -l(ength) -> only works on str, dict, list
32 -k(eys) -> only works on dict
33 -e(xtract) index -> only works on dict, list
34 -s(tring) value -> adds json escapes
35 -n(onstring) value -> creates true/false/null/array/object/int/float
36 -u(nstring) -> removes json escapes, display value
37 -j(son literal) -> preserves json escapes, display value
38 -p(op) -> pop/undo the last manipulation
39 -d(elete) index -> remove an element from an object or array
40 -i(nsert) index -> opposite of extract, merges json up the stack
41 objects will overwrite, arrays will insert
42 arrays can take negative numbers or 'append'
43 -a(cross) -> iterate across the current dict or list
44
45 --version -> returns an arbitrary number, exits
46
47 Multiple commands can be chained.
48 Entire json is loaded into memory.
49 -e/-a copies and stores on a stack with -V.
50 Could use up a lot of memory, usually does not.
51 (For now we don't have to worry about circular refs,
52 but adding 'swap' breaks that proof.)
53
54 Consider a golf mode with shortcuts for -e -a -u -p -l
55 -g 'results.*.Name.!.^.Version.!.^.Description.!'
56 -g 'data.children.*.data.url.!'
57 -g 'c.d.!.^.e.!'
58 (! on object/array does -l)
59 If you have keys with .!^* in them, use the normal options.
60 Implementing this is going to be a pain.
61 Maybe overwrite the original argv data?
62 Maybe two nested parse loops?
63
64 -L(abel)
65 add jsonpipe/style/prefix/labels\t to pretty-printed json
66
67 color?
68 loadf for stdin?
69 */
70
71 #define JSHONVER 20131105
72
73 // deal with API incompatibility between jansson 1.x and 2.x
74 #ifndef JANSSON_MAJOR_VERSION
75 # define JANSSON_MAJOR_VERSION (1)
76 #endif
77
78 #if JANSSON_MAJOR_VERSION < 2
79 # define compat_json_loads json_loads
80 #else
compat_json_loads(const char * input,json_error_t * error)81 static json_t *compat_json_loads(const char *input, json_error_t *error)
82 {
83 return json_loads(input, 0, error);
84 }
85 #endif
86
87 #if JANSSON_VERSION_HEX < 0x020400
88 # define JSON_ESCAPE_SLASH 0
89 #endif
90
91 #if (defined (__SVR4) && defined (__sun)) || defined (_WIN32)
92 #include <stdarg.h>
93
94 #ifdef _WIN32
95 typedef unsigned int uint;
96 // Avoid no-declared error for mingw/gcc with -std=c99.
97 extern int fileno(FILE*);
98 extern char* strdup(const char*);
99 #endif
100
asprintf(char ** ret,const char * format,...)101 int asprintf(char **ret, const char *format, ...)
102 {
103 va_list ap;
104 fprintf(stderr, "%s\n", "in the asprintf");
105
106 *ret = NULL; /* Ensure value can be passed to free() */
107
108 va_start(ap, format);
109 int count = vsnprintf(NULL, 0, format, ap);
110 va_end(ap);
111
112 if (count >= 0)
113 {
114 char* buffer = malloc(count + 1);
115 if (buffer == NULL)
116 {return -1;}
117
118 va_start(ap, format);
119 count = vsnprintf(buffer, count + 1, format, ap);
120 va_end(ap);
121
122 if (count < 0)
123 {
124 free(buffer);
125 return count;
126 }
127 *ret = buffer;
128 }
129
130 return count;
131 }
132 #endif
133
134 int dumps_flags = JSON_INDENT(1) | JSON_PRESERVE_ORDER | JSON_ESCAPE_SLASH;
135 int dumps_compact = JSON_INDENT(0) | JSON_COMPACT | JSON_PRESERVE_ORDER | JSON_ESCAPE_SLASH;
136 int by_value = 0;
137 int in_place = 0;
138 char delim = '\n';
139 char* file_path = "";
140
141 // for error reporting
142 int quiet = 0;
143 int crash = 1;
144 char** g_argv;
145
146 // stack depth is limited by maxargs
147 // if you need more depth, use a SAX parser
148 #define STACKDEPTH 128
149
150 json_t* stack[STACKDEPTH];
151 json_t** stackpointer = stack;
152
err(char * message)153 void err(char* message)
154 // also see arg_err() and json_err() below
155 {
156 if (!quiet)
157 {fprintf(stderr, "%s\n", message);}
158 if (crash)
159 {exit(1);}
160 }
161
hard_err(char * message)162 void hard_err(char* message)
163 {
164 err(message);
165 exit(1);
166 }
167
arg_err(char * message)168 void arg_err(char* message)
169 {
170 char* temp;
171 int i;
172 i = asprintf(&temp, message, optind-1, g_argv[optind-1]);
173 if (i == -1)
174 {hard_err("internal error: out of memory");}
175 err(temp);
176 }
177
PUSH(json_t * json)178 void PUSH(json_t* json)
179 {
180 if (stackpointer >= &stack[STACKDEPTH])
181 {hard_err("internal error: stack overflow");}
182 if (json == NULL)
183 {
184 arg_err("parse error: bad json on arg %i, \"%s\"");
185 json = json_null();
186 }
187 *stackpointer++ = json;
188 }
189
stack_safe_peek()190 json_t** stack_safe_peek()
191 {
192 if (stackpointer < &stack[1])
193 {
194 err("internal error: stack underflow");
195 PUSH(json_null());
196 }
197 return stackpointer - 1;
198 }
199
200 // can not use two macros on the same line
201 #define POP *((stackpointer = stack_safe_peek()))
202 #define PEEK *(stack_safe_peek())
203
maybe_deep(json_t * json)204 json_t* maybe_deep(json_t* json)
205 {
206 if (by_value)
207 {return json_deep_copy(json);}
208 return json;
209 }
210
211 typedef struct
212 {
213 void* itr; // object iterator
214 json_t** stk; // stack reentry
215 uint lin; // array iterator
216 int opt; // optind reentry
217 int fin; // finished iteration
218 } mapping;
219
220 mapping mapstack[STACKDEPTH];
221 mapping* mapstackpointer = mapstack;
222
map_safe_peek()223 mapping* map_safe_peek()
224 {
225 if (mapstackpointer < &mapstack[1])
226 {hard_err("internal error: mapstack underflow");}
227 return mapstackpointer - 1;
228 }
229
MAPPUSH()230 void MAPPUSH()
231 {
232 if (mapstackpointer >= &mapstack[STACKDEPTH])
233 {hard_err("internal error: mapstack overflow");}
234 mapstackpointer++;
235 map_safe_peek()->stk = stack_safe_peek();
236 map_safe_peek()->opt = optind;
237 switch (json_typeof(PEEK))
238 {
239 case JSON_OBJECT:
240 map_safe_peek()->itr = json_object_iter(PEEK);
241 map_safe_peek()->fin = !map_safe_peek()->itr;
242 break;
243 case JSON_ARRAY:
244 map_safe_peek()->lin = 0;
245 map_safe_peek()->fin = json_array_size(*(map_safe_peek()->stk)) == 0;
246 break;
247 default:
248 err("parse error: type not mappable");
249 }
250 }
251
MAPNEXT()252 void MAPNEXT()
253 {
254 stackpointer = map_safe_peek()->stk + 1;
255 optind = map_safe_peek()->opt;
256 switch (json_typeof(*(map_safe_peek()->stk)))
257 {
258 case JSON_OBJECT:
259 json_object_iter_key(map_safe_peek()->itr);
260 PUSH(maybe_deep(json_object_iter_value(map_safe_peek()->itr)));
261 map_safe_peek()->itr = json_object_iter_next(*(map_safe_peek()->stk), map_safe_peek()->itr);
262 if (!map_safe_peek()->itr)
263 {map_safe_peek()->fin = 1;}
264 break;
265 case JSON_ARRAY:
266 PUSH(maybe_deep(json_array_get(*(map_safe_peek()->stk), map_safe_peek()->lin)));
267 map_safe_peek()->lin++;
268 if (map_safe_peek()->lin >= json_array_size(*(map_safe_peek()->stk)))
269 {map_safe_peek()->fin = 1;}
270 break;
271 default:
272 err("parse error: type not mappable");
273 map_safe_peek()->fin = 1;
274 }
275 }
276
MAPPOP()277 void MAPPOP()
278 {
279 stackpointer = map_safe_peek()->stk;
280 optind = map_safe_peek()->opt;
281 mapstackpointer = map_safe_peek();
282 }
283
284 // can not use two macros on the same line
285 #define MAPPEEK *(map_safe_peek())
286 #define MAPEMPTY (mapstackpointer == mapstack)
287
loop_read_fd(int fd)288 char* loop_read_fd(int fd)
289 {
290 char buffer[BUFSIZ];
291 char *content = NULL;
292 size_t content_size = 0;
293 size_t content_capacity = BUFSIZ * 2.5;
294
295 content = malloc(content_capacity);
296 if (content == NULL)
297 {
298 fprintf(stderr, "error: failed to allocate %zd bytes\n", content_capacity);
299 return NULL;
300 }
301
302 for (;;)
303 {
304 ssize_t bytes_r = read(fd, buffer, sizeof(buffer));
305 if (bytes_r < 0)
306 {
307 fprintf(stderr, "error: failed to read from fd: %s\n", strerror(errno));
308 goto fail;
309 }
310
311 if (bytes_r == 0)
312 {
313 return content;
314 }
315
316 if (content_size + bytes_r >= content_capacity)
317 {
318 content_capacity *= 2.5;
319 void *newalloc = realloc(content, content_capacity);
320 if (newalloc == NULL)
321 {
322 fprintf(stderr, "error: failed to reallocate buffer to %zd bytes\n",
323 content_capacity);
324 goto fail;
325 }
326 content = newalloc;
327 }
328
329 memcpy(&content[content_size], buffer, bytes_r);
330 content_size += bytes_r;
331 content[content_size] = '\0';
332 }
333
334 return content;
335
336 fail:
337 free(content);
338 return NULL;
339 }
340
read_stream(FILE * fp)341 char* read_stream(FILE* fp)
342 {
343 struct stat st;
344 char *buffer;
345
346 if (fstat(fileno(fp), &st) < 0)
347 {
348 fprintf(stderr, "failed to stat file: %s\n", strerror(errno));
349 return NULL;
350 }
351
352 if (st.st_size == 0 && lseek(fileno(fp), 0, SEEK_CUR) < 0)
353 {
354 return loop_read_fd(fileno(fp));
355 }
356
357 buffer = malloc(st.st_size + 1);
358 if (buffer == NULL)
359 {
360 fprintf(stderr, "error: failed to allocate %zd bytes\n", (ssize_t)(st.st_size + 1));
361 return NULL;
362 }
363
364 size_t bytes_r = fread(buffer, 1, st.st_size, fp);
365 if ((ssize_t)bytes_r != st.st_size)
366 {
367 fprintf(stderr, "short read: expected to read %zd bytes, only got %zd\n",
368 (ssize_t)st.st_size, (ssize_t)bytes_r);
369 }
370
371 buffer[bytes_r] = 0;
372
373 return buffer;
374 }
375
read_stdin(void)376 char* read_stdin(void)
377 {
378 if (isatty(fileno(stdin)))
379 {return "";}
380 return read_stream(stdin);
381 }
382
read_file(char * path)383 char* read_file(char* path)
384 {
385 FILE* fp;
386 char* content;
387 fp = fopen(path, "r");
388 if ( !fp ) {
389 fprintf(stderr, "unable to read file %s: %s\n", path, strerror(errno));
390 return NULL;
391 }
392 content = read_stream(fp);
393 fclose(fp);
394 return content;
395 }
396
remove_jsonp_callback(char * in,int * rows_skipped,int * cols_skipped)397 char* remove_jsonp_callback(char* in, int* rows_skipped, int* cols_skipped)
398 // this 'removes' jsonp callback code which can surround json, by returning
399 // a pointer to first byte of real JSON, and overwriting the jsonp stuff at
400 // the end of the input with a null byte. it also writes out the number of
401 // lines, and then columns, which were skipped over.
402 //
403 // if a legitimate jsonp callback surround is not detected, the original
404 // input is returned and no other action is taken. this means that JSONP
405 // syntax errors will be effectively ignored, and will then fail json parsing
406 //
407 // this doesn't detect all conceivable JSONP wrappings. a simple function call
408 // with a reasonable ASCII identifier will work, and that covers 99% of the
409 // real world
410 {
411 #define JSON_WHITE(x) ((x) == 0x20 || (x) == 0x9 || (x) == 0xA || (x) == 0xD)
412 #define JSON_IDENTIFIER(x) (isalnum(x) || (x) == '$' || (x) == '_' || (x) == '.')
413
414 char* first = in;
415 char* last = in + strlen(in) - 1;
416
417 // skip over whitespace and semicolons at the end
418 while (first < last && (JSON_WHITE(*last) || *last == ';'))
419 {--last;}
420
421 // count closing brackets at the end, still skipping whitespace
422 int brackets = 0;
423 while (first < last && (JSON_WHITE(*last) || *last == ')'))
424 {
425 if (*last == ')')
426 {++brackets;}
427 --last;
428 }
429
430 // no closing brackets? it's not jsonp
431 if (brackets == 0)
432 {return in;}
433
434 // skip leading whitespace
435 while (first < last && JSON_WHITE(*first))
436 {++first;}
437
438 // skip leading identifier if present
439 while (first < last && JSON_IDENTIFIER(*first))
440 {++first;}
441
442 // skip over forward brackets and whitespace, counting down the opening brackets
443 // against the closing brackets we've already done
444 while (first < last && (JSON_WHITE(*first) || *first == '('))
445 {
446 if (*first == '(')
447 {--brackets;}
448 ++first;
449 }
450
451 // at this point we have a valid jsonp wrapper, provided that the number of opening
452 // and closing brackets matched, and provided the two pointers didn't meet in
453 // the middle (leaving no room for any actual JSON)
454 if (brackets != 0 || !(first < last))
455 {return in;}
456
457 // count lines and columns skipped over
458 *rows_skipped = *cols_skipped = 0;
459 while (in < first)
460 {
461 ++*cols_skipped;
462 if (*in++ == '\n')
463 {
464 *cols_skipped = 0;
465 ++*rows_skipped;
466 }
467 }
468
469 // strip off beginning and end
470 *(last+1) = '\0';
471 return first;
472 }
473
474 #if JANSSON_VERSION_HEX < 0x020100
smart_dumps(json_t * json,int flags)475 char* smart_dumps(json_t* json, int flags)
476 // json_dumps is broken on simple types
477 {
478 char* temp;
479 char* temp2;
480 json_t* j2;
481 int i;
482 if (!flags)
483 {flags = dumps_flags;}
484 switch (json_typeof(json))
485 {
486 case JSON_OBJECT:
487 return json_dumps(json, flags);
488 case JSON_ARRAY:
489 return json_dumps(json, flags);
490 case JSON_STRING:
491 // hack to print escaped string
492 j2 = json_array();
493 json_array_append(j2, json);
494 temp = json_dumps(j2, JSON_ESCAPE_SLASH);
495 i = asprintf(&temp2, "%.*s", (signed)strlen(temp)-2, &temp[1]);
496 if (i == -1)
497 {hard_err("internal error: out of memory");}
498 return temp2;
499 case JSON_INTEGER:
500 i = asprintf(&temp, "%" JSON_INTEGER_FORMAT, json_integer_value(json));
501 if (i == -1)
502 {hard_err("internal error: out of memory");}
503 return temp;
504 case JSON_REAL:
505 i = asprintf(&temp, "%f", json_real_value(json));
506 if (i == -1)
507 {hard_err("internal error: out of memory");}
508 return temp;
509 case JSON_TRUE:
510 return "true";
511 case JSON_FALSE:
512 return "false";
513 case JSON_NULL:
514 return "null";
515 default:
516 err("internal error: unknown type");
517 return "null";
518 }
519 }
520 #else
smart_dumps(json_t * json,int flags)521 char* smart_dumps(json_t* json, int flags)
522 {
523 if (!flags)
524 {flags = dumps_flags;}
525 switch (json_typeof(json))
526 {
527 case JSON_OBJECT:
528 case JSON_ARRAY:
529 case JSON_STRING:
530 case JSON_INTEGER:
531 case JSON_REAL:
532 case JSON_TRUE:
533 case JSON_FALSE:
534 case JSON_NULL:
535 return json_dumps(json, flags | JSON_ENCODE_ANY);
536 default:
537 err("internal error: unknown type");
538 return "null";
539 }
540 }
541 #endif
542
543 /*char* pretty_dumps(json_t* json)
544 // underscore-style colorizing
545 // needs a more or less rewrite of dumps()
546 {
547 int depth = 0;
548 // loop over everything
549 // needs a stack
550 // number, orange
551 // string, green
552 // null, bold white
553 // string, purple?
554 }*/
555
556 #if JANSSON_VERSION_HEX < 0x020300
smart_loads(char * j_string)557 json_t* smart_loads(char* j_string)
558 // json_loads is broken on simple types
559 {
560 json_t* json;
561 json_error_t error;
562 char *temp;
563 int i;
564 i = asprintf(&temp, "[%s]", j_string);
565 if (i == -1)
566 {hard_err("internal error: out of memory");}
567 json = compat_json_loads(temp, &error);
568 if (!json)
569 {return json_string(j_string);}
570 return json_array_get(json, 0);
571 }
572 #else
smart_loads(char * j_string)573 json_t* smart_loads(char* j_string)
574 {
575 json_error_t error;
576 return json_loads(j_string, JSON_DECODE_ANY, &error);
577 }
578 #endif
579
pretty_type(json_t * json)580 char* pretty_type(json_t* json)
581 {
582 if (json == NULL)
583 {err("internal error: null pointer"); return "NULL";}
584 switch (json_typeof(json))
585 {
586 case JSON_OBJECT:
587 return "object";
588 case JSON_ARRAY:
589 return "array";
590 case JSON_STRING:
591 return "string";
592 case JSON_INTEGER:
593 case JSON_REAL:
594 return "number";
595 case JSON_TRUE:
596 case JSON_FALSE:
597 return "bool";
598 case JSON_NULL:
599 return "null";
600 default:
601 err("internal error: unknown type");
602 return "NULL";
603 }
604 }
605
json_err(char * message,json_t * json)606 void json_err(char* message, json_t* json)
607 {
608 char* temp;
609 int i;
610 i = asprintf(&temp, "parse error: type '%s' %s (arg %i)", pretty_type(json), message, optind-1);
611 if (i == -1)
612 {hard_err("internal error: out of memory");}
613 err(temp);
614 }
615
length(json_t * json)616 int length(json_t* json)
617 {
618 switch (json_typeof(json))
619 {
620 case JSON_OBJECT:
621 return json_object_size(json);
622 case JSON_ARRAY:
623 return json_array_size(json);
624 case JSON_STRING:
625 return strlen(json_string_value(json));
626 case JSON_INTEGER:
627 case JSON_REAL:
628 case JSON_TRUE:
629 case JSON_FALSE:
630 case JSON_NULL:
631 default:
632 json_err("has no length", json);
633 return 0;
634 }
635 }
636
compare_strcmp(const void * a,const void * b)637 int compare_strcmp(const void *a, const void *b)
638 {
639 const char *sa = ((const char**)a)[0];
640 const char *sb = ((const char**)b)[0];
641 return strcmp(sa, sb);
642 }
643
keys(json_t * json)644 void keys(json_t* json)
645 // shoddy, prints directly
646 {
647 void* iter;
648 const char** keys;
649 size_t i, n;
650
651 if (!json_is_object(json))
652 {json_err("has no keys", json); return;}
653 if (!((keys = malloc(sizeof(char*) * json_object_size(json)))))
654 {hard_err("internal error: out of memory");}
655
656 iter = json_object_iter(json);
657 n = 0;
658 while (iter)
659 {
660 keys[n++] = json_object_iter_key(iter);
661 iter = json_object_iter_next(json, iter);
662 }
663
664 if (dumps_flags & JSON_SORT_KEYS)
665 {qsort(keys, n, sizeof(char*), compare_strcmp);}
666
667 for (i = 0; i < n; ++i)
668 {printf("%s\n", keys[i]);}
669
670 free(keys);
671 }
672
nonstring(char * arg)673 json_t* nonstring(char* arg)
674 {
675 json_t* temp;
676 char* endptr;
677 if (!strcmp(arg, "null") || !strcmp(arg, "n"))
678 {return json_null();}
679 if (!strcmp(arg, "true") || !strcmp(arg, "t"))
680 {return json_true();}
681 if (!strcmp(arg, "false") || !strcmp(arg, "f"))
682 {return json_false();}
683 if (!strcmp(arg, "array") || !strcmp(arg, "[]"))
684 {return json_array();}
685 if (!strcmp(arg, "object") || !strcmp(arg, "{}"))
686 {return json_object();}
687 errno = 0;
688 temp = json_integer(strtol(arg, &endptr, 10));
689 if (!errno && *endptr=='\0')
690 {return temp;}
691 errno = 0;
692 temp = json_real(strtod(arg, &endptr));
693 if (!errno && *endptr=='\0')
694 {return temp;}
695 arg_err("parse error: illegal nonstring on arg %i, \"%s\"");
696 return json_null();
697 }
698
unstring(json_t * json)699 const char* unstring(json_t* json)
700 {
701 switch (json_typeof(json))
702 {
703 case JSON_STRING:
704 return json_string_value(json);
705 case JSON_INTEGER:
706 case JSON_REAL:
707 case JSON_TRUE:
708 case JSON_FALSE:
709 case JSON_NULL:
710 return smart_dumps(json, 0);
711 case JSON_OBJECT:
712 case JSON_ARRAY:
713 default:
714 json_err("is not simple/printable", json);
715 return "";
716 }
717 }
718
estrtol(char * key)719 int estrtol(char* key)
720 // strtol with more error handling
721 {
722 int i;
723 char* endptr;
724 errno = 0;
725 i = strtol(key, &endptr, 10);
726 if (errno || *endptr!='\0')
727 {
728 arg_err("parse error: illegal index on arg %i, \"%s\"");
729 //return json_null();
730 i = 0;
731 }
732 return i;
733 }
734
extract(json_t * json,char * key)735 json_t* extract(json_t* json, char* key)
736 {
737 int i, s;
738 json_t* temp;
739 switch (json_typeof(json))
740 {
741 case JSON_OBJECT:
742 temp = json_object_get(json, key);
743 if (temp == NULL)
744 {break;}
745 return temp;
746 case JSON_ARRAY:
747 s = json_array_size(json);
748 if (s == 0)
749 {json_err("index out of bounds", json); break;}
750 i = estrtol(key);
751 if ((i < -s) || (i >= s))
752 {json_err("index out of bounds", json);}
753 // stupid fix for a stupid modulus operation
754 while (i<0)
755 {i+=s;}
756 return json_array_get(json, i % s);
757 case JSON_STRING:
758 case JSON_INTEGER:
759 case JSON_REAL:
760 case JSON_TRUE:
761 case JSON_FALSE:
762 case JSON_NULL:
763 default:
764 break;
765 }
766 json_err("has no elements to extract", json);
767 return json_null();
768 }
769
delete(json_t * json,char * key)770 json_t* delete(json_t* json, char* key)
771 // no error checking
772 {
773 int i, s;
774 switch (json_typeof(json))
775 {
776 case JSON_OBJECT:
777 json_object_del(json, key);
778 return json;
779 case JSON_ARRAY:
780 s = json_array_size(json);
781 if (s == 0)
782 {return json;}
783 i = estrtol(key);
784 json_array_remove(json, i % s);
785 return json;
786 case JSON_STRING:
787 case JSON_INTEGER:
788 case JSON_REAL:
789 case JSON_TRUE:
790 case JSON_FALSE:
791 case JSON_NULL:
792 default:
793 json_err("cannot lose elements", json);
794 return json;
795 }
796 }
797
update_native(json_t * json,char * key,json_t * j_value)798 json_t* update_native(json_t* json, char* key, json_t* j_value)
799 // no error checking
800 {
801 int i, s;
802 switch (json_typeof(json))
803 {
804 case JSON_OBJECT:
805 json_object_set(json, key, j_value);
806 return json;
807 case JSON_ARRAY:
808 if (!strcmp(key, "append"))
809 {
810 json_array_append(json, j_value);
811 return json;
812 }
813 // otherwise, insert
814 i = estrtol(key);
815 s = json_array_size(json);
816 if (s == 0)
817 {i = 0;}
818 else
819 {i = i % s;}
820 json_array_insert(json, i, j_value);
821 return json;
822 case JSON_STRING:
823 case JSON_INTEGER:
824 case JSON_REAL:
825 case JSON_TRUE:
826 case JSON_FALSE:
827 case JSON_NULL:
828 default:
829 json_err("cannot gain elements", json);
830 return json;
831 }
832 }
833
update(json_t * json,char * key,char * j_string)834 json_t* update(json_t* json, char* key, char* j_string)
835 {
836 return update_native(json, key, smart_loads(j_string));
837 }
838
debug_stack(int optchar)839 void debug_stack(int optchar)
840 {
841 json_t** j;
842 printf("BEGIN STACK DUMP %c\n", optchar);
843 for (j=stack; j<stackpointer; j++)
844 {printf("%s\n", smart_dumps(*j, 0));}
845 }
846
debug_map()847 void debug_map()
848 {
849 mapping* m;
850 printf("BEGIN MAP DUMP\n");
851 for (m=mapstack; m<mapstackpointer; m++)
852 {printf("%s\n", smart_dumps(*(m->stk), 0));}
853 }
854
main(int argc,char * argv[])855 int main (int argc, char *argv[])
856 #define ALL_OPTIONS "PSQVCI0tlkupajF:e:s:n:d:i:"
857 {
858 char* content = "";
859 char* arg1 = "";
860 FILE* fp;
861 json_t* json = NULL;
862 json_t* jval = NULL;
863 json_error_t error;
864 int output = 1; // flag if json should be printed
865 int optchar;
866 int jsonp = 0; // flag if we should tolerate JSONP wrapping
867 int jsonp_rows = 0, jsonp_cols = 0; // rows+cols skipped over by JSONP prologue
868 int empty;
869 g_argv = argv;
870
871 // todo: get more jsonp stuff out of main
872
873 // avoiding getopt_long for now because the BSD version is a pain
874 if (argc == 2 && strncmp(argv[1], "--version", 9) == 0)
875 {printf("%i\n", JSHONVER); exit(0);}
876
877 // non-manipulation options
878 while ((optchar = getopt(argc, argv, ALL_OPTIONS)) != -1)
879 {
880 switch (optchar)
881 {
882 case 'P':
883 jsonp = 1;
884 break;
885 case 'S':
886 dumps_flags &= ~JSON_PRESERVE_ORDER;
887 dumps_flags |= JSON_SORT_KEYS;
888 dumps_compact &= ~JSON_PRESERVE_ORDER;
889 dumps_compact |= JSON_SORT_KEYS;
890 break;
891 case 'Q':
892 quiet = 1;
893 break;
894 case 'V':
895 by_value = 1;
896 break;
897 case 'C':
898 crash = 0;
899 break;
900 case 'I':
901 in_place = 1;
902 break;
903 case 'F':
904 file_path = (char*) strdup(optarg);
905 break;
906 case '0':
907 delim = '\0';
908 break;
909 case 't':
910 case 'l':
911 case 'k':
912 case 'u':
913 case 'p':
914 case 'e':
915 case 'j':
916 case 's':
917 case 'n':
918 case 'd':
919 case 'i':
920 case 'a':
921 break;
922 default:
923 if (!quiet)
924 {fprintf(stderr, "Valid: -[P|S|Q|V|C|I|0] [-F path] -[t|l|k|u|p|a|j] -[s|n] value -[e|i|d] index\n");}
925 if (crash)
926 {exit(2);}
927 break;
928 }
929 }
930 optind = 1;
931 #ifdef BSD
932 optreset = 1;
933 #endif
934
935 if (in_place && strlen(file_path)==0)
936 {err("warning: in-place editing (-I) requires -F");}
937
938 if (!strcmp(file_path, "-"))
939 {content = read_stdin();}
940 else if (strlen(file_path) > 0)
941 {content = read_file(file_path);}
942 else
943 {content = read_stdin();}
944 if (!content) {
945 fprintf(stderr, "error: failed to read input\n");
946 exit(1);
947 }
948
949 if (jsonp)
950 {content = remove_jsonp_callback(content, &jsonp_rows, &jsonp_cols);}
951
952 if (content[0])
953 {json = compat_json_loads(content, &error);}
954
955 if (!json && content[0])
956 {
957 const char *jsonp_status = "";
958 if (jsonp)
959 {jsonp_status = (jsonp_rows||jsonp_cols) ? "(jsonp detected) " : "(jsonp not detected) ";}
960
961 #if JANSSON_MAJOR_VERSION < 2
962 if (!quiet)
963 {fprintf(stderr, "json %sread error: line %0d: %s\n",
964 jsonp_status, error.line + jsonp_rows, error.text);}
965 #else
966 if (!quiet)
967 {fprintf(stderr, "json %sread error: line %0d column %0d: %s\n",
968 jsonp_status, error.line + jsonp_rows, error.column + jsonp_cols, error.text);}
969 #endif
970 exit(1);
971 }
972
973 if (json)
974 {PUSH(json);}
975
976 do
977 {
978 if (! MAPEMPTY)
979 {
980 while (map_safe_peek()->fin)
981 {
982 MAPPOP();
983 if (MAPEMPTY)
984 {exit(0);}
985 }
986 MAPNEXT();
987 }
988 while ((optchar = getopt(argc, argv, ALL_OPTIONS)) != -1)
989 {
990 empty = 0;
991 switch (optchar)
992 {
993 case 't': // id type
994 printf("%s\n", pretty_type(PEEK));
995 output = 0;
996 break;
997 case 'l': // length
998 printf("%i\n", length(PEEK));
999 output = 0;
1000 break;
1001 case 'k': // keys
1002 keys(PEEK);
1003 output = 0;
1004 break;
1005 case 'u': // unescape string
1006 printf("%s%c", unstring(PEEK), delim);
1007 output = 0;
1008 break;
1009 case 'p': // pop stack
1010 json = POP;
1011 if (by_value)
1012 {json_decref(json);}
1013 output = 1;
1014 break;
1015 case 's': // load string
1016 arg1 = (char*) strdup(optarg);
1017 PUSH(json_string(arg1));
1018 output = 1;
1019 break;
1020 case 'n': // load nonstring
1021 arg1 = (char*) strdup(optarg);
1022 PUSH(nonstring(arg1));
1023 output = 1;
1024 break;
1025 case 'e': // extract
1026 arg1 = (char*) strdup(optarg);
1027 json = PEEK;
1028 PUSH(extract(maybe_deep(json), arg1));
1029 output = 1;
1030 break;
1031 case 'j': // json literal
1032 printf("%s%c", smart_dumps(PEEK, dumps_compact), delim);
1033 output = 0;
1034 break;
1035 case 'd': // delete
1036 arg1 = (char*) strdup(optarg);
1037 json = POP;
1038 PUSH(delete(json, arg1));
1039 output = 1;
1040 break;
1041 case 'i': // insert
1042 arg1 = (char*) strdup(optarg);
1043 jval = POP;
1044 json = POP;
1045 PUSH(update_native(json, arg1, jval));
1046 output = 1;
1047 break;
1048 case 'a': // across
1049 // something about -a is not mappable?
1050 MAPPUSH();
1051 empty = map_safe_peek()->fin;
1052 if (!empty)
1053 {MAPNEXT();}
1054 output = 0;
1055 break;
1056 case 'P': // not manipulations
1057 case 'S':
1058 case 'Q':
1059 case 'V':
1060 case 'C':
1061 case 'I':
1062 case 'F':
1063 case '0':
1064 break;
1065 default:
1066 if (crash)
1067 {exit(2);}
1068 break;
1069 }
1070 if (empty)
1071 {break;}
1072 }
1073 if (!in_place && output && stackpointer != stack)
1074 {printf("%s\n", smart_dumps(PEEK, 0));}
1075 } while (! MAPEMPTY);
1076
1077 if (in_place && strlen(file_path) > 0)
1078 {
1079 fp = fopen(file_path, "w");
1080 fprintf(fp, "%s\n", smart_dumps(stack[0], 0));
1081 fclose(fp);
1082 }
1083 return 0;
1084 }
1085
1086
1087