json_pure 2.0.4 → 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 (46) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -5
  4. data/CHANGES.md +39 -0
  5. data/Gemfile +1 -3
  6. data/LICENSE +56 -0
  7. data/README.md +54 -21
  8. data/Rakefile +19 -93
  9. data/VERSION +1 -1
  10. data/ext/json/ext/generator/generator.c +214 -45
  11. data/ext/json/ext/generator/generator.h +5 -2
  12. data/ext/json/ext/parser/extconf.rb +25 -0
  13. data/ext/json/ext/parser/parser.c +155 -83
  14. data/ext/json/ext/parser/parser.h +2 -0
  15. data/ext/json/ext/parser/parser.rl +79 -7
  16. data/ext/json/extconf.rb +1 -0
  17. data/java/src/json/ext/Generator.java +28 -24
  18. data/java/src/json/ext/GeneratorState.java +30 -0
  19. data/java/src/json/ext/Parser.java +109 -82
  20. data/java/src/json/ext/Parser.rl +39 -12
  21. data/java/src/json/ext/StringEncoder.java +8 -2
  22. data/json-java.gemspec +22 -22
  23. data/json.gemspec +0 -0
  24. data/json_pure.gemspec +9 -14
  25. data/lib/json.rb +549 -29
  26. data/lib/json/add/bigdecimal.rb +2 -2
  27. data/lib/json/add/complex.rb +2 -3
  28. data/lib/json/add/ostruct.rb +1 -1
  29. data/lib/json/add/rational.rb +2 -3
  30. data/lib/json/add/regexp.rb +2 -2
  31. data/lib/json/add/set.rb +29 -0
  32. data/lib/json/common.rb +341 -115
  33. data/lib/json/pure/generator.rb +31 -10
  34. data/lib/json/pure/parser.rb +35 -5
  35. data/lib/json/version.rb +1 -1
  36. data/tests/json_addition_test.rb +6 -0
  37. data/tests/json_common_interface_test.rb +47 -4
  38. data/tests/json_encoding_test.rb +2 -2
  39. data/tests/json_fixtures_test.rb +9 -1
  40. data/tests/json_generator_test.rb +55 -0
  41. data/tests/json_parser_test.rb +43 -12
  42. data/tests/test_helper.rb +3 -7
  43. metadata +17 -13
  44. data/data/example.json +0 -1
  45. data/data/index.html +0 -38
  46. data/data/prototype.js +0 -4184
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.4
1
+ 2.4.0
@@ -15,14 +15,14 @@ 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,
18
+ eNestingError,
19
19
  i_SAFE_STATE_PROTOTYPE;
20
20
 
21
21
  static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
22
22
  i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
23
23
  i_pack, i_unpack, i_create_id, i_extend, i_key_p,
24
24
  i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
25
- i_buffer_initial_length, i_dup;
25
+ i_buffer_initial_length, i_dup, i_escape_slash;
26
26
 
27
27
  /*
28
28
  * Copyright 2001-2004 Unicode, Inc.
@@ -130,7 +130,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
130
130
 
131
131
  /* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
132
132
  * and control characters are JSON escaped. */
133
- 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)
134
134
  {
135
135
  const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
136
136
  const UTF8 *sourceEnd = source + RSTRING_LEN(string);
@@ -180,6 +180,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
180
180
  case '"':
181
181
  fbuffer_append(buffer, "\\\"", 2);
182
182
  break;
183
+ case '/':
184
+ if(escape_slash) {
185
+ fbuffer_append(buffer, "\\/", 2);
186
+ break;
187
+ }
183
188
  default:
184
189
  fbuffer_append_char(buffer, (char)ch);
185
190
  break;
@@ -229,7 +234,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
229
234
  * characters required by the JSON standard are JSON escaped. The remaining
230
235
  * characters (should be UTF8) are just passed through and appended to the
231
236
  * result. */
232
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
237
+ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
233
238
  {
234
239
  const char *ptr = RSTRING_PTR(string), *p;
235
240
  unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
@@ -237,6 +242,7 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
237
242
  int escape_len;
238
243
  unsigned char c;
239
244
  char buf[6] = { '\\', 'u' };
245
+ int ascii_only = rb_enc_str_asciionly_p(string);
240
246
 
241
247
  for (start = 0, end = 0; end < len;) {
242
248
  p = ptr + end;
@@ -279,16 +285,25 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
279
285
  escape = "\\\"";
280
286
  escape_len = 2;
281
287
  break;
288
+ case '/':
289
+ if(escape_slash) {
290
+ escape = "\\/";
291
+ escape_len = 2;
292
+ break;
293
+ }
282
294
  default:
283
295
  {
284
- unsigned short clen = trailingBytesForUTF8[c] + 1;
285
- if (end + clen > len) {
286
- rb_raise(rb_path2class("JSON::GeneratorError"),
287
- "partial character in source, but hit end");
288
- }
289
- if (!isLegalUTF8((UTF8 *) p, clen)) {
290
- rb_raise(rb_path2class("JSON::GeneratorError"),
291
- "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
+ }
292
307
  }
293
308
  end += clen;
294
309
  }
@@ -324,6 +339,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
324
339
  *
325
340
  */
326
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
+
327
412
  /*
328
413
  * call-seq: to_json(state = nil)
329
414
  *
@@ -642,6 +727,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
642
727
  state->allow_nan = RTEST(tmp);
643
728
  tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
644
729
  state->ascii_only = RTEST(tmp);
730
+ tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
731
+ state->escape_slash = RTEST(tmp);
645
732
  return self;
646
733
  }
647
734
 
@@ -676,6 +763,7 @@ static VALUE cState_to_h(VALUE self)
676
763
  rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
677
764
  rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
678
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);
679
767
  rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
680
768
  rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
681
769
  return result;
@@ -692,7 +780,7 @@ static VALUE cState_aref(VALUE self, VALUE name)
692
780
  if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
693
781
  return rb_funcall(self, i_send, 1, name);
694
782
  } else {
695
- 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)));
696
784
  }
697
785
  }
698
786
 
@@ -715,43 +803,83 @@ static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
715
803
  return Qnil;
716
804
  }
717
805
 
718
- 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)
719
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
+
720
821
  char *object_nl = state->object_nl;
721
822
  long object_nl_len = state->object_nl_len;
722
823
  char *indent = state->indent;
723
824
  long indent_len = state->indent_len;
724
- long max_nesting = state->max_nesting;
725
825
  char *delim = FBUFFER_PTR(state->object_delim);
726
826
  long delim_len = FBUFFER_LEN(state->object_delim);
727
827
  char *delim2 = FBUFFER_PTR(state->object_delim2);
728
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;
729
867
  long depth = ++state->depth;
730
- int i, j;
731
- VALUE key, key_to_s, keys;
868
+ int j;
869
+ struct hash_foreach_arg arg;
870
+
732
871
  if (max_nesting != 0 && depth > max_nesting) {
733
872
  fbuffer_free(buffer);
734
873
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
735
874
  }
736
875
  fbuffer_append_char(buffer, '{');
737
- keys = rb_funcall(obj, i_keys, 0);
738
- for(i = 0; i < RARRAY_LEN(keys); i++) {
739
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
740
- if (object_nl) {
741
- fbuffer_append(buffer, object_nl, object_nl_len);
742
- }
743
- if (indent) {
744
- for (j = 0; j < depth; j++) {
745
- fbuffer_append(buffer, indent, indent_len);
746
- }
747
- }
748
- key = rb_ary_entry(keys, i);
749
- key_to_s = rb_funcall(key, i_to_s, 0);
750
- Check_Type(key_to_s, T_STRING);
751
- generate_json(buffer, Vstate, state, key_to_s);
752
- fbuffer_append(buffer, delim2, delim2_len);
753
- generate_json(buffer, Vstate, state, rb_hash_aref(obj, key));
754
- }
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
+
755
883
  depth = --state->depth;
756
884
  if (object_nl) {
757
885
  fbuffer_append(buffer, object_nl, object_nl_len);
@@ -802,16 +930,27 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
802
930
  fbuffer_append_char(buffer, ']');
803
931
  }
804
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
+
805
942
  static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
806
943
  {
807
944
  fbuffer_append_char(buffer, '"');
808
945
  #ifdef HAVE_RUBY_ENCODING_H
809
- 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
+ }
810
949
  #endif
811
950
  if (state->ascii_only) {
812
- convert_UTF8_to_JSON_ASCII(buffer, obj);
951
+ convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
813
952
  } else {
814
- convert_UTF8_to_JSON(buffer, obj);
953
+ convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
815
954
  }
816
955
  fbuffer_append_char(buffer, '"');
817
956
  }
@@ -970,6 +1109,8 @@ static VALUE cState_generate(VALUE self, VALUE obj)
970
1109
  * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
971
1110
  * generated, otherwise an exception is thrown, if these values are
972
1111
  * encountered. This options defaults to false.
1112
+ * * *ascii_only*: true if only ASCII characters should be generated. This
1113
+ * option defaults to false.
973
1114
  * * *buffer_initial_length*: sets the initial length of the generator's
974
1115
  * internal buffer.
975
1116
  */
@@ -1025,10 +1166,8 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1025
1166
  } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
1026
1167
  return rb_funcall(self, i_new, 1, opts);
1027
1168
  } else {
1028
- if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1029
- CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
1030
- }
1031
- 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);
1032
1171
  }
1033
1172
  }
1034
1173
 
@@ -1252,6 +1391,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1252
1391
  return state->max_nesting = FIX2LONG(depth);
1253
1392
  }
1254
1393
 
1394
+ /*
1395
+ * call-seq: escape_slash
1396
+ *
1397
+ * If this boolean is true, the forward slashes will be escaped in
1398
+ * the json output.
1399
+ */
1400
+ static VALUE cState_escape_slash(VALUE self)
1401
+ {
1402
+ GET_STATE(self);
1403
+ return state->escape_slash ? Qtrue : Qfalse;
1404
+ }
1405
+
1406
+ /*
1407
+ * call-seq: escape_slash=(depth)
1408
+ *
1409
+ * This sets whether or not the forward slashes will be escaped in
1410
+ * the json output.
1411
+ */
1412
+ static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
1413
+ {
1414
+ GET_STATE(self);
1415
+ state->escape_slash = RTEST(enable);
1416
+ return Qnil;
1417
+ }
1418
+
1255
1419
  /*
1256
1420
  * call-seq: allow_nan?
1257
1421
  *
@@ -1267,7 +1431,7 @@ static VALUE cState_allow_nan_p(VALUE self)
1267
1431
  /*
1268
1432
  * call-seq: ascii_only?
1269
1433
  *
1270
- * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1434
+ * Returns true, if only ASCII characters should be generated. Otherwise
1271
1435
  * returns false.
1272
1436
  */
1273
1437
  static VALUE cState_ascii_only_p(VALUE self)
@@ -1335,6 +1499,7 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
1335
1499
  */
1336
1500
  void Init_generator(void)
1337
1501
  {
1502
+ #undef rb_intern
1338
1503
  rb_require("json/common");
1339
1504
 
1340
1505
  mJSON = rb_define_module("JSON");
@@ -1343,6 +1508,8 @@ void Init_generator(void)
1343
1508
 
1344
1509
  eGeneratorError = rb_path2class("JSON::GeneratorError");
1345
1510
  eNestingError = rb_path2class("JSON::NestingError");
1511
+ rb_gc_register_mark_object(eGeneratorError);
1512
+ rb_gc_register_mark_object(eNestingError);
1346
1513
 
1347
1514
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1348
1515
  rb_define_alloc_func(cState, cState_s_allocate);
@@ -1361,6 +1528,9 @@ void Init_generator(void)
1361
1528
  rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
1362
1529
  rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
1363
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);
1364
1534
  rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1365
1535
  rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1366
1536
  rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
@@ -1408,7 +1578,6 @@ void Init_generator(void)
1408
1578
  mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1409
1579
  rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1410
1580
 
1411
- CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
1412
1581
  i_to_s = rb_intern("to_s");
1413
1582
  i_to_json = rb_intern("to_json");
1414
1583
  i_new = rb_intern("new");
@@ -1418,6 +1587,7 @@ void Init_generator(void)
1418
1587
  i_object_nl = rb_intern("object_nl");
1419
1588
  i_array_nl = rb_intern("array_nl");
1420
1589
  i_max_nesting = rb_intern("max_nesting");
1590
+ i_escape_slash = rb_intern("escape_slash");
1421
1591
  i_allow_nan = rb_intern("allow_nan");
1422
1592
  i_ascii_only = rb_intern("ascii_only");
1423
1593
  i_depth = rb_intern("depth");
@@ -1439,5 +1609,4 @@ void Init_generator(void)
1439
1609
  i_encode = rb_intern("encode");
1440
1610
  #endif
1441
1611
  i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
1442
- CJSON_SAFE_STATE_PROTOTYPE = Qnil;
1443
1612
  }
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
49
49
  static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
50
50
  static void unicode_escape(char *buf, UTF16 character);
51
51
  static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
52
- static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
53
- static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
52
+ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
53
+ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
54
54
  static char *fstrndup(const char *ptr, unsigned long len);
55
55
 
56
56
  /* ruby api and some helpers */
@@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct {
72
72
  long max_nesting;
73
73
  char allow_nan;
74
74
  char ascii_only;
75
+ char escape_slash;
75
76
  long depth;
76
77
  long buffer_initial_length;
77
78
  } JSON_Generator_State;
@@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
150
151
  static VALUE cState_ascii_only_p(VALUE self);
151
152
  static VALUE cState_depth(VALUE self);
152
153
  static VALUE cState_depth_set(VALUE self, VALUE depth);
154
+ static VALUE cState_escape_slash(VALUE self);
155
+ static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
153
156
  static FBuffer *cState_prepare_buffer(VALUE self);
154
157
  #ifndef ZALLOC
155
158
  #define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))