ruby_deep_clone 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/deep_clone.gemspec +27 -0
- data/ext/deep_clone/deep_clone.c +79 -0
- data/ext/deep_clone/deep_clone.h +49 -0
- data/ext/deep_clone/extconf.rb +7 -0
- data/lib/deep_clone.rb +1 -0
- metadata +102 -0
data/deep_clone.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
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.2.0'
|
8
|
+
s.date = '2013-04-03'
|
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"]
|
14
|
+
s.email = ['balmma@sysinf.ch', 'me@andremedeiros.info']
|
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
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#include "deep_clone.h"
|
2
|
+
|
3
|
+
void Init_deep_clone()
|
4
|
+
{
|
5
|
+
DeepClone = rb_define_module("DeepClone");
|
6
|
+
rb_define_module_function(DeepClone, "clone", deep_clone, 1);
|
7
|
+
}
|
8
|
+
|
9
|
+
static int clone_variable(st_data_t key, st_data_t index, struct dump_call_arg *arg)
|
10
|
+
{
|
11
|
+
VALUE val = ROBJECT_IVPTR(arg->src)[(long)index];
|
12
|
+
rb_ivar_set(arg->obj, key, clone_object(val,arg->tracker));
|
13
|
+
return ST_CONTINUE;
|
14
|
+
}
|
15
|
+
|
16
|
+
static int hash_each(VALUE key, VALUE value, struct dump_call_arg *arg)
|
17
|
+
{
|
18
|
+
rb_hash_aset(arg->obj,clone_object(key,arg->tracker),clone_object(value,arg->tracker));
|
19
|
+
return ST_CONTINUE;
|
20
|
+
}
|
21
|
+
|
22
|
+
static VALUE clone_object(VALUE object, VALUE tracker)
|
23
|
+
{
|
24
|
+
if(rb_special_const_p(object))
|
25
|
+
return object;
|
26
|
+
|
27
|
+
VALUE new_obj;
|
28
|
+
VALUE id = rb_obj_id(object);
|
29
|
+
|
30
|
+
if(st_lookup(RHASH_TBL(tracker), id, 0)) {
|
31
|
+
new_obj = rb_hash_aref(tracker,id);
|
32
|
+
} else {
|
33
|
+
switch (BUILTIN_TYPE(object)) {
|
34
|
+
case T_ARRAY:
|
35
|
+
new_obj = rb_ary_new2(RARRAY_LEN(object));
|
36
|
+
long len = RARRAY_LEN(object);
|
37
|
+
rb_hash_aset(tracker,id,new_obj);
|
38
|
+
VALUE *ptr = RARRAY_PTR(object);
|
39
|
+
while (len--) {
|
40
|
+
rb_ary_push(new_obj,clone_object(*ptr,tracker));
|
41
|
+
ptr++;
|
42
|
+
}
|
43
|
+
break;
|
44
|
+
case T_HASH:
|
45
|
+
new_obj = rb_hash_new();
|
46
|
+
rb_hash_aset(tracker,id,new_obj);
|
47
|
+
struct dump_call_arg arg = {new_obj,tracker, object};
|
48
|
+
rb_hash_foreach(object, hash_each, (st_data_t)&arg);
|
49
|
+
break;
|
50
|
+
case T_STRING:
|
51
|
+
case T_DATA:
|
52
|
+
new_obj = rb_obj_clone(object);
|
53
|
+
rb_hash_aset(tracker,id,new_obj);
|
54
|
+
break;
|
55
|
+
case T_CLASS:
|
56
|
+
case T_MODULE:
|
57
|
+
case T_REGEXP:
|
58
|
+
new_obj = object;
|
59
|
+
rb_hash_aset(tracker,id,new_obj);
|
60
|
+
break;
|
61
|
+
default:
|
62
|
+
new_obj = rb_obj_clone(object);
|
63
|
+
rb_hash_aset(tracker,id,new_obj);
|
64
|
+
st_table *tbl = ROBJECT_IV_INDEX_TBL(object);
|
65
|
+
if(tbl) {
|
66
|
+
struct dump_call_arg arg = {new_obj,tracker, object};
|
67
|
+
TABLE_FOREACH(tbl, clone_variable, (st_data_t)&arg);
|
68
|
+
}
|
69
|
+
break;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return new_obj;
|
73
|
+
}
|
74
|
+
|
75
|
+
VALUE deep_clone(int argc,VALUE argv)
|
76
|
+
{
|
77
|
+
VALUE tracker = rb_hash_new();
|
78
|
+
return clone_object(argv,tracker);
|
79
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#ifndef DEEP_CLONE_H
|
2
|
+
#define DEEP_CLONE_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "ruby/st.h"
|
6
|
+
|
7
|
+
struct dump_call_arg {
|
8
|
+
VALUE obj;
|
9
|
+
VALUE tracker;
|
10
|
+
VALUE src;
|
11
|
+
};
|
12
|
+
|
13
|
+
#ifdef SA_EMPTY
|
14
|
+
|
15
|
+
// Gotta do this because of 1.9.3's falcon patch
|
16
|
+
struct rb_classext_struct {
|
17
|
+
sa_table m_tbl;
|
18
|
+
sa_table iv_tbl;
|
19
|
+
sa_table const_tbl;
|
20
|
+
sa_table iv_index_tbl;
|
21
|
+
};
|
22
|
+
|
23
|
+
#define TABLE_FOREACH sa_foreach
|
24
|
+
#define RCLASS_EXT(c) (RCLASS(c)->ptr)
|
25
|
+
#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl)
|
26
|
+
|
27
|
+
#else
|
28
|
+
|
29
|
+
// Make it work with vanilla ruby (including 2.0)
|
30
|
+
#ifndef TABLE_FOREACH
|
31
|
+
#define TABLE_FOREACH st_foreach
|
32
|
+
#endif
|
33
|
+
|
34
|
+
#ifndef RCLASS_IV_INDEX_TBL
|
35
|
+
#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#endif
|
39
|
+
|
40
|
+
VALUE DeepClone = Qnil;
|
41
|
+
|
42
|
+
void Init_deep_clone();
|
43
|
+
static int clone_variable(st_data_t key, st_data_t index, struct dump_call_arg *arg);
|
44
|
+
static int hash_each(VALUE key, VALUE value, struct dump_call_arg *arg);
|
45
|
+
static VALUE clone_object(VALUE object, VALUE tracker);
|
46
|
+
|
47
|
+
VALUE deep_clone(int argc,VALUE argv);
|
48
|
+
|
49
|
+
#endif
|
data/lib/deep_clone.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "deep_clone/deep_clone"
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_deep_clone
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthias Balmer
|
9
|
+
- Andre Medeiros
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-04-03 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.13.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 2.13.0
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: rake-compiler
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.8.3
|
39
|
+
type: :development
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.8.3
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 10.0.4
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 10.0.4
|
63
|
+
description: Native implementation to create deep clones of Ruby objects
|
64
|
+
email:
|
65
|
+
- balmma@sysinf.ch
|
66
|
+
- me@andremedeiros.info
|
67
|
+
executables: []
|
68
|
+
extensions:
|
69
|
+
- ext/deep_clone/extconf.rb
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- deep_clone.gemspec
|
73
|
+
- lib/deep_clone.rb
|
74
|
+
- ext/deep_clone/deep_clone.c
|
75
|
+
- ext/deep_clone/deep_clone.h
|
76
|
+
- ext/deep_clone/extconf.rb
|
77
|
+
homepage: https://github.com/balmma/ruby-deepclone
|
78
|
+
licenses: []
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- ext
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.24
|
99
|
+
signing_key:
|
100
|
+
specification_version: 2
|
101
|
+
summary: Ruby native deep clone
|
102
|
+
test_files: []
|