1 /* radare2 (from sdb) - MIT - Copyright 2012-2017 - pancake */
2
3 #include <r_util.h>
4
5
doIndent(int idt,char ** o,const char * tab)6 static void doIndent(int idt, char** o, const char *tab) {
7 int i;
8 char *x;
9 for (i = 0; i < idt; i++) {
10 for (x = (char*) tab; *x; x++) {
11 *(*o)++ = *x;
12 }
13 }
14 }
15
16 #define EMIT_ESC(s, code) do { \
17 if (color) { \
18 const char *p = code; \
19 while (*p) { \
20 *(s)++ = *p++; \
21 } \
22 } \
23 } while (0);
24
25 enum {
26 JC_FALSE, // 31m
27 JC_TRUE, // 32m
28 JC_KEY, // 33m
29 JC_VAL, // 34m
30 JC_RESET,
31 };
32
33 static const char *origColors[] = {
34 "\x1b[31m",
35 "\x1b[32m",
36 "\x1b[33m",
37 "\x1b[34m",
38 "\x1b[0m",
39 };
40 // static const char colors
41
r_print_json_path(const char * s,int pos)42 R_API char* r_print_json_path(const char* s, int pos) {
43 int indent = 0;
44 #define DSZ 128
45 const char *words[DSZ] = { NULL };
46 int lengths[DSZ] = { 0 };
47 int indexs[DSZ] = { 0 };
48 int instr = 0;
49 bool isarr = false;
50 if (!s) {
51 return NULL;
52 }
53 int arrpos = 0;
54 const char *os = s;
55 int osz = (1 + strlen (s)) * 20;
56 if (osz < 1) {
57 return NULL;
58 }
59
60 const char *str_a = NULL;
61 for (; *s; s++) {
62 if (instr) {
63 if (s[0] == '"') {
64 instr = 0;
65 ut64 cur = str_a - os;
66 if (cur > pos) {
67 break;
68 }
69 if (indent < DSZ) {
70 words[indent - 1] = str_a;
71 lengths[indent - 1] = s - str_a;
72 indexs[indent - 1] = 0;
73 }
74 }
75 continue;
76 }
77
78 if (s[0] == '"') {
79 instr = 1;
80 str_a = s + 1;
81 }
82 if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
83 continue;
84 }
85 switch (*s) {
86 case ':':
87 break;
88 case ',':
89 if (isarr) {
90 arrpos ++;
91 if (indent < DSZ) {
92 indexs[indent - 1] = arrpos;
93 lengths[indent - 1] = (s - os);
94 }
95 }
96 break;
97 case '{':
98 case '[':
99 if (*s == '[') {
100 isarr = true;
101 arrpos = 0;
102 }
103 if (indent > 128) {
104 eprintf ("JSON indentation is too deep\n");
105 indent = 0;
106 } else {
107 indent++;
108 }
109 break;
110 case '}':
111 case ']':
112 if (*s == ']') {
113 isarr = false;
114 }
115 indent--;
116 break;
117 }
118 }
119 int i;
120 ut64 opos = 0;
121 for (i = 0; i < DSZ && i < indent; i++) {
122 if ((int)(size_t)words[i] < DSZ) {
123 ut64 cur = lengths[i];
124 if (cur < opos) {
125 continue;
126 }
127 opos = cur;
128 if (cur > pos) {
129 break;
130 }
131 eprintf ("0x%08"PFMT64x" %d [%d]\n", cur, i, indexs[i]);
132 } else {
133 char *a = r_str_ndup (words[i], lengths[i]);
134 ut64 cur = words[i] - os - 1;
135 if (cur < opos) {
136 continue;
137 }
138 opos = cur;
139 if (cur > pos) {
140 break;
141 }
142 char *q = strchr (a, '"');
143 if (q) {
144 *q = 0;
145 }
146 eprintf ("0x%08"PFMT64x" %d %s\n", cur, i, a);
147 free (a);
148 }
149 }
150 // TODO return something
151 return NULL;
152 }
153
r_print_json_human(const char * s)154 R_API char* r_print_json_human(const char* s) {
155 int indent = 0;
156 const char *tab = " ";
157 const int indentSize = strlen (tab);
158 int instr = 0;
159 char *o, *OE, *tmp;
160 if (!s) {
161 return NULL;
162 }
163 int osz = (1 + strlen (s)) * 20;
164 if (osz < 1) {
165 return NULL;
166 }
167
168 char *O = malloc (osz);
169 if (!O) {
170 return NULL;
171 }
172 OE = O + osz;
173 for (o = O; *s; s++) {
174 if (o + (indent * indentSize) + 10 > OE) {
175 int delta = o - O;
176 osz += 0x1000 + (indent * indentSize);
177 if (osz < 1) {
178 free (O);
179 return NULL;
180 }
181 tmp = realloc (O, osz);
182 if (!tmp) {
183 free (O);
184 return NULL;
185 }
186 O = tmp;
187 OE = tmp + osz;
188 o = O + delta;
189 }
190 if (instr) {
191 if (s[0] == '"') {
192 instr = 0;
193 } else if (s[0] == '\\' && s[1] == '"') {
194 // XXX maybe buggy
195 *o++ = *s++;
196 }
197 if (*s != '"') {
198 *o++ = *s;
199 }
200 continue;
201 }
202 if (indent <= 0) {
203 // non-JSON part
204 if (s[0] != '{' && s[0] != '[') {
205 *o++ = *s;
206 continue;
207 }
208 }
209
210 if (s[0] == '"') {
211 instr = 1;
212 }
213 if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
214 continue;
215 }
216 switch (*s) {
217 case ':':
218 *o++ = *s;
219 *o++ = ' ';
220 break;
221 case ',':
222 *o++ = '\n';
223 doIndent (indent - 1, &o, tab);
224 break;
225 case '{':
226 case '[':
227 if (indent > 0) {
228 *o++ = (indent != -1)? '\n': ' ';
229 }
230 if (indent > 128) {
231 eprintf ("JSON indentation is too deep\n");
232 indent = 0;
233 } else {
234 indent++;
235 }
236 doIndent (indent - 1, &o, tab);
237 break;
238 case '}':
239 case ']':
240 indent--;
241 doIndent (indent - 1, &o, tab);
242 break;
243 default:
244 if (!instr) {
245 *o++ = *s;
246 }
247 }
248 }
249 *o = 0;
250 return O;
251 }
252
r_print_json_indent(const char * s,bool color,const char * tab,const char ** palette)253 R_API char* r_print_json_indent(const char* s, bool color, const char* tab, const char **palette) {
254 int indent = 0;
255 const int indentSize = strlen (tab);
256 int instr = 0;
257 bool isValue = false;
258 char *o, *OE, *tmp;
259 if (!s) {
260 return NULL;
261 }
262 const char **colors = palette ? palette: origColors;
263 int osz = (1 + strlen (s)) * 20;
264 if (osz < 1) {
265 return NULL;
266 }
267
268 char *O = malloc (osz);
269 if (!O) {
270 return NULL;
271 }
272 OE = O + osz;
273 for (o = O; *s; s++) {
274 if (o + (indent * indentSize) + 10 > OE) {
275 int delta = o - O;
276 osz += 0x1000 + (indent * indentSize);
277 if (osz < 1) {
278 free (O);
279 return NULL;
280 }
281 tmp = realloc (O, osz);
282 if (!tmp) {
283 free (O);
284 return NULL;
285 }
286 O = tmp;
287 OE = tmp + osz;
288 o = O + delta;
289 }
290 if (instr) {
291 if (s[0] == '"') {
292 instr = 0;
293 } else if (s[0] == '\\' && s[1] == '"') {
294 *o++ = *s++;
295 }
296 if (instr) {
297 if (isValue) {
298 // TODO: do not emit color in every char
299 EMIT_ESC (o, colors[JC_VAL]);
300 } else {
301 EMIT_ESC (o, colors[JC_KEY]);
302 }
303 } else {
304 EMIT_ESC (o, colors[JC_RESET]);
305 }
306 *o++ = *s;
307 continue;
308 }
309 if (indent <= 0) {
310 // non-JSON part, skip it
311 if (s[0] != '{' && s[0] != '[') {
312 if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
313 *o++ = *s;
314 }
315 continue;
316 }
317 }
318
319 if (s[0] == '"') {
320 instr = 1;
321 }
322 if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ' || !IS_PRINTABLE(*s)) {
323 continue;
324 }
325 switch (*s) {
326 case ':':
327 *o++ = *s;
328 *o++ = ' ';
329 s = r_str_trim_head_ro (s + 1);
330 if (!strncmp (s, "true", 4)) {
331 EMIT_ESC (o, colors[JC_TRUE]);
332 } else if (!strncmp (s, "false", 5)) {
333 EMIT_ESC (o, colors[JC_FALSE]);
334 }
335 s--;
336 isValue = true;
337 break;
338 case ',':
339 EMIT_ESC (o, colors[JC_RESET]);
340 *o++ = *s;
341 *o++ = '\n';
342 isValue = false;
343 doIndent (indent, &o, tab);
344 break;
345 case '{':
346 case '[':
347 isValue = false;
348 *o++ = *s;
349 *o++ = (indent != -1)? '\n': ' ';
350 if (indent > 128) {
351 eprintf ("JSON indentation is too deep\n");
352 indent = 0;
353 } else {
354 indent++;
355 }
356 doIndent (indent, &o, tab);
357 break;
358 case '}':
359 case ']':
360 EMIT_ESC (o, colors[JC_RESET]);
361 isValue = false;
362 *o++ = '\n';
363 indent--;
364 doIndent (indent, &o, tab);
365 *o++ = *s;
366 break;
367 default:
368 *o++ = *s;
369 }
370 }
371 *o = 0;
372 return O;
373 }
374
375 #undef EMIT_ESC
376