ruby_deep_clone 0.6.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/ext/deep_clone/deep_clone.c +87 -42
- data/ext/deep_clone/extconf.rb +1 -5
- data/lib/deep_clone.rb +1 -1
- metadata +20 -22
- data/deep_clone.gemspec +0 -27
- data/ext/deep_clone/deep_clone.h +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YmEwZmJkNDViNTAxMWUzMjFlZWVjOWMxNGMwZTE0MWI3ZDU4ZTU3ZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjU3ZjYxNjBiMWVkZThjZDE3NzU1NTYzYWZiNjY0ZGRlNjg0NDAxZA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YWIzODVlZjdlMWUwYmNkMDc1ZGIyMTY0YmJjMjBlNjg3NDQ2NzdiNjYyN2Uz
|
10
|
+
MDE1OTQyYWQ0YmQ5YzQxN2FhMTcyOWI5NTc1OGFhMDlkZTI4MTgxNGUyMGEx
|
11
|
+
Zjk5OTUxNDQ5OTk4OTNhMzk4NDA1YmE5YzBjNDVjNjZiZWFiZGM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Nzg2OWE1YWRkYTZjYzM1NGVjY2E4NGZiMjI1MGIwNDQ3MzM4YTE3OTZhMTkx
|
14
|
+
YTY2YmE0ZGM0ODNhY2MxNzg2YTk5MTI0NmFhNGI2ZWI1NmMwZTc4NDJiNDlj
|
15
|
+
NGQ4OWFkYWRhNGNmNWQxOTJmMmM4ZTc0MzllOGYzMjI4M2Q5M2Q=
|
data/ext/deep_clone/deep_clone.c
CHANGED
@@ -1,25 +1,28 @@
|
|
1
1
|
#include "deep_clone.h"
|
2
|
+
|
2
3
|
int ident = 0;
|
3
4
|
|
4
|
-
void
|
5
|
-
|
6
|
-
#
|
7
|
-
int i;
|
8
|
-
|
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
|
-
|
18
|
-
#
|
19
|
-
int i;
|
20
|
-
|
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))
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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)
|
69
|
-
|
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
|
72
|
-
|
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
|
-
|
80
|
-
|
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
|
-
}
|
113
|
+
}
|
114
|
+
else
|
115
|
+
{
|
87
116
|
new_obj = rb_obj_clone(object);
|
88
117
|
}
|
89
|
-
|
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
|
-
|
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
|
-
}
|
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
|
-
|
120
|
-
|
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))
|
161
|
+
if(OBJ_FROZEN(object))
|
162
|
+
{
|
163
|
+
OBJ_FREEZE(new_obj);
|
164
|
+
}
|
124
165
|
}
|
166
|
+
|
125
167
|
break;
|
126
168
|
}
|
127
|
-
|
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
|
-
|
179
|
+
|
180
|
+
return clone_object(argv, tracker);
|
136
181
|
}
|
data/ext/deep_clone/extconf.rb
CHANGED
data/lib/deep_clone.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'deep_clone/deep_clone'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_deep_clone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Balmer
|
@@ -10,50 +10,50 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-03-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: rake
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: '10.5'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
28
|
+
version: '10.5'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: rake-compiler
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ~>
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: 0.8.3
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- -
|
40
|
+
- - ~>
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 0.8.3
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
|
-
name:
|
44
|
+
name: rspec
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - ~>
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: '2.99'
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - ~>
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: '2.99'
|
57
57
|
description: Native implementation to create deep clones of Ruby objects
|
58
58
|
email:
|
59
59
|
- balmma@sysinf.ch
|
@@ -64,33 +64,31 @@ extensions:
|
|
64
64
|
- ext/deep_clone/extconf.rb
|
65
65
|
extra_rdoc_files: []
|
66
66
|
files:
|
67
|
-
- deep_clone.gemspec
|
68
67
|
- ext/deep_clone/deep_clone.c
|
69
|
-
- ext/deep_clone/deep_clone.h
|
70
68
|
- ext/deep_clone/extconf.rb
|
71
69
|
- lib/deep_clone.rb
|
72
70
|
homepage: https://github.com/balmma/ruby-deepclone
|
73
|
-
licenses:
|
71
|
+
licenses:
|
72
|
+
- MIT
|
74
73
|
metadata: {}
|
75
74
|
post_install_message:
|
76
75
|
rdoc_options: []
|
77
76
|
require_paths:
|
78
|
-
- ext
|
79
77
|
- lib
|
80
78
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
79
|
requirements:
|
82
|
-
- -
|
80
|
+
- - ! '>='
|
83
81
|
- !ruby/object:Gem::Version
|
84
82
|
version: '0'
|
85
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
84
|
requirements:
|
87
|
-
- -
|
85
|
+
- - ! '>='
|
88
86
|
- !ruby/object:Gem::Version
|
89
87
|
version: '0'
|
90
88
|
requirements: []
|
91
89
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
90
|
+
rubygems_version: 2.4.7
|
93
91
|
signing_key:
|
94
|
-
specification_version:
|
92
|
+
specification_version: 4
|
95
93
|
summary: Ruby native deep clone
|
96
94
|
test_files: []
|
data/deep_clone.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
-
s.rubygems_version = '1.3.5'
|
5
|
-
|
6
|
-
s.name = 'ruby_deep_clone'
|
7
|
-
s.version = '0.6.0'
|
8
|
-
s.date = '2014-01-21'
|
9
|
-
|
10
|
-
s.summary = "Ruby native deep clone"
|
11
|
-
s.description = "Native implementation to create deep clones of Ruby objects"
|
12
|
-
|
13
|
-
s.authors = ["Matthias Balmer", "Andre Medeiros", "Anthony Williams"]
|
14
|
-
s.email = ['balmma@sysinf.ch', 'me@andremedeiros.info', 'hi@antw.io']
|
15
|
-
|
16
|
-
s.homepage = "https://github.com/balmma/ruby-deepclone"
|
17
|
-
|
18
|
-
s.extensions = ["ext/deep_clone/extconf.rb"]
|
19
|
-
|
20
|
-
s.require_paths = ["ext", "lib"]
|
21
|
-
|
22
|
-
s.files = ["deep_clone.gemspec","lib/deep_clone.rb","ext/deep_clone/deep_clone.c","ext/deep_clone/deep_clone.h","ext/deep_clone/extconf.rb"]
|
23
|
-
|
24
|
-
s.add_development_dependency 'rspec', '~> 2.13.0'
|
25
|
-
s.add_development_dependency 'rake-compiler', '~> 0.8.3'
|
26
|
-
s.add_development_dependency 'rake', '~> 10.0.4'
|
27
|
-
end
|
data/ext/deep_clone/deep_clone.h
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
#ifndef DEEP_CLONE_H
|
2
|
-
#define DEEP_CLONE_H
|
3
|
-
|
4
|
-
#include "ruby.h"
|
5
|
-
#include "ruby/st.h"
|
6
|
-
#include "ruby/version.h"
|
7
|
-
|
8
|
-
struct dump_call_arg {
|
9
|
-
VALUE obj;
|
10
|
-
VALUE tracker;
|
11
|
-
VALUE src;
|
12
|
-
};
|
13
|
-
|
14
|
-
// #define DC_DEBUG 0
|
15
|
-
|
16
|
-
#define OBJ_UNFREEZE(x) FL_UNSET((x), FL_FREEZE)
|
17
|
-
|
18
|
-
#ifdef SA_EMPTY
|
19
|
-
|
20
|
-
// Gotta do this because of 1.9.3's falcon patch
|
21
|
-
struct rb_classext_struct {
|
22
|
-
sa_table m_tbl;
|
23
|
-
sa_table iv_tbl;
|
24
|
-
sa_table const_tbl;
|
25
|
-
sa_table iv_index_tbl;
|
26
|
-
};
|
27
|
-
|
28
|
-
#define TABLE_FOREACH sa_foreach
|
29
|
-
#define DC_RCLASS_EXT(c) (RCLASS(c)->ptr)
|
30
|
-
#define DC_RCLASS_IV_INDEX_TBL(c) (&DC_RCLASS_EXT(c)->iv_index_tbl)
|
31
|
-
|
32
|
-
#else
|
33
|
-
// Make it work with vanilla ruby (including 2.0)
|
34
|
-
#define TABLE_FOREACH st_foreach
|
35
|
-
|
36
|
-
#if RUBY_API_VERSION_CODE >= 20100
|
37
|
-
|
38
|
-
// In Ruby 2.1, iv_index_tbl was moved into internal.h and cannot be accessed
|
39
|
-
// directly. We work around this by defining our own RCLASS helpers (since the
|
40
|
-
// rb_classext_struct returned by RCLASS_EXT is also effectively private).
|
41
|
-
typedef struct dc_iv_tbl_classext_struct {
|
42
|
-
struct st_table *iv_index_tbl;
|
43
|
-
} dc_iv_tbl_classext_t;
|
44
|
-
|
45
|
-
#define DC_RCLASS_EXT(c) ((dc_iv_tbl_classext_t *)RCLASS(c)->ptr)
|
46
|
-
#define DC_RCLASS_IV_INDEX_TBL(c) (DC_RCLASS_EXT(c)->iv_index_tbl)
|
47
|
-
|
48
|
-
#else
|
49
|
-
#define DC_RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
|
50
|
-
#endif
|
51
|
-
#endif
|
52
|
-
|
53
|
-
#define DC_ROBJECT_IV_INDEX_TBL(o) \
|
54
|
-
((RBASIC(o)->flags & ROBJECT_EMBED) ? \
|
55
|
-
DC_RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
|
56
|
-
ROBJECT(o)->as.heap.iv_index_tbl)
|
57
|
-
|
58
|
-
VALUE DeepClone = Qnil;
|
59
|
-
|
60
|
-
void Init_deep_clone();
|
61
|
-
static int clone_variable(st_data_t key, st_data_t index, struct dump_call_arg *arg);
|
62
|
-
static int hash_each(VALUE key, VALUE value, struct dump_call_arg *arg);
|
63
|
-
static VALUE clone_object(VALUE object, VALUE tracker);
|
64
|
-
|
65
|
-
VALUE deep_clone(int argc,VALUE argv);
|
66
|
-
|
67
|
-
#endif
|