forked from quartzjer/js0n
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjs0n.c
More file actions
127 lines (108 loc) · 2.67 KB
/
js0n.c
File metadata and controls
127 lines (108 loc) · 2.67 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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;
int utf8_remain=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 ... 191] = &&l_bad,
[192 ... 223] = &&l_utf8_2,
[224 ... 239] = &&l_utf8_3,
[240 ... 247] = &&l_utf8_4,
[248 ... 255] = &&l_bad
};
static void *goutf8_continue[] =
{
[0 ... 127] = &&l_bad,
[128 ... 191] = &&l_utf_continue,
[192 ... 255] = &&l_bad
};
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];
l_utf8_2:
go = goutf8_continue;
utf8_remain = 1;
goto l_loop;
l_utf8_3:
go = goutf8_continue;
utf8_remain = 2;
goto l_loop;
l_utf8_4:
go = goutf8_continue;
utf8_remain = 3;
goto l_loop;
l_utf_continue:
if (!--utf8_remain)
go=gostring;
goto l_loop;
}