native_btree 0.1.0.alpha1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/CMakeLists.txt +54 -0
- data/Gemfile +18 -0
- data/LICENSE +165 -0
- data/README.md +67 -0
- data/Rakefile +48 -0
- data/ext/native_btree/CMakeLists.txt +38 -0
- data/ext/native_btree/comparator.c +13 -0
- data/ext/native_btree/constructor.c +19 -0
- data/ext/native_btree/conversion.c +54 -0
- data/ext/native_btree/extconf_cmake.rb +15 -0
- data/ext/native_btree/include/common.h +21 -0
- data/ext/native_btree/include/comparator.h +4 -0
- data/ext/native_btree/include/constructor.h +11 -0
- data/ext/native_btree/include/conversion.h +8 -0
- data/ext/native_btree/include/instance.h +22 -0
- data/ext/native_btree/include/iterators.h +5 -0
- data/ext/native_btree/include/native_btree.h +5 -47
- data/ext/native_btree/include/rbtree_type.h +22 -0
- data/ext/native_btree/instance.c +126 -0
- data/ext/native_btree/iterators.c +26 -0
- data/ext/native_btree/native_btree.c +20 -22
- data/ext/native_btree/rbtree_type.c +102 -0
- data/lib/native_btree/native_btree.bundle +0 -0
- data/lib/native_btree/native_btree.so +0 -0
- data/lib/native_btree/version.rb +2 -2
- data/lib/native_btree.rb +2 -1
- data/native_btree.gemspec +33 -0
- data/spec/debug.rb +24 -0
- data/spec/native_btree_class_spec.rb +24 -0
- data/spec/native_btree_instance_spec.rb +283 -0
- data/spec/native_btree_module_spec.rb +15 -0
- data/spec/spec_helper.rb +15 -0
- metadata +50 -18
- data/ext/native_btree/btree.cc +0 -128
- data/ext/native_btree/extconf.h +0 -11
- data/ext/native_btree/extconf.rb +0 -35
- data/ext/native_btree/rb_methods.cc +0 -221
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef _RBTREE_TYPE_
|
2
|
+
#define _RBTREE_TYPE_
|
3
|
+
|
4
|
+
#include <common.h>
|
5
|
+
|
6
|
+
#define NATIVE_TYPE_NAME "native_btree"
|
7
|
+
|
8
|
+
extern const rb_data_type_t rbtree_type;
|
9
|
+
|
10
|
+
VALUE
|
11
|
+
rbtree_alloc(VALUE self);
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Internal native instance
|
15
|
+
*/
|
16
|
+
typedef struct _RBTree
|
17
|
+
{
|
18
|
+
GTree *gtree;
|
19
|
+
VALUE comparator;
|
20
|
+
} RBTree;
|
21
|
+
|
22
|
+
#endif //_RBTREE_TYPE_
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#include <instance.h>
|
2
|
+
|
3
|
+
#ifndef HAVE_GTREE_REMOVE_ALL
|
4
|
+
|
5
|
+
static gboolean
|
6
|
+
rbtree_remove_node(gpointer key, gpointer val, gpointer data) {
|
7
|
+
RBTree *rbtree = (RBTree *) data;
|
8
|
+
|
9
|
+
g_tree_remove(rbtree->gtree, key);
|
10
|
+
|
11
|
+
return FALSE;
|
12
|
+
}
|
13
|
+
|
14
|
+
#endif
|
15
|
+
|
16
|
+
|
17
|
+
VALUE
|
18
|
+
rbtree_set(VALUE self, VALUE key, VALUE value)
|
19
|
+
{
|
20
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
21
|
+
|
22
|
+
g_tree_replace(rbtree->gtree, (gpointer) key, (gpointer) value);
|
23
|
+
|
24
|
+
return self;
|
25
|
+
}
|
26
|
+
|
27
|
+
|
28
|
+
VALUE
|
29
|
+
rbtree_get(VALUE self, VALUE key)
|
30
|
+
{
|
31
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
32
|
+
|
33
|
+
gpointer found = g_tree_lookup(rbtree->gtree, (gpointer) key);
|
34
|
+
|
35
|
+
if (found == NULL) {
|
36
|
+
return Qnil;
|
37
|
+
}
|
38
|
+
|
39
|
+
VALUE result = (VALUE) found;
|
40
|
+
|
41
|
+
return result;
|
42
|
+
}
|
43
|
+
|
44
|
+
|
45
|
+
VALUE
|
46
|
+
rbtree_delete(VALUE self, VALUE key)
|
47
|
+
{
|
48
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
49
|
+
|
50
|
+
VALUE found_key, found_value;
|
51
|
+
gboolean found = g_tree_lookup_extended(
|
52
|
+
rbtree->gtree,
|
53
|
+
(gconstpointer) key,
|
54
|
+
(gpointer *) &found_key,
|
55
|
+
(gpointer *) &found_value
|
56
|
+
);
|
57
|
+
|
58
|
+
if (found) {
|
59
|
+
g_tree_remove(rbtree->gtree, (gconstpointer) key);
|
60
|
+
|
61
|
+
return found_value;
|
62
|
+
}
|
63
|
+
else {
|
64
|
+
if (rb_block_given_p()) {
|
65
|
+
VALUE block = rb_block_proc();
|
66
|
+
|
67
|
+
return rb_funcall(block, rb_intern("call"), 1, key);
|
68
|
+
}
|
69
|
+
|
70
|
+
return Qnil;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
|
75
|
+
VALUE
|
76
|
+
rbtree_height(VALUE self)
|
77
|
+
{
|
78
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
79
|
+
|
80
|
+
gint size = g_tree_height(rbtree->gtree);
|
81
|
+
VALUE result = INT2NUM(size);
|
82
|
+
|
83
|
+
return result;
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
VALUE
|
88
|
+
rbtree_size(VALUE self)
|
89
|
+
{
|
90
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
91
|
+
|
92
|
+
gint size = g_tree_nnodes(rbtree->gtree);
|
93
|
+
VALUE result = INT2NUM(size);
|
94
|
+
|
95
|
+
return result;
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
VALUE
|
100
|
+
rbtree_clear(VALUE self)
|
101
|
+
{
|
102
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
103
|
+
|
104
|
+
#ifdef HAVE_GTREE_REMOVE_ALL
|
105
|
+
g_tree_remove_all(rbtree->gtree);
|
106
|
+
#else
|
107
|
+
g_tree_foreach(rbtree->gtree, rbtree_remove_node, (gpointer) rbtree);
|
108
|
+
#endif
|
109
|
+
|
110
|
+
return self;
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
VALUE
|
115
|
+
rbtree_is_include(VALUE self, VALUE key)
|
116
|
+
{
|
117
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
118
|
+
|
119
|
+
gpointer exists = g_tree_lookup(rbtree->gtree, (gconstpointer) key);
|
120
|
+
|
121
|
+
if (exists == NULL) {
|
122
|
+
return Qfalse;
|
123
|
+
}
|
124
|
+
|
125
|
+
return Qtrue;
|
126
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#include <iterators.h>
|
2
|
+
|
3
|
+
static gboolean
|
4
|
+
foraech_callbac(gpointer a, gpointer b, gpointer data)
|
5
|
+
{
|
6
|
+
VALUE key = (VALUE) a;
|
7
|
+
VALUE value = (VALUE) b;
|
8
|
+
VALUE block = (VALUE) data;
|
9
|
+
|
10
|
+
rb_funcall(block, rb_intern("call"), 2, value, key);
|
11
|
+
|
12
|
+
return FALSE;
|
13
|
+
}
|
14
|
+
|
15
|
+
VALUE
|
16
|
+
rbtree_each(VALUE self)
|
17
|
+
{
|
18
|
+
rb_need_block();
|
19
|
+
VALUE block = rb_block_proc();
|
20
|
+
|
21
|
+
EXTRACT_RBTREE_SELF(rbtree);
|
22
|
+
|
23
|
+
g_tree_foreach(rbtree->gtree, foraech_callbac, (gpointer) block);
|
24
|
+
|
25
|
+
return self;
|
26
|
+
}
|
@@ -1,30 +1,28 @@
|
|
1
1
|
#include <native_btree.h>
|
2
2
|
|
3
|
-
VALUE
|
4
|
-
VALUE
|
3
|
+
VALUE rbtree_class;
|
4
|
+
VALUE rbtree_module;
|
5
|
+
|
5
6
|
|
6
7
|
void
|
7
8
|
Init_native_btree()
|
8
9
|
{
|
9
|
-
|
10
|
-
|
10
|
+
rbtree_module = rb_define_module(NATIVE_BTREE_MODULE);
|
11
|
+
rbtree_class = rb_define_class_under(rbtree_module, NATIVE_BTREE_CLASS, rb_cObject);
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
rb_define_method(btree_class, "size", btree_size, 0);
|
15
|
-
rb_define_method(btree_class, "height", btree_height, 0);
|
16
|
-
rb_define_method(btree_class, "set", btree_set, 2);
|
17
|
-
rb_define_alias(btree_class, "[]=", "set");
|
18
|
-
rb_define_method(btree_class, "get", btree_get, 1);
|
19
|
-
rb_define_alias(btree_class, "[]", "get");
|
20
|
-
rb_define_method(btree_class, "delete", btree_delete, 1);
|
21
|
-
rb_define_method(btree_class, "clear", btree_clear, 0);
|
22
|
-
rb_define_method(btree_class, "has", btree_has, 1);
|
23
|
-
rb_define_method(btree_class, "each", btree_each, 0);
|
24
|
-
rb_define_method(btree_class, "<=>", btree_cmp, 1);
|
25
|
-
rb_define_method(btree_class, "eql?", btree_equal, 1);
|
26
|
-
rb_define_alias(btree_class, "==", "eql?");
|
27
|
-
// TODO: to_ary
|
28
|
-
// TODO: to_hash
|
29
|
-
}
|
13
|
+
rb_define_alloc_func(rbtree_class, rbtree_alloc);
|
14
|
+
rb_define_method(rbtree_class, "initialize", rbtree_initialize, 0);
|
30
15
|
|
16
|
+
rb_define_method(rbtree_class, "[]=", rbtree_set, 2);
|
17
|
+
rb_define_alias(rbtree_class, "set", "[]=");
|
18
|
+
rb_define_method(rbtree_class, "[]", rbtree_get, 1);
|
19
|
+
rb_define_alias(rbtree_class, "get", "[]");
|
20
|
+
rb_define_method(rbtree_class, "delete", rbtree_delete, 1);
|
21
|
+
rb_define_method(rbtree_class, "each", rbtree_each, 0);
|
22
|
+
rb_define_method(rbtree_class, "size", rbtree_size, 0);
|
23
|
+
rb_define_method(rbtree_class, "height", rbtree_height, 0);
|
24
|
+
rb_define_method(rbtree_class, "clear", rbtree_clear, 0);
|
25
|
+
rb_define_method(rbtree_class, "include?", rbtree_is_include, 1);
|
26
|
+
rb_define_method(rbtree_class, "to_h", rbtree_to_h, 0);
|
27
|
+
rb_define_method(rbtree_class, "to_a", rbtree_to_a, 0);
|
28
|
+
}
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#include <rbtree_type.h>
|
2
|
+
|
3
|
+
const rb_data_type_t rbtree_type;
|
4
|
+
|
5
|
+
|
6
|
+
static void
|
7
|
+
rbtree_free(gpointer data)
|
8
|
+
{
|
9
|
+
RBTree *rbtree = (RBTree *) data;
|
10
|
+
|
11
|
+
g_tree_destroy(rbtree->gtree);
|
12
|
+
g_free(data);
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
static gboolean
|
17
|
+
rbtree_mark_callback(gpointer key, gpointer value, gpointer data)
|
18
|
+
{
|
19
|
+
rb_gc_mark((VALUE) key);
|
20
|
+
rb_gc_mark((VALUE) value);
|
21
|
+
|
22
|
+
return FALSE;
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
static void
|
27
|
+
rbtree_mark(gpointer data)
|
28
|
+
{
|
29
|
+
RBTree *rbtree = (RBTree *)data;
|
30
|
+
|
31
|
+
rb_gc_mark(rbtree->comparator);
|
32
|
+
|
33
|
+
g_tree_foreach(rbtree->gtree, rbtree_mark_callback, NULL);
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
|
38
|
+
https://github.com/GNOME/glib/blob/main/glib/gtree.c#L80
|
39
|
+
|
40
|
+
struct _GTree
|
41
|
+
{
|
42
|
+
GTreeNode *root;
|
43
|
+
GCompareDataFunc key_compare;
|
44
|
+
GDestroyNotify key_destroy_func;
|
45
|
+
GDestroyNotify value_destroy_func;
|
46
|
+
gpointer key_compare_data;
|
47
|
+
guint nnodes;
|
48
|
+
gint ref_count;
|
49
|
+
};
|
50
|
+
|
51
|
+
struct _GTreeNode
|
52
|
+
{
|
53
|
+
gpointer key;
|
54
|
+
gpointer value;
|
55
|
+
GTreeNode *left;
|
56
|
+
GTreeNode *right;
|
57
|
+
gint8 balance;
|
58
|
+
guint8 left_child;
|
59
|
+
guint8 right_child;
|
60
|
+
};
|
61
|
+
*/
|
62
|
+
|
63
|
+
static size_t
|
64
|
+
rbtree_size(gconstpointer data)
|
65
|
+
{
|
66
|
+
RBTree *rbtree = (RBTree *) data;
|
67
|
+
|
68
|
+
gint gtree_size = g_tree_nnodes(rbtree->gtree);
|
69
|
+
|
70
|
+
// struct _GTreeNode
|
71
|
+
size_t node_size = sizeof(gpointer) * 4 +
|
72
|
+
sizeof(gint8) +
|
73
|
+
sizeof(guint8) * 2;
|
74
|
+
|
75
|
+
// struct _GTree
|
76
|
+
size_t gtree_root_size = sizeof(gpointer) * 5 +
|
77
|
+
sizeof(gint8) +
|
78
|
+
sizeof(guint8) * 2;
|
79
|
+
|
80
|
+
return sizeof(RBTree) + node_size * gtree_size + gtree_root_size;
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
const rb_data_type_t rbtree_type = {
|
85
|
+
.wrap_struct_name = NATIVE_TYPE_NAME,
|
86
|
+
.function = {
|
87
|
+
.dmark = rbtree_mark,
|
88
|
+
.dfree = rbtree_free,
|
89
|
+
.dsize = rbtree_size,
|
90
|
+
},
|
91
|
+
.data = NULL,
|
92
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
93
|
+
};
|
94
|
+
|
95
|
+
|
96
|
+
VALUE
|
97
|
+
rbtree_alloc(VALUE self)
|
98
|
+
{
|
99
|
+
RBTree *rbtree = g_new(RBTree, 1);
|
100
|
+
|
101
|
+
return TypedData_Wrap_Struct(self, &rbtree_type, rbtree);
|
102
|
+
}
|
Binary file
|
Binary file
|
data/lib/native_btree/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION = "0.
|
1
|
+
module NativeBtree
|
2
|
+
VERSION = "0.2.0".freeze
|
3
3
|
end
|
data/lib/native_btree.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative "lib/native_btree/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'native_btree'
|
5
|
+
s.version = NativeBtree::VERSION
|
6
|
+
|
7
|
+
s.metadata = {
|
8
|
+
"bug_tracker_uri" => "https://github.com/unixs/ruby-native-btree/issues",
|
9
|
+
"changelog_uri" => "https://github.com/unixs/ruby-native-btree/blob/master/CHANGELOG.md",
|
10
|
+
"documentation_uri" => "https://github.com/unixs/ruby-native-btree/wiki",
|
11
|
+
"homepage_uri" => "https://github.com/unixs/ruby-native-btree",
|
12
|
+
"source_code_uri" => "https://github.com/unixs/ruby-native-btree",
|
13
|
+
"wiki_uri" => "https://github.com/unixs/ruby-native-btree/wiki",
|
14
|
+
"rubygems_mfa_required" => "true"
|
15
|
+
}
|
16
|
+
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.summary = 'Balanced binary tree from GLib.'
|
19
|
+
s.description = 'Ruby bindings to GTree balanced binary tree from GLib library.'
|
20
|
+
s.authors = ['Alexander Feodorov']
|
21
|
+
s.email = ['webmaster@unixcomp.org']
|
22
|
+
s.licenses = ['LGPL-3.0-or-later']
|
23
|
+
s.homepage = 'https://github.com/unixs/ruby-native-btree'
|
24
|
+
s.extensions = ["ext/#{s.name}/extconf_cmake.rb"]
|
25
|
+
|
26
|
+
s.files = Dir['{bin,ext,lib,spec}/**/*']
|
27
|
+
s.files += Dir['*.{md}']
|
28
|
+
s.files += %w[Rakefile Gemfile CMakeLists.txt native_btree.gemspec LICENSE]
|
29
|
+
|
30
|
+
s.executables = s.files.grep(%r{\Abin/}) { |f| File.basename(f) }
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
s.required_ruby_version = '>= 2.6'
|
33
|
+
end
|
data/spec/debug.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# rubocop:disable all
|
2
|
+
|
3
|
+
require_relative "../lib/native_btree/native_btree"
|
4
|
+
|
5
|
+
tree = NativeBtree::Btree.new
|
6
|
+
|
7
|
+
GC.start
|
8
|
+
|
9
|
+
tree[3] = {a: 'value 3'}
|
10
|
+
tree[1] = {a: 'value 1'}
|
11
|
+
tree[2] = {a: 'value 2'}
|
12
|
+
tree[16] = {a: 'value 16'}
|
13
|
+
tree[0] = {a: 'value 0'}
|
14
|
+
|
15
|
+
GC.start
|
16
|
+
|
17
|
+
block = ->(key) { "#{key} is not found" }
|
18
|
+
puts tree.delete(77, &block)
|
19
|
+
|
20
|
+
tree = null
|
21
|
+
|
22
|
+
GC.start
|
23
|
+
|
24
|
+
puts "exit 0"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe NativeBtree do
|
4
|
+
it "has a version number" do
|
5
|
+
expect(NativeBtree::VERSION).not_to be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
describe NativeBtree::Btree do
|
9
|
+
|
10
|
+
describe "initialize class method" do
|
11
|
+
it 'respond to new' do
|
12
|
+
expect(described_class).to respond_to('new').with(0).arguments
|
13
|
+
end
|
14
|
+
|
15
|
+
it "return new btree instance" do
|
16
|
+
expect(described_class.new { nil }).to be_kind_of(described_class)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raise error if block is not given" do
|
20
|
+
expect { described_class.new() }.to raise_error(LocalJumpError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|