json 1.8.0 → 2.6.2
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/{CHANGES → CHANGES.md} +262 -87
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/README.md +425 -0
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +10 -4
- data/ext/json/ext/generator/extconf.rb +0 -10
- data/ext/json/ext/generator/generator.c +308 -135
- data/ext/json/ext/generator/generator.h +35 -9
- data/ext/json/ext/parser/extconf.rb +25 -6
- data/ext/json/ext/parser/parser.c +3044 -1901
- data/ext/json/ext/parser/parser.h +29 -10
- data/ext/json/ext/parser/parser.rl +270 -211
- data/ext/json/extconf.rb +3 -0
- data/json.gemspec +57 -27
- data/lib/json/add/bigdecimal.rb +3 -2
- data/lib/json/add/complex.rb +9 -3
- 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 +8 -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 +2 -2
- data/lib/json/common.rb +383 -167
- 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 +63 -85
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +550 -29
- metadata +29 -136
- data/.gitignore +0 -12
- data/.travis.yml +0 -20
- data/COPYING +0 -58
- data/GPL +0 -340
- data/Gemfile +0 -11
- data/README-json-jruby.markdown +0 -33
- data/README.rdoc +0 -358
- data/Rakefile +0 -412
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -167
- data/java/src/json/ext/Generator.java +0 -444
- data/java/src/json/ext/GeneratorMethods.java +0 -232
- data/java/src/json/ext/GeneratorService.java +0 -43
- data/java/src/json/ext/GeneratorState.java +0 -543
- data/java/src/json/ext/OptionsReader.java +0 -114
- data/java/src/json/ext/Parser.java +0 -2644
- data/java/src/json/ext/Parser.rl +0 -968
- data/java/src/json/ext/ParserService.java +0 -35
- data/java/src/json/ext/RuntimeInfo.java +0 -121
- data/java/src/json/ext/StringDecoder.java +0 -167
- data/java/src/json/ext/StringEncoder.java +0 -106
- data/java/src/json/ext/Utils.java +0 -89
- data/json-java.gemspec +0 -23
- data/json_pure.gemspec +0 -39
- data/lib/json/ext/.keep +0 -0
- data/tests/fixtures/fail1.json +0 -1
- data/tests/fixtures/fail10.json +0 -1
- data/tests/fixtures/fail11.json +0 -1
- data/tests/fixtures/fail12.json +0 -1
- data/tests/fixtures/fail13.json +0 -1
- data/tests/fixtures/fail14.json +0 -1
- data/tests/fixtures/fail18.json +0 -1
- data/tests/fixtures/fail19.json +0 -1
- data/tests/fixtures/fail2.json +0 -1
- data/tests/fixtures/fail20.json +0 -1
- data/tests/fixtures/fail21.json +0 -1
- data/tests/fixtures/fail22.json +0 -1
- data/tests/fixtures/fail23.json +0 -1
- data/tests/fixtures/fail24.json +0 -1
- data/tests/fixtures/fail25.json +0 -1
- data/tests/fixtures/fail27.json +0 -2
- data/tests/fixtures/fail28.json +0 -2
- data/tests/fixtures/fail3.json +0 -1
- data/tests/fixtures/fail4.json +0 -1
- data/tests/fixtures/fail5.json +0 -1
- data/tests/fixtures/fail6.json +0 -1
- data/tests/fixtures/fail7.json +0 -1
- data/tests/fixtures/fail8.json +0 -1
- data/tests/fixtures/fail9.json +0 -1
- data/tests/fixtures/pass1.json +0 -56
- data/tests/fixtures/pass15.json +0 -1
- data/tests/fixtures/pass16.json +0 -1
- data/tests/fixtures/pass17.json +0 -1
- data/tests/fixtures/pass2.json +0 -1
- data/tests/fixtures/pass26.json +0 -1
- data/tests/fixtures/pass3.json +0 -6
- data/tests/setup_variant.rb +0 -11
- data/tests/test_json.rb +0 -545
- data/tests/test_json_addition.rb +0 -196
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_fixtures.rb +0 -35
- data/tests/test_json_generate.rb +0 -322
- data/tests/test_json_generic_object.rb +0 -75
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
- data/tools/fuzz.rb +0 -139
- data/tools/server.rb +0 -62
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#include "../fbuffer/fbuffer.h"
|
|
2
2
|
#include "generator.h"
|
|
3
3
|
|
|
4
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
|
5
|
-
static VALUE CEncoding_UTF_8;
|
|
6
|
-
static ID i_encoding, i_encode;
|
|
7
|
-
#endif
|
|
8
|
-
|
|
9
4
|
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
|
10
|
-
mHash, mArray,
|
|
5
|
+
mHash, mArray,
|
|
6
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
7
|
+
mInteger,
|
|
8
|
+
#else
|
|
9
|
+
mFixnum, mBignum,
|
|
10
|
+
#endif
|
|
11
|
+
mFloat, mString, mString_Extend,
|
|
11
12
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
|
12
|
-
eNestingError
|
|
13
|
-
i_SAFE_STATE_PROTOTYPE;
|
|
13
|
+
eNestingError;
|
|
14
14
|
|
|
15
15
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
|
16
16
|
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
|
17
|
-
|
|
17
|
+
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
|
|
18
18
|
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
|
|
19
|
-
i_buffer_initial_length, i_dup;
|
|
19
|
+
i_buffer_initial_length, i_dup, i_escape_slash;
|
|
20
20
|
|
|
21
21
|
/*
|
|
22
22
|
* Copyright 2001-2004 Unicode, Inc.
|
|
@@ -124,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
|
|
124
124
|
|
|
125
125
|
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
|
126
126
|
* and control characters are JSON escaped. */
|
|
127
|
-
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
127
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
|
|
128
128
|
{
|
|
129
129
|
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
|
130
130
|
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
|
@@ -174,6 +174,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
|
174
174
|
case '"':
|
|
175
175
|
fbuffer_append(buffer, "\\\"", 2);
|
|
176
176
|
break;
|
|
177
|
+
case '/':
|
|
178
|
+
if(escape_slash) {
|
|
179
|
+
fbuffer_append(buffer, "\\/", 2);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
177
182
|
default:
|
|
178
183
|
fbuffer_append_char(buffer, (char)ch);
|
|
179
184
|
break;
|
|
@@ -216,13 +221,14 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
|
|
216
221
|
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
|
|
217
222
|
}
|
|
218
223
|
}
|
|
224
|
+
RB_GC_GUARD(string);
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
/* Converts string to a JSON string in FBuffer buffer, where only the
|
|
222
228
|
* characters required by the JSON standard are JSON escaped. The remaining
|
|
223
229
|
* characters (should be UTF8) are just passed through and appended to the
|
|
224
230
|
* result. */
|
|
225
|
-
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
231
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
|
|
226
232
|
{
|
|
227
233
|
const char *ptr = RSTRING_PTR(string), *p;
|
|
228
234
|
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
|
|
@@ -230,6 +236,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
|
230
236
|
int escape_len;
|
|
231
237
|
unsigned char c;
|
|
232
238
|
char buf[6] = { '\\', 'u' };
|
|
239
|
+
int ascii_only = rb_enc_str_asciionly_p(string);
|
|
233
240
|
|
|
234
241
|
for (start = 0, end = 0; end < len;) {
|
|
235
242
|
p = ptr + end;
|
|
@@ -272,16 +279,25 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
|
|
272
279
|
escape = "\\\"";
|
|
273
280
|
escape_len = 2;
|
|
274
281
|
break;
|
|
282
|
+
case '/':
|
|
283
|
+
if(escape_slash) {
|
|
284
|
+
escape = "\\/";
|
|
285
|
+
escape_len = 2;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
275
288
|
default:
|
|
276
289
|
{
|
|
277
|
-
unsigned short clen =
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
290
|
+
unsigned short clen = 1;
|
|
291
|
+
if (!ascii_only) {
|
|
292
|
+
clen += trailingBytesForUTF8[c];
|
|
293
|
+
if (end + clen > len) {
|
|
294
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
|
295
|
+
"partial character in source, but hit end");
|
|
296
|
+
}
|
|
297
|
+
if (!isLegalUTF8((UTF8 *) p, clen)) {
|
|
298
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
|
299
|
+
"source sequence is illegal/malformed utf-8");
|
|
300
|
+
}
|
|
285
301
|
}
|
|
286
302
|
end += clen;
|
|
287
303
|
}
|
|
@@ -301,7 +317,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
|
301
317
|
char *result;
|
|
302
318
|
if (len <= 0) return NULL;
|
|
303
319
|
result = ALLOC_N(char, len);
|
|
304
|
-
|
|
320
|
+
memcpy(result, ptr, len);
|
|
305
321
|
return result;
|
|
306
322
|
}
|
|
307
323
|
|
|
@@ -317,6 +333,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
|
317
333
|
*
|
|
318
334
|
*/
|
|
319
335
|
|
|
336
|
+
/* Explanation of the following: that's the only way to not pollute
|
|
337
|
+
* standard library's docs with GeneratorMethods::<ClassName> which
|
|
338
|
+
* are uninformative and take a large place in a list of classes
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
/*
|
|
342
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods
|
|
343
|
+
* :nodoc:
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
/*
|
|
347
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Array
|
|
348
|
+
* :nodoc:
|
|
349
|
+
*/
|
|
350
|
+
|
|
351
|
+
/*
|
|
352
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
|
|
353
|
+
* :nodoc:
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
/*
|
|
357
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
|
|
358
|
+
* :nodoc:
|
|
359
|
+
*/
|
|
360
|
+
|
|
361
|
+
/*
|
|
362
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
|
|
363
|
+
* :nodoc:
|
|
364
|
+
*/
|
|
365
|
+
|
|
366
|
+
/*
|
|
367
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Float
|
|
368
|
+
* :nodoc:
|
|
369
|
+
*/
|
|
370
|
+
|
|
371
|
+
/*
|
|
372
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
|
|
373
|
+
* :nodoc:
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
/*
|
|
377
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
|
|
378
|
+
* :nodoc:
|
|
379
|
+
*/
|
|
380
|
+
|
|
381
|
+
/*
|
|
382
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
|
|
383
|
+
* :nodoc:
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
|
+
/*
|
|
387
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::Object
|
|
388
|
+
* :nodoc:
|
|
389
|
+
*/
|
|
390
|
+
|
|
391
|
+
/*
|
|
392
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String
|
|
393
|
+
* :nodoc:
|
|
394
|
+
*/
|
|
395
|
+
|
|
396
|
+
/*
|
|
397
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
|
|
398
|
+
* :nodoc:
|
|
399
|
+
*/
|
|
400
|
+
|
|
401
|
+
/*
|
|
402
|
+
* Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
|
|
403
|
+
* :nodoc:
|
|
404
|
+
*/
|
|
405
|
+
|
|
320
406
|
/*
|
|
321
407
|
* call-seq: to_json(state = nil)
|
|
322
408
|
*
|
|
@@ -342,6 +428,18 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
|
342
428
|
GENERATE_JSON(array);
|
|
343
429
|
}
|
|
344
430
|
|
|
431
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
432
|
+
/*
|
|
433
|
+
* call-seq: to_json(*)
|
|
434
|
+
*
|
|
435
|
+
* Returns a JSON string representation for this Integer number.
|
|
436
|
+
*/
|
|
437
|
+
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
438
|
+
{
|
|
439
|
+
GENERATE_JSON(integer);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
#else
|
|
345
443
|
/*
|
|
346
444
|
* call-seq: to_json(*)
|
|
347
445
|
*
|
|
@@ -361,6 +459,7 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
|
|
361
459
|
{
|
|
362
460
|
GENERATE_JSON(bignum);
|
|
363
461
|
}
|
|
462
|
+
#endif
|
|
364
463
|
|
|
365
464
|
/*
|
|
366
465
|
* call-seq: to_json(*)
|
|
@@ -486,8 +585,9 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
|
|
486
585
|
return cState_partial_generate(state, string);
|
|
487
586
|
}
|
|
488
587
|
|
|
489
|
-
static void State_free(
|
|
588
|
+
static void State_free(void *ptr)
|
|
490
589
|
{
|
|
590
|
+
JSON_Generator_State *state = ptr;
|
|
491
591
|
if (state->indent) ruby_xfree(state->indent);
|
|
492
592
|
if (state->space) ruby_xfree(state->space);
|
|
493
593
|
if (state->space_before) ruby_xfree(state->space_before);
|
|
@@ -499,17 +599,42 @@ static void State_free(JSON_Generator_State *state)
|
|
|
499
599
|
ruby_xfree(state);
|
|
500
600
|
}
|
|
501
601
|
|
|
502
|
-
static
|
|
602
|
+
static size_t State_memsize(const void *ptr)
|
|
503
603
|
{
|
|
504
|
-
JSON_Generator_State *state =
|
|
505
|
-
|
|
506
|
-
|
|
604
|
+
const JSON_Generator_State *state = ptr;
|
|
605
|
+
size_t size = sizeof(*state);
|
|
606
|
+
if (state->indent) size += state->indent_len + 1;
|
|
607
|
+
if (state->space) size += state->space_len + 1;
|
|
608
|
+
if (state->space_before) size += state->space_before_len + 1;
|
|
609
|
+
if (state->object_nl) size += state->object_nl_len + 1;
|
|
610
|
+
if (state->array_nl) size += state->array_nl_len + 1;
|
|
611
|
+
if (state->array_delim) size += FBUFFER_CAPA(state->array_delim);
|
|
612
|
+
if (state->object_delim) size += FBUFFER_CAPA(state->object_delim);
|
|
613
|
+
if (state->object_delim2) size += FBUFFER_CAPA(state->object_delim2);
|
|
614
|
+
return size;
|
|
507
615
|
}
|
|
508
616
|
|
|
617
|
+
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
|
618
|
+
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
|
619
|
+
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
620
|
+
#endif
|
|
621
|
+
|
|
622
|
+
#ifdef NEW_TYPEDDATA_WRAPPER
|
|
623
|
+
static const rb_data_type_t JSON_Generator_State_type = {
|
|
624
|
+
"JSON/Generator/State",
|
|
625
|
+
{NULL, State_free, State_memsize,},
|
|
626
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
|
627
|
+
0, 0,
|
|
628
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
629
|
+
#endif
|
|
630
|
+
};
|
|
631
|
+
#endif
|
|
632
|
+
|
|
509
633
|
static VALUE cState_s_allocate(VALUE klass)
|
|
510
634
|
{
|
|
511
|
-
JSON_Generator_State *state
|
|
512
|
-
return
|
|
635
|
+
JSON_Generator_State *state;
|
|
636
|
+
return TypedData_Make_Struct(klass, JSON_Generator_State,
|
|
637
|
+
&JSON_Generator_State_type, state);
|
|
513
638
|
}
|
|
514
639
|
|
|
515
640
|
/*
|
|
@@ -601,8 +726,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
|
601
726
|
state->allow_nan = RTEST(tmp);
|
|
602
727
|
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
|
603
728
|
state->ascii_only = RTEST(tmp);
|
|
604
|
-
tmp = rb_hash_aref(opts, ID2SYM(
|
|
605
|
-
state->
|
|
729
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
|
|
730
|
+
state->escape_slash = RTEST(tmp);
|
|
606
731
|
return self;
|
|
607
732
|
}
|
|
608
733
|
|
|
@@ -636,8 +761,8 @@ static VALUE cState_to_h(VALUE self)
|
|
|
636
761
|
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
|
|
637
762
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
|
638
763
|
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
|
639
|
-
rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
|
|
640
764
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
|
765
|
+
rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
|
|
641
766
|
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
|
|
642
767
|
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
|
|
643
768
|
return result;
|
|
@@ -646,7 +771,7 @@ static VALUE cState_to_h(VALUE self)
|
|
|
646
771
|
/*
|
|
647
772
|
* call-seq: [](name)
|
|
648
773
|
*
|
|
649
|
-
*
|
|
774
|
+
* Returns the value returned by method +name+.
|
|
650
775
|
*/
|
|
651
776
|
static VALUE cState_aref(VALUE self, VALUE name)
|
|
652
777
|
{
|
|
@@ -654,14 +779,14 @@ static VALUE cState_aref(VALUE self, VALUE name)
|
|
|
654
779
|
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
|
655
780
|
return rb_funcall(self, i_send, 1, name);
|
|
656
781
|
} else {
|
|
657
|
-
return
|
|
782
|
+
return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
|
|
658
783
|
}
|
|
659
784
|
}
|
|
660
785
|
|
|
661
786
|
/*
|
|
662
787
|
* call-seq: []=(name, value)
|
|
663
788
|
*
|
|
664
|
-
*
|
|
789
|
+
* Sets the attribute name to value.
|
|
665
790
|
*/
|
|
666
791
|
static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
667
792
|
{
|
|
@@ -677,43 +802,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
|
|
|
677
802
|
return Qnil;
|
|
678
803
|
}
|
|
679
804
|
|
|
680
|
-
|
|
805
|
+
struct hash_foreach_arg {
|
|
806
|
+
FBuffer *buffer;
|
|
807
|
+
JSON_Generator_State *state;
|
|
808
|
+
VALUE Vstate;
|
|
809
|
+
int iter;
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
static int
|
|
813
|
+
json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
681
814
|
{
|
|
815
|
+
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
|
|
816
|
+
FBuffer *buffer = arg->buffer;
|
|
817
|
+
JSON_Generator_State *state = arg->state;
|
|
818
|
+
VALUE Vstate = arg->Vstate;
|
|
819
|
+
|
|
682
820
|
char *object_nl = state->object_nl;
|
|
683
821
|
long object_nl_len = state->object_nl_len;
|
|
684
822
|
char *indent = state->indent;
|
|
685
823
|
long indent_len = state->indent_len;
|
|
686
|
-
long max_nesting = state->max_nesting;
|
|
687
824
|
char *delim = FBUFFER_PTR(state->object_delim);
|
|
688
825
|
long delim_len = FBUFFER_LEN(state->object_delim);
|
|
689
826
|
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
|
690
827
|
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
|
828
|
+
long depth = state->depth;
|
|
829
|
+
int j;
|
|
830
|
+
VALUE klass, key_to_s;
|
|
831
|
+
|
|
832
|
+
if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
|
|
833
|
+
if (object_nl) {
|
|
834
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
|
835
|
+
}
|
|
836
|
+
if (indent) {
|
|
837
|
+
for (j = 0; j < depth; j++) {
|
|
838
|
+
fbuffer_append(buffer, indent, indent_len);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
klass = CLASS_OF(key);
|
|
843
|
+
if (klass == rb_cString) {
|
|
844
|
+
key_to_s = key;
|
|
845
|
+
} else if (klass == rb_cSymbol) {
|
|
846
|
+
key_to_s = rb_id2str(SYM2ID(key));
|
|
847
|
+
} else {
|
|
848
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
|
849
|
+
}
|
|
850
|
+
Check_Type(key_to_s, T_STRING);
|
|
851
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
|
852
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
|
853
|
+
generate_json(buffer, Vstate, state, val);
|
|
854
|
+
|
|
855
|
+
arg->iter++;
|
|
856
|
+
return ST_CONTINUE;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
|
860
|
+
{
|
|
861
|
+
char *object_nl = state->object_nl;
|
|
862
|
+
long object_nl_len = state->object_nl_len;
|
|
863
|
+
char *indent = state->indent;
|
|
864
|
+
long indent_len = state->indent_len;
|
|
865
|
+
long max_nesting = state->max_nesting;
|
|
691
866
|
long depth = ++state->depth;
|
|
692
|
-
int
|
|
693
|
-
|
|
867
|
+
int j;
|
|
868
|
+
struct hash_foreach_arg arg;
|
|
869
|
+
|
|
694
870
|
if (max_nesting != 0 && depth > max_nesting) {
|
|
695
871
|
fbuffer_free(buffer);
|
|
696
872
|
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
|
|
697
873
|
}
|
|
698
874
|
fbuffer_append_char(buffer, '{');
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
for (j = 0; j < depth; j++) {
|
|
707
|
-
fbuffer_append(buffer, indent, indent_len);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
key = rb_ary_entry(keys, i);
|
|
711
|
-
key_to_s = rb_funcall(key, i_to_s, 0);
|
|
712
|
-
Check_Type(key_to_s, T_STRING);
|
|
713
|
-
generate_json(buffer, Vstate, state, key_to_s);
|
|
714
|
-
fbuffer_append(buffer, delim2, delim2_len);
|
|
715
|
-
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
|
|
716
|
-
}
|
|
875
|
+
|
|
876
|
+
arg.buffer = buffer;
|
|
877
|
+
arg.state = state;
|
|
878
|
+
arg.Vstate = Vstate;
|
|
879
|
+
arg.iter = 0;
|
|
880
|
+
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
|
|
881
|
+
|
|
717
882
|
depth = --state->depth;
|
|
718
883
|
if (object_nl) {
|
|
719
884
|
fbuffer_append(buffer, object_nl, object_nl_len);
|
|
@@ -764,16 +929,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
|
764
929
|
fbuffer_append_char(buffer, ']');
|
|
765
930
|
}
|
|
766
931
|
|
|
932
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
|
933
|
+
static int enc_utf8_compatible_p(rb_encoding *enc)
|
|
934
|
+
{
|
|
935
|
+
if (enc == rb_usascii_encoding()) return 1;
|
|
936
|
+
if (enc == rb_utf8_encoding()) return 1;
|
|
937
|
+
return 0;
|
|
938
|
+
}
|
|
939
|
+
#endif
|
|
940
|
+
|
|
767
941
|
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
|
768
942
|
{
|
|
769
943
|
fbuffer_append_char(buffer, '"');
|
|
770
944
|
#ifdef HAVE_RUBY_ENCODING_H
|
|
771
|
-
|
|
945
|
+
if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
|
|
946
|
+
obj = rb_str_export_to_enc(obj, rb_utf8_encoding());
|
|
947
|
+
}
|
|
772
948
|
#endif
|
|
773
949
|
if (state->ascii_only) {
|
|
774
|
-
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
|
950
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
|
|
775
951
|
} else {
|
|
776
|
-
convert_UTF8_to_JSON(buffer, obj);
|
|
952
|
+
convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
|
|
777
953
|
}
|
|
778
954
|
fbuffer_append_char(buffer, '"');
|
|
779
955
|
}
|
|
@@ -804,6 +980,15 @@ static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
|
|
|
804
980
|
fbuffer_append_str(buffer, tmp);
|
|
805
981
|
}
|
|
806
982
|
|
|
983
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
984
|
+
static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
|
985
|
+
{
|
|
986
|
+
if (FIXNUM_P(obj))
|
|
987
|
+
generate_json_fixnum(buffer, Vstate, state, obj);
|
|
988
|
+
else
|
|
989
|
+
generate_json_bignum(buffer, Vstate, state, obj);
|
|
990
|
+
}
|
|
991
|
+
#endif
|
|
807
992
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
|
808
993
|
{
|
|
809
994
|
double value = RFLOAT_VALUE(obj);
|
|
@@ -812,10 +997,10 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
|
|
|
812
997
|
if (!allow_nan) {
|
|
813
998
|
if (isinf(value)) {
|
|
814
999
|
fbuffer_free(buffer);
|
|
815
|
-
rb_raise(eGeneratorError, "%u: %
|
|
1000
|
+
rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
|
|
816
1001
|
} else if (isnan(value)) {
|
|
817
1002
|
fbuffer_free(buffer);
|
|
818
|
-
rb_raise(eGeneratorError, "%u: %
|
|
1003
|
+
rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
|
|
819
1004
|
}
|
|
820
1005
|
}
|
|
821
1006
|
fbuffer_append_str(buffer, tmp);
|
|
@@ -837,9 +1022,9 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
|
837
1022
|
generate_json_false(buffer, Vstate, state, obj);
|
|
838
1023
|
} else if (obj == Qtrue) {
|
|
839
1024
|
generate_json_true(buffer, Vstate, state, obj);
|
|
840
|
-
} else if (
|
|
1025
|
+
} else if (FIXNUM_P(obj)) {
|
|
841
1026
|
generate_json_fixnum(buffer, Vstate, state, obj);
|
|
842
|
-
} else if (
|
|
1027
|
+
} else if (RB_TYPE_P(obj, T_BIGNUM)) {
|
|
843
1028
|
generate_json_bignum(buffer, Vstate, state, obj);
|
|
844
1029
|
} else if (klass == rb_cFloat) {
|
|
845
1030
|
generate_json_float(buffer, Vstate, state, obj);
|
|
@@ -850,7 +1035,7 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
|
|
|
850
1035
|
} else {
|
|
851
1036
|
tmp = rb_funcall(obj, i_to_s, 0);
|
|
852
1037
|
Check_Type(tmp, T_STRING);
|
|
853
|
-
|
|
1038
|
+
generate_json_string(buffer, Vstate, state, tmp);
|
|
854
1039
|
}
|
|
855
1040
|
}
|
|
856
1041
|
|
|
@@ -871,6 +1056,7 @@ static FBuffer *cState_prepare_buffer(VALUE self)
|
|
|
871
1056
|
} else {
|
|
872
1057
|
state->object_delim2 = fbuffer_alloc(16);
|
|
873
1058
|
}
|
|
1059
|
+
if (state->space_before) fbuffer_append(state->object_delim2, state->space_before, state->space_before_len);
|
|
874
1060
|
fbuffer_append_char(state->object_delim2, ':');
|
|
875
1061
|
if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
|
|
876
1062
|
|
|
@@ -892,21 +1078,6 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
|
892
1078
|
return fbuffer_to_s(buffer);
|
|
893
1079
|
}
|
|
894
1080
|
|
|
895
|
-
/*
|
|
896
|
-
* This function returns true if string is either a JSON array or JSON object.
|
|
897
|
-
* It might suffer from false positives, e. g. syntactically incorrect JSON in
|
|
898
|
-
* the string or certain UTF-8 characters on the right hand side.
|
|
899
|
-
*/
|
|
900
|
-
static int isArrayOrObject(VALUE string)
|
|
901
|
-
{
|
|
902
|
-
long string_len = RSTRING_LEN(string);
|
|
903
|
-
char *p = RSTRING_PTR(string), *q = p + string_len - 1;
|
|
904
|
-
if (string_len < 2) return 0;
|
|
905
|
-
for (; p < q && isspace((unsigned char)*p); p++);
|
|
906
|
-
for (; q > p && isspace((unsigned char)*q); q--);
|
|
907
|
-
return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
|
|
908
|
-
}
|
|
909
|
-
|
|
910
1081
|
/*
|
|
911
1082
|
* call-seq: generate(obj)
|
|
912
1083
|
*
|
|
@@ -918,9 +1089,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
|
918
1089
|
{
|
|
919
1090
|
VALUE result = cState_partial_generate(self, obj);
|
|
920
1091
|
GET_STATE(self);
|
|
921
|
-
|
|
922
|
-
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
|
|
923
|
-
}
|
|
1092
|
+
(void)state;
|
|
924
1093
|
return result;
|
|
925
1094
|
}
|
|
926
1095
|
|
|
@@ -939,8 +1108,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
|
|
|
939
1108
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
|
940
1109
|
* generated, otherwise an exception is thrown, if these values are
|
|
941
1110
|
* encountered. This options defaults to false.
|
|
942
|
-
* * *
|
|
943
|
-
*
|
|
1111
|
+
* * *ascii_only*: true if only ASCII characters should be generated. This
|
|
1112
|
+
* option defaults to false.
|
|
944
1113
|
* * *buffer_initial_length*: sets the initial length of the generator's
|
|
945
1114
|
* internal buffer.
|
|
946
1115
|
*/
|
|
@@ -958,15 +1127,16 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
958
1127
|
/*
|
|
959
1128
|
* call-seq: initialize_copy(orig)
|
|
960
1129
|
*
|
|
961
|
-
* Initializes this object from orig if it
|
|
1130
|
+
* Initializes this object from orig if it can be duplicated/cloned and returns
|
|
962
1131
|
* it.
|
|
963
1132
|
*/
|
|
964
1133
|
static VALUE cState_init_copy(VALUE obj, VALUE orig)
|
|
965
1134
|
{
|
|
966
1135
|
JSON_Generator_State *objState, *origState;
|
|
967
1136
|
|
|
968
|
-
|
|
969
|
-
|
|
1137
|
+
if (obj == orig) return obj;
|
|
1138
|
+
GET_STATE_TO(obj, objState);
|
|
1139
|
+
GET_STATE_TO(orig, origState);
|
|
970
1140
|
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
|
|
971
1141
|
|
|
972
1142
|
MEMCPY(objState, origState, JSON_Generator_State, 1);
|
|
@@ -995,17 +1165,14 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
|
995
1165
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
|
996
1166
|
return rb_funcall(self, i_new, 1, opts);
|
|
997
1167
|
} else {
|
|
998
|
-
|
|
999
|
-
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
|
|
1000
|
-
}
|
|
1001
|
-
return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
|
|
1168
|
+
return rb_class_new_instance(0, NULL, cState);
|
|
1002
1169
|
}
|
|
1003
1170
|
}
|
|
1004
1171
|
|
|
1005
1172
|
/*
|
|
1006
1173
|
* call-seq: indent()
|
|
1007
1174
|
*
|
|
1008
|
-
*
|
|
1175
|
+
* Returns the string that is used to indent levels in the JSON text.
|
|
1009
1176
|
*/
|
|
1010
1177
|
static VALUE cState_indent(VALUE self)
|
|
1011
1178
|
{
|
|
@@ -1016,7 +1183,7 @@ static VALUE cState_indent(VALUE self)
|
|
|
1016
1183
|
/*
|
|
1017
1184
|
* call-seq: indent=(indent)
|
|
1018
1185
|
*
|
|
1019
|
-
*
|
|
1186
|
+
* Sets the string that is used to indent levels in the JSON text.
|
|
1020
1187
|
*/
|
|
1021
1188
|
static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
1022
1189
|
{
|
|
@@ -1032,7 +1199,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
|
1032
1199
|
}
|
|
1033
1200
|
} else {
|
|
1034
1201
|
if (state->indent) ruby_xfree(state->indent);
|
|
1035
|
-
state->indent =
|
|
1202
|
+
state->indent = fstrndup(RSTRING_PTR(indent), len);
|
|
1036
1203
|
state->indent_len = len;
|
|
1037
1204
|
}
|
|
1038
1205
|
return Qnil;
|
|
@@ -1041,7 +1208,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
|
1041
1208
|
/*
|
|
1042
1209
|
* call-seq: space()
|
|
1043
1210
|
*
|
|
1044
|
-
*
|
|
1211
|
+
* Returns the string that is used to insert a space between the tokens in a JSON
|
|
1045
1212
|
* string.
|
|
1046
1213
|
*/
|
|
1047
1214
|
static VALUE cState_space(VALUE self)
|
|
@@ -1053,7 +1220,7 @@ static VALUE cState_space(VALUE self)
|
|
|
1053
1220
|
/*
|
|
1054
1221
|
* call-seq: space=(space)
|
|
1055
1222
|
*
|
|
1056
|
-
*
|
|
1223
|
+
* Sets _space_ to the string that is used to insert a space between the tokens in a JSON
|
|
1057
1224
|
* string.
|
|
1058
1225
|
*/
|
|
1059
1226
|
static VALUE cState_space_set(VALUE self, VALUE space)
|
|
@@ -1070,7 +1237,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
|
1070
1237
|
}
|
|
1071
1238
|
} else {
|
|
1072
1239
|
if (state->space) ruby_xfree(state->space);
|
|
1073
|
-
state->space =
|
|
1240
|
+
state->space = fstrndup(RSTRING_PTR(space), len);
|
|
1074
1241
|
state->space_len = len;
|
|
1075
1242
|
}
|
|
1076
1243
|
return Qnil;
|
|
@@ -1079,7 +1246,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
|
1079
1246
|
/*
|
|
1080
1247
|
* call-seq: space_before()
|
|
1081
1248
|
*
|
|
1082
|
-
*
|
|
1249
|
+
* Returns the string that is used to insert a space before the ':' in JSON objects.
|
|
1083
1250
|
*/
|
|
1084
1251
|
static VALUE cState_space_before(VALUE self)
|
|
1085
1252
|
{
|
|
@@ -1090,7 +1257,7 @@ static VALUE cState_space_before(VALUE self)
|
|
|
1090
1257
|
/*
|
|
1091
1258
|
* call-seq: space_before=(space_before)
|
|
1092
1259
|
*
|
|
1093
|
-
*
|
|
1260
|
+
* Sets the string that is used to insert a space before the ':' in JSON objects.
|
|
1094
1261
|
*/
|
|
1095
1262
|
static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
1096
1263
|
{
|
|
@@ -1106,7 +1273,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
|
1106
1273
|
}
|
|
1107
1274
|
} else {
|
|
1108
1275
|
if (state->space_before) ruby_xfree(state->space_before);
|
|
1109
|
-
state->space_before =
|
|
1276
|
+
state->space_before = fstrndup(RSTRING_PTR(space_before), len);
|
|
1110
1277
|
state->space_before_len = len;
|
|
1111
1278
|
}
|
|
1112
1279
|
return Qnil;
|
|
@@ -1143,7 +1310,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
|
1143
1310
|
}
|
|
1144
1311
|
} else {
|
|
1145
1312
|
if (state->object_nl) ruby_xfree(state->object_nl);
|
|
1146
|
-
state->object_nl =
|
|
1313
|
+
state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
|
|
1147
1314
|
state->object_nl_len = len;
|
|
1148
1315
|
}
|
|
1149
1316
|
return Qnil;
|
|
@@ -1178,7 +1345,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
|
1178
1345
|
}
|
|
1179
1346
|
} else {
|
|
1180
1347
|
if (state->array_nl) ruby_xfree(state->array_nl);
|
|
1181
|
-
state->array_nl =
|
|
1348
|
+
state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
|
|
1182
1349
|
state->array_nl_len = len;
|
|
1183
1350
|
}
|
|
1184
1351
|
return Qnil;
|
|
@@ -1223,50 +1390,52 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
|
1223
1390
|
}
|
|
1224
1391
|
|
|
1225
1392
|
/*
|
|
1226
|
-
* call-seq:
|
|
1393
|
+
* call-seq: escape_slash
|
|
1227
1394
|
*
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1395
|
+
* If this boolean is true, the forward slashes will be escaped in
|
|
1396
|
+
* the json output.
|
|
1230
1397
|
*/
|
|
1231
|
-
static VALUE
|
|
1398
|
+
static VALUE cState_escape_slash(VALUE self)
|
|
1232
1399
|
{
|
|
1233
1400
|
GET_STATE(self);
|
|
1234
|
-
return state->
|
|
1401
|
+
return state->escape_slash ? Qtrue : Qfalse;
|
|
1235
1402
|
}
|
|
1236
1403
|
|
|
1237
1404
|
/*
|
|
1238
|
-
* call-seq:
|
|
1405
|
+
* call-seq: escape_slash=(depth)
|
|
1239
1406
|
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1407
|
+
* This sets whether or not the forward slashes will be escaped in
|
|
1408
|
+
* the json output.
|
|
1242
1409
|
*/
|
|
1243
|
-
static VALUE
|
|
1410
|
+
static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
|
|
1244
1411
|
{
|
|
1245
1412
|
GET_STATE(self);
|
|
1246
|
-
|
|
1413
|
+
state->escape_slash = RTEST(enable);
|
|
1414
|
+
return Qnil;
|
|
1247
1415
|
}
|
|
1248
1416
|
|
|
1249
1417
|
/*
|
|
1250
|
-
* call-seq:
|
|
1418
|
+
* call-seq: allow_nan?
|
|
1251
1419
|
*
|
|
1252
|
-
* Returns true, if
|
|
1420
|
+
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
|
|
1421
|
+
* returns false.
|
|
1253
1422
|
*/
|
|
1254
|
-
static VALUE
|
|
1423
|
+
static VALUE cState_allow_nan_p(VALUE self)
|
|
1255
1424
|
{
|
|
1256
1425
|
GET_STATE(self);
|
|
1257
|
-
return state->
|
|
1426
|
+
return state->allow_nan ? Qtrue : Qfalse;
|
|
1258
1427
|
}
|
|
1259
1428
|
|
|
1260
1429
|
/*
|
|
1261
|
-
* call-seq:
|
|
1430
|
+
* call-seq: ascii_only?
|
|
1262
1431
|
*
|
|
1263
|
-
*
|
|
1432
|
+
* Returns true, if only ASCII characters should be generated. Otherwise
|
|
1433
|
+
* returns false.
|
|
1264
1434
|
*/
|
|
1265
|
-
static VALUE
|
|
1435
|
+
static VALUE cState_ascii_only_p(VALUE self)
|
|
1266
1436
|
{
|
|
1267
1437
|
GET_STATE(self);
|
|
1268
|
-
state->
|
|
1269
|
-
return Qnil;
|
|
1438
|
+
return state->ascii_only ? Qtrue : Qfalse;
|
|
1270
1439
|
}
|
|
1271
1440
|
|
|
1272
1441
|
/*
|
|
@@ -1297,7 +1466,7 @@ static VALUE cState_depth_set(VALUE self, VALUE depth)
|
|
|
1297
1466
|
/*
|
|
1298
1467
|
* call-seq: buffer_initial_length
|
|
1299
1468
|
*
|
|
1300
|
-
* This integer returns the current
|
|
1469
|
+
* This integer returns the current initial length of the buffer.
|
|
1301
1470
|
*/
|
|
1302
1471
|
static VALUE cState_buffer_initial_length(VALUE self)
|
|
1303
1472
|
{
|
|
@@ -1326,8 +1495,13 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
|
|
|
1326
1495
|
/*
|
|
1327
1496
|
*
|
|
1328
1497
|
*/
|
|
1329
|
-
void Init_generator()
|
|
1498
|
+
void Init_generator(void)
|
|
1330
1499
|
{
|
|
1500
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
1501
|
+
rb_ext_ractor_safe(true);
|
|
1502
|
+
#endif
|
|
1503
|
+
|
|
1504
|
+
#undef rb_intern
|
|
1331
1505
|
rb_require("json/common");
|
|
1332
1506
|
|
|
1333
1507
|
mJSON = rb_define_module("JSON");
|
|
@@ -1336,6 +1510,8 @@ void Init_generator()
|
|
|
1336
1510
|
|
|
1337
1511
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
|
1338
1512
|
eNestingError = rb_path2class("JSON::NestingError");
|
|
1513
|
+
rb_gc_register_mark_object(eGeneratorError);
|
|
1514
|
+
rb_gc_register_mark_object(eNestingError);
|
|
1339
1515
|
|
|
1340
1516
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
|
1341
1517
|
rb_define_alloc_func(cState, cState_s_allocate);
|
|
@@ -1354,12 +1530,12 @@ void Init_generator()
|
|
|
1354
1530
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
|
1355
1531
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
|
1356
1532
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
|
1533
|
+
rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
|
|
1534
|
+
rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
|
|
1535
|
+
rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
|
|
1357
1536
|
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
|
1358
1537
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
|
1359
1538
|
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
|
1360
|
-
rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
|
|
1361
|
-
rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
|
|
1362
|
-
rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
|
|
1363
1539
|
rb_define_method(cState, "depth", cState_depth, 0);
|
|
1364
1540
|
rb_define_method(cState, "depth=", cState_depth_set, 1);
|
|
1365
1541
|
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
|
|
@@ -1379,10 +1555,15 @@ void Init_generator()
|
|
|
1379
1555
|
rb_define_method(mHash, "to_json", mHash_to_json, -1);
|
|
1380
1556
|
mArray = rb_define_module_under(mGeneratorMethods, "Array");
|
|
1381
1557
|
rb_define_method(mArray, "to_json", mArray_to_json, -1);
|
|
1558
|
+
#ifdef RUBY_INTEGER_UNIFICATION
|
|
1559
|
+
mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
|
|
1560
|
+
rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
|
|
1561
|
+
#else
|
|
1382
1562
|
mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
|
|
1383
1563
|
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
|
|
1384
1564
|
mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
|
|
1385
1565
|
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
|
|
1566
|
+
#endif
|
|
1386
1567
|
mFloat = rb_define_module_under(mGeneratorMethods, "Float");
|
|
1387
1568
|
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
|
|
1388
1569
|
mString = rb_define_module_under(mGeneratorMethods, "String");
|
|
@@ -1399,7 +1580,6 @@ void Init_generator()
|
|
|
1399
1580
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
|
1400
1581
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
|
1401
1582
|
|
|
1402
|
-
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
|
1403
1583
|
i_to_s = rb_intern("to_s");
|
|
1404
1584
|
i_to_json = rb_intern("to_json");
|
|
1405
1585
|
i_new = rb_intern("new");
|
|
@@ -1409,9 +1589,9 @@ void Init_generator()
|
|
|
1409
1589
|
i_object_nl = rb_intern("object_nl");
|
|
1410
1590
|
i_array_nl = rb_intern("array_nl");
|
|
1411
1591
|
i_max_nesting = rb_intern("max_nesting");
|
|
1592
|
+
i_escape_slash = rb_intern("escape_slash");
|
|
1412
1593
|
i_allow_nan = rb_intern("allow_nan");
|
|
1413
1594
|
i_ascii_only = rb_intern("ascii_only");
|
|
1414
|
-
i_quirks_mode = rb_intern("quirks_mode");
|
|
1415
1595
|
i_depth = rb_intern("depth");
|
|
1416
1596
|
i_buffer_initial_length = rb_intern("buffer_initial_length");
|
|
1417
1597
|
i_pack = rb_intern("pack");
|
|
@@ -1425,11 +1605,4 @@ void Init_generator()
|
|
|
1425
1605
|
i_match = rb_intern("match");
|
|
1426
1606
|
i_keys = rb_intern("keys");
|
|
1427
1607
|
i_dup = rb_intern("dup");
|
|
1428
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
|
1429
|
-
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
|
|
1430
|
-
i_encoding = rb_intern("encoding");
|
|
1431
|
-
i_encode = rb_intern("encode");
|
|
1432
|
-
#endif
|
|
1433
|
-
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
|
|
1434
|
-
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
|
1435
1608
|
}
|