native_btree 0.4.1 → 0.6.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: 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