native_btree 0.2.1 → 0.4.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -3
  3. data/CMakeLists.txt +3 -3
  4. data/Gemfile +6 -3
  5. data/README.md +51 -3
  6. data/ext/native_btree/CMakeLists.txt +29 -7
  7. data/ext/native_btree/comparator.c +9 -0
  8. data/ext/native_btree/constructor.c +34 -7
  9. data/ext/native_btree/conversion.c +25 -1
  10. data/ext/native_btree/glib2_68/CMakeLists.txt +3 -0
  11. data/ext/native_btree/glib2_68/additional_iterators.c +84 -0
  12. data/ext/native_btree/glib_module.c +45 -0
  13. data/ext/native_btree/include/common.h +7 -9
  14. data/ext/native_btree/include/comparator.h +3 -0
  15. data/ext/native_btree/include/glib_module.h +6 -0
  16. data/ext/native_btree/include/iterators.h +10 -2
  17. data/ext/native_btree/include/native_btree.h +82 -5
  18. data/ext/native_btree/include/rbtree_type.h +10 -3
  19. data/ext/native_btree/instance.c +15 -3
  20. data/ext/native_btree/iterators.c +55 -1
  21. data/ext/native_btree/native_btree.c +55 -20
  22. data/ext/native_btree/rbtree_type.c +36 -10
  23. data/ext/native_btree/search.c +94 -0
  24. data/lib/native_btree/native_btree.bundle +0 -0
  25. data/lib/native_btree/version.rb +1 -1
  26. data/spec/debug.rb +20 -2
  27. data/spec/native_btree_class_spec.rb +16 -0
  28. data/spec/native_btree_conversion_spec.rb +70 -0
  29. data/spec/native_btree_instance_spec.rb +8 -101
  30. data/spec/native_btree_int_instance_spec.rb +188 -0
  31. data/spec/native_btree_iterators_spec.rb +90 -0
  32. data/spec/native_btree_module_spec.rb +20 -0
  33. data/spec/native_btree_search_spec.rb +210 -0
  34. metadata +12 -8
  35. data/ext/native_btree/Makefile +0 -456
  36. data/ext/native_btree/include/btree.h +0 -63
  37. data/ext/native_btree/include/constructor.h +0 -11
  38. data/ext/native_btree/include/conversion.h +0 -8
  39. data/ext/native_btree/include/instance.h +0 -22
  40. data/lib/native_btree/native_btree.so +0 -0
@@ -1,4 +1,5 @@
1
- #include <iterators.h>
1
+ #include <common.h>
2
+
2
3
 
3
4
  static gboolean
4
5
  foraech_callbac(gpointer a, gpointer b, gpointer data)
@@ -12,6 +13,31 @@ foraech_callbac(gpointer a, gpointer b, gpointer data)
12
13
  return FALSE;
13
14
  }
14
15
 
16
+
17
+ static gboolean
18
+ foraech_key_callbac(gpointer a, gpointer b, gpointer data)
19
+ {
20
+ VALUE key = (VALUE) a;
21
+ VALUE block = (VALUE) data;
22
+
23
+ rb_funcall(block, rb_intern("call"), 1, key);
24
+
25
+ return FALSE;
26
+ }
27
+
28
+
29
+ static gboolean
30
+ foraech_value_callbac(gpointer a, gpointer b, gpointer data)
31
+ {
32
+ VALUE value = (VALUE) b;
33
+ VALUE block = (VALUE) data;
34
+
35
+ rb_funcall(block, rb_intern("call"), 1, value);
36
+
37
+ return FALSE;
38
+ }
39
+
40
+
15
41
  VALUE
16
42
  rbtree_each(VALUE self)
17
43
  {
@@ -24,3 +50,31 @@ rbtree_each(VALUE self)
24
50
 
25
51
  return self;
26
52
  }
53
+
54
+
55
+ VALUE
56
+ rbtree_each_key(VALUE self)
57
+ {
58
+ rb_need_block();
59
+ VALUE block = rb_block_proc();
60
+
61
+ EXTRACT_RBTREE_SELF(rbtree);
62
+
63
+ g_tree_foreach(rbtree->gtree, foraech_key_callbac, (gpointer) block);
64
+
65
+ return self;
66
+ }
67
+
68
+
69
+ VALUE
70
+ rbtree_each_value(VALUE self)
71
+ {
72
+ rb_need_block();
73
+ VALUE block = rb_block_proc();
74
+
75
+ EXTRACT_RBTREE_SELF(rbtree);
76
+
77
+ g_tree_foreach(rbtree->gtree, foraech_value_callbac, (gpointer) block);
78
+
79
+ return self;
80
+ }
@@ -1,28 +1,63 @@
1
1
  #include <native_btree.h>
2
+ #include <rbtree_type.h>
3
+ #include <glib_module.h>
2
4
 
3
- VALUE rbtree_class;
4
- VALUE rbtree_module;
5
+ #define NATIVE_BTREE_MODULE "NativeBtree"
6
+ #define NATIVE_BTREE_CLASS "Btree"
7
+ #define NATIVE_BTREE_CONST_INT_COMPARATOR "INT_COMPARATOR"
5
8
 
6
9
 
10
+ VALUE native_btree_class;
11
+ VALUE native_btree_module;
12
+
7
13
  void
8
14
  Init_native_btree()
9
15
  {
10
- rbtree_module = rb_define_module(NATIVE_BTREE_MODULE);
11
- rbtree_class = rb_define_class_under(rbtree_module, NATIVE_BTREE_CLASS, rb_cObject);
12
-
13
- rb_define_alloc_func(rbtree_class, rbtree_alloc);
14
- rb_define_method(rbtree_class, "initialize", rbtree_initialize, 0);
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);
16
+ native_btree_module = rb_define_module(NATIVE_BTREE_MODULE);
17
+ native_btree_class = rb_define_class_under(
18
+ native_btree_module,
19
+ NATIVE_BTREE_CLASS,
20
+ rb_cObject
21
+ );
22
+
23
+ VALUE int_comparator = USHORT2NUM(RBTREE_FLAG_INT_COMPARATOR);
24
+ OBJ_FREEZE(int_comparator);
25
+ rb_define_const(
26
+ native_btree_class,
27
+ NATIVE_BTREE_CONST_INT_COMPARATOR,
28
+ int_comparator
29
+ );
30
+
31
+ rbtree_attach_module_glib();
32
+
33
+ // rb_include_module(native_btree_class, rb_mEnumerable);
34
+
35
+ rb_define_alloc_func(native_btree_class, rbtree_alloc);
36
+ rb_define_method(native_btree_class, "initialize", rbtree_initialize, -1);
37
+
38
+ rb_define_method(native_btree_class, "[]=", rbtree_set, 2);
39
+ rb_define_alias(native_btree_class, "set", "[]=");
40
+ rb_define_method(native_btree_class, "[]", rbtree_get, 1);
41
+ rb_define_alias(native_btree_class, "get", "[]");
42
+ rb_define_method(native_btree_class, "delete", rbtree_delete, 1);
43
+ rb_define_method(native_btree_class, "each", rbtree_each, 0);
44
+ rb_define_method(native_btree_class, "each_key", rbtree_each_key, 0);
45
+ rb_define_method(native_btree_class, "each_value", rbtree_each_value, 0);
46
+ rb_define_method(native_btree_class, "size", rbtree_size, 0);
47
+ rb_define_method(native_btree_class, "height", rbtree_height, 0);
48
+ rb_define_method(native_btree_class, "clear", rbtree_clear, 0);
49
+ rb_define_method(native_btree_class, "include?", rbtree_is_include, 1);
50
+ rb_define_method(native_btree_class, "to_h", rbtree_to_h, 0);
51
+ rb_define_method(native_btree_class, "to_a", rbtree_to_a, 0);
52
+ rb_define_method(native_btree_class, "to_proc", rbtree_to_proc, 0);
53
+ rb_define_method(native_btree_class, "filter", rbtree_filter, 0);
54
+ rb_define_alias(native_btree_class, "select", "filter");
55
+ rb_define_method(native_btree_class, "filter!", rbtree_filter_bang, 0);
56
+ rb_define_alias(native_btree_class, "select!", "filter!");
57
+ rb_define_method(native_btree_class, "empty?", rbtree_is_empty, 0);
58
+
59
+ #ifdef HAS_GTREE_NODE
60
+ rb_define_method(native_btree_class, "select_before", rbtree_select_before, 1);
61
+ rb_define_method(native_btree_class, "select_after", rbtree_select_after, 1);
62
+ #endif
28
63
  }
@@ -4,11 +4,14 @@ const rb_data_type_t rbtree_type;
4
4
 
5
5
 
6
6
  static void
7
- rbtree_free(gpointer data)
7
+ rbtree_type_free(gpointer data)
8
8
  {
9
9
  RBTree *rbtree = (RBTree *) data;
10
10
 
11
- g_tree_destroy(rbtree->gtree);
11
+ if (rbtree->gtree) {
12
+ g_tree_destroy(rbtree->gtree);
13
+ }
14
+
12
15
  g_free(data);
13
16
  }
14
17
 
@@ -24,11 +27,13 @@ rbtree_mark_callback(gpointer key, gpointer value, gpointer data)
24
27
 
25
28
 
26
29
  static void
27
- rbtree_mark(gpointer data)
30
+ rbtree_type_mark(gpointer data)
28
31
  {
29
- RBTree *rbtree = (RBTree *)data;
32
+ RBTree *rbtree = (RBTree *) data;
30
33
 
31
- rb_gc_mark(rbtree->comparator);
34
+ if (!NIL_P(rbtree->comparator)) {
35
+ rb_gc_mark(rbtree->comparator);
36
+ }
32
37
 
33
38
  g_tree_foreach(rbtree->gtree, rbtree_mark_callback, NULL);
34
39
  }
@@ -61,7 +66,7 @@ struct _GTreeNode
61
66
  */
62
67
 
63
68
  static size_t
64
- rbtree_size(gconstpointer data)
69
+ rbtree_type_size(gconstpointer data)
65
70
  {
66
71
  RBTree *rbtree = (RBTree *) data;
67
72
 
@@ -82,11 +87,11 @@ rbtree_size(gconstpointer data)
82
87
 
83
88
 
84
89
  const rb_data_type_t rbtree_type = {
85
- .wrap_struct_name = NATIVE_TYPE_NAME,
90
+ .wrap_struct_name = RBTREE_NATIVE_TYPE_NAME,
86
91
  .function = {
87
- .dmark = rbtree_mark,
88
- .dfree = rbtree_free,
89
- .dsize = rbtree_size,
92
+ .dmark = rbtree_type_mark,
93
+ .dfree = rbtree_type_free,
94
+ .dsize = rbtree_type_size,
90
95
  },
91
96
  .data = NULL,
92
97
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
@@ -98,5 +103,26 @@ rbtree_alloc(VALUE self)
98
103
  {
99
104
  RBTree *rbtree = g_new(RBTree, 1);
100
105
 
106
+ rbtree->gtree = NULL;
107
+ rbtree->comparator = Qnil;
108
+ rbtree->flags = 0;
109
+
101
110
  return TypedData_Wrap_Struct(self, &rbtree_type, rbtree);
102
111
  }
112
+
113
+
114
+ VALUE
115
+ rbtree_clone_wrap(const RBTree *orig)
116
+ {
117
+ const VALUE rflags = USHORT2NUM(orig->flags);
118
+
119
+ VALUE new_tree = rb_funcall_with_block(
120
+ native_btree_class,
121
+ rb_intern("new"),
122
+ orig->flags ? 1 : 0,
123
+ orig->flags ? &rflags : NULL,
124
+ orig->comparator
125
+ );
126
+
127
+ return new_tree;
128
+ }
@@ -0,0 +1,94 @@
1
+ #include <iterators.h>
2
+
3
+
4
+ static gboolean
5
+ filter_callback(gpointer a, gpointer b, gpointer data)
6
+ {
7
+ RBTreeSearchData *context = (RBTreeSearchData *) data;
8
+
9
+ VALUE compare_result = rb_funcall(
10
+ context->block,
11
+ rb_intern("call"),
12
+ 2,
13
+ (VALUE) b,
14
+ (VALUE) a
15
+ );
16
+
17
+ if (RTEST(compare_result)) {
18
+ g_tree_insert(context->tree->gtree, a, b);
19
+ }
20
+
21
+ return FALSE;
22
+ }
23
+
24
+ static gboolean
25
+ filter_bang_callback(gpointer a, gpointer b, gpointer data)
26
+ {
27
+ RBTreeSearchData *context = (RBTreeSearchData *) data;
28
+ GPtrArray *to_remove = (GPtrArray *) context->something;
29
+
30
+ VALUE compare_result = rb_funcall(
31
+ context->block,
32
+ rb_intern("call"),
33
+ 2,
34
+ (VALUE) b,
35
+ (VALUE) a
36
+ );
37
+
38
+ if (!RTEST(compare_result)) {
39
+ // Add to remove
40
+ g_ptr_array_add(to_remove, a);
41
+ }
42
+
43
+ return FALSE;
44
+ }
45
+
46
+ VALUE
47
+ rbtree_filter(VALUE self)
48
+ {
49
+ rb_need_block();
50
+ EXTRACT_RBTREE_SELF(rbtree);
51
+
52
+ VALUE block = rb_block_proc();
53
+
54
+ VALUE new_tree = rbtree_clone_wrap(rbtree);
55
+
56
+ EXTRACT_RBTREE(new_tree, new_rbtree);
57
+
58
+ RBTreeSearchData data = {
59
+ block,
60
+ new_rbtree,
61
+ NULL
62
+ };
63
+
64
+ g_tree_foreach(rbtree->gtree, filter_callback, &data);
65
+
66
+ return new_tree;
67
+ }
68
+
69
+ VALUE
70
+ rbtree_filter_bang(VALUE self)
71
+ {
72
+ rb_need_block();
73
+ EXTRACT_RBTREE_SELF(rbtree);
74
+
75
+ VALUE block = rb_block_proc();
76
+
77
+ GPtrArray *to_remove = g_ptr_array_new();
78
+
79
+ RBTreeSearchData data = {
80
+ block,
81
+ NULL,
82
+ (gconstpointer) to_remove
83
+ };
84
+
85
+ g_tree_foreach(rbtree->gtree, filter_bang_callback, &data);
86
+
87
+ for (size_t i = 0; i < to_remove->len; i++) {
88
+ g_tree_remove(rbtree->gtree, g_ptr_array_index(to_remove, i));
89
+ }
90
+
91
+ g_ptr_array_free(to_remove, TRUE);
92
+
93
+ return self;
94
+ }
@@ -1,3 +1,3 @@
1
1
  module NativeBtree
2
- VERSION = "0.2.1".freeze
2
+ VERSION = "0.4.0".freeze
3
3
  end
data/spec/debug.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "../lib/native_btree/native_btree"
4
4
 
5
- tree = NativeBtree::Btree.new
5
+ tree = NativeBtree::Btree.new() {|a, b| a - b }
6
6
 
7
7
  GC.start
8
8
 
@@ -17,7 +17,25 @@ GC.start
17
17
  block = ->(key) { "#{key} is not found" }
18
18
  puts tree.delete(77, &block)
19
19
 
20
- tree = null
20
+ tree2 = tree.filter!() { true }
21
+
22
+ puts tree.to_h
23
+
24
+ pr = tree.to_proc
25
+
26
+ puts pr
27
+
28
+
29
+ tree.clear
30
+ tree[1] = 15
31
+ tree[2] = 22
32
+ tree[3] = 33
33
+ tree[4] = 44
34
+ tree[5] = 55
35
+ tree[6] = 66
36
+ tree[7] = 77
37
+
38
+ puts tree.select_after(4).to_h
21
39
 
22
40
  GC.start
23
41
 
@@ -19,6 +19,22 @@ RSpec.describe NativeBtree do
19
19
  it "raise error if block is not given" do
20
20
  expect { described_class.new() }.to raise_error(LocalJumpError)
21
21
  end
22
+
23
+ it 'return new btree with int comparator' do
24
+ expect(described_class.new(described_class::INT_COMPARATOR))
25
+ .to be_kind_of(described_class)
26
+ end
27
+
28
+ end
29
+
30
+ describe "constants" do
31
+ it 'has const INT_COMPARATOR' do
32
+ expect(described_class.const_defined?(:INT_COMPARATOR)).to be true
33
+ end
34
+
35
+ it 'const INT_COMPARATOR is 1' do
36
+ expect(described_class::INT_COMPARATOR).to be 128
37
+ end
22
38
  end
23
39
  end
24
40
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe NativeBtree do
4
+
5
+ describe NativeBtree::Btree do
6
+ let(:tree) do
7
+ described_class.new do |a, b|
8
+ a - b
9
+ end
10
+ end
11
+
12
+ describe "to_ methods" do
13
+ describe "#to_a" do
14
+ it "respond to" do
15
+ expect(tree).to respond_to(:to_a)
16
+ end
17
+
18
+ it 'return Array' do
19
+ expect(tree.to_a).to be_kind_of(Array)
20
+ end
21
+
22
+ it 'has similar items' do
23
+ tree[2] = 22
24
+ tree[1] = 11
25
+ expect(tree.to_a()[0][1]).to be 11
26
+ end
27
+ end
28
+
29
+ describe "#to_h" do
30
+ it "respond to" do
31
+ expect(tree).to respond_to(:to_h)
32
+ end
33
+
34
+ it "return Hash" do
35
+ expect(tree.to_h).to be_kind_of(Hash)
36
+ end
37
+
38
+ it 'has similar keys' do
39
+ tree[2] = 22
40
+ tree[1] = 11
41
+ expect(tree.to_h()[1]).to be 11
42
+ end
43
+ end
44
+
45
+ describe '#to_proc' do
46
+ it 'respond to' do
47
+ expect(tree).to respond_to(:to_proc)
48
+ end
49
+
50
+ it 'return Proc' do
51
+ expect(tree.to_proc).to be_kind_of(Proc)
52
+ end
53
+
54
+ it 'return value for key' do
55
+ tree[2] = 22
56
+ tree[1] = 11
57
+ pr = tree.to_proc
58
+ expect(pr.call(1)).to be 11
59
+ end
60
+
61
+ it 'return null for non existent key' do
62
+ tree[2] = 22
63
+ tree[1] = 11
64
+ pr = tree.to_proc
65
+ expect(pr.call(12)).to be_nil
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -156,18 +156,6 @@ RSpec.describe NativeBtree do
156
156
  end
157
157
  end
158
158
 
159
- describe "#filter method" do
160
- xit "respond to" do
161
- expect(described_cless.respond_to?(:filter)).to be true
162
- end
163
- end
164
-
165
- describe "#filter! method" do
166
- xit "respond to" do
167
- expect(described_cless.respond_to?(:filter!)).to be true
168
- end
169
- end
170
-
171
159
  describe "#include? method" do
172
160
  it "respond to" do
173
161
  expect(tree).to respond_to(:include?)
@@ -184,99 +172,18 @@ RSpec.describe NativeBtree do
184
172
  end
185
173
  end
186
174
 
187
- describe "to_ methods" do
188
- describe "#to_a" do
189
- it "respond to" do
190
- expect(tree).to respond_to(:to_a)
191
- end
192
-
193
- it 'return Array' do
194
- expect(tree.to_a).to be_kind_of(Array)
195
- end
196
-
197
- it 'has similar items' do
198
- tree[2] = 22
199
- tree[1] = 11
200
- expect(tree.to_a()[0][1]).to be 11
201
- end
175
+ describe "#empty? method" do
176
+ it 'respond to' do
177
+ expect(tree).to respond_to(:empty?)
202
178
  end
203
179
 
204
- describe "#to_h" do
205
- it "respond to" do
206
- expect(tree).to respond_to(:to_h)
207
- end
208
-
209
- it "return Hash" do
210
- expect(tree.to_h).to be_kind_of(Hash)
211
- end
212
-
213
- it 'has similar keys' do
214
- tree[2] = 22
215
- tree[1] = 11
216
- expect(tree.to_h()[1]).to be 11
217
- end
218
- end
219
- end
220
-
221
- describe "#each method" do
222
- it "respond to" do
223
- expect(tree).to respond_to(:each)
224
- end
225
-
226
- it 'yield in to block value first' do
227
- tree[2] = 22
228
-
229
- value = nil
230
- tree.each { |v| value = v }
231
-
232
- expect(value).to be 22
233
- end
234
-
235
- it 'yield in to block key second' do
236
- tree[2] = 22
237
-
238
- key = nil
239
- tree.each { |_v, k| key = k }
240
-
241
- expect(key).to be 2
242
- end
243
-
244
- it 'yield ordered keys' do
245
- tree[16] = 16
246
- tree[0] = 0
247
- tree[5] = 5
248
- tree[-4] = -4
249
- tree[7] = 7
250
-
251
- check = [-4, 0, 5, 7, 16]
252
- result = []
253
- tree.each { |value| result << value }
254
-
255
- expect(result).to eq(check)
256
- end
257
- end
258
-
259
- describe "#each_key method" do
260
- xit "respond to" do
261
- expect(described_cless.respond_to?(:each_key)).to be true
262
- end
263
- end
264
-
265
- describe "#each_value method" do
266
- xit "respond to" do
267
- expect(described_cless.respond_to?(:each_value)).to be true
268
- end
269
- end
270
-
271
- describe "#select method" do
272
- xit "respond to" do
273
- expect(described_cless.respond_to?(:select)).to be true
180
+ it 'return false if nodes exists' do
181
+ tree[3] = 33
182
+ expect(tree.empty?).to be false
274
183
  end
275
- end
276
184
 
277
- describe "#select! method" do
278
- xit "respond to" do
279
- expect(described_cless.respond_to?(:select!)).to be true
185
+ it 'return true if nodes not exists' do
186
+ expect(tree.empty?).to be true
280
187
  end
281
188
  end
282
189
  end