native_btree 0.5.0 → 0.6.1

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: '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