Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 8c417df6e2
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 97 lines (81 sloc) 2.196 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
// by jeremie miller - 2010
// public domain, contributions/improvements welcome via github

// opportunity to further optimize would be having different jump tables for higher depths
#define PUSH(i) if(depth == 1) *out++ = ((cur+i) - js)
#define CAP(i) if(depth == 1) *out++ = (cur+i) - (js + *(out-1)) + 1

int js0n(unsigned char *js, unsigned int len, unsigned short *out)
{
unsigned char *cur, *end;
int depth=0;
static void *gostruct[] =
{
[0 ... 255] = &&l_bad,
['\t'] = &&l_loop, [' '] = &&l_loop, ['\r'] = &&l_loop, ['\n'] = &&l_loop,
['"'] = &&l_qup,
[':'] = &&l_loop,[','] = &&l_loop,
['['] = &&l_up, [']'] = &&l_down, // tracking [] and {} individually would allow fuller validation but is really messy
['{'] = &&l_up, ['}'] = &&l_down,
['-'] = &&l_bare, [48 ... 57] = &&l_bare, // 0-9
['t'] = &&l_bare, ['f'] = &&l_bare, ['n'] = &&l_bare // true, false, null
};
static void *gobare[] =
{
[0 ... 31] = &&l_bad,
[32 ... 126] = &&l_loop, // could be more pedantic/validation-checking
['\t'] = &&l_unbare, [' '] = &&l_unbare, ['\r'] = &&l_unbare, ['\n'] = &&l_unbare,
[','] = &&l_unbare, [']'] = &&l_unbare, ['}'] = &&l_unbare,
[127 ... 255] = &&l_bad
};
static void *gostring[] =
{
[0 ... 31] = &&l_bad, [127] = &&l_bad,
[32 ... 126] = &&l_loop,
['\\'] = &&l_esc, ['"'] = &&l_qdown,
[128 ... 255] = &&l_loop
};
static void *goesc[] =
{
[0 ... 255] = &&l_bad,
['"'] = &&l_unesc, ['\\'] = &&l_unesc, ['/'] = &&l_unesc, ['b'] = &&l_unesc,
['f'] = &&l_unesc, ['n'] = &&l_unesc, ['r'] = &&l_unesc, ['t'] = &&l_unesc, ['u'] = &&l_unesc
};
static void **go = gostruct;

for(cur=js,end=js+len; cur<end; cur++)
{
goto *go[*cur];
l_loop:;
}

return depth; // 0 if successful full parse, >0 for incomplete data

l_bad:
return 1;

l_up:
PUSH(0);
++depth;
goto l_loop;

l_down:
--depth;
CAP(0);
goto l_loop;

l_qup:
PUSH(1);
go=gostring;
goto l_loop;

l_qdown:
CAP(-1);
go=gostruct;
goto l_loop;

l_esc:
go = goesc;
goto l_loop;

l_unesc:
go = gostring;
goto l_loop;

l_bare:
PUSH(0);
go = gobare;
goto l_loop;

l_unbare:
CAP(-1);
go = gostruct;
goto *go[*cur];

}

Something went wrong with that request. Please try again.