json 1.8.3 → 2.4.0

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