Initial commit
[oweals/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 }