1919KHASH_DECLARE (set , mrb_value , char , FALSE)
2020KHASH_DEFINE (set , mrb_value , char , FALSE, mrb_obj_hash_code , mrb_eql )
2121
22+ struct RSet {
23+ MRB_OBJECT_HEADER ;
24+ khash_t (set ) * kh ;
25+ };
26+
2227static void
2328set_copy_elements (mrb_state * mrb , khash_t (set ) * target_kh , khash_t (set ) * source_kh )
2429{
@@ -31,31 +36,60 @@ set_copy_elements(mrb_state *mrb, khash_t(set) *target_kh, khash_t(set) *source_
3136 }
3237}
3338
34- #define SET_KHASH_IV MRB_SYM(khash)
35-
39+ #define mrb_set_ptr (o ) ((struct RSet*)mrb_obj_ptr(o))
3640static void
37- set_free (mrb_state * mrb , void * ptr )
41+ set_set_khash (mrb_state * mrb , mrb_value self , khash_t ( set ) * kh )
3842{
39- khash_t (set ) * kh = (khash_t (set )* )ptr ;
40- if (kh ) {
41- kh_destroy (set , mrb , kh );
42- }
43+ mrb_check_type (mrb , self , MRB_TT_SET );
44+ struct RSet * set = mrb_set_ptr (self );
45+ set -> kh = kh ;
4346}
4447
45- static const struct mrb_data_type set_data_type = {
46- "Set" , set_free
47- };
48+ static khash_t (set ) *
49+ set_get_khash (mrb_state * mrb , mrb_value self )
50+ {
51+ mrb_check_type (mrb , self , MRB_TT_SET );
52+ return mrb_set_ptr (self )-> kh ;
53+ }
4854
49- static void
50- set_set_khash (mrb_state * mrb , mrb_value self , khash_t (set ) * kh )
55+ /* Mark function for Set instances */
56+ size_t
57+ mrb_gc_mark_set (mrb_state * mrb , struct RBasic * obj )
5158{
52- mrb_data_init (self , kh , & set_data_type );
59+ struct RSet * s = (struct RSet * )obj ;
60+ khash_t (set ) * kh = s -> kh ;
61+ if (!kh ) return 0 ;
62+
63+ KHASH_FOREACH (mrb , kh , k ) {
64+ if (kh_exist (kh , k )) {
65+ mrb_gc_mark_value (mrb , kh_key (kh , k ));
66+ }
67+ }
68+ return kh_size (kh );
5369}
5470
55- static khash_t (set ) *
56- set_get_khash (mrb_state * mrb , mrb_value self )
71+ void
72+ mrb_gc_free_set (mrb_state * mrb , struct RBasic * obj )
73+ {
74+ struct RSet * s = (struct RSet * )obj ;
75+ if (s -> kh ) {
76+ khash_t (set ) * kh = s -> kh ;
77+ if (kh ) {
78+ kh_destroy (set , mrb , kh );
79+ }
80+ }
81+ }
82+
83+ size_t
84+ mrb_set_memsize (mrb_value set )
5785{
58- return (khash_t (set )* )mrb_data_get_ptr (mrb , self , & set_data_type );
86+
87+ size_t size = mrb_objspace_page_slot_size ();
88+ struct RSet * s = mrb_set_ptr (set );
89+ if (s -> kh ) {
90+ size += kh_size (s -> kh ) * sizeof (mrb_value );
91+ }
92+ return size ;
5993}
6094
6195/* Helper function to check if a value is a Set and return a boolean result */
@@ -93,7 +127,10 @@ set_init_copy(mrb_state *mrb, mrb_value self)
93127 mrb_value orig = mrb_get_arg1 (mrb );
94128 khash_t (set ) * kh ;
95129
96- if (mrb_type (orig ) != MRB_TT_CDATA || (DATA_TYPE (self ) && DATA_TYPE (self ) != DATA_TYPE (orig ))) {
130+ if (mrb_type (orig ) != MRB_TT_SET ) {
131+ mrb_raise (mrb , E_TYPE_ERROR , "initialize_copy should take a Set object" );
132+ }
133+ if (mrb_obj_class (mrb , self ) != mrb_obj_class (mrb , orig )) {
97134 mrb_raise (mrb , E_TYPE_ERROR , "initialize_copy should take same class object" );
98135 }
99136
@@ -1356,7 +1393,7 @@ mrb_mruby_set_gem_init(mrb_state *mrb)
13561393 struct RClass * set ;
13571394
13581395 set = mrb_define_class (mrb , "Set" , mrb -> object_class );
1359- MRB_SET_INSTANCE_TT (set , MRB_TT_CDATA ); /* Set instances will hold a C pointer (khash) */
1396+ MRB_SET_INSTANCE_TT (set , MRB_TT_SET );
13601397
13611398 mrb_include_module (mrb , set , mrb_module_get (mrb , "Enumerable" ));
13621399
0 commit comments