Initial commit
[project/jsonpath.git] / main.c
1 /*
2 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
3 *
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.
7 *
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.
15 */
16
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <errno.h>
20
21 #ifdef JSONC
22 #include <json.h>
23 #else
24 #include <json-c/json.h>
25 #endif
26
27 #include "lexer.h"
28 #include "parser.h"
29 #include "matcher.h"
30
31 static struct json_object *
32 parse_json(FILE *fd)
33 {
34 int len;
35 char buf[256];
36 struct json_object *obj = NULL;
37 struct json_tokener *tok = json_tokener_new();
38 enum json_tokener_error err = json_tokener_continue;
39
40 if (!tok)
41 return NULL;
42
43 while ((len = fread(buf, 1, sizeof(buf), fd)) > 0)
44 {
45 obj = json_tokener_parse_ex(tok, buf, len);
46 err = json_tokener_get_error(tok);
47
48 if (!err || err != json_tokener_continue)
49 break;
50 }
51
52 json_tokener_free(tok);
53
54 return err ? NULL : obj;
55 }
56
57 static void
58 print_string(const char *s)
59 {
60 const char *p;
61
62 printf("'");
63
64 for (p = s; *p; p++)
65 {
66 if (*p == '\'')
67 printf("'\"'\"'");
68 else
69 printf("%c", *p);
70 }
71
72 printf("'");
73 }
74
75 static void
76 export_json(struct json_object *jsobj, char *expr)
77 {
78 bool first;
79 struct jp_opcode *tree;
80 struct json_object *res;
81 const char *error, *prefix;
82
83 tree = jp_parse(expr, &error);
84
85 if (error)
86 {
87 fprintf(stderr, "In expression '%s': %s\n", expr, error);
88 return;
89 }
90
91 res = jp_match(tree, jsobj);
92
93 if (tree->type == T_LABEL)
94 {
95 prefix = tree->str;
96
97 switch (json_object_get_type(res))
98 {
99 case json_type_object:
100 printf("export %s_TYPE=object; ", prefix);
101
102 first = true;
103 printf("export %s_KEYS=", prefix);
104 json_object_object_foreach(res, key, val)
105 {
106 if (!val)
107 continue;
108
109 if (!first)
110 printf("\\ ");
111
112 print_string(key);
113 first = false;
114 }
115 printf("; ");
116
117 //printf("export %s=", prefix);
118 //print_string(json_object_to_json_string(res));
119 //printf("; ");
120
121 break;
122
123 case json_type_array:
124 printf("export %s_TYPE=array; ", prefix);
125 printf("export %s_LENGTH=%d; ",
126 prefix, json_object_array_length(res));
127
128 //printf("export %s=", prefix);
129 //print_string(json_object_to_json_string(res));
130 //printf("; ");
131 break;
132
133 case json_type_boolean:
134 printf("export %s_TYPE=bool; ", prefix);
135 printf("export %s=%d; ", prefix, json_object_get_boolean(res));
136 break;
137
138 case json_type_int:
139 printf("export %s_TYPE=int; ", prefix);
140 printf("export %s=%d; ", prefix, json_object_get_int(res));
141 break;
142
143 case json_type_double:
144 printf("export %s_TYPE=double; ", prefix);
145 printf("export %s=%f; ", prefix, json_object_get_double(res));
146 break;
147
148 case json_type_string:
149 printf("export %s_TYPE=string; ", prefix);
150 printf("export %s=", prefix);
151 print_string(json_object_get_string(res));
152 printf("; ");
153 break;
154
155 case json_type_null:
156 printf("unset %s %s_TYPE %s_LENGTH %s_KEYS; ",
157 prefix, prefix, prefix, prefix);
158 break;
159 }
160 }
161 else
162 {
163 printf("%s\n", json_object_to_json_string(res));
164 }
165
166 jp_free();
167 }
168
169 int main(int argc, char **argv)
170 {
171 int opt;
172 FILE *input = stdin;
173 struct json_object *jsobj = NULL;
174
175 while ((opt = getopt(argc, argv, "i:e:")) != -1)
176 {
177 switch (opt)
178 {
179 case 'i':
180 input = fopen(optarg, "r");
181
182 if (!input)
183 {
184 fprintf(stderr, "Failed to open %s: %s\n",
185 optarg, strerror(errno));
186
187 exit(1);
188 }
189
190 break;
191
192 case 'e':
193 if (!jsobj)
194 {
195 jsobj = parse_json(input);
196
197 if (!jsobj)
198 {
199 fprintf(stderr, "Failed to parse json data\n");
200 exit(2);
201 }
202 }
203
204 export_json(jsobj, optarg);
205 break;
206 }
207 }
208
209 if (jsobj)
210 json_object_put(jsobj);
211
212 fclose(input);
213
214 return 0;
215 }