@@ -27,14 +27,16 @@ typedef struct JSON_Generator_StateStruct {
2727 bool ascii_only ;
2828 bool script_safe ;
2929 bool strict ;
30+ bool rfc8785 ;
3031 VALUE sort_keys ;
3132} JSON_Generator_State ;
3233
33- static VALUE mJSON , cState , cFragment , eGeneratorError , eNestingError , Encoding_UTF_8 , default_sort_keys_proc ;
34+ static VALUE mJSON , cState , cFragment , eGeneratorError , eNestingError , Encoding_UTF_8 , default_sort_keys_proc ,
35+ rfc8785_number_formater_proc , rfc8785_sort_keys_proc ;
3436
3537static ID i_to_s , i_to_json , i_new , i_encode ;
3638static VALUE sym_indent , sym_space , sym_space_before , sym_object_nl , sym_array_nl , sym_max_nesting , sym_allow_nan , sym_allow_duplicate_key ,
37- sym_ascii_only , sym_depth , sym_buffer_initial_length , sym_script_safe , sym_strict , sym_as_json , sym_sort_keys ;
39+ sym_ascii_only , sym_depth , sym_buffer_initial_length , sym_script_safe , sym_strict , sym_as_json , sym_sort_keys , sym_rfc8785 ;
3840
3941
4042#define GET_STATE_TO (self , state ) \
@@ -1052,7 +1054,10 @@ static inline long increase_depth(struct generate_json_data *data)
10521054
10531055static void generate_json_object (FBuffer * buffer , struct generate_json_data * data , VALUE obj )
10541056{
1055- if (RB_UNLIKELY (data -> state -> sort_keys )) {
1057+ if (RB_UNLIKELY (data -> state -> rfc8785 )) {
1058+ obj = rb_proc_call_with_block (rfc8785_sort_keys_proc , 1 , & obj , Qnil );
1059+ Check_Type (obj , T_HASH );
1060+ } else if (RB_UNLIKELY (data -> state -> sort_keys )) {
10561061 obj = rb_proc_call_with_block (data -> state -> sort_keys , 1 , & obj , Qnil );
10571062 Check_Type (obj , T_HASH );
10581063 }
@@ -1180,6 +1185,13 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
11801185 return ;
11811186 }
11821187
1188+ if (RB_UNLIKELY (data -> state -> rfc8785 )) {
1189+ VALUE str = rb_proc_call_with_block (rfc8785_number_formater_proc , 1 , & obj , Qnil );
1190+ Check_Type (str , T_STRING );
1191+ fbuffer_append_str (buffer , str );
1192+ return ;
1193+ }
1194+
11831195 /* This implementation writes directly into the buffer. We reserve
11841196 * the 32 characters that fpconv_dtoa states as its maximum.
11851197 */
@@ -1757,6 +1769,28 @@ static VALUE cState_set_default_sort_keys_proc(VALUE self, VALUE proc)
17571769 return default_sort_keys_proc = proc ;
17581770}
17591771
1772+ static VALUE cState_set_rfc8785_number_formater_proc (VALUE self , VALUE proc )
1773+ {
1774+ if (!rb_obj_is_proc (proc )) {
1775+ rb_raise (rb_eTypeError , "rfc8785_number_formater_proc must be a Proc" );
1776+ }
1777+ if (rfc8785_number_formater_proc ) {
1778+ rb_raise (rb_eArgError , "rfc8785_number_formater_proc can only be set once" );
1779+ }
1780+ return rfc8785_number_formater_proc = proc ;
1781+ }
1782+
1783+ static VALUE cState_set_rfc8785_sort_keys_proc (VALUE self , VALUE proc )
1784+ {
1785+ if (!rb_obj_is_proc (proc )) {
1786+ rb_raise (rb_eTypeError , "rfc8785_sort_keys_proc must be a Proc" );
1787+ }
1788+ if (rfc8785_sort_keys_proc ) {
1789+ rb_raise (rb_eArgError , "rfc8785_sort_keys_proc can only be set once" );
1790+ }
1791+ return rfc8785_sort_keys_proc = proc ;
1792+ }
1793+
17601794static VALUE normalize_sort_keys (VALUE value )
17611795{
17621796 if (rb_obj_is_proc (value )) {
@@ -1775,7 +1809,7 @@ static VALUE normalize_sort_keys(VALUE value)
17751809 *
17761810 * Get the value of sort_keys.
17771811 */
1778- static VALUE cState_sort_keys_p (VALUE self )
1812+ static VALUE cState_sort_keys (VALUE self )
17791813{
17801814 GET_STATE (self );
17811815 return state -> sort_keys ;
@@ -1795,7 +1829,33 @@ static VALUE cState_sort_keys_set(VALUE self, VALUE value)
17951829 rb_check_frozen (self );
17961830 GET_STATE (self );
17971831 RB_OBJ_WRITE (self , & state -> sort_keys , normalize_sort_keys (value ));
1798- return Qnil ;
1832+ return state -> sort_keys ;
1833+ }
1834+
1835+
1836+ /*
1837+ * call-seq: rfc8785?
1838+ *
1839+ * Get whether RFC8785 (canonicalization) is enabled.
1840+ */
1841+ static VALUE cState_rfc8785_p (VALUE self )
1842+ {
1843+ GET_STATE (self );
1844+ return state -> rfc8785 ? Qtrue : Qfalse ;
1845+ }
1846+
1847+ /*
1848+ * call-seq: rfc8785=
1849+ *
1850+ * Sets whether RFC8785 (canonicalization) is enabled.
1851+ */
1852+
1853+ static VALUE cState_rfc8785_set (VALUE self , VALUE value )
1854+ {
1855+ rb_check_frozen (self );
1856+ GET_STATE (self );
1857+ state -> rfc8785 = RTEST (value );
1858+ return state -> rfc8785 ? Qtrue : Qfalse ;
17991859}
18001860
18011861static VALUE cState_allow_duplicate_key_p (VALUE self )
@@ -1895,6 +1955,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
18951955 else if (key == sym_script_safe ) { state -> script_safe = RTEST (val ); }
18961956 else if (key == sym_strict ) { state -> strict = RTEST (val ); }
18971957 else if (key == sym_allow_duplicate_key ) { state -> allow_duplicate_key = RTEST (val ); }
1958+ else if (key == sym_rfc8785 ) { state -> rfc8785 = RTEST (val ); }
18981959 else if (key == sym_as_json ) {
18991960 VALUE proc = RTEST (val ) ? as_json_config (val ) : Qfalse ;
19001961 state -> as_json_single_arg = proc && rb_proc_arity (proc ) == 1 ;
@@ -1990,6 +2051,8 @@ void Init_generator(void)
19902051 VALUE mGenerator = rb_define_module_under (mExt , "Generator" );
19912052
19922053 rb_global_variable (& default_sort_keys_proc );
2054+ rb_global_variable (& rfc8785_number_formater_proc );
2055+ rb_global_variable (& rfc8785_sort_keys_proc );
19932056
19942057 rb_global_variable (& eGeneratorError );
19952058 eGeneratorError = rb_path2class ("JSON::GeneratorError" );
@@ -2001,6 +2064,8 @@ void Init_generator(void)
20012064 rb_define_alloc_func (cState , cState_s_allocate );
20022065 rb_define_singleton_method (cState , "from_state" , cState_from_state_s , 1 );
20032066 rb_define_singleton_method (cState , "default_sort_keys_proc=" , cState_set_default_sort_keys_proc , 1 );
2067+ rb_define_singleton_method (cState , "rfc8785_number_formater_proc=" , cState_set_rfc8785_number_formater_proc , 1 );
2068+ rb_define_singleton_method (cState , "rfc8785_sort_keys_proc=" , cState_set_rfc8785_sort_keys_proc , 1 );
20042069
20052070 rb_define_method (cState , "initialize" , cState_initialize , -1 );
20062071 rb_define_alias (cState , "initialize" , "initialize" ); // avoid method redefinition warnings
@@ -2038,8 +2103,10 @@ void Init_generator(void)
20382103 rb_define_method (cState , "buffer_initial_length=" , cState_buffer_initial_length_set , 1 );
20392104 rb_define_method (cState , "generate" , cState_generate , -1 );
20402105 rb_define_method (cState , "_generate_no_fallback" , cState_generate_no_fallback , -1 );
2041- rb_define_method (cState , "sort_keys" , cState_sort_keys_p , 0 );
2106+ rb_define_method (cState , "sort_keys" , cState_sort_keys , 0 );
20422107 rb_define_method (cState , "sort_keys=" , cState_sort_keys_set , 1 );
2108+ rb_define_method (cState , "rfc8785?" , cState_rfc8785_p , 0 );
2109+ rb_define_method (cState , "rfc8785=" , cState_rfc8785_set , 1 );
20432110
20442111 rb_define_private_method (cState , "allow_duplicate_key?" , cState_allow_duplicate_key_p , 0 );
20452112
@@ -2069,6 +2136,7 @@ void Init_generator(void)
20692136 sym_as_json = ID2SYM (rb_intern ("as_json" ));
20702137 sym_allow_duplicate_key = ID2SYM (rb_intern ("allow_duplicate_key" ));
20712138 sym_sort_keys = ID2SYM (rb_intern ("sort_keys" ));
2139+ sym_rfc8785 = ID2SYM (rb_intern ("rfc8785" ));
20722140
20732141 usascii_encindex = rb_usascii_encindex ();
20742142 utf8_encindex = rb_utf8_encindex ();
0 commit comments