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>
30 #define MAX_VARLEN 256
32 static const char *var_prefix
= "";
33 static int var_prefix_len
= 0;
35 static int add_json_element(const char *key
, json_object
*obj
);
37 static int add_json_object(json_object
*obj
)
41 json_object_object_foreach(obj
, key
, val
) {
42 ret
= add_json_element(key
, val
);
49 static int add_json_array(struct array_list
*a
)
55 for (i
= 0, len
= array_list_length(a
); i
< len
; i
++) {
56 sprintf(seq
, "%d", i
);
57 ret
= add_json_element(seq
, array_list_get_idx(a
, i
));
65 static void add_json_string(const char *str
)
67 char *ptr
= (char *) str
;
71 while ((c
= strchr(ptr
, '\'')) != NULL
) {
74 fwrite(ptr
, len
, 1, stdout
);
77 fwrite(c
, strlen(c
), 1, stdout
);
81 fwrite(ptr
, len
, 1, stdout
);
84 static void write_key_string(const char *key
)
87 putc(isalnum(*key
) ? *key
: '_', stdout
);
92 static int add_json_element(const char *key
, json_object
*obj
)
99 switch (json_object_get_type(obj
)) {
100 case json_type_object
:
103 case json_type_array
:
106 case json_type_string
:
109 case json_type_boolean
:
115 case json_type_double
:
122 fprintf(stdout
, "json_add_%s '", type
);
123 write_key_string(key
);
125 switch (json_object_get_type(obj
)) {
126 case json_type_object
:
127 fprintf(stdout
, "';\n");
128 add_json_object(obj
);
129 fprintf(stdout
, "json_close_object;\n");
131 case json_type_array
:
132 fprintf(stdout
, "';\n");
133 add_json_array(json_object_get_array(obj
));
134 fprintf(stdout
, "json_close_array;\n");
136 case json_type_string
:
137 fprintf(stdout
, "' '");
138 add_json_string(json_object_get_string(obj
));
139 fprintf(stdout
, "';\n");
141 case json_type_boolean
:
142 fprintf(stdout
, "' %d;\n", json_object_get_boolean(obj
));
145 fprintf(stdout
, "' %d;\n", json_object_get_int(obj
));
147 case json_type_double
:
148 fprintf(stdout
, "' %lf;\n", json_object_get_double(obj
));
157 static int jshn_parse(const char *str
)
161 obj
= json_tokener_parse(str
);
162 if (is_error(obj
) || json_object_get_type(obj
) != json_type_object
) {
163 fprintf(stderr
, "Failed to parse message data\n");
166 fprintf(stdout
, "json_init;\n");
167 add_json_object(obj
);
173 static char *get_keys(const char *prefix
)
177 keys
= alloca(var_prefix_len
+ strlen(prefix
) + sizeof("KEYS_") + 1);
178 sprintf(keys
, "%sKEYS_%s", var_prefix
, prefix
);
182 static void get_var(const char *prefix
, const char **name
, char **var
, char **type
)
184 char *tmpname
, *varname
;
186 tmpname
= alloca(var_prefix_len
+ strlen(prefix
) + 1 + strlen(*name
) + 1 + sizeof("TYPE_"));
188 sprintf(tmpname
, "%s%s_%s", var_prefix
, prefix
, *name
);
189 *var
= getenv(tmpname
);
191 sprintf(tmpname
, "%sTYPE_%s_%s", var_prefix
, prefix
, *name
);
192 *type
= getenv(tmpname
);
194 sprintf(tmpname
, "%sNAME_%s_%s", var_prefix
, prefix
, *name
);
195 varname
= getenv(tmpname
);
200 static json_object
*jshn_add_objects(json_object
*obj
, const char *prefix
, bool array
);
202 static void jshn_add_object_var(json_object
*obj
, bool array
, const char *prefix
, const char *name
)
207 get_var(prefix
, &name
, &var
, &type
);
211 if (!strcmp(type
, "array")) {
212 new = json_object_new_array();
213 jshn_add_objects(new, var
, true);
214 } else if (!strcmp(type
, "object")) {
215 new = json_object_new_object();
216 jshn_add_objects(new, var
, false);
217 } else if (!strcmp(type
, "string")) {
218 new = json_object_new_string(var
);
219 } else if (!strcmp(type
, "int")) {
220 new = json_object_new_int(atoi(var
));
221 } else if (!strcmp(type
, "double")) {
222 new = json_object_new_double(strtod(var
, NULL
));
223 } else if (!strcmp(type
, "boolean")) {
224 new = json_object_new_boolean(!!atoi(var
));
230 json_object_array_add(obj
, new);
232 json_object_object_add(obj
, name
, new);
235 static json_object
*jshn_add_objects(json_object
*obj
, const char *prefix
, bool array
)
237 char *keys
, *key
, *brk
;
239 keys
= get_keys(prefix
);
243 for (key
= strtok_r(keys
, " ", &brk
); key
;
244 key
= strtok_r(NULL
, " ", &brk
)) {
245 jshn_add_object_var(obj
, array
, prefix
, key
);
252 static int jshn_format(bool no_newline
)
256 obj
= json_object_new_object();
257 jshn_add_objects(obj
, "JSON_VAR", false);
258 fprintf(stdout
, "%s%s", json_object_to_json_string(obj
),
259 no_newline
? "" : "\n");
260 json_object_put(obj
);
264 static int usage(const char *progname
)
266 fprintf(stderr
, "Usage: %s [-n] -r <message>|-w\n", progname
);
270 int main(int argc
, char **argv
)
272 bool no_newline
= false;
275 while ((ch
= getopt(argc
, argv
, "p:nr:w")) != -1) {
279 var_prefix_len
= strlen(var_prefix
);
282 return jshn_parse(optarg
);
284 return jshn_format(no_newline
);
289 return usage(argv
[0]);
292 return usage(argv
[0]);