• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/json-c/apps/json_parse.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt