texplay 0.2.7-x86-mswin32

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.
Files changed (54) hide show
  1. data/CHANGELOG +103 -0
  2. data/README.markdown +41 -0
  3. data/Rakefile +61 -0
  4. data/examples/common.rb +8 -0
  5. data/examples/example_alpha_blend.rb +31 -0
  6. data/examples/example_bezier.rb +42 -0
  7. data/examples/example_blur.rb +59 -0
  8. data/examples/example_color_control.rb +69 -0
  9. data/examples/example_color_transform.rb +29 -0
  10. data/examples/example_dup.rb +75 -0
  11. data/examples/example_each.rb +42 -0
  12. data/examples/example_effect.rb +35 -0
  13. data/examples/example_fill.rb +44 -0
  14. data/examples/example_fill_old.rb +49 -0
  15. data/examples/example_fluent.rb +31 -0
  16. data/examples/example_gen_eval.rb +34 -0
  17. data/examples/example_hash_arguments.rb +47 -0
  18. data/examples/example_lsystem.rb +61 -0
  19. data/examples/example_melt.rb +27 -0
  20. data/examples/example_polyline.rb +43 -0
  21. data/examples/example_scale.rb +29 -0
  22. data/examples/example_simple.rb +38 -0
  23. data/examples/example_splice.rb +33 -0
  24. data/examples/example_sync.rb +60 -0
  25. data/examples/example_turtle.rb +40 -0
  26. data/examples/media/empty2.png +0 -0
  27. data/examples/media/gosu.png +0 -0
  28. data/examples/media/logo.png +0 -0
  29. data/examples/media/maria.png +0 -0
  30. data/examples/media/rose.bmp +0 -0
  31. data/examples/media/sand1.png +0 -0
  32. data/examples/media/sunset.png +0 -0
  33. data/examples/media/texplay.png +0 -0
  34. data/ext/texplay/actions.c +1331 -0
  35. data/ext/texplay/actions.h +52 -0
  36. data/ext/texplay/bindings.c +1129 -0
  37. data/ext/texplay/bindings.h +46 -0
  38. data/ext/texplay/cache.c +135 -0
  39. data/ext/texplay/cache.h +24 -0
  40. data/ext/texplay/compat.h +27 -0
  41. data/ext/texplay/extconf.rb +30 -0
  42. data/ext/texplay/gen_eval.c +211 -0
  43. data/ext/texplay/gen_eval.h +20 -0
  44. data/ext/texplay/object2module.c +171 -0
  45. data/ext/texplay/object2module.h +11 -0
  46. data/ext/texplay/texplay.c +137 -0
  47. data/ext/texplay/texplay.h +107 -0
  48. data/ext/texplay/utils.c +978 -0
  49. data/ext/texplay/utils.h +145 -0
  50. data/lib/1.8/texplay.so +0 -0
  51. data/lib/1.9/texplay.so +0 -0
  52. data/lib/texplay-contrib.rb +171 -0
  53. data/lib/texplay.rb +134 -0
  54. metadata +114 -0
@@ -0,0 +1,46 @@
1
+ #ifndef GUARD_BINDINGS_H
2
+ #define GUARD_BINDINGS_H
3
+
4
+ /* class methods */
5
+ VALUE M_create_macro(VALUE self , VALUE method_name);
6
+ VALUE M_remove_macro(VALUE self, VALUE method_name);
7
+ VALUE M_refresh_cache_all(VALUE self);
8
+ VALUE M_create_blank(VALUE self, VALUE window, VALUE width, VALUE height);
9
+
10
+ /* instance methods */
11
+ VALUE m_paint(int argc, VALUE * argv, VALUE self);
12
+ VALUE m_getpixel(int argc, VALUE * argv, VALUE self);
13
+ VALUE m_circle(int argc, VALUE * argv, VALUE self);
14
+ VALUE m_line(int argc, VALUE * argv, VALUE self);
15
+ VALUE m_rect(int argc, VALUE * argv, VALUE self);
16
+ VALUE m_pixel(int argc, VALUE * argv, VALUE self);
17
+ VALUE m_flood_fill(int argc, VALUE * argv, VALUE self);
18
+ VALUE m_bezier(int argc, VALUE * argv, VALUE self);
19
+ VALUE m_polyline(int argc, VALUE * argv, VALUE self);
20
+ VALUE m_ngon(int argc, VALUE * argv, VALUE self);
21
+ VALUE m_special_pixel(int argc, VALUE * argv, VALUE self);
22
+ VALUE m_splice(int argc, VALUE * argv, VALUE self);
23
+ VALUE m_clear(int argc, VALUE * argv, VALUE self);
24
+ VALUE m_offset(int argc, VALUE * argv, VALUE self);
25
+ VALUE m_color(int argc, VALUE * argv, VALUE self);
26
+ VALUE m_missing(int argc, VALUE * argv, VALUE self);
27
+ VALUE m_bitmask(int argc, VALUE * argv, VALUE self);
28
+ VALUE m_lshift(int argc, VALUE * argv, VALUE self);
29
+ VALUE m_rshift(int argc, VALUE * argv, VALUE self);
30
+
31
+ VALUE m_each(int argc, VALUE * argv, VALUE self);
32
+
33
+ VALUE m_quad_cached(VALUE self);
34
+ VALUE m_cache_refresh(VALUE self);
35
+
36
+ VALUE m_user_set_options(VALUE self, VALUE options);
37
+ VALUE m_user_delete_options(VALUE self);
38
+ VALUE m_get_options(VALUE self);
39
+ VALUE m_force_sync(VALUE self, VALUE ary);
40
+
41
+ VALUE m_dup_image(VALUE self);
42
+ VALUE m_clone_image(VALUE self);
43
+
44
+ VALUE m_to_blob(VALUE self);
45
+
46
+ #endif
@@ -0,0 +1,135 @@
1
+ /* cache.c */
2
+
3
+ #include <ruby.h>
4
+
5
+ #ifdef __APPLE__
6
+ #include <glut.h>
7
+ #else
8
+ #include <GL/glut.h>
9
+ #endif
10
+
11
+ #include "cache.h"
12
+ #include "texplay.h"
13
+
14
+ typedef struct {
15
+ int len;
16
+ cache_entry entry[CACHE_SIZE];
17
+ } cache_t;
18
+
19
+ /* var has internal linkage, static duration */
20
+ /* contains cache data */
21
+ static cache_t cache = {0};
22
+
23
+ /* create a new cache entry */
24
+ cache_entry*
25
+ cache_create_entry(int tname) {
26
+ float * new_array;
27
+ int sidelength, new_element = cache.len;
28
+ GLint saved_tname;
29
+
30
+ if(cache.len >= CACHE_SIZE) { rb_raise(rb_eRuntimeError, "cache is full! increase CACHE_SIZE"); }
31
+
32
+ /* save current texture binding */
33
+ /* glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname); */
34
+
35
+ /* opengl initialization code */
36
+ glEnable(GL_TEXTURE_2D);
37
+ glBindTexture(GL_TEXTURE_2D, tname);
38
+
39
+ /* get length of a side, since square texture */
40
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sidelength);
41
+
42
+ /* initialize texture data array, mult. by 4 because {rgba} */
43
+ new_array = malloc(sidelength * sidelength * 4 * sizeof(float));
44
+
45
+ /* get texture data from video memory */
46
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT,(void*)(new_array));
47
+
48
+ /* save texture data in the cache */
49
+ cache.entry[new_element].tname = tname;
50
+ cache.entry[new_element].sidelength = sidelength;
51
+ cache.entry[new_element].tdata = new_array;
52
+
53
+ /* update size of cache */
54
+ cache.len++;
55
+
56
+ /* restore saved texture binding */
57
+ /* glBindTexture(GL_TEXTURE_2D, saved_tname); */
58
+
59
+ glDisable(GL_TEXTURE_2D);
60
+
61
+
62
+ return &cache.entry[new_element];
63
+ }
64
+
65
+ /* return the entry if it exists, otherwise return NULL */
66
+ cache_entry*
67
+ find_in_cache(int tname) {
68
+ /* check if entry exists in cache */
69
+ int index;
70
+ for(index = 0; index < cache.len; index++)
71
+ if(cache.entry[index].tname == tname)
72
+ return &cache.entry[index];
73
+
74
+
75
+ return NULL;
76
+ }
77
+
78
+ /* if the entry doesn't exist then create it and return it.
79
+ otherwise just return it */
80
+ cache_entry*
81
+ find_or_create_cache_entry(int tname) {
82
+ cache_entry * entry;
83
+
84
+ if((entry=find_in_cache(tname)))
85
+ return entry;
86
+ else
87
+ return cache_create_entry(tname);
88
+ }
89
+
90
+ /* refresh the cache for all quads */
91
+ void
92
+ cache_refresh_all(void) {
93
+ float * tdata;
94
+ int tname, index;
95
+ GLint saved_tname;
96
+
97
+ /* save current texture binding */
98
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname);
99
+
100
+ for(index = 0; index < cache.len; index++) {
101
+ tdata = cache.entry[index].tdata;
102
+ tname = cache.entry[index].tname;
103
+
104
+ /* opengl initialization code */
105
+ glEnable(GL_TEXTURE_2D);
106
+ glBindTexture(GL_TEXTURE_2D, tname);
107
+
108
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, (void*)(tdata));
109
+ }
110
+
111
+ /* restore saved texture binding */
112
+ glBindTexture(GL_TEXTURE_2D, saved_tname);
113
+ }
114
+
115
+ /* refresh the cache for a specific quad */
116
+ void
117
+ cache_refresh_entry(int tname) {
118
+ GLint saved_tname;
119
+ cache_entry * entry;
120
+
121
+ /* save current texture binding */
122
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname);
123
+
124
+ entry = find_in_cache(tname);
125
+
126
+ /* opengl initialization code */
127
+ glEnable(GL_TEXTURE_2D);
128
+ glBindTexture(GL_TEXTURE_2D, entry->tname);
129
+
130
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, (void*)(entry->tdata));
131
+
132
+ /* restore saved texture binding */
133
+ glBindTexture(GL_TEXTURE_2D, saved_tname);
134
+ }
135
+
@@ -0,0 +1,24 @@
1
+ /* cache.h */
2
+ /* see cache.c for annotations */
3
+
4
+ #ifndef GUARD_CACHE_H
5
+ #define GUARD_CACHE_H
6
+
7
+ /* defines */
8
+ #define CACHE_SIZE 10000
9
+
10
+ /* data types */
11
+ typedef struct {
12
+ int tname;
13
+ int sidelength;
14
+ float * tdata;
15
+ } cache_entry;
16
+
17
+ /* functions */
18
+ void cache_refresh_all(void);
19
+ void cache_refresh_entry(int tname);
20
+ cache_entry * cache_create_entry(int texture_name);
21
+ cache_entry * find_in_cache(int texture_name);
22
+ cache_entry * find_or_create_cache_entry(int texture_name);
23
+
24
+ #endif
@@ -0,0 +1,27 @@
1
+ /* contains basic macros to facilitate ruby 1.8 and ruby 1.9 compatibility */
2
+
3
+ #ifndef GUARD_COMPAT_H
4
+ #define GUARD_COMPAT_H
5
+
6
+ #include <ruby.h>
7
+
8
+ /* this is the test we use to identify ruby 1.9.1 */
9
+
10
+ /* commenting out this test because it doesn't seem to work in 1.8.7 */
11
+ /*
12
+ #ifdef RCLASS_M_TBL
13
+ # define RUBY_19
14
+ #endif
15
+ */
16
+
17
+ /* macros for backwards compatibility with 1.8 */
18
+ #ifndef RUBY_19
19
+ # define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
20
+ # define RCLASS_SUPER(c) (RCLASS(c)->super)
21
+ # define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
22
+ #endif
23
+
24
+ /* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
25
+ #define KLASS_OF(c) (RBASIC(c)->klass)
26
+
27
+ #endif
@@ -0,0 +1,30 @@
1
+ require 'mkmf'
2
+
3
+
4
+ # linux
5
+ if RUBY_PLATFORM =~ /linux/ then
6
+ exit unless have_library("glut")
7
+ exit unless have_library("GL")
8
+
9
+ # macosx
10
+ elsif RUBY_PLATFORM =~ /darwin/
11
+ $LDFLAGS += " -framework GLUT"
12
+ $CFLAGS += " -I/System/Library/Frameworks/GLUT.framework/Headers"
13
+
14
+ # windows
15
+ else
16
+
17
+ exit unless have_library("freeglut_static")
18
+ exit unless have_library("opengl32")
19
+
20
+ if RUBY_PLATFORM =~ /mingw/
21
+ $CFLAGS += " -I/home/john/.rake-compiler/ruby/ruby-1.9.1-p243/include"
22
+ $CFLAGS += " -I/home/john/.rake-compiler/ruby/ruby-1.8.6-p287/include"
23
+ $CFLAGS += " -D FREEGLUT_STATIC"
24
+ end
25
+ end
26
+
27
+ # 1.9 compatibility
28
+ $CFLAGS += " -DRUBY_19" if RUBY_VERSION =~ /1.9/
29
+
30
+ create_makefile('texplay')
@@ -0,0 +1,211 @@
1
+ /* gen_eval.c */
2
+ /* (C) John Mair 2009
3
+ * This program is distributed under the terms of the MIT License
4
+ * */
5
+
6
+ #include <ruby.h>
7
+ #include "object2module.h"
8
+ #include "compat.h"
9
+
10
+ VALUE
11
+ retrieve_hidden_self(VALUE duped_context)
12
+ {
13
+ VALUE thread_id, unique_name, hidden_self;
14
+
15
+ /* retrieve hidden self (if it exists) */
16
+ thread_id = rb_funcall(rb_obj_id(rb_thread_current()), rb_intern("to_s"), 0);
17
+ unique_name = rb_str_plus(rb_str_new2("__hidden_self__"), thread_id);
18
+
19
+ hidden_self = rb_ivar_get(duped_context, rb_to_id(unique_name));
20
+
21
+ return hidden_self;
22
+ }
23
+
24
+ void
25
+ set_hidden_self(VALUE duped_context, VALUE hidden_self)
26
+ {
27
+ VALUE thread_id, unique_name;
28
+
29
+ /* generate a unique (thread safe) name for the hidden self */
30
+ thread_id = rb_funcall(rb_obj_id(rb_thread_current()), rb_intern("to_s"), 0);
31
+ unique_name = rb_str_plus(rb_str_new2("__hidden_self__"), thread_id);
32
+
33
+ /* store self in hidden var in duped context */
34
+ rb_ivar_set(duped_context, rb_to_id(unique_name), hidden_self);
35
+ }
36
+
37
+ VALUE
38
+ rb_capture(VALUE self) {
39
+ VALUE hidden_self;
40
+ VALUE result;
41
+
42
+ rb_need_block();
43
+
44
+ hidden_self = retrieve_hidden_self(self);
45
+
46
+ /* 2 cases: (1) if rb_gen_eval is active then instance_eval wrt hidden_self
47
+ (2) otherwise simply yield to the block
48
+ */
49
+ if(!NIL_P(hidden_self))
50
+ result = rb_obj_instance_eval(0, 0, hidden_self);
51
+ else
52
+ result = rb_yield(Qnil);
53
+
54
+ /* we want the return value of capture to be the return value of the block */
55
+ return result;
56
+ }
57
+
58
+ /** ruby 1.9 funcs **/
59
+ #ifdef RUBY_19
60
+ void
61
+ redirect_iv_for_object(VALUE obj, VALUE dest)
62
+ {
63
+ if(TYPE(obj) != T_OBJECT)
64
+ rb_raise(rb_eArgError, "must provide a T_OBJECT");
65
+
66
+ if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
67
+ rb_raise(rb_eArgError, "im sorry gen_eval does not yet work with this type of ROBJECT");
68
+ }
69
+ if (RBASIC(obj)->flags & ROBJECT_EMBED) {
70
+ rb_raise(rb_eArgError, "im sorry gen_eval does not yet work with ROBJECT_EMBED types");
71
+ }
72
+ else {
73
+ ROBJECT(dest)->as.heap.ivptr = ROBJECT(obj)->as.heap.ivptr;
74
+ ROBJECT(dest)->as.heap.numiv = ROBJECT(obj)->as.heap.numiv;
75
+ ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
76
+ RBASIC(dest)->flags &= ~ROBJECT_EMBED;
77
+ }
78
+ }
79
+
80
+ void
81
+ release_iv_for_object(VALUE obj)
82
+ {
83
+ if(TYPE(obj) != T_OBJECT)
84
+ rb_raise(rb_eArgError, "must provide a T_OBJECT");
85
+
86
+ ROBJECT(obj)->as.heap.ivptr = (void *) 0;
87
+ ROBJECT(obj)->as.heap.numiv = 0;
88
+ ROBJECT(obj)->as.heap.iv_index_tbl = (void *) 0;
89
+ RBASIC(obj)->flags &= ~ROBJECT_EMBED;
90
+ }
91
+ #endif
92
+ /** end of ruby 1.9 funcs **/
93
+
94
+ VALUE
95
+ rb_gen_eval(int argc, VALUE * argv, VALUE self) {
96
+ VALUE duped_context;
97
+ VALUE is_a_module;
98
+ VALUE context;
99
+ VALUE result;
100
+
101
+ rb_need_block();
102
+
103
+ context = rb_funcall(rb_block_proc(), rb_intern("__context__"), 0);
104
+
105
+ /* using Class instead of Object (where possible) because Object's iv_tbl setup in 1.9 is weird */
106
+ #ifdef RUBY_19
107
+ if(TYPE(context) == T_OBJECT)
108
+ duped_context = rb_funcall(rb_cObject, rb_intern("new"), 0);
109
+ else
110
+ duped_context = rb_funcall(rb_cClass, rb_intern("new"), 0);
111
+
112
+ #else
113
+
114
+ duped_context = rb_funcall(rb_cClass, rb_intern("new"), 0);
115
+
116
+ #endif
117
+
118
+
119
+ /* the duped_context shares the context's iv_tbl.
120
+ 2 cases: (1) external iv_tbl, (2) local iv_tbl
121
+
122
+ NOTE: we do not need to save original iv_tbl before replacing it, a brand new Class
123
+ instance does not yet have an iv_tbl (the pointer is set to 0)
124
+ */
125
+ if(FL_TEST(context, FL_EXIVAR))
126
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) rb_generic_ivar_table(context);
127
+ else {
128
+ #ifdef RUBY_19
129
+ if(TYPE(context) == T_OBJECT)
130
+ redirect_iv_for_object(context, duped_context);
131
+ else {
132
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) RCLASS_IV_TBL(context);
133
+ }
134
+ #else
135
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) RCLASS_IV_TBL(context);
136
+ #endif
137
+
138
+
139
+ }
140
+
141
+ /* ensure singleton exists */
142
+ rb_singleton_class(context);
143
+
144
+ /* set up the class hierarchy for our dup_context */
145
+ KLASS_OF(duped_context) = rb_singleton_class_clone(context);
146
+
147
+ /* if no args then default to mixing in 'self' */
148
+ if(argc == 0) {
149
+ argc = 1;
150
+ argv = &self;
151
+ }
152
+
153
+ /* mix the objects (or self) into the duped context */
154
+ rb_gen_extend(argc, argv, duped_context);
155
+
156
+ /* store self in hidden var in duped context */
157
+ set_hidden_self(duped_context, self);
158
+
159
+ is_a_module = rb_funcall(duped_context, rb_intern("is_a?"), 1, rb_cModule);
160
+
161
+ /* eval block wrt duped_context */
162
+ if(is_a_module == Qtrue)
163
+ result = rb_mod_module_eval(0, 0, duped_context);
164
+ else
165
+ result = rb_obj_instance_eval(0, 0, duped_context);
166
+
167
+ /* clean up goes below */
168
+
169
+ /* release context's iv_tbl from duped_context. */
170
+ #ifdef RUBY_19
171
+ if(TYPE(duped_context) == T_OBJECT)
172
+ release_iv_for_object(duped_context);
173
+ else {
174
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) 0;
175
+ }
176
+ #else
177
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) 0;
178
+ #endif
179
+
180
+ /* delete hidden self */
181
+ set_hidden_self(duped_context, Qnil);
182
+
183
+ return result;
184
+ }
185
+
186
+ void
187
+ Init_gen_eval() {
188
+
189
+ rb_define_method(rb_cObject, "gen_eval", rb_gen_eval, -1);
190
+ rb_define_method(rb_cObject, "capture", rb_capture, 0);
191
+
192
+ rb_define_method(rb_cObject, "to_module", rb_to_module , 0);
193
+ rb_define_method(rb_cObject, "reset_tbls", rb_reset_tbls , 0);
194
+ rb_define_method(rb_cObject, "gen_extend", rb_gen_extend, -1);
195
+ rb_define_method(rb_cModule, "gen_include", rb_gen_include, -1);
196
+
197
+ /* below is much too hard to achieve in pure C */
198
+ rb_eval_string("class Proc;"
199
+ " def __context__;"
200
+ " eval('self', self.binding);"
201
+ " end;"
202
+ "end;"
203
+ );
204
+
205
+ rb_define_alias(rb_cObject, "gen_eval_with", "gen_eval");
206
+ }
207
+
208
+
209
+
210
+
211
+
@@ -0,0 +1,20 @@
1
+ /* gen_eval.h */
2
+
3
+ #ifndef GUARD_GEN_EVAL_H
4
+ #define GUARD_GEN_EVAL_H
5
+
6
+ #include <ruby.h>
7
+
8
+ VALUE rb_gen_eval(int argc, VALUE * argv, VALUE self);
9
+ VALUE rb_capture(VALUE self);
10
+ VALUE retrieve_hidden_self(VALUE duped_context);
11
+ void set_hidden_self(VALUE duped_context, VALUE hidden_self);
12
+
13
+ /* change self to hidden self if __hidden_self__ defined */
14
+ #define ADJUST_SELF(X) \
15
+ do { \
16
+ if(!NIL_P(retrieve_hidden_self((X)))) \
17
+ (X) = retrieve_hidden_self((X)); \
18
+ } while(0)
19
+
20
+ #endif
@@ -0,0 +1,171 @@
1
+ /* object2module.c */
2
+ /* (C) John Mair 2009
3
+ * This program is distributed under the terms of the MIT License
4
+ * */
5
+
6
+ #include <ruby.h>
7
+ #include "compat.h"
8
+
9
+ #ifdef RUBY_19
10
+ # include <ruby/st.h>
11
+ #else
12
+ # include <st.h>
13
+ #endif
14
+
15
+ /* class creation. from class.c in 1.9.1 */
16
+ #ifdef RUBY_19
17
+ static VALUE
18
+ class_alloc(VALUE flags, VALUE klass)
19
+ {
20
+ rb_classext_t *ext = ALLOC(rb_classext_t);
21
+ NEWOBJ(obj, struct RClass);
22
+ OBJSETUP(obj, klass, flags);
23
+ obj->ptr = ext;
24
+ RCLASS_IV_TBL(obj) = 0;
25
+ RCLASS_M_TBL(obj) = 0;
26
+ RCLASS_SUPER(obj) = 0;
27
+ RCLASS_IV_INDEX_TBL(obj) = 0;
28
+ return (VALUE)obj;
29
+ }
30
+ #endif
31
+
32
+ /* a modified version of include_class_new from class.c */
33
+ static VALUE
34
+ j_class_new(VALUE module, VALUE sup)
35
+ {
36
+
37
+ #ifdef RUBY_19
38
+ VALUE klass = class_alloc(T_ICLASS, rb_cClass);
39
+ #else
40
+ NEWOBJ(klass, struct RClass);
41
+ OBJSETUP(klass, rb_cClass, T_ICLASS);
42
+ #endif
43
+
44
+ if (BUILTIN_TYPE(module) == T_ICLASS) {
45
+ module = KLASS_OF(module);
46
+ }
47
+
48
+ if (!RCLASS_IV_TBL(module)) {
49
+
50
+ RCLASS_IV_TBL(module) = (struct st_table *)st_init_numtable();
51
+ }
52
+
53
+ /* assign iv_tbl, m_tbl and super */
54
+ RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
55
+ RCLASS_SUPER(klass) = sup;
56
+ if(TYPE(module) != T_OBJECT) {
57
+
58
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
59
+ }
60
+ else {
61
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module));
62
+ }
63
+
64
+ /* */
65
+
66
+ if (TYPE(module) == T_ICLASS) {
67
+ KLASS_OF(klass) = KLASS_OF(module);
68
+ }
69
+ else {
70
+ KLASS_OF(klass) = module;
71
+ }
72
+
73
+ if(TYPE(module) != T_OBJECT) {
74
+ OBJ_INFECT(klass, module);
75
+ OBJ_INFECT(klass, sup);
76
+ }
77
+ return (VALUE)klass;
78
+ }
79
+
80
+ VALUE
81
+ rb_to_module(VALUE self)
82
+ {
83
+ VALUE rclass, chain_start, jcur, klass;
84
+
85
+ switch(BUILTIN_TYPE(self)) {
86
+ case T_MODULE:
87
+ return self;
88
+ case T_CLASS:
89
+ klass = self;
90
+ break;
91
+ case T_OBJECT:
92
+ default:
93
+ klass = rb_singleton_class(self);
94
+ }
95
+
96
+ chain_start = j_class_new(klass, rb_cObject);
97
+
98
+ KLASS_OF(chain_start) = rb_cModule;
99
+ RBASIC(chain_start)->flags = T_MODULE;
100
+
101
+ jcur = chain_start;
102
+ for(rclass = RCLASS_SUPER(klass); rclass != rb_cObject;
103
+ rclass = RCLASS_SUPER(rclass)) {
104
+
105
+ RCLASS_SUPER(jcur) = j_class_new(rclass, rb_cObject);
106
+ jcur = RCLASS_SUPER(jcur);
107
+ }
108
+
109
+ RCLASS_SUPER(jcur) = (VALUE)NULL;
110
+
111
+ return chain_start;
112
+ }
113
+
114
+ VALUE
115
+ rb_reset_tbls(VALUE self)
116
+ {
117
+ RCLASS_IV_TBL(self) = (struct st_table *) 0;
118
+ RCLASS_M_TBL(self) = (struct st_table *) st_init_numtable();
119
+ return Qnil;
120
+ }
121
+
122
+ /* cannot simply forward to gen_include as need to invoke 'extended' hook */
123
+ VALUE
124
+ rb_gen_extend(int argc, VALUE * argv, VALUE self)
125
+ {
126
+ int i;
127
+
128
+ if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
129
+
130
+ rb_singleton_class(self);
131
+
132
+ for(i = 0; i < argc; i++) {
133
+ VALUE mod = rb_to_module(argv[i]);
134
+ rb_funcall(mod, rb_intern("extend_object"), 1, self);
135
+ rb_funcall(mod, rb_intern("extended"), 1, self);
136
+
137
+ /* only redirect if argv[i] is not a module */
138
+ if(argv[i] != mod) rb_reset_tbls(mod);
139
+ }
140
+
141
+ return self;
142
+ }
143
+
144
+ VALUE
145
+ rb_gen_include(int argc, VALUE * argv, VALUE self)
146
+ {
147
+ int i;
148
+
149
+ if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
150
+
151
+ for(i = 0; i < argc; i++) {
152
+ VALUE mod = rb_to_module(argv[i]);
153
+ rb_funcall(mod, rb_intern("append_features"), 1, self);
154
+ rb_funcall(mod, rb_intern("included"), 1, self);
155
+
156
+ if(argv[i] != mod) rb_reset_tbls(mod);
157
+ }
158
+
159
+ return self;
160
+ }
161
+
162
+
163
+ void Init_object2module()
164
+ {
165
+
166
+ rb_define_method(rb_cObject, "to_module", rb_to_module , 0);
167
+ rb_define_method(rb_cObject, "gen_extend", rb_gen_extend, -1);
168
+ rb_define_method(rb_cModule, "gen_include", rb_gen_include, -1);
169
+ rb_define_method(rb_cModule, "reset_tbls", rb_reset_tbls, 0);
170
+ }
171
+
@@ -0,0 +1,11 @@
1
+ /* object2module.h */
2
+
3
+ #ifndef GUARD_OBJECT2MODULE_H
4
+ #define GUARD_OBJECT2MODULE_H
5
+
6
+ VALUE rb_gen_include(int argc, VALUE * argv, VALUE self);
7
+ VALUE rb_gen_extend(int argc, VALUE * argv, VALUE self);
8
+ VALUE rb_to_module(VALUE self);
9
+ VALUE rb_reset_tbls(VALUE self);
10
+
11
+ #endif