birch 0.0.4-java
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/ext/birch/extconf.rb +3 -0
- data/ext/birch/native.c +424 -0
- data/lib/birch/pure.rb +132 -0
- data/lib/birch/version.rb +3 -0
- data/lib/birch.rb +6 -0
- metadata +85 -0
data/ext/birch/native.c
ADDED
|
@@ -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
|
+
|
data/lib/birch.rb
ADDED
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
|
+
...
|