native_btree 0.4.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 467637c8963d9da6b70984356470bddfaa7d1b6b3952091e76730852bde71bac
4
- data.tar.gz: a1842e6875ae3dbd94855a50cc38e35369a623518a502694df1d7f223ebe481b
3
+ metadata.gz: '08e62bb88bd973ac257570f1b769323dea7ccedf9c0c2d80f5e99ba7eb2f33ff'
4
+ data.tar.gz: d8d2cfac5c388216c45b1c17e225a2982871dd94c871414623f73222cd8e6f81
5
5
  SHA512:
6
- metadata.gz: c14e828145463b99a5edd19b0c830fcba54a86872380e32acee447ce302daea5a9300771f8b4ee68c90c2807e2fd9d595bb9f71ac15c7e9d2f261f95790f9767
7
- data.tar.gz: b2d449bfd707dabec594f0847312956cbf6c80543497027611c04eb81215b620dfd4efdbda8427f4628ddd8e500742fdb3d7e12f9664ba963387a1556c40bb74
6
+ metadata.gz: 5ef4b7687b447e1b36c32e0252bb71f90005e0cfa729a1ddfd6f62f0b4e6b0c11ef29e3703563459de551fa3ae0577c537cd8d09f1a04fa34745d2abf53ab541
7
+ data.tar.gz: 99d89673be28500e83030d0d300f758ff0857d0be0d9026dd39d72fe7b35ac58bdc44ba5fd567145ace04676ada29dd6a4afe895e47c99b23de530f53cf72951
data/CHANGELOG.md CHANGED
@@ -8,7 +8,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
  * delete_if()
11
- * each method refactoring for Enumerator return type
11
+ * first, min
12
+ * last, max
13
+
14
+ ## [0.5.0] - 2022-10-04
15
+
16
+ ### Added
17
+
18
+ * ==()
19
+ * each like methods without a block returns Enumerator
20
+ * reverse_each
21
+
22
+ ### Changed
23
+
24
+ * Refactoring
25
+
26
+ ## [0.4.1] - 2022-09-30
27
+
28
+ ### Changed
29
+
30
+ * Fix - Failed building on Apple M1 CPU
12
31
 
13
32
  ## [0.4.0] - 2022-09-16
14
33
 
data/CMakeLists.txt CHANGED
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5)
2
2
 
3
3
  project(ruby-native-btree
4
4
  LANGUAGES C
5
- VERSION 0.4.1)
5
+ VERSION 0.5.0)
6
6
 
7
7
  include(CheckSymbolExists)
8
8
  include(CheckCCompilerFlag)
data/README.md CHANGED
@@ -99,6 +99,7 @@ Implemented methods:
99
99
 
100
100
  * `[]= (alias: set)`
101
101
  * `[] (alias: get)`
102
+ * `==`
102
103
  * `delete`
103
104
  * `size`
104
105
  * `height`
@@ -115,5 +116,6 @@ Implemented methods:
115
116
  * `search_before` (GLib version >= 2.68) - Select keys <= first arg, ret new Btree
116
117
  * `search_after` (GLib version >= 2.68) - Select keys >= first arg, ret new Btree
117
118
  * `empty?`
119
+ * `reverse_each`
118
120
 
119
121
  You can mix in the `Enumerable` module if additional methods are needed.
@@ -38,6 +38,7 @@ add_library(iterators OBJECT iterators.c)
38
38
  add_library(conversion OBJECT conversion.c)
39
39
  add_library(search OBJECT search.c)
40
40
  add_library(glib_module OBJECT glib_module.c)
41
+ add_library(utils OBJECT utils.c)
41
42
 
42
43
 
43
44
  set(LIB_OBJECTS)
@@ -53,6 +54,9 @@ list(APPEND LIB_OBJECTS
53
54
 
54
55
  if(HAS_GTREE_NODE)
55
56
  list(APPEND LIB_OBJECTS $<TARGET_OBJECTS:additional_iterators>)
57
+ list(APPEND LIB_OBJECTS $<TARGET_OBJECTS:compare_trees>)
58
+ else()
59
+ list(APPEND LIB_OBJECTS $<TARGET_OBJECTS:utils>)
56
60
  endif()
57
61
 
58
62
  add_library(native_btree_interface
@@ -1,3 +1,4 @@
1
1
  # set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
2
2
 
3
3
  add_library(additional_iterators OBJECT additional_iterators.c)
4
+ add_library(compare_trees OBJECT compare_trees.c)
@@ -0,0 +1,54 @@
1
+ #include <compare_trees.h>
2
+
3
+ static inline gboolean
4
+ rbtree_compare_trees_nodes(GTreeNode *a, GTreeNode *b)
5
+ {
6
+ gboolean result = TRUE;
7
+
8
+ VALUE key_a = (VALUE) g_tree_node_key(a);
9
+ VALUE val_a = (VALUE) g_tree_node_value(a);
10
+ VALUE key_b = (VALUE) g_tree_node_key(b);
11
+ VALUE val_b = (VALUE) g_tree_node_value(b);
12
+
13
+ VALUE key_result = rb_funcall(key_a, rb_intern("=="), 1, key_b);
14
+
15
+ if (!RTEST(key_result)) {
16
+ return FALSE;
17
+ }
18
+
19
+ VALUE val_result = rb_funcall(val_a, rb_intern("=="), 1, val_b);
20
+
21
+ if (!RTEST(val_result)) {
22
+ return FALSE;
23
+ }
24
+
25
+ return result;
26
+ }
27
+
28
+ /**
29
+ * Compare two trees
30
+ *
31
+ * This function assumes that the number of nodes is same (already checked)
32
+ */
33
+ gboolean
34
+ rbtree_compare_trees(const RBTree *a, const RBTree *b)
35
+ {
36
+
37
+ GTreeNode *a_node = g_tree_node_first(a->gtree);
38
+ GTreeNode *b_node = g_tree_node_first(b->gtree);
39
+
40
+ gboolean result = FALSE;
41
+
42
+ while (a_node && b_node) {
43
+ result = rbtree_compare_trees_nodes(a_node, b_node);
44
+
45
+ if (!result) {
46
+ break;
47
+ }
48
+
49
+ a_node = g_tree_node_next(a_node);
50
+ b_node = g_tree_node_next(b_node);
51
+ }
52
+
53
+ return result;
54
+ }
@@ -0,0 +1,4 @@
1
+ #include <common.h>
2
+
3
+ gboolean
4
+ rbtree_compare_trees(const RBTree *a, const RBTree *b);
@@ -83,4 +83,10 @@ rbtree_keys(VALUE self);
83
83
  VALUE
84
84
  rbtree_values(VALUE self);
85
85
 
86
+ VALUE
87
+ rbtree_equal(VALUE self, VALUE btree);
88
+
89
+ VALUE
90
+ rbtree_reverse_each(VALUE self);
91
+
86
92
  #endif // _NATIVE_BTREE_
@@ -0,0 +1,10 @@
1
+ #include <common.h>
2
+
3
+
4
+ #ifndef _NATIVE_BTREE_UTILS_
5
+ #define _NATIVE_BTREE_UTILS_
6
+
7
+ GPtrArray*
8
+ rbtree_to_ptr_array(const RBTree *rbtree);
9
+
10
+ #endif //_NATIVE_BTREE_UTILS_
@@ -1,5 +1,10 @@
1
1
  #include <common.h>
2
2
 
3
+ #ifdef HAS_GTREE_NODE
4
+ #include <compare_trees.h>
5
+ #else
6
+ #include <utils.h>
7
+ #endif
3
8
 
4
9
  #ifndef HAS_GTREE_REMOVE_ALL
5
10
 
@@ -63,9 +68,7 @@ rbtree_delete(VALUE self, VALUE key)
63
68
  }
64
69
  else {
65
70
  if (rb_block_given_p()) {
66
- VALUE block = rb_block_proc();
67
-
68
- return rb_funcall(block, rb_intern("call"), 1, key);
71
+ return rb_yield(key);
69
72
  }
70
73
 
71
74
  return Qnil;
@@ -136,3 +139,85 @@ rbtree_is_empty(VALUE self)
136
139
 
137
140
  return size > 0 ? Qfalse : Qtrue;
138
141
  }
142
+
143
+
144
+ #ifndef HAS_GTREE_NODE
145
+
146
+ static inline gboolean
147
+ legacy_rbtree_compare(const RBTree *a, const RBTree *b)
148
+ {
149
+ gboolean result = FALSE;
150
+
151
+ GPtrArray *first = rbtree_to_ptr_array(a);
152
+ GPtrArray *second = rbtree_to_ptr_array(b);
153
+
154
+ // assumes that the size of arrays is same (checked before)
155
+
156
+ VALUE key, val, key2, val2, is_eq;
157
+
158
+ for (guint i = 0; i < first->len; i += 2) {
159
+ key = (VALUE) g_ptr_array_index(first, i);
160
+ val = (VALUE) g_ptr_array_index(first, i + 1);
161
+
162
+ key2 = (VALUE) g_ptr_array_index(second, i);
163
+ val2 = (VALUE) g_ptr_array_index(second, i + 1);
164
+
165
+ is_eq = rb_funcall(key, rb_intern("=="), 1, key2);
166
+
167
+ if (!RTEST(is_eq)) {
168
+ goto fail;
169
+ }
170
+
171
+ is_eq = rb_funcall(val, rb_intern("=="), 1, val2);
172
+
173
+ if (!RTEST(is_eq)) {
174
+ goto fail;
175
+ }
176
+ }
177
+
178
+ result = TRUE;
179
+
180
+ fail:
181
+
182
+ g_ptr_array_free(first, TRUE);
183
+ g_ptr_array_free(second, TRUE);
184
+
185
+ return result;
186
+ }
187
+
188
+ #endif
189
+
190
+
191
+ VALUE
192
+ rbtree_equal(VALUE self, VALUE second)
193
+ {
194
+ EXTRACT_RBTREE_SELF(rbtree);
195
+ EXTRACT_RBTREE(second, rbtree2);
196
+
197
+ gint self_size = g_tree_nnodes(rbtree->gtree);
198
+ gint second_size = g_tree_nnodes(rbtree2->gtree);
199
+
200
+ VALUE result = Qfalse;
201
+
202
+ if (self_size != second_size) {
203
+ goto ret;
204
+ }
205
+
206
+ if (self_size == 0) {
207
+ result = Qtrue;
208
+ goto ret;
209
+ }
210
+
211
+ #ifdef HAS_GTREE_NODE
212
+ if (rbtree_compare_trees(rbtree, rbtree2)) {
213
+ result = Qtrue;
214
+ }
215
+ #else
216
+ if (legacy_rbtree_compare(rbtree, rbtree2)) {
217
+ result = Qtrue;
218
+ }
219
+ #endif
220
+
221
+ ret:
222
+ return result;
223
+ }
@@ -1,5 +1,8 @@
1
1
  #include <common.h>
2
2
 
3
+ #ifndef HAS_GTREE_NODE
4
+ #include <utils.h>
5
+ #endif
3
6
 
4
7
  static gboolean
5
8
  foraech_callbac(gpointer a, gpointer b, gpointer data)
@@ -38,14 +41,22 @@ foraech_value_callbac(gpointer a, gpointer b, gpointer data)
38
41
  }
39
42
 
40
43
 
44
+ static VALUE
45
+ rbtree_enum_length(VALUE rbtree, VALUE args, VALUE eobj)
46
+ {
47
+ return rbtree_size(rbtree);
48
+ }
49
+
50
+
41
51
  VALUE
42
52
  rbtree_each(VALUE self)
43
53
  {
44
- rb_need_block();
45
- VALUE block = rb_block_proc();
54
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
46
55
 
47
56
  EXTRACT_RBTREE_SELF(rbtree);
48
57
 
58
+ VALUE block = rb_block_proc();
59
+
49
60
  g_tree_foreach(rbtree->gtree, foraech_callbac, (gpointer) block);
50
61
 
51
62
  return self;
@@ -55,11 +66,12 @@ rbtree_each(VALUE self)
55
66
  VALUE
56
67
  rbtree_each_key(VALUE self)
57
68
  {
58
- rb_need_block();
59
- VALUE block = rb_block_proc();
69
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
60
70
 
61
71
  EXTRACT_RBTREE_SELF(rbtree);
62
72
 
73
+ VALUE block = rb_block_proc();
74
+
63
75
  g_tree_foreach(rbtree->gtree, foraech_key_callbac, (gpointer) block);
64
76
 
65
77
  return self;
@@ -69,12 +81,50 @@ rbtree_each_key(VALUE self)
69
81
  VALUE
70
82
  rbtree_each_value(VALUE self)
71
83
  {
72
- rb_need_block();
73
- VALUE block = rb_block_proc();
84
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
74
85
 
75
86
  EXTRACT_RBTREE_SELF(rbtree);
76
87
 
88
+ VALUE block = rb_block_proc();
89
+
77
90
  g_tree_foreach(rbtree->gtree, foraech_value_callbac, (gpointer) block);
78
91
 
79
92
  return self;
80
93
  }
94
+
95
+
96
+ VALUE
97
+ rbtree_reverse_each(VALUE self)
98
+ {
99
+ EXTRACT_RBTREE_SELF(rbtree);
100
+
101
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
102
+
103
+ #ifdef HAS_GTREE_NODE
104
+ GTreeNode *current = g_tree_node_last(rbtree->gtree);
105
+
106
+ VALUE key, val;
107
+ while (current) {
108
+ key = (VALUE) g_tree_node_key(current);
109
+ val = (VALUE) g_tree_node_value(current);
110
+
111
+ rb_yield_values(2, val, key);
112
+
113
+ current = g_tree_node_previous(current);
114
+ }
115
+ #else
116
+ GPtrArray *buff = rbtree_to_ptr_array(rbtree);
117
+
118
+ VALUE key, val;
119
+ for (glong i = buff->len - 1; i > 0; i--) {
120
+ val = (VALUE) g_ptr_array_index(buff, i);
121
+ key = (VALUE) g_ptr_array_index(buff, --i);
122
+
123
+ rb_yield_values(2, val, key);
124
+ }
125
+
126
+ g_ptr_array_free(buff, TRUE);
127
+ #endif
128
+
129
+ return self;
130
+ }
@@ -55,6 +55,8 @@ Init_native_btree()
55
55
  rb_define_method(native_btree_class, "filter!", rbtree_filter_bang, 0);
56
56
  rb_define_alias(native_btree_class, "select!", "filter!");
57
57
  rb_define_method(native_btree_class, "empty?", rbtree_is_empty, 0);
58
+ rb_define_method(native_btree_class, "==", rbtree_equal, 1);
59
+ rb_define_method(native_btree_class, "reverse_each", rbtree_reverse_each, 0);
58
60
 
59
61
  #ifdef HAS_GTREE_NODE
60
62
  rb_define_method(native_btree_class, "select_before", rbtree_select_before, 1);
@@ -0,0 +1,26 @@
1
+ #include <utils.h>
2
+
3
+
4
+ static gint
5
+ to_ptr_array_cb(gpointer a, gpointer b, gpointer data)
6
+ {
7
+ GPtrArray *buff = (GPtrArray *) data;
8
+
9
+ g_ptr_array_add(buff, a);
10
+ g_ptr_array_add(buff, b);
11
+
12
+ return FALSE;
13
+ }
14
+
15
+
16
+ GPtrArray*
17
+ rbtree_to_ptr_array(const RBTree *rbtree)
18
+ {
19
+ gint tree_size = g_tree_nnodes(rbtree->gtree);
20
+
21
+ GPtrArray *buff = g_ptr_array_sized_new(tree_size * 2);
22
+
23
+ g_tree_foreach(rbtree->gtree, to_ptr_array_cb, (gpointer) buff);
24
+
25
+ return buff;
26
+ }
Binary file
@@ -1,3 +1,3 @@
1
1
  module NativeBtree
2
- VERSION = "0.4.1".freeze
2
+ VERSION = "0.5.0".freeze
3
3
  end
data/spec/debug.rb CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  require_relative "../lib/native_btree/native_btree"
4
4
 
5
+ NativeBtree::Btree.include(Enumerable)
6
+
5
7
  tree = NativeBtree::Btree.new() {|a, b| a - b }
8
+ tree2 = NativeBtree::Btree.new() {|a, b| a - b }
6
9
 
7
10
  GC.start
8
11
 
@@ -17,8 +20,6 @@ GC.start
17
20
  block = ->(key) { "#{key} is not found" }
18
21
  puts tree.delete(77, &block)
19
22
 
20
- tree2 = tree.filter!() { true }
21
-
22
23
  puts tree.to_h
23
24
 
24
25
  pr = tree.to_proc
@@ -27,15 +28,12 @@ puts pr
27
28
 
28
29
 
29
30
  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
31
+ (1..1000000).each do |i|
32
+ tree[i] = i+2
33
+ tree2[i] = i+2
34
+ end
35
+
36
+ puts tree == tree2
39
37
 
40
38
  GC.start
41
39
 
@@ -186,5 +186,77 @@ RSpec.describe NativeBtree do
186
186
  expect(tree.empty?).to be true
187
187
  end
188
188
  end
189
+
190
+ describe '#== method' do
191
+ let(:tree2) do
192
+ described_class.new do |a, b|
193
+ a - b
194
+ end
195
+ end
196
+
197
+ it 'respond to' do
198
+ expect(tree).to respond_to(:==)
199
+ end
200
+
201
+ it 'return true if eql' do
202
+ tree[1] = 11
203
+ tree[2] = 22
204
+ tree[7] = 77
205
+
206
+ tree2[7] = 77
207
+ tree2[2] = 22
208
+ tree2[1] = 11
209
+
210
+ expect(tree).to eq tree2
211
+ end
212
+
213
+ it 'return false if not eql' do
214
+ tree[1] = 11
215
+ tree[2] = 22
216
+ tree[7] = 77
217
+ tree[8] = 88
218
+
219
+ tree2[7] = 77
220
+ tree2[2] = 22
221
+ tree2[1] = 11
222
+
223
+ expect(tree).not_to eq tree2
224
+ end
225
+
226
+ it 'return true if are empty trees' do
227
+ expect(tree).to eq tree2
228
+ end
229
+
230
+ it 'return false if one key is not eq' do
231
+ tree[5] = 11
232
+ tree[2] = 22
233
+ tree[7] = 77
234
+
235
+ tree2[7] = 77
236
+ tree2[2] = 22
237
+ tree2[1] = 11
238
+
239
+ expect(tree).not_to eq tree2
240
+ end
241
+
242
+ it 'return false if one value is not eq' do
243
+ tree[1] = 11
244
+ tree[2] = 22
245
+ tree[7] = 7
246
+
247
+ tree2[7] = 77
248
+ tree2[2] = 22
249
+ tree2[1] = 11
250
+
251
+ expect(tree).not_to eq tree2
252
+ end
253
+
254
+ it 'return false if any tree is empty' do
255
+ tree[1] = 11
256
+ tree[2] = 22
257
+
258
+ expect(tree).not_to eq tree2
259
+ end
260
+ end
189
261
  end
190
262
  end
@@ -45,6 +45,28 @@ RSpec.describe NativeBtree do
45
45
 
46
46
  expect(result).to eq(check)
47
47
  end
48
+
49
+ it 'return Enumerator without block' do
50
+ expect(tree.each).to be_kind_of(Enumerator)
51
+ end
52
+
53
+ it 'enumerator return correct values' do
54
+ tree[16] = 16
55
+ tree[0] = 0
56
+ tree[5] = 5
57
+ tree[-4] = -4
58
+ tree[7] = 7
59
+
60
+ check = [[-4, -4], [0, 0], [5, 5], [7, 7], [16, 16]]
61
+ result = []
62
+ enum = tree.each
63
+
64
+ loop do
65
+ result.push enum.next
66
+ end
67
+
68
+ expect(result).to eq(check)
69
+ end
48
70
  end
49
71
 
50
72
  describe "#each_key method" do
@@ -86,5 +108,43 @@ RSpec.describe NativeBtree do
86
108
  expect(result).to eq(check)
87
109
  end
88
110
  end
111
+
112
+ describe "#reverse_each method" do
113
+ it "respond to" do
114
+ expect(tree).to respond_to(:reverse_each)
115
+ end
116
+
117
+ it 'yield in to block value first' do
118
+ tree[2] = 22
119
+
120
+ value = nil
121
+ tree.reverse_each { |v| value = v }
122
+
123
+ expect(value).to be 22
124
+ end
125
+
126
+ it 'yield in to block key second' do
127
+ tree[2] = 22
128
+
129
+ key = nil
130
+ tree.reverse_each { |_v, k| key = k }
131
+
132
+ expect(key).to be 2
133
+ end
134
+
135
+ it 'yield ordered keys in reverse order' do
136
+ tree[16] = 16
137
+ tree[0] = 0
138
+ tree[5] = 5
139
+ tree[-4] = -4
140
+ tree[7] = 7
141
+
142
+ check = [16, 7, 5, 0, -4]
143
+ result = []
144
+ tree.reverse_each { |value| result << value }
145
+
146
+ expect(result).to eq(check)
147
+ end
148
+ end
89
149
  end
90
150
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: native_btree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Feodorov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-30 00:00:00.000000000 Z
11
+ date: 2022-10-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby bindings to GTree balanced binary tree from GLib library.
14
14
  email:
@@ -31,18 +31,22 @@ files:
31
31
  - ext/native_btree/extconf_cmake.rb
32
32
  - ext/native_btree/glib2_68/CMakeLists.txt
33
33
  - ext/native_btree/glib2_68/additional_iterators.c
34
+ - ext/native_btree/glib2_68/compare_trees.c
34
35
  - ext/native_btree/glib_module.c
35
36
  - ext/native_btree/include/common.h
36
37
  - ext/native_btree/include/comparator.h
38
+ - ext/native_btree/include/compare_trees.h
37
39
  - ext/native_btree/include/glib_module.h
38
40
  - ext/native_btree/include/iterators.h
39
41
  - ext/native_btree/include/native_btree.h
40
42
  - ext/native_btree/include/rbtree_type.h
43
+ - ext/native_btree/include/utils.h
41
44
  - ext/native_btree/instance.c
42
45
  - ext/native_btree/iterators.c
43
46
  - ext/native_btree/native_btree.c
44
47
  - ext/native_btree/rbtree_type.c
45
48
  - ext/native_btree/search.c
49
+ - ext/native_btree/utils.c
46
50
  - lib/native_btree.rb
47
51
  - lib/native_btree/native_btree.bundle
48
52
  - lib/native_btree/version.rb