You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

json_parse.c 4.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <getopt.h>
  5. #include <stddef.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include "config.h"
  11. #include "json_object.h"
  12. #include "json_tokener.h"
  13. #include "json_util.h"
  14. #ifdef HAVE_SYS_RESOURCE_H
  15. #include <sys/resource.h>
  16. #include <sys/time.h>
  17. #endif
  18. static int formatted_output = 0;
  19. static int show_output = 1;
  20. static int strict_mode = 0;
  21. static const char *fname = NULL;
  22. static void usage(int exitval, const char *errmsg);
  23. static void showmem(void);
  24. static int parseit(int fd, int (*callback)(struct json_object *));
  25. static int showobj(struct json_object *new_obj);
  26. static void showmem(void)
  27. {
  28. #ifdef HAVE_GETRUSAGE
  29. struct rusage rusage;
  30. memset(&rusage, 0, sizeof(rusage));
  31. getrusage(RUSAGE_SELF, &rusage);
  32. printf("maxrss: %d KB\n", rusage.ru_maxrss);
  33. #endif
  34. }
  35. static int parseit(int fd, int (*callback)(struct json_object *))
  36. {
  37. struct json_object *obj;
  38. char buf[32768];
  39. int ret;
  40. int depth = JSON_TOKENER_DEFAULT_DEPTH;
  41. json_tokener *tok;
  42. tok = json_tokener_new_ex(depth);
  43. if (!tok)
  44. {
  45. fprintf(stderr, "unable to allocate json_tokener: %s\n", strerror(errno));
  46. return 1;
  47. }
  48. json_tokener_set_flags(tok, JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS);
  49. // XXX push this into some kind of json_tokener_parse_fd API?
  50. // json_object_from_fd isn't flexible enough, and mirroring
  51. // everything you can do with a tokener into json_util.c seems
  52. // like the wrong approach.
  53. size_t total_read = 0;
  54. while ((ret = read(fd, buf, sizeof(buf))) > 0)
  55. {
  56. total_read += ret;
  57. int start_pos = 0;
  58. while (start_pos != ret)
  59. {
  60. obj = json_tokener_parse_ex(tok, &buf[start_pos], ret - start_pos);
  61. enum json_tokener_error jerr = json_tokener_get_error(tok);
  62. int parse_end = json_tokener_get_parse_end(tok);
  63. if (obj == NULL && jerr != json_tokener_continue)
  64. {
  65. char *aterr = &buf[start_pos + parse_end];
  66. fflush(stdout);
  67. int fail_offset = total_read - ret + start_pos + parse_end;
  68. fprintf(stderr, "Failed at offset %d: %s %c\n", fail_offset,
  69. json_tokener_error_desc(jerr), aterr[0]);
  70. json_tokener_free(tok);
  71. return 1;
  72. }
  73. if (obj != NULL)
  74. {
  75. int cb_ret = callback(obj);
  76. json_object_put(obj);
  77. if (cb_ret != 0)
  78. {
  79. json_tokener_free(tok);
  80. return 1;
  81. }
  82. }
  83. start_pos += json_tokener_get_parse_end(tok);
  84. assert(start_pos <= ret);
  85. }
  86. }
  87. if (ret < 0)
  88. {
  89. fprintf(stderr, "error reading fd %d: %s\n", fd, strerror(errno));
  90. }
  91. json_tokener_free(tok);
  92. return 0;
  93. }
  94. static int showobj(struct json_object *new_obj)
  95. {
  96. if (new_obj == NULL)
  97. {
  98. fprintf(stderr, "%s: Failed to parse\n", fname);
  99. return 1;
  100. }
  101. printf("Successfully parsed object from %s\n", fname);
  102. if (show_output)
  103. {
  104. const char *output;
  105. if (formatted_output)
  106. output = json_object_to_json_string(new_obj);
  107. else
  108. output = json_object_to_json_string_ext(new_obj, JSON_C_TO_STRING_PRETTY);
  109. printf("%s\n", output);
  110. }
  111. showmem();
  112. return 0;
  113. }
  114. static void usage(int exitval, const char *errmsg)
  115. {
  116. FILE *fp = stdout;
  117. if (exitval != 0)
  118. fp = stderr;
  119. if (errmsg != NULL)
  120. fprintf(fp, "ERROR: %s\n\n", errmsg);
  121. fprintf(fp, "Usage: %s [-f] [-n] [-s]\n");
  122. fprintf(fp, " -f - Format the output with JSON_C_TO_STRING_PRETTY\n");
  123. fprintf(fp, " -n - No output\n");
  124. fprintf(fp, " -s - Parse in strict mode, flags:\n");
  125. fprintf(fp, " JSON_TOKENER_STRICT|JSON_TOKENER_ALLOW_TRAILING_CHARS\n");
  126. fprintf(fp, "\nWARNING WARNING WARNING\n");
  127. fprintf(fp, "This is a prototype, it may change or be removed at any time!\n");
  128. exit(exitval);
  129. }
  130. int main(int argc, char **argv)
  131. {
  132. json_object *new_obj;
  133. int opt;
  134. while ((opt = getopt(argc, argv, "fns")) != -1)
  135. {
  136. switch (opt)
  137. {
  138. case 'f': formatted_output = 1; break;
  139. case 'n': show_output = 0; break;
  140. case 's': strict_mode = 1; break;
  141. default: /* '?' */ fprintf(stderr, "Usage: %s [-f]\n", argv[0]); exit(EXIT_FAILURE);
  142. }
  143. }
  144. if (optind >= argc)
  145. {
  146. fprintf(stderr, "Expected argument after options\n");
  147. exit(EXIT_FAILURE);
  148. }
  149. fname = argv[optind];
  150. int fd = open(argv[optind], O_RDONLY, 0);
  151. showmem();
  152. if (parseit(fd, showobj) != 0)
  153. exit(EXIT_FAILURE);
  154. showmem();
  155. exit(EXIT_SUCCESS);
  156. }