birch 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.
@@ -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: []