AUTHORS: Add James Page.
[sliver-openvswitch.git] / tests / test-json.c
1 /*
2  * Copyright (c) 2009, 2010 Nicira, Inc.
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(FILE *stream)
71 {
72     struct json_parser *parser;
73     char buffer[BUFSIZ];
74     size_t n, used;
75     bool ok;
76
77     parser = NULL;
78     n = used = 0;
79     ok = true;
80     while (used < n || refill(stream, buffer, sizeof buffer, &n, &used)) {
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
89             used += json_parser_feed(parser, &buffer[used], n - used);
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;
110     FILE *stream;
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];
144     stream = !strcmp(input_file, "-") ? stdin : fopen(input_file, "r");
145     if (!stream) {
146         ovs_fatal(errno, "Cannot open \"%s\"", input_file);
147     }
148
149     if (multiple) {
150         ok = parse_multiple(stream);
151     } else {
152         ok = print_and_free_json(json_from_stream(stream));
153     }
154
155     fclose(stream);
156
157     return !ok;
158 }