about summary refs log tree commit
diff options
context:
space:
mode:
authorcodeout <goodies@codeout.net>2012-10-03 20:57:13 +0900
committerEric Wong <normalperson@yhbt.net>2012-10-04 03:20:43 -0700
commit523c6a46b06a726d63aa7a27840b79586f356bb5 (patch)
treee1db845c24704b15dda6c4706f58b13744ecc77d
parenta5be0f72618bcb2c82ee5131f4899abb3d9db529 (diff)
downloadrpatricia-523c6a46b06a726d63aa7a27840b79586f356bb5.tar.gz
Added a method 'nodes' to return all nodes in ruby's Hash.
This is useful when a ruby code requires nodes list for example,
and also it helps when we sort user data by prefix.

[ew: minor compiler compatibility fixes]
-rw-r--r--ext/rpatricia/rpatricia.c25
-rw-r--r--test.rb3
-rw-r--r--test/test_nodes.rb29
3 files changed, 57 insertions, 0 deletions
diff --git a/ext/rpatricia/rpatricia.c b/ext/rpatricia/rpatricia.c
index e1ae1df..03f6588 100644
--- a/ext/rpatricia/rpatricia.c
+++ b/ext/rpatricia/rpatricia.c
@@ -203,6 +203,30 @@ p_print_nodes (int argc, VALUE *argv, VALUE self)
 }
 
 static VALUE
+p_nodes (VALUE self)
+{
+  VALUE buf = rb_str_new(0, 0);
+  char *cbuf;
+  patricia_tree_t *tree;
+  patricia_node_t *node;
+  VALUE hash;
+
+  Data_Get_Struct(self, patricia_tree_t, tree);
+
+  hash = rb_hash_new();
+  if (tree->head) {
+    PATRICIA_WALK(tree->head, node) {
+      rb_str_resize(buf, PATRICIA_MAXSTRLEN);
+      cbuf = RSTRING_PTR(buf);
+      prefix_toa2x(node->prefix, cbuf, 1);
+      rb_str_set_len(buf, strlen(cbuf));
+      rb_hash_aset(hash, buf, (VALUE)node->data);
+    } PATRICIA_WALK_END;
+  }
+  return hash;
+}
+
+static VALUE
 p_data (VALUE self)
 {
   VALUE user_data;
@@ -385,6 +409,7 @@ Init_rpatricia (void)
   /* derivatives of climb */
   rb_define_method(cPatricia, "num_nodes", p_num_nodes, 0);
   rb_define_method(cPatricia, "show_nodes", p_print_nodes, -1);
+  rb_define_method(cPatricia, "nodes", p_nodes, 0);
 
   /* destroy tree */
   rb_define_method(cPatricia, "destroy", p_destroy, 0);
diff --git a/test.rb b/test.rb
index 09a11d0..6a2a066 100644
--- a/test.rb
+++ b/test.rb
@@ -60,4 +60,7 @@ my_test(4 == t.num_nodes)
 puts "test: showing all nodes"
 t.show_nodes
 
+puts "test: return all nodes in Hash"
+my_test(t.nodes == {"127.0.0.0/24"=>"", "192.168.1.0/24"=>"", "192.168.2.0/24"=>"", "192.168.3.100/32"=>""})
+
 t.destroy
diff --git a/test/test_nodes.rb b/test/test_nodes.rb
new file mode 100644
index 0000000..580a1f9
--- /dev/null
+++ b/test/test_nodes.rb
@@ -0,0 +1,29 @@
+require 'test/unit'
+require 'rpatricia'
+
+class TestShowNodes < Test::Unit::TestCase
+
+  def test_nodes
+    t = Patricia.new
+    string = "pref_10"
+    array = [:something]
+    t.add("127.0.0.0/24")
+    t.add("192.168.1.0/24")
+    t.add("192.168.2.0/24")
+    t.add("192.168.3.100")
+    t.add("10.0.0.0/8", string)
+    t.add("10.0.0.0/9", array)
+
+    assert_equal({"10.0.0.0/8" => "pref_10",
+                  "10.0.0.0/9" => [:something],
+                  "127.0.0.0/24" => "",
+                  "192.168.1.0/24" => "",
+                  "192.168.2.0/24" => "",
+                  "192.168.3.100/32" => ""},
+                  t.nodes)
+
+    assert(string.object_id != t.nodes["10.0.0.0/8"].object_id)
+    assert(array.object_id == t.nodes["10.0.0.0/9"].object_id)
+  end
+
+end