native_btree 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 467637c8963d9da6b70984356470bddfaa7d1b6b3952091e76730852bde71bac
4
- data.tar.gz: a1842e6875ae3dbd94855a50cc38e35369a623518a502694df1d7f223ebe481b
3
+ metadata.gz: 4744529a22fe3d5cd3eb53cf258fa5440346df593e6d268d7af3d2e4b197addf
4
+ data.tar.gz: 887db38cf3c3c23cd72984f6ec2bbdfce1ebce57e547c5cc2d96c81184a36833
5
5
  SHA512:
6
- metadata.gz: c14e828145463b99a5edd19b0c830fcba54a86872380e32acee447ce302daea5a9300771f8b4ee68c90c2807e2fd9d595bb9f71ac15c7e9d2f261f95790f9767
7
- data.tar.gz: b2d449bfd707dabec594f0847312956cbf6c80543497027611c04eb81215b620dfd4efdbda8427f4628ddd8e500742fdb3d7e12f9664ba963387a1556c40bb74
6
+ metadata.gz: f46367c894c10a0ca5db645470228f08edafabe9010a5115d9c92008688eec29f9a0973ba462138483912a2bebe52660eb17828298ea69ebd1709d4811cfb470
7
+ data.tar.gz: 9a342ae22e6ced29b02aa24917f1307fc0a0721885667185266eaa1b23f73fd37c90918126dd1ac6aa24cee08a3c838c25a951e3a84ea5f23cb93e2532d9549d
data/CHANGELOG.md CHANGED
@@ -7,8 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- * delete_if()
11
- * each method refactoring for Enumerator return type
10
+ * #compact
11
+ * #compact!
12
+ * #>
13
+ * #>=
14
+ * #<
15
+ * #<=
16
+
17
+ ## [0.6.0] - 2022-10-28
18
+
19
+ ### Added
20
+
21
+ * inspect
22
+ * to_s
23
+ * delete_if
24
+ * first, min
25
+ * last, max
26
+
27
+ ### Changed
28
+
29
+ * Refactoring
30
+ * Performance improvements for #==
31
+
32
+ ## [0.5.0] - 2022-10-04
33
+
34
+ ### Added
35
+
36
+ * ==()
37
+ * each like methods without a block returns Enumerator
38
+ * reverse_each
39
+
40
+ ### Changed
41
+
42
+ * Refactoring
43
+
44
+ ## [0.4.1] - 2022-09-30
45
+
46
+ ### Changed
47
+
48
+ * Fix - Failed building on Apple M1 CPU
12
49
 
13
50
  ## [0.4.0] - 2022-09-16
14
51
 
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.6.0)
6
6
 
7
7
  include(CheckSymbolExists)
8
8
  include(CheckCCompilerFlag)
data/README.md CHANGED
@@ -99,15 +99,18 @@ Implemented methods:
99
99
 
100
100
  * `[]= (alias: set)`
101
101
  * `[] (alias: get)`
102
+ * `==`
102
103
  * `delete`
103
104
  * `size`
104
105
  * `height`
105
- * `each` (NB! block is required) (NB! block is required)
106
+ * `each`
106
107
  * `include?`
107
108
  * `clear`
108
109
  * `to_h`
109
110
  * `to_a`
110
111
  * `to_proc`
112
+ * `to_s`
113
+ * `inspect`
111
114
  * `filter` (alias: select)
112
115
  * `filter!` (alias: select!)
113
116
  * `each_value`
@@ -115,5 +118,7 @@ Implemented methods:
115
118
  * `search_before` (GLib version >= 2.68) - Select keys <= first arg, ret new Btree
116
119
  * `search_after` (GLib version >= 2.68) - Select keys >= first arg, ret new Btree
117
120
  * `empty?`
121
+ * `reverse_each`
122
+ * `delete_if`
118
123
 
119
124
  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
@@ -76,3 +76,14 @@ rbtree_to_proc(VALUE self)
76
76
  {
77
77
  return rb_proc_new(to_proc_proc, self);
78
78
  }
79
+
80
+
81
+ VALUE
82
+ rbtree_to_s(VALUE self)
83
+ {
84
+ VALUE h = rbtree_to_h(self);
85
+
86
+ VALUE str = rb_sprintf("#<NativeBtree::Btree:%"PRIsVALUE">", h);
87
+
88
+ return str;
89
+ }
@@ -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);
@@ -1,13 +1,20 @@
1
1
  #include <common.h>
2
2
 
3
+ #ifndef _NATIVE_BTREE_ITERATORS_
4
+ #define _NATIVE_BTREE_ITERATORS_
5
+
3
6
  typedef struct {
4
7
  const VALUE block;
5
8
  const RBTree *tree;
9
+ glong counter;
10
+ gushort flags;
6
11
  gconstpointer something;
7
- } RBTreeSearchData;
12
+ } RBTreeSearchContext;
8
13
 
9
14
  #ifdef HAS_GTREE_NODE
10
15
 
11
16
  typedef GTreeNode *(RBTreeStepFunction) (GTreeNode *node);
12
17
 
13
18
  #endif
19
+
20
+ #endif // _NATIVE_BTREE_ITERATORS_
@@ -83,4 +83,19 @@ 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
+
92
+ VALUE
93
+ rbtree_first(VALUE self);
94
+
95
+ VALUE
96
+ rbtree_last(VALUE self);
97
+
98
+ VALUE
99
+ rbtree_to_s(VALUE self);
100
+
86
101
  #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,11 @@
1
1
  #include <common.h>
2
2
 
3
+ #ifdef HAS_GTREE_NODE
4
+ #include <compare_trees.h>
5
+ #else
6
+ #include <utils.h>
7
+ #include <iterators.h>
8
+ #endif
3
9
 
4
10
  #ifndef HAS_GTREE_REMOVE_ALL
5
11
 
@@ -15,6 +21,96 @@ rbtree_remove_node(gpointer key, gpointer val, gpointer data) {
15
21
  #endif
16
22
 
17
23
 
24
+ #ifndef HAS_GTREE_NODE
25
+
26
+ static gint
27
+ rbtree_first_cb(gpointer a, gpointer b, gpointer data)
28
+ {
29
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
30
+
31
+ context->something = (gconstpointer) b;
32
+ context->counter = 0;
33
+
34
+ return TRUE;
35
+ }
36
+
37
+
38
+ static gint
39
+ rbtree_last_cb(gpointer a, gpointer b, gpointer data)
40
+ {
41
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
42
+
43
+ context->something = (gconstpointer) b;
44
+ context->counter += 1;
45
+
46
+ return FALSE;
47
+ }
48
+
49
+
50
+ static gint
51
+ legacy_compare_visitor(gpointer a, gpointer b, gpointer data)
52
+ {
53
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
54
+
55
+ GPtrArray *flat_tree = (GPtrArray *) context->something;
56
+ VALUE key = (VALUE) a;
57
+ VALUE val = (VALUE) b;
58
+ VALUE is_eq = Qfalse;
59
+
60
+ VALUE key2 = (VALUE) g_ptr_array_index(flat_tree, context->counter);
61
+ VALUE val2 = (VALUE) g_ptr_array_index(flat_tree, context->counter + 1);
62
+
63
+ is_eq = rb_funcall(key, rb_intern("=="), 1, key2);
64
+
65
+ if (!RTEST(is_eq)) {
66
+ context->flags = 1;
67
+ return TRUE;
68
+ }
69
+
70
+ is_eq = rb_funcall(val, rb_intern("=="), 1, val2);
71
+
72
+ if (!RTEST(is_eq)) {
73
+ context->flags = 1;
74
+ return TRUE;
75
+ }
76
+
77
+ (context->counter) += 2;
78
+
79
+ return FALSE;
80
+ }
81
+
82
+
83
+ static inline gboolean
84
+ legacy_rbtree_compare(const RBTree *a, const RBTree *b)
85
+ {
86
+ gboolean result = TRUE;
87
+
88
+ GPtrArray *second = rbtree_to_ptr_array(b);
89
+
90
+ // assumes that the size of arrays is same (checked before)
91
+
92
+ RBTreeSearchContext context = {
93
+ Qnil,
94
+ NULL,
95
+ 0,
96
+ 0,
97
+ (gconstpointer) second
98
+ };
99
+
100
+ g_tree_foreach(a->gtree, legacy_compare_visitor, &context);
101
+
102
+ if (context.flags) {
103
+ result = FALSE;
104
+ }
105
+
106
+ g_ptr_array_free(second, TRUE);
107
+
108
+ return result;
109
+ }
110
+
111
+ #endif
112
+
113
+
18
114
  VALUE
19
115
  rbtree_set(VALUE self, VALUE key, VALUE value)
20
116
  {
@@ -63,9 +159,7 @@ rbtree_delete(VALUE self, VALUE key)
63
159
  }
64
160
  else {
65
161
  if (rb_block_given_p()) {
66
- VALUE block = rb_block_proc();
67
-
68
- return rb_funcall(block, rb_intern("call"), 1, key);
162
+ return rb_yield(key);
69
163
  }
70
164
 
71
165
  return Qnil;
@@ -136,3 +230,104 @@ rbtree_is_empty(VALUE self)
136
230
 
137
231
  return size > 0 ? Qfalse : Qtrue;
138
232
  }
233
+
234
+
235
+ VALUE
236
+ rbtree_equal(VALUE self, VALUE second)
237
+ {
238
+ EXTRACT_RBTREE_SELF(rbtree);
239
+ EXTRACT_RBTREE(second, rbtree2);
240
+
241
+ gint self_size = g_tree_nnodes(rbtree->gtree);
242
+ gint second_size = g_tree_nnodes(rbtree2->gtree);
243
+
244
+ VALUE result = Qfalse;
245
+
246
+ if (self_size != second_size) {
247
+ goto ret;
248
+ }
249
+
250
+ if (self_size == 0) {
251
+ result = Qtrue;
252
+ goto ret;
253
+ }
254
+
255
+ #ifdef HAS_GTREE_NODE
256
+ if (rbtree_compare_trees(rbtree, rbtree2)) {
257
+ result = Qtrue;
258
+ }
259
+ #else
260
+ if (legacy_rbtree_compare(rbtree, rbtree2)) {
261
+ result = Qtrue;
262
+ }
263
+ #endif
264
+
265
+ ret:
266
+ return result;
267
+ }
268
+
269
+
270
+ VALUE
271
+ rbtree_first(VALUE self)
272
+ {
273
+ EXTRACT_RBTREE_SELF(rbtree);
274
+
275
+ #ifdef HAS_GTREE_NODE
276
+ GTreeNode *node = g_tree_node_first(rbtree->gtree);
277
+
278
+ if (!node) {
279
+ return Qnil;
280
+ }
281
+
282
+ return (VALUE) g_tree_node_value(node);
283
+ #else
284
+ RBTreeSearchContext context = {
285
+ Qnil,
286
+ NULL,
287
+ 1,
288
+ 0,
289
+ NULL
290
+ };
291
+
292
+ g_tree_foreach(rbtree->gtree, rbtree_first_cb, &context);
293
+
294
+ if (context.counter) {
295
+ return Qnil;
296
+ }
297
+
298
+ return (VALUE) context.something;
299
+ #endif
300
+ }
301
+
302
+
303
+ VALUE
304
+ rbtree_last(VALUE self)
305
+ {
306
+ EXTRACT_RBTREE_SELF(rbtree);
307
+
308
+ #ifdef HAS_GTREE_NODE
309
+ GTreeNode *node = g_tree_node_last(rbtree->gtree);
310
+
311
+ if (!node) {
312
+ return Qnil;
313
+ }
314
+
315
+ return (VALUE) g_tree_node_value(node);
316
+ #else
317
+ RBTreeSearchContext context = {
318
+ Qnil,
319
+ NULL,
320
+ 0,
321
+ 0,
322
+ NULL
323
+ };
324
+
325
+ g_tree_foreach(rbtree->gtree, rbtree_last_cb, &context);
326
+
327
+ if (!context.counter) {
328
+ return Qnil;
329
+ }
330
+
331
+ return (VALUE) context.something;
332
+ #endif
333
+ }
@@ -1,5 +1,9 @@
1
1
  #include <common.h>
2
+ #include <iterators.h>
2
3
 
4
+ #ifndef HAS_GTREE_NODE
5
+ #include <utils.h>
6
+ #endif
3
7
 
4
8
  static gboolean
5
9
  foraech_callbac(gpointer a, gpointer b, gpointer data)
@@ -38,14 +42,22 @@ foraech_value_callbac(gpointer a, gpointer b, gpointer data)
38
42
  }
39
43
 
40
44
 
45
+ static VALUE
46
+ rbtree_enum_length(VALUE rbtree, VALUE args, VALUE eobj)
47
+ {
48
+ return rbtree_size(rbtree);
49
+ }
50
+
51
+
41
52
  VALUE
42
53
  rbtree_each(VALUE self)
43
54
  {
44
- rb_need_block();
45
- VALUE block = rb_block_proc();
55
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
46
56
 
47
57
  EXTRACT_RBTREE_SELF(rbtree);
48
58
 
59
+ VALUE block = rb_block_proc();
60
+
49
61
  g_tree_foreach(rbtree->gtree, foraech_callbac, (gpointer) block);
50
62
 
51
63
  return self;
@@ -55,11 +67,12 @@ rbtree_each(VALUE self)
55
67
  VALUE
56
68
  rbtree_each_key(VALUE self)
57
69
  {
58
- rb_need_block();
59
- VALUE block = rb_block_proc();
70
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
60
71
 
61
72
  EXTRACT_RBTREE_SELF(rbtree);
62
73
 
74
+ VALUE block = rb_block_proc();
75
+
63
76
  g_tree_foreach(rbtree->gtree, foraech_key_callbac, (gpointer) block);
64
77
 
65
78
  return self;
@@ -69,12 +82,100 @@ rbtree_each_key(VALUE self)
69
82
  VALUE
70
83
  rbtree_each_value(VALUE self)
71
84
  {
72
- rb_need_block();
73
- VALUE block = rb_block_proc();
85
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
74
86
 
75
87
  EXTRACT_RBTREE_SELF(rbtree);
76
88
 
89
+ VALUE block = rb_block_proc();
90
+
77
91
  g_tree_foreach(rbtree->gtree, foraech_value_callbac, (gpointer) block);
78
92
 
79
93
  return self;
80
94
  }
95
+
96
+
97
+ VALUE
98
+ rbtree_reverse_each(VALUE self)
99
+ {
100
+ EXTRACT_RBTREE_SELF(rbtree);
101
+
102
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
103
+
104
+ #ifdef HAS_GTREE_NODE
105
+ GTreeNode *current = g_tree_node_last(rbtree->gtree);
106
+
107
+ VALUE key, val;
108
+ while (current) {
109
+ key = (VALUE) g_tree_node_key(current);
110
+ val = (VALUE) g_tree_node_value(current);
111
+
112
+ rb_yield_values(2, val, key);
113
+
114
+ current = g_tree_node_previous(current);
115
+ }
116
+ #else
117
+ GPtrArray *buff = rbtree_to_ptr_array(rbtree);
118
+
119
+ VALUE key, val;
120
+ for (glong i = buff->len - 1; i > 0; i--) {
121
+ val = (VALUE) g_ptr_array_index(buff, i);
122
+ key = (VALUE) g_ptr_array_index(buff, --i);
123
+
124
+ rb_yield_values(2, val, key);
125
+ }
126
+
127
+ g_ptr_array_free(buff, TRUE);
128
+ #endif
129
+
130
+ return self;
131
+ }
132
+
133
+
134
+ static gint
135
+ rbtree_delete_if_cb(gpointer k, gpointer v, gpointer data)
136
+ {
137
+ VALUE key = (VALUE) k;
138
+ VALUE value = (VALUE) v;
139
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
140
+ VALUE block = (VALUE) context->block;
141
+ GPtrArray *result = (GPtrArray *) context->something;
142
+
143
+ VALUE to_delete = rb_funcall(block, rb_intern("call"), 2, key, value);
144
+
145
+ if (RTEST(to_delete)) {
146
+ g_ptr_array_add(result, (gpointer) key);
147
+ }
148
+
149
+ return FALSE;
150
+ }
151
+
152
+
153
+ VALUE
154
+ rbtree_delete_if(VALUE self)
155
+ {
156
+ EXTRACT_RBTREE_SELF(rbtree);
157
+
158
+ GPtrArray *to_delete = g_ptr_array_new();
159
+
160
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
161
+
162
+ VALUE block = rb_block_proc();
163
+
164
+ RBTreeSearchContext context = {
165
+ block,
166
+ NULL,
167
+ 0,
168
+ 0,
169
+ to_delete
170
+ };
171
+
172
+ g_tree_foreach(rbtree->gtree, rbtree_delete_if_cb, &context);
173
+
174
+ for (guint i = 0; i < to_delete->len; i++) {
175
+ g_tree_remove(rbtree->gtree, g_ptr_array_index(to_delete, i));
176
+ }
177
+
178
+ g_ptr_array_free(to_delete, TRUE);
179
+
180
+ return self;
181
+ }
@@ -55,6 +55,15 @@ 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);
60
+ rb_define_method(native_btree_class, "first", rbtree_first, 0);
61
+ rb_define_alias(native_btree_class, "min", "first");
62
+ rb_define_method(native_btree_class, "last", rbtree_last, 0);
63
+ rb_define_alias(native_btree_class, "max", "last");
64
+ rb_define_method(native_btree_class, "delete_if", rbtree_delete_if, 0);
65
+ rb_define_method(native_btree_class, "to_s", rbtree_to_s, 0);
66
+ rb_define_alias(native_btree_class, "inspect", "to_s");
58
67
 
59
68
  #ifdef HAS_GTREE_NODE
60
69
  rb_define_method(native_btree_class, "select_before", rbtree_select_before, 1);
@@ -4,7 +4,7 @@
4
4
  static gboolean
5
5
  filter_callback(gpointer a, gpointer b, gpointer data)
6
6
  {
7
- RBTreeSearchData *context = (RBTreeSearchData *) data;
7
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
8
8
 
9
9
  VALUE compare_result = rb_funcall(
10
10
  context->block,
@@ -24,7 +24,7 @@ filter_callback(gpointer a, gpointer b, gpointer data)
24
24
  static gboolean
25
25
  filter_bang_callback(gpointer a, gpointer b, gpointer data)
26
26
  {
27
- RBTreeSearchData *context = (RBTreeSearchData *) data;
27
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
28
28
  GPtrArray *to_remove = (GPtrArray *) context->something;
29
29
 
30
30
  VALUE compare_result = rb_funcall(
@@ -55,9 +55,11 @@ rbtree_filter(VALUE self)
55
55
 
56
56
  EXTRACT_RBTREE(new_tree, new_rbtree);
57
57
 
58
- RBTreeSearchData data = {
58
+ RBTreeSearchContext data = {
59
59
  block,
60
60
  new_rbtree,
61
+ 0,
62
+ 0,
61
63
  NULL
62
64
  };
63
65
 
@@ -76,9 +78,11 @@ rbtree_filter_bang(VALUE self)
76
78
 
77
79
  GPtrArray *to_remove = g_ptr_array_new();
78
80
 
79
- RBTreeSearchData data = {
81
+ RBTreeSearchContext data = {
80
82
  block,
81
83
  NULL,
84
+ 0,
85
+ 0,
82
86
  (gconstpointer) to_remove
83
87
  };
84
88
 
@@ -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.6.0".freeze
3
3
  end
data/spec/debug.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  # rubocop:disable all
2
2
 
3
3
  require_relative "../lib/native_btree/native_btree"
4
+ require 'benchmark'
5
+
6
+ NativeBtree::Btree.include(Enumerable)
4
7
 
5
8
  tree = NativeBtree::Btree.new() {|a, b| a - b }
9
+ tree2 = NativeBtree::Btree.new() {|a, b| a - b }
6
10
 
7
11
  GC.start
8
12
 
@@ -17,8 +21,6 @@ GC.start
17
21
  block = ->(key) { "#{key} is not found" }
18
22
  puts tree.delete(77, &block)
19
23
 
20
- tree2 = tree.filter!() { true }
21
-
22
24
  puts tree.to_h
23
25
 
24
26
  pr = tree.to_proc
@@ -27,15 +29,12 @@ puts pr
27
29
 
28
30
 
29
31
  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
32
+ (1..1000000).each do |i|
33
+ tree[i] = i+2
34
+ tree2[i] = i+2
35
+ end
36
+
37
+ puts tree == tree2
39
38
 
40
39
  GC.start
41
40
 
@@ -65,6 +65,37 @@ RSpec.describe NativeBtree do
65
65
  expect(pr.call(12)).to be_nil
66
66
  end
67
67
  end
68
+
69
+ describe "#to_s" do
70
+ it 'respond to' do
71
+ expect(tree).to respond_to(:to_s)
72
+ end
73
+
74
+ it 'return correct str for empty' do
75
+ expect(tree.to_s).to eq('#<NativeBtree::Btree:{}>')
76
+ end
77
+
78
+ it 'return correct str' do
79
+ tree[10] = "20"
80
+ expect(tree.to_s).to eq('#<NativeBtree::Btree:{10=>"20"}>')
81
+ end
82
+ end
83
+
84
+ describe "#inspect" do
85
+ it 'respond to' do
86
+ expect(tree).to respond_to(:inspect)
87
+ end
88
+
89
+ it 'return correct str for empty' do
90
+ expect(tree.to_s).to eq('#<NativeBtree::Btree:{}>')
91
+ end
92
+
93
+ it 'return correct str' do
94
+ tree[10] = "20"
95
+ tree[30] = "40"
96
+ expect(tree.to_s).to eq('#<NativeBtree::Btree:{10=>"20", 30=>"40"}>')
97
+ end
98
+ end
68
99
  end
69
100
  end
70
101
  end
@@ -186,5 +186,134 @@ 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
261
+
262
+ describe '#last method' do
263
+ it 'respond to' do
264
+ expect(tree).to respond_to(:last)
265
+ end
266
+
267
+ it 'return correct value' do
268
+ tree[1] = 10
269
+ tree[10] = 20
270
+ tree[20] = 30
271
+
272
+ expect(tree.last).to eq(30)
273
+ end
274
+
275
+ it 'return nil if empty' do
276
+ expect(tree.last).to be_nil
277
+ end
278
+ end
279
+
280
+ describe '#first method' do
281
+ it 'respond to' do
282
+ expect(tree).to respond_to(:first)
283
+ end
284
+
285
+ it 'return correct value' do
286
+ tree[1] = 10
287
+ tree[10] = 20
288
+ tree[20] = 30
289
+
290
+ expect(tree.first).to eq(10)
291
+ end
292
+
293
+ it 'return nil if empty' do
294
+ expect(tree.first).to be_nil
295
+ end
296
+ end
297
+
298
+ describe '#delete_if method' do
299
+ it 'respond to' do
300
+ expect(tree).to respond_to(:delete_if)
301
+ end
302
+
303
+ it 'return self' do
304
+ expect(tree.delete_if { |_, _| false }).to be tree
305
+ end
306
+
307
+ it 'return expected result' do
308
+ tree[1] = 10
309
+ tree[10] = 20
310
+ tree[20] = 30
311
+
312
+ tree.delete_if { |_, v| v < 30 }
313
+
314
+ expect(tree.to_a).to eq([[20, 30]])
315
+ end
316
+ end
317
+
189
318
  end
190
319
  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.6.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-27 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