json_pure 1.5.3 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,7 +9,7 @@
9
9
 
10
10
  #ifdef HAVE_RUBY_ENCODING_H
11
11
  #include "ruby/encoding.h"
12
- #define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
12
+ #define FORCE_UTF8(obj) ((obj) = rb_enc_associate(rb_str_dup(obj), rb_utf8_encoding()))
13
13
  #else
14
14
  #define FORCE_UTF8(obj)
15
15
  #endif
@@ -44,6 +44,7 @@ typedef struct JSON_ParserStruct {
44
44
  int allow_nan;
45
45
  int parsing_name;
46
46
  int symbolize_names;
47
+ int quirks_mode;
47
48
  VALUE object_class;
48
49
  VALUE array_class;
49
50
  int create_additions;
@@ -51,6 +52,9 @@ typedef struct JSON_ParserStruct {
51
52
  } JSON_Parser;
52
53
 
53
54
  #define GET_PARSER \
55
+ GET_PARSER_INIT; \
56
+ if (!json->Vsource) rb_raise(rb_eTypeError, "uninitialized instance")
57
+ #define GET_PARSER_INIT \
54
58
  JSON_Parser *json; \
55
59
  Data_Get_Struct(self, JSON_Parser, json)
56
60
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  /* unicode */
4
4
 
5
- static const char digit_values[256] = {
5
+ static const char digit_values[256] = {
6
6
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
7
7
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
8
8
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -38,7 +38,7 @@ static UTF32 unescape_unicode(const unsigned char *p)
38
38
  return result;
39
39
  }
40
40
 
41
- static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
41
+ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
42
42
  {
43
43
  int len = 1;
44
44
  if (ch <= 0x7F) {
@@ -67,7 +67,7 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
67
67
  #ifdef HAVE_RUBY_ENCODING_H
68
68
  static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
69
69
  CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
70
- static ID i_encoding, i_encode, i_encode_bang, i_force_encoding;
70
+ static ID i_encoding, i_encode;
71
71
  #else
72
72
  static ID i_iconv;
73
73
  #endif
@@ -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;
@@ -97,7 +98,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
97
98
  VNaN = 'NaN';
98
99
  VInfinity = 'Infinity';
99
100
  VMinusInfinity = '-Infinity';
100
- begin_value = [nft"\-[{NI] | digit;
101
+ begin_value = [nft\"\-\[\{NI] | digit;
101
102
  begin_object = '{';
102
103
  end_object = '}';
103
104
  begin_array = '[';
@@ -115,14 +116,14 @@ 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
- 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 {
122
123
  if (NIL_P(json->object_class)) {
123
- rb_hash_aset(*result, last_name, v);
124
+ rb_hash_aset(*result, last_name, v);
124
125
  } else {
125
- rb_funcall(*result, i_aset, 2, last_name, v);
126
+ rb_funcall(*result, i_aset, 2, last_name, v);
126
127
  }
127
128
  fexec np;
128
129
  }
@@ -138,13 +139,14 @@ 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
152
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -178,6 +180,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
178
180
  }
179
181
  }
180
182
 
183
+
181
184
  %%{
182
185
  machine JSON_value;
183
186
  include JSON_common;
@@ -214,7 +217,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
214
217
 
215
218
  action parse_number {
216
219
  char *np;
217
- if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
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;
@@ -230,7 +233,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
230
233
  fhold; fbreak;
231
234
  }
232
235
 
233
- action parse_array {
236
+ action parse_array {
234
237
  char *np;
235
238
  json->current_nesting++;
236
239
  np = JSON_parse_array(json, fpc, pe, result);
@@ -238,7 +241,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
238
241
  if (np == NULL) { fhold; fbreak; } else fexec np;
239
242
  }
240
243
 
241
- action parse_object {
244
+ action parse_object {
242
245
  char *np;
243
246
  json->current_nesting++;
244
247
  np = JSON_parse_object(json, fpc, pe, result);
@@ -282,7 +285,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
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
291
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -313,7 +316,7 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
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
322
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -342,7 +345,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
342
345
 
343
346
  action parse_value {
344
347
  VALUE v = Qnil;
345
- 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 {
@@ -419,7 +422,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
419
422
  unescape = (char *) "\f";
420
423
  break;
421
424
  case 'u':
422
- if (pe > stringEnd - 4) {
425
+ if (pe > stringEnd - 4) {
423
426
  return Qnil;
424
427
  } else {
425
428
  char buf[4];
@@ -475,7 +478,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
475
478
 
476
479
  action exit { fhold; fbreak; }
477
480
 
478
- main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
481
+ main := '"' ((^([\"\\] | 0..0x1f) | '\\'[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^([\"\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
479
482
  }%%
480
483
 
481
484
  static int
@@ -521,35 +524,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
521
524
  }
522
525
  }
523
526
 
524
-
525
- %%{
526
- machine JSON;
527
-
528
- write data;
529
-
530
- include JSON_common;
531
-
532
- action parse_object {
533
- char *np;
534
- json->current_nesting = 1;
535
- np = JSON_parse_object(json, fpc, pe, &result);
536
- if (np == NULL) { fhold; fbreak; } else fexec np;
537
- }
538
-
539
- action parse_array {
540
- char *np;
541
- json->current_nesting = 1;
542
- np = JSON_parse_array(json, fpc, pe, &result);
543
- if (np == NULL) { fhold; fbreak; } else fexec np;
544
- }
545
-
546
- main := ignore* (
547
- begin_object >parse_object |
548
- begin_array >parse_array
549
- ) ignore*;
550
- }%%
551
-
552
- /*
527
+ /*
553
528
  * Document-class: JSON::Ext::Parser
554
529
  *
555
530
  * This is the JSON parser implemented as a C extension. It can be configured
@@ -573,22 +548,15 @@ static VALUE convert_encoding(VALUE source)
573
548
  VALUE encoding = rb_funcall(source, i_encoding, 0);
574
549
  if (encoding == CEncoding_ASCII_8BIT) {
575
550
  if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
576
- source = rb_str_dup(source);
577
- rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32BE);
578
- source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
551
+ source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
579
552
  } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
580
- source = rb_str_dup(source);
581
- rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16BE);
582
- source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
553
+ source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
583
554
  } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
584
- source = rb_str_dup(source);
585
- rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_32LE);
586
- source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
555
+ source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
587
556
  } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
588
- source = rb_str_dup(source);
589
- rb_funcall(source, i_force_encoding, 1, CEncoding_UTF_16LE);
590
- source = rb_funcall(source, i_encode_bang, 1, CEncoding_UTF_8);
557
+ source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
591
558
  } else {
559
+ source = rb_str_dup(source);
592
560
  FORCE_UTF8(source);
593
561
  }
594
562
  } else {
@@ -637,14 +605,13 @@ static VALUE convert_encoding(VALUE source)
637
605
  */
638
606
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
639
607
  {
640
- char *ptr;
641
- long len;
642
608
  VALUE source, opts;
643
- GET_PARSER;
609
+ GET_PARSER_INIT;
610
+
611
+ if (json->Vsource) {
612
+ rb_raise(rb_eTypeError, "already initialized instance");
613
+ }
644
614
  rb_scan_args(argc, argv, "11", &source, &opts);
645
- source = convert_encoding(StringValue(source));
646
- ptr = RSTRING_PTR(source);
647
- len = RSTRING_LEN(source);
648
615
  if (!NIL_P(opts)) {
649
616
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
650
617
  if (NIL_P(opts)) {
@@ -674,6 +641,13 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
674
641
  } else {
675
642
  json->symbolize_names = 0;
676
643
  }
644
+ tmp = ID2SYM(i_quirks_mode);
645
+ if (option_given_p(opts, tmp)) {
646
+ VALUE quirks_mode = rb_hash_aref(opts, tmp);
647
+ json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
648
+ } else {
649
+ json->quirks_mode = 0;
650
+ }
677
651
  tmp = ID2SYM(i_create_additions);
678
652
  if (option_given_p(opts, tmp)) {
679
653
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -714,20 +688,44 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
714
688
  json->object_class = Qnil;
715
689
  json->array_class = Qnil;
716
690
  }
691
+ if (!json->quirks_mode) {
692
+ source = convert_encoding(StringValue(source));
693
+ }
717
694
  json->current_nesting = 0;
718
- json->len = len;
719
- json->source = ptr;
695
+ json->len = RSTRING_LEN(source);
696
+ json->source = RSTRING_PTR(source);;
720
697
  json->Vsource = source;
721
698
  return self;
722
699
  }
723
700
 
724
- /*
725
- * call-seq: parse()
726
- *
727
- * Parses the current JSON text _source_ and returns the complete data
728
- * structure as a result.
729
- */
730
- static VALUE cParser_parse(VALUE self)
701
+ %%{
702
+ machine JSON;
703
+
704
+ write data;
705
+
706
+ include JSON_common;
707
+
708
+ action parse_object {
709
+ char *np;
710
+ json->current_nesting = 1;
711
+ np = JSON_parse_object(json, fpc, pe, &result);
712
+ if (np == NULL) { fhold; fbreak; } else fexec np;
713
+ }
714
+
715
+ action parse_array {
716
+ char *np;
717
+ json->current_nesting = 1;
718
+ np = JSON_parse_array(json, fpc, pe, &result);
719
+ if (np == NULL) { fhold; fbreak; } else fexec np;
720
+ }
721
+
722
+ main := ignore* (
723
+ begin_object >parse_object |
724
+ begin_array >parse_array
725
+ ) ignore*;
726
+ }%%
727
+
728
+ static VALUE cParser_parse_strict(VALUE self)
731
729
  {
732
730
  char *p, *pe;
733
731
  int cs = EVIL;
@@ -747,6 +745,62 @@ static VALUE cParser_parse(VALUE self)
747
745
  }
748
746
  }
749
747
 
748
+
749
+ %%{
750
+ machine JSON_quirks_mode;
751
+
752
+ write data;
753
+
754
+ include JSON_common;
755
+
756
+ action parse_value {
757
+ char *np = JSON_parse_value(json, fpc, pe, &result);
758
+ if (np == NULL) { fhold; fbreak; } else fexec np;
759
+ }
760
+
761
+ main := ignore* (
762
+ begin_value >parse_value
763
+ ) ignore*;
764
+ }%%
765
+
766
+ static VALUE cParser_parse_quirks_mode(VALUE self)
767
+ {
768
+ char *p, *pe;
769
+ int cs = EVIL;
770
+ VALUE result = Qnil;
771
+ GET_PARSER;
772
+
773
+ %% write init;
774
+ p = json->source;
775
+ pe = p + json->len;
776
+ %% write exec;
777
+
778
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
779
+ return result;
780
+ } else {
781
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
782
+ return Qnil;
783
+ }
784
+ }
785
+
786
+ /*
787
+ * call-seq: parse()
788
+ *
789
+ * Parses the current JSON text _source_ and returns the complete data
790
+ * structure as a result.
791
+ */
792
+ static VALUE cParser_parse(VALUE self)
793
+ {
794
+ GET_PARSER;
795
+
796
+ if (json->quirks_mode) {
797
+ return cParser_parse_quirks_mode(self);
798
+ } else {
799
+ return cParser_parse_strict(self);
800
+ }
801
+ }
802
+
803
+
750
804
  static JSON_Parser *JSON_allocate()
751
805
  {
752
806
  JSON_Parser *json = ALLOC(JSON_Parser);
@@ -786,6 +840,18 @@ static VALUE cParser_source(VALUE self)
786
840
  return rb_str_dup(json->Vsource);
787
841
  }
788
842
 
843
+ /*
844
+ * call-seq: quirks_mode?()
845
+ *
846
+ * Returns a true, if this parser is in quirks_mode, false otherwise.
847
+ */
848
+ static VALUE cParser_quirks_mode_p(VALUE self)
849
+ {
850
+ GET_PARSER;
851
+ return json->quirks_mode ? Qtrue : Qfalse;
852
+ }
853
+
854
+
789
855
  void Init_parser()
790
856
  {
791
857
  rb_require("json/common");
@@ -798,6 +864,7 @@ void Init_parser()
798
864
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
799
865
  rb_define_method(cParser, "parse", cParser_parse, 0);
800
866
  rb_define_method(cParser, "source", cParser_source, 0);
867
+ rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
801
868
 
802
869
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
803
870
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -811,6 +878,7 @@ void Init_parser()
811
878
  i_max_nesting = rb_intern("max_nesting");
812
879
  i_allow_nan = rb_intern("allow_nan");
813
880
  i_symbolize_names = rb_intern("symbolize_names");
881
+ i_quirks_mode = rb_intern("quirks_mode");
814
882
  i_object_class = rb_intern("object_class");
815
883
  i_array_class = rb_intern("array_class");
816
884
  i_match = rb_intern("match");
@@ -828,9 +896,15 @@ void Init_parser()
828
896
  CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
829
897
  i_encoding = rb_intern("encoding");
830
898
  i_encode = rb_intern("encode");
831
- i_encode_bang = rb_intern("encode!");
832
- i_force_encoding = rb_intern("force_encoding");
833
899
  #else
834
900
  i_iconv = rb_intern("iconv");
835
901
  #endif
836
902
  }
903
+
904
+ /*
905
+ * Local variables:
906
+ * mode: c
907
+ * c-file-style: ruby
908
+ * indent-tabs-mode: nil
909
+ * End:
910
+ */
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
- *
3
+ *
4
4
  * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
5
  * for details.
6
6
  */
@@ -85,11 +85,11 @@ public final class Generator {
85
85
  /**
86
86
  * A class that concentrates all the information that is shared by
87
87
  * generators working on a single session.
88
- *
88
+ *
89
89
  * <p>A session is defined as the process of serializing a single root
90
90
  * object; any handler directly called by container handlers (arrays and
91
91
  * hashes/objects) shares this object with its caller.
92
- *
92
+ *
93
93
  * <p>Note that anything called indirectly (via {@link GENERIC_HANDLER})
94
94
  * won't be part of the session.
95
95
  */
@@ -376,9 +376,9 @@ public final class Generator {
376
376
  RubyString src;
377
377
 
378
378
  if (info.encodingsSupported() &&
379
- object.encoding(session.getContext()) != info.utf8) {
379
+ object.encoding(session.getContext()) != info.utf8.get()) {
380
380
  src = (RubyString)object.encode(session.getContext(),
381
- info.utf8);
381
+ info.utf8.get());
382
382
  } else {
383
383
  src = object;
384
384
  }