]> git.proxmox.com Git - mirror_ovs.git/blob - tests/test-json.c
Implement JSON parsing and serialization.
[mirror_ovs.git] / tests / test-json.c
1 /*
2 * Copyright (c) 2009 Nicira Networks.
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
70 parse_multiple(const char *input_file)
71 {
72 struct json_parser *parser;
73 char buffer[BUFSIZ];
74 size_t n, used;
75 FILE *file;
76 bool ok;
77
78 file = fopen(input_file, "r");
79 if (!file) {
80 ovs_fatal(errno, "Cannot open \"%s\"", input_file);
81 }
82
83 parser = NULL;
84 n = used = 0;
85 ok = true;
86 while (used < n || refill(file, buffer, sizeof buffer, &n, &used)) {
87 if (!parser && isspace((unsigned char) buffer[used])) {
88 /* Skip white space. */
89 used++;
90 } else {
91 if (!parser) {
92 parser = json_parser_create(0);
93 }
94
95 used = n - json_parser_feed(parser, &buffer[used], n - used);
96 if (used < n) {
97 if (!print_and_free_json(json_parser_finish(parser))) {
98 ok = false;
99 }
100 parser = NULL;
101 }
102 }
103 }
104 if (parser) {
105 if (!print_and_free_json(json_parser_finish(parser))) {
106 ok = false;
107 }
108 }
109 return ok;
110 }
111
112 int
113 main(int argc, char *argv[])
114 {
115 const char *input_file;
116 bool ok;
117
118 set_program_name(argv[0]);
119
120 for (;;) {
121 static const struct option options[] = {
122 {"pretty", no_argument, &pretty, 1},
123 {"multiple", no_argument, &multiple, 1},
124 };
125 int option_index = 0;
126 int c = getopt_long (argc, argv, "", options, &option_index);
127
128 if (c == -1) {
129 break;
130 }
131 switch (c) {
132 case 0:
133 break;
134
135 case '?':
136 exit(1);
137
138 default:
139 abort();
140 }
141 }
142
143 if (argc - optind != 1) {
144 ovs_fatal(0, "usage: %s [--pretty] [--multiple] INPUT.json",
145 program_name);
146 }
147
148 input_file = argv[optind];
149 if (!strcmp(input_file, "-")) {
150 input_file = "/dev/stdin";
151 }
152
153 if (multiple) {
154 ok = parse_multiple(input_file);
155 } else {
156 ok = print_and_free_json(json_from_file(input_file));
157 }
158
159 return !ok;
160 }