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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -10
- data/CHANGES +12 -0
- data/Gemfile +1 -2
- data/{README.rdoc → README.md} +145 -111
- data/Rakefile +26 -29
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +38 -55
- data/ext/json/ext/generator/generator.h +7 -1
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +309 -439
- data/ext/json/ext/parser/parser.h +0 -1
- data/ext/json/ext/parser/parser.rl +67 -160
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +11 -12
- data/java/src/json/ext/GeneratorMethods.java +1 -2
- data/java/src/json/ext/GeneratorService.java +1 -2
- data/java/src/json/ext/GeneratorState.java +3 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +110 -411
- data/java/src/json/ext/Parser.rl +25 -119
- data/java/src/json/ext/ParserService.java +1 -2
- data/java/src/json/ext/RuntimeInfo.java +1 -6
- data/java/src/json/ext/StringDecoder.java +1 -2
- data/java/src/json/ext/StringEncoder.java +5 -0
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +15 -0
- data/json.gemspec +0 -0
- data/json_pure.gemspec +23 -26
- data/lib/json/add/bigdecimal.rb +1 -0
- data/lib/json/add/complex.rb +2 -1
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +1 -1
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +1 -0
- data/lib/json/add/regexp.rb +1 -1
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +24 -52
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +61 -125
- data/lib/json/pure/parser.rb +28 -80
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +1 -0
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +22 -25
- data/tests/json_common_interface_test.rb +126 -0
- data/tests/json_encoding_test.rb +105 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +76 -37
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +448 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/test_helper.rb +23 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +27 -42
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- data/GPL +0 -340
- data/TODO +0 -1
- data/tests/fixtures/fail1.json +0 -1
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
@@ -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,
|
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
|
-
|
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
|
-
|
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 +
|
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
|
-
|
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
|
-
|
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
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
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
|
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 =
|
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
|
-
|
811
|
-
|
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
|
-
|
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,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
|
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
|
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
|
-
|
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.
|
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
|
-
|
432
|
-
object.callMethod(session.getContext(), "to_json",
|
433
|
-
|
434
|
-
|
435
|
-
|
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
|
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
|
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
|
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
|
-
|
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 (
|
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
|
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 (
|
87
|
+
if (str.encoding(context) != info.utf8.get()) {
|
89
88
|
str = (RubyString)str.encode(context, info.utf8.get());
|
90
89
|
}
|
91
90
|
return str;
|