json 1.8.6 → 2.5.1

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 (92) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +234 -95
  3. data/Gemfile +10 -3
  4. data/LICENSE +56 -0
  5. data/README.md +187 -107
  6. data/VERSION +1 -1
  7. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  8. data/ext/json/ext/generator/generator.c +227 -101
  9. data/ext/json/ext/generator/generator.h +5 -8
  10. data/ext/json/ext/parser/extconf.rb +28 -0
  11. data/ext/json/ext/parser/parser.c +420 -481
  12. data/ext/json/ext/parser/parser.h +5 -5
  13. data/ext/json/ext/parser/parser.rl +148 -172
  14. data/ext/json/extconf.rb +1 -1
  15. data/json.gemspec +0 -0
  16. data/lib/json.rb +550 -29
  17. data/lib/json/add/bigdecimal.rb +3 -2
  18. data/lib/json/add/complex.rb +4 -4
  19. data/lib/json/add/core.rb +1 -0
  20. data/lib/json/add/date.rb +1 -1
  21. data/lib/json/add/date_time.rb +1 -1
  22. data/lib/json/add/exception.rb +1 -1
  23. data/lib/json/add/ostruct.rb +3 -3
  24. data/lib/json/add/range.rb +1 -1
  25. data/lib/json/add/rational.rb +3 -3
  26. data/lib/json/add/regexp.rb +3 -3
  27. data/lib/json/add/set.rb +29 -0
  28. data/lib/json/add/struct.rb +1 -1
  29. data/lib/json/add/symbol.rb +1 -1
  30. data/lib/json/add/time.rb +1 -1
  31. data/lib/json/common.rb +381 -162
  32. data/lib/json/ext.rb +0 -6
  33. data/lib/json/generic_object.rb +5 -4
  34. data/lib/json/pure.rb +2 -8
  35. data/lib/json/pure/generator.rb +73 -124
  36. data/lib/json/pure/parser.rb +62 -84
  37. data/lib/json/version.rb +2 -1
  38. data/tests/fixtures/fail29.json +1 -0
  39. data/tests/fixtures/fail30.json +1 -0
  40. data/tests/fixtures/fail31.json +1 -0
  41. data/tests/fixtures/fail32.json +1 -0
  42. data/tests/fixtures/obsolete_fail1.json +1 -0
  43. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  44. data/tests/json_common_interface_test.rb +169 -0
  45. data/tests/json_encoding_test.rb +107 -0
  46. data/tests/json_ext_parser_test.rb +15 -0
  47. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  48. data/tests/{test_json_generate.rb → json_generator_test.rb} +98 -47
  49. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  50. data/tests/json_parser_test.rb +497 -0
  51. data/tests/json_string_matching_test.rb +38 -0
  52. data/tests/lib/core_assertions.rb +763 -0
  53. data/tests/lib/envutil.rb +365 -0
  54. data/tests/lib/find_executable.rb +22 -0
  55. data/tests/lib/helper.rb +4 -0
  56. data/tests/ractor_test.rb +30 -0
  57. data/tests/test_helper.rb +17 -0
  58. metadata +43 -69
  59. data/.gitignore +0 -17
  60. data/.travis.yml +0 -18
  61. data/README-json-jruby.markdown +0 -33
  62. data/Rakefile +0 -402
  63. data/TODO +0 -1
  64. data/data/example.json +0 -1
  65. data/data/index.html +0 -38
  66. data/data/prototype.js +0 -4184
  67. data/diagrams/.keep +0 -0
  68. data/install.rb +0 -23
  69. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  70. data/java/src/json/ext/Generator.java +0 -446
  71. data/java/src/json/ext/GeneratorMethods.java +0 -231
  72. data/java/src/json/ext/GeneratorService.java +0 -42
  73. data/java/src/json/ext/GeneratorState.java +0 -542
  74. data/java/src/json/ext/OptionsReader.java +0 -113
  75. data/java/src/json/ext/Parser.java +0 -2644
  76. data/java/src/json/ext/Parser.rl +0 -968
  77. data/java/src/json/ext/ParserService.java +0 -34
  78. data/java/src/json/ext/RuntimeInfo.java +0 -120
  79. data/java/src/json/ext/StringDecoder.java +0 -166
  80. data/java/src/json/ext/StringEncoder.java +0 -111
  81. data/java/src/json/ext/Utils.java +0 -88
  82. data/json-java.gemspec +0 -38
  83. data/json_pure.gemspec +0 -37
  84. data/tests/fixtures/fail1.json +0 -1
  85. data/tests/setup_variant.rb +0 -11
  86. data/tests/test_json.rb +0 -519
  87. data/tests/test_json_encoding.rb +0 -65
  88. data/tests/test_json_string_matching.rb +0 -39
  89. data/tests/test_json_unicode.rb +0 -72
  90. data/tools/diff.sh +0 -18
  91. data/tools/fuzz.rb +0 -139
  92. data/tools/server.rb +0 -62
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.6
1
+ 2.5.1
@@ -12,9 +12,6 @@
12
12
  #define RFLOAT_VALUE(val) (RFLOAT(val)->value)
13
13
  #endif
14
14
 
15
- #ifndef RARRAY_PTR
16
- #define RARRAY_PTR(ARRAY) RARRAY(ARRAY)->ptr
17
- #endif
18
15
  #ifndef RARRAY_LEN
19
16
  #define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
20
17
  #endif
@@ -15,14 +15,13 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
15
15
  #endif
16
16
  mFloat, mString, mString_Extend,
17
17
  mTrueClass, mFalseClass, mNilClass, eGeneratorError,
18
- eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE,
19
- i_SAFE_STATE_PROTOTYPE;
18
+ eNestingError;
20
19
 
21
20
  static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
22
21
  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,
22
+ i_pack, i_unpack, i_create_id, i_extend, i_key_p,
24
23
  i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
25
- i_buffer_initial_length, i_dup;
24
+ i_buffer_initial_length, i_dup, i_escape_slash;
26
25
 
27
26
  /*
28
27
  * Copyright 2001-2004 Unicode, Inc.
@@ -130,7 +129,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
130
129
 
131
130
  /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
132
131
  * and control characters are JSON escaped. */
133
- static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
132
+ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
134
133
  {
135
134
  const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
136
135
  const UTF8 *sourceEnd = source + RSTRING_LEN(string);
@@ -180,6 +179,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
180
179
  case '"':
181
180
  fbuffer_append(buffer, "\\\"", 2);
182
181
  break;
182
+ case '/':
183
+ if(escape_slash) {
184
+ fbuffer_append(buffer, "\\/", 2);
185
+ break;
186
+ }
183
187
  default:
184
188
  fbuffer_append_char(buffer, (char)ch);
185
189
  break;
@@ -222,13 +226,14 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
222
226
  unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
223
227
  }
224
228
  }
229
+ RB_GC_GUARD(string);
225
230
  }
226
231
 
227
232
  /* Converts string to a JSON string in FBuffer buffer, where only the
228
233
  * characters required by the JSON standard are JSON escaped. The remaining
229
234
  * characters (should be UTF8) are just passed through and appended to the
230
235
  * result. */
231
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
236
+ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
232
237
  {
233
238
  const char *ptr = RSTRING_PTR(string), *p;
234
239
  unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
@@ -236,6 +241,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
236
241
  int escape_len;
237
242
  unsigned char c;
238
243
  char buf[6] = { '\\', 'u' };
244
+ int ascii_only = rb_enc_str_asciionly_p(string);
239
245
 
240
246
  for (start = 0, end = 0; end < len;) {
241
247
  p = ptr + end;
@@ -278,16 +284,25 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
278
284
  escape = "\\\"";
279
285
  escape_len = 2;
280
286
  break;
287
+ case '/':
288
+ if(escape_slash) {
289
+ escape = "\\/";
290
+ escape_len = 2;
291
+ break;
292
+ }
281
293
  default:
282
294
  {
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");
295
+ unsigned short clen = 1;
296
+ if (!ascii_only) {
297
+ clen += trailingBytesForUTF8[c];
298
+ if (end + clen > len) {
299
+ rb_raise(rb_path2class("JSON::GeneratorError"),
300
+ "partial character in source, but hit end");
301
+ }
302
+ if (!isLegalUTF8((UTF8 *) p, clen)) {
303
+ rb_raise(rb_path2class("JSON::GeneratorError"),
304
+ "source sequence is illegal/malformed utf-8");
305
+ }
291
306
  }
292
307
  end += clen;
293
308
  }
@@ -307,7 +322,7 @@ static char *fstrndup(const char *ptr, unsigned long len) {
307
322
  char *result;
308
323
  if (len <= 0) return NULL;
309
324
  result = ALLOC_N(char, len);
310
- memccpy(result, ptr, 0, len);
325
+ memcpy(result, ptr, len);
311
326
  return result;
312
327
  }
313
328
 
@@ -323,6 +338,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
323
338
  *
324
339
  */
325
340
 
341
+ /* Explanation of the following: that's the only way to not pollute
342
+ * standard library's docs with GeneratorMethods::<ClassName> which
343
+ * are uninformative and take a large place in a list of classes
344
+ */
345
+
346
+ /*
347
+ * Document-module: JSON::Ext::Generator::GeneratorMethods
348
+ * :nodoc:
349
+ */
350
+
351
+ /*
352
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Array
353
+ * :nodoc:
354
+ */
355
+
356
+ /*
357
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
358
+ * :nodoc:
359
+ */
360
+
361
+ /*
362
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
363
+ * :nodoc:
364
+ */
365
+
366
+ /*
367
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
368
+ * :nodoc:
369
+ */
370
+
371
+ /*
372
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Float
373
+ * :nodoc:
374
+ */
375
+
376
+ /*
377
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
378
+ * :nodoc:
379
+ */
380
+
381
+ /*
382
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
383
+ * :nodoc:
384
+ */
385
+
386
+ /*
387
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
388
+ * :nodoc:
389
+ */
390
+
391
+ /*
392
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Object
393
+ * :nodoc:
394
+ */
395
+
396
+ /*
397
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String
398
+ * :nodoc:
399
+ */
400
+
401
+ /*
402
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
403
+ * :nodoc:
404
+ */
405
+
406
+ /*
407
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
408
+ * :nodoc:
409
+ */
410
+
326
411
  /*
327
412
  * call-seq: to_json(state = nil)
328
413
  *
@@ -534,13 +619,18 @@ static size_t State_memsize(const void *ptr)
534
619
  return size;
535
620
  }
536
621
 
622
+ #ifndef HAVE_RB_EXT_RACTOR_SAFE
623
+ # undef RUBY_TYPED_FROZEN_SHAREABLE
624
+ # define RUBY_TYPED_FROZEN_SHAREABLE 0
625
+ #endif
626
+
537
627
  #ifdef NEW_TYPEDDATA_WRAPPER
538
628
  static const rb_data_type_t JSON_Generator_State_type = {
539
629
  "JSON/Generator/State",
540
630
  {NULL, State_free, State_memsize,},
541
631
  #ifdef RUBY_TYPED_FREE_IMMEDIATELY
542
632
  0, 0,
543
- RUBY_TYPED_FREE_IMMEDIATELY,
633
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
544
634
  #endif
545
635
  };
546
636
  #endif
@@ -641,8 +731,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
641
731
  state->allow_nan = RTEST(tmp);
642
732
  tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
643
733
  state->ascii_only = RTEST(tmp);
644
- tmp = rb_hash_aref(opts, ID2SYM(i_quirks_mode));
645
- state->quirks_mode = RTEST(tmp);
734
+ tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
735
+ state->escape_slash = RTEST(tmp);
646
736
  return self;
647
737
  }
648
738
 
@@ -676,8 +766,8 @@ static VALUE cState_to_h(VALUE self)
676
766
  rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
677
767
  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
678
768
  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
769
  rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
770
+ rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
681
771
  rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
682
772
  rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
683
773
  return result;
@@ -694,7 +784,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
694
784
  if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
695
785
  return rb_funcall(self, i_send, 1, name);
696
786
  } else {
697
- return rb_ivar_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
787
+ return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
698
788
  }
699
789
  }
700
790
 
@@ -717,43 +807,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
717
807
  return Qnil;
718
808
  }
719
809
 
720
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
810
+ struct hash_foreach_arg {
811
+ FBuffer *buffer;
812
+ JSON_Generator_State *state;
813
+ VALUE Vstate;
814
+ int iter;
815
+ };
816
+
817
+ static int
818
+ json_object_i(VALUE key, VALUE val, VALUE _arg)
721
819
  {
820
+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
821
+ FBuffer *buffer = arg->buffer;
822
+ JSON_Generator_State *state = arg->state;
823
+ VALUE Vstate = arg->Vstate;
824
+
722
825
  char *object_nl = state->object_nl;
723
826
  long object_nl_len = state->object_nl_len;
724
827
  char *indent = state->indent;
725
828
  long indent_len = state->indent_len;
726
- long max_nesting = state->max_nesting;
727
829
  char *delim = FBUFFER_PTR(state->object_delim);
728
830
  long delim_len = FBUFFER_LEN(state->object_delim);
729
831
  char *delim2 = FBUFFER_PTR(state->object_delim2);
730
832
  long delim2_len = FBUFFER_LEN(state->object_delim2);
833
+ long depth = state->depth;
834
+ int j;
835
+ VALUE klass, key_to_s;
836
+
837
+ if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
838
+ if (object_nl) {
839
+ fbuffer_append(buffer, object_nl, object_nl_len);
840
+ }
841
+ if (indent) {
842
+ for (j = 0; j < depth; j++) {
843
+ fbuffer_append(buffer, indent, indent_len);
844
+ }
845
+ }
846
+
847
+ klass = CLASS_OF(key);
848
+ if (klass == rb_cString) {
849
+ key_to_s = key;
850
+ } else if (klass == rb_cSymbol) {
851
+ key_to_s = rb_id2str(SYM2ID(key));
852
+ } else {
853
+ key_to_s = rb_funcall(key, i_to_s, 0);
854
+ }
855
+ Check_Type(key_to_s, T_STRING);
856
+ generate_json(buffer, Vstate, state, key_to_s);
857
+ fbuffer_append(buffer, delim2, delim2_len);
858
+ generate_json(buffer, Vstate, state, val);
859
+
860
+ arg->iter++;
861
+ return ST_CONTINUE;
862
+ }
863
+
864
+ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
865
+ {
866
+ char *object_nl = state->object_nl;
867
+ long object_nl_len = state->object_nl_len;
868
+ char *indent = state->indent;
869
+ long indent_len = state->indent_len;
870
+ long max_nesting = state->max_nesting;
731
871
  long depth = ++state->depth;
732
- int i, j;
733
- VALUE key, key_to_s, keys;
872
+ int j;
873
+ struct hash_foreach_arg arg;
874
+
734
875
  if (max_nesting != 0 && depth > max_nesting) {
735
876
  fbuffer_free(buffer);
736
877
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
737
878
  }
738
879
  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
- }
880
+
881
+ arg.buffer = buffer;
882
+ arg.state = state;
883
+ arg.Vstate = Vstate;
884
+ arg.iter = 0;
885
+ rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
886
+
757
887
  depth = --state->depth;
758
888
  if (object_nl) {
759
889
  fbuffer_append(buffer, object_nl, object_nl_len);
@@ -804,16 +934,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
804
934
  fbuffer_append_char(buffer, ']');
805
935
  }
806
936
 
937
+ #ifdef HAVE_RUBY_ENCODING_H
938
+ static int enc_utf8_compatible_p(rb_encoding *enc)
939
+ {
940
+ if (enc == rb_usascii_encoding()) return 1;
941
+ if (enc == rb_utf8_encoding()) return 1;
942
+ return 0;
943
+ }
944
+ #endif
945
+
807
946
  static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
808
947
  {
809
948
  fbuffer_append_char(buffer, '"');
810
949
  #ifdef HAVE_RUBY_ENCODING_H
811
- obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
950
+ if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
951
+ obj = rb_str_encode(obj, CEncoding_UTF_8, 0, Qnil);
952
+ }
812
953
  #endif
813
954
  if (state->ascii_only) {
814
- convert_UTF8_to_JSON_ASCII(buffer, obj);
955
+ convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
815
956
  } else {
816
- convert_UTF8_to_JSON(buffer, obj);
957
+ convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
817
958
  }
818
959
  fbuffer_append_char(buffer, '"');
819
960
  }
@@ -853,7 +994,6 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
853
994
  generate_json_bignum(buffer, Vstate, state, obj);
854
995
  }
855
996
  #endif
856
-
857
997
  static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
858
998
  {
859
999
  double value = RFLOAT_VALUE(obj);
@@ -943,21 +1083,6 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
943
1083
  return fbuffer_to_s(buffer);
944
1084
  }
945
1085
 
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 == '}');
959
- }
960
-
961
1086
  /*
962
1087
  * call-seq: generate(obj)
963
1088
  *
@@ -969,9 +1094,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
969
1094
  {
970
1095
  VALUE result = cState_partial_generate(self, obj);
971
1096
  GET_STATE(self);
972
- if (!state->quirks_mode && !isArrayOrObject(result)) {
973
- rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
974
- }
1097
+ (void)state;
975
1098
  return result;
976
1099
  }
977
1100
 
@@ -990,8 +1113,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
990
1113
  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
991
1114
  * generated, otherwise an exception is thrown, if these values are
992
1115
  * 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.
1116
+ * * *ascii_only*: true if only ASCII characters should be generated. This
1117
+ * option defaults to false.
995
1118
  * * *buffer_initial_length*: sets the initial length of the generator's
996
1119
  * internal buffer.
997
1120
  */
@@ -1047,10 +1170,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1047
1170
  } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
1048
1171
  return rb_funcall(self, i_new, 1, opts);
1049
1172
  } 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);
1173
+ return rb_class_new_instance(0, NULL, cState);
1054
1174
  }
1055
1175
  }
1056
1176
 
@@ -1084,7 +1204,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1084
1204
  }
1085
1205
  } else {
1086
1206
  if (state->indent) ruby_xfree(state->indent);
1087
- state->indent = strdup(RSTRING_PTR(indent));
1207
+ state->indent = fstrndup(RSTRING_PTR(indent), len);
1088
1208
  state->indent_len = len;
1089
1209
  }
1090
1210
  return Qnil;
@@ -1122,7 +1242,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1122
1242
  }
1123
1243
  } else {
1124
1244
  if (state->space) ruby_xfree(state->space);
1125
- state->space = strdup(RSTRING_PTR(space));
1245
+ state->space = fstrndup(RSTRING_PTR(space), len);
1126
1246
  state->space_len = len;
1127
1247
  }
1128
1248
  return Qnil;
@@ -1158,7 +1278,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1158
1278
  }
1159
1279
  } else {
1160
1280
  if (state->space_before) ruby_xfree(state->space_before);
1161
- state->space_before = strdup(RSTRING_PTR(space_before));
1281
+ state->space_before = fstrndup(RSTRING_PTR(space_before), len);
1162
1282
  state->space_before_len = len;
1163
1283
  }
1164
1284
  return Qnil;
@@ -1195,7 +1315,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1195
1315
  }
1196
1316
  } else {
1197
1317
  if (state->object_nl) ruby_xfree(state->object_nl);
1198
- state->object_nl = strdup(RSTRING_PTR(object_nl));
1318
+ state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
1199
1319
  state->object_nl_len = len;
1200
1320
  }
1201
1321
  return Qnil;
@@ -1230,7 +1350,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1230
1350
  }
1231
1351
  } else {
1232
1352
  if (state->array_nl) ruby_xfree(state->array_nl);
1233
- state->array_nl = strdup(RSTRING_PTR(array_nl));
1353
+ state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
1234
1354
  state->array_nl_len = len;
1235
1355
  }
1236
1356
  return Qnil;
@@ -1275,50 +1395,52 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1275
1395
  }
1276
1396
 
1277
1397
  /*
1278
- * call-seq: allow_nan?
1398
+ * call-seq: escape_slash
1279
1399
  *
1280
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1281
- * returns false.
1400
+ * If this boolean is true, the forward slashes will be escaped in
1401
+ * the json output.
1282
1402
  */
1283
- static VALUE cState_allow_nan_p(VALUE self)
1403
+ static VALUE cState_escape_slash(VALUE self)
1284
1404
  {
1285
1405
  GET_STATE(self);
1286
- return state->allow_nan ? Qtrue : Qfalse;
1406
+ return state->escape_slash ? Qtrue : Qfalse;
1287
1407
  }
1288
1408
 
1289
1409
  /*
1290
- * call-seq: ascii_only?
1410
+ * call-seq: escape_slash=(depth)
1291
1411
  *
1292
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1293
- * returns false.
1412
+ * This sets whether or not the forward slashes will be escaped in
1413
+ * the json output.
1294
1414
  */
1295
- static VALUE cState_ascii_only_p(VALUE self)
1415
+ static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
1296
1416
  {
1297
1417
  GET_STATE(self);
1298
- return state->ascii_only ? Qtrue : Qfalse;
1418
+ state->escape_slash = RTEST(enable);
1419
+ return Qnil;
1299
1420
  }
1300
1421
 
1301
1422
  /*
1302
- * call-seq: quirks_mode?
1423
+ * call-seq: allow_nan?
1303
1424
  *
1304
- * Returns true, if quirks mode is enabled. Otherwise returns false.
1425
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1426
+ * returns false.
1305
1427
  */
1306
- static VALUE cState_quirks_mode_p(VALUE self)
1428
+ static VALUE cState_allow_nan_p(VALUE self)
1307
1429
  {
1308
1430
  GET_STATE(self);
1309
- return state->quirks_mode ? Qtrue : Qfalse;
1431
+ return state->allow_nan ? Qtrue : Qfalse;
1310
1432
  }
1311
1433
 
1312
1434
  /*
1313
- * call-seq: quirks_mode=(enable)
1435
+ * call-seq: ascii_only?
1314
1436
  *
1315
- * If set to true, enables the quirks_mode mode.
1437
+ * Returns true, if only ASCII characters should be generated. Otherwise
1438
+ * returns false.
1316
1439
  */
1317
- static VALUE cState_quirks_mode_set(VALUE self, VALUE enable)
1440
+ static VALUE cState_ascii_only_p(VALUE self)
1318
1441
  {
1319
1442
  GET_STATE(self);
1320
- state->quirks_mode = RTEST(enable);
1321
- return Qnil;
1443
+ return state->ascii_only ? Qtrue : Qfalse;
1322
1444
  }
1323
1445
 
1324
1446
  /*
@@ -1380,6 +1502,11 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
1380
1502
  */
1381
1503
  void Init_generator(void)
1382
1504
  {
1505
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
1506
+ rb_ext_ractor_safe(true);
1507
+ #endif
1508
+
1509
+ #undef rb_intern
1383
1510
  rb_require("json/common");
1384
1511
 
1385
1512
  mJSON = rb_define_module("JSON");
@@ -1388,6 +1515,8 @@ void Init_generator(void)
1388
1515
 
1389
1516
  eGeneratorError = rb_path2class("JSON::GeneratorError");
1390
1517
  eNestingError = rb_path2class("JSON::NestingError");
1518
+ rb_gc_register_mark_object(eGeneratorError);
1519
+ rb_gc_register_mark_object(eNestingError);
1391
1520
 
1392
1521
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1393
1522
  rb_define_alloc_func(cState, cState_s_allocate);
@@ -1406,12 +1535,12 @@ void Init_generator(void)
1406
1535
  rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
1407
1536
  rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
1408
1537
  rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
1538
+ rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
1539
+ rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
1540
+ rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
1409
1541
  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1410
1542
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1411
1543
  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
1544
  rb_define_method(cState, "depth", cState_depth, 0);
1416
1545
  rb_define_method(cState, "depth=", cState_depth_set, 1);
1417
1546
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
@@ -1456,7 +1585,6 @@ void Init_generator(void)
1456
1585
  mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1457
1586
  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1458
1587
 
1459
- CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
1460
1588
  i_to_s = rb_intern("to_s");
1461
1589
  i_to_json = rb_intern("to_json");
1462
1590
  i_new = rb_intern("new");
@@ -1466,9 +1594,9 @@ void Init_generator(void)
1466
1594
  i_object_nl = rb_intern("object_nl");
1467
1595
  i_array_nl = rb_intern("array_nl");
1468
1596
  i_max_nesting = rb_intern("max_nesting");
1597
+ i_escape_slash = rb_intern("escape_slash");
1469
1598
  i_allow_nan = rb_intern("allow_nan");
1470
1599
  i_ascii_only = rb_intern("ascii_only");
1471
- i_quirks_mode = rb_intern("quirks_mode");
1472
1600
  i_depth = rb_intern("depth");
1473
1601
  i_buffer_initial_length = rb_intern("buffer_initial_length");
1474
1602
  i_pack = rb_intern("pack");
@@ -1487,6 +1615,4 @@ void Init_generator(void)
1487
1615
  i_encoding = rb_intern("encoding");
1488
1616
  i_encode = rb_intern("encode");
1489
1617
  #endif
1490
- i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1491
- CJSON_SAFE_STATE_PROTOTYPE = Qnil;
1492
1618
  }