2017-02-20 01:31:49 +00:00
|
|
|
/* radare2 (from sdb) - MIT - Copyright 2012-2017 - pancake */
|
|
|
|
|
|
|
|
#include <r_util.h>
|
|
|
|
#include <r_print.h>
|
|
|
|
|
2017-03-17 11:09:17 +00:00
|
|
|
|
|
|
|
static void doIndent(int idt, char** o, const char *tab) {
|
|
|
|
int i;
|
|
|
|
char *x;
|
|
|
|
for (i = 0; i < idt; i++) {
|
|
|
|
for (x = (char*) tab; *x; x++) {
|
|
|
|
*(*o)++ = *x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-19 11:43:33 +00:00
|
|
|
#define EMIT_ESC(s, code) do { \
|
2017-05-15 20:32:46 +00:00
|
|
|
if (color) { \
|
2017-08-11 10:23:57 +00:00
|
|
|
const char *p = code; \
|
2017-05-15 20:32:46 +00:00
|
|
|
while (*p) { \
|
|
|
|
*s++ = *p++; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while (0);
|
|
|
|
|
2017-08-11 10:23:57 +00:00
|
|
|
enum {
|
|
|
|
JC_FALSE, // 31m
|
|
|
|
JC_TRUE, // 32m
|
|
|
|
JC_KEY, // 33m
|
|
|
|
JC_VAL, // 34m
|
|
|
|
JC_RESET,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *origColors[] = {
|
|
|
|
"\x1b[31m",
|
|
|
|
"\x1b[32m",
|
|
|
|
"\x1b[33m",
|
|
|
|
"\x1b[34m",
|
|
|
|
"\x1b[0m",
|
|
|
|
};
|
|
|
|
// static const char colors
|
|
|
|
|
2017-10-16 11:31:13 +00:00
|
|
|
R_API char* r_print_json_path(const char* s, int pos) {
|
|
|
|
int indent = 0;
|
|
|
|
#define DSZ 128
|
|
|
|
const char *words[DSZ] = { NULL };
|
|
|
|
int lengths[DSZ] = { 0 };
|
|
|
|
int indexs[DSZ] = { 0 };
|
|
|
|
int instr = 0;
|
|
|
|
bool isarr = false;
|
|
|
|
if (!s) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
int arrpos = 0;
|
|
|
|
const char *os = s;
|
|
|
|
int osz = (1 + strlen (s)) * 20;
|
|
|
|
if (osz < 1) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *str_a = NULL;
|
2017-12-08 14:47:48 +00:00
|
|
|
for (; *s; s++) {
|
2017-10-16 11:31:13 +00:00
|
|
|
if (instr) {
|
|
|
|
if (s[0] == '"') {
|
|
|
|
instr = 0;
|
|
|
|
ut64 cur = str_a - os;
|
|
|
|
if (cur > pos) {
|
|
|
|
break;
|
|
|
|
}
|
2017-10-21 09:33:51 +00:00
|
|
|
if (indent < DSZ) {
|
|
|
|
words[indent - 1] = str_a;
|
|
|
|
lengths[indent - 1] = s - str_a;
|
|
|
|
indexs[indent - 1] = 0;
|
|
|
|
}
|
2017-10-16 11:31:13 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s[0] == '"') {
|
|
|
|
instr = 1;
|
|
|
|
str_a = s + 1;
|
|
|
|
}
|
|
|
|
if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (*s) {
|
|
|
|
case ':':
|
|
|
|
break;
|
|
|
|
case ',':
|
|
|
|
if (isarr) {
|
|
|
|
arrpos ++;
|
2017-10-21 09:33:51 +00:00
|
|
|
if (indent < DSZ) {
|
|
|
|
indexs[indent - 1] = arrpos;
|
|
|
|
lengths[indent - 1] = (s - os);
|
|
|
|
}
|
2017-10-16 11:31:13 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '{':
|
|
|
|
case '[':
|
|
|
|
if (*s == '[') {
|
|
|
|
isarr = true;
|
|
|
|
arrpos = 0;
|
|
|
|
}
|
|
|
|
if (indent > 128) {
|
|
|
|
eprintf ("JSON indentation is too deep\n");
|
|
|
|
indent = 0;
|
|
|
|
} else {
|
|
|
|
indent++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '}':
|
|
|
|
case ']':
|
|
|
|
if (*s == ']') {
|
|
|
|
isarr = false;
|
|
|
|
}
|
|
|
|
indent--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int i;
|
|
|
|
ut64 opos = 0;
|
2017-10-21 09:33:51 +00:00
|
|
|
for (i = 0; i < DSZ && i < indent; i++) {
|
2017-12-03 17:22:47 +00:00
|
|
|
if ((int)(size_t)words[i] < DSZ) {
|
2017-10-16 11:31:13 +00:00
|
|
|
ut64 cur = lengths[i];
|
|
|
|
if (cur < opos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
opos = cur;
|
|
|
|
if (cur > pos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
eprintf ("0x%08"PFMT64x" %d [%d]\n", cur, i, indexs[i]);
|
|
|
|
} else {
|
|
|
|
char *a = r_str_ndup (words[i], lengths[i]);
|
|
|
|
ut64 cur = words[i] - os - 1;
|
|
|
|
if (cur < opos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
opos = cur;
|
|
|
|
if (cur > pos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
char *q = strchr (a, '"');
|
|
|
|
if (q) {
|
|
|
|
*q = 0;
|
|
|
|
}
|
|
|
|
eprintf ("0x%08"PFMT64x" %d %s\n", cur, i, a);
|
|
|
|
free (a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO return something
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-08-11 10:23:57 +00:00
|
|
|
R_API char* r_print_json_indent(const char* s, bool color, const char* tab, const char **palette) {
|
2017-02-20 01:31:49 +00:00
|
|
|
int indent = 0;
|
2017-09-13 09:39:10 +00:00
|
|
|
const int indentSize = strlen (tab);
|
2017-03-17 11:09:17 +00:00
|
|
|
int instr = 0;
|
2017-02-20 01:31:49 +00:00
|
|
|
bool isValue = false;
|
2017-08-11 10:23:57 +00:00
|
|
|
char *o, *OE, *tmp;
|
2017-02-20 01:31:49 +00:00
|
|
|
if (!s) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-08-11 10:23:57 +00:00
|
|
|
const char **colors = palette ? palette: origColors;
|
|
|
|
int osz = (1 + strlen (s)) * 20;
|
2017-02-20 01:31:49 +00:00
|
|
|
if (osz < 1) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-05-15 20:32:46 +00:00
|
|
|
|
2017-08-11 10:23:57 +00:00
|
|
|
char *O = malloc (osz);
|
2017-02-20 01:31:49 +00:00
|
|
|
if (!O) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
OE = O + osz;
|
|
|
|
for (o = O; *s; s++) {
|
2017-09-13 09:39:10 +00:00
|
|
|
if (o + (indent * indentSize) + 10 > OE) {
|
2017-02-20 01:31:49 +00:00
|
|
|
int delta = o - O;
|
2017-09-13 09:39:10 +00:00
|
|
|
osz += 0x1000 + (indent * indentSize);
|
2017-02-20 01:31:49 +00:00
|
|
|
if (osz < 1) {
|
|
|
|
free (O);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tmp = realloc (O, osz);
|
|
|
|
if (!tmp) {
|
|
|
|
free (O);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
O = tmp;
|
|
|
|
OE = tmp + osz;
|
|
|
|
o = O + delta;
|
|
|
|
}
|
|
|
|
if (instr) {
|
|
|
|
if (s[0] == '"') {
|
|
|
|
instr = 0;
|
|
|
|
} else if (s[0] == '\\' && s[1] == '"') {
|
2017-12-07 23:34:29 +00:00
|
|
|
*o++ = *s++;
|
2017-02-20 01:31:49 +00:00
|
|
|
}
|
|
|
|
if (instr) {
|
|
|
|
if (isValue) {
|
2017-08-11 10:23:57 +00:00
|
|
|
// TODO: do not emit color in every char
|
|
|
|
EMIT_ESC (o, colors[JC_VAL]);
|
2017-02-20 01:31:49 +00:00
|
|
|
} else {
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_KEY]);
|
2017-02-20 01:31:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_RESET]);
|
2017-02-20 01:31:49 +00:00
|
|
|
}
|
|
|
|
*o++ = *s;
|
|
|
|
continue;
|
|
|
|
}
|
2017-05-15 20:32:46 +00:00
|
|
|
if (indent <= 0) {
|
|
|
|
// non-JSON part
|
|
|
|
if (s[0] != '{' && s[0] != '[') {
|
|
|
|
*o++ = *s;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-20 01:31:49 +00:00
|
|
|
if (s[0] == '"') {
|
|
|
|
instr = 1;
|
|
|
|
}
|
|
|
|
if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (*s) {
|
|
|
|
case ':':
|
|
|
|
*o++ = *s;
|
|
|
|
*o++ = ' ';
|
|
|
|
if (!strncmp (s + 1, "true", 4)) {
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_TRUE]);
|
2017-02-20 01:31:49 +00:00
|
|
|
} else if (!strncmp (s + 1, "false", 5)) {
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_FALSE]);
|
2017-02-20 01:31:49 +00:00
|
|
|
}
|
|
|
|
isValue = true;
|
|
|
|
break;
|
|
|
|
case ',':
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_RESET]);
|
2017-02-20 01:31:49 +00:00
|
|
|
*o++ = *s;
|
|
|
|
*o++ = '\n';
|
|
|
|
isValue = false;
|
2017-03-17 11:09:17 +00:00
|
|
|
doIndent (indent, &o, tab);
|
2017-02-20 01:31:49 +00:00
|
|
|
break;
|
|
|
|
case '{':
|
|
|
|
case '[':
|
|
|
|
isValue = false;
|
|
|
|
*o++ = *s;
|
|
|
|
*o++ = (indent != -1)? '\n': ' ';
|
2017-09-13 09:39:10 +00:00
|
|
|
if (indent > 128) {
|
|
|
|
eprintf ("JSON indentation is too deep\n");
|
|
|
|
indent = 0;
|
|
|
|
} else {
|
|
|
|
indent++;
|
|
|
|
}
|
2017-03-17 11:09:17 +00:00
|
|
|
doIndent (indent, &o, tab);
|
2017-02-20 01:31:49 +00:00
|
|
|
break;
|
|
|
|
case '}':
|
|
|
|
case ']':
|
2017-08-11 10:23:57 +00:00
|
|
|
EMIT_ESC (o, colors[JC_RESET]);
|
2017-02-20 01:31:49 +00:00
|
|
|
isValue = false;
|
|
|
|
*o++ = '\n';
|
2017-03-17 11:09:17 +00:00
|
|
|
indent--;
|
|
|
|
doIndent (indent, &o, tab);
|
2017-02-20 01:31:49 +00:00
|
|
|
*o++ = *s;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*o++ = *s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*o = 0;
|
|
|
|
return O;
|
|
|
|
}
|
2017-05-15 20:32:46 +00:00
|
|
|
|
|
|
|
#undef EMIT_ESC
|