]>
Commit | Line | Data |
---|---|---|
f38b84ea | 1 | /* |
93ff0290 | 2 | * Copyright (c) 2009, 2010 Nicira Networks. |
f38b84ea BP |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #include <config.h> | |
18 | ||
19 | #include "json.h" | |
20 | ||
21 | #include <ctype.h> | |
22 | #include <errno.h> | |
23 | #include <getopt.h> | |
24 | #include <stdio.h> | |
25 | ||
26 | #include "util.h" | |
27 | ||
28 | /* --pretty: If set, the JSON output is pretty-printed, instead of printed as | |
29 | * compactly as possible. */ | |
30 | static int pretty = 0; | |
31 | ||
32 | /* --multiple: If set, the input is a sequence of JSON objects or arrays, | |
33 | * instead of exactly one object or array. */ | |
34 | static int multiple = 0; | |
35 | ||
36 | static bool | |
37 | print_and_free_json(struct json *json) | |
38 | { | |
39 | bool ok; | |
40 | if (json->type == JSON_STRING) { | |
41 | printf("error: %s\n", json->u.string); | |
42 | ok = false; | |
43 | } else { | |
44 | char *s = json_to_string(json, JSSF_SORT | (pretty ? JSSF_PRETTY : 0)); | |
45 | puts(s); | |
46 | free(s); | |
47 | ok = true; | |
48 | } | |
49 | json_destroy(json); | |
50 | return ok; | |
51 | } | |
52 | ||
53 | static bool | |
54 | refill(FILE *file, void *buffer, size_t buffer_size, size_t *n, size_t *used) | |
55 | { | |
56 | *used = 0; | |
57 | if (feof(file)) { | |
58 | *n = 0; | |
59 | return false; | |
60 | } else { | |
61 | *n = fread(buffer, 1, buffer_size, file); | |
62 | if (ferror(file)) { | |
63 | ovs_fatal(errno, "Error reading input file"); | |
64 | } | |
65 | return *n > 0; | |
66 | } | |
67 | } | |
68 | ||
69 | static bool | |
5562d6f5 | 70 | parse_multiple(FILE *stream) |
f38b84ea BP |
71 | { |
72 | struct json_parser *parser; | |
73 | char buffer[BUFSIZ]; | |
74 | size_t n, used; | |
f38b84ea BP |
75 | bool ok; |
76 | ||
f38b84ea BP |
77 | parser = NULL; |
78 | n = used = 0; | |
79 | ok = true; | |
5562d6f5 | 80 | while (used < n || refill(stream, buffer, sizeof buffer, &n, &used)) { |
f38b84ea BP |
81 | if (!parser && isspace((unsigned char) buffer[used])) { |
82 | /* Skip white space. */ | |
83 | used++; | |
84 | } else { | |
85 | if (!parser) { | |
86 | parser = json_parser_create(0); | |
87 | } | |
88 | ||
f2129093 | 89 | used += json_parser_feed(parser, &buffer[used], n - used); |
f38b84ea BP |
90 | if (used < n) { |
91 | if (!print_and_free_json(json_parser_finish(parser))) { | |
92 | ok = false; | |
93 | } | |
94 | parser = NULL; | |
95 | } | |
96 | } | |
97 | } | |
98 | if (parser) { | |
99 | if (!print_and_free_json(json_parser_finish(parser))) { | |
100 | ok = false; | |
101 | } | |
102 | } | |
103 | return ok; | |
104 | } | |
105 | ||
106 | int | |
107 | main(int argc, char *argv[]) | |
108 | { | |
109 | const char *input_file; | |
5562d6f5 | 110 | FILE *stream; |
f38b84ea BP |
111 | bool ok; |
112 | ||
113 | set_program_name(argv[0]); | |
114 | ||
115 | for (;;) { | |
116 | static const struct option options[] = { | |
117 | {"pretty", no_argument, &pretty, 1}, | |
118 | {"multiple", no_argument, &multiple, 1}, | |
119 | }; | |
120 | int option_index = 0; | |
121 | int c = getopt_long (argc, argv, "", options, &option_index); | |
122 | ||
123 | if (c == -1) { | |
124 | break; | |
125 | } | |
126 | switch (c) { | |
127 | case 0: | |
128 | break; | |
129 | ||
130 | case '?': | |
131 | exit(1); | |
132 | ||
133 | default: | |
134 | abort(); | |
135 | } | |
136 | } | |
137 | ||
138 | if (argc - optind != 1) { | |
139 | ovs_fatal(0, "usage: %s [--pretty] [--multiple] INPUT.json", | |
140 | program_name); | |
141 | } | |
142 | ||
143 | input_file = argv[optind]; | |
5562d6f5 BP |
144 | stream = !strcmp(input_file, "-") ? stdin : fopen(input_file, "r"); |
145 | if (!stream) { | |
146 | ovs_fatal(errno, "Cannot open \"%s\"", input_file); | |
f38b84ea BP |
147 | } |
148 | ||
149 | if (multiple) { | |
5562d6f5 | 150 | ok = parse_multiple(stream); |
f38b84ea | 151 | } else { |
5562d6f5 | 152 | ok = print_and_free_json(json_from_stream(stream)); |
f38b84ea BP |
153 | } |
154 | ||
93ff0290 BP |
155 | fclose(stream); |
156 | ||
f38b84ea BP |
157 | return !ok; |
158 | } |