]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright (c) Intel Corporation. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | /* Simple JSON "cat" utility */ | |
35 | ||
11fdf7f2 | 36 | #include "spdk/stdinc.h" |
7c673cae FG |
37 | |
38 | #include "spdk/json.h" | |
9f95a23c | 39 | #include "spdk/file.h" |
7c673cae FG |
40 | |
41 | static void | |
42 | usage(const char *prog) | |
43 | { | |
44 | printf("usage: %s [-c] [-f] file.json\n", prog); | |
45 | printf("Options:\n"); | |
46 | printf("-c\tallow comments in input (non-standard)\n"); | |
47 | printf("-f\tformatted output (default: compact output)\n"); | |
48 | } | |
49 | ||
50 | static void | |
51 | print_json_error(FILE *pf, int rc, const char *filename) | |
52 | { | |
53 | switch (rc) { | |
54 | case SPDK_JSON_PARSE_INVALID: | |
55 | fprintf(pf, "%s: invalid JSON\n", filename); | |
56 | break; | |
57 | case SPDK_JSON_PARSE_INCOMPLETE: | |
58 | fprintf(pf, "%s: incomplete JSON\n", filename); | |
59 | break; | |
60 | case SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED: | |
61 | fprintf(pf, "%s: maximum nesting depth exceeded\n", filename); | |
62 | break; | |
63 | default: | |
64 | fprintf(pf, "%s: unknown JSON parse error\n", filename); | |
65 | break; | |
66 | } | |
67 | } | |
68 | ||
69 | static int | |
70 | json_write_cb(void *cb_ctx, const void *data, size_t size) | |
71 | { | |
72 | FILE *f = cb_ctx; | |
73 | size_t rc; | |
74 | ||
75 | rc = fwrite(data, 1, size, f); | |
76 | return rc == size ? 0 : -1; | |
77 | } | |
78 | ||
7c673cae FG |
79 | static int |
80 | process_file(const char *filename, FILE *f, uint32_t parse_flags, uint32_t write_flags) | |
81 | { | |
82 | size_t size; | |
83 | void *buf, *end; | |
84 | ssize_t rc; | |
85 | struct spdk_json_val *values; | |
86 | size_t num_values; | |
87 | struct spdk_json_write_ctx *w; | |
88 | ||
9f95a23c | 89 | buf = spdk_posix_file_load(f, &size); |
7c673cae FG |
90 | if (buf == NULL) { |
91 | fprintf(stderr, "%s: file read error\n", filename); | |
92 | return 1; | |
93 | } | |
94 | ||
95 | rc = spdk_json_parse(buf, size, NULL, 0, NULL, parse_flags); | |
96 | if (rc <= 0) { | |
97 | print_json_error(stderr, rc, filename); | |
98 | free(buf); | |
99 | return 1; | |
100 | } | |
101 | ||
102 | num_values = (size_t)rc; | |
103 | values = calloc(num_values, sizeof(*values)); | |
104 | if (values == NULL) { | |
105 | perror("values calloc"); | |
106 | free(buf); | |
107 | return 1; | |
108 | } | |
109 | ||
110 | rc = spdk_json_parse(buf, size, values, num_values, &end, | |
111 | parse_flags | SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE); | |
112 | if (rc <= 0) { | |
113 | print_json_error(stderr, rc, filename); | |
114 | free(values); | |
115 | free(buf); | |
116 | return 1; | |
117 | } | |
118 | ||
119 | w = spdk_json_write_begin(json_write_cb, stdout, write_flags); | |
120 | if (w == NULL) { | |
121 | fprintf(stderr, "json_write_begin failed\n"); | |
122 | free(values); | |
123 | free(buf); | |
124 | return 1; | |
125 | } | |
126 | ||
127 | spdk_json_write_val(w, values); | |
128 | spdk_json_write_end(w); | |
129 | printf("\n"); | |
130 | ||
131 | if (end != buf + size) { | |
132 | fprintf(stderr, "%s: garbage at end of file\n", filename); | |
133 | free(values); | |
134 | free(buf); | |
135 | return 1; | |
136 | } | |
137 | ||
138 | free(values); | |
139 | free(buf); | |
140 | return 0; | |
141 | } | |
142 | ||
143 | int | |
144 | main(int argc, char **argv) | |
145 | { | |
146 | FILE *f; | |
147 | int ch; | |
148 | int rc; | |
149 | uint32_t parse_flags = 0, write_flags = 0; | |
150 | const char *filename; | |
151 | ||
152 | while ((ch = getopt(argc, argv, "cf")) != -1) { | |
153 | switch (ch) { | |
154 | case 'c': | |
155 | parse_flags |= SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS; | |
156 | break; | |
157 | case 'f': | |
158 | write_flags |= SPDK_JSON_WRITE_FLAG_FORMATTED; | |
159 | break; | |
160 | default: | |
161 | usage(argv[0]); | |
162 | return 1; | |
163 | } | |
164 | } | |
165 | ||
166 | if (optind == argc) { | |
167 | filename = "-"; | |
168 | } else if (optind == argc - 1) { | |
169 | filename = argv[optind]; | |
170 | } else { | |
171 | usage(argv[0]); | |
172 | return 1; | |
173 | } | |
174 | ||
175 | if (strcmp(filename, "-") == 0) { | |
176 | f = stdin; | |
177 | } else { | |
178 | f = fopen(filename, "r"); | |
179 | if (f == NULL) { | |
180 | perror("fopen"); | |
181 | return 1; | |
182 | } | |
183 | } | |
184 | ||
185 | rc = process_file(filename, f, parse_flags, write_flags); | |
186 | ||
187 | if (f != stdin) { | |
188 | fclose(f); | |
189 | } | |
190 | ||
191 | return rc; | |
192 | } |