include_any 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +65 -0
- data/Rakefile +1 -0
- data/ext/include_any/extconf.rb +6 -0
- data/ext/include_any/include_any.c +112 -0
- data/ext/include_any/include_any.h +6 -0
- data/include_any.gemspec +20 -0
- data/lib/include_any/core_ext.rb +9 -0
- data/lib/include_any/version.rb +3 -0
- data/lib/include_any.rb +2 -0
- metadata +59 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 J. Andrew Marshall <http://johnandrewmarshall.com>
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# IncludeAny
|
2
|
+
|
3
|
+
Allows including any object, not just modules. Of course, this is just in
|
4
|
+
theory—see “Bugs & Caveats” below.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Simply run
|
9
|
+
|
10
|
+
$ gem install include_any
|
11
|
+
|
12
|
+
or include it in your Gemfile as usual.
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
The method of interest here is `IncludeAny.include_any`. By default this is not
|
17
|
+
mixed-in anywhere, but doing
|
18
|
+
|
19
|
+
require 'include_any/core_ext'
|
20
|
+
|
21
|
+
will `include IncludeAny` into `Class` and `Module`.
|
22
|
+
|
23
|
+
Then we can get going:
|
24
|
+
|
25
|
+
class C
|
26
|
+
def foo
|
27
|
+
'bar!'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class D
|
32
|
+
include_any C
|
33
|
+
end
|
34
|
+
|
35
|
+
D.ancestors
|
36
|
+
#=> [C, Object, Kernel, BasicObject]
|
37
|
+
|
38
|
+
D.new.f
|
39
|
+
#=> "bar!"
|
40
|
+
|
41
|
+
Well would you look at that! We’ve included a `Class`. Magical!
|
42
|
+
|
43
|
+
## Bugs & Caveats
|
44
|
+
|
45
|
+
Use at your own risk, kids.
|
46
|
+
|
47
|
+
- Currently seg faults if passed anything but a `Class` or `Module`. It should
|
48
|
+
accept (most) any object.
|
49
|
+
- Will probably fail to install or seg fault under anything but MRI 1.9.3
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
Patches and improvements welcome. Especially if they fix a seg fault. Note that
|
54
|
+
there is no intention to support Ruby 1.8.
|
55
|
+
|
56
|
+
1. Fork it
|
57
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
58
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
59
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
60
|
+
5. Create new Pull Request
|
61
|
+
|
62
|
+
## Credits
|
63
|
+
|
64
|
+
© 2012 J. Andrew Marshall. All rights reserved. See the LICENSE file for more
|
65
|
+
information.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "include_any.h"
|
3
|
+
|
4
|
+
#define KLASS_OF(c) (RBASIC(c)->klass)
|
5
|
+
#define RCLASS_EXT(c) (RCLASS(c)->ptr)
|
6
|
+
#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super)
|
7
|
+
#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
|
8
|
+
#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
|
9
|
+
#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
|
10
|
+
#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
|
11
|
+
|
12
|
+
struct rb_classext_struct {
|
13
|
+
VALUE super;
|
14
|
+
struct st_table *iv_tbl;
|
15
|
+
struct st_table *const_tbl;
|
16
|
+
};
|
17
|
+
|
18
|
+
static VALUE
|
19
|
+
class_alloc(VALUE flags, VALUE klass)
|
20
|
+
{
|
21
|
+
rb_classext_t *ext = ALLOC(rb_classext_t);
|
22
|
+
NEWOBJ(obj, struct RClass);
|
23
|
+
OBJSETUP(obj, klass, flags);
|
24
|
+
obj->ptr = ext;
|
25
|
+
RCLASS_IV_TBL(obj) = 0;
|
26
|
+
RCLASS_CONST_TBL(obj) = 0;
|
27
|
+
RCLASS_M_TBL(obj) = 0;
|
28
|
+
RCLASS_SUPER(obj) = 0;
|
29
|
+
RCLASS_IV_INDEX_TBL(obj) = 0;
|
30
|
+
return (VALUE)obj;
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE
|
34
|
+
include_class_new(VALUE module, VALUE super)
|
35
|
+
{
|
36
|
+
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
|
37
|
+
|
38
|
+
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
39
|
+
module = RBASIC(module)->klass;
|
40
|
+
}
|
41
|
+
if (!RCLASS_IV_TBL(module)) {
|
42
|
+
RCLASS_IV_TBL(module) = st_init_numtable();
|
43
|
+
}
|
44
|
+
if (!RCLASS_CONST_TBL(module)) {
|
45
|
+
RCLASS_CONST_TBL(module) = st_init_numtable();
|
46
|
+
}
|
47
|
+
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
48
|
+
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
|
49
|
+
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
|
50
|
+
RCLASS_SUPER(klass) = super;
|
51
|
+
if (TYPE(module) == T_ICLASS) {
|
52
|
+
RBASIC(klass)->klass = RBASIC(module)->klass;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
RBASIC(klass)->klass = module;
|
56
|
+
}
|
57
|
+
OBJ_INFECT(klass, module);
|
58
|
+
OBJ_INFECT(klass, super);
|
59
|
+
|
60
|
+
return (VALUE)klass;
|
61
|
+
}
|
62
|
+
|
63
|
+
VALUE rb_include_any(VALUE klass, VALUE module)
|
64
|
+
{
|
65
|
+
VALUE p, c;
|
66
|
+
int changed = 0;
|
67
|
+
|
68
|
+
rb_frozen_class_p(klass);
|
69
|
+
if (!OBJ_UNTRUSTED(klass)) {
|
70
|
+
rb_secure(4);
|
71
|
+
}
|
72
|
+
|
73
|
+
OBJ_INFECT(klass, module);
|
74
|
+
c = klass;
|
75
|
+
while (module) {
|
76
|
+
int superclass_seen = 0;
|
77
|
+
|
78
|
+
if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
|
79
|
+
rb_raise(rb_eArgError, "cyclic include detected");
|
80
|
+
/* ignore if the module included already in superclasses */
|
81
|
+
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
|
82
|
+
switch (BUILTIN_TYPE(p)) {
|
83
|
+
case T_ICLASS:
|
84
|
+
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
|
85
|
+
if (!superclass_seen) {
|
86
|
+
c = p; /* move insertion point */
|
87
|
+
}
|
88
|
+
goto skip;
|
89
|
+
}
|
90
|
+
break;
|
91
|
+
case T_CLASS:
|
92
|
+
superclass_seen = 1;
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
|
97
|
+
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
|
98
|
+
changed = 1;
|
99
|
+
skip:
|
100
|
+
module = RCLASS_SUPER(module);
|
101
|
+
}
|
102
|
+
if (changed) rb_clear_cache();
|
103
|
+
|
104
|
+
return Qnil;
|
105
|
+
}
|
106
|
+
|
107
|
+
VALUE mIncludeAny;
|
108
|
+
|
109
|
+
void Init_include_any() {
|
110
|
+
mIncludeAny = rb_define_module("IncludeAny");
|
111
|
+
rb_define_method(mIncludeAny, "include_any", rb_include_any, 1);
|
112
|
+
}
|
data/include_any.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'include_any/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "include_any"
|
8
|
+
gem.version = IncludeAny::VERSION
|
9
|
+
gem.authors = ["Andrew Marshall"]
|
10
|
+
gem.email = ["andrew@johnandrewmarshall.com"]
|
11
|
+
gem.description = %q{Allows including any object}
|
12
|
+
gem.summary = %q{Allows including any object}
|
13
|
+
gem.homepage = "http://johnandrewmarshall.com/projects/include_any"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.extensions = ['ext/include_any/extconf.rb']
|
20
|
+
end
|
data/lib/include_any.rb
ADDED
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: include_any
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Marshall
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-19 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Allows including any object
|
15
|
+
email:
|
16
|
+
- andrew@johnandrewmarshall.com
|
17
|
+
executables: []
|
18
|
+
extensions:
|
19
|
+
- ext/include_any/extconf.rb
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- ext/include_any/extconf.rb
|
28
|
+
- ext/include_any/include_any.c
|
29
|
+
- ext/include_any/include_any.h
|
30
|
+
- include_any.gemspec
|
31
|
+
- lib/include_any.rb
|
32
|
+
- lib/include_any/core_ext.rb
|
33
|
+
- lib/include_any/version.rb
|
34
|
+
homepage: http://johnandrewmarshall.com/projects/include_any
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.24
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Allows including any object
|
58
|
+
test_files: []
|
59
|
+
has_rdoc:
|