birch 0.0.4-java

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