1
1
#include "deep_clone.h"
2
+
2
3
int ident = 0 ;
3
4
4
- void
5
- inspect ( VALUE val ) {
6
- #ifdef DC_DEBUG
7
- int i ;
8
- for ( i = 0 ; i <= ident - 1 ; i ++ ) {
5
+ void inspect ( VALUE val )
6
+ {
7
+ #if DC_DEBUG
8
+ for ( int i = 0 ; i <= ident - 1 ; ++ i )
9
+ {
9
10
printf ("\t" );
10
11
}
12
+
11
13
printf ("BEFORE %d " , BUILTIN_TYPE (val ));
12
14
printf ("INSPECT: %s\n" , RSTRING_PTR (rb_any_to_s (val )));
13
15
#endif
14
16
}
15
17
16
- void
17
- inspect_kvp ( ID key , VALUE val ) {
18
- #ifdef DC_DEBUG
19
- int i ;
20
- for ( i = 0 ; i <= ident - 1 ; i ++ ) {
18
+ void inspect_kvp ( ID key , VALUE val )
19
+ {
20
+ #if DC_DEBUG
21
+ for ( int i = 0 ; i <= ident - 1 ; ++ i )
22
+ {
21
23
printf ("\t" );
22
24
}
25
+
23
26
printf ("BEFORE %s %d %d" , RSTRING_PTR (rb_inspect (ID2SYM (key ))), val );
24
27
printf ("VALUE: %s => %s\n" , RSTRING_PTR (rb_inspect (ID2SYM (key ))), RSTRING_PTR (rb_any_to_s (val )));
25
28
#endif
@@ -33,60 +36,88 @@ void Init_deep_clone()
33
36
34
37
static int clone_variable (st_data_t key , st_data_t index , struct dump_call_arg * arg )
35
38
{
36
- VALUE val = rb_ivar_get (arg -> obj , (ID )key );
37
- inspect_kvp ((ID )key , val );
39
+ VALUE val = rb_ivar_get (arg -> obj , (ID ) key );
40
+ inspect_kvp ((ID ) key , val );
41
+
38
42
// Check if value is nil. For some reason, if you "force" an instance value
39
43
// to nil, the ||= operator won't work.
40
- if (!NIL_P (val )) rb_ivar_set (arg -> obj , (ID )key , clone_object (val ,arg -> tracker ));
44
+ if (!NIL_P (val ))
45
+ {
46
+ rb_ivar_set (arg -> obj , (ID ) key , clone_object (val , arg -> tracker ));
47
+ }
48
+
41
49
return ST_CONTINUE ;
42
50
}
43
51
44
52
static int hash_each (VALUE key , VALUE value , struct dump_call_arg * arg )
45
53
{
46
- rb_hash_aset (arg -> obj ,clone_object (key ,arg -> tracker ),clone_object (value ,arg -> tracker ));
54
+ rb_hash_aset (arg -> obj , clone_object (key , arg -> tracker ), clone_object (value , arg -> tracker ));
55
+
47
56
return ST_CONTINUE ;
48
57
}
49
58
50
59
static VALUE clone_object (VALUE object , VALUE tracker )
51
60
{
52
61
if (rb_special_const_p (object ))
62
+ {
53
63
return object ;
64
+ }
54
65
55
66
inspect (object );
56
67
57
68
VALUE new_obj ;
58
69
VALUE id = rb_obj_id (object );
59
70
60
- if (st_lookup (RHASH_TBL (tracker ), id , 0 )) {
61
- new_obj = rb_hash_aref (tracker ,id );
62
- } else {
63
- ident ++ ;
64
- switch (BUILTIN_TYPE (object )) {
71
+ if (st_lookup (RHASH_TBL (tracker ), id , 0 ))
72
+ {
73
+ new_obj = rb_hash_aref (tracker , id );
74
+ }
75
+ else
76
+ {
77
+ ++ ident ;
78
+
79
+ switch (BUILTIN_TYPE (object ))
80
+ {
65
81
case T_ARRAY :
66
82
new_obj = rb_ary_new2 (RARRAY_LEN (object ));
67
83
long len = RARRAY_LEN (object );
68
- if (len == 0 ) break ;
69
- rb_hash_aset (tracker ,id ,new_obj );
84
+ if (len == 0 )
85
+ {
86
+ break ;
87
+ }
88
+
89
+ rb_hash_aset (tracker , id , new_obj );
90
+
70
91
VALUE * ptr = RARRAY_PTR (object );
71
- while (len -- ) {
72
- rb_ary_push (new_obj ,clone_object (* ptr ,tracker ));
73
- ptr ++ ;
92
+ while (len -- )
93
+ {
94
+ rb_ary_push (new_obj , clone_object (* ptr , tracker ));
95
+
96
+ ++ ptr ;
74
97
}
98
+
75
99
break ;
76
100
case T_HASH :
77
101
new_obj = rb_hash_new ();
78
- rb_hash_aset (tracker ,id ,new_obj );
79
- struct dump_call_arg arg = {new_obj ,tracker , object };
80
- rb_hash_foreach (object , hash_each , (st_data_t )& arg );
102
+ rb_hash_aset (tracker , id , new_obj );
103
+
104
+ struct dump_call_arg arg = { new_obj , tracker , object };
105
+ rb_hash_foreach (object , hash_each , (st_data_t ) & arg );
106
+
81
107
break ;
82
108
case T_STRING :
83
109
case T_DATA :
84
- if (rb_obj_is_kind_of (object ,rb_cNumeric )){
110
+ if (rb_obj_is_kind_of (object , rb_cNumeric ))
111
+ {
85
112
new_obj = object ;
86
- } else {
113
+ }
114
+ else
115
+ {
87
116
new_obj = rb_obj_clone (object );
88
117
}
89
- rb_hash_aset (tracker ,id ,new_obj );
118
+
119
+ rb_hash_aset (tracker , id , new_obj );
120
+
90
121
break ;
91
122
case T_CLASS :
92
123
case T_MODULE :
@@ -100,37 +131,51 @@ static VALUE clone_object(VALUE object, VALUE tracker)
100
131
case T_STRUCT :
101
132
case T_FILE :
102
133
new_obj = object ;
103
- rb_hash_aset (tracker ,id ,new_obj );
134
+
135
+ rb_hash_aset (tracker , id , new_obj );
136
+
104
137
break ;
105
138
default :
106
- if (rb_obj_is_kind_of (object ,rb_cNumeric )){
139
+ if (rb_obj_is_kind_of (object , rb_cNumeric ))
140
+ {
107
141
new_obj = object ;
108
- rb_hash_aset (tracker ,id ,new_obj );
109
- } else {
142
+ rb_hash_aset (tracker , id , new_obj );
143
+ }
144
+ else
145
+ {
110
146
new_obj = rb_obj_clone (object );
111
147
112
148
// Unfreeze the new object
113
149
OBJ_UNFREEZE (new_obj );
114
150
115
- rb_hash_aset (tracker ,id ,new_obj );
151
+ rb_hash_aset (tracker , id , new_obj );
152
+
116
153
st_table * tbl = DC_ROBJECT_IV_INDEX_TBL (object );
117
154
118
- if (tbl ) {
119
- struct dump_call_arg arg = {new_obj ,tracker , object };
120
- TABLE_FOREACH (tbl , clone_variable , (st_data_t )& arg );
155
+ if (tbl )
156
+ {
157
+ struct dump_call_arg arg = { new_obj , tracker , object };
158
+ TABLE_FOREACH (tbl , clone_variable , (st_data_t ) & arg );
121
159
}
122
160
123
- if (OBJ_FROZEN (object )) OBJ_FREEZE (new_obj );
161
+ if (OBJ_FROZEN (object ))
162
+ {
163
+ OBJ_FREEZE (new_obj );
164
+ }
124
165
}
166
+
125
167
break ;
126
168
}
127
- ident -- ;
169
+
170
+ -- ident ;
128
171
}
172
+
129
173
return new_obj ;
130
174
}
131
175
132
- VALUE deep_clone (int argc ,VALUE argv )
176
+ VALUE deep_clone (int argc , VALUE argv )
133
177
{
134
178
VALUE tracker = rb_hash_new ();
135
- return clone_object (argv ,tracker );
179
+
180
+ return clone_object (argv , tracker );
136
181
}
0 commit comments