json 1.4.3 → 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- data/CHANGES +4 -0
- data/README +5 -7
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/ext/json/ext/generator/extconf.rb +6 -2
- data/ext/json/ext/generator/generator.c +194 -156
- data/ext/json/ext/generator/generator.h +25 -1
- data/lib/json/pure/parser.rb +9 -8
- data/lib/json/version.rb +1 -1
- data/tests/test_json.rb +39 -6
- data/tests/test_json_addition.rb +6 -6
- metadata +17 -5
data/CHANGES
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
2010-08-06 (1.4.4)
|
2
|
+
* Fixes build problem for rubinius under OS X, http://github.com/flori/json/issues/closed#issue/25
|
3
|
+
* Fixes crashes described in http://github.com/flori/json/issues/closed#issue/21 and
|
4
|
+
http://github.com/flori/json/issues/closed#issue/23
|
1
5
|
2010-05-05 (1.4.3)
|
2
6
|
* Fixed some test assertions, from Ruby r27587 and r27590, patch by nobu.
|
3
7
|
* Fixed issue http://github.com/flori/json/issues/#issue/20 reported by
|
data/README
CHANGED
@@ -11,13 +11,11 @@ will be two variants available:
|
|
11
11
|
generated by the ragel state machine compiler
|
12
12
|
http://www.cs.queensu.ca/~thurston/ragel .
|
13
13
|
|
14
|
-
Both variants of the JSON generator
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
that don't expect UTF-8 encoded texts. On the negative side this may lead to a
|
20
|
-
bit longer strings than necessarry.
|
14
|
+
Both variants of the JSON generator generate UTF-8 character sequences by
|
15
|
+
default. If an :ascii_only option with a true value is given, they escape all
|
16
|
+
non-ASCII and control characters with \uXXXX escape sequences, and support
|
17
|
+
UTF-16 surrogate pairs in order to be able to generate the whole range of
|
18
|
+
unicode code points.
|
21
19
|
|
22
20
|
All strings, that are to be encoded as JSON strings, should be UTF-8 byte
|
23
21
|
sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
|
data/Rakefile
CHANGED
@@ -174,7 +174,7 @@ task :benchmark => [ :benchmark_parser, :benchmark_generator ]
|
|
174
174
|
|
175
175
|
desc "Create RDOC documentation"
|
176
176
|
task :doc => [ :version, EXT_PARSER_SRC ] do
|
177
|
-
sh "
|
177
|
+
sh "sdoc -o doc -t '#{PKG_TITLE}' -m README README lib/json.rb #{FileList['lib/json/**/*.rb']} #{EXT_PARSER_SRC} #{EXT_GENERATOR_SRC}"
|
178
178
|
end
|
179
179
|
|
180
180
|
if defined?(Gem) and defined?(Rake::GemPackageTask)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.4
|
@@ -11,6 +11,10 @@ if CONFIG['CC'] =~ /gcc/
|
|
11
11
|
#end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
have_header("
|
14
|
+
if RUBY_VERSION < "1.9"
|
15
|
+
have_header("re.h")
|
16
|
+
else
|
17
|
+
have_header("ruby/re.h")
|
18
|
+
have_header("ruby/encoding.h")
|
19
|
+
end
|
16
20
|
create_makefile 'json/ext/generator'
|
@@ -6,14 +6,15 @@ static ID i_encoding, i_encode;
|
|
6
6
|
#endif
|
7
7
|
|
8
8
|
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
9
|
-
mHash, mArray,
|
9
|
+
mHash, mArray, mFixnum, mBignum, mFloat, mString, mString_Extend,
|
10
10
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
11
|
-
eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE
|
11
|
+
eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
|
12
|
+
i_SAFE_STATE_PROTOTYPE;
|
12
13
|
|
13
14
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
14
15
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
15
16
|
i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
|
16
|
-
i_respond_to_p, i_match;
|
17
|
+
i_respond_to_p, i_match, i_keys;
|
17
18
|
|
18
19
|
/*
|
19
20
|
* Copyright 2001-2004 Unicode, Inc.
|
@@ -339,7 +340,7 @@ static void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
|
|
339
340
|
for (required = fb->capa; requested > required - fb->len; required <<= 1);
|
340
341
|
|
341
342
|
if (required > fb->capa) {
|
342
|
-
|
343
|
+
REALLOC_N(fb->ptr, char, required);
|
343
344
|
fb->capa = required;
|
344
345
|
}
|
345
346
|
}
|
@@ -426,11 +427,7 @@ static FBuffer *fbuffer_dup(FBuffer *fb)
|
|
426
427
|
*/
|
427
428
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
428
429
|
{
|
429
|
-
|
430
|
-
|
431
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
432
|
-
state = cState_from_state_s(cState, state);
|
433
|
-
return cState_partial_generate(state, self, depth);
|
430
|
+
GENERATE_JSON(object);
|
434
431
|
}
|
435
432
|
|
436
433
|
/*
|
@@ -443,10 +440,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
443
440
|
* _depth_ is used to find out nesting depth, to indent accordingly.
|
444
441
|
*/
|
445
442
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
446
|
-
|
447
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
448
|
-
state = cState_from_state_s(cState, state);
|
449
|
-
return cState_partial_generate(state, self, depth);
|
443
|
+
GENERATE_JSON(array);
|
450
444
|
}
|
451
445
|
|
452
446
|
/*
|
@@ -454,12 +448,19 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
454
448
|
*
|
455
449
|
* Returns a JSON string representation for this Integer number.
|
456
450
|
*/
|
457
|
-
static VALUE
|
451
|
+
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
|
458
452
|
{
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
453
|
+
GENERATE_JSON(fixnum);
|
454
|
+
}
|
455
|
+
|
456
|
+
/*
|
457
|
+
* call-seq: to_json(*)
|
458
|
+
*
|
459
|
+
* Returns a JSON string representation for this Integer number.
|
460
|
+
*/
|
461
|
+
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
462
|
+
{
|
463
|
+
GENERATE_JSON(bignum);
|
463
464
|
}
|
464
465
|
|
465
466
|
/*
|
@@ -469,10 +470,7 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
469
470
|
*/
|
470
471
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
471
472
|
{
|
472
|
-
|
473
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
474
|
-
state = cState_from_state_s(cState, state);
|
475
|
-
return cState_partial_generate(state, self, depth);
|
473
|
+
GENERATE_JSON(float);
|
476
474
|
}
|
477
475
|
|
478
476
|
/*
|
@@ -494,10 +492,7 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
|
|
494
492
|
*/
|
495
493
|
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
496
494
|
{
|
497
|
-
|
498
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
499
|
-
state = cState_from_state_s(cState, state);
|
500
|
-
return cState_partial_generate(state, self, depth);
|
495
|
+
GENERATE_JSON(string);
|
501
496
|
}
|
502
497
|
|
503
498
|
/*
|
@@ -552,10 +547,7 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
|
|
552
547
|
*/
|
553
548
|
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
554
549
|
{
|
555
|
-
|
556
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
557
|
-
state = cState_from_state_s(cState, state);
|
558
|
-
return cState_partial_generate(state, self, depth);
|
550
|
+
GENERATE_JSON(true);
|
559
551
|
}
|
560
552
|
|
561
553
|
/*
|
@@ -565,10 +557,7 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
565
557
|
*/
|
566
558
|
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
567
559
|
{
|
568
|
-
|
569
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
570
|
-
state = cState_from_state_s(cState, state);
|
571
|
-
return cState_partial_generate(state, self, depth);
|
560
|
+
GENERATE_JSON(false);
|
572
561
|
}
|
573
562
|
|
574
563
|
/*
|
@@ -577,10 +566,7 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
577
566
|
*/
|
578
567
|
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
579
568
|
{
|
580
|
-
|
581
|
-
rb_scan_args(argc, argv, "02", &state, &depth);
|
582
|
-
state = cState_from_state_s(cState, state);
|
583
|
-
return cState_partial_generate(state, self, depth);
|
569
|
+
GENERATE_JSON(null);
|
584
570
|
}
|
585
571
|
|
586
572
|
/*
|
@@ -616,6 +602,7 @@ static void State_free(JSON_Generator_State *state)
|
|
616
602
|
static JSON_Generator_State *State_allocate()
|
617
603
|
{
|
618
604
|
JSON_Generator_State *state = ALLOC(JSON_Generator_State);
|
605
|
+
MEMZERO(state, JSON_Generator_State, 1);
|
619
606
|
return state;
|
620
607
|
}
|
621
608
|
|
@@ -735,127 +722,172 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
735
722
|
}
|
736
723
|
}
|
737
724
|
|
738
|
-
static void
|
725
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
739
726
|
{
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
depth
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
keys = rb_funcall(obj, rb_intern("keys"), 0);
|
761
|
-
for(i = 0; i < RARRAY_LEN(keys); i++) {
|
762
|
-
if (i > 0) fbuffer_append(buffer, delim, delim_len);
|
763
|
-
if (object_nl) {
|
764
|
-
fbuffer_append(buffer, object_nl, object_nl_len);
|
765
|
-
}
|
766
|
-
if (indent) {
|
767
|
-
for (j = 0; j < depth; j++) {
|
768
|
-
fbuffer_append(buffer, indent, indent_len);
|
769
|
-
}
|
770
|
-
}
|
771
|
-
key = rb_ary_entry(keys, i);
|
772
|
-
key_to_s = rb_funcall(key, i_to_s, 0);
|
773
|
-
Check_Type(key_to_s, T_STRING);
|
774
|
-
generate_json(buffer, Vstate, state, key_to_s, depth);
|
775
|
-
fbuffer_append(buffer, delim2, delim2_len);
|
776
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
|
777
|
-
}
|
778
|
-
depth--;
|
727
|
+
char *object_nl = state->object_nl;
|
728
|
+
long object_nl_len = state->object_nl_len;
|
729
|
+
char *indent = state->indent;
|
730
|
+
long indent_len = state->indent_len;
|
731
|
+
long max_nesting = state->max_nesting;
|
732
|
+
char *delim = FBUFFER_PTR(state->object_delim);
|
733
|
+
long delim_len = FBUFFER_LEN(state->object_delim);
|
734
|
+
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
735
|
+
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
736
|
+
int i, j;
|
737
|
+
VALUE key, key_to_s, keys;
|
738
|
+
depth++;
|
739
|
+
if (max_nesting != 0 && depth > max_nesting) {
|
740
|
+
fbuffer_free(buffer);
|
741
|
+
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
742
|
+
}
|
743
|
+
fbuffer_append_char(buffer, '{');
|
744
|
+
keys = rb_funcall(obj, i_keys, 0);
|
745
|
+
for(i = 0; i < RARRAY_LEN(keys); i++) {
|
746
|
+
if (i > 0) fbuffer_append(buffer, delim, delim_len);
|
779
747
|
if (object_nl) {
|
780
748
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
749
|
+
}
|
750
|
+
if (indent) {
|
751
|
+
for (j = 0; j < depth; j++) {
|
752
|
+
fbuffer_append(buffer, indent, indent_len);
|
785
753
|
}
|
786
754
|
}
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
755
|
+
key = rb_ary_entry(keys, i);
|
756
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
757
|
+
Check_Type(key_to_s, T_STRING);
|
758
|
+
generate_json(buffer, Vstate, state, key_to_s, depth);
|
759
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
760
|
+
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
|
761
|
+
}
|
762
|
+
depth--;
|
763
|
+
if (object_nl) {
|
764
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
765
|
+
if (indent) {
|
766
|
+
for (j = 0; j < depth; j++) {
|
767
|
+
fbuffer_append(buffer, indent, indent_len);
|
768
|
+
}
|
801
769
|
}
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
770
|
+
}
|
771
|
+
fbuffer_append_char(buffer, '}');
|
772
|
+
}
|
773
|
+
|
774
|
+
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
775
|
+
{
|
776
|
+
char *array_nl = state->array_nl;
|
777
|
+
long array_nl_len = state->array_nl_len;
|
778
|
+
char *indent = state->indent;
|
779
|
+
long indent_len = state->indent_len;
|
780
|
+
long max_nesting = state->max_nesting;
|
781
|
+
char *delim = FBUFFER_PTR(state->array_delim);
|
782
|
+
long delim_len = FBUFFER_LEN(state->array_delim);
|
783
|
+
int i, j;
|
784
|
+
depth++;
|
785
|
+
if (max_nesting != 0 && depth > max_nesting) {
|
786
|
+
fbuffer_free(buffer);
|
787
|
+
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
788
|
+
}
|
789
|
+
fbuffer_append_char(buffer, '[');
|
790
|
+
if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
|
791
|
+
for(i = 0; i < RARRAY_LEN(obj); i++) {
|
792
|
+
if (i > 0) fbuffer_append(buffer, delim, delim_len);
|
793
|
+
if (indent) {
|
794
|
+
for (j = 0; j < depth; j++) {
|
795
|
+
fbuffer_append(buffer, indent, indent_len);
|
810
796
|
}
|
811
|
-
generate_json(buffer, Vstate, state, rb_ary_entry(obj, i), depth);
|
812
797
|
}
|
813
|
-
depth
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
798
|
+
generate_json(buffer, Vstate, state, rb_ary_entry(obj, i), depth);
|
799
|
+
}
|
800
|
+
depth--;
|
801
|
+
if (array_nl) {
|
802
|
+
fbuffer_append(buffer, array_nl, array_nl_len);
|
803
|
+
if (indent) {
|
804
|
+
for (j = 0; j < depth; j++) {
|
805
|
+
fbuffer_append(buffer, indent, indent_len);
|
820
806
|
}
|
821
807
|
}
|
822
|
-
|
823
|
-
|
824
|
-
|
808
|
+
}
|
809
|
+
fbuffer_append_char(buffer, ']');
|
810
|
+
}
|
811
|
+
|
812
|
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
813
|
+
{
|
814
|
+
fbuffer_append_char(buffer, '"');
|
825
815
|
#ifdef HAVE_RUBY_ENCODING_H
|
826
|
-
|
816
|
+
obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
|
827
817
|
#endif
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
818
|
+
if (state->ascii_only) {
|
819
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
820
|
+
} else {
|
821
|
+
convert_UTF8_to_JSON(buffer, obj);
|
822
|
+
}
|
823
|
+
fbuffer_append_char(buffer, '"');
|
824
|
+
}
|
825
|
+
|
826
|
+
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
827
|
+
{
|
828
|
+
fbuffer_append(buffer, "null", 4);
|
829
|
+
}
|
830
|
+
|
831
|
+
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
832
|
+
{
|
833
|
+
fbuffer_append(buffer, "false", 5);
|
834
|
+
}
|
835
|
+
|
836
|
+
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
837
|
+
{
|
838
|
+
fbuffer_append(buffer, "true", 4);
|
839
|
+
}
|
840
|
+
|
841
|
+
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
842
|
+
{
|
843
|
+
fbuffer_append_long(buffer, FIX2LONG(obj));
|
844
|
+
}
|
845
|
+
|
846
|
+
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
847
|
+
{
|
848
|
+
VALUE tmp = rb_funcall(obj, i_to_s, 0);
|
849
|
+
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
850
|
+
}
|
851
|
+
|
852
|
+
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
853
|
+
{
|
854
|
+
double value = RFLOAT_VALUE(obj);
|
855
|
+
char allow_nan = state->allow_nan;
|
856
|
+
VALUE tmp = rb_funcall(obj, i_to_s, 0);
|
857
|
+
if (!allow_nan) {
|
858
|
+
if (isinf(value)) {
|
859
|
+
fbuffer_free(buffer);
|
860
|
+
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
861
|
+
} else if (isnan(value)) {
|
862
|
+
fbuffer_free(buffer);
|
863
|
+
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
832
864
|
}
|
833
|
-
|
865
|
+
}
|
866
|
+
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
867
|
+
}
|
868
|
+
|
869
|
+
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
870
|
+
{
|
871
|
+
VALUE tmp;
|
872
|
+
VALUE klass = CLASS_OF(obj);
|
873
|
+
if (klass == rb_cHash) {
|
874
|
+
generate_json_object(buffer, Vstate, state, obj, depth);
|
875
|
+
} else if (klass == rb_cArray) {
|
876
|
+
generate_json_array(buffer, Vstate, state, obj, depth);
|
877
|
+
} else if (klass == rb_cString) {
|
878
|
+
generate_json_string(buffer, Vstate, state, obj, depth);
|
834
879
|
} else if (obj == Qnil) {
|
835
|
-
|
880
|
+
generate_json_null(buffer, Vstate, state, obj, depth);
|
836
881
|
} else if (obj == Qfalse) {
|
837
|
-
|
882
|
+
generate_json_false(buffer, Vstate, state, obj, depth);
|
838
883
|
} else if (obj == Qtrue) {
|
839
|
-
|
884
|
+
generate_json_true(buffer, Vstate, state, obj, depth);
|
840
885
|
} else if (klass == rb_cFixnum) {
|
841
|
-
|
886
|
+
generate_json_fixnum(buffer, Vstate, state, obj, depth);
|
842
887
|
} else if (klass == rb_cBignum) {
|
843
|
-
|
844
|
-
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
888
|
+
generate_json_bignum(buffer, Vstate, state, obj, depth);
|
845
889
|
} else if (klass == rb_cFloat) {
|
846
|
-
|
847
|
-
char allow_nan = state->allow_nan;
|
848
|
-
tmp = rb_funcall(obj, i_to_s, 0);
|
849
|
-
if (!allow_nan) {
|
850
|
-
if (isinf(value)) {
|
851
|
-
fbuffer_free(buffer);
|
852
|
-
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
853
|
-
} else if (isnan(value)) {
|
854
|
-
fbuffer_free(buffer);
|
855
|
-
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
856
|
-
}
|
857
|
-
}
|
858
|
-
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
890
|
+
generate_json_float(buffer, Vstate, state, obj, depth);
|
859
891
|
} else if (rb_respond_to(obj, i_to_json)) {
|
860
892
|
tmp = rb_funcall(obj, i_to_json, 2, Vstate, INT2FIX(depth + 1));
|
861
893
|
Check_Type(tmp, T_STRING);
|
@@ -867,15 +899,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
867
899
|
}
|
868
900
|
}
|
869
901
|
|
870
|
-
|
871
|
-
* call-seq: partial_generate(obj)
|
872
|
-
*
|
873
|
-
* Generates a part of a JSON document from object +obj+ and returns the
|
874
|
-
* result.
|
875
|
-
*/
|
876
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
|
902
|
+
static FBuffer *cState_prepare_buffer(VALUE self)
|
877
903
|
{
|
878
|
-
VALUE result;
|
879
904
|
FBuffer *buffer = fbuffer_alloc();
|
880
905
|
GET_STATE(self);
|
881
906
|
|
@@ -900,14 +925,25 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
|
|
900
925
|
}
|
901
926
|
fbuffer_append_char(state->array_delim, ',');
|
902
927
|
if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
|
928
|
+
return buffer;
|
929
|
+
}
|
903
930
|
|
904
|
-
|
905
|
-
|
906
|
-
|
931
|
+
static VALUE fbuffer_to_s(FBuffer *fb)
|
932
|
+
{
|
933
|
+
VALUE result = rb_str_new(FBUFFER_PAIR(fb));
|
934
|
+
fbuffer_free(fb);
|
907
935
|
FORCE_UTF8(result);
|
908
936
|
return result;
|
909
937
|
}
|
910
938
|
|
939
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
|
940
|
+
{
|
941
|
+
FBuffer *buffer = cState_prepare_buffer(self);
|
942
|
+
GET_STATE(self);
|
943
|
+
generate_json(buffer, self, state, obj, NIL_P(depth) ? 0 : FIX2INT(depth));
|
944
|
+
return fbuffer_to_s(buffer);
|
945
|
+
}
|
946
|
+
|
911
947
|
/*
|
912
948
|
* call-seq: generate(obj)
|
913
949
|
*
|
@@ -948,7 +984,6 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
948
984
|
{
|
949
985
|
VALUE opts;
|
950
986
|
GET_STATE(self);
|
951
|
-
MEMZERO(state, JSON_Generator_State, 1);
|
952
987
|
state->max_nesting = 19;
|
953
988
|
rb_scan_args(argc, argv, "01", &opts);
|
954
989
|
if (!NIL_P(opts)) cState_configure(self, opts);
|
@@ -996,7 +1031,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
996
1031
|
return rb_funcall(self, i_new, 1, opts);
|
997
1032
|
} else {
|
998
1033
|
if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
|
999
|
-
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON,
|
1034
|
+
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
1000
1035
|
}
|
1001
1036
|
return CJSON_SAFE_STATE_PROTOTYPE;
|
1002
1037
|
}
|
@@ -1266,7 +1301,6 @@ void Init_generator()
|
|
1266
1301
|
rb_define_method(cState, "to_h", cState_to_h, 0);
|
1267
1302
|
rb_define_method(cState, "[]", cState_aref, 1);
|
1268
1303
|
rb_define_method(cState, "generate", cState_generate, 1);
|
1269
|
-
rb_define_method(cState, "partial_generate", cState_partial_generate, 1);
|
1270
1304
|
|
1271
1305
|
mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
|
1272
1306
|
mObject = rb_define_module_under(mGeneratorMethods, "Object");
|
@@ -1275,8 +1309,10 @@ void Init_generator()
|
|
1275
1309
|
rb_define_method(mHash, "to_json", mHash_to_json, -1);
|
1276
1310
|
mArray = rb_define_module_under(mGeneratorMethods, "Array");
|
1277
1311
|
rb_define_method(mArray, "to_json", mArray_to_json, -1);
|
1278
|
-
|
1279
|
-
rb_define_method(
|
1312
|
+
mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
|
1313
|
+
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
|
1314
|
+
mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
|
1315
|
+
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
|
1280
1316
|
mFloat = rb_define_module_under(mGeneratorMethods, "Float");
|
1281
1317
|
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
|
1282
1318
|
mString = rb_define_module_under(mGeneratorMethods, "String");
|
@@ -1314,10 +1350,12 @@ void Init_generator()
|
|
1314
1350
|
i_send = rb_intern("__send__");
|
1315
1351
|
i_respond_to_p = rb_intern("respond_to?");
|
1316
1352
|
i_match = rb_intern("match");
|
1353
|
+
i_keys = rb_intern("keys");
|
1317
1354
|
#ifdef HAVE_RUBY_ENCODING_H
|
1318
1355
|
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
|
1319
1356
|
i_encoding = rb_intern("encoding");
|
1320
1357
|
i_encode = rb_intern("encode");
|
1321
1358
|
#endif
|
1359
|
+
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1322
1360
|
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
1323
1361
|
}
|
@@ -73,6 +73,7 @@ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len);
|
|
73
73
|
static void fbuffer_append_long(FBuffer *fb, long number);
|
74
74
|
static void fbuffer_append_char(FBuffer *fb, char newchr);
|
75
75
|
static FBuffer *fbuffer_dup(FBuffer *fb);
|
76
|
+
static VALUE fbuffer_to_s(FBuffer *fb);
|
76
77
|
|
77
78
|
/* unicode defintions */
|
78
79
|
|
@@ -129,9 +130,22 @@ typedef struct JSON_Generator_StateStruct {
|
|
129
130
|
JSON_Generator_State *state; \
|
130
131
|
Data_Get_Struct(self, JSON_Generator_State, state)
|
131
132
|
|
133
|
+
#define GENERATE_JSON(type) \
|
134
|
+
FBuffer *buffer; \
|
135
|
+
VALUE Vstate, depth; \
|
136
|
+
JSON_Generator_State *state; \
|
137
|
+
\
|
138
|
+
rb_scan_args(argc, argv, "02", &Vstate, &depth); \
|
139
|
+
Vstate = cState_from_state_s(cState, Vstate); \
|
140
|
+
Data_Get_Struct(Vstate, JSON_Generator_State, state); \
|
141
|
+
buffer = cState_prepare_buffer(Vstate); \
|
142
|
+
generate_json_##type(buffer, Vstate, state, self, NIL_P(depth) ? 0 : FIX2INT(depth)); \
|
143
|
+
return fbuffer_to_s(buffer)
|
144
|
+
|
132
145
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self);
|
133
146
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self);
|
134
|
-
static VALUE
|
147
|
+
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self);
|
148
|
+
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self);
|
135
149
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self);
|
136
150
|
static VALUE mString_included_s(VALUE self, VALUE modul);
|
137
151
|
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self);
|
@@ -148,6 +162,15 @@ static VALUE cState_s_allocate(VALUE klass);
|
|
148
162
|
static VALUE cState_configure(VALUE self, VALUE opts);
|
149
163
|
static VALUE cState_to_h(VALUE self);
|
150
164
|
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
165
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
166
|
+
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
167
|
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
168
|
+
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
169
|
+
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
170
|
+
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
171
|
+
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
172
|
+
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
173
|
+
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth);
|
151
174
|
static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth);
|
152
175
|
static VALUE cState_generate(VALUE self, VALUE obj);
|
153
176
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self);
|
@@ -166,5 +189,6 @@ static VALUE cState_max_nesting(VALUE self);
|
|
166
189
|
static VALUE cState_max_nesting_set(VALUE self, VALUE depth);
|
167
190
|
static VALUE cState_allow_nan_p(VALUE self);
|
168
191
|
static VALUE cState_ascii_only_p(VALUE self);
|
192
|
+
static FBuffer *cState_prepare_buffer(VALUE self);
|
169
193
|
|
170
194
|
#endif
|
data/lib/json/pure/parser.rb
CHANGED
@@ -70,24 +70,25 @@ module JSON
|
|
70
70
|
# * *array_class*: Defaults to Array
|
71
71
|
def initialize(source, opts = {})
|
72
72
|
if defined?(::Encoding)
|
73
|
-
if source.encoding == Encoding::ASCII_8BIT
|
73
|
+
if source.encoding == ::Encoding::ASCII_8BIT
|
74
74
|
b = source[0, 4].bytes.to_a
|
75
75
|
source = case
|
76
76
|
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
77
|
-
source.dup.force_encoding(Encoding::UTF_32BE).encode!(Encoding::UTF_8)
|
77
|
+
source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
|
78
78
|
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
79
|
-
source.dup.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8)
|
79
|
+
source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
|
80
80
|
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
81
|
-
source.dup.force_encoding(Encoding::UTF_32LE).encode!(Encoding::UTF_8)
|
81
|
+
source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
|
82
|
+
|
82
83
|
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
83
|
-
source.dup.force_encoding(Encoding::UTF_16LE).encode!(Encoding::UTF_8)
|
84
|
+
source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
|
84
85
|
else
|
85
86
|
source.dup
|
86
87
|
end
|
87
88
|
else
|
88
|
-
source = source.encode(Encoding::UTF_8)
|
89
|
+
source = source.encode(::Encoding::UTF_8)
|
89
90
|
end
|
90
|
-
source.force_encoding(Encoding::ASCII_8BIT)
|
91
|
+
source.force_encoding(::Encoding::ASCII_8BIT)
|
91
92
|
else
|
92
93
|
b = source
|
93
94
|
source = case
|
@@ -180,7 +181,7 @@ module JSON
|
|
180
181
|
end
|
181
182
|
end
|
182
183
|
if string.respond_to?(:force_encoding)
|
183
|
-
string.force_encoding(Encoding::UTF_8)
|
184
|
+
string.force_encoding(::Encoding::UTF_8)
|
184
185
|
end
|
185
186
|
string
|
186
187
|
else
|
data/lib/json/version.rb
CHANGED
data/tests/test_json.rb
CHANGED
@@ -160,6 +160,20 @@ class TC_JSON < Test::Unit::TestCase
|
|
160
160
|
|
161
161
|
class SubArray < Array; end
|
162
162
|
|
163
|
+
class SubArray2 < Array
|
164
|
+
def to_json(*a)
|
165
|
+
{
|
166
|
+
JSON.create_id => self.class.name,
|
167
|
+
'ary' => to_a,
|
168
|
+
}.to_json(*a)
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.json_create(o)
|
172
|
+
o.delete JSON.create_id
|
173
|
+
o['ary']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
163
177
|
def test_parse_array_custom_class
|
164
178
|
res = parse('[]', :array_class => SubArray)
|
165
179
|
assert_equal([], res)
|
@@ -174,6 +188,9 @@ class TC_JSON < Test::Unit::TestCase
|
|
174
188
|
end
|
175
189
|
|
176
190
|
class SubHash < Hash
|
191
|
+
end
|
192
|
+
|
193
|
+
class SubHash2 < Hash
|
177
194
|
def to_json(*a)
|
178
195
|
{
|
179
196
|
JSON.create_id => self.class.name,
|
@@ -182,22 +199,38 @@ class TC_JSON < Test::Unit::TestCase
|
|
182
199
|
|
183
200
|
def self.json_create(o)
|
184
201
|
o.delete JSON.create_id
|
185
|
-
|
202
|
+
self[o]
|
186
203
|
end
|
187
204
|
end
|
188
205
|
|
189
206
|
def test_parse_object_custom_class
|
190
|
-
res = parse('{}', :object_class =>
|
207
|
+
res = parse('{}', :object_class => SubHash2)
|
191
208
|
assert_equal({}, res)
|
192
|
-
assert_equal(
|
209
|
+
assert_equal(SubHash2, res.class)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_generation_of_core_subclasses_with_new_to_json
|
213
|
+
obj = SubHash2["foo" => SubHash2["bar" => true]]
|
214
|
+
obj_json = JSON(obj)
|
215
|
+
obj_again = JSON(obj_json)
|
216
|
+
assert_kind_of SubHash2, obj_again
|
217
|
+
assert_kind_of SubHash2, obj_again['foo']
|
218
|
+
assert obj_again['foo']['bar']
|
219
|
+
assert_equal obj, obj_again
|
220
|
+
assert_equal ["foo"], JSON(JSON(SubArray2["foo"]))
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_generation_of_core_subclasses_with_default_to_json
|
224
|
+
assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"])
|
225
|
+
assert_equal '["foo"]', JSON(SubArray["foo"])
|
193
226
|
end
|
194
227
|
|
195
228
|
def test_generation_of_core_subclasses
|
196
|
-
obj = SubHash
|
229
|
+
obj = SubHash["foo" => SubHash["bar" => true]]
|
197
230
|
obj_json = JSON(obj)
|
198
231
|
obj_again = JSON(obj_json)
|
199
|
-
assert_kind_of
|
200
|
-
assert_kind_of
|
232
|
+
assert_kind_of Hash, obj_again
|
233
|
+
assert_kind_of Hash, obj_again['foo']
|
201
234
|
assert obj_again['foo']['bar']
|
202
235
|
assert_equal obj, obj_again
|
203
236
|
end
|
data/tests/test_json_addition.rb
CHANGED
@@ -151,12 +151,12 @@ class TC_JSONAddition < Test::Unit::TestCase
|
|
151
151
|
def test_utc_datetime
|
152
152
|
now = Time.now
|
153
153
|
d = DateTime.parse(now.to_s) # usual case
|
154
|
-
|
154
|
+
assert_equal d, JSON.parse(d.to_json)
|
155
155
|
d = DateTime.parse(now.utc.to_s) # of = 0
|
156
|
-
|
157
|
-
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 1)
|
158
|
-
|
159
|
-
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 12)
|
160
|
-
|
156
|
+
assert_equal d, JSON.parse(d.to_json)
|
157
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
|
158
|
+
assert_equal d, JSON.parse(d.to_json)
|
159
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
|
160
|
+
assert_equal d, JSON.parse(d.to_json)
|
161
161
|
end
|
162
162
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 4
|
9
|
+
- 4
|
10
|
+
version: 1.4.4
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Florian Frank
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-08-06 00:00:00 +02:00
|
13
19
|
default_executable: edit_json.rb
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -155,21 +161,27 @@ require_paths:
|
|
155
161
|
- ext
|
156
162
|
- lib
|
157
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
158
165
|
requirements:
|
159
166
|
- - ">="
|
160
167
|
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
170
|
+
- 0
|
161
171
|
version: "0"
|
162
|
-
version:
|
163
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
164
174
|
requirements:
|
165
175
|
- - ">="
|
166
176
|
- !ruby/object:Gem::Version
|
177
|
+
hash: 3
|
178
|
+
segments:
|
179
|
+
- 0
|
167
180
|
version: "0"
|
168
|
-
version:
|
169
181
|
requirements: []
|
170
182
|
|
171
183
|
rubyforge_project: json
|
172
|
-
rubygems_version: 1.3.
|
184
|
+
rubygems_version: 1.3.7
|
173
185
|
signing_key:
|
174
186
|
specification_version: 3
|
175
187
|
summary: JSON Implementation for Ruby
|