source: EcnlProtoTool/trunk/mrbgems/mruby-iijson/src/json.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 14.8 KB
Line 
1#include <ctype.h>
2#include <inttypes.h>
3#include <string.h>
4
5#include "mruby.h"
6#include "mruby/array.h"
7#include "mruby/hash.h"
8#include "mruby/string.h"
9#include "mruby/value.h"
10
11#define E_JSON_PARSER_ERROR (mrb_class_get_under(mrb, mrb_module_get(mrb, "JSON"), "ParserError"))
12
13#define JSON_EOF -1
14
15#define DEFAULT_MAX_NESTING 100
16
17struct json_parser {
18 mrb_state *mrb;
19 mrb_value src;
20 unsigned int cursor;
21 unsigned int lineno;
22 int nesting;
23
24 int max_nesting;
25};
26
27static void json_check_nesting(struct json_parser *);
28static int json_delimiter_p(char ch);
29static int json_getc(struct json_parser *);
30static void json_skip_ws(struct json_parser *);
31static void json_ungetc(struct json_parser *);
32static int json_unicode2utf8(uint32_t, char *);
33static int json_whitespace_p(char ch);
34
35static int json_parse_array(struct json_parser *, mrb_value *);
36static int json_parse_object(struct json_parser *, mrb_value *);
37static int json_parse_number2(struct json_parser *, int, mrb_value *, mrb_int, int);
38static int json_parse_string(struct json_parser *, mrb_value *);
39static int json_parse_value(struct json_parser *, mrb_value *);
40
41#if MRUBY_RELEASE_NO < 10000
42static struct RClass *
43mrb_module_get(mrb_state *mrb, const char *name)
44{
45 return mrb_class_get(mrb, name);
46}
47#endif
48#if !defined(MRB_PRId)
49#if defined(MRB_INT64)
50# define MRB_PRId PRId64
51#elif defined(MRB_INT16)
52# define MRB_PRId PRId16
53#else
54# define MRB_PRId PRId32
55#endif
56#endif /* !defined(MRB_PRId) */
57
58static void
59json_check_nesting(struct json_parser *parser)
60{
61 mrb_state *mrb = parser->mrb;
62
63 if (parser->max_nesting != -1) {
64 if (parser->nesting >= parser->max_nesting) {
65 // +1 for compatibility with CRuby
66 mrb_raisef(mrb, E_JSON_PARSER_ERROR, "nesting of %S is too deep", mrb_fixnum_value(parser->nesting+1));
67 }
68 }
69}
70
71static int
72json_delimiter_p(char ch)
73{
74 return (json_whitespace_p(ch) || ch == ',' || ch == ']' || ch == '}');
75}
76
77static int
78json_getc(struct json_parser *parser)
79{
80 if (parser->cursor < RSTRING_LEN(parser->src)) {
81 unsigned char ch = RSTRING_PTR(parser->src)[parser->cursor];
82 parser->cursor++;
83 return ch;
84 } else {
85 return JSON_EOF;
86 }
87}
88
89static int
90json_parse_readstring(struct json_parser *parser, const char *str)
91{
92 size_t len;
93 int ch;
94
95 len = strlen(str);
96 if (parser->cursor + len > RSTRING_LEN(parser->src))
97 return 0;
98 if (memcmp(str, RSTRING_PTR(parser->src) + parser->cursor, len) != 0)
99 return -1;
100 parser->cursor += len;
101 if (parser->cursor == RSTRING_LEN(parser->src))
102 return 1;
103 ch = RSTRING_PTR(parser->src)[parser->cursor];
104 if (!json_delimiter_p(ch))
105 return -1;
106 return 1;
107}
108
109static void
110json_skip_ws(struct json_parser *parser)
111{
112 int ch;
113
114 do {
115 ch = json_getc(parser);
116 if (ch == 0x0a)
117 parser->lineno++;
118 } while (json_whitespace_p(ch));
119 if (ch != JSON_EOF) {
120 json_ungetc(parser);
121 }
122}
123
124static void
125json_ungetc(struct json_parser *parser)
126{
127 if (parser->cursor > 0)
128 parser->cursor--;
129}
130
131static int
132json_unicode2utf8(uint32_t unicode, char *cp)
133{
134 int n = 0;
135 if (unicode < 0x80) {
136 cp[n++] = unicode;
137 } else if (unicode < 0x800) {
138 cp[n++] = 0xc0 + (unicode >> 6);
139 cp[n++] = 0x80 + (unicode & 0x3f);
140 } else if (unicode < 0x10000) {
141 cp[n++] = 0xe0 + (unicode >> 12);
142 cp[n++] = 0x80 + ((unicode >> 6) & 0x3f);
143 cp[n++] = 0x80 + (unicode & 0x3f);
144 } else {
145 cp[n++] = 0xf0 + (unicode >> 18);
146 cp[n++] = 0x80 + ((unicode >> 12) & 0x3f);
147 cp[n++] = 0x80 + ((unicode >> 6) & 0x3f);
148 cp[n++] = 0x80 + (unicode & 0x3f);
149 }
150 return n;
151}
152
153static int
154json_whitespace_p(char ch)
155{
156 return (ch == 0x20 || ch == 0x09 || ch == 0x0a || ch == 0x0d);
157}
158
159static int
160json_parse_array(struct json_parser *parser, mrb_value *result)
161{
162 mrb_state *mrb = parser->mrb;
163 mrb_value ary, v;
164 int ch;
165
166 json_check_nesting(parser);
167
168 ary = mrb_ary_new(mrb);
169
170 json_skip_ws(parser);
171 ch = json_getc(parser);
172 if (ch == ']') { /* easy case */
173 *result = ary;
174 return 1;
175 }
176 if (ch == JSON_EOF) {
177 mrb_raise(mrb, E_JSON_PARSER_ERROR, "JSON_EOF in array(1)");
178 }
179 json_ungetc(parser);
180
181 while (1) {
182 parser->nesting++;
183 if (json_parse_value(parser, &v) != 1) {
184 mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in array");
185 }
186 parser->nesting--;
187
188 mrb_ary_push(mrb, ary, v);
189
190 json_skip_ws(parser);
191 ch = json_getc(parser);
192 if (ch == ']') {
193 break;
194 }
195 if (ch == JSON_EOF) {
196 mrb_raise(mrb, E_JSON_PARSER_ERROR, "JSON_EOF in array(2)");
197 }
198 if (ch != ',') {
199 mrb_raise(mrb, E_JSON_PARSER_ERROR, "not ',' in array");
200 }
201 }
202 *result = ary;
203 return 1;
204}
205
206static int
207json_parse_object(struct json_parser *parser, mrb_value *result)
208{
209 mrb_state *mrb = parser->mrb;
210 mrb_value h, k, v;
211 int ch;
212
213 json_check_nesting(parser);
214
215 h = mrb_hash_new(mrb);
216
217 json_skip_ws(parser);
218 ch = json_getc(parser);
219 if (ch == '}') { /* easy case */
220 *result = h;
221 return 1;
222 }
223 if (ch == JSON_EOF) {
224 mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(1)");
225 }
226 json_ungetc(parser);
227
228 while (1) {
229 parser->nesting++;
230 if (json_parse_value(parser, &k) != 1) {
231 mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in object key");
232 }
233 parser->nesting--;
234 if (! mrb_string_p(k)) {
235 mrb_raise(mrb, E_JSON_PARSER_ERROR, "key is not a string");
236 }
237
238 json_skip_ws(parser);
239
240 ch = json_getc(parser);
241 if (ch == JSON_EOF) {
242 mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(2)");
243 }
244 if (ch != ':') {
245 mrb_raise(mrb, E_JSON_PARSER_ERROR, "no ':' in object");
246 }
247
248 parser->nesting++;
249 if (json_parse_value(parser, &v) != 1) {
250 mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in object value");
251 }
252 parser->nesting--;
253
254 mrb_hash_set(mrb, h, k, v);
255
256 json_skip_ws(parser);
257 ch = json_getc(parser);
258 if (ch == '}') {
259 break;
260 }
261 if (ch == JSON_EOF) {
262 mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(3)");
263 }
264 if (ch != ',') {
265 mrb_raise(mrb, E_JSON_PARSER_ERROR, "no ',' in object");
266 }
267 }
268 *result = h;
269 return 1;
270}
271
272static int
273json_parse_number(struct json_parser *parser, int ch, mrb_value *result)
274{
275 mrb_state *mrb = parser->mrb;
276 mrb_int num;
277 int d, sign;
278
279 if (ch == '-') {
280 sign = -1;
281 ch = json_getc(parser);
282 if (ch == JSON_EOF) {
283 mrb_raise(mrb, E_JSON_PARSER_ERROR, "no character following minus");
284 }
285 if (!isdigit(ch)) {
286 mrb_raise(mrb, E_JSON_PARSER_ERROR, "character following minus is not a digit");
287 }
288 } else {
289 sign = 1;
290 }
291 num = (ch - '0') * sign;
292 while (1) {
293 ch = json_getc(parser);
294 if (ch == JSON_EOF) {
295 break;
296 }
297 if (isdigit(ch)) {
298 if (num == 0) {
299 mrb_raise(mrb, E_JSON_PARSER_ERROR, "leading zeros are not allowed");
300 }
301 d = (ch - '0') * sign;
302 if (num < MRB_INT_MIN / 10 ||
303 (num == MRB_INT_MIN / 10 && d < MRB_INT_MIN - num * 10) ||
304 num > MRB_INT_MAX / 10 ||
305 (num == MRB_INT_MAX / 10 && d > MRB_INT_MAX - num * 10)) {
306 return json_parse_number2(parser, ch, result, num, sign);
307 }
308 num = num * 10 + d;
309 } else if (ch == '.' || ch == 'e' || ch == 'E') {
310 return json_parse_number2(parser, ch, result, num, sign);
311 } else if (json_delimiter_p(ch)) {
312 json_ungetc(parser);
313 break;
314 } else {
315 mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid number");
316 }
317 }
318 *result = mrb_fixnum_value(num);
319 return 1;
320}
321
322static int
323json_parse_number2(struct json_parser *parser, int ch, mrb_value *result, mrb_int num, int sign)
324{
325 mrb_state *mrb = parser->mrb;
326 double d;
327 int i, state;
328 char buf[64];
329
330 /*
331 * "-"? ("0" | [1-9] digit* ) ("." digit+ )? ([eE][-+] digit+)?
332 * state: 000000 111 222222 33334444 555555
333 */
334 i = snprintf(buf, sizeof(buf), "%s%"MRB_PRId"%c",
335 (num == 0 && sign < 0) ? "-" : "",
336 num, ch);
337
338 if (isdigit(ch))
339 state = 0;
340 else if (ch == '.')
341 state = 1;
342 else /* (ch == 'e' || ch == 'E') */
343 state = 3;
344
345 while (1) {
346 ch = json_getc(parser);
347 if (ch == JSON_EOF)
348 break;
349 switch (state) {
350 case 0:
351 if (isdigit(ch))
352 ; /* read more digits */
353 else if (ch == '.')
354 state = 1;
355 else if (ch == 'e' || ch == 'E')
356 state = 3;
357 else if (json_delimiter_p(ch)) {
358 json_ungetc(parser);
359 state = -1;
360 } else
361 goto formaterr;
362 break;
363 case 1:
364 if (!isdigit(ch))
365 goto formaterr;
366 state = 2;
367 break;
368 case 2:
369 if (isdigit(ch))
370 ; /* read more digits */
371 else if (ch == 'e' || ch == 'E')
372 state = 3;
373 else if (json_delimiter_p(ch)) {
374 json_ungetc(parser);
375 state = -1;
376 } else
377 goto formaterr;
378 break;
379 case 3:
380 if (ch == '-' || ch == '+')
381 state = 4;
382 else if (isdigit(ch))
383 state = 5;
384 else
385 goto formaterr;
386 break;
387 case 4:
388 if (!isdigit(ch))
389 goto formaterr;
390 state = 5;
391 break;
392 case 5:
393 default:
394 if (isdigit(ch))
395 ; /* read more digits */
396 else {
397 json_ungetc(parser);
398 state = -1;
399 }
400 break;
401 }
402 if (state == -1)
403 break;
404 if (i == sizeof(buf) - 1) {
405 mrb_raise(mrb, E_JSON_PARSER_ERROR, "floating point number too long");
406 }
407 buf[i++] = ch;
408 }
409 buf[i] = '\0';
410 sscanf(buf, "%lf", &d);
411 *result = mrb_float_value(mrb, d);
412 return 1;
413
414formaterr:
415 mrb_raise(mrb, E_JSON_PARSER_ERROR, "floating point number error");
416 return -1;
417}
418
419static int
420json_parse_string(struct json_parser *parser, mrb_value *result)
421{
422 mrb_state *mrb = parser->mrb;
423 mrb_value str;
424 uint32_t unicode;
425 uint16_t utf16;
426 int ch, i, n;
427 char *cp;
428
429 str = mrb_str_buf_new(mrb, 30);
430 cp = RSTRING_PTR(str);
431 n = 0;
432 unicode = 0;
433
434 while (1) {
435 ch = json_getc(parser);
436 if (ch == JSON_EOF) {
437 mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in string");
438 }
439
440 if (ch == '"') {
441 break;
442 } else if (ch == '\\') {
443 ch = json_getc(parser);
444 if (ch == JSON_EOF) {
445 mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF following escape char");
446 }
447 switch (ch) {
448 case '"':
449 case '\\':
450 case '/':
451 break;
452 case 'b':
453 ch = 0x08;
454 break;
455 case 'f':
456 ch = 0x0c;
457 break;
458 case 'n':
459 ch = 0x0a;
460 break;
461 case 'r':
462 ch = 0x0d;
463 break;
464 case 't':
465 ch = 0x09;
466 break;
467 case 'u':
468 utf16 = 0;
469 for (i = 0; i < 4; i++) {
470 ch = json_getc(parser);
471 if (ch == JSON_EOF) {
472 mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid unicode escape");
473 }
474 if (ch >= '0' && ch <= '9') {
475 ch -= '0';
476 } else if (ch >= 'A' && ch <= 'F') {
477 ch = (ch - 'A') + 10;
478 } else if (ch >= 'a' && ch <= 'f') {
479 ch = (ch - 'a') + 10;
480 } else {
481 mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid unicode character");
482 }
483 utf16 *= 16;
484 utf16 += ch;
485 }
486
487 if (n + 8 >= RSTRING_CAPA(str)) {
488 mrb_str_resize(mrb, str, RSTRING_CAPA(str)*2);
489 cp = RSTRING_PTR(str);
490 }
491
492 if ((utf16 & 0xf800) == 0xd800) {
493 if ((utf16 & 0xfc00) == 0xd800) {
494 /* high surrogate */
495 unicode = utf16;
496 continue;
497 } else {
498 /* low surrogate */
499 if (unicode > 0) {
500 unicode = ((unicode & 0x03ff) + 0x040) << 10;
501 unicode += utf16 & 0x03ff;
502 } else {
503 /* error: low surrogate comes first... */
504 }
505 }
506 } else {
507 if (unicode > 0) {
508 /* error: high surrogate not followed by low surrogate */
509 n += json_unicode2utf8(unicode, &cp[n]);
510 }
511 unicode = utf16;
512 }
513
514 n += json_unicode2utf8(unicode, &cp[n]);
515 unicode = 0;
516 continue;
517 default:
518 mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid escape char");
519 break;
520 }
521 } else if (ch < 0x20) {
522 mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid char");
523 }
524
525 if (n + 1 == RSTRING_CAPA(str)) {
526 mrb_str_resize(mrb, str, RSTRING_CAPA(str)*2);
527 cp = RSTRING_PTR(str);
528 }
529 cp[n++] = ch;
530 }
531 cp[n] = '\0';
532 mrb_str_resize(mrb, str, n);
533 *result = str;
534 return 1;
535}
536
537static int
538json_parse_value(struct json_parser *parser, mrb_value *result)
539{
540 mrb_state *mrb = parser->mrb;
541 int ch;
542
543 do {
544 ch = json_getc(parser);
545 if (ch == JSON_EOF)
546 return 0;
547 } while (json_whitespace_p(ch));
548
549 switch (ch) {
550 case '0': case '1': case '2': case '3': case '4':
551 case '5': case '6': case '7': case '8': case '9':
552 case '-':
553 if (json_parse_number(parser, ch, result) != 1) {
554 mrb_raise(mrb, E_JSON_PARSER_ERROR, "number...?");
555 }
556 break;
557
558 case '"':
559 if (json_parse_string(parser, result) != 1) {
560 mrb_raise(mrb, E_JSON_PARSER_ERROR, "string...?");
561 }
562 break;
563
564 case '[':
565 if (json_parse_array(parser, result) != 1) {
566 mrb_raise(mrb, E_JSON_PARSER_ERROR, "array...?");
567 }
568 break;
569
570 case '{':
571 if (json_parse_object(parser, result) != 1) {
572 mrb_raise(mrb, E_JSON_PARSER_ERROR, "object...?");
573 }
574 break;
575
576 case 'f':
577 if (json_parse_readstring(parser, "alse") != 1) {
578 mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected f");
579 }
580 *result = mrb_false_value();
581 break;
582
583 case 'n':
584 if (json_parse_readstring(parser, "ull") != 1) {
585 mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected n");
586 }
587 *result = mrb_nil_value();
588 break;
589
590 case 't':
591 if (json_parse_readstring(parser, "rue") != 1) {
592 mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected t");
593 }
594 *result = mrb_true_value();
595 break;
596
597 default:
598 mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected character");
599 }
600
601 return 1;
602}
603
604static mrb_value
605mrb_json_parse(mrb_state *mrb, mrb_value mod)
606{
607 struct json_parser parser;
608 mrb_value obj, options, source;
609
610 mrb_get_args(mrb, "S|H", &source, &options);
611
612 parser.mrb = mrb;
613 parser.src = source;
614 parser.cursor = 0;
615 parser.lineno = 0;
616 parser.nesting = 0;
617 parser.max_nesting = DEFAULT_MAX_NESTING;
618
619 if (json_parse_value(&parser, &obj) == 0) {
620 mrb_raise(mrb, E_JSON_PARSER_ERROR, "no JSON value");
621 }
622
623 // if we have extra characters:
624 // unexpected token at '3' (JSON::ParserError)
625
626 return obj;
627}
628
629void
630mrb_mruby_iijson_gem_init(mrb_state *mrb)
631{
632 struct RClass *m;
633
634 m = mrb_define_module(mrb, "JSON");
635 mrb_define_module_function(mrb, m, "parse", mrb_json_parse, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
636}
637
638void
639mrb_mruby_iijson_gem_final(mrb_state *mrb)
640{
641}
Note: See TracBrowser for help on using the repository browser.