json 1.8.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -10
  3. data/CHANGES +12 -0
  4. data/Gemfile +1 -2
  5. data/{README.rdoc → README.md} +145 -111
  6. data/Rakefile +26 -29
  7. data/VERSION +1 -1
  8. data/ext/json/ext/generator/generator.c +38 -55
  9. data/ext/json/ext/generator/generator.h +7 -1
  10. data/ext/json/ext/parser/extconf.rb +3 -0
  11. data/ext/json/ext/parser/parser.c +309 -439
  12. data/ext/json/ext/parser/parser.h +0 -1
  13. data/ext/json/ext/parser/parser.rl +67 -160
  14. data/ext/json/extconf.rb +0 -1
  15. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  16. data/java/src/json/ext/Generator.java +11 -12
  17. data/java/src/json/ext/GeneratorMethods.java +1 -2
  18. data/java/src/json/ext/GeneratorService.java +1 -2
  19. data/java/src/json/ext/GeneratorState.java +3 -56
  20. data/java/src/json/ext/OptionsReader.java +2 -3
  21. data/java/src/json/ext/Parser.java +110 -411
  22. data/java/src/json/ext/Parser.rl +25 -119
  23. data/java/src/json/ext/ParserService.java +1 -2
  24. data/java/src/json/ext/RuntimeInfo.java +1 -6
  25. data/java/src/json/ext/StringDecoder.java +1 -2
  26. data/java/src/json/ext/StringEncoder.java +5 -0
  27. data/java/src/json/ext/Utils.java +1 -2
  28. data/json-java.gemspec +15 -0
  29. data/json.gemspec +0 -0
  30. data/json_pure.gemspec +23 -26
  31. data/lib/json/add/bigdecimal.rb +1 -0
  32. data/lib/json/add/complex.rb +2 -1
  33. data/lib/json/add/core.rb +1 -0
  34. data/lib/json/add/date.rb +1 -1
  35. data/lib/json/add/date_time.rb +1 -1
  36. data/lib/json/add/exception.rb +1 -1
  37. data/lib/json/add/ostruct.rb +1 -1
  38. data/lib/json/add/range.rb +1 -1
  39. data/lib/json/add/rational.rb +1 -0
  40. data/lib/json/add/regexp.rb +1 -1
  41. data/lib/json/add/struct.rb +1 -1
  42. data/lib/json/add/symbol.rb +1 -1
  43. data/lib/json/add/time.rb +1 -1
  44. data/lib/json/common.rb +24 -52
  45. data/lib/json/ext.rb +0 -6
  46. data/lib/json/generic_object.rb +5 -4
  47. data/lib/json/pure/generator.rb +61 -125
  48. data/lib/json/pure/parser.rb +28 -80
  49. data/lib/json/pure.rb +2 -8
  50. data/lib/json/version.rb +2 -1
  51. data/lib/json.rb +1 -0
  52. data/references/rfc7159.txt +899 -0
  53. data/tests/fixtures/obsolete_fail1.json +1 -0
  54. data/tests/{test_json_addition.rb → json_addition_test.rb} +22 -25
  55. data/tests/json_common_interface_test.rb +126 -0
  56. data/tests/json_encoding_test.rb +105 -0
  57. data/tests/json_ext_parser_test.rb +15 -0
  58. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
  59. data/tests/{test_json_generate.rb → json_generator_test.rb} +76 -37
  60. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  61. data/tests/json_parser_test.rb +448 -0
  62. data/tests/json_string_matching_test.rb +38 -0
  63. data/tests/test_helper.rb +23 -0
  64. data/tools/diff.sh +18 -0
  65. data/tools/fuzz.rb +1 -9
  66. metadata +27 -42
  67. data/COPYING +0 -58
  68. data/COPYING-json-jruby +0 -57
  69. data/GPL +0 -340
  70. data/TODO +0 -1
  71. data/tests/fixtures/fail1.json +0 -1
  72. data/tests/setup_variant.rb +0 -11
  73. data/tests/test_json.rb +0 -553
  74. data/tests/test_json_encoding.rb +0 -65
  75. data/tests/test_json_string_matching.rb +0 -39
  76. data/tests/test_json_unicode.rb +0 -72
@@ -38,7 +38,6 @@ typedef struct JSON_ParserStruct {
38
38
  int allow_nan;
39
39
  int parsing_name;
40
40
  int symbolize_names;
41
- int quirks_mode;
42
41
  VALUE object_class;
43
42
  VALUE array_class;
44
43
  int create_additions;
@@ -1,6 +1,28 @@
1
1
  #include "../fbuffer/fbuffer.h"
2
2
  #include "parser.h"
3
3
 
4
+ #if defined HAVE_RUBY_ENCODING_H
5
+ # define EXC_ENCODING rb_utf8_encoding(),
6
+ # ifndef HAVE_RB_ENC_RAISE
7
+ static void
8
+ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
9
+ {
10
+ va_list args;
11
+ VALUE mesg;
12
+
13
+ va_start(args, fmt);
14
+ mesg = rb_enc_vsprintf(enc, fmt, args);
15
+ va_end(args);
16
+
17
+ rb_exc_raise(rb_exc_new3(exc, mesg));
18
+ }
19
+ # define rb_enc_raise enc_raise
20
+ # endif
21
+ #else
22
+ # define EXC_ENCODING /* nothing */
23
+ # define rb_enc_raise rb_raise
24
+ #endif
25
+
4
26
  /* unicode */
5
27
 
6
28
  static const char digit_values[256] = {
@@ -65,19 +87,11 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
65
87
  return len;
66
88
  }
67
89
 
68
- #ifdef HAVE_RUBY_ENCODING_H
69
- static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
70
- CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
71
- static ID i_encoding, i_encode;
72
- #else
73
- static ID i_iconv;
74
- #endif
75
-
76
90
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
77
91
  static VALUE CNaN, CInfinity, CMinusInfinity;
78
92
 
79
93
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
80
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
94
+ i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
81
95
  i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
82
96
  i_match_string, i_aset, i_aref, i_leftshift;
83
97
 
@@ -206,14 +220,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
206
220
  if (json->allow_nan) {
207
221
  *result = CNaN;
208
222
  } else {
209
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
223
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
210
224
  }
211
225
  }
212
226
  action parse_infinity {
213
227
  if (json->allow_nan) {
214
228
  *result = CInfinity;
215
229
  } else {
216
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
230
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
217
231
  }
218
232
  }
219
233
  action parse_string {
@@ -223,13 +237,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
223
237
 
224
238
  action parse_number {
225
239
  char *np;
226
- if(pe > fpc + 9 - json->quirks_mode && !strncmp(MinusInfinity, fpc, 9)) {
240
+ if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
227
241
  if (json->allow_nan) {
228
242
  *result = CMinusInfinity;
229
243
  fexec p + 10;
230
244
  fhold; fbreak;
231
245
  } else {
232
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
246
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
233
247
  }
234
248
  }
235
249
  np = JSON_parse_float(json, fpc, pe, result);
@@ -257,7 +271,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
257
271
 
258
272
  action exit { fhold; fbreak; }
259
273
 
260
- main := (
274
+ main := ignore* (
261
275
  Vnull @parse_null |
262
276
  Vfalse @parse_false |
263
277
  Vtrue @parse_true |
@@ -267,7 +281,7 @@ main := (
267
281
  begin_string >parse_string |
268
282
  begin_array >parse_array |
269
283
  begin_object >parse_object
270
- ) %*exit;
284
+ ) ignore* %*exit;
271
285
  }%%
272
286
 
273
287
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -396,7 +410,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
396
410
  if(cs >= JSON_array_first_final) {
397
411
  return p + 1;
398
412
  } else {
399
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
413
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
400
414
  return NULL;
401
415
  }
402
416
  }
@@ -528,6 +542,8 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
528
542
 
529
543
  if (json->symbolize_names && json->parsing_name) {
530
544
  *result = rb_str_intern(*result);
545
+ } else {
546
+ rb_str_resize(*result, RSTRING_LEN(*result));
531
547
  }
532
548
  if (cs >= JSON_string_first_final) {
533
549
  return p + 1;
@@ -550,41 +566,13 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
550
566
 
551
567
  static VALUE convert_encoding(VALUE source)
552
568
  {
553
- char *ptr = RSTRING_PTR(source);
554
- long len = RSTRING_LEN(source);
555
- if (len < 2) {
556
- rb_raise(eParserError, "A JSON text must at least contain two octets!");
557
- }
558
569
  #ifdef HAVE_RUBY_ENCODING_H
559
- {
560
- VALUE encoding = rb_funcall(source, i_encoding, 0);
561
- if (encoding == CEncoding_ASCII_8BIT) {
562
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
563
- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
564
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
565
- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
566
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
567
- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
568
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
569
- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
570
- } else {
571
- source = rb_str_dup(source);
572
- FORCE_UTF8(source);
573
- }
574
- } else {
575
- source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
576
- }
577
- }
578
- #else
579
- if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
580
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32be"), source);
581
- } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
582
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16be"), source);
583
- } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
584
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-32le"), source);
585
- } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
586
- source = rb_funcall(mJSON, i_iconv, 3, rb_str_new2("utf-8"), rb_str_new2("utf-16le"), source);
587
- }
570
+ rb_encoding *enc = rb_enc_get(source);
571
+ if (enc == rb_ascii8bit_encoding()) {
572
+ FORCE_UTF8(source);
573
+ } else {
574
+ source = rb_str_conv_enc(source, NULL, rb_utf8_encoding());
575
+ }
588
576
  #endif
589
577
  return source;
590
578
  }
@@ -607,8 +595,9 @@ static VALUE convert_encoding(VALUE source)
607
595
  * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
608
596
  * false.
609
597
  * * *symbolize_names*: If set to true, returns symbols for the names
610
- * (keys) in a JSON object. Otherwise strings are returned, which is also
611
- * the default.
598
+ * (keys) in a JSON object. Otherwise strings are returned, which is
599
+ * also the default. It's not possible to use this option in
600
+ * conjunction with the *create_additions* option.
612
601
  * * *create_additions*: If set to false, the Parser doesn't create
613
602
  * additions even if a matching class and create_id was found. This option
614
603
  * defaults to false.
@@ -623,12 +612,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
623
612
  if (json->Vsource) {
624
613
  rb_raise(rb_eTypeError, "already initialized instance");
625
614
  }
615
+ #ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
616
+ rb_scan_args(argc, argv, "1:", &source, &opts);
617
+ #else
626
618
  rb_scan_args(argc, argv, "11", &source, &opts);
619
+ #endif
627
620
  if (!NIL_P(opts)) {
621
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
628
622
  opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
629
623
  if (NIL_P(opts)) {
630
624
  rb_raise(rb_eArgError, "opts needs to be like a hash");
631
625
  } else {
626
+ #endif
632
627
  VALUE tmp = ID2SYM(i_max_nesting);
633
628
  if (option_given_p(opts, tmp)) {
634
629
  VALUE max_nesting = rb_hash_aref(opts, tmp);
@@ -653,19 +648,17 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
653
648
  } else {
654
649
  json->symbolize_names = 0;
655
650
  }
656
- tmp = ID2SYM(i_quirks_mode);
657
- if (option_given_p(opts, tmp)) {
658
- VALUE quirks_mode = rb_hash_aref(opts, tmp);
659
- json->quirks_mode = RTEST(quirks_mode) ? 1 : 0;
660
- } else {
661
- json->quirks_mode = 0;
662
- }
663
651
  tmp = ID2SYM(i_create_additions);
664
652
  if (option_given_p(opts, tmp)) {
665
653
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
666
654
  } else {
667
655
  json->create_additions = 0;
668
656
  }
657
+ if (json->symbolize_names && json->create_additions) {
658
+ rb_raise(rb_eArgError,
659
+ "options :symbolize_names and :create_additions cannot be "
660
+ " used in conjunction");
661
+ }
669
662
  tmp = ID2SYM(i_create_id);
670
663
  if (option_given_p(opts, tmp)) {
671
664
  json->create_id = rb_hash_aref(opts, tmp);
@@ -691,7 +684,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
691
684
  } else {
692
685
  json->match_string = Qnil;
693
686
  }
687
+ #ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
694
688
  }
689
+ #endif
695
690
  } else {
696
691
  json->max_nesting = 100;
697
692
  json->allow_nan = 0;
@@ -700,10 +695,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
700
695
  json->object_class = Qnil;
701
696
  json->array_class = Qnil;
702
697
  }
703
- source = rb_convert_type(source, T_STRING, "String", "to_str");
704
- if (!json->quirks_mode) {
705
- source = convert_encoding(StringValue(source));
706
- }
698
+ source = convert_encoding(StringValue(source));
707
699
  json->current_nesting = 0;
708
700
  StringValue(source);
709
701
  json->len = RSTRING_LEN(source);
@@ -719,54 +711,6 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
719
711
 
720
712
  include JSON_common;
721
713
 
722
- action parse_object {
723
- char *np;
724
- json->current_nesting = 1;
725
- np = JSON_parse_object(json, fpc, pe, &result);
726
- if (np == NULL) { fhold; fbreak; } else fexec np;
727
- }
728
-
729
- action parse_array {
730
- char *np;
731
- json->current_nesting = 1;
732
- np = JSON_parse_array(json, fpc, pe, &result);
733
- if (np == NULL) { fhold; fbreak; } else fexec np;
734
- }
735
-
736
- main := ignore* (
737
- begin_object >parse_object |
738
- begin_array >parse_array
739
- ) ignore*;
740
- }%%
741
-
742
- static VALUE cParser_parse_strict(VALUE self)
743
- {
744
- char *p, *pe;
745
- int cs = EVIL;
746
- VALUE result = Qnil;
747
- GET_PARSER;
748
-
749
- %% write init;
750
- p = json->source;
751
- pe = p + json->len;
752
- %% write exec;
753
-
754
- if (cs >= JSON_first_final && p == pe) {
755
- return result;
756
- } else {
757
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
758
- return Qnil;
759
- }
760
- }
761
-
762
-
763
- %%{
764
- machine JSON_quirks_mode;
765
-
766
- write data;
767
-
768
- include JSON_common;
769
-
770
714
  action parse_value {
771
715
  char *np = JSON_parse_value(json, fpc, pe, &result);
772
716
  if (np == NULL) { fhold; fbreak; } else fexec np;
@@ -777,26 +721,6 @@ static VALUE cParser_parse_strict(VALUE self)
777
721
  ) ignore*;
778
722
  }%%
779
723
 
780
- static VALUE cParser_parse_quirks_mode(VALUE self)
781
- {
782
- char *p, *pe;
783
- int cs = EVIL;
784
- VALUE result = Qnil;
785
- GET_PARSER;
786
-
787
- %% write init;
788
- p = json->source;
789
- pe = p + json->len;
790
- %% write exec;
791
-
792
- if (cs >= JSON_quirks_mode_first_final && p == pe) {
793
- return result;
794
- } else {
795
- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
796
- return Qnil;
797
- }
798
- }
799
-
800
724
  /*
801
725
  * call-seq: parse()
802
726
  *
@@ -805,12 +729,21 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
805
729
  */
806
730
  static VALUE cParser_parse(VALUE self)
807
731
  {
732
+ char *p, *pe;
733
+ int cs = EVIL;
734
+ VALUE result = Qnil;
808
735
  GET_PARSER;
809
736
 
810
- if (json->quirks_mode) {
811
- return cParser_parse_quirks_mode(self);
737
+ %% write init;
738
+ p = json->source;
739
+ pe = p + json->len;
740
+ %% write exec;
741
+
742
+ if (cs >= JSON_first_final && p == pe) {
743
+ return result;
812
744
  } else {
813
- return cParser_parse_strict(self);
745
+ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
746
+ return Qnil;
814
747
  }
815
748
  }
816
749
 
@@ -868,18 +801,6 @@ static VALUE cParser_source(VALUE self)
868
801
  return rb_str_dup(json->Vsource);
869
802
  }
870
803
 
871
- /*
872
- * call-seq: quirks_mode?()
873
- *
874
- * Returns a true, if this parser is in quirks_mode, false otherwise.
875
- */
876
- static VALUE cParser_quirks_mode_p(VALUE self)
877
- {
878
- GET_PARSER;
879
- return json->quirks_mode ? Qtrue : Qfalse;
880
- }
881
-
882
-
883
804
  void Init_parser(void)
884
805
  {
885
806
  rb_require("json/common");
@@ -892,7 +813,6 @@ void Init_parser(void)
892
813
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
893
814
  rb_define_method(cParser, "parse", cParser_parse, 0);
894
815
  rb_define_method(cParser, "source", cParser_source, 0);
895
- rb_define_method(cParser, "quirks_mode?", cParser_quirks_mode_p, 0);
896
816
 
897
817
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
898
818
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
@@ -906,7 +826,6 @@ void Init_parser(void)
906
826
  i_max_nesting = rb_intern("max_nesting");
907
827
  i_allow_nan = rb_intern("allow_nan");
908
828
  i_symbolize_names = rb_intern("symbolize_names");
909
- i_quirks_mode = rb_intern("quirks_mode");
910
829
  i_object_class = rb_intern("object_class");
911
830
  i_array_class = rb_intern("array_class");
912
831
  i_match = rb_intern("match");
@@ -916,18 +835,6 @@ void Init_parser(void)
916
835
  i_aset = rb_intern("[]=");
917
836
  i_aref = rb_intern("[]");
918
837
  i_leftshift = rb_intern("<<");
919
- #ifdef HAVE_RUBY_ENCODING_H
920
- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
921
- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
922
- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
923
- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
924
- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
925
- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
926
- i_encoding = rb_intern("encoding");
927
- i_encode = rb_intern("encode");
928
- #else
929
- i_iconv = rb_intern("iconv");
930
- #endif
931
838
  }
932
839
 
933
840
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  require 'mkmf'
2
2
  create_makefile('json')
3
-
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -173,9 +172,7 @@ public final class Generator {
173
172
  result = RubyString.newString(session.getRuntime(), buffer);
174
173
  ThreadContext context = session.getContext();
175
174
  RuntimeInfo info = session.getInfo();
176
- if (info.encodingsSupported()) {
177
- result.force_encoding(context, info.utf8.get());
178
- }
175
+ result.force_encoding(context, info.utf8.get());
179
176
  return result;
180
177
  }
181
178
 
@@ -382,8 +379,7 @@ public final class Generator {
382
379
  RuntimeInfo info = session.getInfo();
383
380
  RubyString src;
384
381
 
385
- if (info.encodingsSupported() &&
386
- object.encoding(session.getContext()) != info.utf8.get()) {
382
+ if (object.encoding(session.getContext()) != info.utf8.get()) {
387
383
  src = (RubyString)object.encode(session.getContext(),
388
384
  info.utf8.get());
389
385
  } else {
@@ -428,11 +424,14 @@ public final class Generator {
428
424
  new Handler<IRubyObject>() {
429
425
  @Override
430
426
  RubyString generateNew(Session session, IRubyObject object) {
431
- IRubyObject result =
432
- object.callMethod(session.getContext(), "to_json",
433
- new IRubyObject[] {session.getState()});
434
- if (result instanceof RubyString) return (RubyString)result;
435
- throw session.getRuntime().newTypeError("to_json must return a String");
427
+ if (object.respondsTo("to_json")) {
428
+ IRubyObject result = object.callMethod(session.getContext(), "to_json",
429
+ new IRubyObject[] {session.getState()});
430
+ if (result instanceof RubyString) return (RubyString)result;
431
+ throw session.getRuntime().newTypeError("to_json must return a String");
432
+ } else {
433
+ return OBJECT_HANDLER.generateNew(session, object);
434
+ }
436
435
  }
437
436
 
438
437
  @Override
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -208,45 +207,11 @@ public class GeneratorState extends RubyObject {
208
207
  @JRubyMethod
209
208
  public IRubyObject generate(ThreadContext context, IRubyObject obj) {
210
209
  RubyString result = Generator.generateJson(context, obj, this);
211
- if (!quirksMode && !objectOrArrayLiteral(result)) {
212
- throw Utils.newException(context, Utils.M_GENERATOR_ERROR,
213
- "only generation of JSON objects or arrays allowed");
214
- }
215
210
  RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
216
- if (info.encodingsSupported()) {
217
- result.force_encoding(context, info.utf8.get());
218
- }
211
+ result.force_encoding(context, info.utf8.get());
219
212
  return result;
220
213
  }
221
214
 
222
- /**
223
- * Ensures the given string is in the form "[...]" or "{...}", being
224
- * possibly surrounded by white space.
225
- * The string's encoding must be ASCII-compatible.
226
- * @param value
227
- * @return
228
- */
229
- private static boolean objectOrArrayLiteral(RubyString value) {
230
- ByteList bl = value.getByteList();
231
- int len = bl.length();
232
-
233
- for (int pos = 0; pos < len - 1; pos++) {
234
- int b = bl.get(pos);
235
- if (Character.isWhitespace(b)) continue;
236
-
237
- // match the opening brace
238
- switch (b) {
239
- case '[':
240
- return matchClosingBrace(bl, pos, len, ']');
241
- case '{':
242
- return matchClosingBrace(bl, pos, len, '}');
243
- default:
244
- return false;
245
- }
246
- }
247
- return false;
248
- }
249
-
250
215
  private static boolean matchClosingBrace(ByteList bl, int pos, int len,
251
216
  int brace) {
252
217
  for (int endPos = len - 1; endPos > pos; endPos--) {
@@ -399,17 +364,6 @@ public class GeneratorState extends RubyObject {
399
364
  return context.getRuntime().newBoolean(asciiOnly);
400
365
  }
401
366
 
402
- @JRubyMethod(name="quirks_mode")
403
- public RubyBoolean quirks_mode_get(ThreadContext context) {
404
- return context.getRuntime().newBoolean(quirksMode);
405
- }
406
-
407
- @JRubyMethod(name="quirks_mode=")
408
- public IRubyObject quirks_mode_set(IRubyObject quirks_mode) {
409
- quirksMode = quirks_mode.isTrue();
410
- return quirks_mode.getRuntime().newBoolean(quirksMode);
411
- }
412
-
413
367
  @JRubyMethod(name="buffer_initial_length")
414
368
  public RubyInteger buffer_initial_length_get(ThreadContext context) {
415
369
  return context.getRuntime().newFixnum(bufferInitialLength);
@@ -422,11 +376,6 @@ public class GeneratorState extends RubyObject {
422
376
  return buffer_initial_length;
423
377
  }
424
378
 
425
- @JRubyMethod(name="quirks_mode?")
426
- public RubyBoolean quirks_mode_p(ThreadContext context) {
427
- return context.getRuntime().newBoolean(quirksMode);
428
- }
429
-
430
379
  public int getDepth() {
431
380
  return depth;
432
381
  }
@@ -445,7 +394,7 @@ public class GeneratorState extends RubyObject {
445
394
  private ByteList prepareByteList(ThreadContext context, IRubyObject value) {
446
395
  RubyString str = value.convertToString();
447
396
  RuntimeInfo info = RuntimeInfo.forRuntime(context.getRuntime());
448
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
397
+ if (str.encoding(context) != info.utf8.get()) {
449
398
  str = (RubyString)str.encode(context, info.utf8.get());
450
399
  }
451
400
  return str.getByteList().dup();
@@ -481,7 +430,6 @@ public class GeneratorState extends RubyObject {
481
430
  maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING);
482
431
  allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN);
483
432
  asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY);
484
- quirksMode = opts.getBool("quirks_mode", DEFAULT_QUIRKS_MODE);
485
433
  bufferInitialLength = opts.getInt("buffer_initial_length", DEFAULT_BUFFER_INITIAL_LENGTH);
486
434
 
487
435
  depth = opts.getInt("depth", 0);
@@ -508,7 +456,6 @@ public class GeneratorState extends RubyObject {
508
456
  result.op_aset(context, runtime.newSymbol("array_nl"), array_nl_get(context));
509
457
  result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context));
510
458
  result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context));
511
- result.op_aset(context, runtime.newSymbol("quirks_mode"), quirks_mode_p(context));
512
459
  result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context));
513
460
  result.op_aset(context, runtime.newSymbol("depth"), depth_get(context));
514
461
  result.op_aset(context, runtime.newSymbol("buffer_initial_length"), buffer_initial_length_get(context));
@@ -1,8 +1,7 @@
1
1
  /*
2
2
  * This code is copyrighted work by Daniel Luz <dev at mernen dot com>.
3
3
  *
4
- * Distributed under the Ruby and GPLv2 licenses; see COPYING and GPL files
5
- * for details.
4
+ * Distributed under the Ruby license: https://www.ruby-lang.org/en/about/license.txt
6
5
  */
7
6
  package json.ext;
8
7
 
@@ -85,7 +84,7 @@ final class OptionsReader {
85
84
 
86
85
  RubyString str = value.convertToString();
87
86
  RuntimeInfo info = getRuntimeInfo();
88
- if (info.encodingsSupported() && str.encoding(context) != info.utf8.get()) {
87
+ if (str.encoding(context) != info.utf8.get()) {
89
88
  str = (RubyString)str.encode(context, info.utf8.get());
90
89
  }
91
90
  return str;