@@ -13,47 +13,47 @@ typedef struct
1313 int symbolize_path_keys ;
1414 int with_roots_info ;
1515} scan_options ;
16+
1617#define SCAN_OPTION_VALUE_MASK 1
1718#define SCAN_OPTION_SET_MASK (1 << 1)
1819#define SCAN_OPTION (options , field ) ((options)->field & SCAN_OPTION_VALUE_MASK)
1920#define SCAN_OPTION_IS_SET (options , field ) ((options)->field & SCAN_OPTION_SET_MASK)
2021#define SCAN_OPTION_SET (options , field , value ) ((options)->field = ((value) & SCAN_OPTION_VALUE_MASK) | SCAN_OPTION_SET_MASK)
2122#define SCAN_OPTION_FALSE (options , field ) \
2223 (!SCAN_OPTION(options, field) && ((options)->field & SCAN_OPTION_SET_MASK))
24+ #define OPTIONS_FIELDS (X ) \
25+ X(with_path) \
26+ X(verbose_error) \
27+ X(allow_comments) \
28+ X(dont_validate_strings) \
29+ X(allow_trailing_garbage) \
30+ X(allow_multiple_values) \
31+ X(allow_partial_values) \
32+ X(symbolize_path_keys) \
33+ X(with_roots_info)
34+
35+ static VALUE rb_cJsonScannerOptions ;
36+ enum
37+ {
38+ #define SCAN_KWARG_ENUM(field) SCAN_KWARG_##field,
39+ OPTIONS_FIELDS (SCAN_KWARG_ENUM )
40+ #undef SCAN_KWARG_ENUM
41+ SCAN_KWARGS_SIZE ,
42+ };
43+ static ID scan_kwargs_table [SCAN_KWARGS_SIZE ];
2344
2445static void scan_options_init (scan_options * options , VALUE kwargs )
2546{
26- options -> with_path = 0 ;
27- options -> verbose_error = 0 ;
28- options -> allow_comments = 0 ;
29- options -> dont_validate_strings = 0 ;
30- options -> allow_trailing_garbage = 0 ;
31- options -> allow_multiple_values = 0 ;
32- options -> allow_partial_values = 0 ;
33- options -> symbolize_path_keys = 0 ;
34- options -> with_roots_info = 0 ;
47+ memset (options , 0 , sizeof (* options ));
3548 if (kwargs != Qnil )
3649 {
3750 VALUE kwargs_values [SCAN_KWARGS_SIZE ];
3851 rb_get_kwargs (kwargs , scan_kwargs_table , 0 , SCAN_KWARGS_SIZE , kwargs_values );
39- if (kwargs_values [0 ] != Qundef )
40- SCAN_OPTION_SET (options , with_path , RTEST (kwargs_values [0 ]));
41- if (kwargs_values [1 ] != Qundef )
42- SCAN_OPTION_SET (options , verbose_error , RTEST (kwargs_values [1 ]));
43- if (kwargs_values [2 ] != Qundef )
44- SCAN_OPTION_SET (options , allow_comments , RTEST (kwargs_values [2 ]));
45- if (kwargs_values [3 ] != Qundef )
46- SCAN_OPTION_SET (options , dont_validate_strings , RTEST (kwargs_values [3 ]));
47- if (kwargs_values [4 ] != Qundef )
48- SCAN_OPTION_SET (options , allow_trailing_garbage , RTEST (kwargs_values [4 ]));
49- if (kwargs_values [5 ] != Qundef )
50- SCAN_OPTION_SET (options , allow_multiple_values , RTEST (kwargs_values [5 ]));
51- if (kwargs_values [6 ] != Qundef )
52- SCAN_OPTION_SET (options , allow_partial_values , RTEST (kwargs_values [6 ]));
53- if (kwargs_values [7 ] != Qundef )
54- SCAN_OPTION_SET (options , symbolize_path_keys , RTEST (kwargs_values [7 ]));
55- if (kwargs_values [8 ] != Qundef )
56- SCAN_OPTION_SET (options , with_roots_info , RTEST (kwargs_values [8 ]));
52+ #define SCAN_OPTION_SET_KWARG (field ) \
53+ if (kwargs_values[SCAN_KWARG_##field] != Qundef) \
54+ SCAN_OPTION_SET(options, field, RTEST(kwargs_values[SCAN_KWARG_##field]));
55+ OPTIONS_FIELDS (SCAN_OPTION_SET_KWARG )
56+ #undef SCAN_OPTION_SET_KWARG
5757 }
5858}
5959
@@ -68,12 +68,17 @@ static const rb_data_type_t options_type = {
6868 .dfree = RUBY_DEFAULT_FREE ,
6969 .dsize = options_size ,
7070 },
71- .flags = RUBY_TYPED_FREE_IMMEDIATELY ,
71+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
72+ #ifdef RUBY_TYPED_FROZEN_SHAREABLE
73+ | RUBY_TYPED_FROZEN_SHAREABLE
74+ #endif
75+ ,
7276};
7377
7478static VALUE options_alloc (VALUE self )
7579{
7680 scan_options * options ;
81+ // TypedData_Make_Struct zeroes options.
7782 return TypedData_Make_Struct (self , scan_options , & options_type , options );
7883}
7984
@@ -91,6 +96,50 @@ static VALUE options_m_initialize(int argc, VALUE *argv, VALUE self)
9196 return self ;
9297}
9398
99+ static VALUE options_m_initialize_copy (VALUE self , VALUE other )
100+ {
101+ scan_options * options , * other_options ;
102+ rb_call_super (1 , & other );
103+ TypedData_Get_Struct (self , scan_options , & options_type , options );
104+ TypedData_Get_Struct (other , scan_options , & options_type , other_options );
105+ * options = * other_options ;
106+ return self ;
107+ }
108+
109+ #define DEFINE_OPTIONS_ACCESSORS (field ) \
110+ static VALUE options_m_##field(VALUE self) \
111+ { \
112+ scan_options *options; \
113+ TypedData_Get_Struct(self, scan_options, &options_type, options); \
114+ if (!SCAN_OPTION_IS_SET(options, field)) \
115+ return Qnil; \
116+ return SCAN_OPTION(options, field) ? Qtrue : Qfalse; \
117+ } \
118+ static VALUE options_m_##field##_set(VALUE self, VALUE value) \
119+ { \
120+ scan_options *options; \
121+ rb_check_frozen(self); \
122+ TypedData_Get_Struct(self, scan_options, &options_type, options); \
123+ SCAN_OPTION_SET(options, field, RTEST(value)); \
124+ return value; \
125+ }
126+ OPTIONS_FIELDS (DEFINE_OPTIONS_ACCESSORS )
127+
128+ static VALUE options_m_equal (VALUE self , VALUE other )
129+ {
130+ scan_options * options , * other_options ;
131+ if (!rb_obj_is_kind_of (other , rb_cJsonScannerOptions ))
132+ return Qfalse ;
133+ TypedData_Get_Struct (self , scan_options , & options_type , options );
134+ TypedData_Get_Struct (other , scan_options , & options_type , other_options );
135+ #define OPTIONS_EQUAL (field ) \
136+ if (options->field != other_options->field) \
137+ return Qfalse;
138+ OPTIONS_FIELDS (OPTIONS_EQUAL )
139+ #undef OPTIONS_EQUAL
140+ return Qtrue ;
141+ }
142+
94143static VALUE options_m_inspect (VALUE self )
95144{
96145 VALUE res ;
@@ -100,15 +149,7 @@ static VALUE options_m_inspect(VALUE self)
100149#define APPEND_OPTION_INSPECT (field ) \
101150 if (SCAN_OPTION_IS_SET(options, field)) \
102151 rb_str_catf(res, #field ": %s, ", SCAN_OPTION(options, field) ? "true" : "false");
103- APPEND_OPTION_INSPECT (with_path )
104- APPEND_OPTION_INSPECT (verbose_error )
105- APPEND_OPTION_INSPECT (allow_comments )
106- APPEND_OPTION_INSPECT (dont_validate_strings )
107- APPEND_OPTION_INSPECT (allow_trailing_garbage )
108- APPEND_OPTION_INSPECT (allow_multiple_values )
109- APPEND_OPTION_INSPECT (allow_partial_values )
110- APPEND_OPTION_INSPECT (symbolize_path_keys )
111- APPEND_OPTION_INSPECT (with_roots_info )
152+ OPTIONS_FIELDS (APPEND_OPTION_INSPECT )
112153#undef APPEND_OPTION_INSPECT
113154 if (RSTRING_END (res )[-1 ] == ' ' )
114155 rb_str_resize (res , RSTRING_LEN (res ) - 2 );
@@ -121,7 +162,17 @@ static void init_options(VALUE json_scanner_module)
121162 rb_cJsonScannerOptions = rb_define_class_under (json_scanner_module , "Options" , rb_cObject );
122163 rb_define_alloc_func (rb_cJsonScannerOptions , options_alloc );
123164 rb_define_method (rb_cJsonScannerOptions , "initialize" , options_m_initialize , -1 );
165+ rb_define_method (rb_cJsonScannerOptions , "initialize_copy" , options_m_initialize_copy , 1 );
166+ #define DEFINE_OPTIONS_ACCESSOR_METHODS (field ) \
167+ rb_define_method(rb_cJsonScannerOptions, #field, options_m_##field, 0); \
168+ rb_define_method(rb_cJsonScannerOptions, #field "=", options_m_##field##_set, 1);
169+ OPTIONS_FIELDS (DEFINE_OPTIONS_ACCESSOR_METHODS )
170+ #undef DEFINE_OPTIONS_ACCESSOR_METHODS
171+ rb_define_method (rb_cJsonScannerOptions , "==" , options_m_equal , 1 );
124172 rb_define_method (rb_cJsonScannerOptions , "inspect" , options_m_inspect , 0 );
173+ #define INIT_SCAN_KWARG (field ) scan_kwargs_table[SCAN_KWARG_##field] = rb_intern(#field);
174+ OPTIONS_FIELDS (INIT_SCAN_KWARG )
175+ #undef INIT_SCAN_KWARG
125176}
126177
127178#endif /* JSON_SCANNER_OPTIONS_H */
0 commit comments