05e445c1569353f666aac89a2c872409e3c57b03
[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 }