Amend gitignore
[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_state *state;
80 struct json_object *res;
81 const char *prefix;
82
83 state = jp_parse(expr);
84
85 if (!state || state->error)
86 {
87 fprintf(stderr, "In expression '%s': %s\n",
88 expr, state ? state->error : "Out of memory");
89
90 goto out;
91 }
92
93 res = jp_match(state->path, jsobj);
94
95 if (state->path->type == T_LABEL)
96 {
97 prefix = state->path->str;
98
99 switch (json_object_get_type(res))
100 {
101 case json_type_object:
102 printf("export %s_TYPE=object; ", prefix);
103
104 first = true;
105 printf("export %s_KEYS=", prefix);
106 json_object_object_foreach(res, key, val)
107 {
108 if (!val)
109 continue;
110
111 if (!first)
112 printf("\\ ");
113
114 print_string(key);
115 first = false;
116 }
117 printf("; ");
118
119 //printf("export %s=", prefix);
120 //print_string(json_object_to_json_string(res));
121 //printf("; ");
122
123 break;
124
125 case json_type_array:
126 printf("export %s_TYPE=array; ", prefix);
127 printf("export %s_LENGTH=%d; ",
128 prefix, json_object_array_length(res));
129
130 //printf("export %s=", prefix);
131 //print_string(json_object_to_json_string(res));
132 //printf("; ");
133 break;
134
135 case json_type_boolean:
136 printf("export %s_TYPE=bool; ", prefix);
137 printf("export %s=%d; ", prefix, json_object_get_boolean(res));
138 break;
139
140 case json_type_int:
141 printf("export %s_TYPE=int; ", prefix);
142 printf("export %s=%d; ", prefix, json_object_get_int(res));
143 break;
144
145 case json_type_double:
146 printf("export %s_TYPE=double; ", prefix);
147 printf("export %s=%f; ", prefix, json_object_get_double(res));
148 break;
149
150 case json_type_string:
151 printf("export %s_TYPE=string; ", prefix);
152 printf("export %s=", prefix);
153 print_string(json_object_get_string(res));
154 printf("; ");
155 break;
156
157 case json_type_null:
158 printf("unset %s %s_TYPE %s_LENGTH %s_KEYS; ",
159 prefix, prefix, prefix, prefix);
160 break;
161 }
162 }
163 else
164 {
165 printf("%s\n", json_object_to_json_string(res));
166 }
167
168 out:
169 if (state)
170 jp_free(state);
171 }
172
173 int main(int argc, char **argv)
174 {
175 int opt;
176 FILE *input = stdin;
177 struct json_object *jsobj = NULL;
178
179 while ((opt = getopt(argc, argv, "i:e:")) != -1)
180 {
181 switch (opt)
182 {
183 case 'i':
184 input = fopen(optarg, "r");
185
186 if (!input)
187 {
188 fprintf(stderr, "Failed to open %s: %s\n",
189 optarg, strerror(errno));
190
191 exit(1);
192 }
193
194 break;
195
196 case 'e':
197 if (!jsobj)
198 {
199 jsobj = parse_json(input);
200
201 if (!jsobj)
202 {
203 fprintf(stderr, "Failed to parse json data\n");
204 exit(2);
205 }
206 }
207
208 export_json(jsobj, optarg);
209 break;
210 }
211 }
212
213 if (jsobj)
214 json_object_put(jsobj);
215
216 fclose(input);
217
218 return 0;
219 }