native_btree 0.2.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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