json-maglev- 1.5.4 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/CHANGES +11 -1
  2. data/Rakefile +14 -12
  3. data/VERSION +1 -1
  4. data/ext/json/ext/generator/extconf.rb +0 -7
  5. data/ext/json/ext/generator/generator.c +55 -10
  6. data/ext/json/ext/generator/generator.h +7 -5
  7. data/ext/json/ext/parser/extconf.rb +0 -3
  8. data/ext/json/ext/parser/parser.c +418 -207
  9. data/ext/json/ext/parser/parser.h +11 -10
  10. data/ext/json/ext/parser/parser.rl +178 -104
  11. data/install.rb +1 -8
  12. data/java/src/json/ext/Generator.java +3 -3
  13. data/java/src/json/ext/GeneratorMethods.java +2 -2
  14. data/java/src/json/ext/GeneratorService.java +1 -1
  15. data/java/src/json/ext/GeneratorState.java +41 -13
  16. data/java/src/json/ext/OptionsReader.java +1 -1
  17. data/java/src/json/ext/Parser.java +382 -107
  18. data/java/src/json/ext/Parser.rl +97 -28
  19. data/java/src/json/ext/ParserService.java +1 -1
  20. data/java/src/json/ext/Utils.java +1 -1
  21. data/json.gemspec +5 -6
  22. data/json_pure.gemspec +5 -9
  23. data/lib/json.rb +4 -4
  24. data/lib/json/add/complex.rb +22 -0
  25. data/lib/json/add/core.rb +9 -241
  26. data/lib/json/add/date.rb +34 -0
  27. data/lib/json/add/date_time.rb +50 -0
  28. data/lib/json/add/exception.rb +31 -0
  29. data/lib/json/add/range.rb +29 -0
  30. data/lib/json/add/rational.rb +22 -0
  31. data/lib/json/add/regexp.rb +30 -0
  32. data/lib/json/add/struct.rb +30 -0
  33. data/lib/json/add/symbol.rb +25 -0
  34. data/lib/json/add/time.rb +35 -0
  35. data/lib/json/common.rb +47 -35
  36. data/lib/json/ext.rb +2 -15
  37. data/lib/json/pure/generator.rb +17 -2
  38. data/lib/json/pure/parser.rb +89 -55
  39. data/lib/json/version.rb +1 -1
  40. data/tests/test_json.rb +36 -0
  41. data/tests/test_json_addition.rb +8 -1
  42. data/tests/test_json_generate.rb +34 -1
  43. data/tools/server.rb +1 -0
  44. metadata +20 -24
  45. data/bin/edit_json.rb +0 -9
  46. data/bin/prettify_json.rb +0 -48
  47. data/lib/json/Array.xpm +0 -21
  48. data/lib/json/FalseClass.xpm +0 -21
  49. data/lib/json/Hash.xpm +0 -21
  50. data/lib/json/Key.xpm +0 -73
  51. data/lib/json/NilClass.xpm +0 -21
  52. data/lib/json/Numeric.xpm +0 -28
  53. data/lib/json/String.xpm +0 -96
  54. data/lib/json/TrueClass.xpm +0 -21
  55. data/lib/json/add/rails.rb +0 -8
  56. data/lib/json/editor.rb +0 -1369
  57. data/lib/json/json.xpm +0 -1499
@@ -3,7 +3,7 @@
3
3
 
4
4
  #include "ruby.h"
5
5
 
6
- #if HAVE_RE_H
6
+ #ifndef HAVE_RUBY_RE_H
7
7
  #include "re.h"
8
8
  #endif
9
9
 
@@ -36,15 +36,16 @@ typedef unsigned char UTF8; /* typically 8 bits */
36
36
  typedef struct JSON_ParserStruct {
37
37
  VALUE dwrapped_parser;
38
38
  VALUE Vsource;
39
- const char *source;
39
+ char *source;
40
40
  long len;
41
- const char *memo;
41
+ char *memo;
42
42
  VALUE create_id;
43
43
  int max_nesting;
44
44
  int current_nesting;
45
45
  int allow_nan;
46
46
  int parsing_name;
47
47
  int symbolize_names;
48
+ int quirks_mode;
48
49
  VALUE object_class;
49
50
  VALUE array_class;
50
51
  int create_additions;
@@ -63,13 +64,13 @@ typedef struct JSON_ParserStruct {
63
64
 
64
65
  static UTF32 unescape_unicode(const unsigned char *p);
65
66
  static int convert_UTF32_to_UTF8(char *buf, UTF32 ch);
66
- static const char *JSON_parse_object(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
67
- static const char *JSON_parse_value(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
68
- static const char *JSON_parse_integer(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
69
- static const char *JSON_parse_float(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
70
- static const char *JSON_parse_array(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
71
- static VALUE json_string_unescape(VALUE result, const char *string, const char *stringEnd);
72
- static const char *JSON_parse_string(JSON_Parser *json, const char *p, const char *pe, VALUE *result);
67
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
68
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result);
69
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
70
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
71
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result);
72
+ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
73
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
73
74
  static VALUE convert_encoding(VALUE source);
74
75
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
75
76
  static VALUE cParser_parse(VALUE self);
@@ -76,8 +76,9 @@ static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
76
76
  static VALUE CNaN, CInfinity, CMinusInfinity;
77
77
 
78
78
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
79
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_object_class,
80
- i_array_class, i_key_p, i_deep_const_get, i_match, i_match_string, i_aset, i_leftshift;
79
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
80
+ i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
81
+ i_match_string, i_aset, i_leftshift;
81
82
 
82
83
  %%{
83
84
  machine JSON_common;
@@ -115,7 +116,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
115
116
 
116
117
  action parse_value {
117
118
  VALUE v = Qnil;
118
- const char *np = JSON_parse_value(json, fpc, pe, &v);
119
+ char *np = JSON_parse_value(json, fpc, pe, &v);
119
120
  if (np == NULL) {
120
121
  fhold; fbreak;
121
122
  } else {
@@ -129,7 +130,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
129
130
  }
130
131
 
131
132
  action parse_name {
132
- const char *np;
133
+ char *np;
133
134
  json->parsing_name = 1;
134
135
  np = JSON_parse_string(json, fpc, pe, &last_name);
135
136
  json->parsing_name = 0;
@@ -138,16 +139,17 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
138
139
 
139
140
  action exit { fhold; fbreak; }
140
141
 
141
- a_pair = ignore* begin_name >parse_name
142
- ignore* name_separator ignore*
143
- begin_value >parse_value;
142
+ pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value;
143
+ next_pair = ignore* value_separator pair;
144
144
 
145
- main := begin_object
146
- (a_pair (ignore* value_separator a_pair)*)?
147
- ignore* end_object @exit;
145
+ main := (
146
+ begin_object
147
+ (pair (next_pair)*)? ignore*
148
+ end_object
149
+ ) @exit;
148
150
  }%%
149
151
 
150
- static const char *JSON_parse_object(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
152
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
151
153
  {
152
154
  int cs = EVIL;
153
155
  VALUE last_name = Qnil;
@@ -178,6 +180,7 @@ static const char *JSON_parse_object(JSON_Parser *json, const char *p, const cha
178
180
  }
179
181
  }
180
182
 
183
+
181
184
  %%{
182
185
  machine JSON_value;
183
186
  include JSON_common;
@@ -208,13 +211,13 @@ static const char *JSON_parse_object(JSON_Parser *json, const char *p, const cha
208
211
  }
209
212
  }
210
213
  action parse_string {
211
- const char *np = JSON_parse_string(json, fpc, pe, result);
214
+ char *np = JSON_parse_string(json, fpc, pe, result);
212
215
  if (np == NULL) { fhold; fbreak; } else fexec np;
213
216
  }
214
217
 
215
218
  action parse_number {
216
- const char *np;
217
- if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
219
+ char *np;
220
+ if(pe > fpc + 9 - json->quirks_mode && !strncmp(MinusInfinity, fpc, 9)) {
218
221
  if (json->allow_nan) {
219
222
  *result = CMinusInfinity;
220
223
  fexec p + 10;
@@ -231,7 +234,7 @@ static const char *JSON_parse_object(JSON_Parser *json, const char *p, const cha
231
234
  }
232
235
 
233
236
  action parse_array {
234
- const char *np;
237
+ char *np;
235
238
  json->current_nesting++;
236
239
  np = JSON_parse_array(json, fpc, pe, result);
237
240
  json->current_nesting--;
@@ -239,7 +242,7 @@ static const char *JSON_parse_object(JSON_Parser *json, const char *p, const cha
239
242
  }
240
243
 
241
244
  action parse_object {
242
- const char *np;
245
+ char *np;
243
246
  json->current_nesting++;
244
247
  np = JSON_parse_object(json, fpc, pe, result);
245
248
  json->current_nesting--;
@@ -261,7 +264,7 @@ main := (
261
264
  ) %*exit;
262
265
  }%%
263
266
 
264
- static const char *JSON_parse_value(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
267
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
265
268
  {
266
269
  int cs = EVIL;
267
270
 
@@ -282,10 +285,10 @@ static const char *JSON_parse_value(JSON_Parser *json, const char *p, const char
282
285
 
283
286
  action exit { fhold; fbreak; }
284
287
 
285
- main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
288
+ main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit);
286
289
  }%%
287
290
 
288
- static const char *JSON_parse_integer(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
291
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
289
292
  {
290
293
  int cs = EVIL;
291
294
 
@@ -313,10 +316,10 @@ static const char *JSON_parse_integer(JSON_Parser *json, const char *p, const ch
313
316
  main := '-'? (
314
317
  (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
315
318
  | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
316
- ) (^[0-9Ee.\-] @exit );
319
+ ) (^[0-9Ee.\-]? @exit );
317
320
  }%%
318
321
 
319
- static const char *JSON_parse_float(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
322
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
320
323
  {
321
324
  int cs = EVIL;
322
325
 
@@ -342,7 +345,7 @@ static const char *JSON_parse_float(JSON_Parser *json, const char *p, const char
342
345
 
343
346
  action parse_value {
344
347
  VALUE v = Qnil;
345
- const char *np = JSON_parse_value(json, fpc, pe, &v);
348
+ char *np = JSON_parse_value(json, fpc, pe, &v);
346
349
  if (np == NULL) {
347
350
  fhold; fbreak;
348
351
  } else {
@@ -365,7 +368,7 @@ static const char *JSON_parse_float(JSON_Parser *json, const char *p, const char
365
368
  end_array @exit;
366
369
  }%%
367
370
 
368
- static const char *JSON_parse_array(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
371
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
369
372
  {
370
373
  int cs = EVIL;
371
374
  VALUE array_class = json->array_class;
@@ -386,9 +389,9 @@ static const char *JSON_parse_array(JSON_Parser *json, const char *p, const char
386
389
  }
387
390
  }
388
391
 
389
- static VALUE json_string_unescape(VALUE result, const char *string, const char *stringEnd)
392
+ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
390
393
  {
391
- const char *p = string, *pe = string, *unescape;
394
+ char *p = string, *pe = string, *unescape;
392
395
  int unescape_len;
393
396
 
394
397
  while (pe < stringEnd) {
@@ -490,17 +493,17 @@ match_i(VALUE regexp, VALUE klass, VALUE memo)
490
493
  return ST_CONTINUE;
491
494
  }
492
495
 
493
- static const char *JSON_parse_string(JSON_Parser *json, const char *p, const char *pe, VALUE *result)
496
+ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
494
497
  {
495
498
  int cs = EVIL;
499
+ VALUE match_string;
500
+
496
501
  *result = rb_str_buf_new(0);
497
502
  %% write init;
498
503
  json->memo = p;
499
504
  %% write exec;
500
505
 
501
- if (json->create_additions) {
502
- VALUE match_string = json->match_string;
503
- if (RTEST(match_string)) {
506
+ if (json->create_additions && RTEST(match_string = json->match_string)) {
504
507
  VALUE klass;
505
508
  VALUE memo = rb_ary_new2(2);
506
509
  rb_ary_push(memo, *result);
@@ -509,7 +512,6 @@ static const char *JSON_parse_string(JSON_Parser *json, const char *p, const cha
509
512
  if (RTEST(klass)) {
510
513
  *result = rb_funcall(klass, i_json_create, 1, *result);
511
514
  }
512
- }
513
515
  }
514
516
 
515
517
  if (json->symbolize_names && json->parsing_name) {
@@ -522,34 +524,6 @@ static const char *JSON_parse_string(JSON_Parser *json, const char *p, const cha
522
524
  }
523
525
  }
524
526
 
525
-
526
- %%{
527
- machine JSON;
528
-
529
- write data;
530
-
531
- include JSON_common;
532
-
533
- action parse_object {
534
- const char *np;
535
- json->current_nesting = 1;
536
- np = JSON_parse_object(json, fpc, pe, &result);
537
- if (np == NULL) { fhold; fbreak; } else fexec np;
538
- }
539
-
540
- action parse_array {
541
- const char *np;
542
- json->current_nesting = 1;
543
- np = JSON_parse_array(json, fpc, pe, &result);
544
- if (np == NULL) { fhold; fbreak; } else fexec np;
545
- }
546
-
547
- main := ignore* (
548
- begin_object >parse_object |
549
- begin_array >parse_array
550
- ) ignore*;
551
- }%%
552
-
553
527
  /*
554
528
  * Document-class: JSON::Ext::Parser
555
529
  *
@@ -564,7 +538,7 @@ static const char *JSON_parse_string(JSON_Parser *json, const char *p, const cha
564
538
 
565
539
  static VALUE convert_encoding(VALUE source)
566
540
  {
567
- const char *ptr = RSTRING_PTR(source);
541
+ char *ptr = RSTRING_PTR(source);
568
542
  long len = RSTRING_LEN(source);
569
543
  if (len < 2) {
570
544
  rb_raise(eParserError, "A JSON text must at least contain two octets!");
@@ -603,12 +577,15 @@ static VALUE convert_encoding(VALUE source)
603
577
  return source;
604
578
  }
605
579
 
606
- static inline void parser_iv_set(JSON_Parser *json, const char* iv_name, VALUE v)
607
- {
608
- // store reference to v in a Ruby instVar to keep v alive
609
- // without using a gc_mark function in Data_Wrap_Struct calls
610
- rb_iv_set(json->dwrapped_parser, iv_name, v);
611
- }
580
+ #if defined MAGLEV
581
+ // Maglev doesn't support the mark function, keep a reference in the object
582
+ #define QUOTE(x) #x
583
+ #define PARSER_SET_REFERENCE(json, field, val) \
584
+ (json)->field = (val); \
585
+ rb_iv_set(json->dwrapped_parser, QUOTE(@field), (json)->field);
586
+ #else
587
+ #define PARSER_SET_REFERENCE(json, field, val) (json)->field = (val);
588
+ #endif
612
589
 
613
590
  /*
614
591
  * call-seq: new(source, opts => {})
@@ -636,26 +613,15 @@ static inline void parser_iv_set(JSON_Parser *json, const char* iv_name, VALUE v
636
613
  * * *object_class*: Defaults to Hash
637
614
  * * *array_class*: Defaults to Array
638
615
  */
639
-
640
- static int init_count = 0;
641
616
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
642
617
  {
643
- const char *ptr;
644
- long len;
645
618
  VALUE source, opts;
646
-
647
619
  GET_PARSER_INIT;
648
- init_count += 1;
649
620
 
650
- #ifndef MAGLEV
651
- if (json->Vsource) {
621
+ if (RTEST(json->Vsource)) {
652
622
  rb_raise(rb_eTypeError, "already initialized instance");
653
623
  }
654
- #endif
655
624
  rb_scan_args(argc, argv, "11", &source, &opts);
656
- source = convert_encoding(StringValue(source));
657
- ptr = RSTRING_PTR(source);
658
- len = RSTRING_LEN(source);
659
625
  if (!NIL_P(opts)) {
660
626
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
661
627
  if (NIL_P(opts)) {
@@ -685,6 +651,13 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
685
651
  } else {
686
652
  json->symbolize_names = 0;
687
653
  }
654
+ tmp = ID2SYM(i_quirks_mode);
655
+ if (option_given_p(opts, tmp)) {
656
+ VALUE quirks_mode = rb_hash_aref(opts, tmp);
657
+ json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
658
+ } else {
659
+ json->quirks_mode = 0;
660
+ }
688
661
  tmp = ID2SYM(i_create_additions);
689
662
  if (option_given_p(opts, tmp)) {
690
663
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -693,52 +666,78 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
693
666
  }
694
667
  tmp = ID2SYM(i_create_id);
695
668
  if (option_given_p(opts, tmp)) {
696
- json->create_id = rb_hash_aref(opts, tmp);
669
+ PARSER_SET_REFERENCE(json, create_id, rb_hash_aref(opts, tmp));
697
670
  } else {
698
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
671
+ PARSER_SET_REFERENCE(json, create_id, rb_funcall(mJSON, i_create_id, 0));
699
672
  }
700
- parser_iv_set(json, "@create_id", json->create_id);
701
673
  tmp = ID2SYM(i_object_class);
702
674
  if (option_given_p(opts, tmp)) {
703
- json->object_class = rb_hash_aref(opts, tmp);
704
- parser_iv_set(json, "@object_class", json->object_class);
675
+ PARSER_SET_REFERENCE(json, object_class, rb_hash_aref(opts, tmp));
676
+ } else {
677
+ PARSER_SET_REFERENCE(json, object_class, Qnil);
705
678
  }
706
679
  tmp = ID2SYM(i_array_class);
707
680
  if (option_given_p(opts, tmp)) {
708
- json->array_class = rb_hash_aref(opts, tmp);
709
- parser_iv_set(json, "@array_class", json->array_class);
681
+ PARSER_SET_REFERENCE(json, array_class, rb_hash_aref(opts, tmp));
682
+ } else {
683
+ PARSER_SET_REFERENCE(json, array_class, Qnil);
710
684
  }
711
685
  tmp = ID2SYM(i_match_string);
712
686
  if (option_given_p(opts, tmp)) {
713
687
  VALUE match_string = rb_hash_aref(opts, tmp);
714
- json->match_string = RTEST(match_string) ? match_string : Qnil;
715
- parser_iv_set(json, "@match_string", json->match_string);
688
+ PARSER_SET_REFERENCE(json, match_string, RTEST(match_string) ? match_string : Qnil);
689
+ } else {
690
+ PARSER_SET_REFERENCE(json, match_string, Qnil);
716
691
  }
717
692
  }
718
693
  } else {
719
694
  json->max_nesting = 19;
720
695
  json->allow_nan = 0;
721
696
  json->create_additions = 1;
722
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
723
- parser_iv_set(json, "@create_id", json->create_id);
697
+ PARSER_SET_REFERENCE(json, create_id, rb_funcall(mJSON, i_create_id, 0));
698
+ json->object_class = Qnil;
699
+ json->array_class = Qnil;
700
+ }
701
+ if (!json->quirks_mode) {
702
+ source = convert_encoding(StringValue(source));
724
703
  }
725
704
  json->current_nesting = 0;
726
- json->len = len;
727
- json->source = ptr;
728
- json->Vsource = source;
729
- parser_iv_set(json, "@vsource", json->Vsource);
705
+ json->len = RSTRING_LEN(source);
706
+ json->source = RSTRING_PTR(source);;
707
+ PARSER_SET_REFERENCE(json, Vsource, source);
730
708
  return self;
731
709
  }
732
710
 
733
- /*
734
- * call-seq: parse()
735
- *
736
- * Parses the current JSON text _source_ and returns the complete data
737
- * structure as a result.
738
- */
739
- static VALUE cParser_parse(VALUE self)
711
+ %%{
712
+ machine JSON;
713
+
714
+ write data;
715
+
716
+ include JSON_common;
717
+
718
+ action parse_object {
719
+ char *np;
720
+ json->current_nesting = 1;
721
+ np = JSON_parse_object(json, fpc, pe, &result);
722
+ if (np == NULL) { fhold; fbreak; } else fexec np;
723
+ }
724
+
725
+ action parse_array {
726
+ char *np;
727
+ json->current_nesting = 1;
728
+ np = JSON_parse_array(json, fpc, pe, &result);
729
+ if (np == NULL) { fhold; fbreak; } else fexec np;
730
+ }
731
+
732
+ main := ignore* (
733
+ begin_object >parse_object |
734
+ begin_array >parse_array
735
+ ) ignore*;
736
+ }%%
737
+
738
+ static VALUE cParser_parse_strict(VALUE self)
740
739
  {
741
- const char *p, *pe;
740
+ char *p, *pe;
742
741
  int cs = EVIL;
743
742
  VALUE result = Qnil;
744
743
  GET_PARSER;
@@ -756,6 +755,62 @@ static VALUE cParser_parse(VALUE self)
756
755
  }
757
756
  }
758
757
 
758
+
759
+ %%{
760
+ machine JSON_quirks_mode;
761
+
762
+ write data;
763
+
764
+ include JSON_common;
765
+
766
+ action parse_value {
767
+ char *np = JSON_parse_value(json, fpc, pe, &result);
768
+ if (np == NULL) { fhold; fbreak; } else fexec np;
769
+ }
770
+
771
+ main := ignore* (
772
+ begin_value >parse_value
773
+ ) ignore*;
774
+ }%%
775
+
776
+ static VALUE cParser_parse_quirks_mode(VALUE self)
777
+ {
778
+ char *p, *pe;
779
+ int cs = EVIL;
780
+ VALUE result = Qnil;
781
+ GET_PARSER;
782
+
783
+ %% write init;
784
+ p = json->source;
785
+ pe = p + json->len;
786
+ %% write exec;
787
+
788
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
789
+ return result;
790
+ } else {
791
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
792
+ return Qnil;
793
+ }
794
+ }
795
+
796
+ /*
797
+ * call-seq: parse()
798
+ *
799
+ * Parses the current JSON text _source_ and returns the complete data
800
+ * structure as a result.
801
+ */
802
+ static VALUE cParser_parse(VALUE self)
803
+ {
804
+ GET_PARSER;
805
+
806
+ if (json->quirks_mode) {
807
+ return cParser_parse_quirks_mode(self);
808
+ } else {
809
+ return cParser_parse_strict(self);
810
+ }
811
+ }
812
+
813
+
759
814
  static JSON_Parser *JSON_allocate()
760
815
  {
761
816
  JSON_Parser *json = ALLOC(JSON_Parser);
@@ -770,7 +825,14 @@ static JSON_Parser *JSON_allocate()
770
825
  return json;
771
826
  }
772
827
 
773
- /* deleted JSON_mark function */
828
+ static void JSON_mark(JSON_Parser *json)
829
+ {
830
+ rb_gc_mark_maybe(json->Vsource);
831
+ rb_gc_mark_maybe(json->create_id);
832
+ rb_gc_mark_maybe(json->object_class);
833
+ rb_gc_mark_maybe(json->array_class);
834
+ rb_gc_mark_maybe(json->match_string);
835
+ }
774
836
 
775
837
  static void JSON_free(JSON_Parser *json)
776
838
  {
@@ -780,9 +842,7 @@ static void JSON_free(JSON_Parser *json)
780
842
  static VALUE cJSON_parser_s_allocate(VALUE klass)
781
843
  {
782
844
  JSON_Parser *json = JSON_allocate();
783
- VALUE data_obj = Data_Wrap_Struct(klass, NULL, JSON_free, json);
784
- json->dwrapped_parser = data_obj;
785
- return data_obj;
845
+ return json->dwrapped_parser = Data_Wrap_Struct(klass, JSON_mark, JSON_free, json);
786
846
  }
787
847
 
788
848
  /*
@@ -797,6 +857,18 @@ static VALUE cParser_source(VALUE self)
797
857
  return rb_str_dup(json->Vsource);
798
858
  }
799
859
 
860
+ /*
861
+ * call-seq: quirks_mode?()
862
+ *
863
+ * Returns a true, if this parser is in quirks_mode, false otherwise.
864
+ */
865
+ static VALUE cParser_quirks_mode_p(VALUE self)
866
+ {
867
+ GET_PARSER;
868
+ return json->quirks_mode ? Qtrue : Qfalse;
869
+ }
870
+
871
+
800
872
  void Init_parser()
801
873
  {
802
874
  rb_require("json/common");
@@ -809,6 +881,7 @@ void Init_parser()
809
881
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
810
882
  rb_define_method(cParser, "parse", cParser_parse, 0);
811
883
  rb_define_method(cParser, "source", cParser_source, 0);
884
+ rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
812
885
 
813
886
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
814
887
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -822,6 +895,7 @@ void Init_parser()
822
895
  i_max_nesting = rb_intern("max_nesting");
823
896
  i_allow_nan = rb_intern("allow_nan");
824
897
  i_symbolize_names = rb_intern("symbolize_names");
898
+ i_quirks_mode = rb_intern("quirks_mode");
825
899
  i_object_class = rb_intern("object_class");
826
900
  i_array_class = rb_intern("array_class");
827
901
  i_match = rb_intern("match");