json 2.7.5 → 2.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,27 @@
1
+ #include "ruby.h"
1
2
  #include "../fbuffer/fbuffer.h"
2
- #include "generator.h"
3
+
4
+ #include <math.h>
5
+ #include <ctype.h>
6
+
7
+ /* ruby api and some helpers */
8
+
9
+ typedef struct JSON_Generator_StateStruct {
10
+ VALUE indent;
11
+ VALUE space;
12
+ VALUE space_before;
13
+ VALUE object_nl;
14
+ VALUE array_nl;
15
+
16
+ long max_nesting;
17
+ long depth;
18
+ long buffer_initial_length;
19
+
20
+ bool allow_nan;
21
+ bool ascii_only;
22
+ bool script_safe;
23
+ bool strict;
24
+ } JSON_Generator_State;
3
25
 
4
26
  #ifndef RB_UNLIKELY
5
27
  #define RB_UNLIKELY(cond) (cond)
@@ -8,6 +30,46 @@
8
30
  static VALUE mJSON, cState, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8;
9
31
 
10
32
  static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode;
33
+ static ID sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan,
34
+ sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict;
35
+
36
+
37
+ #define GET_STATE_TO(self, state) \
38
+ TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state)
39
+
40
+ #define GET_STATE(self) \
41
+ JSON_Generator_State *state; \
42
+ GET_STATE_TO(self, state)
43
+
44
+ struct generate_json_data;
45
+
46
+ typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
47
+
48
+ struct generate_json_data {
49
+ FBuffer *buffer;
50
+ VALUE vstate;
51
+ JSON_Generator_State *state;
52
+ VALUE obj;
53
+ generator_func func;
54
+ };
55
+
56
+ static VALUE cState_from_state_s(VALUE self, VALUE opts);
57
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func);
58
+ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
59
+ static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
60
+ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
61
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
62
+ static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
63
+ static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
64
+ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
65
+ #ifdef RUBY_INTEGER_UNIFICATION
66
+ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
67
+ #endif
68
+ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
69
+ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
70
+ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
71
+
72
+ static int usascii_encindex, utf8_encindex, binary_encindex;
11
73
 
12
74
  /* Converts in_string to a JSON string (without the wrapping '"'
13
75
  * characters) in FBuffer out_buffer.
@@ -44,9 +106,6 @@ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char esca
44
106
 
45
107
  if (RB_UNLIKELY(ch_len)) {
46
108
  switch (ch_len) {
47
- case 0:
48
- pos++;
49
- break;
50
109
  case 1: {
51
110
  FLUSH_POS(1);
52
111
  switch (ch) {
@@ -59,8 +118,8 @@ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char esca
59
118
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
60
119
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
61
120
  default: {
62
- scratch[2] = hexdig[ch >> 12];
63
- scratch[3] = hexdig[(ch >> 8) & 0xf];
121
+ scratch[2] = '0';
122
+ scratch[3] = '0';
64
123
  scratch[4] = hexdig[(ch >> 4) & 0xf];
65
124
  scratch[5] = hexdig[ch & 0xf];
66
125
  fbuffer_append(out_buffer, scratch, 6);
@@ -181,8 +240,8 @@ static void convert_ASCII_to_JSON(FBuffer *out_buffer, VALUE str, const char esc
181
240
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
182
241
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
183
242
  default:
184
- scratch[2] = hexdig[ch >> 12];
185
- scratch[3] = hexdig[(ch >> 8) & 0xf];
243
+ scratch[2] = '0';
244
+ scratch[3] = '0';
186
245
  scratch[4] = hexdig[(ch >> 4) & 0xf];
187
246
  scratch[5] = hexdig[ch & 0xf];
188
247
  fbuffer_append(out_buffer, scratch, 6);
@@ -217,9 +276,6 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
217
276
 
218
277
  if (RB_UNLIKELY(ch_len)) {
219
278
  switch (ch_len) {
220
- case 0:
221
- pos++;
222
- break;
223
279
  case 1: {
224
280
  FLUSH_POS(1);
225
281
  switch (ch) {
@@ -232,8 +288,8 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
232
288
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
233
289
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
234
290
  default: {
235
- scratch[2] = hexdig[ch >> 12];
236
- scratch[3] = hexdig[(ch >> 8) & 0xf];
291
+ scratch[2] = '0';
292
+ scratch[3] = '0';
237
293
  scratch[4] = hexdig[(ch >> 4) & 0xf];
238
294
  scratch[5] = hexdig[ch & 0xf];
239
295
  fbuffer_append(out_buffer, scratch, 6);
@@ -303,14 +359,6 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
303
359
  RB_GC_GUARD(str);
304
360
  }
305
361
 
306
- static char *fstrndup(const char *ptr, unsigned long len) {
307
- char *result;
308
- if (len <= 0) return NULL;
309
- result = ALLOC_N(char, len);
310
- memcpy(result, ptr, len);
311
- return result;
312
- }
313
-
314
362
  /*
315
363
  * Document-module: JSON::Ext::Generator
316
364
  *
@@ -512,7 +560,7 @@ static VALUE mString_to_json_raw_object(VALUE self)
512
560
  VALUE result = rb_hash_new();
513
561
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
514
562
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
515
- rb_hash_aset(result, rb_str_new2("raw"), ary);
563
+ rb_hash_aset(result, rb_utf8_str_new_lit("raw"), ary);
516
564
  return result;
517
565
  }
518
566
 
@@ -593,27 +641,35 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
593
641
  return cState_partial_generate(state, string, generate_json_string);
594
642
  }
595
643
 
644
+ static void State_mark(void *ptr)
645
+ {
646
+ JSON_Generator_State *state = ptr;
647
+ rb_gc_mark_movable(state->indent);
648
+ rb_gc_mark_movable(state->space);
649
+ rb_gc_mark_movable(state->space_before);
650
+ rb_gc_mark_movable(state->object_nl);
651
+ rb_gc_mark_movable(state->array_nl);
652
+ }
653
+
654
+ static void State_compact(void *ptr)
655
+ {
656
+ JSON_Generator_State *state = ptr;
657
+ state->indent = rb_gc_location(state->indent);
658
+ state->space = rb_gc_location(state->space);
659
+ state->space_before = rb_gc_location(state->space_before);
660
+ state->object_nl = rb_gc_location(state->object_nl);
661
+ state->array_nl = rb_gc_location(state->array_nl);
662
+ }
663
+
596
664
  static void State_free(void *ptr)
597
665
  {
598
666
  JSON_Generator_State *state = ptr;
599
- if (state->indent) ruby_xfree(state->indent);
600
- if (state->space) ruby_xfree(state->space);
601
- if (state->space_before) ruby_xfree(state->space_before);
602
- if (state->object_nl) ruby_xfree(state->object_nl);
603
- if (state->array_nl) ruby_xfree(state->array_nl);
604
667
  ruby_xfree(state);
605
668
  }
606
669
 
607
670
  static size_t State_memsize(const void *ptr)
608
671
  {
609
- const JSON_Generator_State *state = ptr;
610
- size_t size = sizeof(*state);
611
- if (state->indent) size += state->indent_len + 1;
612
- if (state->space) size += state->space_len + 1;
613
- if (state->space_before) size += state->space_before_len + 1;
614
- if (state->object_nl) size += state->object_nl_len + 1;
615
- if (state->array_nl) size += state->array_nl_len + 1;
616
- return size;
672
+ return sizeof(JSON_Generator_State);
617
673
  }
618
674
 
619
675
  #ifndef HAVE_RB_EXT_RACTOR_SAFE
@@ -623,24 +679,54 @@ static size_t State_memsize(const void *ptr)
623
679
 
624
680
  static const rb_data_type_t JSON_Generator_State_type = {
625
681
  "JSON/Generator/State",
626
- {NULL, State_free, State_memsize,},
682
+ {
683
+ .dmark = State_mark,
684
+ .dfree = State_free,
685
+ .dsize = State_memsize,
686
+ .dcompact = State_compact,
687
+ },
627
688
  0, 0,
628
689
  RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
629
690
  };
630
691
 
692
+ static void state_init(JSON_Generator_State *state)
693
+ {
694
+ state->max_nesting = 100;
695
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
696
+ }
697
+
631
698
  static VALUE cState_s_allocate(VALUE klass)
632
699
  {
633
700
  JSON_Generator_State *state;
634
701
  VALUE obj = TypedData_Make_Struct(klass, JSON_Generator_State, &JSON_Generator_State_type, state);
635
- state->max_nesting = 100;
636
- state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
702
+ state_init(state);
637
703
  return obj;
638
704
  }
639
705
 
706
+ static void vstate_spill(struct generate_json_data *data)
707
+ {
708
+ VALUE vstate = cState_s_allocate(cState);
709
+ GET_STATE(vstate);
710
+ MEMCPY(state, data->state, JSON_Generator_State, 1);
711
+ data->state = state;
712
+ data->vstate = vstate;
713
+ RB_OBJ_WRITTEN(vstate, Qundef, state->indent);
714
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space);
715
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space_before);
716
+ RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
717
+ RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
718
+ }
719
+
720
+ static inline VALUE vstate_get(struct generate_json_data *data)
721
+ {
722
+ if (RB_UNLIKELY(!data->vstate)) {
723
+ vstate_spill(data);
724
+ }
725
+ return data->vstate;
726
+ }
727
+
640
728
  struct hash_foreach_arg {
641
- FBuffer *buffer;
642
- JSON_Generator_State *state;
643
- VALUE Vstate;
729
+ struct generate_json_data *data;
644
730
  int iter;
645
731
  };
646
732
 
@@ -648,27 +734,32 @@ static int
648
734
  json_object_i(VALUE key, VALUE val, VALUE _arg)
649
735
  {
650
736
  struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
651
- FBuffer *buffer = arg->buffer;
652
- JSON_Generator_State *state = arg->state;
653
- VALUE Vstate = arg->Vstate;
737
+ struct generate_json_data *data = arg->data;
738
+
739
+ FBuffer *buffer = data->buffer;
740
+ JSON_Generator_State *state = data->state;
654
741
 
655
742
  long depth = state->depth;
656
743
  int j;
657
744
 
658
745
  if (arg->iter > 0) fbuffer_append_char(buffer, ',');
659
746
  if (RB_UNLIKELY(state->object_nl)) {
660
- fbuffer_append(buffer, state->object_nl, state->object_nl_len);
747
+ fbuffer_append_str(buffer, state->object_nl);
661
748
  }
662
749
  if (RB_UNLIKELY(state->indent)) {
663
750
  for (j = 0; j < depth; j++) {
664
- fbuffer_append(buffer, state->indent, state->indent_len);
751
+ fbuffer_append_str(buffer, state->indent);
665
752
  }
666
753
  }
667
754
 
668
755
  VALUE key_to_s;
669
756
  switch(rb_type(key)) {
670
757
  case T_STRING:
671
- key_to_s = key;
758
+ if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
759
+ key_to_s = key;
760
+ } else {
761
+ key_to_s = rb_funcall(key, i_to_s, 0);
762
+ }
672
763
  break;
673
764
  case T_SYMBOL:
674
765
  key_to_s = rb_sym2str(key);
@@ -678,47 +769,57 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
678
769
  break;
679
770
  }
680
771
 
681
- generate_json_string(buffer, Vstate, state, key_to_s);
682
- if (RB_UNLIKELY(state->space_before)) fbuffer_append(buffer, state->space_before, state->space_before_len);
772
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
773
+ generate_json_string(buffer, data, state, key_to_s);
774
+ } else {
775
+ generate_json(buffer, data, state, key_to_s);
776
+ }
777
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, state->space_before);
683
778
  fbuffer_append_char(buffer, ':');
684
- if (RB_UNLIKELY(state->space)) fbuffer_append(buffer, state->space, state->space_len);
685
- generate_json(buffer, Vstate, state, val);
779
+ if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, state->space);
780
+ generate_json(buffer, data, state, val);
686
781
 
687
782
  arg->iter++;
688
783
  return ST_CONTINUE;
689
784
  }
690
785
 
691
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
786
+ static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
692
787
  {
693
788
  long max_nesting = state->max_nesting;
694
789
  long depth = ++state->depth;
695
790
  int j;
696
- struct hash_foreach_arg arg;
697
791
 
698
792
  if (max_nesting != 0 && depth > max_nesting) {
699
793
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
700
794
  }
795
+
796
+ if (RHASH_SIZE(obj) == 0) {
797
+ fbuffer_append(buffer, "{}", 2);
798
+ --state->depth;
799
+ return;
800
+ }
801
+
701
802
  fbuffer_append_char(buffer, '{');
702
803
 
703
- arg.buffer = buffer;
704
- arg.state = state;
705
- arg.Vstate = Vstate;
706
- arg.iter = 0;
804
+ struct hash_foreach_arg arg = {
805
+ .data = data,
806
+ .iter = 0,
807
+ };
707
808
  rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
708
809
 
709
810
  depth = --state->depth;
710
811
  if (RB_UNLIKELY(state->object_nl)) {
711
- fbuffer_append(buffer, state->object_nl, state->object_nl_len);
812
+ fbuffer_append_str(buffer, state->object_nl);
712
813
  if (RB_UNLIKELY(state->indent)) {
713
814
  for (j = 0; j < depth; j++) {
714
- fbuffer_append(buffer, state->indent, state->indent_len);
815
+ fbuffer_append_str(buffer, state->indent);
715
816
  }
716
817
  }
717
818
  }
718
819
  fbuffer_append_char(buffer, '}');
719
820
  }
720
821
 
721
- static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
822
+ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
722
823
  {
723
824
  long max_nesting = state->max_nesting;
724
825
  long depth = ++state->depth;
@@ -726,34 +827,39 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
726
827
  if (max_nesting != 0 && depth > max_nesting) {
727
828
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
728
829
  }
830
+
831
+ if (RARRAY_LEN(obj) == 0) {
832
+ fbuffer_append(buffer, "[]", 2);
833
+ --state->depth;
834
+ return;
835
+ }
836
+
729
837
  fbuffer_append_char(buffer, '[');
730
- if (RB_UNLIKELY(state->array_nl)) fbuffer_append(buffer, state->array_nl, state->array_nl_len);
838
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
731
839
  for(i = 0; i < RARRAY_LEN(obj); i++) {
732
840
  if (i > 0) {
733
841
  fbuffer_append_char(buffer, ',');
734
- if (RB_UNLIKELY(state->array_nl)) fbuffer_append(buffer, state->array_nl, state->array_nl_len);
842
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
735
843
  }
736
844
  if (RB_UNLIKELY(state->indent)) {
737
845
  for (j = 0; j < depth; j++) {
738
- fbuffer_append(buffer, state->indent, state->indent_len);
846
+ fbuffer_append_str(buffer, state->indent);
739
847
  }
740
848
  }
741
- generate_json(buffer, Vstate, state, RARRAY_AREF(obj, i));
849
+ generate_json(buffer, data, state, RARRAY_AREF(obj, i));
742
850
  }
743
851
  state->depth = --depth;
744
852
  if (RB_UNLIKELY(state->array_nl)) {
745
- fbuffer_append(buffer, state->array_nl, state->array_nl_len);
853
+ fbuffer_append_str(buffer, state->array_nl);
746
854
  if (RB_UNLIKELY(state->indent)) {
747
855
  for (j = 0; j < depth; j++) {
748
- fbuffer_append(buffer, state->indent, state->indent_len);
856
+ fbuffer_append_str(buffer, state->indent);
749
857
  }
750
858
  }
751
859
  }
752
860
  fbuffer_append_char(buffer, ']');
753
861
  }
754
862
 
755
- static int usascii_encindex, utf8_encindex, binary_encindex;
756
-
757
863
  static inline int enc_utf8_compatible_p(int enc_idx)
758
864
  {
759
865
  if (enc_idx == usascii_encindex) return 1;
@@ -767,13 +873,14 @@ static inline VALUE ensure_valid_encoding(VALUE str)
767
873
  VALUE utf8_string;
768
874
  if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) {
769
875
  if (encindex == binary_encindex) {
770
- // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
771
- // TODO: Deprecate in 2.8.0
772
- // TODO: Remove in 3.0.0
773
876
  utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
774
877
  switch (rb_enc_str_coderange(utf8_string)) {
775
878
  case ENC_CODERANGE_7BIT:
879
+ return utf8_string;
776
880
  case ENC_CODERANGE_VALID:
881
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
882
+ // TODO: Raise in 3.0.0
883
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
777
884
  return utf8_string;
778
885
  break;
779
886
  }
@@ -784,7 +891,7 @@ static inline VALUE ensure_valid_encoding(VALUE str)
784
891
  return str;
785
892
  }
786
893
 
787
- static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
894
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
788
895
  {
789
896
  obj = ensure_valid_encoding(obj);
790
897
 
@@ -808,43 +915,43 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
808
915
  fbuffer_append_char(buffer, '"');
809
916
  }
810
917
 
811
- static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
918
+ static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
812
919
  {
813
920
  fbuffer_append(buffer, "null", 4);
814
921
  }
815
922
 
816
- static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
923
+ static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
817
924
  {
818
925
  fbuffer_append(buffer, "false", 5);
819
926
  }
820
927
 
821
- static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
928
+ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
822
929
  {
823
930
  fbuffer_append(buffer, "true", 4);
824
931
  }
825
932
 
826
- static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
933
+ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
827
934
  {
828
935
  fbuffer_append_long(buffer, FIX2LONG(obj));
829
936
  }
830
937
 
831
- static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
938
+ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
832
939
  {
833
940
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
834
941
  fbuffer_append_str(buffer, tmp);
835
942
  }
836
943
 
837
944
  #ifdef RUBY_INTEGER_UNIFICATION
838
- static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
945
+ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
839
946
  {
840
947
  if (FIXNUM_P(obj))
841
- generate_json_fixnum(buffer, Vstate, state, obj);
948
+ generate_json_fixnum(buffer, data, state, obj);
842
949
  else
843
- generate_json_bignum(buffer, Vstate, state, obj);
950
+ generate_json_bignum(buffer, data, state, obj);
844
951
  }
845
952
  #endif
846
953
 
847
- static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
954
+ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
848
955
  {
849
956
  double value = RFLOAT_VALUE(obj);
850
957
  char allow_nan = state->allow_nan;
@@ -859,20 +966,20 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
859
966
  fbuffer_append_str(buffer, tmp);
860
967
  }
861
968
 
862
- static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
969
+ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
863
970
  {
864
971
  VALUE tmp;
865
972
  if (obj == Qnil) {
866
- generate_json_null(buffer, Vstate, state, obj);
973
+ generate_json_null(buffer, data, state, obj);
867
974
  } else if (obj == Qfalse) {
868
- generate_json_false(buffer, Vstate, state, obj);
975
+ generate_json_false(buffer, data, state, obj);
869
976
  } else if (obj == Qtrue) {
870
- generate_json_true(buffer, Vstate, state, obj);
977
+ generate_json_true(buffer, data, state, obj);
871
978
  } else if (RB_SPECIAL_CONST_P(obj)) {
872
979
  if (RB_FIXNUM_P(obj)) {
873
- generate_json_fixnum(buffer, Vstate, state, obj);
980
+ generate_json_fixnum(buffer, data, state, obj);
874
981
  } else if (RB_FLONUM_P(obj)) {
875
- generate_json_float(buffer, Vstate, state, obj);
982
+ generate_json_float(buffer, data, state, obj);
876
983
  } else {
877
984
  goto general;
878
985
  }
@@ -880,63 +987,46 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
880
987
  VALUE klass = RBASIC_CLASS(obj);
881
988
  switch (RB_BUILTIN_TYPE(obj)) {
882
989
  case T_BIGNUM:
883
- generate_json_bignum(buffer, Vstate, state, obj);
990
+ generate_json_bignum(buffer, data, state, obj);
884
991
  break;
885
992
  case T_HASH:
886
993
  if (klass != rb_cHash) goto general;
887
- generate_json_object(buffer, Vstate, state, obj);
994
+ generate_json_object(buffer, data, state, obj);
888
995
  break;
889
996
  case T_ARRAY:
890
997
  if (klass != rb_cArray) goto general;
891
- generate_json_array(buffer, Vstate, state, obj);
998
+ generate_json_array(buffer, data, state, obj);
892
999
  break;
893
1000
  case T_STRING:
894
1001
  if (klass != rb_cString) goto general;
895
- generate_json_string(buffer, Vstate, state, obj);
1002
+ generate_json_string(buffer, data, state, obj);
896
1003
  break;
897
1004
  case T_FLOAT:
898
1005
  if (klass != rb_cFloat) goto general;
899
- generate_json_float(buffer, Vstate, state, obj);
1006
+ generate_json_float(buffer, data, state, obj);
900
1007
  break;
901
1008
  default:
902
1009
  general:
903
1010
  if (state->strict) {
904
1011
  rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
905
1012
  } else if (rb_respond_to(obj, i_to_json)) {
906
- tmp = rb_funcall(obj, i_to_json, 1, Vstate);
1013
+ tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
907
1014
  Check_Type(tmp, T_STRING);
908
1015
  fbuffer_append_str(buffer, tmp);
909
1016
  } else {
910
1017
  tmp = rb_funcall(obj, i_to_s, 0);
911
1018
  Check_Type(tmp, T_STRING);
912
- generate_json_string(buffer, Vstate, state, tmp);
1019
+ generate_json_string(buffer, data, state, tmp);
913
1020
  }
914
1021
  }
915
1022
  }
916
1023
  }
917
1024
 
918
- static FBuffer *cState_prepare_buffer(VALUE self)
919
- {
920
- FBuffer *buffer;
921
- GET_STATE(self);
922
- buffer = fbuffer_alloc(state->buffer_initial_length);
923
-
924
- return buffer;
925
- }
926
-
927
- struct generate_json_data {
928
- FBuffer *buffer;
929
- VALUE vstate;
930
- JSON_Generator_State *state;
931
- VALUE obj;
932
- void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
933
- };
934
-
935
1025
  static VALUE generate_json_try(VALUE d)
936
1026
  {
937
1027
  struct generate_json_data *data = (struct generate_json_data *)d;
938
1028
 
939
- data->func(data->buffer, data->vstate, data->state, data->obj);
1029
+ data->func(data->buffer, data, data->state, data->obj);
940
1030
 
941
1031
  return Qnil;
942
1032
  }
@@ -946,18 +1036,25 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
946
1036
  struct generate_json_data *data = (struct generate_json_data *)d;
947
1037
  fbuffer_free(data->buffer);
948
1038
 
1039
+ if (RBASIC_CLASS(exc) == rb_path2class("Encoding::UndefinedConversionError")) {
1040
+ exc = rb_exc_new_str(eGeneratorError, rb_funcall(exc, rb_intern("message"), 0));
1041
+ }
1042
+
949
1043
  rb_exc_raise(exc);
950
1044
 
951
1045
  return Qundef;
952
1046
  }
953
1047
 
954
- static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj))
1048
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func)
955
1049
  {
956
- FBuffer *buffer = cState_prepare_buffer(self);
957
1050
  GET_STATE(self);
958
1051
 
1052
+ char stack_buffer[FBUFFER_STACK_SIZE];
1053
+ FBuffer buffer = {0};
1054
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1055
+
959
1056
  struct generate_json_data data = {
960
- .buffer = buffer,
1057
+ .buffer = &buffer,
961
1058
  .vstate = self,
962
1059
  .state = state,
963
1060
  .obj = obj,
@@ -965,7 +1062,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer
965
1062
  };
966
1063
  rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
967
1064
 
968
- return fbuffer_to_s(buffer);
1065
+ return fbuffer_to_s(&buffer);
969
1066
  }
970
1067
 
971
1068
  /*
@@ -1005,11 +1102,11 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1005
1102
  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1006
1103
 
1007
1104
  MEMCPY(objState, origState, JSON_Generator_State, 1);
1008
- objState->indent = fstrndup(origState->indent, origState->indent_len);
1009
- objState->space = fstrndup(origState->space, origState->space_len);
1010
- objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
1011
- objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
1012
- objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
1105
+ objState->indent = origState->indent;
1106
+ objState->space = origState->space;
1107
+ objState->space_before = origState->space_before;
1108
+ objState->object_nl = origState->object_nl;
1109
+ objState->array_nl = origState->array_nl;
1013
1110
  return obj;
1014
1111
  }
1015
1112
 
@@ -1039,7 +1136,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1039
1136
  static VALUE cState_indent(VALUE self)
1040
1137
  {
1041
1138
  GET_STATE(self);
1042
- return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
1139
+ return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0));
1140
+ }
1141
+
1142
+ static VALUE string_config(VALUE config)
1143
+ {
1144
+ if (RTEST(config)) {
1145
+ Check_Type(config, T_STRING);
1146
+ if (RSTRING_LEN(config)) {
1147
+ return rb_str_new_frozen(config);
1148
+ }
1149
+ }
1150
+ return Qfalse;
1043
1151
  }
1044
1152
 
1045
1153
  /*
@@ -1049,21 +1157,8 @@ static VALUE cState_indent(VALUE self)
1049
1157
  */
1050
1158
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1051
1159
  {
1052
- unsigned long len;
1053
1160
  GET_STATE(self);
1054
- Check_Type(indent, T_STRING);
1055
- len = RSTRING_LEN(indent);
1056
- if (len == 0) {
1057
- if (state->indent) {
1058
- ruby_xfree(state->indent);
1059
- state->indent = NULL;
1060
- state->indent_len = 0;
1061
- }
1062
- } else {
1063
- if (state->indent) ruby_xfree(state->indent);
1064
- state->indent = fstrndup(RSTRING_PTR(indent), len);
1065
- state->indent_len = len;
1066
- }
1161
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
1067
1162
  return Qnil;
1068
1163
  }
1069
1164
 
@@ -1076,7 +1171,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1076
1171
  static VALUE cState_space(VALUE self)
1077
1172
  {
1078
1173
  GET_STATE(self);
1079
- return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
1174
+ return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0));
1080
1175
  }
1081
1176
 
1082
1177
  /*
@@ -1087,21 +1182,8 @@ static VALUE cState_space(VALUE self)
1087
1182
  */
1088
1183
  static VALUE cState_space_set(VALUE self, VALUE space)
1089
1184
  {
1090
- unsigned long len;
1091
1185
  GET_STATE(self);
1092
- Check_Type(space, T_STRING);
1093
- len = RSTRING_LEN(space);
1094
- if (len == 0) {
1095
- if (state->space) {
1096
- ruby_xfree(state->space);
1097
- state->space = NULL;
1098
- state->space_len = 0;
1099
- }
1100
- } else {
1101
- if (state->space) ruby_xfree(state->space);
1102
- state->space = fstrndup(RSTRING_PTR(space), len);
1103
- state->space_len = len;
1104
- }
1186
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
1105
1187
  return Qnil;
1106
1188
  }
1107
1189
 
@@ -1113,7 +1195,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1113
1195
  static VALUE cState_space_before(VALUE self)
1114
1196
  {
1115
1197
  GET_STATE(self);
1116
- return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
1198
+ return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0));
1117
1199
  }
1118
1200
 
1119
1201
  /*
@@ -1123,21 +1205,8 @@ static VALUE cState_space_before(VALUE self)
1123
1205
  */
1124
1206
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1125
1207
  {
1126
- unsigned long len;
1127
1208
  GET_STATE(self);
1128
- Check_Type(space_before, T_STRING);
1129
- len = RSTRING_LEN(space_before);
1130
- if (len == 0) {
1131
- if (state->space_before) {
1132
- ruby_xfree(state->space_before);
1133
- state->space_before = NULL;
1134
- state->space_before_len = 0;
1135
- }
1136
- } else {
1137
- if (state->space_before) ruby_xfree(state->space_before);
1138
- state->space_before = fstrndup(RSTRING_PTR(space_before), len);
1139
- state->space_before_len = len;
1140
- }
1209
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
1141
1210
  return Qnil;
1142
1211
  }
1143
1212
 
@@ -1150,7 +1219,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1150
1219
  static VALUE cState_object_nl(VALUE self)
1151
1220
  {
1152
1221
  GET_STATE(self);
1153
- return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
1222
+ return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1154
1223
  }
1155
1224
 
1156
1225
  /*
@@ -1161,20 +1230,8 @@ static VALUE cState_object_nl(VALUE self)
1161
1230
  */
1162
1231
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1163
1232
  {
1164
- unsigned long len;
1165
1233
  GET_STATE(self);
1166
- Check_Type(object_nl, T_STRING);
1167
- len = RSTRING_LEN(object_nl);
1168
- if (len == 0) {
1169
- if (state->object_nl) {
1170
- ruby_xfree(state->object_nl);
1171
- state->object_nl = NULL;
1172
- }
1173
- } else {
1174
- if (state->object_nl) ruby_xfree(state->object_nl);
1175
- state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
1176
- state->object_nl_len = len;
1177
- }
1234
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
1178
1235
  return Qnil;
1179
1236
  }
1180
1237
 
@@ -1186,7 +1243,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1186
1243
  static VALUE cState_array_nl(VALUE self)
1187
1244
  {
1188
1245
  GET_STATE(self);
1189
- return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
1246
+ return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1190
1247
  }
1191
1248
 
1192
1249
  /*
@@ -1196,20 +1253,8 @@ static VALUE cState_array_nl(VALUE self)
1196
1253
  */
1197
1254
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1198
1255
  {
1199
- unsigned long len;
1200
1256
  GET_STATE(self);
1201
- Check_Type(array_nl, T_STRING);
1202
- len = RSTRING_LEN(array_nl);
1203
- if (len == 0) {
1204
- if (state->array_nl) {
1205
- ruby_xfree(state->array_nl);
1206
- state->array_nl = NULL;
1207
- }
1208
- } else {
1209
- if (state->array_nl) ruby_xfree(state->array_nl);
1210
- state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
1211
- state->array_nl_len = len;
1212
- }
1257
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
1213
1258
  return Qnil;
1214
1259
  }
1215
1260
 
@@ -1238,6 +1283,11 @@ static VALUE cState_max_nesting(VALUE self)
1238
1283
  return LONG2FIX(state->max_nesting);
1239
1284
  }
1240
1285
 
1286
+ static long long_config(VALUE num)
1287
+ {
1288
+ return RTEST(num) ? FIX2LONG(num) : 0;
1289
+ }
1290
+
1241
1291
  /*
1242
1292
  * call-seq: max_nesting=(depth)
1243
1293
  *
@@ -1247,8 +1297,7 @@ static VALUE cState_max_nesting(VALUE self)
1247
1297
  static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1248
1298
  {
1249
1299
  GET_STATE(self);
1250
- Check_Type(depth, T_FIXNUM);
1251
- state->max_nesting = FIX2LONG(depth);
1300
+ state->max_nesting = long_config(depth);
1252
1301
  return Qnil;
1253
1302
  }
1254
1303
 
@@ -1376,8 +1425,7 @@ static VALUE cState_depth(VALUE self)
1376
1425
  static VALUE cState_depth_set(VALUE self, VALUE depth)
1377
1426
  {
1378
1427
  GET_STATE(self);
1379
- Check_Type(depth, T_FIXNUM);
1380
- state->depth = FIX2LONG(depth);
1428
+ state->depth = long_config(depth);
1381
1429
  return Qnil;
1382
1430
  }
1383
1431
 
@@ -1392,6 +1440,15 @@ static VALUE cState_buffer_initial_length(VALUE self)
1392
1440
  return LONG2FIX(state->buffer_initial_length);
1393
1441
  }
1394
1442
 
1443
+ static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length)
1444
+ {
1445
+ Check_Type(buffer_initial_length, T_FIXNUM);
1446
+ long initial_length = FIX2LONG(buffer_initial_length);
1447
+ if (initial_length > 0) {
1448
+ state->buffer_initial_length = initial_length;
1449
+ }
1450
+ }
1451
+
1395
1452
  /*
1396
1453
  * call-seq: buffer_initial_length=(length)
1397
1454
  *
@@ -1400,16 +1457,73 @@ static VALUE cState_buffer_initial_length(VALUE self)
1400
1457
  */
1401
1458
  static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1402
1459
  {
1403
- long initial_length;
1404
1460
  GET_STATE(self);
1405
- Check_Type(buffer_initial_length, T_FIXNUM);
1406
- initial_length = FIX2LONG(buffer_initial_length);
1407
- if (initial_length > 0) {
1408
- state->buffer_initial_length = initial_length;
1409
- }
1461
+ buffer_initial_length_set(state, buffer_initial_length);
1410
1462
  return Qnil;
1411
1463
  }
1412
1464
 
1465
+ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
1466
+ {
1467
+ JSON_Generator_State *state = (JSON_Generator_State *)_arg;
1468
+
1469
+ if (key == sym_indent) { state->indent = string_config(val); }
1470
+ else if (key == sym_space) { state->space = string_config(val); }
1471
+ else if (key == sym_space_before) { state->space_before = string_config(val); }
1472
+ else if (key == sym_object_nl) { state->object_nl = string_config(val); }
1473
+ else if (key == sym_array_nl) { state->array_nl = string_config(val); }
1474
+ else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
1475
+ else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
1476
+ else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
1477
+ else if (key == sym_depth) { state->depth = long_config(val); }
1478
+ else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
1479
+ else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
1480
+ else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
1481
+ else if (key == sym_strict) { state->strict = RTEST(val); }
1482
+ return ST_CONTINUE;
1483
+ }
1484
+
1485
+ static void configure_state(JSON_Generator_State *state, VALUE config)
1486
+ {
1487
+ if (!RTEST(config)) return;
1488
+
1489
+ Check_Type(config, T_HASH);
1490
+
1491
+ if (!RHASH_SIZE(config)) return;
1492
+
1493
+ // We assume in most cases few keys are set so it's faster to go over
1494
+ // the provided keys than to check all possible keys.
1495
+ rb_hash_foreach(config, configure_state_i, (VALUE)state);
1496
+ }
1497
+
1498
+ static VALUE cState_configure(VALUE self, VALUE opts)
1499
+ {
1500
+ GET_STATE(self);
1501
+ configure_state(state, opts);
1502
+ return self;
1503
+ }
1504
+
1505
+ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts)
1506
+ {
1507
+ JSON_Generator_State state = {0};
1508
+ state_init(&state);
1509
+ configure_state(&state, opts);
1510
+
1511
+ char stack_buffer[FBUFFER_STACK_SIZE];
1512
+ FBuffer buffer = {0};
1513
+ fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1514
+
1515
+ struct generate_json_data data = {
1516
+ .buffer = &buffer,
1517
+ .vstate = Qfalse,
1518
+ .state = &state,
1519
+ .obj = obj,
1520
+ .func = generate_json,
1521
+ };
1522
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1523
+
1524
+ return fbuffer_to_s(&buffer);
1525
+ }
1526
+
1413
1527
  /*
1414
1528
  *
1415
1529
  */
@@ -1436,6 +1550,7 @@ void Init_generator(void)
1436
1550
  rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
1437
1551
  rb_define_method(cState, "initialize", cState_initialize, -1);
1438
1552
  rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
1553
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
1439
1554
 
1440
1555
  rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1441
1556
  rb_define_method(cState, "indent", cState_indent, 0);
@@ -1470,6 +1585,8 @@ void Init_generator(void)
1470
1585
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
1471
1586
  rb_define_method(cState, "generate", cState_generate, 1);
1472
1587
 
1588
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 2);
1589
+
1473
1590
  VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1474
1591
 
1475
1592
  VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
@@ -1524,6 +1641,20 @@ void Init_generator(void)
1524
1641
  i_extend = rb_intern("extend");
1525
1642
  i_encode = rb_intern("encode");
1526
1643
 
1644
+ sym_indent = ID2SYM(rb_intern("indent"));
1645
+ sym_space = ID2SYM(rb_intern("space"));
1646
+ sym_space_before = ID2SYM(rb_intern("space_before"));
1647
+ sym_object_nl = ID2SYM(rb_intern("object_nl"));
1648
+ sym_array_nl = ID2SYM(rb_intern("array_nl"));
1649
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
1650
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1651
+ sym_ascii_only = ID2SYM(rb_intern("ascii_only"));
1652
+ sym_depth = ID2SYM(rb_intern("depth"));
1653
+ sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
1654
+ sym_script_safe = ID2SYM(rb_intern("script_safe"));
1655
+ sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
1656
+ sym_strict = ID2SYM(rb_intern("strict"));
1657
+
1527
1658
  usascii_encindex = rb_usascii_encindex();
1528
1659
  utf8_encindex = rb_utf8_encindex();
1529
1660
  binary_encindex = rb_ascii8bit_encindex();