json 1.8.6 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +292 -96
  3. data/LICENSE +56 -0
  4. data/README.md +185 -114
  5. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  6. data/ext/json/ext/generator/generator.c +328 -117
  7. data/ext/json/ext/generator/generator.h +8 -8
  8. data/ext/json/ext/parser/extconf.rb +29 -0
  9. data/ext/json/ext/parser/parser.c +540 -569
  10. data/ext/json/ext/parser/parser.h +10 -6
  11. data/ext/json/ext/parser/parser.rl +269 -261
  12. data/ext/json/extconf.rb +1 -1
  13. data/json.gemspec +0 -0
  14. data/lib/json/add/bigdecimal.rb +40 -10
  15. data/lib/json/add/complex.rb +32 -9
  16. data/lib/json/add/core.rb +1 -0
  17. data/lib/json/add/date.rb +27 -7
  18. data/lib/json/add/date_time.rb +26 -9
  19. data/lib/json/add/exception.rb +25 -7
  20. data/lib/json/add/ostruct.rb +32 -9
  21. data/lib/json/add/range.rb +33 -8
  22. data/lib/json/add/rational.rb +30 -8
  23. data/lib/json/add/regexp.rb +28 -10
  24. data/lib/json/add/set.rb +48 -0
  25. data/lib/json/add/struct.rb +29 -7
  26. data/lib/json/add/symbol.rb +28 -5
  27. data/lib/json/add/time.rb +27 -6
  28. data/lib/json/common.rb +402 -188
  29. data/lib/json/ext.rb +0 -6
  30. data/lib/json/generic_object.rb +11 -6
  31. data/lib/json/pure/generator.rb +120 -137
  32. data/lib/json/pure/parser.rb +64 -86
  33. data/lib/json/pure.rb +2 -8
  34. data/lib/json/version.rb +2 -1
  35. data/lib/json.rb +559 -29
  36. metadata +18 -129
  37. data/.gitignore +0 -17
  38. data/.travis.yml +0 -18
  39. data/Gemfile +0 -7
  40. data/README-json-jruby.markdown +0 -33
  41. data/Rakefile +0 -402
  42. data/TODO +0 -1
  43. data/VERSION +0 -1
  44. data/data/example.json +0 -1
  45. data/data/index.html +0 -38
  46. data/data/prototype.js +0 -4184
  47. data/diagrams/.keep +0 -0
  48. data/install.rb +0 -23
  49. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  50. data/java/src/json/ext/Generator.java +0 -446
  51. data/java/src/json/ext/GeneratorMethods.java +0 -231
  52. data/java/src/json/ext/GeneratorService.java +0 -42
  53. data/java/src/json/ext/GeneratorState.java +0 -542
  54. data/java/src/json/ext/OptionsReader.java +0 -113
  55. data/java/src/json/ext/Parser.java +0 -2644
  56. data/java/src/json/ext/Parser.rl +0 -968
  57. data/java/src/json/ext/ParserService.java +0 -34
  58. data/java/src/json/ext/RuntimeInfo.java +0 -120
  59. data/java/src/json/ext/StringDecoder.java +0 -166
  60. data/java/src/json/ext/StringEncoder.java +0 -111
  61. data/java/src/json/ext/Utils.java +0 -88
  62. data/json-java.gemspec +0 -38
  63. data/json_pure.gemspec +0 -37
  64. data/lib/json/ext/.keep +0 -0
  65. data/tests/fixtures/fail1.json +0 -1
  66. data/tests/fixtures/fail10.json +0 -1
  67. data/tests/fixtures/fail11.json +0 -1
  68. data/tests/fixtures/fail12.json +0 -1
  69. data/tests/fixtures/fail13.json +0 -1
  70. data/tests/fixtures/fail14.json +0 -1
  71. data/tests/fixtures/fail18.json +0 -1
  72. data/tests/fixtures/fail19.json +0 -1
  73. data/tests/fixtures/fail2.json +0 -1
  74. data/tests/fixtures/fail20.json +0 -1
  75. data/tests/fixtures/fail21.json +0 -1
  76. data/tests/fixtures/fail22.json +0 -1
  77. data/tests/fixtures/fail23.json +0 -1
  78. data/tests/fixtures/fail24.json +0 -1
  79. data/tests/fixtures/fail25.json +0 -1
  80. data/tests/fixtures/fail27.json +0 -2
  81. data/tests/fixtures/fail28.json +0 -2
  82. data/tests/fixtures/fail3.json +0 -1
  83. data/tests/fixtures/fail4.json +0 -1
  84. data/tests/fixtures/fail5.json +0 -1
  85. data/tests/fixtures/fail6.json +0 -1
  86. data/tests/fixtures/fail7.json +0 -1
  87. data/tests/fixtures/fail8.json +0 -1
  88. data/tests/fixtures/fail9.json +0 -1
  89. data/tests/fixtures/pass1.json +0 -56
  90. data/tests/fixtures/pass15.json +0 -1
  91. data/tests/fixtures/pass16.json +0 -1
  92. data/tests/fixtures/pass17.json +0 -1
  93. data/tests/fixtures/pass2.json +0 -1
  94. data/tests/fixtures/pass26.json +0 -1
  95. data/tests/fixtures/pass3.json +0 -6
  96. data/tests/setup_variant.rb +0 -11
  97. data/tests/test_json.rb +0 -519
  98. data/tests/test_json_addition.rb +0 -196
  99. data/tests/test_json_encoding.rb +0 -65
  100. data/tests/test_json_fixtures.rb +0 -35
  101. data/tests/test_json_generate.rb +0 -348
  102. data/tests/test_json_generic_object.rb +0 -75
  103. data/tests/test_json_string_matching.rb +0 -39
  104. data/tests/test_json_unicode.rb +0 -72
  105. data/tools/diff.sh +0 -18
  106. data/tools/fuzz.rb +0 -139
  107. data/tools/server.rb +0 -62
@@ -1,11 +1,6 @@
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
5
  mHash, mArray,
11
6
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -15,14 +10,13 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
15
10
  #endif
16
11
  mFloat, mString, mString_Extend,
17
12
  mTrueClass, mFalseClass, mNilClass, eGeneratorError,
18
- eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
19
- i_SAFE_STATE_PROTOTYPE;
13
+ eNestingError;
20
14
 
21
15
  static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
22
16
  i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
23
- 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,
24
18
  i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
25
- i_buffer_initial_length, i_dup;
19
+ i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
26
20
 
27
21
  /*
28
22
  * Copyright 2001-2004 Unicode, Inc.
@@ -130,7 +124,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
130
124
 
131
125
  /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
132
126
  * and control characters are JSON escaped. */
133
- static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
127
+ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe)
134
128
  {
135
129
  const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
136
130
  const UTF8 *sourceEnd = source + RSTRING_LEN(string);
@@ -180,6 +174,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
180
174
  case '"':
181
175
  fbuffer_append(buffer, "\\\"", 2);
182
176
  break;
177
+ case '/':
178
+ if(script_safe) {
179
+ fbuffer_append(buffer, "\\/", 2);
180
+ break;
181
+ }
183
182
  default:
184
183
  fbuffer_append_char(buffer, (char)ch);
185
184
  break;
@@ -222,13 +221,14 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
222
221
  unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
223
222
  }
224
223
  }
224
+ RB_GC_GUARD(string);
225
225
  }
226
226
 
227
227
  /* Converts string to a JSON string in FBuffer buffer, where only the
228
228
  * characters required by the JSON standard are JSON escaped. The remaining
229
229
  * characters (should be UTF8) are just passed through and appended to the
230
230
  * result. */
231
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
231
+ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe)
232
232
  {
233
233
  const char *ptr = RSTRING_PTR(string), *p;
234
234
  unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
@@ -236,6 +236,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
236
236
  int escape_len;
237
237
  unsigned char c;
238
238
  char buf[6] = { '\\', 'u' };
239
+ int ascii_only = rb_enc_str_asciionly_p(string);
239
240
 
240
241
  for (start = 0, end = 0; end < len;) {
241
242
  p = ptr + end;
@@ -278,16 +279,41 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
278
279
  escape = "\\\"";
279
280
  escape_len = 2;
280
281
  break;
282
+ case '/':
283
+ if(script_safe) {
284
+ escape = "\\/";
285
+ escape_len = 2;
286
+ break;
287
+ }
281
288
  default:
282
289
  {
283
- unsigned short clen = trailingBytesForUTF8[c] + 1;
284
- if (end + clen > len) {
285
- rb_raise(rb_path2class("JSON::GeneratorError"),
286
- "partial character in source, but hit end");
287
- }
288
- if (!isLegalUTF8((UTF8 *) p, clen)) {
289
- rb_raise(rb_path2class("JSON::GeneratorError"),
290
- "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
+
298
+ if (script_safe && c == 0xE2) {
299
+ unsigned char c2 = (unsigned char) *(p+1);
300
+ unsigned char c3 = (unsigned char) *(p+2);
301
+ if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) {
302
+ fbuffer_append(buffer, ptr + start, end - start);
303
+ start = end = (end + clen);
304
+ if (c3 == 0xA8) {
305
+ fbuffer_append(buffer, "\\u2028", 6);
306
+ } else {
307
+ fbuffer_append(buffer, "\\u2029", 6);
308
+ }
309
+ continue;
310
+ }
311
+ }
312
+
313
+ if (!isLegalUTF8((UTF8 *) p, clen)) {
314
+ rb_raise(rb_path2class("JSON::GeneratorError"),
315
+ "source sequence is illegal/malformed utf-8");
316
+ }
291
317
  }
292
318
  end += clen;
293
319
  }
@@ -307,7 +333,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
307
333
  char *result;
308
334
  if (len <= 0) return NULL;
309
335
  result = ALLOC_N(char, len);
310
- memccpy(result, ptr, 0, len);
336
+ memcpy(result, ptr, len);
311
337
  return result;
312
338
  }
313
339
 
@@ -323,6 +349,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
323
349
  *
324
350
  */
325
351
 
352
+ /* Explanation of the following: that's the only way to not pollute
353
+ * standard library's docs with GeneratorMethods::<ClassName> which
354
+ * are uninformative and take a large place in a list of classes
355
+ */
356
+
357
+ /*
358
+ * Document-module: JSON::Ext::Generator::GeneratorMethods
359
+ * :nodoc:
360
+ */
361
+
362
+ /*
363
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Array
364
+ * :nodoc:
365
+ */
366
+
367
+ /*
368
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
369
+ * :nodoc:
370
+ */
371
+
372
+ /*
373
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
374
+ * :nodoc:
375
+ */
376
+
377
+ /*
378
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
379
+ * :nodoc:
380
+ */
381
+
382
+ /*
383
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Float
384
+ * :nodoc:
385
+ */
386
+
387
+ /*
388
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
389
+ * :nodoc:
390
+ */
391
+
392
+ /*
393
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
394
+ * :nodoc:
395
+ */
396
+
397
+ /*
398
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
399
+ * :nodoc:
400
+ */
401
+
402
+ /*
403
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Object
404
+ * :nodoc:
405
+ */
406
+
407
+ /*
408
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String
409
+ * :nodoc:
410
+ */
411
+
412
+ /*
413
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
414
+ * :nodoc:
415
+ */
416
+
417
+ /*
418
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
419
+ * :nodoc:
420
+ */
421
+
326
422
  /*
327
423
  * call-seq: to_json(state = nil)
328
424
  *
@@ -398,6 +494,7 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
398
494
  */
399
495
  static VALUE mString_included_s(VALUE self, VALUE modul) {
400
496
  VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
497
+ rb_call_super(1, &modul);
401
498
  return result;
402
499
  }
403
500
 
@@ -534,13 +631,18 @@ static size_t State_memsize(const void *ptr)
534
631
  return size;
535
632
  }
536
633
 
634
+ #ifndef HAVE_RB_EXT_RACTOR_SAFE
635
+ # undef RUBY_TYPED_FROZEN_SHAREABLE
636
+ # define RUBY_TYPED_FROZEN_SHAREABLE 0
637
+ #endif
638
+
537
639
  #ifdef NEW_TYPEDDATA_WRAPPER
538
640
  static const rb_data_type_t JSON_Generator_State_type = {
539
641
  "JSON/Generator/State",
540
642
  {NULL, State_free, State_memsize,},
541
643
  #ifdef RUBY_TYPED_FREE_IMMEDIATELY
542
644
  0, 0,
543
- RUBY_TYPED_FREE_IMMEDIATELY,
645
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
544
646
  #endif
545
647
  };
546
648
  #endif
@@ -641,8 +743,14 @@ static VALUE cState_configure(VALUE self, VALUE opts)
641
743
  state->allow_nan = RTEST(tmp);
642
744
  tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
643
745
  state->ascii_only = RTEST(tmp);
644
- tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
645
- state->quirks_mode = RTEST(tmp);
746
+ tmp = rb_hash_aref(opts, ID2SYM(i_script_safe));
747
+ state->script_safe = RTEST(tmp);
748
+ if (!state->script_safe) {
749
+ tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
750
+ state->script_safe = RTEST(tmp);
751
+ }
752
+ tmp = rb_hash_aref(opts, ID2SYM(i_strict));
753
+ state->strict = RTEST(tmp);
646
754
  return self;
647
755
  }
648
756
 
@@ -676,8 +784,9 @@ static VALUE cState_to_h(VALUE self)
676
784
  rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
677
785
  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
678
786
  rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
679
- rb_hash_aset(result, ID2SYM(i_quirks_mode), state->quirks_mode ? Qtrue : Qfalse);
680
787
  rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
788
+ rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
789
+ rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
681
790
  rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
682
791
  rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
683
792
  return result;
@@ -694,7 +803,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
694
803
  if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
695
804
  return rb_funcall(self, i_send, 1, name);
696
805
  } else {
697
- return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
806
+ return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
698
807
  }
699
808
  }
700
809
 
@@ -717,43 +826,82 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
717
826
  return Qnil;
718
827
  }
719
828
 
720
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
829
+ struct hash_foreach_arg {
830
+ FBuffer *buffer;
831
+ JSON_Generator_State *state;
832
+ VALUE Vstate;
833
+ int iter;
834
+ };
835
+
836
+ static int
837
+ json_object_i(VALUE key, VALUE val, VALUE _arg)
721
838
  {
839
+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
840
+ FBuffer *buffer = arg->buffer;
841
+ JSON_Generator_State *state = arg->state;
842
+ VALUE Vstate = arg->Vstate;
843
+
722
844
  char *object_nl = state->object_nl;
723
845
  long object_nl_len = state->object_nl_len;
724
846
  char *indent = state->indent;
725
847
  long indent_len = state->indent_len;
726
- long max_nesting = state->max_nesting;
727
848
  char *delim = FBUFFER_PTR(state->object_delim);
728
849
  long delim_len = FBUFFER_LEN(state->object_delim);
729
850
  char *delim2 = FBUFFER_PTR(state->object_delim2);
730
851
  long delim2_len = FBUFFER_LEN(state->object_delim2);
852
+ long depth = state->depth;
853
+ int j;
854
+ VALUE klass, key_to_s;
855
+
856
+ if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
857
+ if (object_nl) {
858
+ fbuffer_append(buffer, object_nl, object_nl_len);
859
+ }
860
+ if (indent) {
861
+ for (j = 0; j < depth; j++) {
862
+ fbuffer_append(buffer, indent, indent_len);
863
+ }
864
+ }
865
+
866
+ klass = CLASS_OF(key);
867
+ if (klass == rb_cString) {
868
+ key_to_s = key;
869
+ } else if (klass == rb_cSymbol) {
870
+ key_to_s = rb_sym2str(key);
871
+ } else {
872
+ key_to_s = rb_funcall(key, i_to_s, 0);
873
+ }
874
+ Check_Type(key_to_s, T_STRING);
875
+ generate_json(buffer, Vstate, state, key_to_s);
876
+ fbuffer_append(buffer, delim2, delim2_len);
877
+ generate_json(buffer, Vstate, state, val);
878
+
879
+ arg->iter++;
880
+ return ST_CONTINUE;
881
+ }
882
+
883
+ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
884
+ {
885
+ char *object_nl = state->object_nl;
886
+ long object_nl_len = state->object_nl_len;
887
+ char *indent = state->indent;
888
+ long indent_len = state->indent_len;
889
+ long max_nesting = state->max_nesting;
731
890
  long depth = ++state->depth;
732
- int i, j;
733
- VALUE key, key_to_s, keys;
891
+ int j;
892
+ struct hash_foreach_arg arg;
893
+
734
894
  if (max_nesting != 0 && depth > max_nesting) {
735
- fbuffer_free(buffer);
736
895
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
737
896
  }
738
897
  fbuffer_append_char(buffer, '{');
739
- keys = rb_funcall(obj, i_keys, 0);
740
- for(i = 0; i < RARRAY_LEN(keys); i++) {
741
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
742
- if (object_nl) {
743
- fbuffer_append(buffer, object_nl, object_nl_len);
744
- }
745
- if (indent) {
746
- for (j = 0; j < depth; j++) {
747
- fbuffer_append(buffer, indent, indent_len);
748
- }
749
- }
750
- key = rb_ary_entry(keys, i);
751
- key_to_s = rb_funcall(key, i_to_s, 0);
752
- Check_Type(key_to_s, T_STRING);
753
- generate_json(buffer, Vstate, state, key_to_s);
754
- fbuffer_append(buffer, delim2, delim2_len);
755
- generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
756
- }
898
+
899
+ arg.buffer = buffer;
900
+ arg.state = state;
901
+ arg.Vstate = Vstate;
902
+ arg.iter = 0;
903
+ rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
904
+
757
905
  depth = --state->depth;
758
906
  if (object_nl) {
759
907
  fbuffer_append(buffer, object_nl, object_nl_len);
@@ -778,7 +926,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
778
926
  long depth = ++state->depth;
779
927
  int i, j;
780
928
  if (max_nesting != 0 && depth > max_nesting) {
781
- fbuffer_free(buffer);
782
929
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
783
930
  }
784
931
  fbuffer_append_char(buffer, '[');
@@ -804,16 +951,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
804
951
  fbuffer_append_char(buffer, ']');
805
952
  }
806
953
 
954
+ #ifdef HAVE_RUBY_ENCODING_H
955
+ static int enc_utf8_compatible_p(rb_encoding *enc)
956
+ {
957
+ if (enc == rb_usascii_encoding()) return 1;
958
+ if (enc == rb_utf8_encoding()) return 1;
959
+ return 0;
960
+ }
961
+ #endif
962
+
807
963
  static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
808
964
  {
809
965
  fbuffer_append_char(buffer, '"');
810
966
  #ifdef HAVE_RUBY_ENCODING_H
811
- obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
967
+ if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
968
+ obj = rb_str_export_to_enc(obj, rb_utf8_encoding());
969
+ }
812
970
  #endif
813
971
  if (state->ascii_only) {
814
- convert_UTF8_to_JSON_ASCII(buffer, obj);
972
+ convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe);
815
973
  } else {
816
- convert_UTF8_to_JSON(buffer, obj);
974
+ convert_UTF8_to_JSON(buffer, obj, state->script_safe);
817
975
  }
818
976
  fbuffer_append_char(buffer, '"');
819
977
  }
@@ -853,7 +1011,6 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
853
1011
  generate_json_bignum(buffer, Vstate, state, obj);
854
1012
  }
855
1013
  #endif
856
-
857
1014
  static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
858
1015
  {
859
1016
  double value = RFLOAT_VALUE(obj);
@@ -861,11 +1018,9 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
861
1018
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
862
1019
  if (!allow_nan) {
863
1020
  if (isinf(value)) {
864
- fbuffer_free(buffer);
865
- rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
1021
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
866
1022
  } else if (isnan(value)) {
867
- fbuffer_free(buffer);
868
- rb_raise(eGeneratorError, "%u: %"PRIsVALUE" not allowed in JSON", __LINE__, RB_OBJ_STRING(tmp));
1023
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
869
1024
  }
870
1025
  }
871
1026
  fbuffer_append_str(buffer, tmp);
@@ -893,6 +1048,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
893
1048
  generate_json_bignum(buffer, Vstate, state, obj);
894
1049
  } else if (klass == rb_cFloat) {
895
1050
  generate_json_float(buffer, Vstate, state, obj);
1051
+ } else if (state->strict) {
1052
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
896
1053
  } else if (rb_respond_to(obj, i_to_json)) {
897
1054
  tmp = rb_funcall(obj, i_to_json, 1, Vstate);
898
1055
  Check_Type(tmp, T_STRING);
@@ -935,27 +1092,46 @@ static FBuffer *cState_prepare_buffer(VALUE self)
935
1092
  return buffer;
936
1093
  }
937
1094
 
1095
+ struct generate_json_data {
1096
+ FBuffer *buffer;
1097
+ VALUE vstate;
1098
+ JSON_Generator_State *state;
1099
+ VALUE obj;
1100
+ };
1101
+
1102
+ static VALUE generate_json_try(VALUE d)
1103
+ {
1104
+ struct generate_json_data *data = (struct generate_json_data *)d;
1105
+
1106
+ generate_json(data->buffer, data->vstate, data->state, data->obj);
1107
+
1108
+ return Qnil;
1109
+ }
1110
+
1111
+ static VALUE generate_json_rescue(VALUE d, VALUE exc)
1112
+ {
1113
+ struct generate_json_data *data = (struct generate_json_data *)d;
1114
+ fbuffer_free(data->buffer);
1115
+
1116
+ rb_exc_raise(exc);
1117
+
1118
+ return Qundef;
1119
+ }
1120
+
938
1121
  static VALUE cState_partial_generate(VALUE self, VALUE obj)
939
1122
  {
940
1123
  FBuffer *buffer = cState_prepare_buffer(self);
941
1124
  GET_STATE(self);
942
- generate_json(buffer, self, state, obj);
943
- return fbuffer_to_s(buffer);
944
- }
945
1125
 
946
- /*
947
- * This function returns true if string is either a JSON array or JSON object.
948
- * It might suffer from false positives, e. g. syntactically incorrect JSON in
949
- * the string or certain UTF-8 characters on the right hand side.
950
- */
951
- static int isArrayOrObject(VALUE string)
952
- {
953
- long string_len = RSTRING_LEN(string);
954
- char *p = RSTRING_PTR(string), *q = p + string_len - 1;
955
- if (string_len < 2) return 0;
956
- for (; p < q && isspace((unsigned char)*p); p++);
957
- for (; q > p && isspace((unsigned char)*q); q--);
958
- return (*p == '[' && *q == ']') || (*p == '{' && *q == '}');
1126
+ struct generate_json_data data = {
1127
+ .buffer = buffer,
1128
+ .vstate = self,
1129
+ .state = state,
1130
+ .obj = obj
1131
+ };
1132
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1133
+
1134
+ return fbuffer_to_s(buffer);
959
1135
  }
960
1136
 
961
1137
  /*
@@ -969,9 +1145,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
969
1145
  {
970
1146
  VALUE result = cState_partial_generate(self, obj);
971
1147
  GET_STATE(self);
972
- if (!state->quirks_mode && !isArrayOrObject(result)) {
973
- rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
974
- }
1148
+ (void)state;
975
1149
  return result;
976
1150
  }
977
1151
 
@@ -990,8 +1164,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
990
1164
  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
991
1165
  * generated, otherwise an exception is thrown, if these values are
992
1166
  * encountered. This options defaults to false.
993
- * * *quirks_mode*: Enables quirks_mode for parser, that is for example
994
- * generating single JSON values instead of documents is possible.
1167
+ * * *ascii_only*: true if only ASCII characters should be generated. This
1168
+ * option defaults to false.
995
1169
  * * *buffer_initial_length*: sets the initial length of the generator's
996
1170
  * internal buffer.
997
1171
  */
@@ -1047,10 +1221,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1047
1221
  } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
1048
1222
  return rb_funcall(self, i_new, 1, opts);
1049
1223
  } else {
1050
- if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1051
- CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1052
- }
1053
- return rb_funcall(CJSON_SAFE_STATE_PROTOTYPE, i_dup, 0);
1224
+ return rb_class_new_instance(0, NULL, cState);
1054
1225
  }
1055
1226
  }
1056
1227
 
@@ -1084,7 +1255,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1084
1255
  }
1085
1256
  } else {
1086
1257
  if (state->indent) ruby_xfree(state->indent);
1087
- state->indent = strdup(RSTRING_PTR(indent));
1258
+ state->indent = fstrndup(RSTRING_PTR(indent), len);
1088
1259
  state->indent_len = len;
1089
1260
  }
1090
1261
  return Qnil;
@@ -1122,7 +1293,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1122
1293
  }
1123
1294
  } else {
1124
1295
  if (state->space) ruby_xfree(state->space);
1125
- state->space = strdup(RSTRING_PTR(space));
1296
+ state->space = fstrndup(RSTRING_PTR(space), len);
1126
1297
  state->space_len = len;
1127
1298
  }
1128
1299
  return Qnil;
@@ -1158,7 +1329,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1158
1329
  }
1159
1330
  } else {
1160
1331
  if (state->space_before) ruby_xfree(state->space_before);
1161
- state->space_before = strdup(RSTRING_PTR(space_before));
1332
+ state->space_before = fstrndup(RSTRING_PTR(space_before), len);
1162
1333
  state->space_before_len = len;
1163
1334
  }
1164
1335
  return Qnil;
@@ -1195,7 +1366,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1195
1366
  }
1196
1367
  } else {
1197
1368
  if (state->object_nl) ruby_xfree(state->object_nl);
1198
- state->object_nl = strdup(RSTRING_PTR(object_nl));
1369
+ state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
1199
1370
  state->object_nl_len = len;
1200
1371
  }
1201
1372
  return Qnil;
@@ -1230,7 +1401,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1230
1401
  }
1231
1402
  } else {
1232
1403
  if (state->array_nl) ruby_xfree(state->array_nl);
1233
- state->array_nl = strdup(RSTRING_PTR(array_nl));
1404
+ state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
1234
1405
  state->array_nl_len = len;
1235
1406
  }
1236
1407
  return Qnil;
@@ -1275,52 +1446,85 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1275
1446
  }
1276
1447
 
1277
1448
  /*
1278
- * call-seq: allow_nan?
1449
+ * call-seq: script_safe
1279
1450
  *
1280
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1281
- * returns false.
1451
+ * If this boolean is true, the forward slashes will be escaped in
1452
+ * the json output.
1282
1453
  */
1283
- static VALUE cState_allow_nan_p(VALUE self)
1454
+ static VALUE cState_script_safe(VALUE self)
1284
1455
  {
1285
1456
  GET_STATE(self);
1286
- return state->allow_nan ? Qtrue : Qfalse;
1457
+ return state->script_safe ? Qtrue : Qfalse;
1287
1458
  }
1288
1459
 
1289
1460
  /*
1290
- * call-seq: ascii_only?
1461
+ * call-seq: script_safe=(enable)
1291
1462
  *
1292
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1293
- * returns false.
1463
+ * This sets whether or not the forward slashes will be escaped in
1464
+ * the json output.
1294
1465
  */
1295
- static VALUE cState_ascii_only_p(VALUE self)
1466
+ static VALUE cState_script_safe_set(VALUE self, VALUE enable)
1296
1467
  {
1297
1468
  GET_STATE(self);
1298
- return state->ascii_only ? Qtrue : Qfalse;
1469
+ state->script_safe = RTEST(enable);
1470
+ return Qnil;
1299
1471
  }
1300
1472
 
1301
1473
  /*
1302
- * call-seq: quirks_mode?
1474
+ * call-seq: strict
1303
1475
  *
1304
- * Returns true, if quirks mode is enabled. Otherwise returns false.
1476
+ * If this boolean is false, types unsupported by the JSON format will
1477
+ * be serialized as strings.
1478
+ * If this boolean is true, types unsupported by the JSON format will
1479
+ * raise a JSON::GeneratorError.
1305
1480
  */
1306
- static VALUE cState_quirks_mode_p(VALUE self)
1481
+ static VALUE cState_strict(VALUE self)
1307
1482
  {
1308
1483
  GET_STATE(self);
1309
- return state->quirks_mode ? Qtrue : Qfalse;
1484
+ return state->strict ? Qtrue : Qfalse;
1310
1485
  }
1311
1486
 
1312
1487
  /*
1313
- * call-seq: quirks_mode=(enable)
1488
+ * call-seq: strict=(enable)
1314
1489
  *
1315
- * If set to true, enables the quirks_mode mode.
1490
+ * This sets whether or not to serialize types unsupported by the
1491
+ * JSON format as strings.
1492
+ * If this boolean is false, types unsupported by the JSON format will
1493
+ * be serialized as strings.
1494
+ * If this boolean is true, types unsupported by the JSON format will
1495
+ * raise a JSON::GeneratorError.
1316
1496
  */
1317
- static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
1497
+ static VALUE cState_strict_set(VALUE self, VALUE enable)
1318
1498
  {
1319
1499
  GET_STATE(self);
1320
- state->quirks_mode = RTEST(enable);
1500
+ state->strict = RTEST(enable);
1321
1501
  return Qnil;
1322
1502
  }
1323
1503
 
1504
+ /*
1505
+ * call-seq: allow_nan?
1506
+ *
1507
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1508
+ * returns false.
1509
+ */
1510
+ static VALUE cState_allow_nan_p(VALUE self)
1511
+ {
1512
+ GET_STATE(self);
1513
+ return state->allow_nan ? Qtrue : Qfalse;
1514
+ }
1515
+
1516
+ /*
1517
+ * call-seq: ascii_only?
1518
+ *
1519
+ * Returns true, if only ASCII characters should be generated. Otherwise
1520
+ * returns false.
1521
+ */
1522
+ static VALUE cState_ascii_only_p(VALUE self)
1523
+ {
1524
+ GET_STATE(self);
1525
+ return state->ascii_only ? Qtrue : Qfalse;
1526
+ }
1527
+
1324
1528
  /*
1325
1529
  * call-seq: depth
1326
1530
  *
@@ -1380,6 +1584,11 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
1380
1584
  */
1381
1585
  void Init_generator(void)
1382
1586
  {
1587
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1588
+ rb_ext_ractor_safe(true);
1589
+ #endif
1590
+
1591
+ #undef rb_intern
1383
1592
  rb_require("json/common");
1384
1593
 
1385
1594
  mJSON = rb_define_module("JSON");
@@ -1388,6 +1597,8 @@ void Init_generator(void)
1388
1597
 
1389
1598
  eGeneratorError = rb_path2class("JSON::GeneratorError");
1390
1599
  eNestingError = rb_path2class("JSON::NestingError");
1600
+ rb_gc_register_mark_object(eGeneratorError);
1601
+ rb_gc_register_mark_object(eNestingError);
1391
1602
 
1392
1603
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1393
1604
  rb_define_alloc_func(cState, cState_s_allocate);
@@ -1406,12 +1617,18 @@ void Init_generator(void)
1406
1617
  rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
1407
1618
  rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
1408
1619
  rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
1620
+ rb_define_method(cState, "script_safe", cState_script_safe, 0);
1621
+ rb_define_method(cState, "script_safe?", cState_script_safe, 0);
1622
+ rb_define_method(cState, "script_safe=", cState_script_safe_set, 1);
1623
+ rb_define_alias(cState, "escape_slash", "script_safe");
1624
+ rb_define_alias(cState, "escape_slash?", "script_safe?");
1625
+ rb_define_alias(cState, "escape_slash=", "script_safe=");
1626
+ rb_define_method(cState, "strict", cState_strict, 0);
1627
+ rb_define_method(cState, "strict?", cState_strict, 0);
1628
+ rb_define_method(cState, "strict=", cState_strict_set, 1);
1409
1629
  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1410
1630
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1411
1631
  rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1412
- rb_define_method(cState, "quirks_mode?", cState_quirks_mode_p, 0);
1413
- rb_define_method(cState, "quirks_mode", cState_quirks_mode_p, 0);
1414
- rb_define_method(cState, "quirks_mode=", cState_quirks_mode_set, 1);
1415
1632
  rb_define_method(cState, "depth", cState_depth, 0);
1416
1633
  rb_define_method(cState, "depth=", cState_depth_set, 1);
1417
1634
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
@@ -1456,7 +1673,6 @@ void Init_generator(void)
1456
1673
  mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1457
1674
  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1458
1675
 
1459
- CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
1460
1676
  i_to_s = rb_intern("to_s");
1461
1677
  i_to_json = rb_intern("to_json");
1462
1678
  i_new = rb_intern("new");
@@ -1466,9 +1682,11 @@ void Init_generator(void)
1466
1682
  i_object_nl = rb_intern("object_nl");
1467
1683
  i_array_nl = rb_intern("array_nl");
1468
1684
  i_max_nesting = rb_intern("max_nesting");
1685
+ i_script_safe = rb_intern("script_safe");
1686
+ i_escape_slash = rb_intern("escape_slash");
1687
+ i_strict = rb_intern("strict");
1469
1688
  i_allow_nan = rb_intern("allow_nan");
1470
1689
  i_ascii_only = rb_intern("ascii_only");
1471
- i_quirks_mode = rb_intern("quirks_mode");
1472
1690
  i_depth = rb_intern("depth");
1473
1691
  i_buffer_initial_length = rb_intern("buffer_initial_length");
1474
1692
  i_pack = rb_intern("pack");
@@ -1482,11 +1700,4 @@ void Init_generator(void)
1482
1700
  i_match = rb_intern("match");
1483
1701
  i_keys = rb_intern("keys");
1484
1702
  i_dup = rb_intern("dup");
1485
- #ifdef HAVE_RUBY_ENCODING_H
1486
- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
1487
- i_encoding = rb_intern("encoding");
1488
- i_encode = rb_intern("encode");
1489
- #endif
1490
- i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1491
- CJSON_SAFE_STATE_PROTOTYPE = Qnil;
1492
1703
  }