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.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +262 -87
  3. data/{COPYING-json-jruby → LICENSE} +5 -6
  4. data/README.md +425 -0
  5. data/VERSION +1 -1
  6. data/ext/json/ext/fbuffer/fbuffer.h +10 -4
  7. data/ext/json/ext/generator/extconf.rb +0 -10
  8. data/ext/json/ext/generator/generator.c +308 -135
  9. data/ext/json/ext/generator/generator.h +35 -9
  10. data/ext/json/ext/parser/extconf.rb +25 -6
  11. data/ext/json/ext/parser/parser.c +3044 -1901
  12. data/ext/json/ext/parser/parser.h +29 -10
  13. data/ext/json/ext/parser/parser.rl +270 -211
  14. data/ext/json/extconf.rb +3 -0
  15. data/json.gemspec +57 -27
  16. data/lib/json/add/bigdecimal.rb +3 -2
  17. data/lib/json/add/complex.rb +9 -3
  18. data/lib/json/add/core.rb +1 -0
  19. data/lib/json/add/date.rb +1 -1
  20. data/lib/json/add/date_time.rb +1 -1
  21. data/lib/json/add/exception.rb +1 -1
  22. data/lib/json/add/ostruct.rb +3 -3
  23. data/lib/json/add/range.rb +1 -1
  24. data/lib/json/add/rational.rb +8 -3
  25. data/lib/json/add/regexp.rb +3 -3
  26. data/lib/json/add/set.rb +29 -0
  27. data/lib/json/add/struct.rb +1 -1
  28. data/lib/json/add/symbol.rb +1 -1
  29. data/lib/json/add/time.rb +2 -2
  30. data/lib/json/common.rb +383 -167
  31. data/lib/json/ext.rb +0 -6
  32. data/lib/json/generic_object.rb +5 -4
  33. data/lib/json/pure/generator.rb +83 -126
  34. data/lib/json/pure/parser.rb +63 -85
  35. data/lib/json/pure.rb +2 -8
  36. data/lib/json/version.rb +2 -1
  37. data/lib/json.rb +550 -29
  38. metadata +29 -136
  39. data/.gitignore +0 -12
  40. data/.travis.yml +0 -20
  41. data/COPYING +0 -58
  42. data/GPL +0 -340
  43. data/Gemfile +0 -11
  44. data/README-json-jruby.markdown +0 -33
  45. data/README.rdoc +0 -358
  46. data/Rakefile +0 -412
  47. data/TODO +0 -1
  48. data/data/example.json +0 -1
  49. data/data/index.html +0 -38
  50. data/data/prototype.js +0 -4184
  51. data/diagrams/.keep +0 -0
  52. data/install.rb +0 -23
  53. data/java/src/json/ext/ByteListTranscoder.java +0 -167
  54. data/java/src/json/ext/Generator.java +0 -444
  55. data/java/src/json/ext/GeneratorMethods.java +0 -232
  56. data/java/src/json/ext/GeneratorService.java +0 -43
  57. data/java/src/json/ext/GeneratorState.java +0 -543
  58. data/java/src/json/ext/OptionsReader.java +0 -114
  59. data/java/src/json/ext/Parser.java +0 -2644
  60. data/java/src/json/ext/Parser.rl +0 -968
  61. data/java/src/json/ext/ParserService.java +0 -35
  62. data/java/src/json/ext/RuntimeInfo.java +0 -121
  63. data/java/src/json/ext/StringDecoder.java +0 -167
  64. data/java/src/json/ext/StringEncoder.java +0 -106
  65. data/java/src/json/ext/Utils.java +0 -89
  66. data/json-java.gemspec +0 -23
  67. data/json_pure.gemspec +0 -39
  68. data/lib/json/ext/.keep +0 -0
  69. data/tests/fixtures/fail1.json +0 -1
  70. data/tests/fixtures/fail10.json +0 -1
  71. data/tests/fixtures/fail11.json +0 -1
  72. data/tests/fixtures/fail12.json +0 -1
  73. data/tests/fixtures/fail13.json +0 -1
  74. data/tests/fixtures/fail14.json +0 -1
  75. data/tests/fixtures/fail18.json +0 -1
  76. data/tests/fixtures/fail19.json +0 -1
  77. data/tests/fixtures/fail2.json +0 -1
  78. data/tests/fixtures/fail20.json +0 -1
  79. data/tests/fixtures/fail21.json +0 -1
  80. data/tests/fixtures/fail22.json +0 -1
  81. data/tests/fixtures/fail23.json +0 -1
  82. data/tests/fixtures/fail24.json +0 -1
  83. data/tests/fixtures/fail25.json +0 -1
  84. data/tests/fixtures/fail27.json +0 -2
  85. data/tests/fixtures/fail28.json +0 -2
  86. data/tests/fixtures/fail3.json +0 -1
  87. data/tests/fixtures/fail4.json +0 -1
  88. data/tests/fixtures/fail5.json +0 -1
  89. data/tests/fixtures/fail6.json +0 -1
  90. data/tests/fixtures/fail7.json +0 -1
  91. data/tests/fixtures/fail8.json +0 -1
  92. data/tests/fixtures/fail9.json +0 -1
  93. data/tests/fixtures/pass1.json +0 -56
  94. data/tests/fixtures/pass15.json +0 -1
  95. data/tests/fixtures/pass16.json +0 -1
  96. data/tests/fixtures/pass17.json +0 -1
  97. data/tests/fixtures/pass2.json +0 -1
  98. data/tests/fixtures/pass26.json +0 -1
  99. data/tests/fixtures/pass3.json +0 -6
  100. data/tests/setup_variant.rb +0 -11
  101. data/tests/test_json.rb +0 -545
  102. data/tests/test_json_addition.rb +0 -196
  103. data/tests/test_json_encoding.rb +0 -65
  104. data/tests/test_json_fixtures.rb +0 -35
  105. data/tests/test_json_generate.rb +0 -322
  106. data/tests/test_json_generic_object.rb +0 -75
  107. data/tests/test_json_string_matching.rb +0 -39
  108. data/tests/test_json_unicode.rb +0 -72
  109. data/tools/fuzz.rb +0 -139
  110. 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, mFixnum, mBignum, mFloat, mString, mString_Extend,
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, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
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
- i_quirks_mode, i_pack, i_unpack, i_create_id, i_extend, i_key_p,
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 = trailingBytesForUTF8[c] + 1;
278
- if (end + clen > len) {
279
- rb_raise(rb_path2class("JSON::GeneratorError"),
280
- "partial character in source, but hit end");
281
- }
282
- if (!isLegalUTF8((UTF8 *) p, clen)) {
283
- rb_raise(rb_path2class("JSON::GeneratorError"),
284
- "source sequence is illegal/malformed utf-8");
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
- memccpy(result, ptr, 0, len);
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(JSON_Generator_State *state)
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 JSON_Generator_State *State_allocate()
602
+ static size_t State_memsize(const void *ptr)
503
603
  {
504
- JSON_Generator_State *state = ALLOC(JSON_Generator_State);
505
- MEMZERO(state, JSON_Generator_State, 1);
506
- return state;
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 = State_allocate();
512
- return Data_Wrap_Struct(klass, NULL, State_free, state);
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(i_quirks_mode));
605
- state->quirks_mode = RTEST(tmp);
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
- * Return the value returned by method +name+.
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 rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
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
- * Set the attribute name to value.
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
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
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 i, j;
693
- VALUE key, key_to_s, keys;
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
- keys = rb_funcall(obj, i_keys, 0);
700
- for(i = 0; i < RARRAY_LEN(keys); i++) {
701
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
702
- if (object_nl) {
703
- fbuffer_append(buffer, object_nl, object_nl_len);
704
- }
705
- if (indent) {
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
- obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
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: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
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: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
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 (klass == rb_cFixnum) {
1025
+ } else if (FIXNUM_P(obj)) {
841
1026
  generate_json_fixnum(buffer, Vstate, state, obj);
842
- } else if (klass == rb_cBignum) {
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
- generate_json(buffer, Vstate, state, tmp);
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
- if (!state->quirks_mode && !isArrayOrObject(result)) {
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
- * * *quirks_mode*: Enables quirks_mode for parser, that is for example
943
- * generating single JSON values instead of documents is possible.
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 to be duplicated/cloned and returns
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
- Data_Get_Struct(obj, JSON_Generator_State, objState);
969
- Data_Get_Struct(orig, JSON_Generator_State, origState);
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
- if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
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
- * This string is used to indent levels in the JSON text.
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
- * This string is used to indent levels in the JSON text.
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 = strdup(RSTRING_PTR(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
- * This string is used to insert a space between the tokens in a JSON
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
- * This string is used to insert a space between the tokens in a JSON
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 = strdup(RSTRING_PTR(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
- * This string is used to insert a space before the ':' in JSON objects.
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
- * This string is used to insert a space before the ':' in JSON objects.
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 = strdup(RSTRING_PTR(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 = strdup(RSTRING_PTR(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 = strdup(RSTRING_PTR(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: allow_nan?
1393
+ * call-seq: escape_slash
1227
1394
  *
1228
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1229
- * returns false.
1395
+ * If this boolean is true, the forward slashes will be escaped in
1396
+ * the json output.
1230
1397
  */
1231
- static VALUE cState_allow_nan_p(VALUE self)
1398
+ static VALUE cState_escape_slash(VALUE self)
1232
1399
  {
1233
1400
  GET_STATE(self);
1234
- return state->allow_nan ? Qtrue : Qfalse;
1401
+ return state->escape_slash ? Qtrue : Qfalse;
1235
1402
  }
1236
1403
 
1237
1404
  /*
1238
- * call-seq: ascii_only?
1405
+ * call-seq: escape_slash=(depth)
1239
1406
  *
1240
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1241
- * returns false.
1407
+ * This sets whether or not the forward slashes will be escaped in
1408
+ * the json output.
1242
1409
  */
1243
- static VALUE cState_ascii_only_p(VALUE self)
1410
+ static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
1244
1411
  {
1245
1412
  GET_STATE(self);
1246
- return state->ascii_only ? Qtrue : Qfalse;
1413
+ state->escape_slash = RTEST(enable);
1414
+ return Qnil;
1247
1415
  }
1248
1416
 
1249
1417
  /*
1250
- * call-seq: quirks_mode?
1418
+ * call-seq: allow_nan?
1251
1419
  *
1252
- * Returns true, if quirks mode is enabled. Otherwise returns false.
1420
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1421
+ * returns false.
1253
1422
  */
1254
- static VALUE cState_quirks_mode_p(VALUE self)
1423
+ static VALUE cState_allow_nan_p(VALUE self)
1255
1424
  {
1256
1425
  GET_STATE(self);
1257
- return state->quirks_mode ? Qtrue : Qfalse;
1426
+ return state->allow_nan ? Qtrue : Qfalse;
1258
1427
  }
1259
1428
 
1260
1429
  /*
1261
- * call-seq: quirks_mode=(enable)
1430
+ * call-seq: ascii_only?
1262
1431
  *
1263
- * If set to true, enables the quirks_mode mode.
1432
+ * Returns true, if only ASCII characters should be generated. Otherwise
1433
+ * returns false.
1264
1434
  */
1265
- static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
1435
+ static VALUE cState_ascii_only_p(VALUE self)
1266
1436
  {
1267
1437
  GET_STATE(self);
1268
- state->quirks_mode = RTEST(enable);
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 inital length of the buffer.
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
  }