json 2.7.6 → 2.8.0.alpha1

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,20 +734,21 @@ 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
 
@@ -683,50 +770,56 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
683
770
  }
684
771
 
685
772
  if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
686
- generate_json_string(buffer, Vstate, state, key_to_s);
773
+ generate_json_string(buffer, data, state, key_to_s);
687
774
  } else {
688
- generate_json(buffer, Vstate, state, key_to_s);
775
+ generate_json(buffer, data, state, key_to_s);
689
776
  }
690
- if (RB_UNLIKELY(state->space_before)) fbuffer_append(buffer, state->space_before, state->space_before_len);
777
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, state->space_before);
691
778
  fbuffer_append_char(buffer, ':');
692
- if (RB_UNLIKELY(state->space)) fbuffer_append(buffer, state->space, state->space_len);
693
- 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);
694
781
 
695
782
  arg->iter++;
696
783
  return ST_CONTINUE;
697
784
  }
698
785
 
699
- 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)
700
787
  {
701
788
  long max_nesting = state->max_nesting;
702
789
  long depth = ++state->depth;
703
790
  int j;
704
- struct hash_foreach_arg arg;
705
791
 
706
792
  if (max_nesting != 0 && depth > max_nesting) {
707
793
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
708
794
  }
795
+
796
+ if (RHASH_SIZE(obj) == 0) {
797
+ fbuffer_append(buffer, "{}", 2);
798
+ --state->depth;
799
+ return;
800
+ }
801
+
709
802
  fbuffer_append_char(buffer, '{');
710
803
 
711
- arg.buffer = buffer;
712
- arg.state = state;
713
- arg.Vstate = Vstate;
714
- arg.iter = 0;
804
+ struct hash_foreach_arg arg = {
805
+ .data = data,
806
+ .iter = 0,
807
+ };
715
808
  rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
716
809
 
717
810
  depth = --state->depth;
718
811
  if (RB_UNLIKELY(state->object_nl)) {
719
- fbuffer_append(buffer, state->object_nl, state->object_nl_len);
812
+ fbuffer_append_str(buffer, state->object_nl);
720
813
  if (RB_UNLIKELY(state->indent)) {
721
814
  for (j = 0; j < depth; j++) {
722
- fbuffer_append(buffer, state->indent, state->indent_len);
815
+ fbuffer_append_str(buffer, state->indent);
723
816
  }
724
817
  }
725
818
  }
726
819
  fbuffer_append_char(buffer, '}');
727
820
  }
728
821
 
729
- 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)
730
823
  {
731
824
  long max_nesting = state->max_nesting;
732
825
  long depth = ++state->depth;
@@ -734,34 +827,39 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
734
827
  if (max_nesting != 0 && depth > max_nesting) {
735
828
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
736
829
  }
830
+
831
+ if (RARRAY_LEN(obj) == 0) {
832
+ fbuffer_append(buffer, "[]", 2);
833
+ --state->depth;
834
+ return;
835
+ }
836
+
737
837
  fbuffer_append_char(buffer, '[');
738
- 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);
739
839
  for(i = 0; i < RARRAY_LEN(obj); i++) {
740
840
  if (i > 0) {
741
841
  fbuffer_append_char(buffer, ',');
742
- 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);
743
843
  }
744
844
  if (RB_UNLIKELY(state->indent)) {
745
845
  for (j = 0; j < depth; j++) {
746
- fbuffer_append(buffer, state->indent, state->indent_len);
846
+ fbuffer_append_str(buffer, state->indent);
747
847
  }
748
848
  }
749
- generate_json(buffer, Vstate, state, RARRAY_AREF(obj, i));
849
+ generate_json(buffer, data, state, RARRAY_AREF(obj, i));
750
850
  }
751
851
  state->depth = --depth;
752
852
  if (RB_UNLIKELY(state->array_nl)) {
753
- fbuffer_append(buffer, state->array_nl, state->array_nl_len);
853
+ fbuffer_append_str(buffer, state->array_nl);
754
854
  if (RB_UNLIKELY(state->indent)) {
755
855
  for (j = 0; j < depth; j++) {
756
- fbuffer_append(buffer, state->indent, state->indent_len);
856
+ fbuffer_append_str(buffer, state->indent);
757
857
  }
758
858
  }
759
859
  }
760
860
  fbuffer_append_char(buffer, ']');
761
861
  }
762
862
 
763
- static int usascii_encindex, utf8_encindex, binary_encindex;
764
-
765
863
  static inline int enc_utf8_compatible_p(int enc_idx)
766
864
  {
767
865
  if (enc_idx == usascii_encindex) return 1;
@@ -775,13 +873,14 @@ static inline VALUE ensure_valid_encoding(VALUE str)
775
873
  VALUE utf8_string;
776
874
  if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) {
777
875
  if (encindex == binary_encindex) {
778
- // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
779
- // TODO: Deprecate in 2.8.0
780
- // TODO: Remove in 3.0.0
781
876
  utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
782
877
  switch (rb_enc_str_coderange(utf8_string)) {
783
878
  case ENC_CODERANGE_7BIT:
879
+ return utf8_string;
784
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");
785
884
  return utf8_string;
786
885
  break;
787
886
  }
@@ -792,7 +891,7 @@ static inline VALUE ensure_valid_encoding(VALUE str)
792
891
  return str;
793
892
  }
794
893
 
795
- 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)
796
895
  {
797
896
  obj = ensure_valid_encoding(obj);
798
897
 
@@ -816,43 +915,43 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
816
915
  fbuffer_append_char(buffer, '"');
817
916
  }
818
917
 
819
- 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)
820
919
  {
821
920
  fbuffer_append(buffer, "null", 4);
822
921
  }
823
922
 
824
- 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)
825
924
  {
826
925
  fbuffer_append(buffer, "false", 5);
827
926
  }
828
927
 
829
- 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)
830
929
  {
831
930
  fbuffer_append(buffer, "true", 4);
832
931
  }
833
932
 
834
- 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)
835
934
  {
836
935
  fbuffer_append_long(buffer, FIX2LONG(obj));
837
936
  }
838
937
 
839
- 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)
840
939
  {
841
940
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
842
941
  fbuffer_append_str(buffer, tmp);
843
942
  }
844
943
 
845
944
  #ifdef RUBY_INTEGER_UNIFICATION
846
- 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)
847
946
  {
848
947
  if (FIXNUM_P(obj))
849
- generate_json_fixnum(buffer, Vstate, state, obj);
948
+ generate_json_fixnum(buffer, data, state, obj);
850
949
  else
851
- generate_json_bignum(buffer, Vstate, state, obj);
950
+ generate_json_bignum(buffer, data, state, obj);
852
951
  }
853
952
  #endif
854
953
 
855
- 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)
856
955
  {
857
956
  double value = RFLOAT_VALUE(obj);
858
957
  char allow_nan = state->allow_nan;
@@ -867,20 +966,20 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
867
966
  fbuffer_append_str(buffer, tmp);
868
967
  }
869
968
 
870
- 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)
871
970
  {
872
971
  VALUE tmp;
873
972
  if (obj == Qnil) {
874
- generate_json_null(buffer, Vstate, state, obj);
973
+ generate_json_null(buffer, data, state, obj);
875
974
  } else if (obj == Qfalse) {
876
- generate_json_false(buffer, Vstate, state, obj);
975
+ generate_json_false(buffer, data, state, obj);
877
976
  } else if (obj == Qtrue) {
878
- generate_json_true(buffer, Vstate, state, obj);
977
+ generate_json_true(buffer, data, state, obj);
879
978
  } else if (RB_SPECIAL_CONST_P(obj)) {
880
979
  if (RB_FIXNUM_P(obj)) {
881
- generate_json_fixnum(buffer, Vstate, state, obj);
980
+ generate_json_fixnum(buffer, data, state, obj);
882
981
  } else if (RB_FLONUM_P(obj)) {
883
- generate_json_float(buffer, Vstate, state, obj);
982
+ generate_json_float(buffer, data, state, obj);
884
983
  } else {
885
984
  goto general;
886
985
  }
@@ -888,63 +987,46 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
888
987
  VALUE klass = RBASIC_CLASS(obj);
889
988
  switch (RB_BUILTIN_TYPE(obj)) {
890
989
  case T_BIGNUM:
891
- generate_json_bignum(buffer, Vstate, state, obj);
990
+ generate_json_bignum(buffer, data, state, obj);
892
991
  break;
893
992
  case T_HASH:
894
993
  if (klass != rb_cHash) goto general;
895
- generate_json_object(buffer, Vstate, state, obj);
994
+ generate_json_object(buffer, data, state, obj);
896
995
  break;
897
996
  case T_ARRAY:
898
997
  if (klass != rb_cArray) goto general;
899
- generate_json_array(buffer, Vstate, state, obj);
998
+ generate_json_array(buffer, data, state, obj);
900
999
  break;
901
1000
  case T_STRING:
902
1001
  if (klass != rb_cString) goto general;
903
- generate_json_string(buffer, Vstate, state, obj);
1002
+ generate_json_string(buffer, data, state, obj);
904
1003
  break;
905
1004
  case T_FLOAT:
906
1005
  if (klass != rb_cFloat) goto general;
907
- generate_json_float(buffer, Vstate, state, obj);
1006
+ generate_json_float(buffer, data, state, obj);
908
1007
  break;
909
1008
  default:
910
1009
  general:
911
1010
  if (state->strict) {
912
1011
  rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
913
1012
  } else if (rb_respond_to(obj, i_to_json)) {
914
- tmp = rb_funcall(obj, i_to_json, 1, Vstate);
1013
+ tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
915
1014
  Check_Type(tmp, T_STRING);
916
1015
  fbuffer_append_str(buffer, tmp);
917
1016
  } else {
918
1017
  tmp = rb_funcall(obj, i_to_s, 0);
919
1018
  Check_Type(tmp, T_STRING);
920
- generate_json_string(buffer, Vstate, state, tmp);
1019
+ generate_json_string(buffer, data, state, tmp);
921
1020
  }
922
1021
  }
923
1022
  }
924
1023
  }
925
1024
 
926
- static FBuffer *cState_prepare_buffer(VALUE self)
927
- {
928
- FBuffer *buffer;
929
- GET_STATE(self);
930
- buffer = fbuffer_alloc(state->buffer_initial_length);
931
-
932
- return buffer;
933
- }
934
-
935
- struct generate_json_data {
936
- FBuffer *buffer;
937
- VALUE vstate;
938
- JSON_Generator_State *state;
939
- VALUE obj;
940
- void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
941
- };
942
-
943
1025
  static VALUE generate_json_try(VALUE d)
944
1026
  {
945
1027
  struct generate_json_data *data = (struct generate_json_data *)d;
946
1028
 
947
- data->func(data->buffer, data->vstate, data->state, data->obj);
1029
+ data->func(data->buffer, data, data->state, data->obj);
948
1030
 
949
1031
  return Qnil;
950
1032
  }
@@ -954,18 +1036,25 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
954
1036
  struct generate_json_data *data = (struct generate_json_data *)d;
955
1037
  fbuffer_free(data->buffer);
956
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
+
957
1043
  rb_exc_raise(exc);
958
1044
 
959
1045
  return Qundef;
960
1046
  }
961
1047
 
962
- 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)
963
1049
  {
964
- FBuffer *buffer = cState_prepare_buffer(self);
965
1050
  GET_STATE(self);
966
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
+
967
1056
  struct generate_json_data data = {
968
- .buffer = buffer,
1057
+ .buffer = &buffer,
969
1058
  .vstate = self,
970
1059
  .state = state,
971
1060
  .obj = obj,
@@ -973,7 +1062,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer
973
1062
  };
974
1063
  rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
975
1064
 
976
- return fbuffer_to_s(buffer);
1065
+ return fbuffer_to_s(&buffer);
977
1066
  }
978
1067
 
979
1068
  /*
@@ -1013,11 +1102,11 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1013
1102
  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1014
1103
 
1015
1104
  MEMCPY(objState, origState, JSON_Generator_State, 1);
1016
- objState->indent = fstrndup(origState->indent, origState->indent_len);
1017
- objState->space = fstrndup(origState->space, origState->space_len);
1018
- objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
1019
- objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
1020
- 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;
1021
1110
  return obj;
1022
1111
  }
1023
1112
 
@@ -1047,7 +1136,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1047
1136
  static VALUE cState_indent(VALUE self)
1048
1137
  {
1049
1138
  GET_STATE(self);
1050
- 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;
1051
1151
  }
1052
1152
 
1053
1153
  /*
@@ -1057,21 +1157,8 @@ static VALUE cState_indent(VALUE self)
1057
1157
  */
1058
1158
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1059
1159
  {
1060
- unsigned long len;
1061
1160
  GET_STATE(self);
1062
- Check_Type(indent, T_STRING);
1063
- len = RSTRING_LEN(indent);
1064
- if (len == 0) {
1065
- if (state->indent) {
1066
- ruby_xfree(state->indent);
1067
- state->indent = NULL;
1068
- state->indent_len = 0;
1069
- }
1070
- } else {
1071
- if (state->indent) ruby_xfree(state->indent);
1072
- state->indent = fstrndup(RSTRING_PTR(indent), len);
1073
- state->indent_len = len;
1074
- }
1161
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
1075
1162
  return Qnil;
1076
1163
  }
1077
1164
 
@@ -1084,7 +1171,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1084
1171
  static VALUE cState_space(VALUE self)
1085
1172
  {
1086
1173
  GET_STATE(self);
1087
- 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));
1088
1175
  }
1089
1176
 
1090
1177
  /*
@@ -1095,21 +1182,8 @@ static VALUE cState_space(VALUE self)
1095
1182
  */
1096
1183
  static VALUE cState_space_set(VALUE self, VALUE space)
1097
1184
  {
1098
- unsigned long len;
1099
1185
  GET_STATE(self);
1100
- Check_Type(space, T_STRING);
1101
- len = RSTRING_LEN(space);
1102
- if (len == 0) {
1103
- if (state->space) {
1104
- ruby_xfree(state->space);
1105
- state->space = NULL;
1106
- state->space_len = 0;
1107
- }
1108
- } else {
1109
- if (state->space) ruby_xfree(state->space);
1110
- state->space = fstrndup(RSTRING_PTR(space), len);
1111
- state->space_len = len;
1112
- }
1186
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
1113
1187
  return Qnil;
1114
1188
  }
1115
1189
 
@@ -1121,7 +1195,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1121
1195
  static VALUE cState_space_before(VALUE self)
1122
1196
  {
1123
1197
  GET_STATE(self);
1124
- 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));
1125
1199
  }
1126
1200
 
1127
1201
  /*
@@ -1131,21 +1205,8 @@ static VALUE cState_space_before(VALUE self)
1131
1205
  */
1132
1206
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1133
1207
  {
1134
- unsigned long len;
1135
1208
  GET_STATE(self);
1136
- Check_Type(space_before, T_STRING);
1137
- len = RSTRING_LEN(space_before);
1138
- if (len == 0) {
1139
- if (state->space_before) {
1140
- ruby_xfree(state->space_before);
1141
- state->space_before = NULL;
1142
- state->space_before_len = 0;
1143
- }
1144
- } else {
1145
- if (state->space_before) ruby_xfree(state->space_before);
1146
- state->space_before = fstrndup(RSTRING_PTR(space_before), len);
1147
- state->space_before_len = len;
1148
- }
1209
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
1149
1210
  return Qnil;
1150
1211
  }
1151
1212
 
@@ -1158,7 +1219,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1158
1219
  static VALUE cState_object_nl(VALUE self)
1159
1220
  {
1160
1221
  GET_STATE(self);
1161
- 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));
1162
1223
  }
1163
1224
 
1164
1225
  /*
@@ -1169,20 +1230,8 @@ static VALUE cState_object_nl(VALUE self)
1169
1230
  */
1170
1231
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1171
1232
  {
1172
- unsigned long len;
1173
1233
  GET_STATE(self);
1174
- Check_Type(object_nl, T_STRING);
1175
- len = RSTRING_LEN(object_nl);
1176
- if (len == 0) {
1177
- if (state->object_nl) {
1178
- ruby_xfree(state->object_nl);
1179
- state->object_nl = NULL;
1180
- }
1181
- } else {
1182
- if (state->object_nl) ruby_xfree(state->object_nl);
1183
- state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
1184
- state->object_nl_len = len;
1185
- }
1234
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
1186
1235
  return Qnil;
1187
1236
  }
1188
1237
 
@@ -1194,7 +1243,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1194
1243
  static VALUE cState_array_nl(VALUE self)
1195
1244
  {
1196
1245
  GET_STATE(self);
1197
- 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));
1198
1247
  }
1199
1248
 
1200
1249
  /*
@@ -1204,20 +1253,8 @@ static VALUE cState_array_nl(VALUE self)
1204
1253
  */
1205
1254
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1206
1255
  {
1207
- unsigned long len;
1208
1256
  GET_STATE(self);
1209
- Check_Type(array_nl, T_STRING);
1210
- len = RSTRING_LEN(array_nl);
1211
- if (len == 0) {
1212
- if (state->array_nl) {
1213
- ruby_xfree(state->array_nl);
1214
- state->array_nl = NULL;
1215
- }
1216
- } else {
1217
- if (state->array_nl) ruby_xfree(state->array_nl);
1218
- state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
1219
- state->array_nl_len = len;
1220
- }
1257
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
1221
1258
  return Qnil;
1222
1259
  }
1223
1260
 
@@ -1246,6 +1283,11 @@ static VALUE cState_max_nesting(VALUE self)
1246
1283
  return LONG2FIX(state->max_nesting);
1247
1284
  }
1248
1285
 
1286
+ static long long_config(VALUE num)
1287
+ {
1288
+ return RTEST(num) ? FIX2LONG(num) : 0;
1289
+ }
1290
+
1249
1291
  /*
1250
1292
  * call-seq: max_nesting=(depth)
1251
1293
  *
@@ -1255,8 +1297,7 @@ static VALUE cState_max_nesting(VALUE self)
1255
1297
  static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1256
1298
  {
1257
1299
  GET_STATE(self);
1258
- Check_Type(depth, T_FIXNUM);
1259
- state->max_nesting = FIX2LONG(depth);
1300
+ state->max_nesting = long_config(depth);
1260
1301
  return Qnil;
1261
1302
  }
1262
1303
 
@@ -1384,8 +1425,7 @@ static VALUE cState_depth(VALUE self)
1384
1425
  static VALUE cState_depth_set(VALUE self, VALUE depth)
1385
1426
  {
1386
1427
  GET_STATE(self);
1387
- Check_Type(depth, T_FIXNUM);
1388
- state->depth = FIX2LONG(depth);
1428
+ state->depth = long_config(depth);
1389
1429
  return Qnil;
1390
1430
  }
1391
1431
 
@@ -1400,6 +1440,15 @@ static VALUE cState_buffer_initial_length(VALUE self)
1400
1440
  return LONG2FIX(state->buffer_initial_length);
1401
1441
  }
1402
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
+
1403
1452
  /*
1404
1453
  * call-seq: buffer_initial_length=(length)
1405
1454
  *
@@ -1408,16 +1457,73 @@ static VALUE cState_buffer_initial_length(VALUE self)
1408
1457
  */
1409
1458
  static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1410
1459
  {
1411
- long initial_length;
1412
1460
  GET_STATE(self);
1413
- Check_Type(buffer_initial_length, T_FIXNUM);
1414
- initial_length = FIX2LONG(buffer_initial_length);
1415
- if (initial_length > 0) {
1416
- state->buffer_initial_length = initial_length;
1417
- }
1461
+ buffer_initial_length_set(state, buffer_initial_length);
1418
1462
  return Qnil;
1419
1463
  }
1420
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
+
1421
1527
  /*
1422
1528
  *
1423
1529
  */
@@ -1444,6 +1550,7 @@ void Init_generator(void)
1444
1550
  rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
1445
1551
  rb_define_method(cState, "initialize", cState_initialize, -1);
1446
1552
  rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
1553
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
1447
1554
 
1448
1555
  rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1449
1556
  rb_define_method(cState, "indent", cState_indent, 0);
@@ -1478,6 +1585,8 @@ void Init_generator(void)
1478
1585
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
1479
1586
  rb_define_method(cState, "generate", cState_generate, 1);
1480
1587
 
1588
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 2);
1589
+
1481
1590
  VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1482
1591
 
1483
1592
  VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
@@ -1532,6 +1641,20 @@ void Init_generator(void)
1532
1641
  i_extend = rb_intern("extend");
1533
1642
  i_encode = rb_intern("encode");
1534
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
+
1535
1658
  usascii_encindex = rb_usascii_encindex();
1536
1659
  utf8_encindex = rb_utf8_encindex();
1537
1660
  binary_encindex = rb_ascii8bit_encindex();