@@ -1609,15 +1609,30 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
1609
1609
return Qnil ;
1610
1610
}
1611
1611
1612
+ struct configure_state_data {
1613
+ JSON_Generator_State * state ;
1614
+ VALUE vstate ; // Ruby object that owns the state, or Qfalse if stack-allocated
1615
+ };
1616
+
1617
+ static inline void state_write_value (struct configure_state_data * data , VALUE * field , VALUE value )
1618
+ {
1619
+ if (RTEST (data -> vstate )) {
1620
+ RB_OBJ_WRITE (data -> vstate , field , value );
1621
+ } else {
1622
+ * field = value ;
1623
+ }
1624
+ }
1625
+
1612
1626
static int configure_state_i (VALUE key , VALUE val , VALUE _arg )
1613
1627
{
1614
- JSON_Generator_State * state = (JSON_Generator_State * )_arg ;
1628
+ struct configure_state_data * data = (struct configure_state_data * )_arg ;
1629
+ JSON_Generator_State * state = data -> state ;
1615
1630
1616
- if (key == sym_indent ) { state -> indent = string_config (val ); }
1617
- else if (key == sym_space ) { state -> space = string_config (val ); }
1618
- else if (key == sym_space_before ) { state -> space_before = string_config (val ); }
1619
- else if (key == sym_object_nl ) { state -> object_nl = string_config (val ); }
1620
- else if (key == sym_array_nl ) { state -> array_nl = string_config (val ); }
1631
+ if (key == sym_indent ) { state_write_value ( data , & state -> indent , string_config (val ) ); }
1632
+ else if (key == sym_space ) { state_write_value ( data , & state -> space , string_config (val ) ); }
1633
+ else if (key == sym_space_before ) { state_write_value ( data , & state -> space_before , string_config (val ) ); }
1634
+ else if (key == sym_object_nl ) { state_write_value ( data , & state -> object_nl , string_config (val ) ); }
1635
+ else if (key == sym_array_nl ) { state_write_value ( data , & state -> array_nl , string_config (val ) ); }
1621
1636
else if (key == sym_max_nesting ) { state -> max_nesting = long_config (val ); }
1622
1637
else if (key == sym_allow_nan ) { state -> allow_nan = RTEST (val ); }
1623
1638
else if (key == sym_ascii_only ) { state -> ascii_only = RTEST (val ); }
@@ -1626,35 +1641,43 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
1626
1641
else if (key == sym_script_safe ) { state -> script_safe = RTEST (val ); }
1627
1642
else if (key == sym_escape_slash ) { state -> script_safe = RTEST (val ); }
1628
1643
else if (key == sym_strict ) { state -> strict = RTEST (val ); }
1629
- else if (key == sym_as_json ) { state -> as_json = RTEST (val ) ? rb_convert_type (val , T_DATA , "Proc" , "to_proc" ) : Qfalse ; }
1644
+ else if (key == sym_as_json ) {
1645
+ VALUE proc = RTEST (val ) ? rb_convert_type (val , T_DATA , "Proc" , "to_proc" ) : Qfalse ;
1646
+ state_write_value (data , & state -> as_json , proc );
1647
+ }
1630
1648
return ST_CONTINUE ;
1631
1649
}
1632
1650
1633
- static void configure_state (JSON_Generator_State * state , VALUE config )
1651
+ static void configure_state (JSON_Generator_State * state , VALUE vstate , VALUE config )
1634
1652
{
1635
1653
if (!RTEST (config )) return ;
1636
1654
1637
1655
Check_Type (config , T_HASH );
1638
1656
1639
1657
if (!RHASH_SIZE (config )) return ;
1640
1658
1659
+ struct configure_state_data data = {
1660
+ .state = state ,
1661
+ .vstate = vstate
1662
+ };
1663
+
1641
1664
// We assume in most cases few keys are set so it's faster to go over
1642
1665
// the provided keys than to check all possible keys.
1643
- rb_hash_foreach (config , configure_state_i , (VALUE )state );
1666
+ rb_hash_foreach (config , configure_state_i , (VALUE )& data );
1644
1667
}
1645
1668
1646
1669
static VALUE cState_configure (VALUE self , VALUE opts )
1647
1670
{
1648
1671
GET_STATE (self );
1649
- configure_state (state , opts );
1672
+ configure_state (state , self , opts );
1650
1673
return self ;
1651
1674
}
1652
1675
1653
1676
static VALUE cState_m_generate (VALUE klass , VALUE obj , VALUE opts , VALUE io )
1654
1677
{
1655
1678
JSON_Generator_State state = {0 };
1656
1679
state_init (& state );
1657
- configure_state (& state , opts );
1680
+ configure_state (& state , Qfalse , opts );
1658
1681
1659
1682
char stack_buffer [FBUFFER_STACK_SIZE ];
1660
1683
FBuffer buffer = {
0 commit comments