json 2.7.5 → 2.9.1

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,71 @@
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, VALUE io);
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;
73
+
74
+ #ifdef RBIMPL_ATTR_NORETURN
75
+ RBIMPL_ATTR_NORETURN()
76
+ #endif
77
+ static void raise_generator_error_str(VALUE invalid_object, VALUE str)
78
+ {
79
+ VALUE exc = rb_exc_new_str(eGeneratorError, str);
80
+ rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object);
81
+ rb_exc_raise(exc);
82
+ }
83
+
84
+ #ifdef RBIMPL_ATTR_NORETURN
85
+ RBIMPL_ATTR_NORETURN()
86
+ #endif
87
+ #ifdef RBIMPL_ATTR_FORMAT
88
+ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
89
+ #endif
90
+ static void raise_generator_error(VALUE invalid_object, const char *fmt, ...)
91
+ {
92
+ va_list args;
93
+ va_start(args, fmt);
94
+ VALUE str = rb_vsprintf(fmt, args);
95
+ va_end(args);
96
+ raise_generator_error_str(invalid_object, str);
97
+ }
11
98
 
12
99
  /* Converts in_string to a JSON string (without the wrapping '"'
13
100
  * characters) in FBuffer out_buffer.
@@ -44,9 +131,6 @@ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char esca
44
131
 
45
132
  if (RB_UNLIKELY(ch_len)) {
46
133
  switch (ch_len) {
47
- case 0:
48
- pos++;
49
- break;
50
134
  case 1: {
51
135
  FLUSH_POS(1);
52
136
  switch (ch) {
@@ -59,8 +143,8 @@ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char esca
59
143
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
60
144
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
61
145
  default: {
62
- scratch[2] = hexdig[ch >> 12];
63
- scratch[3] = hexdig[(ch >> 8) & 0xf];
146
+ scratch[2] = '0';
147
+ scratch[3] = '0';
64
148
  scratch[4] = hexdig[(ch >> 4) & 0xf];
65
149
  scratch[5] = hexdig[ch & 0xf];
66
150
  fbuffer_append(out_buffer, scratch, 6);
@@ -71,7 +155,7 @@ static void convert_UTF8_to_JSON(FBuffer *out_buffer, VALUE str, const char esca
71
155
  }
72
156
  case 3: {
73
157
  unsigned char b2 = ptr[pos + 1];
74
- if (RB_UNLIKELY(out_script_safe && b2 == 0x80)) {
158
+ if (RB_UNLIKELY(out_script_safe && ch == 0xE2 && b2 == 0x80)) {
75
159
  unsigned char b3 = ptr[pos + 2];
76
160
  if (b3 == 0xA8) {
77
161
  FLUSH_POS(3);
@@ -181,8 +265,8 @@ static void convert_ASCII_to_JSON(FBuffer *out_buffer, VALUE str, const char esc
181
265
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
182
266
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
183
267
  default:
184
- scratch[2] = hexdig[ch >> 12];
185
- scratch[3] = hexdig[(ch >> 8) & 0xf];
268
+ scratch[2] = '0';
269
+ scratch[3] = '0';
186
270
  scratch[4] = hexdig[(ch >> 4) & 0xf];
187
271
  scratch[5] = hexdig[ch & 0xf];
188
272
  fbuffer_append(out_buffer, scratch, 6);
@@ -217,9 +301,6 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
217
301
 
218
302
  if (RB_UNLIKELY(ch_len)) {
219
303
  switch (ch_len) {
220
- case 0:
221
- pos++;
222
- break;
223
304
  case 1: {
224
305
  FLUSH_POS(1);
225
306
  switch (ch) {
@@ -232,8 +313,8 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
232
313
  case '\r': fbuffer_append(out_buffer, "\\r", 2); break;
233
314
  case '\t': fbuffer_append(out_buffer, "\\t", 2); break;
234
315
  default: {
235
- scratch[2] = hexdig[ch >> 12];
236
- scratch[3] = hexdig[(ch >> 8) & 0xf];
316
+ scratch[2] = '0';
317
+ scratch[3] = '0';
237
318
  scratch[4] = hexdig[(ch >> 4) & 0xf];
238
319
  scratch[5] = hexdig[ch & 0xf];
239
320
  fbuffer_append(out_buffer, scratch, 6);
@@ -303,14 +384,6 @@ static void convert_UTF8_to_ASCII_only_JSON(FBuffer *out_buffer, VALUE str, cons
303
384
  RB_GC_GUARD(str);
304
385
  }
305
386
 
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
387
  /*
315
388
  * Document-module: JSON::Ext::Generator
316
389
  *
@@ -405,7 +478,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
405
478
  {
406
479
  rb_check_arity(argc, 0, 1);
407
480
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
408
- return cState_partial_generate(Vstate, self, generate_json_object);
481
+ return cState_partial_generate(Vstate, self, generate_json_object, Qfalse);
409
482
  }
410
483
 
411
484
  /*
@@ -419,7 +492,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
419
492
  static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
420
493
  rb_check_arity(argc, 0, 1);
421
494
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
422
- return cState_partial_generate(Vstate, self, generate_json_array);
495
+ return cState_partial_generate(Vstate, self, generate_json_array, Qfalse);
423
496
  }
424
497
 
425
498
  #ifdef RUBY_INTEGER_UNIFICATION
@@ -432,7 +505,7 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
432
505
  {
433
506
  rb_check_arity(argc, 0, 1);
434
507
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
435
- return cState_partial_generate(Vstate, self, generate_json_integer);
508
+ return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse);
436
509
  }
437
510
 
438
511
  #else
@@ -445,7 +518,7 @@ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
445
518
  {
446
519
  rb_check_arity(argc, 0, 1);
447
520
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
448
- return cState_partial_generate(Vstate, self, generate_json_fixnum);
521
+ return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse);
449
522
  }
450
523
 
451
524
  /*
@@ -457,7 +530,7 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
457
530
  {
458
531
  rb_check_arity(argc, 0, 1);
459
532
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
460
- return cState_partial_generate(Vstate, self, generate_json_bignum);
533
+ return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse);
461
534
  }
462
535
  #endif
463
536
 
@@ -470,7 +543,7 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
470
543
  {
471
544
  rb_check_arity(argc, 0, 1);
472
545
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
473
- return cState_partial_generate(Vstate, self, generate_json_float);
546
+ return cState_partial_generate(Vstate, self, generate_json_float, Qfalse);
474
547
  }
475
548
 
476
549
  /*
@@ -495,7 +568,7 @@ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
495
568
  {
496
569
  rb_check_arity(argc, 0, 1);
497
570
  VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
498
- return cState_partial_generate(Vstate, self, generate_json_string);
571
+ return cState_partial_generate(Vstate, self, generate_json_string, Qfalse);
499
572
  }
500
573
 
501
574
  /*
@@ -512,7 +585,7 @@ static VALUE mString_to_json_raw_object(VALUE self)
512
585
  VALUE result = rb_hash_new();
513
586
  rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
514
587
  ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
515
- rb_hash_aset(result, rb_str_new2("raw"), ary);
588
+ rb_hash_aset(result, rb_utf8_str_new_lit("raw"), ary);
516
589
  return result;
517
590
  }
518
591
 
@@ -590,30 +663,38 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
590
663
  rb_scan_args(argc, argv, "01", &state);
591
664
  Check_Type(string, T_STRING);
592
665
  state = cState_from_state_s(cState, state);
593
- return cState_partial_generate(state, string, generate_json_string);
666
+ return cState_partial_generate(state, string, generate_json_string, Qfalse);
667
+ }
668
+
669
+ static void State_mark(void *ptr)
670
+ {
671
+ JSON_Generator_State *state = ptr;
672
+ rb_gc_mark_movable(state->indent);
673
+ rb_gc_mark_movable(state->space);
674
+ rb_gc_mark_movable(state->space_before);
675
+ rb_gc_mark_movable(state->object_nl);
676
+ rb_gc_mark_movable(state->array_nl);
677
+ }
678
+
679
+ static void State_compact(void *ptr)
680
+ {
681
+ JSON_Generator_State *state = ptr;
682
+ state->indent = rb_gc_location(state->indent);
683
+ state->space = rb_gc_location(state->space);
684
+ state->space_before = rb_gc_location(state->space_before);
685
+ state->object_nl = rb_gc_location(state->object_nl);
686
+ state->array_nl = rb_gc_location(state->array_nl);
594
687
  }
595
688
 
596
689
  static void State_free(void *ptr)
597
690
  {
598
691
  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
692
  ruby_xfree(state);
605
693
  }
606
694
 
607
695
  static size_t State_memsize(const void *ptr)
608
696
  {
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;
697
+ return sizeof(JSON_Generator_State);
617
698
  }
618
699
 
619
700
  #ifndef HAVE_RB_EXT_RACTOR_SAFE
@@ -623,24 +704,54 @@ static size_t State_memsize(const void *ptr)
623
704
 
624
705
  static const rb_data_type_t JSON_Generator_State_type = {
625
706
  "JSON/Generator/State",
626
- {NULL, State_free, State_memsize,},
707
+ {
708
+ .dmark = State_mark,
709
+ .dfree = State_free,
710
+ .dsize = State_memsize,
711
+ .dcompact = State_compact,
712
+ },
627
713
  0, 0,
628
714
  RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
629
715
  };
630
716
 
717
+ static void state_init(JSON_Generator_State *state)
718
+ {
719
+ state->max_nesting = 100;
720
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
721
+ }
722
+
631
723
  static VALUE cState_s_allocate(VALUE klass)
632
724
  {
633
725
  JSON_Generator_State *state;
634
726
  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;
727
+ state_init(state);
637
728
  return obj;
638
729
  }
639
730
 
731
+ static void vstate_spill(struct generate_json_data *data)
732
+ {
733
+ VALUE vstate = cState_s_allocate(cState);
734
+ GET_STATE(vstate);
735
+ MEMCPY(state, data->state, JSON_Generator_State, 1);
736
+ data->state = state;
737
+ data->vstate = vstate;
738
+ RB_OBJ_WRITTEN(vstate, Qundef, state->indent);
739
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space);
740
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space_before);
741
+ RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
742
+ RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
743
+ }
744
+
745
+ static inline VALUE vstate_get(struct generate_json_data *data)
746
+ {
747
+ if (RB_UNLIKELY(!data->vstate)) {
748
+ vstate_spill(data);
749
+ }
750
+ return data->vstate;
751
+ }
752
+
640
753
  struct hash_foreach_arg {
641
- FBuffer *buffer;
642
- JSON_Generator_State *state;
643
- VALUE Vstate;
754
+ struct generate_json_data *data;
644
755
  int iter;
645
756
  };
646
757
 
@@ -648,27 +759,32 @@ static int
648
759
  json_object_i(VALUE key, VALUE val, VALUE _arg)
649
760
  {
650
761
  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;
762
+ struct generate_json_data *data = arg->data;
763
+
764
+ FBuffer *buffer = data->buffer;
765
+ JSON_Generator_State *state = data->state;
654
766
 
655
767
  long depth = state->depth;
656
768
  int j;
657
769
 
658
770
  if (arg->iter > 0) fbuffer_append_char(buffer, ',');
659
771
  if (RB_UNLIKELY(state->object_nl)) {
660
- fbuffer_append(buffer, state->object_nl, state->object_nl_len);
772
+ fbuffer_append_str(buffer, state->object_nl);
661
773
  }
662
774
  if (RB_UNLIKELY(state->indent)) {
663
775
  for (j = 0; j < depth; j++) {
664
- fbuffer_append(buffer, state->indent, state->indent_len);
776
+ fbuffer_append_str(buffer, state->indent);
665
777
  }
666
778
  }
667
779
 
668
780
  VALUE key_to_s;
669
781
  switch(rb_type(key)) {
670
782
  case T_STRING:
671
- key_to_s = key;
783
+ if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
784
+ key_to_s = key;
785
+ } else {
786
+ key_to_s = rb_funcall(key, i_to_s, 0);
787
+ }
672
788
  break;
673
789
  case T_SYMBOL:
674
790
  key_to_s = rb_sym2str(key);
@@ -678,47 +794,57 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
678
794
  break;
679
795
  }
680
796
 
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);
797
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
798
+ generate_json_string(buffer, data, state, key_to_s);
799
+ } else {
800
+ generate_json(buffer, data, state, key_to_s);
801
+ }
802
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, state->space_before);
683
803
  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);
804
+ if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, state->space);
805
+ generate_json(buffer, data, state, val);
686
806
 
687
807
  arg->iter++;
688
808
  return ST_CONTINUE;
689
809
  }
690
810
 
691
- static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
811
+ static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
692
812
  {
693
813
  long max_nesting = state->max_nesting;
694
814
  long depth = ++state->depth;
695
815
  int j;
696
- struct hash_foreach_arg arg;
697
816
 
698
817
  if (max_nesting != 0 && depth > max_nesting) {
699
818
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
700
819
  }
820
+
821
+ if (RHASH_SIZE(obj) == 0) {
822
+ fbuffer_append(buffer, "{}", 2);
823
+ --state->depth;
824
+ return;
825
+ }
826
+
701
827
  fbuffer_append_char(buffer, '{');
702
828
 
703
- arg.buffer = buffer;
704
- arg.state = state;
705
- arg.Vstate = Vstate;
706
- arg.iter = 0;
829
+ struct hash_foreach_arg arg = {
830
+ .data = data,
831
+ .iter = 0,
832
+ };
707
833
  rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
708
834
 
709
835
  depth = --state->depth;
710
836
  if (RB_UNLIKELY(state->object_nl)) {
711
- fbuffer_append(buffer, state->object_nl, state->object_nl_len);
837
+ fbuffer_append_str(buffer, state->object_nl);
712
838
  if (RB_UNLIKELY(state->indent)) {
713
839
  for (j = 0; j < depth; j++) {
714
- fbuffer_append(buffer, state->indent, state->indent_len);
840
+ fbuffer_append_str(buffer, state->indent);
715
841
  }
716
842
  }
717
843
  }
718
844
  fbuffer_append_char(buffer, '}');
719
845
  }
720
846
 
721
- static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
847
+ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
722
848
  {
723
849
  long max_nesting = state->max_nesting;
724
850
  long depth = ++state->depth;
@@ -726,34 +852,39 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
726
852
  if (max_nesting != 0 && depth > max_nesting) {
727
853
  rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
728
854
  }
855
+
856
+ if (RARRAY_LEN(obj) == 0) {
857
+ fbuffer_append(buffer, "[]", 2);
858
+ --state->depth;
859
+ return;
860
+ }
861
+
729
862
  fbuffer_append_char(buffer, '[');
730
- if (RB_UNLIKELY(state->array_nl)) fbuffer_append(buffer, state->array_nl, state->array_nl_len);
863
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
731
864
  for(i = 0; i < RARRAY_LEN(obj); i++) {
732
865
  if (i > 0) {
733
866
  fbuffer_append_char(buffer, ',');
734
- if (RB_UNLIKELY(state->array_nl)) fbuffer_append(buffer, state->array_nl, state->array_nl_len);
867
+ if (RB_UNLIKELY(state->array_nl)) fbuffer_append_str(buffer, state->array_nl);
735
868
  }
736
869
  if (RB_UNLIKELY(state->indent)) {
737
870
  for (j = 0; j < depth; j++) {
738
- fbuffer_append(buffer, state->indent, state->indent_len);
871
+ fbuffer_append_str(buffer, state->indent);
739
872
  }
740
873
  }
741
- generate_json(buffer, Vstate, state, RARRAY_AREF(obj, i));
874
+ generate_json(buffer, data, state, RARRAY_AREF(obj, i));
742
875
  }
743
876
  state->depth = --depth;
744
877
  if (RB_UNLIKELY(state->array_nl)) {
745
- fbuffer_append(buffer, state->array_nl, state->array_nl_len);
878
+ fbuffer_append_str(buffer, state->array_nl);
746
879
  if (RB_UNLIKELY(state->indent)) {
747
880
  for (j = 0; j < depth; j++) {
748
- fbuffer_append(buffer, state->indent, state->indent_len);
881
+ fbuffer_append_str(buffer, state->indent);
749
882
  }
750
883
  }
751
884
  }
752
885
  fbuffer_append_char(buffer, ']');
753
886
  }
754
887
 
755
- static int usascii_encindex, utf8_encindex, binary_encindex;
756
-
757
888
  static inline int enc_utf8_compatible_p(int enc_idx)
758
889
  {
759
890
  if (enc_idx == usascii_encindex) return 1;
@@ -761,30 +892,42 @@ static inline int enc_utf8_compatible_p(int enc_idx)
761
892
  return 0;
762
893
  }
763
894
 
895
+ static VALUE encode_json_string_try(VALUE str)
896
+ {
897
+ return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
898
+ }
899
+
900
+ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
901
+ {
902
+ raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
903
+ return Qundef;
904
+ }
905
+
764
906
  static inline VALUE ensure_valid_encoding(VALUE str)
765
907
  {
766
908
  int encindex = RB_ENCODING_GET(str);
767
909
  VALUE utf8_string;
768
910
  if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) {
769
911
  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
912
  utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
774
913
  switch (rb_enc_str_coderange(utf8_string)) {
775
914
  case ENC_CODERANGE_7BIT:
915
+ return utf8_string;
776
916
  case ENC_CODERANGE_VALID:
917
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
918
+ // TODO: Raise in 3.0.0
919
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
777
920
  return utf8_string;
778
921
  break;
779
922
  }
780
923
  }
781
924
 
782
- str = rb_funcall(str, i_encode, 1, Encoding_UTF_8);
925
+ str = rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
783
926
  }
784
927
  return str;
785
928
  }
786
929
 
787
- static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
930
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
788
931
  {
789
932
  obj = ensure_valid_encoding(obj);
790
933
 
@@ -802,77 +945,75 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
802
945
  }
803
946
  break;
804
947
  default:
805
- rb_raise(rb_path2class("JSON::GeneratorError"), "source sequence is illegal/malformed utf-8");
948
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
806
949
  break;
807
950
  }
808
951
  fbuffer_append_char(buffer, '"');
809
952
  }
810
953
 
811
- static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
954
+ static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
812
955
  {
813
956
  fbuffer_append(buffer, "null", 4);
814
957
  }
815
958
 
816
- static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
959
+ static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
817
960
  {
818
961
  fbuffer_append(buffer, "false", 5);
819
962
  }
820
963
 
821
- static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
964
+ static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
822
965
  {
823
966
  fbuffer_append(buffer, "true", 4);
824
967
  }
825
968
 
826
- static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
969
+ static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
827
970
  {
828
971
  fbuffer_append_long(buffer, FIX2LONG(obj));
829
972
  }
830
973
 
831
- static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
974
+ static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
832
975
  {
833
976
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
834
977
  fbuffer_append_str(buffer, tmp);
835
978
  }
836
979
 
837
980
  #ifdef RUBY_INTEGER_UNIFICATION
838
- static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
981
+ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
839
982
  {
840
983
  if (FIXNUM_P(obj))
841
- generate_json_fixnum(buffer, Vstate, state, obj);
984
+ generate_json_fixnum(buffer, data, state, obj);
842
985
  else
843
- generate_json_bignum(buffer, Vstate, state, obj);
986
+ generate_json_bignum(buffer, data, state, obj);
844
987
  }
845
988
  #endif
846
989
 
847
- static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
990
+ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
848
991
  {
849
992
  double value = RFLOAT_VALUE(obj);
850
993
  char allow_nan = state->allow_nan;
851
994
  VALUE tmp = rb_funcall(obj, i_to_s, 0);
852
995
  if (!allow_nan) {
853
- if (isinf(value)) {
854
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", tmp);
855
- } else if (isnan(value)) {
856
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", tmp);
996
+ if (isinf(value) || isnan(value)) {
997
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", tmp);
857
998
  }
858
999
  }
859
1000
  fbuffer_append_str(buffer, tmp);
860
1001
  }
861
1002
 
862
- static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
1003
+ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
863
1004
  {
864
1005
  VALUE tmp;
865
1006
  if (obj == Qnil) {
866
- generate_json_null(buffer, Vstate, state, obj);
1007
+ generate_json_null(buffer, data, state, obj);
867
1008
  } else if (obj == Qfalse) {
868
- generate_json_false(buffer, Vstate, state, obj);
1009
+ generate_json_false(buffer, data, state, obj);
869
1010
  } else if (obj == Qtrue) {
870
- generate_json_true(buffer, Vstate, state, obj);
1011
+ generate_json_true(buffer, data, state, obj);
871
1012
  } else if (RB_SPECIAL_CONST_P(obj)) {
872
1013
  if (RB_FIXNUM_P(obj)) {
873
- generate_json_fixnum(buffer, Vstate, state, obj);
1014
+ generate_json_fixnum(buffer, data, state, obj);
874
1015
  } else if (RB_FLONUM_P(obj)) {
875
- generate_json_float(buffer, Vstate, state, obj);
1016
+ generate_json_float(buffer, data, state, obj);
876
1017
  } else {
877
1018
  goto general;
878
1019
  }
@@ -880,63 +1021,46 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
880
1021
  VALUE klass = RBASIC_CLASS(obj);
881
1022
  switch (RB_BUILTIN_TYPE(obj)) {
882
1023
  case T_BIGNUM:
883
- generate_json_bignum(buffer, Vstate, state, obj);
1024
+ generate_json_bignum(buffer, data, state, obj);
884
1025
  break;
885
1026
  case T_HASH:
886
1027
  if (klass != rb_cHash) goto general;
887
- generate_json_object(buffer, Vstate, state, obj);
1028
+ generate_json_object(buffer, data, state, obj);
888
1029
  break;
889
1030
  case T_ARRAY:
890
1031
  if (klass != rb_cArray) goto general;
891
- generate_json_array(buffer, Vstate, state, obj);
1032
+ generate_json_array(buffer, data, state, obj);
892
1033
  break;
893
1034
  case T_STRING:
894
1035
  if (klass != rb_cString) goto general;
895
- generate_json_string(buffer, Vstate, state, obj);
1036
+ generate_json_string(buffer, data, state, obj);
896
1037
  break;
897
1038
  case T_FLOAT:
898
1039
  if (klass != rb_cFloat) goto general;
899
- generate_json_float(buffer, Vstate, state, obj);
1040
+ generate_json_float(buffer, data, state, obj);
900
1041
  break;
901
1042
  default:
902
1043
  general:
903
1044
  if (state->strict) {
904
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
1045
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
905
1046
  } else if (rb_respond_to(obj, i_to_json)) {
906
- tmp = rb_funcall(obj, i_to_json, 1, Vstate);
1047
+ tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
907
1048
  Check_Type(tmp, T_STRING);
908
1049
  fbuffer_append_str(buffer, tmp);
909
1050
  } else {
910
1051
  tmp = rb_funcall(obj, i_to_s, 0);
911
1052
  Check_Type(tmp, T_STRING);
912
- generate_json_string(buffer, Vstate, state, tmp);
1053
+ generate_json_string(buffer, data, state, tmp);
913
1054
  }
914
1055
  }
915
1056
  }
916
1057
  }
917
1058
 
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
1059
  static VALUE generate_json_try(VALUE d)
936
1060
  {
937
1061
  struct generate_json_data *data = (struct generate_json_data *)d;
938
1062
 
939
- data->func(data->buffer, data->vstate, data->state, data->obj);
1063
+ data->func(data->buffer, data, data->state, data->obj);
940
1064
 
941
1065
  return Qnil;
942
1066
  }
@@ -951,13 +1075,18 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
951
1075
  return Qundef;
952
1076
  }
953
1077
 
954
- static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj))
1078
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
955
1079
  {
956
- FBuffer *buffer = cState_prepare_buffer(self);
957
1080
  GET_STATE(self);
958
1081
 
1082
+ char stack_buffer[FBUFFER_STACK_SIZE];
1083
+ FBuffer buffer = {
1084
+ .io = RTEST(io) ? io : Qfalse,
1085
+ };
1086
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1087
+
959
1088
  struct generate_json_data data = {
960
- .buffer = buffer,
1089
+ .buffer = &buffer,
961
1090
  .vstate = self,
962
1091
  .state = state,
963
1092
  .obj = obj,
@@ -965,19 +1094,12 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer
965
1094
  };
966
1095
  rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
967
1096
 
968
- return fbuffer_to_s(buffer);
1097
+ return fbuffer_finalize(&buffer);
969
1098
  }
970
1099
 
971
- /*
972
- * call-seq: generate(obj)
973
- *
974
- * Generates a valid JSON document from object +obj+ and returns the
975
- * result. If no valid JSON document can be created this method raises a
976
- * GeneratorError exception.
977
- */
978
- static VALUE cState_generate(VALUE self, VALUE obj)
1100
+ static VALUE cState_generate(VALUE self, VALUE obj, VALUE io)
979
1101
  {
980
- VALUE result = cState_partial_generate(self, obj, generate_json);
1102
+ VALUE result = cState_partial_generate(self, obj, generate_json, io);
981
1103
  GET_STATE(self);
982
1104
  (void)state;
983
1105
  return result;
@@ -1005,11 +1127,11 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1005
1127
  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1006
1128
 
1007
1129
  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);
1130
+ objState->indent = origState->indent;
1131
+ objState->space = origState->space;
1132
+ objState->space_before = origState->space_before;
1133
+ objState->object_nl = origState->object_nl;
1134
+ objState->array_nl = origState->array_nl;
1013
1135
  return obj;
1014
1136
  }
1015
1137
 
@@ -1039,7 +1161,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1039
1161
  static VALUE cState_indent(VALUE self)
1040
1162
  {
1041
1163
  GET_STATE(self);
1042
- return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
1164
+ return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0));
1165
+ }
1166
+
1167
+ static VALUE string_config(VALUE config)
1168
+ {
1169
+ if (RTEST(config)) {
1170
+ Check_Type(config, T_STRING);
1171
+ if (RSTRING_LEN(config)) {
1172
+ return rb_str_new_frozen(config);
1173
+ }
1174
+ }
1175
+ return Qfalse;
1043
1176
  }
1044
1177
 
1045
1178
  /*
@@ -1049,21 +1182,8 @@ static VALUE cState_indent(VALUE self)
1049
1182
  */
1050
1183
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1051
1184
  {
1052
- unsigned long len;
1053
1185
  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
- }
1186
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
1067
1187
  return Qnil;
1068
1188
  }
1069
1189
 
@@ -1076,7 +1196,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
1076
1196
  static VALUE cState_space(VALUE self)
1077
1197
  {
1078
1198
  GET_STATE(self);
1079
- return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
1199
+ return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0));
1080
1200
  }
1081
1201
 
1082
1202
  /*
@@ -1087,21 +1207,8 @@ static VALUE cState_space(VALUE self)
1087
1207
  */
1088
1208
  static VALUE cState_space_set(VALUE self, VALUE space)
1089
1209
  {
1090
- unsigned long len;
1091
1210
  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
- }
1211
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
1105
1212
  return Qnil;
1106
1213
  }
1107
1214
 
@@ -1113,7 +1220,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
1113
1220
  static VALUE cState_space_before(VALUE self)
1114
1221
  {
1115
1222
  GET_STATE(self);
1116
- return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
1223
+ return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0));
1117
1224
  }
1118
1225
 
1119
1226
  /*
@@ -1123,21 +1230,8 @@ static VALUE cState_space_before(VALUE self)
1123
1230
  */
1124
1231
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1125
1232
  {
1126
- unsigned long len;
1127
1233
  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
- }
1234
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
1141
1235
  return Qnil;
1142
1236
  }
1143
1237
 
@@ -1150,7 +1244,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1150
1244
  static VALUE cState_object_nl(VALUE self)
1151
1245
  {
1152
1246
  GET_STATE(self);
1153
- return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
1247
+ return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1154
1248
  }
1155
1249
 
1156
1250
  /*
@@ -1161,20 +1255,8 @@ static VALUE cState_object_nl(VALUE self)
1161
1255
  */
1162
1256
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1163
1257
  {
1164
- unsigned long len;
1165
1258
  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
- }
1259
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
1178
1260
  return Qnil;
1179
1261
  }
1180
1262
 
@@ -1186,7 +1268,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1186
1268
  static VALUE cState_array_nl(VALUE self)
1187
1269
  {
1188
1270
  GET_STATE(self);
1189
- return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
1271
+ return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0));
1190
1272
  }
1191
1273
 
1192
1274
  /*
@@ -1196,20 +1278,8 @@ static VALUE cState_array_nl(VALUE self)
1196
1278
  */
1197
1279
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1198
1280
  {
1199
- unsigned long len;
1200
1281
  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
- }
1282
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
1213
1283
  return Qnil;
1214
1284
  }
1215
1285
 
@@ -1238,6 +1308,11 @@ static VALUE cState_max_nesting(VALUE self)
1238
1308
  return LONG2FIX(state->max_nesting);
1239
1309
  }
1240
1310
 
1311
+ static long long_config(VALUE num)
1312
+ {
1313
+ return RTEST(num) ? FIX2LONG(num) : 0;
1314
+ }
1315
+
1241
1316
  /*
1242
1317
  * call-seq: max_nesting=(depth)
1243
1318
  *
@@ -1247,8 +1322,7 @@ static VALUE cState_max_nesting(VALUE self)
1247
1322
  static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1248
1323
  {
1249
1324
  GET_STATE(self);
1250
- Check_Type(depth, T_FIXNUM);
1251
- state->max_nesting = FIX2LONG(depth);
1325
+ state->max_nesting = long_config(depth);
1252
1326
  return Qnil;
1253
1327
  }
1254
1328
 
@@ -1376,8 +1450,7 @@ static VALUE cState_depth(VALUE self)
1376
1450
  static VALUE cState_depth_set(VALUE self, VALUE depth)
1377
1451
  {
1378
1452
  GET_STATE(self);
1379
- Check_Type(depth, T_FIXNUM);
1380
- state->depth = FIX2LONG(depth);
1453
+ state->depth = long_config(depth);
1381
1454
  return Qnil;
1382
1455
  }
1383
1456
 
@@ -1392,6 +1465,15 @@ static VALUE cState_buffer_initial_length(VALUE self)
1392
1465
  return LONG2FIX(state->buffer_initial_length);
1393
1466
  }
1394
1467
 
1468
+ static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length)
1469
+ {
1470
+ Check_Type(buffer_initial_length, T_FIXNUM);
1471
+ long initial_length = FIX2LONG(buffer_initial_length);
1472
+ if (initial_length > 0) {
1473
+ state->buffer_initial_length = initial_length;
1474
+ }
1475
+ }
1476
+
1395
1477
  /*
1396
1478
  * call-seq: buffer_initial_length=(length)
1397
1479
  *
@@ -1400,16 +1482,75 @@ static VALUE cState_buffer_initial_length(VALUE self)
1400
1482
  */
1401
1483
  static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1402
1484
  {
1403
- long initial_length;
1404
1485
  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
- }
1486
+ buffer_initial_length_set(state, buffer_initial_length);
1410
1487
  return Qnil;
1411
1488
  }
1412
1489
 
1490
+ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
1491
+ {
1492
+ JSON_Generator_State *state = (JSON_Generator_State *)_arg;
1493
+
1494
+ if (key == sym_indent) { state->indent = string_config(val); }
1495
+ else if (key == sym_space) { state->space = string_config(val); }
1496
+ else if (key == sym_space_before) { state->space_before = string_config(val); }
1497
+ else if (key == sym_object_nl) { state->object_nl = string_config(val); }
1498
+ else if (key == sym_array_nl) { state->array_nl = string_config(val); }
1499
+ else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
1500
+ else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
1501
+ else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
1502
+ else if (key == sym_depth) { state->depth = long_config(val); }
1503
+ else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
1504
+ else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
1505
+ else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
1506
+ else if (key == sym_strict) { state->strict = RTEST(val); }
1507
+ return ST_CONTINUE;
1508
+ }
1509
+
1510
+ static void configure_state(JSON_Generator_State *state, VALUE config)
1511
+ {
1512
+ if (!RTEST(config)) return;
1513
+
1514
+ Check_Type(config, T_HASH);
1515
+
1516
+ if (!RHASH_SIZE(config)) return;
1517
+
1518
+ // We assume in most cases few keys are set so it's faster to go over
1519
+ // the provided keys than to check all possible keys.
1520
+ rb_hash_foreach(config, configure_state_i, (VALUE)state);
1521
+ }
1522
+
1523
+ static VALUE cState_configure(VALUE self, VALUE opts)
1524
+ {
1525
+ GET_STATE(self);
1526
+ configure_state(state, opts);
1527
+ return self;
1528
+ }
1529
+
1530
+ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
1531
+ {
1532
+ JSON_Generator_State state = {0};
1533
+ state_init(&state);
1534
+ configure_state(&state, opts);
1535
+
1536
+ char stack_buffer[FBUFFER_STACK_SIZE];
1537
+ FBuffer buffer = {
1538
+ .io = RTEST(io) ? io : Qfalse,
1539
+ };
1540
+ fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1541
+
1542
+ struct generate_json_data data = {
1543
+ .buffer = &buffer,
1544
+ .vstate = Qfalse,
1545
+ .state = &state,
1546
+ .obj = obj,
1547
+ .func = generate_json,
1548
+ };
1549
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1550
+
1551
+ return fbuffer_finalize(&buffer);
1552
+ }
1553
+
1413
1554
  /*
1414
1555
  *
1415
1556
  */
@@ -1426,16 +1567,18 @@ void Init_generator(void)
1426
1567
  VALUE mExt = rb_define_module_under(mJSON, "Ext");
1427
1568
  VALUE mGenerator = rb_define_module_under(mExt, "Generator");
1428
1569
 
1570
+ rb_global_variable(&eGeneratorError);
1429
1571
  eGeneratorError = rb_path2class("JSON::GeneratorError");
1572
+
1573
+ rb_global_variable(&eNestingError);
1430
1574
  eNestingError = rb_path2class("JSON::NestingError");
1431
- rb_gc_register_mark_object(eGeneratorError);
1432
- rb_gc_register_mark_object(eNestingError);
1433
1575
 
1434
1576
  cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1435
1577
  rb_define_alloc_func(cState, cState_s_allocate);
1436
1578
  rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
1437
1579
  rb_define_method(cState, "initialize", cState_initialize, -1);
1438
1580
  rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
1581
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
1439
1582
 
1440
1583
  rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1441
1584
  rb_define_method(cState, "indent", cState_indent, 0);
@@ -1468,7 +1611,9 @@ void Init_generator(void)
1468
1611
  rb_define_method(cState, "depth=", cState_depth_set, 1);
1469
1612
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
1470
1613
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
1471
- rb_define_method(cState, "generate", cState_generate, 1);
1614
+ rb_define_private_method(cState, "_generate", cState_generate, 2);
1615
+
1616
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
1472
1617
 
1473
1618
  VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1474
1619
 
@@ -1524,6 +1669,20 @@ void Init_generator(void)
1524
1669
  i_extend = rb_intern("extend");
1525
1670
  i_encode = rb_intern("encode");
1526
1671
 
1672
+ sym_indent = ID2SYM(rb_intern("indent"));
1673
+ sym_space = ID2SYM(rb_intern("space"));
1674
+ sym_space_before = ID2SYM(rb_intern("space_before"));
1675
+ sym_object_nl = ID2SYM(rb_intern("object_nl"));
1676
+ sym_array_nl = ID2SYM(rb_intern("array_nl"));
1677
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
1678
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1679
+ sym_ascii_only = ID2SYM(rb_intern("ascii_only"));
1680
+ sym_depth = ID2SYM(rb_intern("depth"));
1681
+ sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
1682
+ sym_script_safe = ID2SYM(rb_intern("script_safe"));
1683
+ sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
1684
+ sym_strict = ID2SYM(rb_intern("strict"));
1685
+
1527
1686
  usascii_encindex = rb_usascii_encindex();
1528
1687
  utf8_encindex = rb_utf8_encindex();
1529
1688
  binary_encindex = rb_ascii8bit_encindex();