ruby_deep_clone 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|