native_btree 0.5.0 → 0.6.1

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: '08e62bb88bd973ac257570f1b769323dea7ccedf9c0c2d80f5e99ba7eb2f33ff'
4
- data.tar.gz: d8d2cfac5c388216c45b1c17e225a2982871dd94c871414623f73222cd8e6f81
3
+ metadata.gz: 48b0e894826a65be636d9e13813c6d084c69a306d0778caf3fc709511dc5d2f5
4
+ data.tar.gz: 18f2f200813df0762181ebb4e7d3cc32c1cd8ae337ab9a35547d9265fa91eaeb
5
5
  SHA512:
6
- metadata.gz: 5ef4b7687b447e1b36c32e0252bb71f90005e0cfa729a1ddfd6f62f0b4e6b0c11ef29e3703563459de551fa3ae0577c537cd8d09f1a04fa34745d2abf53ab541
7
- data.tar.gz: 99d89673be28500e83030d0d300f758ff0857d0be0d9026dd39d72fe7b35ac58bdc44ba5fd567145ace04676ada29dd6a4afe895e47c99b23de530f53cf72951
6
+ metadata.gz: 4c574719cc0366f86f8459e5e17c59739dab7886ae2cfe56450ed8696906fe4c13be6e90265756a195d04548a627018540c8d119e143d19e0b5cab378c166448
7
+ data.tar.gz: 8239197687c68a713da92c7d108b41acfe83c30dcbee888e7363e0842b2f6bdc7af30e584e96a5438c08bb5bd306399f986cb31d0dad86d2cf17c9ee65820638
data/CHANGELOG.md CHANGED
@@ -7,10 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- * delete_if()
10
+ * #compact
11
+ * #compact!
12
+ * #>
13
+ * #>=
14
+ * #<
15
+ * #<=
16
+
17
+ ## [0.6.1] - 2023-05-05
18
+
19
+ ### Added
20
+
21
+ * api docs
22
+
23
+ ## [0.6.0] - 2022-10-28
24
+
25
+ ### Added
26
+
27
+ * inspect
28
+ * to_s
29
+ * delete_if
11
30
  * first, min
12
31
  * last, max
13
32
 
33
+ ### Changed
34
+
35
+ * Refactoring
36
+ * Performance improvements for #==
37
+
14
38
  ## [0.5.0] - 2022-10-04
15
39
 
16
40
  ### Added
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.5.0)
5
+ VERSION 0.6.1)
6
6
 
7
7
  include(CheckSymbolExists)
8
8
  include(CheckCCompilerFlag)
@@ -22,7 +22,7 @@ if(HAVE_CC_MARCH_NATIVE)
22
22
  string(APPEND CMAKE_C_FLAGS " -march=native")
23
23
  endif()
24
24
 
25
- set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb3 -Wall -Wextra -Wno-unused-parameter")
25
+ set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb3 -Wall -Wextra -Wno-unused-parameter --coverage")
26
26
  set(CMAKE_C_FLAGS_RELEASE "-O3 -fomit-frame-pointer")
27
27
 
28
28
  # Force -fPIC
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # GLib Balanced binary tree (GTree) bindings for Ruby
2
2
 
3
3
  [![Ruby](https://github.com/unixs/ruby-native-btree/actions/workflows/main.yml/badge.svg)](https://github.com/unixs/ruby-native-btree/actions/workflows/main.yml)
4
+ [![codecov](https://codecov.io/gh/unixs/ruby-native-btree/branch/master/graph/badge.svg?token=10JIVX89NG)](https://codecov.io/gh/unixs/ruby-native-btree)
4
5
  [![Gem Version](https://badge.fury.io/rb/native_btree.svg)](https://badge.fury.io/rb/native_btree)
5
6
  [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
6
7
 
@@ -87,35 +88,11 @@ tree.to_a
87
88
  #]
88
89
  ```
89
90
 
90
- ## API ref
91
+ ## API
91
92
 
92
- You must provide your own comparator for keys in `new` class method block.
93
+ * You must provide your own comparator for keys in `new` class method block.
94
+ * You can mix in the `Enumerable` module if additional methods are needed.
93
95
 
94
96
  ### API methods
95
97
 
96
- In general this class behave same as Hash
97
-
98
- Implemented methods:
99
-
100
- * `[]= (alias: set)`
101
- * `[] (alias: get)`
102
- * `==`
103
- * `delete`
104
- * `size`
105
- * `height`
106
- * `each` (NB! block is required) (NB! block is required)
107
- * `include?`
108
- * `clear`
109
- * `to_h`
110
- * `to_a`
111
- * `to_proc`
112
- * `filter` (alias: select)
113
- * `filter!` (alias: select!)
114
- * `each_value`
115
- * `each_key`
116
- * `search_before` (GLib version >= 2.68) - Select keys <= first arg, ret new Btree
117
- * `search_after` (GLib version >= 2.68) - Select keys >= first arg, ret new Btree
118
- * `empty?`
119
- * `reverse_each`
120
-
121
- You can mix in the `Enumerable` module if additional methods are needed.
98
+ [YARD documentation](https://rubydoc.info/gems/native_btree)
data/Rakefile CHANGED
@@ -37,7 +37,7 @@ namespace :cmake do
37
37
  sh "cmake --build #{BUILD_DIR}"
38
38
  end
39
39
 
40
- desc "`Rebuild ext CMake project"
40
+ desc "Rebuild ext CMake project"
41
41
  task rebuild: %i[cmake:configure] do
42
42
  sh "cmake --build #{BUILD_DIR} --clean-first"
43
43
  end
@@ -27,6 +27,14 @@ init_rbtree(RBTree *rbtree, gushort flags)
27
27
  rbtree->flags = flags;
28
28
  }
29
29
 
30
+ /**
31
+ * Constructor
32
+ *
33
+ * Accepts block as "comparator" function.
34
+ * This function will recive two keys for comparison.
35
+ *
36
+ * @return [Btree] new instance
37
+ */
30
38
  VALUE
31
39
  rbtree_initialize(int argc, VALUE* argv, VALUE self)
32
40
  {
@@ -26,7 +26,11 @@ rbtree_to_a_callback(gpointer key, gpointer value, gpointer data)
26
26
  return FALSE;
27
27
  }
28
28
 
29
-
29
+ /**
30
+ * Converts tree to Hash
31
+ *
32
+ * @return [Hash] result
33
+ */
30
34
  VALUE
31
35
  rbtree_to_h(VALUE self)
32
36
  {
@@ -39,7 +43,13 @@ rbtree_to_h(VALUE self)
39
43
  return hash;
40
44
  }
41
45
 
42
-
46
+ /**
47
+ * Converts tree to array
48
+ *
49
+ * Coverts tree to array of arrays with key and value
50
+ *
51
+ * @return [Array] result
52
+ */
43
53
  VALUE
44
54
  rbtree_to_a(VALUE self)
45
55
  {
@@ -70,9 +80,30 @@ to_proc_proc(RB_BLOCK_CALL_FUNC_ARGLIST(key, callback_arg))
70
80
  return value;
71
81
  }
72
82
 
73
-
83
+ /**
84
+ * Returns a Proc object that maps a key to its value
85
+ *
86
+ * @return [Proc] block
87
+ */
74
88
  VALUE
75
89
  rbtree_to_proc(VALUE self)
76
90
  {
77
91
  return rb_proc_new(to_proc_proc, self);
78
92
  }
93
+
94
+ /**
95
+ * Converts tree to string.
96
+ *
97
+ * Under hood will convert tree to Hash.
98
+ *
99
+ * @return [String] result
100
+ */
101
+ VALUE
102
+ rbtree_to_s(VALUE self)
103
+ {
104
+ VALUE h = rbtree_to_h(self);
105
+
106
+ VALUE str = rb_sprintf("#<NativeBtree::Btree:%"PRIsVALUE">", h);
107
+
108
+ return str;
109
+ }
@@ -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_
@@ -89,4 +89,13 @@ rbtree_equal(VALUE self, VALUE btree);
89
89
  VALUE
90
90
  rbtree_reverse_each(VALUE self);
91
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
+
92
101
  #endif // _NATIVE_BTREE_
@@ -4,6 +4,7 @@
4
4
  #include <compare_trees.h>
5
5
  #else
6
6
  #include <utils.h>
7
+ #include <iterators.h>
7
8
  #endif
8
9
 
9
10
  #ifndef HAS_GTREE_REMOVE_ALL
@@ -20,6 +21,104 @@ rbtree_remove_node(gpointer key, gpointer val, gpointer data) {
20
21
  #endif
21
22
 
22
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
+ /**
114
+ * Adds key/value pair in to tree.
115
+ *
116
+ * Key/value will be replaced if key already exists.
117
+ *
118
+ * @param key [Object]
119
+ * @param value [Object]
120
+ * @return [Btree] self
121
+ */
23
122
  VALUE
24
123
  rbtree_set(VALUE self, VALUE key, VALUE value)
25
124
  {
@@ -30,7 +129,14 @@ rbtree_set(VALUE self, VALUE key, VALUE value)
30
129
  return self;
31
130
  }
32
131
 
33
-
132
+ /**
133
+ * Gets value by key from tree.
134
+ *
135
+ * * Returns +nil+ if key does not exist.
136
+ *
137
+ * @param key [Object]
138
+ * @return [Object] result
139
+ */
34
140
  VALUE
35
141
  rbtree_get(VALUE self, VALUE key)
36
142
  {
@@ -47,7 +153,16 @@ rbtree_get(VALUE self, VALUE key)
47
153
  return result;
48
154
  }
49
155
 
50
-
156
+ /**
157
+ * Deletes key/value pair from tree.
158
+ *
159
+ * * Returns value if key exists
160
+ * * Returns +nil+ if key does not exists
161
+ * * Returns result of block if block was given
162
+ *
163
+ * @param key [Object] Key
164
+ * @return [Object] result
165
+ */
51
166
  VALUE
52
167
  rbtree_delete(VALUE self, VALUE key)
53
168
  {
@@ -75,7 +190,11 @@ rbtree_delete(VALUE self, VALUE key)
75
190
  }
76
191
  }
77
192
 
78
-
193
+ /**
194
+ * Returns tree height
195
+ *
196
+ * @return [Integer] maximum nodes in path from root to leaf
197
+ */
79
198
  VALUE
80
199
  rbtree_height(VALUE self)
81
200
  {
@@ -87,7 +206,11 @@ rbtree_height(VALUE self)
87
206
  return result;
88
207
  }
89
208
 
90
-
209
+ /**
210
+ * Returns number of nodes
211
+ *
212
+ * @return [Integer] number of nodes
213
+ */
91
214
  VALUE
92
215
  rbtree_size(VALUE self)
93
216
  {
@@ -99,7 +222,11 @@ rbtree_size(VALUE self)
99
222
  return result;
100
223
  }
101
224
 
102
-
225
+ /**
226
+ * Remove all nodes from tree.
227
+ *
228
+ * @return [Btree] self
229
+ */
103
230
  VALUE
104
231
  rbtree_clear(VALUE self)
105
232
  {
@@ -115,6 +242,12 @@ rbtree_clear(VALUE self)
115
242
  }
116
243
 
117
244
 
245
+ /**
246
+ * Checks that the given key is in the tree.
247
+ *
248
+ * @param key [Object]
249
+ * @return [Boolean] result
250
+ */
118
251
  VALUE
119
252
  rbtree_is_include(VALUE self, VALUE key)
120
253
  {
@@ -129,7 +262,11 @@ rbtree_is_include(VALUE self, VALUE key)
129
262
  return Qtrue;
130
263
  }
131
264
 
132
-
265
+ /**
266
+ * Checks that self tree is empty.
267
+ *
268
+ * @return [Boolean] result
269
+ */
133
270
  VALUE
134
271
  rbtree_is_empty(VALUE self)
135
272
  {
@@ -140,54 +277,18 @@ rbtree_is_empty(VALUE self)
140
277
  return size > 0 ? Qfalse : Qtrue;
141
278
  }
142
279
 
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
-
280
+ /**
281
+ * Checks if two trees are equal.
282
+ *
283
+ * Compares with +==+ method all keys and values from trees by order.
284
+ *
285
+ * * Returns +false+ if number of keys are not equal.
286
+ * * Returns +false+ if one keys or one values pair are not equal.
287
+ * * Returns +true+ if all keys and values are equal.
288
+ *
289
+ * @param second [Btree]
290
+ * @return [Boolean] result
291
+ */
191
292
  VALUE
192
293
  rbtree_equal(VALUE self, VALUE second)
193
294
  {
@@ -221,3 +322,77 @@ rbtree_equal(VALUE self, VALUE second)
221
322
  ret:
222
323
  return result;
223
324
  }
325
+
326
+ /**
327
+ * Returns value from smallest key
328
+ *
329
+ * @return [Object] result
330
+ */
331
+ VALUE
332
+ rbtree_first(VALUE self)
333
+ {
334
+ EXTRACT_RBTREE_SELF(rbtree);
335
+
336
+ #ifdef HAS_GTREE_NODE
337
+ GTreeNode *node = g_tree_node_first(rbtree->gtree);
338
+
339
+ if (!node) {
340
+ return Qnil;
341
+ }
342
+
343
+ return (VALUE) g_tree_node_value(node);
344
+ #else
345
+ RBTreeSearchContext context = {
346
+ Qnil,
347
+ NULL,
348
+ 1,
349
+ 0,
350
+ NULL
351
+ };
352
+
353
+ g_tree_foreach(rbtree->gtree, rbtree_first_cb, &context);
354
+
355
+ if (context.counter) {
356
+ return Qnil;
357
+ }
358
+
359
+ return (VALUE) context.something;
360
+ #endif
361
+ }
362
+
363
+ /**
364
+ * Returns value from largest key
365
+ *
366
+ * @return [Object] result
367
+ */
368
+ VALUE
369
+ rbtree_last(VALUE self)
370
+ {
371
+ EXTRACT_RBTREE_SELF(rbtree);
372
+
373
+ #ifdef HAS_GTREE_NODE
374
+ GTreeNode *node = g_tree_node_last(rbtree->gtree);
375
+
376
+ if (!node) {
377
+ return Qnil;
378
+ }
379
+
380
+ return (VALUE) g_tree_node_value(node);
381
+ #else
382
+ RBTreeSearchContext context = {
383
+ Qnil,
384
+ NULL,
385
+ 0,
386
+ 0,
387
+ NULL
388
+ };
389
+
390
+ g_tree_foreach(rbtree->gtree, rbtree_last_cb, &context);
391
+
392
+ if (!context.counter) {
393
+ return Qnil;
394
+ }
395
+
396
+ return (VALUE) context.something;
397
+ #endif
398
+ }
@@ -1,4 +1,5 @@
1
1
  #include <common.h>
2
+ #include <iterators.h>
2
3
 
3
4
  #ifndef HAS_GTREE_NODE
4
5
  #include <utils.h>
@@ -47,7 +48,11 @@ rbtree_enum_length(VALUE rbtree, VALUE args, VALUE eobj)
47
48
  return rbtree_size(rbtree);
48
49
  }
49
50
 
50
-
51
+ /**
52
+ * Execute block for each key/value pairs
53
+ *
54
+ * @return [Btree] self
55
+ */
51
56
  VALUE
52
57
  rbtree_each(VALUE self)
53
58
  {
@@ -62,7 +67,11 @@ rbtree_each(VALUE self)
62
67
  return self;
63
68
  }
64
69
 
65
-
70
+ /**
71
+ * Execute block for each key
72
+ *
73
+ * @return [Btree] self
74
+ */
66
75
  VALUE
67
76
  rbtree_each_key(VALUE self)
68
77
  {
@@ -77,7 +86,11 @@ rbtree_each_key(VALUE self)
77
86
  return self;
78
87
  }
79
88
 
80
-
89
+ /**
90
+ * Execute block for each value
91
+ *
92
+ * @return [Btree] self
93
+ */
81
94
  VALUE
82
95
  rbtree_each_value(VALUE self)
83
96
  {
@@ -92,7 +105,11 @@ rbtree_each_value(VALUE self)
92
105
  return self;
93
106
  }
94
107
 
95
-
108
+ /**
109
+ * Execute block for each key/value pairs in reverse order
110
+ *
111
+ * @return [Btree] self
112
+ */
96
113
  VALUE
97
114
  rbtree_reverse_each(VALUE self)
98
115
  {
@@ -128,3 +145,60 @@ rbtree_reverse_each(VALUE self)
128
145
 
129
146
  return self;
130
147
  }
148
+
149
+
150
+ static gint
151
+ rbtree_delete_if_cb(gpointer k, gpointer v, gpointer data)
152
+ {
153
+ VALUE key = (VALUE) k;
154
+ VALUE value = (VALUE) v;
155
+ RBTreeSearchContext *context = (RBTreeSearchContext *) data;
156
+ VALUE block = (VALUE) context->block;
157
+ GPtrArray *result = (GPtrArray *) context->something;
158
+
159
+ VALUE to_delete = rb_funcall(block, rb_intern("call"), 2, key, value);
160
+
161
+ if (RTEST(to_delete)) {
162
+ g_ptr_array_add(result, (gpointer) key);
163
+ }
164
+
165
+ return FALSE;
166
+ }
167
+
168
+ /**
169
+ * Deletes key/value pair from tree by result of block.
170
+ *
171
+ * Will execute block for each key/value pairs
172
+ * and delete them if block returns +true+
173
+ *
174
+ * @return [Btree] self
175
+ */
176
+ VALUE
177
+ rbtree_delete_if(VALUE self)
178
+ {
179
+ EXTRACT_RBTREE_SELF(rbtree);
180
+
181
+ GPtrArray *to_delete = g_ptr_array_new();
182
+
183
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, rbtree_enum_length);
184
+
185
+ VALUE block = rb_block_proc();
186
+
187
+ RBTreeSearchContext context = {
188
+ block,
189
+ NULL,
190
+ 0,
191
+ 0,
192
+ to_delete
193
+ };
194
+
195
+ g_tree_foreach(rbtree->gtree, rbtree_delete_if_cb, &context);
196
+
197
+ for (guint i = 0; i < to_delete->len; i++) {
198
+ g_tree_remove(rbtree->gtree, g_ptr_array_index(to_delete, i));
199
+ }
200
+
201
+ g_ptr_array_free(to_delete, TRUE);
202
+
203
+ return self;
204
+ }
@@ -2,29 +2,25 @@
2
2
  #include <rbtree_type.h>
3
3
  #include <glib_module.h>
4
4
 
5
- #define NATIVE_BTREE_MODULE "NativeBtree"
6
- #define NATIVE_BTREE_CLASS "Btree"
7
- #define NATIVE_BTREE_CONST_INT_COMPARATOR "INT_COMPARATOR"
8
-
9
-
10
5
  VALUE native_btree_class;
11
6
  VALUE native_btree_module;
12
7
 
13
8
  void
14
9
  Init_native_btree()
15
10
  {
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
- );
11
+ native_btree_module = rb_define_module("NativeBtree");
12
+ native_btree_class = rb_define_class_under(native_btree_module, "Btree", rb_cObject);
22
13
 
23
14
  VALUE int_comparator = USHORT2NUM(RBTREE_FLAG_INT_COMPARATOR);
24
15
  OBJ_FREEZE(int_comparator);
16
+
17
+ /**
18
+ * Represents native comparator for integer keys
19
+ * @note Can be replaced with specific class in future releases
20
+ */
25
21
  rb_define_const(
26
22
  native_btree_class,
27
- NATIVE_BTREE_CONST_INT_COMPARATOR,
23
+ "INT_COMPARATOR",
28
24
  int_comparator
29
25
  );
30
26
 
@@ -57,6 +53,13 @@ Init_native_btree()
57
53
  rb_define_method(native_btree_class, "empty?", rbtree_is_empty, 0);
58
54
  rb_define_method(native_btree_class, "==", rbtree_equal, 1);
59
55
  rb_define_method(native_btree_class, "reverse_each", rbtree_reverse_each, 0);
56
+ rb_define_method(native_btree_class, "first", rbtree_first, 0);
57
+ rb_define_alias(native_btree_class, "min", "first");
58
+ rb_define_method(native_btree_class, "last", rbtree_last, 0);
59
+ rb_define_alias(native_btree_class, "max", "last");
60
+ rb_define_method(native_btree_class, "delete_if", rbtree_delete_if, 0);
61
+ rb_define_method(native_btree_class, "to_s", rbtree_to_s, 0);
62
+ rb_define_alias(native_btree_class, "inspect", "to_s");
60
63
 
61
64
  #ifdef HAS_GTREE_NODE
62
65
  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(
@@ -43,6 +43,13 @@ filter_bang_callback(gpointer a, gpointer b, gpointer data)
43
43
  return FALSE;
44
44
  }
45
45
 
46
+ /**
47
+ * Filters btree by block call
48
+ *
49
+ * If block returns true, key/value will include in result tree
50
+ *
51
+ * @return [Btree] result
52
+ */
46
53
  VALUE
47
54
  rbtree_filter(VALUE self)
48
55
  {
@@ -55,9 +62,11 @@ rbtree_filter(VALUE self)
55
62
 
56
63
  EXTRACT_RBTREE(new_tree, new_rbtree);
57
64
 
58
- RBTreeSearchData data = {
65
+ RBTreeSearchContext data = {
59
66
  block,
60
67
  new_rbtree,
68
+ 0,
69
+ 0,
61
70
  NULL
62
71
  };
63
72
 
@@ -66,6 +75,13 @@ rbtree_filter(VALUE self)
66
75
  return new_tree;
67
76
  }
68
77
 
78
+ /**
79
+ * Filters btree by block call
80
+ *
81
+ * Same as #filter but returns changed self.
82
+ *
83
+ * @return [Btree] result
84
+ */
69
85
  VALUE
70
86
  rbtree_filter_bang(VALUE self)
71
87
  {
@@ -76,9 +92,11 @@ rbtree_filter_bang(VALUE self)
76
92
 
77
93
  GPtrArray *to_remove = g_ptr_array_new();
78
94
 
79
- RBTreeSearchData data = {
95
+ RBTreeSearchContext data = {
80
96
  block,
81
97
  NULL,
98
+ 0,
99
+ 0,
82
100
  (gconstpointer) to_remove
83
101
  };
84
102
 
@@ -0,0 +1,6 @@
1
+ module NativeBtree
2
+ # Main Btree class
3
+ class Btree # rubocop:disable Lint/EmptyClass
4
+ # all methods defined in native module
5
+ end
6
+ end
Binary file
@@ -1,3 +1,4 @@
1
1
  module NativeBtree
2
- VERSION = "0.5.0".freeze
2
+ # gem version
3
+ VERSION = "0.6.1".freeze
3
4
  end
data/lib/native_btree.rb CHANGED
@@ -1,4 +1,6 @@
1
- # Bindings to GLib-2.0 data structure BTree
1
+ # Bindings to GLib-2.0 BTree data structure
2
+ #
3
+ # gem root namespace
2
4
  module NativeBtree
3
5
  end
4
6
 
data/spec/debug.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # rubocop:disable all
2
2
 
3
3
  require_relative "../lib/native_btree/native_btree"
4
+ require 'benchmark'
4
5
 
5
6
  NativeBtree::Btree.include(Enumerable)
6
7
 
@@ -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
@@ -258,5 +258,62 @@ RSpec.describe NativeBtree do
258
258
  expect(tree).not_to eq tree2
259
259
  end
260
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
+
261
318
  end
262
319
  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.5.0
4
+ version: 0.6.1
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-10-03 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby bindings to GTree balanced binary tree from GLib library.
14
14
  email:
@@ -48,6 +48,7 @@ files:
48
48
  - ext/native_btree/search.c
49
49
  - ext/native_btree/utils.c
50
50
  - lib/native_btree.rb
51
+ - lib/native_btree/btree.rb
51
52
  - lib/native_btree/native_btree.bundle
52
53
  - lib/native_btree/version.rb
53
54
  - native_btree.gemspec