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