@@ -1907,15 +1907,30 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
19071907 return Qnil ;
19081908}
19091909
1910+ struct configure_state_data {
1911+ JSON_Generator_State * state ;
1912+ VALUE vstate ; // Ruby object that owns the state, or Qfalse if stack-allocated
1913+ };
1914+
1915+ static inline void state_write_value (struct configure_state_data * data , VALUE * field , VALUE value )
1916+ {
1917+ if (RTEST (data -> vstate )) {
1918+ RB_OBJ_WRITE (data -> vstate , field , value );
1919+ } else {
1920+ * field = value ;
1921+ }
1922+ }
1923+
19101924static int configure_state_i (VALUE key , VALUE val , VALUE _arg )
19111925{
1912- JSON_Generator_State * state = (JSON_Generator_State * )_arg ;
1926+ struct configure_state_data * data = (struct configure_state_data * )_arg ;
1927+ JSON_Generator_State * state = data -> state ;
19131928
1914- if (key == sym_indent ) { state -> indent = string_config (val ); }
1915- else if (key == sym_space ) { state -> space = string_config (val ); }
1916- else if (key == sym_space_before ) { state -> space_before = string_config (val ); }
1917- else if (key == sym_object_nl ) { state -> object_nl = string_config (val ); }
1918- else if (key == sym_array_nl ) { state -> array_nl = string_config (val ); }
1929+ if (key == sym_indent ) { state_write_value ( data , & state -> indent , string_config (val ) ); }
1930+ else if (key == sym_space ) { state_write_value ( data , & state -> space , string_config (val ) ); }
1931+ else if (key == sym_space_before ) { state_write_value ( data , & state -> space_before , string_config (val ) ); }
1932+ else if (key == sym_object_nl ) { state_write_value ( data , & state -> object_nl , string_config (val ) ); }
1933+ else if (key == sym_array_nl ) { state_write_value ( data , & state -> array_nl , string_config (val ) ); }
19191934 else if (key == sym_max_nesting ) { state -> max_nesting = long_config (val ); }
19201935 else if (key == sym_allow_nan ) { state -> allow_nan = RTEST (val ); }
19211936 else if (key == sym_ascii_only ) { state -> ascii_only = RTEST (val ); }
@@ -1924,35 +1939,43 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
19241939 else if (key == sym_script_safe ) { state -> script_safe = RTEST (val ); }
19251940 else if (key == sym_escape_slash ) { state -> script_safe = RTEST (val ); }
19261941 else if (key == sym_strict ) { state -> strict = RTEST (val ); }
1927- else if (key == sym_as_json ) { state -> as_json = RTEST (val ) ? rb_convert_type (val , T_DATA , "Proc" , "to_proc" ) : Qfalse ; }
1942+ else if (key == sym_as_json ) {
1943+ VALUE proc = RTEST (val ) ? rb_convert_type (val , T_DATA , "Proc" , "to_proc" ) : Qfalse ;
1944+ state_write_value (data , & state -> as_json , proc );
1945+ }
19281946 return ST_CONTINUE ;
19291947}
19301948
1931- static void configure_state (JSON_Generator_State * state , VALUE config )
1949+ static void configure_state (JSON_Generator_State * state , VALUE vstate , VALUE config )
19321950{
19331951 if (!RTEST (config )) return ;
19341952
19351953 Check_Type (config , T_HASH );
19361954
19371955 if (!RHASH_SIZE (config )) return ;
19381956
1957+ struct configure_state_data data = {
1958+ .state = state ,
1959+ .vstate = vstate
1960+ };
1961+
19391962 // We assume in most cases few keys are set so it's faster to go over
19401963 // the provided keys than to check all possible keys.
1941- rb_hash_foreach (config , configure_state_i , (VALUE )state );
1964+ rb_hash_foreach (config , configure_state_i , (VALUE )& data );
19421965}
19431966
19441967static VALUE cState_configure (VALUE self , VALUE opts )
19451968{
19461969 GET_STATE (self );
1947- configure_state (state , opts );
1970+ configure_state (state , self , opts );
19481971 return self ;
19491972}
19501973
19511974static VALUE cState_m_generate (VALUE klass , VALUE obj , VALUE opts , VALUE io )
19521975{
19531976 JSON_Generator_State state = {0 };
19541977 state_init (& state );
1955- configure_state (& state , opts );
1978+ configure_state (& state , Qfalse , opts );
19561979
19571980 char stack_buffer [FBUFFER_STACK_SIZE ];
19581981 FBuffer buffer = {
0 commit comments