2 * Copyright (C) 2011-2013 Felix Fietkau <nbd@openwrt.org>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <json/json.h>
31 #include "blobmsg_json.h"
33 #define MAX_VARLEN 256
35 static struct blob_buf b
= { 0 };
37 static const char *var_prefix
= "";
38 static int var_prefix_len
= 0;
40 static int add_json_element(const char *key
, json_object
*obj
);
42 static int add_json_object(json_object
*obj
)
46 json_object_object_foreach(obj
, key
, val
) {
47 ret
= add_json_element(key
, val
);
54 static int add_json_array(struct array_list
*a
)
60 for (i
= 0, len
= array_list_length(a
); i
< len
; i
++) {
61 sprintf(seq
, "%d", i
);
62 ret
= add_json_element(seq
, array_list_get_idx(a
, i
));
70 static void add_json_string(const char *str
)
72 char *ptr
= (char *) str
;
76 while ((c
= strchr(ptr
, '\'')) != NULL
) {
79 fwrite(ptr
, len
, 1, stdout
);
82 fwrite(c
, strlen(c
), 1, stdout
);
86 fwrite(ptr
, len
, 1, stdout
);
89 static void write_key_string(const char *key
)
92 putc(isalnum(*key
) ? *key
: '_', stdout
);
97 static int add_json_element(const char *key
, json_object
*obj
)
104 switch (json_object_get_type(obj
)) {
105 case json_type_object
:
108 case json_type_array
:
111 case json_type_string
:
114 case json_type_boolean
:
120 case json_type_double
:
127 fprintf(stdout
, "json_add_%s '", type
);
128 write_key_string(key
);
130 switch (json_object_get_type(obj
)) {
131 case json_type_object
:
132 fprintf(stdout
, "';\n");
133 add_json_object(obj
);
134 fprintf(stdout
, "json_close_object;\n");
136 case json_type_array
:
137 fprintf(stdout
, "';\n");
138 add_json_array(json_object_get_array(obj
));
139 fprintf(stdout
, "json_close_array;\n");
141 case json_type_string
:
142 fprintf(stdout
, "' '");
143 add_json_string(json_object_get_string(obj
));
144 fprintf(stdout
, "';\n");
146 case json_type_boolean
:
147 fprintf(stdout
, "' %d;\n", json_object_get_boolean(obj
));
150 fprintf(stdout
, "' %d;\n", json_object_get_int(obj
));
152 case json_type_double
:
153 fprintf(stdout
, "' %lf;\n", json_object_get_double(obj
));
162 static int jshn_parse(const char *str
)
166 obj
= json_tokener_parse(str
);
167 if (!obj
|| json_object_get_type(obj
) != json_type_object
) {
168 fprintf(stderr
, "Failed to parse message data\n");
171 fprintf(stdout
, "json_init;\n");
172 add_json_object(obj
);
178 static char *get_keys(const char *prefix
)
182 keys
= alloca(var_prefix_len
+ strlen(prefix
) + sizeof("K_") + 1);
183 sprintf(keys
, "%sK_%s", var_prefix
, prefix
);
187 static void get_var(const char *prefix
, const char **name
, char **var
, char **type
)
189 char *tmpname
, *varname
;
191 tmpname
= alloca(var_prefix_len
+ strlen(prefix
) + 1 + strlen(*name
) + 1 + sizeof("T_"));
193 sprintf(tmpname
, "%s%s_%s", var_prefix
, prefix
, *name
);
194 *var
= getenv(tmpname
);
196 sprintf(tmpname
, "%sT_%s_%s", var_prefix
, prefix
, *name
);
197 *type
= getenv(tmpname
);
199 sprintf(tmpname
, "%sN_%s_%s", var_prefix
, prefix
, *name
);
200 varname
= getenv(tmpname
);
205 static json_object
*jshn_add_objects(json_object
*obj
, const char *prefix
, bool array
);
207 static void jshn_add_object_var(json_object
*obj
, bool array
, const char *prefix
, const char *name
)
212 get_var(prefix
, &name
, &var
, &type
);
216 if (!strcmp(type
, "array")) {
217 new = json_object_new_array();
218 jshn_add_objects(new, var
, true);
219 } else if (!strcmp(type
, "object")) {
220 new = json_object_new_object();
221 jshn_add_objects(new, var
, false);
222 } else if (!strcmp(type
, "string")) {
223 new = json_object_new_string(var
);
224 } else if (!strcmp(type
, "int")) {
225 new = json_object_new_int(atoi(var
));
226 } else if (!strcmp(type
, "double")) {
227 new = json_object_new_double(strtod(var
, NULL
));
228 } else if (!strcmp(type
, "boolean")) {
229 new = json_object_new_boolean(!!atoi(var
));
235 json_object_array_add(obj
, new);
237 json_object_object_add(obj
, name
, new);
240 static json_object
*jshn_add_objects(json_object
*obj
, const char *prefix
, bool array
)
242 char *keys
, *key
, *brk
;
244 keys
= get_keys(prefix
);
248 for (key
= strtok_r(keys
, " ", &brk
); key
;
249 key
= strtok_r(NULL
, " ", &brk
)) {
250 jshn_add_object_var(obj
, array
, prefix
, key
);
257 static int jshn_format(bool no_newline
, bool indent
)
261 char *blobmsg_output
= NULL
;
264 if (!(obj
= json_object_new_object()))
267 jshn_add_objects(obj
, "J_V", false);
268 if (!(output
= json_object_to_json_string(obj
)))
272 blob_buf_init(&b
, 0);
273 if (!blobmsg_add_json_from_string(&b
, output
))
275 if (!(blobmsg_output
= blobmsg_format_json_indent(b
.head
, 1, 0)))
277 output
= blobmsg_output
;
279 fprintf(stdout
, "%s%s", output
, no_newline
? "" : "\n");
280 free(blobmsg_output
);
284 json_object_put(obj
);
288 static int usage(const char *progname
)
290 fprintf(stderr
, "Usage: %s [-n] [-i] -r <message>|-w\n", progname
);
294 int main(int argc
, char **argv
)
296 bool no_newline
= false;
300 while ((ch
= getopt(argc
, argv
, "p:nir:w")) != -1) {
304 var_prefix_len
= strlen(var_prefix
);
307 return jshn_parse(optarg
);
309 return jshn_format(no_newline
, indent
);
317 return usage(argv
[0]);
320 return usage(argv
[0]);