Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : /* Simple JSON "cat" utility */
7 : :
8 : : #include "spdk/stdinc.h"
9 : :
10 : : #include "spdk/json.h"
11 : : #include "spdk/file.h"
12 : :
13 : : static void
14 : 0 : usage(const char *prog)
15 : : {
16 : 0 : printf("usage: %s [-c] [-f] file.json\n", prog);
17 : 0 : printf("Options:\n");
18 : 0 : printf("-c\tallow comments in input (non-standard)\n");
19 : 0 : printf("-f\tformatted output (default: compact output)\n");
20 : 0 : }
21 : :
22 : : static void
23 : 0 : print_json_error(FILE *pf, int rc, const char *filename)
24 : : {
25 [ # # # # ]: 0 : switch (rc) {
26 : 0 : case SPDK_JSON_PARSE_INVALID:
27 : 0 : fprintf(pf, "%s: invalid JSON\n", filename);
28 : 0 : break;
29 : 0 : case SPDK_JSON_PARSE_INCOMPLETE:
30 : 0 : fprintf(pf, "%s: incomplete JSON\n", filename);
31 : 0 : break;
32 : 0 : case SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED:
33 : 0 : fprintf(pf, "%s: maximum nesting depth exceeded\n", filename);
34 : 0 : break;
35 : 0 : default:
36 : 0 : fprintf(pf, "%s: unknown JSON parse error\n", filename);
37 : 0 : break;
38 : : }
39 : 0 : }
40 : :
41 : : static int
42 : 0 : json_write_cb(void *cb_ctx, const void *data, size_t size)
43 : : {
44 : 0 : FILE *f = cb_ctx;
45 : : size_t rc;
46 : :
47 : 0 : rc = fwrite(data, 1, size, f);
48 [ # # ]: 0 : return rc == size ? 0 : -1;
49 : : }
50 : :
51 : : static int
52 : 0 : process_file(const char *filename, FILE *f, uint32_t parse_flags, uint32_t write_flags)
53 : : {
54 : 0 : size_t size;
55 : 0 : void *buf, *end;
56 : : ssize_t rc;
57 : : struct spdk_json_val *values;
58 : : size_t num_values;
59 : : struct spdk_json_write_ctx *w;
60 : :
61 : 0 : buf = spdk_posix_file_load(f, &size);
62 [ # # ]: 0 : if (buf == NULL) {
63 : 0 : fprintf(stderr, "%s: file read error\n", filename);
64 : 0 : return 1;
65 : : }
66 : :
67 : 0 : rc = spdk_json_parse(buf, size, NULL, 0, NULL, parse_flags);
68 [ # # ]: 0 : if (rc <= 0) {
69 : 0 : print_json_error(stderr, rc, filename);
70 : 0 : free(buf);
71 : 0 : return 1;
72 : : }
73 : :
74 : 0 : num_values = (size_t)rc;
75 : 0 : values = calloc(num_values, sizeof(*values));
76 [ # # ]: 0 : if (values == NULL) {
77 : 0 : perror("values calloc");
78 : 0 : free(buf);
79 : 0 : return 1;
80 : : }
81 : :
82 : 0 : rc = spdk_json_parse(buf, size, values, num_values, &end,
83 : : parse_flags | SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
84 [ # # ]: 0 : if (rc <= 0) {
85 : 0 : print_json_error(stderr, rc, filename);
86 : 0 : free(values);
87 : 0 : free(buf);
88 : 0 : return 1;
89 : : }
90 : :
91 : 0 : w = spdk_json_write_begin(json_write_cb, stdout, write_flags);
92 [ # # ]: 0 : if (w == NULL) {
93 : 0 : fprintf(stderr, "json_write_begin failed\n");
94 : 0 : free(values);
95 : 0 : free(buf);
96 : 0 : return 1;
97 : : }
98 : :
99 : 0 : spdk_json_write_val(w, values);
100 : 0 : spdk_json_write_end(w);
101 : 0 : printf("\n");
102 : :
103 [ # # ]: 0 : if (end != buf + size) {
104 : 0 : fprintf(stderr, "%s: garbage at end of file\n", filename);
105 : 0 : free(values);
106 : 0 : free(buf);
107 : 0 : return 1;
108 : : }
109 : :
110 : 0 : free(values);
111 : 0 : free(buf);
112 : 0 : return 0;
113 : : }
114 : :
115 : : int
116 : 0 : main(int argc, char **argv)
117 : : {
118 : : FILE *f;
119 : : int ch;
120 : : int rc;
121 : 0 : uint32_t parse_flags = 0, write_flags = 0;
122 : : const char *filename;
123 : :
124 [ # # ]: 0 : while ((ch = getopt(argc, argv, "cf")) != -1) {
125 [ # # # ]: 0 : switch (ch) {
126 : 0 : case 'c':
127 : 0 : parse_flags |= SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS;
128 : 0 : break;
129 : 0 : case 'f':
130 : 0 : write_flags |= SPDK_JSON_WRITE_FLAG_FORMATTED;
131 : 0 : break;
132 : 0 : default:
133 : 0 : usage(argv[0]);
134 : 0 : return 1;
135 : : }
136 : : }
137 : :
138 [ # # ]: 0 : if (optind == argc) {
139 : 0 : filename = "-";
140 [ # # ]: 0 : } else if (optind == argc - 1) {
141 : 0 : filename = argv[optind];
142 : : } else {
143 : 0 : usage(argv[0]);
144 : 0 : return 1;
145 : : }
146 : :
147 [ # # ]: 0 : if (strcmp(filename, "-") == 0) {
148 : 0 : f = stdin;
149 : : } else {
150 : 0 : f = fopen(filename, "r");
151 [ # # ]: 0 : if (f == NULL) {
152 : 0 : perror("fopen");
153 : 0 : return 1;
154 : : }
155 : : }
156 : :
157 : 0 : rc = process_file(filename, f, parse_flags, write_flags);
158 : :
159 [ # # ]: 0 : if (f != stdin) {
160 : 0 : fclose(f);
161 : : }
162 : :
163 : 0 : return rc;
164 : : }
|