birch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,354 @@
1
+ #include <ruby.h>
2
+
3
+ /*
4
+ * Initialize the node with its value and id.
5
+ * Setup containers for the children, features
6
+ * and dependencies of this node.
7
+ */
8
+ static VALUE birch_initialize(VALUE self, VALUE value, VALUE id)
9
+ {
10
+ VALUE parent;
11
+ VALUE children;
12
+ VALUE children_hash;
13
+ VALUE features;
14
+ VALUE edges;
15
+
16
+ parent = Qnil;
17
+ children = rb_ary_new();
18
+ children_hash = rb_hash_new();
19
+ features = rb_hash_new();
20
+ edges = rb_ary_new();
21
+
22
+ rb_iv_set(self, "@value", value);
23
+ rb_iv_set(self, "@id", id);
24
+
25
+ rb_iv_set(self, "@parent", parent);
26
+ rb_iv_set(self, "@children", children);
27
+ rb_iv_set(self, "@children_hash", children_hash);
28
+ rb_iv_set(self, "@features", features);
29
+ rb_iv_set(self, "@edges", edges);
30
+
31
+ return self;
32
+ }
33
+
34
+ /* Return the root of the tree. */
35
+ static VALUE birch_root(VALUE self) {
36
+
37
+ VALUE ancestor;
38
+ VALUE parent;
39
+ VALUE tmp;
40
+
41
+ parent = rb_iv_get(ancestor, "@parent");
42
+
43
+ if (parent == Qnil) {
44
+ return self;
45
+ } else {
46
+ ancestor = parent;
47
+ while (ancestor != Qnil) {
48
+ tmp = rb_iv_get(ancestor, "@parent");
49
+ if (tmp == Qnil) {
50
+ return ancestor;
51
+ } else {
52
+ ancestor = tmp;
53
+ }
54
+ }
55
+ return Qnil;
56
+ }
57
+ }
58
+
59
+ /* Add a child to this node. */
60
+ static VALUE birch_add(VALUE self, VALUE child) {
61
+
62
+ VALUE children;
63
+ VALUE children_hash;
64
+
65
+ VALUE child_id;
66
+
67
+ children = rb_iv_get(self, "@children");
68
+ child_id = rb_funcall(child, rb_intern("id"), 0);
69
+ children_hash = rb_iv_get(self, "@children_hash");
70
+
71
+ rb_funcall(children, rb_intern("push"), 1, child);
72
+
73
+ rb_funcall(
74
+ children_hash,
75
+ rb_intern("store"),
76
+ 2, child_id, child
77
+ );
78
+
79
+ rb_iv_set(child, "@parent", self);
80
+
81
+ return child;
82
+
83
+ }
84
+
85
+ /* Return the feature with the supplied name. */
86
+ static VALUE birch_get(VALUE self, VALUE feature) {
87
+ if (feature == rb_intern("id")) {
88
+ return rb_iv_get(self, "@id");
89
+ } else if (feature == rb_intern("value")) {
90
+ return rb_iv_get(self, "@value");
91
+ } else {
92
+ return rb_hash_aref(rb_iv_get(self, "@features"), feature);
93
+ }
94
+ }
95
+
96
+ /* Set the feature to the supplied value. */
97
+ static VALUE birch_set(VALUE self, VALUE feature, VALUE value) {
98
+ return rb_hash_aset(rb_iv_get(self, "@features"), feature, value);
99
+ }
100
+
101
+ /* Unset a feature. */
102
+ static VALUE birch_unset(VALUE self, VALUE feature) {
103
+ return rb_hash_delete(
104
+ rb_iv_get(self, "@features"),
105
+ feature
106
+ );
107
+ }
108
+
109
+ /* Return the total number of nodes in the subtree */
110
+ static VALUE birch_size(VALUE self) {
111
+
112
+
113
+ VALUE children;
114
+ int sum;
115
+ long len;
116
+ long i;
117
+
118
+ children = rb_iv_get(self, "@children");
119
+ len = RARRAY_LEN(children);
120
+ sum = 0;
121
+
122
+ for (i=0; i<len; i++) {
123
+ sum += rb_funcall(
124
+ RARRAY_PTR(children)[i],
125
+ rb_intern("size"), 0
126
+ );
127
+ }
128
+
129
+ return INT2NUM(sum);
130
+
131
+ }
132
+
133
+ /* Iterate over each children of the node. */
134
+ static VALUE birch_each(VALUE self) {
135
+
136
+ long i;
137
+ VALUE children;
138
+ children = rb_iv_get(self, "@children");
139
+
140
+ RETURN_ENUMERATOR(children, 0, 0);
141
+
142
+ for (i=0; i<RARRAY_LEN(children); i++) {
143
+ rb_yield(RARRAY_PTR(children)[i]);
144
+ }
145
+
146
+ return children;
147
+
148
+ }
149
+
150
+ static VALUE birch_find(VALUE self, VALUE id) {
151
+
152
+ VALUE children_hash;
153
+ VALUE children;
154
+ VALUE result;
155
+ long i;
156
+
157
+ children_hash = rb_iv_get(self, "@children_hash");
158
+ result = rb_hash_aref(children_hash, id);
159
+
160
+ if (result == Qnil) {
161
+ children = rb_iv_get(self, "@children");
162
+ for (i=0; i < RARRAY_LEN(children); i++) {
163
+ result = rb_funcall(
164
+ RARRAY_PTR(children)[i],
165
+ rb_intern("find"), 1, id
166
+ );
167
+ if (result != Qnil) { return result; }
168
+ }
169
+ return Qnil;
170
+ } else { return result; }
171
+
172
+ }
173
+
174
+ /* Boolean - is this node's subtree empty? */
175
+ static VALUE birch_is_leaf(VALUE self) {
176
+ if (RARRAY_LEN(rb_iv_get(self, "@children")) == 0) {
177
+ return Qtrue;
178
+ } else {
179
+ return Qfalse;
180
+ }
181
+ }
182
+
183
+ /* Boolean - is this node parent-less? */
184
+ static VALUE birch_is_root(VALUE self) {
185
+ if (rb_iv_get(self, "@parent") == Qnil) {
186
+ return Qtrue;
187
+ } else {
188
+ return Qfalse;
189
+ }
190
+ }
191
+
192
+ /* Boolean - does this node have children */
193
+ static VALUE birch_has_children(VALUE self) {
194
+ if (RARRAY_LEN(rb_iv_get(self, "@children")) == 0) {
195
+ return Qfalse;
196
+ } else {
197
+ return Qtrue;
198
+ }
199
+ }
200
+
201
+ /* Boolean - does the node have a parent? */
202
+ static VALUE birch_has_parent(VALUE self) {
203
+ if (rb_iv_get(self, "@parent") == Qnil) {
204
+ return Qfalse;
205
+ } else {
206
+ return Qtrue;
207
+ }
208
+ }
209
+
210
+ /* Boolean - does the node have edges? */
211
+ static VALUE birch_has_edges(VALUE self) {
212
+ if (RARRAY_LEN(rb_iv_get(self, "@edges")) == 0) {
213
+ return Qfalse;
214
+ } else {
215
+ return Qtrue;
216
+ }
217
+ }
218
+
219
+ /* Boolean - does the node have feature? */
220
+ static VALUE birch_has_feature(VALUE self, VALUE feature) {
221
+ VALUE features;
222
+ features = rb_iv_get(self, "@features");
223
+ if (rb_hash_aref(features, feature) == Qnil) {
224
+ return Qfalse;
225
+ } else {
226
+ return Qtrue;
227
+ }
228
+ }
229
+
230
+ static VALUE birch_link(VALUE self, VALUE edge) {
231
+
232
+ VALUE edges;
233
+ edges = rb_iv_get(self, "@edges");
234
+
235
+ rb_funcall(
236
+ edges, rb_intern("push"), 1, edge
237
+ );
238
+
239
+ }
240
+
241
+ /* Remove from parent and set as root */
242
+ static VALUE birch_set_as_root(VALUE self) {
243
+
244
+ // Set the parent to be nil.
245
+ rb_iv_set(self, "@parent", Qnil);
246
+
247
+ // Return self.
248
+ return self;
249
+
250
+ }
251
+
252
+ /* Removes a node by ID and returns it */
253
+ static VALUE birch_remove(VALUE self, VALUE id) {
254
+
255
+ VALUE val;
256
+
257
+ // Delete the node from the hash and retrieve it.
258
+ val = rb_hash_delete(
259
+ rb_iv_get(self, "@children_hash"), id
260
+ );
261
+
262
+ // Raise an exception if the value can't be found.
263
+ if (val == Qundef) {
264
+ rb_raise(rb_eArgError,
265
+ "Given ID is not a children of this node.");
266
+ return Qnil;
267
+ }
268
+
269
+ // Delete the node from the children array.
270
+ rb_funcall(
271
+ rb_iv_get(self, "@children"),
272
+ rb_intern("delete"), 1, val
273
+ );
274
+
275
+ // Set the node as a root (set its parent to nil).
276
+ rb_funcall(
277
+ val, rb_intern("set_as_root!"), 0
278
+ );
279
+
280
+ return val;
281
+
282
+ }
283
+
284
+ /* Remove all children and set them as root. */
285
+ static VALUE birch_remove_all(VALUE self) {
286
+
287
+ VALUE children;
288
+ long i;
289
+ long children_len;
290
+
291
+ children = rb_iv_get(self, "@children");
292
+
293
+ for (i = 0; i < children_len; i++) {
294
+ rb_funcall(
295
+ RARRAY_PTR(children)[i],
296
+ rb_intern("set_as_root!"), 0
297
+ );
298
+ }
299
+
300
+ rb_iv_set(self, "@children", rb_ary_new());
301
+ rb_iv_set(self, "@children_hash", rb_hash_new());
302
+
303
+ return self;
304
+ }
305
+
306
+ /* This class is a node for an N-ary tree data structure
307
+ * with a unique identifier, text value, children, features
308
+ * (annotations) and dependencies.
309
+ *
310
+ * This class was partly based on the 'rubytree' gem.
311
+ * RubyTree is licensed under the BSD license and can
312
+ * be found at http://rubytree.rubyforge.org/rdoc/.
313
+ */
314
+ void Init_birch(void) {
315
+
316
+ VALUE module = rb_define_module("Birch");
317
+ VALUE klass = rb_define_class_under(module, "Tree", rb_cObject);
318
+
319
+ // Attribute accessors
320
+ rb_attr(klass, rb_intern("id"), 1, 1, 1);
321
+ rb_attr(klass, rb_intern("value"), 1, 1, 1);
322
+
323
+ // Attribute readers
324
+ rb_attr(klass, rb_intern("parent"), 1, 0, 0);
325
+ rb_attr(klass, rb_intern("children"), 1, 0, 0);
326
+ rb_attr(klass, rb_intern("features"), 1, 0, 0);
327
+ rb_attr(klass, rb_intern("edges"), 1, 0, 0);
328
+
329
+ // Methods
330
+ rb_define_method(klass, "initialize", birch_initialize, 2);
331
+ rb_define_method(klass, "root", birch_root, 0);
332
+ rb_define_method(klass, "<<", birch_add, 1);
333
+ rb_define_method(klass, "add", birch_add, 1);
334
+ rb_define_method(klass, "[]", birch_get, 1);
335
+ rb_define_method(klass, "get", birch_get, 1);
336
+ rb_define_method(klass, "[]=", birch_set, 2);
337
+ rb_define_method(klass, "set", birch_set, 2);
338
+ rb_define_method(klass, "unset", birch_unset, 1);
339
+ rb_define_method(klass, "size", birch_size, 0);
340
+ rb_define_method(klass, "each", birch_each, 0);
341
+ rb_define_method(klass, "find", birch_find, 1);
342
+ rb_define_method(klass, "is_leaf?", birch_is_leaf, 0);
343
+ rb_define_method(klass, "is_root?", birch_is_root, 0);
344
+ rb_define_method(klass, "has_parent?", birch_has_parent, 0);
345
+ rb_define_method(klass, "has_children?", birch_has_children, 0);
346
+ rb_define_method(klass, "has_edges?", birch_has_edges, 0);
347
+ rb_define_method(klass, "has_feature?", birch_has_feature, 1);
348
+ rb_define_method(klass, "has?", birch_has_feature, 1);
349
+ rb_define_method(klass, "link", birch_link, 1);
350
+ rb_define_method(klass, "set_as_root!", birch_set_as_root, 0);
351
+ rb_define_method(klass, "remove", birch_remove, 1);
352
+ rb_define_method(klass, "remove_all!", birch_remove_all, 0);
353
+
354
+ }
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('birch/birch')
@@ -0,0 +1 @@
1
+ require 'birch/birch'
@@ -0,0 +1,3 @@
1
+ class Birch
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: birch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Louis Mullie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! ' '
15
+ email:
16
+ - louis.mullie@gmail.com
17
+ executables: []
18
+ extensions:
19
+ - ext/birch/extconf.rb
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/birch/version.rb
23
+ - lib/birch.rb
24
+ - ext/birch/birch.c
25
+ - ext/birch/extconf.rb
26
+ homepage: https://github.com/louismullie/birch
27
+ licenses: []
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 1.8.24
47
+ signing_key:
48
+ specification_version: 3
49
+ summary: Birch is a generic tree implementation for Ruby, in C.
50
+ test_files: []