json 2.7.5 → 2.8.2

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.
@@ -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();