json 1.4.4 → 1.4.5
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 +5 -0
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +99 -44
- data/ext/json/ext/generator/generator.h +18 -15
- data/lib/json/common.rb +11 -17
- data/lib/json/pure/generator.rb +6 -1
- data/lib/json/pure/parser.rb +28 -27
- data/lib/json/version.rb +1 -1
- data/tests/test_json_generate.rb +45 -0
- metadata +4 -4
data/CHANGES
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
2010-08-07 (1.4.5)
|
2
|
+
* Manage data structure nesting depth in state object during generation. This
|
3
|
+
should reduce problems with to_json method definіtions that only have one
|
4
|
+
argument.
|
5
|
+
* Some fixes in the state objects and additional tests.
|
1
6
|
2010-08-06 (1.4.4)
|
2
7
|
* Fixes build problem for rubinius under OS X, http://github.com/flori/json/issues/closed#issue/25
|
3
8
|
* Fixes crashes described in http://github.com/flori/json/issues/closed#issue/21 and
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.5
|
@@ -14,7 +14,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
|
14
14
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
15
15
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
16
16
|
i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
|
17
|
-
i_respond_to_p, i_match, i_keys;
|
17
|
+
i_respond_to_p, i_match, i_keys, i_depth;
|
18
18
|
|
19
19
|
/*
|
20
20
|
* Copyright 2001-2004 Unicode, Inc.
|
@@ -417,13 +417,12 @@ static FBuffer *fbuffer_dup(FBuffer *fb)
|
|
417
417
|
*/
|
418
418
|
|
419
419
|
/*
|
420
|
-
* call-seq: to_json(state = nil
|
420
|
+
* call-seq: to_json(state = nil)
|
421
421
|
*
|
422
422
|
* Returns a JSON string containing a JSON object, that is generated from
|
423
423
|
* this Hash instance.
|
424
424
|
* _state_ is a JSON::State object, that can also be used to configure the
|
425
425
|
* produced JSON string output further.
|
426
|
-
* _depth_ is used to find out nesting depth, to indent accordingly.
|
427
426
|
*/
|
428
427
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
429
428
|
{
|
@@ -431,13 +430,12 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
431
430
|
}
|
432
431
|
|
433
432
|
/*
|
434
|
-
* call-seq: to_json(state = nil
|
433
|
+
* call-seq: to_json(state = nil)
|
435
434
|
*
|
436
435
|
* Returns a JSON string containing a JSON array, that is generated from
|
437
436
|
* this Array instance.
|
438
437
|
* _state_ is a JSON::State object, that can also be used to configure the
|
439
438
|
* produced JSON string output further.
|
440
|
-
* _depth_ is used to find out nesting depth, to indent accordingly.
|
441
439
|
*/
|
442
440
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
443
441
|
GENERATE_JSON(array);
|
@@ -578,12 +576,12 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
578
576
|
*/
|
579
577
|
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
580
578
|
{
|
581
|
-
VALUE state
|
579
|
+
VALUE state;
|
582
580
|
VALUE string = rb_funcall(self, i_to_s, 0);
|
583
|
-
rb_scan_args(argc, argv, "
|
581
|
+
rb_scan_args(argc, argv, "01", &state);
|
584
582
|
Check_Type(string, T_STRING);
|
585
583
|
state = cState_from_state_s(cState, state);
|
586
|
-
return cState_partial_generate(state, string
|
584
|
+
return cState_partial_generate(state, string);
|
587
585
|
}
|
588
586
|
|
589
587
|
static void State_free(JSON_Generator_State *state)
|
@@ -679,6 +677,17 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
679
677
|
state->max_nesting = 0;
|
680
678
|
}
|
681
679
|
}
|
680
|
+
tmp = ID2SYM(i_depth);
|
681
|
+
state->depth = 0;
|
682
|
+
if (option_given_p(opts, tmp)) {
|
683
|
+
VALUE depth = rb_hash_aref(opts, tmp);
|
684
|
+
if (RTEST(depth)) {
|
685
|
+
Check_Type(depth, T_FIXNUM);
|
686
|
+
state->depth = FIX2LONG(depth);
|
687
|
+
} else {
|
688
|
+
state->depth = 0;
|
689
|
+
}
|
690
|
+
}
|
682
691
|
tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
|
683
692
|
state->allow_nan = RTEST(tmp);
|
684
693
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
@@ -704,6 +713,7 @@ static VALUE cState_to_h(VALUE self)
|
|
704
713
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
705
714
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
706
715
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
716
|
+
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
707
717
|
return result;
|
708
718
|
}
|
709
719
|
|
@@ -722,7 +732,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
722
732
|
}
|
723
733
|
}
|
724
734
|
|
725
|
-
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
735
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
726
736
|
{
|
727
737
|
char *object_nl = state->object_nl;
|
728
738
|
long object_nl_len = state->object_nl_len;
|
@@ -733,9 +743,9 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
733
743
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
734
744
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
735
745
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
746
|
+
long depth = ++state->depth;
|
736
747
|
int i, j;
|
737
748
|
VALUE key, key_to_s, keys;
|
738
|
-
depth++;
|
739
749
|
if (max_nesting != 0 && depth > max_nesting) {
|
740
750
|
fbuffer_free(buffer);
|
741
751
|
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
@@ -755,11 +765,11 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
755
765
|
key = rb_ary_entry(keys, i);
|
756
766
|
key_to_s = rb_funcall(key, i_to_s, 0);
|
757
767
|
Check_Type(key_to_s, T_STRING);
|
758
|
-
generate_json(buffer, Vstate, state, key_to_s
|
768
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
759
769
|
fbuffer_append(buffer, delim2, delim2_len);
|
760
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key)
|
770
|
+
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
|
761
771
|
}
|
762
|
-
depth
|
772
|
+
depth = --state->depth;
|
763
773
|
if (object_nl) {
|
764
774
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
765
775
|
if (indent) {
|
@@ -771,7 +781,7 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
771
781
|
fbuffer_append_char(buffer, '}');
|
772
782
|
}
|
773
783
|
|
774
|
-
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
784
|
+
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
775
785
|
{
|
776
786
|
char *array_nl = state->array_nl;
|
777
787
|
long array_nl_len = state->array_nl_len;
|
@@ -780,8 +790,8 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
780
790
|
long max_nesting = state->max_nesting;
|
781
791
|
char *delim = FBUFFER_PTR(state->array_delim);
|
782
792
|
long delim_len = FBUFFER_LEN(state->array_delim);
|
793
|
+
long depth = ++state->depth;
|
783
794
|
int i, j;
|
784
|
-
depth++;
|
785
795
|
if (max_nesting != 0 && depth > max_nesting) {
|
786
796
|
fbuffer_free(buffer);
|
787
797
|
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
@@ -795,9 +805,9 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
795
805
|
fbuffer_append(buffer, indent, indent_len);
|
796
806
|
}
|
797
807
|
}
|
798
|
-
generate_json(buffer, Vstate, state, rb_ary_entry(obj, i)
|
808
|
+
generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
|
799
809
|
}
|
800
|
-
depth
|
810
|
+
state->depth = --depth;
|
801
811
|
if (array_nl) {
|
802
812
|
fbuffer_append(buffer, array_nl, array_nl_len);
|
803
813
|
if (indent) {
|
@@ -809,7 +819,7 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
809
819
|
fbuffer_append_char(buffer, ']');
|
810
820
|
}
|
811
821
|
|
812
|
-
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
822
|
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
813
823
|
{
|
814
824
|
fbuffer_append_char(buffer, '"');
|
815
825
|
#ifdef HAVE_RUBY_ENCODING_H
|
@@ -823,33 +833,33 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
823
833
|
fbuffer_append_char(buffer, '"');
|
824
834
|
}
|
825
835
|
|
826
|
-
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
836
|
+
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
827
837
|
{
|
828
838
|
fbuffer_append(buffer, "null", 4);
|
829
839
|
}
|
830
840
|
|
831
|
-
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
841
|
+
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
832
842
|
{
|
833
843
|
fbuffer_append(buffer, "false", 5);
|
834
844
|
}
|
835
845
|
|
836
|
-
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
846
|
+
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
837
847
|
{
|
838
848
|
fbuffer_append(buffer, "true", 4);
|
839
849
|
}
|
840
850
|
|
841
|
-
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
851
|
+
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
842
852
|
{
|
843
853
|
fbuffer_append_long(buffer, FIX2LONG(obj));
|
844
854
|
}
|
845
855
|
|
846
|
-
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
856
|
+
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
847
857
|
{
|
848
858
|
VALUE tmp = rb_funcall(obj, i_to_s, 0);
|
849
859
|
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
850
860
|
}
|
851
861
|
|
852
|
-
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
862
|
+
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
853
863
|
{
|
854
864
|
double value = RFLOAT_VALUE(obj);
|
855
865
|
char allow_nan = state->allow_nan;
|
@@ -866,36 +876,36 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
866
876
|
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
867
877
|
}
|
868
878
|
|
869
|
-
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
879
|
+
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
870
880
|
{
|
871
881
|
VALUE tmp;
|
872
882
|
VALUE klass = CLASS_OF(obj);
|
873
883
|
if (klass == rb_cHash) {
|
874
|
-
generate_json_object(buffer, Vstate, state, obj
|
884
|
+
generate_json_object(buffer, Vstate, state, obj);
|
875
885
|
} else if (klass == rb_cArray) {
|
876
|
-
generate_json_array(buffer, Vstate, state, obj
|
886
|
+
generate_json_array(buffer, Vstate, state, obj);
|
877
887
|
} else if (klass == rb_cString) {
|
878
|
-
generate_json_string(buffer, Vstate, state, obj
|
888
|
+
generate_json_string(buffer, Vstate, state, obj);
|
879
889
|
} else if (obj == Qnil) {
|
880
|
-
generate_json_null(buffer, Vstate, state, obj
|
890
|
+
generate_json_null(buffer, Vstate, state, obj);
|
881
891
|
} else if (obj == Qfalse) {
|
882
|
-
generate_json_false(buffer, Vstate, state, obj
|
892
|
+
generate_json_false(buffer, Vstate, state, obj);
|
883
893
|
} else if (obj == Qtrue) {
|
884
|
-
generate_json_true(buffer, Vstate, state, obj
|
894
|
+
generate_json_true(buffer, Vstate, state, obj);
|
885
895
|
} else if (klass == rb_cFixnum) {
|
886
|
-
generate_json_fixnum(buffer, Vstate, state, obj
|
896
|
+
generate_json_fixnum(buffer, Vstate, state, obj);
|
887
897
|
} else if (klass == rb_cBignum) {
|
888
|
-
generate_json_bignum(buffer, Vstate, state, obj
|
898
|
+
generate_json_bignum(buffer, Vstate, state, obj);
|
889
899
|
} else if (klass == rb_cFloat) {
|
890
|
-
generate_json_float(buffer, Vstate, state, obj
|
900
|
+
generate_json_float(buffer, Vstate, state, obj);
|
891
901
|
} else if (rb_respond_to(obj, i_to_json)) {
|
892
|
-
tmp = rb_funcall(obj, i_to_json,
|
902
|
+
tmp = rb_funcall(obj, i_to_json, 1, Vstate);
|
893
903
|
Check_Type(tmp, T_STRING);
|
894
904
|
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
895
905
|
} else {
|
896
906
|
tmp = rb_funcall(obj, i_to_s, 0);
|
897
907
|
Check_Type(tmp, T_STRING);
|
898
|
-
generate_json(buffer, Vstate, state, tmp
|
908
|
+
generate_json(buffer, Vstate, state, tmp);
|
899
909
|
}
|
900
910
|
}
|
901
911
|
|
@@ -936,11 +946,11 @@ static VALUE fbuffer_to_s(FBuffer *fb)
|
|
936
946
|
return result;
|
937
947
|
}
|
938
948
|
|
939
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj
|
949
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
940
950
|
{
|
941
951
|
FBuffer *buffer = cState_prepare_buffer(self);
|
942
952
|
GET_STATE(self);
|
943
|
-
generate_json(buffer, self, state, obj
|
953
|
+
generate_json(buffer, self, state, obj);
|
944
954
|
return fbuffer_to_s(buffer);
|
945
955
|
}
|
946
956
|
|
@@ -953,7 +963,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
|
|
953
963
|
*/
|
954
964
|
static VALUE cState_generate(VALUE self, VALUE obj)
|
955
965
|
{
|
956
|
-
VALUE result = cState_partial_generate(self, obj
|
966
|
+
VALUE result = cState_partial_generate(self, obj);
|
957
967
|
VALUE re, args[2];
|
958
968
|
args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
|
959
969
|
args[1] = CRegexp_MULTILINE;
|
@@ -1055,16 +1065,20 @@ static VALUE cState_indent(VALUE self)
|
|
1055
1065
|
*/
|
1056
1066
|
static VALUE cState_indent_set(VALUE self, VALUE indent)
|
1057
1067
|
{
|
1068
|
+
int len;
|
1058
1069
|
GET_STATE(self);
|
1059
1070
|
Check_Type(indent, T_STRING);
|
1060
|
-
|
1071
|
+
len = RSTRING_LEN(indent);
|
1072
|
+
if (len == 0) {
|
1061
1073
|
if (state->indent) {
|
1062
1074
|
ruby_xfree(state->indent);
|
1063
1075
|
state->indent = NULL;
|
1076
|
+
state->indent_len = 0;
|
1064
1077
|
}
|
1065
1078
|
} else {
|
1066
1079
|
if (state->indent) ruby_xfree(state->indent);
|
1067
1080
|
state->indent = strdup(RSTRING_PTR(indent));
|
1081
|
+
state->indent_len = len;
|
1068
1082
|
}
|
1069
1083
|
return Qnil;
|
1070
1084
|
}
|
@@ -1089,16 +1103,20 @@ static VALUE cState_space(VALUE self)
|
|
1089
1103
|
*/
|
1090
1104
|
static VALUE cState_space_set(VALUE self, VALUE space)
|
1091
1105
|
{
|
1106
|
+
int len;
|
1092
1107
|
GET_STATE(self);
|
1093
1108
|
Check_Type(space, T_STRING);
|
1094
|
-
|
1109
|
+
len = RSTRING_LEN(space);
|
1110
|
+
if (len == 0) {
|
1095
1111
|
if (state->space) {
|
1096
1112
|
ruby_xfree(state->space);
|
1097
1113
|
state->space = NULL;
|
1114
|
+
state->space_len = 0;
|
1098
1115
|
}
|
1099
1116
|
} else {
|
1100
1117
|
if (state->space) ruby_xfree(state->space);
|
1101
1118
|
state->space = strdup(RSTRING_PTR(space));
|
1119
|
+
state->space_len = len;
|
1102
1120
|
}
|
1103
1121
|
return Qnil;
|
1104
1122
|
}
|
@@ -1121,16 +1139,20 @@ static VALUE cState_space_before(VALUE self)
|
|
1121
1139
|
*/
|
1122
1140
|
static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
1123
1141
|
{
|
1142
|
+
int len;
|
1124
1143
|
GET_STATE(self);
|
1125
1144
|
Check_Type(space_before, T_STRING);
|
1126
|
-
|
1145
|
+
len = RSTRING_LEN(space_before);
|
1146
|
+
if (len == 0) {
|
1127
1147
|
if (state->space_before) {
|
1128
1148
|
ruby_xfree(state->space_before);
|
1129
1149
|
state->space_before = NULL;
|
1150
|
+
state->space_before_len = 0;
|
1130
1151
|
}
|
1131
1152
|
} else {
|
1132
1153
|
if (state->space_before) ruby_xfree(state->space_before);
|
1133
1154
|
state->space_before = strdup(RSTRING_PTR(space_before));
|
1155
|
+
state->space_before_len = len;
|
1134
1156
|
}
|
1135
1157
|
return Qnil;
|
1136
1158
|
}
|
@@ -1155,9 +1177,11 @@ static VALUE cState_object_nl(VALUE self)
|
|
1155
1177
|
*/
|
1156
1178
|
static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
1157
1179
|
{
|
1180
|
+
int len;
|
1158
1181
|
GET_STATE(self);
|
1159
1182
|
Check_Type(object_nl, T_STRING);
|
1160
|
-
|
1183
|
+
len = RSTRING_LEN(object_nl);
|
1184
|
+
if (len == 0) {
|
1161
1185
|
if (state->object_nl) {
|
1162
1186
|
ruby_xfree(state->object_nl);
|
1163
1187
|
state->object_nl = NULL;
|
@@ -1165,6 +1189,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
1165
1189
|
} else {
|
1166
1190
|
if (state->object_nl) ruby_xfree(state->object_nl);
|
1167
1191
|
state->object_nl = strdup(RSTRING_PTR(object_nl));
|
1192
|
+
state->object_nl_len = len;
|
1168
1193
|
}
|
1169
1194
|
return Qnil;
|
1170
1195
|
}
|
@@ -1187,9 +1212,11 @@ static VALUE cState_array_nl(VALUE self)
|
|
1187
1212
|
*/
|
1188
1213
|
static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
1189
1214
|
{
|
1215
|
+
int len;
|
1190
1216
|
GET_STATE(self);
|
1191
1217
|
Check_Type(array_nl, T_STRING);
|
1192
|
-
|
1218
|
+
len = RSTRING_LEN(array_nl);
|
1219
|
+
if (len == 0) {
|
1193
1220
|
if (state->array_nl) {
|
1194
1221
|
ruby_xfree(state->array_nl);
|
1195
1222
|
state->array_nl = NULL;
|
@@ -1197,6 +1224,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
1197
1224
|
} else {
|
1198
1225
|
if (state->array_nl) ruby_xfree(state->array_nl);
|
1199
1226
|
state->array_nl = strdup(RSTRING_PTR(array_nl));
|
1227
|
+
state->array_nl_len = len;
|
1200
1228
|
}
|
1201
1229
|
return Qnil;
|
1202
1230
|
}
|
@@ -1263,6 +1291,30 @@ static VALUE cState_ascii_only_p(VALUE self)
|
|
1263
1291
|
return state->ascii_only ? Qtrue : Qfalse;
|
1264
1292
|
}
|
1265
1293
|
|
1294
|
+
/*
|
1295
|
+
* call-seq: depth
|
1296
|
+
*
|
1297
|
+
* This integer returns the current depth of data structure nesting.
|
1298
|
+
*/
|
1299
|
+
static VALUE cState_depth(VALUE self)
|
1300
|
+
{
|
1301
|
+
GET_STATE(self);
|
1302
|
+
return LONG2FIX(state->depth);
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
/*
|
1306
|
+
* call-seq: depth=(depth)
|
1307
|
+
*
|
1308
|
+
* This sets the maximum level of data structure nesting in the generated JSON
|
1309
|
+
* to the integer depth, max_nesting = 0 if no maximum should be checked.
|
1310
|
+
*/
|
1311
|
+
static VALUE cState_depth_set(VALUE self, VALUE depth)
|
1312
|
+
{
|
1313
|
+
GET_STATE(self);
|
1314
|
+
Check_Type(depth, T_FIXNUM);
|
1315
|
+
return state->depth = FIX2LONG(depth);
|
1316
|
+
}
|
1317
|
+
|
1266
1318
|
/*
|
1267
1319
|
*
|
1268
1320
|
*/
|
@@ -1297,6 +1349,8 @@ void Init_generator()
|
|
1297
1349
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
1298
1350
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
1299
1351
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
1352
|
+
rb_define_method(cState, "depth", cState_depth, 0);
|
1353
|
+
rb_define_method(cState, "depth=", cState_depth_set, 1);
|
1300
1354
|
rb_define_method(cState, "configure", cState_configure, 1);
|
1301
1355
|
rb_define_method(cState, "to_h", cState_to_h, 0);
|
1302
1356
|
rb_define_method(cState, "[]", cState_aref, 1);
|
@@ -1341,6 +1395,7 @@ void Init_generator()
|
|
1341
1395
|
i_max_nesting = rb_intern("max_nesting");
|
1342
1396
|
i_allow_nan = rb_intern("allow_nan");
|
1343
1397
|
i_ascii_only = rb_intern("ascii_only");
|
1398
|
+
i_depth = rb_intern("depth");
|
1344
1399
|
i_pack = rb_intern("pack");
|
1345
1400
|
i_unpack = rb_intern("unpack");
|
1346
1401
|
i_create_id = rb_intern("create_id");
|
@@ -124,22 +124,23 @@ typedef struct JSON_Generator_StateStruct {
|
|
124
124
|
long max_nesting;
|
125
125
|
char allow_nan;
|
126
126
|
char ascii_only;
|
127
|
+
long depth;
|
127
128
|
} JSON_Generator_State;
|
128
129
|
|
129
130
|
#define GET_STATE(self) \
|
130
131
|
JSON_Generator_State *state; \
|
131
132
|
Data_Get_Struct(self, JSON_Generator_State, state)
|
132
133
|
|
133
|
-
#define GENERATE_JSON(type)
|
134
|
+
#define GENERATE_JSON(type) \
|
134
135
|
FBuffer *buffer; \
|
135
|
-
VALUE Vstate
|
136
|
+
VALUE Vstate; \
|
136
137
|
JSON_Generator_State *state; \
|
137
138
|
\
|
138
|
-
rb_scan_args(argc, argv, "
|
139
|
+
rb_scan_args(argc, argv, "01", &Vstate); \
|
139
140
|
Vstate = cState_from_state_s(cState, Vstate); \
|
140
141
|
Data_Get_Struct(Vstate, JSON_Generator_State, state); \
|
141
142
|
buffer = cState_prepare_buffer(Vstate); \
|
142
|
-
generate_json_##type(buffer, Vstate, state, self
|
143
|
+
generate_json_##type(buffer, Vstate, state, self); \
|
143
144
|
return fbuffer_to_s(buffer)
|
144
145
|
|
145
146
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self);
|
@@ -161,17 +162,17 @@ static JSON_Generator_State *State_allocate();
|
|
161
162
|
static VALUE cState_s_allocate(VALUE klass);
|
162
163
|
static VALUE cState_configure(VALUE self, VALUE opts);
|
163
164
|
static VALUE cState_to_h(VALUE self);
|
164
|
-
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
165
|
-
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
166
|
-
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
167
|
-
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
168
|
-
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
169
|
-
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
170
|
-
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
171
|
-
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
172
|
-
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
173
|
-
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
174
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj
|
165
|
+
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
166
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
167
|
+
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
168
|
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
169
|
+
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
170
|
+
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
171
|
+
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
172
|
+
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
173
|
+
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
174
|
+
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
175
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj);
|
175
176
|
static VALUE cState_generate(VALUE self, VALUE obj);
|
176
177
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self);
|
177
178
|
static VALUE cState_from_state_s(VALUE self, VALUE opts);
|
@@ -189,6 +190,8 @@ static VALUE cState_max_nesting(VALUE self);
|
|
189
190
|
static VALUE cState_max_nesting_set(VALUE self, VALUE depth);
|
190
191
|
static VALUE cState_allow_nan_p(VALUE self);
|
191
192
|
static VALUE cState_ascii_only_p(VALUE self);
|
193
|
+
static VALUE cState_depth(VALUE self);
|
194
|
+
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
192
195
|
static FBuffer *cState_prepare_buffer(VALUE self);
|
193
196
|
|
194
197
|
#endif
|
data/lib/json/common.rb
CHANGED
@@ -11,9 +11,9 @@ module JSON
|
|
11
11
|
# generate and parse for their documentation.
|
12
12
|
def [](object, opts = {})
|
13
13
|
if object.respond_to? :to_str
|
14
|
-
JSON.parse(object.to_str, opts
|
14
|
+
JSON.parse(object.to_str, opts)
|
15
15
|
else
|
16
|
-
JSON.generate(object, opts
|
16
|
+
JSON.generate(object, opts)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -63,20 +63,20 @@ module JSON
|
|
63
63
|
end
|
64
64
|
self.state = generator::State
|
65
65
|
const_set :State, self.state
|
66
|
-
const_set :SAFE_STATE_PROTOTYPE, State.new
|
66
|
+
const_set :SAFE_STATE_PROTOTYPE, State.new
|
67
67
|
const_set :FAST_STATE_PROTOTYPE, State.new(
|
68
68
|
:indent => '',
|
69
69
|
:space => '',
|
70
70
|
:object_nl => "",
|
71
71
|
:array_nl => "",
|
72
72
|
:max_nesting => false
|
73
|
-
)
|
73
|
+
)
|
74
74
|
const_set :PRETTY_STATE_PROTOTYPE, State.new(
|
75
75
|
:indent => ' ',
|
76
76
|
:space => ' ',
|
77
77
|
:object_nl => "\n",
|
78
78
|
:array_nl => "\n"
|
79
|
-
)
|
79
|
+
)
|
80
80
|
end
|
81
81
|
|
82
82
|
# Returns the JSON generator modul, that is used by JSON. This might be
|
@@ -196,6 +196,7 @@ module JSON
|
|
196
196
|
# amount of sanity checks, and the pretty_generate method for some
|
197
197
|
# defaults for a pretty output.
|
198
198
|
def generate(obj, opts = nil)
|
199
|
+
state = SAFE_STATE_PROTOTYPE.dup
|
199
200
|
if opts
|
200
201
|
if opts.respond_to? :to_hash
|
201
202
|
opts = opts.to_hash
|
@@ -204,10 +205,7 @@ module JSON
|
|
204
205
|
else
|
205
206
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
206
207
|
end
|
207
|
-
state = SAFE_STATE_PROTOTYPE.dup
|
208
208
|
state = state.configure(opts)
|
209
|
-
else
|
210
|
-
state = SAFE_STATE_PROTOTYPE
|
211
209
|
end
|
212
210
|
state.generate(obj)
|
213
211
|
end
|
@@ -225,6 +223,7 @@ module JSON
|
|
225
223
|
# *WARNING*: Be careful not to pass any Ruby data structures with circles as
|
226
224
|
# _obj_ argument, because this will cause JSON to go into an infinite loop.
|
227
225
|
def fast_generate(obj, opts = nil)
|
226
|
+
state = FAST_STATE_PROTOTYPE.dup
|
228
227
|
if opts
|
229
228
|
if opts.respond_to? :to_hash
|
230
229
|
opts = opts.to_hash
|
@@ -233,10 +232,7 @@ module JSON
|
|
233
232
|
else
|
234
233
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
235
234
|
end
|
236
|
-
state = FAST_STATE_PROTOTYPE.dup
|
237
235
|
state.configure(opts)
|
238
|
-
else
|
239
|
-
state = FAST_STATE_PROTOTYPE
|
240
236
|
end
|
241
237
|
state.generate(obj)
|
242
238
|
end
|
@@ -254,6 +250,7 @@ module JSON
|
|
254
250
|
# The _opts_ argument can be used to configure the generator, see the
|
255
251
|
# generate method for a more detailed explanation.
|
256
252
|
def pretty_generate(obj, opts = nil)
|
253
|
+
state = PRETTY_STATE_PROTOTYPE.dup
|
257
254
|
if opts
|
258
255
|
if opts.respond_to? :to_hash
|
259
256
|
opts = opts.to_hash
|
@@ -262,10 +259,7 @@ module JSON
|
|
262
259
|
else
|
263
260
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
264
261
|
end
|
265
|
-
state = PRETTY_STATE_PROTOTYPE.dup
|
266
262
|
state.configure(opts)
|
267
|
-
else
|
268
|
-
state = PRETTY_STATE_PROTOTYPE
|
269
263
|
end
|
270
264
|
state.generate(obj)
|
271
265
|
end
|
@@ -377,11 +371,11 @@ module ::Kernel
|
|
377
371
|
#
|
378
372
|
# The _opts_ argument is passed through to generate/parse respectively, see
|
379
373
|
# generate and parse for their documentation.
|
380
|
-
def JSON(object,
|
374
|
+
def JSON(object, *args)
|
381
375
|
if object.respond_to? :to_str
|
382
|
-
JSON.parse(object.to_str,
|
376
|
+
JSON.parse(object.to_str, args.first)
|
383
377
|
else
|
384
|
-
JSON.generate(object,
|
378
|
+
JSON.generate(object, args.first)
|
385
379
|
end
|
386
380
|
end
|
387
381
|
end
|
data/lib/json/pure/generator.rb
CHANGED
@@ -163,6 +163,10 @@ module JSON
|
|
163
163
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
164
164
|
attr_accessor :max_nesting
|
165
165
|
|
166
|
+
# This integer returns the current depth data structure nesting in the
|
167
|
+
# generated JSON.
|
168
|
+
attr_accessor :depth
|
169
|
+
|
166
170
|
def check_max_nesting(depth) # :nodoc:
|
167
171
|
return if @max_nesting.zero?
|
168
172
|
current_nesting = depth + 1
|
@@ -196,6 +200,7 @@ module JSON
|
|
196
200
|
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
197
201
|
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
198
202
|
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
203
|
+
@depth = opts[:depth] || 0
|
199
204
|
if !opts.key?(:max_nesting) # defaults to 19
|
200
205
|
@max_nesting = 19
|
201
206
|
elsif opts[:max_nesting]
|
@@ -210,7 +215,7 @@ module JSON
|
|
210
215
|
# passed to the configure method.
|
211
216
|
def to_h
|
212
217
|
result = {}
|
213
|
-
for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting]
|
218
|
+
for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only depth]
|
214
219
|
result[iv.intern] = instance_variable_get("@#{iv}")
|
215
220
|
end
|
216
221
|
result
|
data/lib/json/pure/parser.rb
CHANGED
@@ -69,41 +69,42 @@ module JSON
|
|
69
69
|
# * *object_class*: Defaults to Hash
|
70
70
|
# * *array_class*: Defaults to Array
|
71
71
|
def initialize(source, opts = {})
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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)
|
78
|
-
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
79
|
-
source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
|
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)
|
82
|
-
|
83
|
-
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
84
|
-
source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
|
85
|
-
else
|
86
|
-
source.dup
|
87
|
-
end
|
88
|
-
else
|
89
|
-
source = source.encode(::Encoding::UTF_8)
|
90
|
-
end
|
91
|
-
source.force_encoding(::Encoding::ASCII_8BIT)
|
92
|
-
else
|
93
|
-
b = source
|
72
|
+
opts ||= {}
|
73
|
+
if defined?(::Encoding)
|
74
|
+
if source.encoding == ::Encoding::ASCII_8BIT
|
75
|
+
b = source[0, 4].bytes.to_a
|
94
76
|
source = case
|
95
77
|
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
96
|
-
|
78
|
+
source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
|
97
79
|
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
98
|
-
|
80
|
+
source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
|
99
81
|
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
100
|
-
|
82
|
+
source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
|
83
|
+
|
101
84
|
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
102
|
-
|
85
|
+
source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
|
103
86
|
else
|
104
|
-
|
87
|
+
source.dup
|
105
88
|
end
|
89
|
+
else
|
90
|
+
source = source.encode(::Encoding::UTF_8)
|
106
91
|
end
|
92
|
+
source.force_encoding(::Encoding::ASCII_8BIT)
|
93
|
+
else
|
94
|
+
b = source
|
95
|
+
source = case
|
96
|
+
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
97
|
+
JSON.iconv('utf-8', 'utf-32be', b)
|
98
|
+
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
99
|
+
JSON.iconv('utf-8', 'utf-16be', b)
|
100
|
+
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
101
|
+
JSON.iconv('utf-8', 'utf-32le', b)
|
102
|
+
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
103
|
+
JSON.iconv('utf-8', 'utf-16le', b)
|
104
|
+
else
|
105
|
+
b
|
106
|
+
end
|
107
|
+
end
|
107
108
|
super source
|
108
109
|
if !opts.key?(:max_nesting) # defaults to 19
|
109
110
|
@max_nesting = 19
|
data/lib/json/version.rb
CHANGED
data/tests/test_json_generate.rb
CHANGED
@@ -102,6 +102,51 @@ EOT
|
|
102
102
|
assert s[:check_circular?]
|
103
103
|
end
|
104
104
|
|
105
|
+
def test_pretty_state
|
106
|
+
state = PRETTY_STATE_PROTOTYPE.dup
|
107
|
+
assert_equal({
|
108
|
+
:allow_nan => false,
|
109
|
+
:array_nl => "\n",
|
110
|
+
:ascii_only => false,
|
111
|
+
:depth => 0,
|
112
|
+
:indent => " ",
|
113
|
+
:max_nesting => 19,
|
114
|
+
:object_nl => "\n",
|
115
|
+
:space => " ",
|
116
|
+
:space_before => "",
|
117
|
+
}.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_safe_state
|
121
|
+
state = SAFE_STATE_PROTOTYPE.dup
|
122
|
+
assert_equal({
|
123
|
+
:allow_nan => false,
|
124
|
+
:array_nl => "",
|
125
|
+
:ascii_only => false,
|
126
|
+
:depth => 0,
|
127
|
+
:indent => "",
|
128
|
+
:max_nesting => 19,
|
129
|
+
:object_nl => "",
|
130
|
+
:space => "",
|
131
|
+
:space_before => "",
|
132
|
+
}.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_fast_state
|
136
|
+
state = FAST_STATE_PROTOTYPE.dup
|
137
|
+
assert_equal({
|
138
|
+
:allow_nan => false,
|
139
|
+
:array_nl => "",
|
140
|
+
:ascii_only => false,
|
141
|
+
:depth => 0,
|
142
|
+
:indent => "",
|
143
|
+
:max_nesting => 0,
|
144
|
+
:object_nl => "",
|
145
|
+
:space => "",
|
146
|
+
:space_before => "",
|
147
|
+
}.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
|
148
|
+
end
|
149
|
+
|
105
150
|
def test_allow_nan
|
106
151
|
assert_raises(GeneratorError) { generate([JSON::NaN]) }
|
107
152
|
assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 5
|
10
|
+
version: 1.4.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Florian Frank
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-07 00:00:00 +02:00
|
19
19
|
default_executable: edit_json.rb
|
20
20
|
dependencies: []
|
21
21
|
|