json 1.8.3 → 2.4.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.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +9 -12
- data/{CHANGES → CHANGES.md} +219 -90
- data/Gemfile +10 -6
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +201 -134
- data/Rakefile +35 -113
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +255 -101
- data/ext/json/ext/generator/generator.h +12 -4
- data/ext/json/ext/parser/extconf.rb +28 -0
- data/ext/json/ext/parser/parser.c +410 -462
- data/ext/json/ext/parser/parser.h +5 -5
- data/ext/json/ext/parser/parser.rl +166 -181
- data/ext/json/extconf.rb +1 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +39 -36
- 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 +33 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +146 -417
- data/java/src/json/ext/Parser.rl +62 -126
- 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 +13 -2
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +22 -7
- data/json.gemspec +0 -0
- data/json_pure.gemspec +22 -29
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +4 -4
- 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 +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +3 -3
- data/lib/json/add/regexp.rb +3 -3
- data/lib/json/add/set.rb +29 -0
- 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 +350 -152
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +83 -126
- data/lib/json/pure/parser.rb +62 -84
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
- data/tests/json_common_interface_test.rb +169 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +497 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/test_helper.rb +17 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +47 -53
- data/COPYING +0 -58
- data/GPL +0 -340
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- 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
@@ -7,16 +7,22 @@ static ID i_encoding, i_encode;
|
|
7
7
|
#endif
|
8
8
|
|
9
9
|
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
10
|
-
mHash, mArray,
|
10
|
+
mHash, mArray,
|
11
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
12
|
+
mInteger,
|
13
|
+
#else
|
14
|
+
mFixnum, mBignum,
|
15
|
+
#endif
|
16
|
+
mFloat, mString, mString_Extend,
|
11
17
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
12
|
-
eNestingError,
|
18
|
+
eNestingError,
|
13
19
|
i_SAFE_STATE_PROTOTYPE;
|
14
20
|
|
15
21
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
16
22
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
17
|
-
|
23
|
+
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
18
24
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
19
|
-
i_buffer_initial_length, i_dup;
|
25
|
+
i_buffer_initial_length, i_dup, i_escape_slash;
|
20
26
|
|
21
27
|
/*
|
22
28
|
* Copyright 2001-2004 Unicode, Inc.
|
@@ -124,7 +130,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|
124
130
|
|
125
131
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
126
132
|
* and control characters are JSON escaped. */
|
127
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
133
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
|
128
134
|
{
|
129
135
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
130
136
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
@@ -174,6 +180,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
174
180
|
case '"':
|
175
181
|
fbuffer_append(buffer, "\\\"", 2);
|
176
182
|
break;
|
183
|
+
case '/':
|
184
|
+
if(escape_slash) {
|
185
|
+
fbuffer_append(buffer, "\\/", 2);
|
186
|
+
break;
|
187
|
+
}
|
177
188
|
default:
|
178
189
|
fbuffer_append_char(buffer, (char)ch);
|
179
190
|
break;
|
@@ -216,13 +227,14 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
216
227
|
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
|
217
228
|
}
|
218
229
|
}
|
230
|
+
RB_GC_GUARD(string);
|
219
231
|
}
|
220
232
|
|
221
233
|
/* Converts string to a JSON string in FBuffer buffer, where only the
|
222
234
|
* characters required by the JSON standard are JSON escaped. The remaining
|
223
235
|
* characters (should be UTF8) are just passed through and appended to the
|
224
236
|
* result. */
|
225
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
237
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
|
226
238
|
{
|
227
239
|
const char *ptr = RSTRING_PTR(string), *p;
|
228
240
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
@@ -230,6 +242,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
230
242
|
int escape_len;
|
231
243
|
unsigned char c;
|
232
244
|
char buf[6] = { '\\', 'u' };
|
245
|
+
int ascii_only = rb_enc_str_asciionly_p(string);
|
233
246
|
|
234
247
|
for (start = 0, end = 0; end < len;) {
|
235
248
|
p = ptr + end;
|
@@ -272,16 +285,25 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
272
285
|
escape = "\\\"";
|
273
286
|
escape_len = 2;
|
274
287
|
break;
|
288
|
+
case '/':
|
289
|
+
if(escape_slash) {
|
290
|
+
escape = "\\/";
|
291
|
+
escape_len = 2;
|
292
|
+
break;
|
293
|
+
}
|
275
294
|
default:
|
276
295
|
{
|
277
|
-
unsigned short clen =
|
278
|
-
if (
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
296
|
+
unsigned short clen = 1;
|
297
|
+
if (!ascii_only) {
|
298
|
+
clen += trailingBytesForUTF8[c];
|
299
|
+
if (end + clen > len) {
|
300
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
301
|
+
"partial character in source, but hit end");
|
302
|
+
}
|
303
|
+
if (!isLegalUTF8((UTF8 *) p, clen)) {
|
304
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
305
|
+
"source sequence is illegal/malformed utf-8");
|
306
|
+
}
|
285
307
|
}
|
286
308
|
end += clen;
|
287
309
|
}
|
@@ -301,7 +323,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
301
323
|
char *result;
|
302
324
|
if (len <= 0) return NULL;
|
303
325
|
result = ALLOC_N(char, len);
|
304
|
-
|
326
|
+
memcpy(result, ptr, len);
|
305
327
|
return result;
|
306
328
|
}
|
307
329
|
|
@@ -317,6 +339,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
317
339
|
*
|
318
340
|
*/
|
319
341
|
|
342
|
+
/* Explanation of the following: that's the only way to not pollute
|
343
|
+
* standard library's docs with GeneratorMethods::<ClassName> which
|
344
|
+
* are uninformative and take a large place in a list of classes
|
345
|
+
*/
|
346
|
+
|
347
|
+
/*
|
348
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
349
|
+
* :nodoc:
|
350
|
+
*/
|
351
|
+
|
352
|
+
/*
|
353
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
354
|
+
* :nodoc:
|
355
|
+
*/
|
356
|
+
|
357
|
+
/*
|
358
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
359
|
+
* :nodoc:
|
360
|
+
*/
|
361
|
+
|
362
|
+
/*
|
363
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
364
|
+
* :nodoc:
|
365
|
+
*/
|
366
|
+
|
367
|
+
/*
|
368
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
369
|
+
* :nodoc:
|
370
|
+
*/
|
371
|
+
|
372
|
+
/*
|
373
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
374
|
+
* :nodoc:
|
375
|
+
*/
|
376
|
+
|
377
|
+
/*
|
378
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
379
|
+
* :nodoc:
|
380
|
+
*/
|
381
|
+
|
382
|
+
/*
|
383
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
384
|
+
* :nodoc:
|
385
|
+
*/
|
386
|
+
|
387
|
+
/*
|
388
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
389
|
+
* :nodoc:
|
390
|
+
*/
|
391
|
+
|
392
|
+
/*
|
393
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
394
|
+
* :nodoc:
|
395
|
+
*/
|
396
|
+
|
397
|
+
/*
|
398
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
399
|
+
* :nodoc:
|
400
|
+
*/
|
401
|
+
|
402
|
+
/*
|
403
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
404
|
+
* :nodoc:
|
405
|
+
*/
|
406
|
+
|
407
|
+
/*
|
408
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
409
|
+
* :nodoc:
|
410
|
+
*/
|
411
|
+
|
320
412
|
/*
|
321
413
|
* call-seq: to_json(state = nil)
|
322
414
|
*
|
@@ -342,6 +434,18 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
342
434
|
GENERATE_JSON(array);
|
343
435
|
}
|
344
436
|
|
437
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
438
|
+
/*
|
439
|
+
* call-seq: to_json(*)
|
440
|
+
*
|
441
|
+
* Returns a JSON string representation for this Integer number.
|
442
|
+
*/
|
443
|
+
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
444
|
+
{
|
445
|
+
GENERATE_JSON(integer);
|
446
|
+
}
|
447
|
+
|
448
|
+
#else
|
345
449
|
/*
|
346
450
|
* call-seq: to_json(*)
|
347
451
|
*
|
@@ -361,6 +465,7 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
|
361
465
|
{
|
362
466
|
GENERATE_JSON(bignum);
|
363
467
|
}
|
468
|
+
#endif
|
364
469
|
|
365
470
|
/*
|
366
471
|
* call-seq: to_json(*)
|
@@ -622,8 +727,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
622
727
|
state->allow_nan = RTEST(tmp);
|
623
728
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
624
729
|
state->ascii_only = RTEST(tmp);
|
625
|
-
tmp = rb_hash_aref(opts, ID2SYM(
|
626
|
-
state->
|
730
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
731
|
+
state->escape_slash = RTEST(tmp);
|
627
732
|
return self;
|
628
733
|
}
|
629
734
|
|
@@ -657,8 +762,8 @@ static VALUE cState_to_h(VALUE self)
|
|
657
762
|
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
|
658
763
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
659
764
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
660
|
-
rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
|
661
765
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
766
|
+
rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
|
662
767
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
663
768
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
664
769
|
return result;
|
@@ -675,7 +780,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
675
780
|
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
676
781
|
return rb_funcall(self, i_send, 1, name);
|
677
782
|
} else {
|
678
|
-
return
|
783
|
+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
|
679
784
|
}
|
680
785
|
}
|
681
786
|
|
@@ -698,43 +803,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
698
803
|
return Qnil;
|
699
804
|
}
|
700
805
|
|
701
|
-
|
806
|
+
struct hash_foreach_arg {
|
807
|
+
FBuffer *buffer;
|
808
|
+
JSON_Generator_State *state;
|
809
|
+
VALUE Vstate;
|
810
|
+
int iter;
|
811
|
+
};
|
812
|
+
|
813
|
+
static int
|
814
|
+
json_object_i(VALUE key, VALUE val, VALUE _arg)
|
702
815
|
{
|
816
|
+
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
|
817
|
+
FBuffer *buffer = arg->buffer;
|
818
|
+
JSON_Generator_State *state = arg->state;
|
819
|
+
VALUE Vstate = arg->Vstate;
|
820
|
+
|
703
821
|
char *object_nl = state->object_nl;
|
704
822
|
long object_nl_len = state->object_nl_len;
|
705
823
|
char *indent = state->indent;
|
706
824
|
long indent_len = state->indent_len;
|
707
|
-
long max_nesting = state->max_nesting;
|
708
825
|
char *delim = FBUFFER_PTR(state->object_delim);
|
709
826
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
710
827
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
711
828
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
829
|
+
long depth = state->depth;
|
830
|
+
int j;
|
831
|
+
VALUE klass, key_to_s;
|
832
|
+
|
833
|
+
if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
|
834
|
+
if (object_nl) {
|
835
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
836
|
+
}
|
837
|
+
if (indent) {
|
838
|
+
for (j = 0; j < depth; j++) {
|
839
|
+
fbuffer_append(buffer, indent, indent_len);
|
840
|
+
}
|
841
|
+
}
|
842
|
+
|
843
|
+
klass = CLASS_OF(key);
|
844
|
+
if (klass == rb_cString) {
|
845
|
+
key_to_s = key;
|
846
|
+
} else if (klass == rb_cSymbol) {
|
847
|
+
key_to_s = rb_id2str(SYM2ID(key));
|
848
|
+
} else {
|
849
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
850
|
+
}
|
851
|
+
Check_Type(key_to_s, T_STRING);
|
852
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
853
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
854
|
+
generate_json(buffer, Vstate, state, val);
|
855
|
+
|
856
|
+
arg->iter++;
|
857
|
+
return ST_CONTINUE;
|
858
|
+
}
|
859
|
+
|
860
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
861
|
+
{
|
862
|
+
char *object_nl = state->object_nl;
|
863
|
+
long object_nl_len = state->object_nl_len;
|
864
|
+
char *indent = state->indent;
|
865
|
+
long indent_len = state->indent_len;
|
866
|
+
long max_nesting = state->max_nesting;
|
712
867
|
long depth = ++state->depth;
|
713
|
-
int
|
714
|
-
|
868
|
+
int j;
|
869
|
+
struct hash_foreach_arg arg;
|
870
|
+
|
715
871
|
if (max_nesting != 0 && depth > max_nesting) {
|
716
872
|
fbuffer_free(buffer);
|
717
873
|
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
|
718
874
|
}
|
719
875
|
fbuffer_append_char(buffer, '{');
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
for (j = 0; j < depth; j++) {
|
728
|
-
fbuffer_append(buffer, indent, indent_len);
|
729
|
-
}
|
730
|
-
}
|
731
|
-
key = rb_ary_entry(keys, i);
|
732
|
-
key_to_s = rb_funcall(key, i_to_s, 0);
|
733
|
-
Check_Type(key_to_s, T_STRING);
|
734
|
-
generate_json(buffer, Vstate, state, key_to_s);
|
735
|
-
fbuffer_append(buffer, delim2, delim2_len);
|
736
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
|
737
|
-
}
|
876
|
+
|
877
|
+
arg.buffer = buffer;
|
878
|
+
arg.state = state;
|
879
|
+
arg.Vstate = Vstate;
|
880
|
+
arg.iter = 0;
|
881
|
+
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
882
|
+
|
738
883
|
depth = --state->depth;
|
739
884
|
if (object_nl) {
|
740
885
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
@@ -785,16 +930,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
785
930
|
fbuffer_append_char(buffer, ']');
|
786
931
|
}
|
787
932
|
|
933
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
934
|
+
static int enc_utf8_compatible_p(rb_encoding *enc)
|
935
|
+
{
|
936
|
+
if (enc == rb_usascii_encoding()) return 1;
|
937
|
+
if (enc == rb_utf8_encoding()) return 1;
|
938
|
+
return 0;
|
939
|
+
}
|
940
|
+
#endif
|
941
|
+
|
788
942
|
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
789
943
|
{
|
790
944
|
fbuffer_append_char(buffer, '"');
|
791
945
|
#ifdef HAVE_RUBY_ENCODING_H
|
792
|
-
|
946
|
+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
|
947
|
+
obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
|
948
|
+
}
|
793
949
|
#endif
|
794
950
|
if (state->ascii_only) {
|
795
|
-
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
951
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
|
796
952
|
} else {
|
797
|
-
convert_UTF8_to_JSON(buffer, obj);
|
953
|
+
convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
|
798
954
|
}
|
799
955
|
fbuffer_append_char(buffer, '"');
|
800
956
|
}
|
@@ -825,6 +981,15 @@ static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
825
981
|
fbuffer_append_str(buffer, tmp);
|
826
982
|
}
|
827
983
|
|
984
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
985
|
+
static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
986
|
+
{
|
987
|
+
if (FIXNUM_P(obj))
|
988
|
+
generate_json_fixnum(buffer, Vstate, state, obj);
|
989
|
+
else
|
990
|
+
generate_json_bignum(buffer, Vstate, state, obj);
|
991
|
+
}
|
992
|
+
#endif
|
828
993
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
829
994
|
{
|
830
995
|
double value = RFLOAT_VALUE(obj);
|
@@ -858,9 +1023,9 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
858
1023
|
generate_json_false(buffer, Vstate, state, obj);
|
859
1024
|
} else if (obj == Qtrue) {
|
860
1025
|
generate_json_true(buffer, Vstate, state, obj);
|
861
|
-
} else if (
|
1026
|
+
} else if (FIXNUM_P(obj)) {
|
862
1027
|
generate_json_fixnum(buffer, Vstate, state, obj);
|
863
|
-
} else if (
|
1028
|
+
} else if (RB_TYPE_P(obj, T_BIGNUM)) {
|
864
1029
|
generate_json_bignum(buffer, Vstate, state, obj);
|
865
1030
|
} else if (klass == rb_cFloat) {
|
866
1031
|
generate_json_float(buffer, Vstate, state, obj);
|
@@ -871,7 +1036,7 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
871
1036
|
} else {
|
872
1037
|
tmp = rb_funcall(obj, i_to_s, 0);
|
873
1038
|
Check_Type(tmp, T_STRING);
|
874
|
-
|
1039
|
+
generate_json_string(buffer, Vstate, state, tmp);
|
875
1040
|
}
|
876
1041
|
}
|
877
1042
|
|
@@ -914,21 +1079,6 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
914
1079
|
return fbuffer_to_s(buffer);
|
915
1080
|
}
|
916
1081
|
|
917
|
-
/*
|
918
|
-
* This function returns true if string is either a JSON array or JSON object.
|
919
|
-
* It might suffer from false positives, e. g. syntactically incorrect JSON in
|
920
|
-
* the string or certain UTF-8 characters on the right hand side.
|
921
|
-
*/
|
922
|
-
static int isArrayOrObject(VALUE string)
|
923
|
-
{
|
924
|
-
long string_len = RSTRING_LEN(string);
|
925
|
-
char *p = RSTRING_PTR(string), *q = p + string_len - 1;
|
926
|
-
if (string_len < 2) return 0;
|
927
|
-
for (; p < q && isspace((unsigned char)*p); p++);
|
928
|
-
for (; q > p && isspace((unsigned char)*q); q--);
|
929
|
-
return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
|
930
|
-
}
|
931
|
-
|
932
1082
|
/*
|
933
1083
|
* call-seq: generate(obj)
|
934
1084
|
*
|
@@ -940,9 +1090,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
940
1090
|
{
|
941
1091
|
VALUE result = cState_partial_generate(self, obj);
|
942
1092
|
GET_STATE(self);
|
943
|
-
|
944
|
-
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
|
945
|
-
}
|
1093
|
+
(void)state;
|
946
1094
|
return result;
|
947
1095
|
}
|
948
1096
|
|
@@ -961,8 +1109,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
961
1109
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
962
1110
|
* generated, otherwise an exception is thrown, if these values are
|
963
1111
|
* encountered. This options defaults to false.
|
964
|
-
* * *
|
965
|
-
*
|
1112
|
+
* * *ascii_only*: true if only ASCII characters should be generated. This
|
1113
|
+
* option defaults to false.
|
966
1114
|
* * *buffer_initial_length*: sets the initial length of the generator's
|
967
1115
|
* internal buffer.
|
968
1116
|
*/
|
@@ -1018,10 +1166,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
1018
1166
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
1019
1167
|
return rb_funcall(self, i_new, 1, opts);
|
1020
1168
|
} else {
|
1021
|
-
|
1022
|
-
|
1023
|
-
}
|
1024
|
-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
|
1169
|
+
VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
1170
|
+
return rb_funcall(prototype, i_dup, 0);
|
1025
1171
|
}
|
1026
1172
|
}
|
1027
1173
|
|
@@ -1055,7 +1201,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
1055
1201
|
}
|
1056
1202
|
} else {
|
1057
1203
|
if (state->indent) ruby_xfree(state->indent);
|
1058
|
-
state->indent =
|
1204
|
+
state->indent = fstrndup(RSTRING_PTR(indent), len);
|
1059
1205
|
state->indent_len = len;
|
1060
1206
|
}
|
1061
1207
|
return Qnil;
|
@@ -1093,7 +1239,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
1093
1239
|
}
|
1094
1240
|
} else {
|
1095
1241
|
if (state->space) ruby_xfree(state->space);
|
1096
|
-
state->space =
|
1242
|
+
state->space = fstrndup(RSTRING_PTR(space), len);
|
1097
1243
|
state->space_len = len;
|
1098
1244
|
}
|
1099
1245
|
return Qnil;
|
@@ -1129,7 +1275,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
1129
1275
|
}
|
1130
1276
|
} else {
|
1131
1277
|
if (state->space_before) ruby_xfree(state->space_before);
|
1132
|
-
state->space_before =
|
1278
|
+
state->space_before = fstrndup(RSTRING_PTR(space_before), len);
|
1133
1279
|
state->space_before_len = len;
|
1134
1280
|
}
|
1135
1281
|
return Qnil;
|
@@ -1166,7 +1312,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
1166
1312
|
}
|
1167
1313
|
} else {
|
1168
1314
|
if (state->object_nl) ruby_xfree(state->object_nl);
|
1169
|
-
state->object_nl =
|
1315
|
+
state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
|
1170
1316
|
state->object_nl_len = len;
|
1171
1317
|
}
|
1172
1318
|
return Qnil;
|
@@ -1201,7 +1347,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
1201
1347
|
}
|
1202
1348
|
} else {
|
1203
1349
|
if (state->array_nl) ruby_xfree(state->array_nl);
|
1204
|
-
state->array_nl =
|
1350
|
+
state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
|
1205
1351
|
state->array_nl_len = len;
|
1206
1352
|
}
|
1207
1353
|
return Qnil;
|
@@ -1246,50 +1392,52 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
1246
1392
|
}
|
1247
1393
|
|
1248
1394
|
/*
|
1249
|
-
* call-seq:
|
1395
|
+
* call-seq: escape_slash
|
1250
1396
|
*
|
1251
|
-
*
|
1252
|
-
*
|
1397
|
+
* If this boolean is true, the forward slashes will be escaped in
|
1398
|
+
* the json output.
|
1253
1399
|
*/
|
1254
|
-
static VALUE
|
1400
|
+
static VALUE cState_escape_slash(VALUE self)
|
1255
1401
|
{
|
1256
1402
|
GET_STATE(self);
|
1257
|
-
return state->
|
1403
|
+
return state->escape_slash ? Qtrue : Qfalse;
|
1258
1404
|
}
|
1259
1405
|
|
1260
1406
|
/*
|
1261
|
-
* call-seq:
|
1407
|
+
* call-seq: escape_slash=(depth)
|
1262
1408
|
*
|
1263
|
-
*
|
1264
|
-
*
|
1409
|
+
* This sets whether or not the forward slashes will be escaped in
|
1410
|
+
* the json output.
|
1265
1411
|
*/
|
1266
|
-
static VALUE
|
1412
|
+
static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
|
1267
1413
|
{
|
1268
1414
|
GET_STATE(self);
|
1269
|
-
|
1415
|
+
state->escape_slash = RTEST(enable);
|
1416
|
+
return Qnil;
|
1270
1417
|
}
|
1271
1418
|
|
1272
1419
|
/*
|
1273
|
-
* call-seq:
|
1420
|
+
* call-seq: allow_nan?
|
1274
1421
|
*
|
1275
|
-
* Returns true, if
|
1422
|
+
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
|
1423
|
+
* returns false.
|
1276
1424
|
*/
|
1277
|
-
static VALUE
|
1425
|
+
static VALUE cState_allow_nan_p(VALUE self)
|
1278
1426
|
{
|
1279
1427
|
GET_STATE(self);
|
1280
|
-
return state->
|
1428
|
+
return state->allow_nan ? Qtrue : Qfalse;
|
1281
1429
|
}
|
1282
1430
|
|
1283
1431
|
/*
|
1284
|
-
* call-seq:
|
1432
|
+
* call-seq: ascii_only?
|
1285
1433
|
*
|
1286
|
-
*
|
1434
|
+
* Returns true, if only ASCII characters should be generated. Otherwise
|
1435
|
+
* returns false.
|
1287
1436
|
*/
|
1288
|
-
static VALUE
|
1437
|
+
static VALUE cState_ascii_only_p(VALUE self)
|
1289
1438
|
{
|
1290
1439
|
GET_STATE(self);
|
1291
|
-
state->
|
1292
|
-
return Qnil;
|
1440
|
+
return state->ascii_only ? Qtrue : Qfalse;
|
1293
1441
|
}
|
1294
1442
|
|
1295
1443
|
/*
|
@@ -1351,6 +1499,7 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
1351
1499
|
*/
|
1352
1500
|
void Init_generator(void)
|
1353
1501
|
{
|
1502
|
+
#undef rb_intern
|
1354
1503
|
rb_require("json/common");
|
1355
1504
|
|
1356
1505
|
mJSON = rb_define_module("JSON");
|
@@ -1359,6 +1508,8 @@ void Init_generator(void)
|
|
1359
1508
|
|
1360
1509
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
1361
1510
|
eNestingError = rb_path2class("JSON::NestingError");
|
1511
|
+
rb_gc_register_mark_object(eGeneratorError);
|
1512
|
+
rb_gc_register_mark_object(eNestingError);
|
1362
1513
|
|
1363
1514
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
1364
1515
|
rb_define_alloc_func(cState, cState_s_allocate);
|
@@ -1377,12 +1528,12 @@ void Init_generator(void)
|
|
1377
1528
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
1378
1529
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
1379
1530
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
1531
|
+
rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
|
1532
|
+
rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
|
1533
|
+
rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
|
1380
1534
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
1381
1535
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
1382
1536
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
1383
|
-
rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
|
1384
|
-
rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
|
1385
|
-
rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
|
1386
1537
|
rb_define_method(cState, "depth", cState_depth, 0);
|
1387
1538
|
rb_define_method(cState, "depth=", cState_depth_set, 1);
|
1388
1539
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
@@ -1402,10 +1553,15 @@ void Init_generator(void)
|
|
1402
1553
|
rb_define_method(mHash, "to_json", mHash_to_json, -1);
|
1403
1554
|
mArray = rb_define_module_under(mGeneratorMethods, "Array");
|
1404
1555
|
rb_define_method(mArray, "to_json", mArray_to_json, -1);
|
1556
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
1557
|
+
mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
|
1558
|
+
rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
|
1559
|
+
#else
|
1405
1560
|
mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
|
1406
1561
|
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
|
1407
1562
|
mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
|
1408
1563
|
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
|
1564
|
+
#endif
|
1409
1565
|
mFloat = rb_define_module_under(mGeneratorMethods, "Float");
|
1410
1566
|
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
|
1411
1567
|
mString = rb_define_module_under(mGeneratorMethods, "String");
|
@@ -1422,7 +1578,6 @@ void Init_generator(void)
|
|
1422
1578
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
1423
1579
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
1424
1580
|
|
1425
|
-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
1426
1581
|
i_to_s = rb_intern("to_s");
|
1427
1582
|
i_to_json = rb_intern("to_json");
|
1428
1583
|
i_new = rb_intern("new");
|
@@ -1432,9 +1587,9 @@ void Init_generator(void)
|
|
1432
1587
|
i_object_nl = rb_intern("object_nl");
|
1433
1588
|
i_array_nl = rb_intern("array_nl");
|
1434
1589
|
i_max_nesting = rb_intern("max_nesting");
|
1590
|
+
i_escape_slash = rb_intern("escape_slash");
|
1435
1591
|
i_allow_nan = rb_intern("allow_nan");
|
1436
1592
|
i_ascii_only = rb_intern("ascii_only");
|
1437
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
1438
1593
|
i_depth = rb_intern("depth");
|
1439
1594
|
i_buffer_initial_length = rb_intern("buffer_initial_length");
|
1440
1595
|
i_pack = rb_intern("pack");
|
@@ -1454,5 +1609,4 @@ void Init_generator(void)
|
|
1454
1609
|
i_encode = rb_intern("encode");
|
1455
1610
|
#endif
|
1456
1611
|
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
1457
|
-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
1458
1612
|
}
|