]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/mujs/json.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / mujs / json.c
1 #include "jsi.h"
2 #include "jslex.h"
3 #include "jsvalue.h"
4 #include "jsbuiltin.h"
5
6 #include "utf.h"
7
8 static void jsonnext(js_State *J)
9 {
10         J->lookahead = jsY_lexjson(J);
11 }
12
13 static int jsonaccept(js_State *J, int t)
14 {
15         if (J->lookahead == t) {
16                 jsonnext(J);
17                 return 1;
18         }
19         return 0;
20 }
21
22 static void jsonexpect(js_State *J, int t)
23 {
24         if (!jsonaccept(J, t))
25                 js_syntaxerror(J, "JSON: unexpected token: %s (expected %s)",
26                                 jsY_tokenstring(J->lookahead), jsY_tokenstring(t));
27 }
28
29 static void jsonvalue(js_State *J)
30 {
31         int i;
32         const char *name;
33
34         switch (J->lookahead) {
35         case TK_STRING:
36                 js_pushliteral(J, J->text);
37                 jsonnext(J);
38                 break;
39
40         case TK_NUMBER:
41                 js_pushnumber(J, J->number);
42                 jsonnext(J);
43                 break;
44
45         case '{':
46                 js_newobject(J);
47                 jsonnext(J);
48                 if (jsonaccept(J, '}'))
49                         return;
50                 do {
51                         if (J->lookahead != TK_STRING)
52                                 js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead));
53                         name = J->text;
54                         jsonnext(J);
55                         jsonexpect(J, ':');
56                         jsonvalue(J);
57                         js_setproperty(J, -2, name);
58                 } while (jsonaccept(J, ','));
59                 jsonexpect(J, '}');
60                 break;
61
62         case '[':
63                 js_newarray(J);
64                 jsonnext(J);
65                 i = 0;
66                 if (jsonaccept(J, ']'))
67                         return;
68                 do {
69                         jsonvalue(J);
70                         js_setindex(J, -2, i++);
71                 } while (jsonaccept(J, ','));
72                 jsonexpect(J, ']');
73                 break;
74
75         case TK_TRUE:
76                 js_pushboolean(J, 1);
77                 jsonnext(J);
78                 break;
79
80         case TK_FALSE:
81                 js_pushboolean(J, 0);
82                 jsonnext(J);
83                 break;
84
85         case TK_NULL:
86                 js_pushnull(J);
87                 jsonnext(J);
88                 break;
89
90         default:
91                 js_syntaxerror(J, "JSON: unexpected token: %s", jsY_tokenstring(J->lookahead));
92         }
93 }
94
95 static void JSON_parse(js_State *J)
96 {
97         const char *source = js_tostring(J, 1);
98         jsY_initlex(J, "JSON", source);
99         jsonnext(J);
100         jsonvalue(J);
101         // TODO: reviver Walk()
102 }
103
104 static void fmtnum(js_State *J, js_Buffer **sb, double n)
105 {
106         if (isnan(n)) js_puts(J, sb, "null");
107         else if (isinf(n)) js_puts(J, sb, "null");
108         else if (n == 0) js_puts(J, sb, "0");
109         else {
110                 char buf[40];
111                 sprintf(buf, "%.17g", n);
112                 js_puts(J, sb, buf);
113         }
114 }
115
116 static void fmtstr(js_State *J, js_Buffer **sb, const char *s)
117 {
118         static const char *HEX = "0123456789ABCDEF";
119         Rune c;
120         js_putc(J, sb, '"');
121         while (*s) {
122                 s += chartorune(&c, s);
123                 switch (c) {
124                 case '"': js_puts(J, sb, "\\\""); break;
125                 case '\\': js_puts(J, sb, "\\\\"); break;
126                 case '\b': js_puts(J, sb, "\\b"); break;
127                 case '\f': js_puts(J, sb, "\\f"); break;
128                 case '\n': js_puts(J, sb, "\\n"); break;
129                 case '\r': js_puts(J, sb, "\\r"); break;
130                 case '\t': js_puts(J, sb, "\\t"); break;
131                 default:
132                         if (c < ' ') {
133                                 js_puts(J, sb, "\\u");
134                                 js_putc(J, sb, HEX[(c>>12)&15]);
135                                 js_putc(J, sb, HEX[(c>>8)&15]);
136                                 js_putc(J, sb, HEX[(c>>4)&15]);
137                                 js_putc(J, sb, HEX[c&15]);
138                         } else {
139                                 js_putc(J, sb, c); break;
140                         }
141                 }
142         }
143         js_putc(J, sb, '"');
144 }
145
146 static void fmtindent(js_State *J, js_Buffer **sb, const char *gap, int level)
147 {
148         js_putc(J, sb, '\n');
149         while (level--)
150                 js_puts(J, sb, gap);
151 }
152
153 static int fmtvalue(js_State *J, js_Buffer **sb, const char *key, const char *gap, int level);
154
155 static void fmtobject(js_State *J, js_Buffer **sb, js_Object *obj, const char *gap, int level)
156 {
157         js_Property *ref;
158         int save;
159         int n = 0;
160
161         js_putc(J, sb, '{');
162         for (ref = obj->head; ref; ref = ref->next) {
163                 if (ref->atts & JS_DONTENUM)
164                         continue;
165                 save = (*sb)->n;
166                 if (n) js_putc(J, sb, ',');
167                 if (gap) fmtindent(J, sb, gap, level + 1);
168                 fmtstr(J, sb, ref->name);
169                 js_putc(J, sb, ':');
170                 if (gap)
171                         js_putc(J, sb, ' ');
172                 js_pushvalue(J, ref->value);
173                 if (!fmtvalue(J, sb, ref->name, gap, level + 1))
174                         (*sb)->n = save;
175                 else
176                         ++n;
177                 js_pop(J, 1);
178         }
179         if (gap && n) fmtindent(J, sb, gap, level);
180         js_putc(J, sb, '}');
181 }
182
183 static void fmtarray(js_State *J, js_Buffer **sb, const char *gap, int level)
184 {
185         unsigned int n, k;
186         char buf[32];
187
188         n = js_getlength(J, -1);
189
190         js_putc(J, sb, '[');
191         for (k = 0; k < n; ++k) {
192                 if (k) js_putc(J, sb, ',');
193                 if (gap) fmtindent(J, sb, gap, level + 1);
194                 js_itoa(buf, k);
195                 js_getproperty(J, -1, buf);
196                 if (!fmtvalue(J, sb, js_intern(J, buf), gap, level + 1))
197                         js_puts(J, sb, "null");
198                 js_pop(J, 1);
199         }
200         if (gap && n) fmtindent(J, sb, gap, level);
201         js_putc(J, sb, ']');
202 }
203
204 static int fmtvalue(js_State *J, js_Buffer **sb, const char *key, const char *gap, int level)
205 {
206         if (js_try(J)) {
207                 js_free(J, *sb);
208                 js_throw(J);
209         }
210         if (js_isobject(J, -1)) {
211                 if (js_hasproperty(J, -1, "toJSON")) {
212                         if (js_iscallable(J, -1)) {
213                                 js_copy(J, -2);
214                                 js_pushliteral(J, key);
215                                 js_call(J, 1);
216                                 js_rot2pop1(J);
217                         } else {
218                                 js_pop(J, 1);
219                         }
220                 }
221         }
222         js_endtry(J);
223
224         // TODO: replacer()
225
226         if (js_isobject(J, -1) && !js_iscallable(J, -1)) {
227                 js_Object *obj = js_toobject(J, -1);
228                 switch (obj->type) {
229                 case JS_CNUMBER: fmtnum(J, sb, obj->u.number); break;
230                 case JS_CSTRING: fmtstr(J, sb, obj->u.s.string); break;
231                 case JS_CBOOLEAN: js_puts(J, sb, obj->u.boolean ? "true" : "false"); break;
232                 case JS_CARRAY: fmtarray(J, sb, gap, level); break;
233                 default: fmtobject(J, sb, obj, gap, level); break;
234                 }
235         }
236         else if (js_isboolean(J, -1))
237                 js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
238         else if (js_isnumber(J, -1))
239                 fmtnum(J, sb, js_tonumber(J, -1));
240         else if (js_isstring(J, -1))
241                 fmtstr(J, sb, js_tostring(J, -1));
242         else if (js_isnull(J, -1))
243                 js_puts(J, sb, "null");
244         else
245                 return 0;
246
247         return 1;
248 }
249
250 static void JSON_stringify(js_State *J)
251 {
252         js_Buffer *sb = NULL;
253         char buf[12];
254         const char *s, *gap;
255         int n;
256
257         gap = NULL;
258
259         if (js_isnumber(J, 3)) {
260                 n = js_tointeger(J, 3);
261                 if (n < 0) n = 0;
262                 if (n > 10) n = 10;
263                 memset(buf, ' ', n);
264                 buf[n] = 0;
265                 if (n > 0) gap = buf;
266         } else if (js_isstring(J, 3)) {
267                 s = js_tostring(J, 3);
268                 n = strlen(s);
269                 if (n > 10) n = 10;
270                 memcpy(buf, s, n);
271                 buf[n] = 0;
272                 if (n > 0) gap = buf;
273         }
274
275         // TODO: replacer
276
277         if (js_isdefined(J, 1)) {
278                 js_copy(J, 1);
279                 if (fmtvalue(J, &sb, "", gap, 0)) {
280                         js_putc(J, &sb, 0);
281                         if (js_try(J)) {
282                                 js_free(J, sb);
283                                 js_throw(J);
284                         }
285                         js_pushstring(J, sb ? sb->s : "");
286                         js_endtry(J);
287                         js_free(J, sb);
288                 }
289         } else {
290                 js_pushundefined(J);
291         }
292 }
293
294 void jsB_initjson(js_State *J)
295 {
296         js_pushobject(J, jsV_newobject(J, JS_CJSON, J->Object_prototype));
297         {
298                 jsB_propf(J, "parse", JSON_parse, 2);
299                 jsB_propf(J, "stringify", JSON_stringify, 3);
300         }
301         js_defglobal(J, "JSON", JS_DONTENUM);
302 }