ruby_deep_clone 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'deep_clone'
4
+
5
+ dir_config(extension_name)
6
+
7
+ create_makefile(extension_name)
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: []