native_btree 0.2.1 → 0.3.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: 398bae312c489bfe71fdee2f82499005e655097606a5537c38cfb122980b9f48
4
- data.tar.gz: 492df9b7fc0585e0615da770a6c3fd3e2d02323d33c1d3cfecae46b882b881a3
3
+ metadata.gz: 1dbf5cc77f1056fc6f84cf49496c233b9a3ecd9c62a0d82149cce9804a80edd7
4
+ data.tar.gz: eb1f55db08e767f443b02751258fb749ae991eb98e5426a8d5c81714c66ebd49
5
5
  SHA512:
6
- metadata.gz: 634ac5f2eab6a8f9ebf9ed577d5cd2fcdca75fdb8e61f285b3e83e244204976bdef93981320ea101a621b2845cb9346099d61a94193eb5872d0f1480ad363f09
7
- data.tar.gz: cf5f853401bdcab2d12088fe11c23cbde946e5a3542620d905e1acb59ede62522cbd293f65c7b10ca54f4a00737c9fe5485519c72358f185840fa8efbe81719b
6
+ metadata.gz: 7753f72aa3babc2151d74ae4bad29fb7c43e41cd7cf8b3bc9348e4b6e9be3c156d2ecc78fd2e689ca099e27df8bdee376550cbbc16b97ef15f15c431e8c5c093
7
+ data.tar.gz: d1992054500ad7207aea7186a0aa9bd3099cf013983c2596f5c2b5289ca5c8129f4ceeea4bf9ddf0777eb019b4dfc70be3b0feb571d741bb148af1f68de6e754
data/CHANGELOG.md CHANGED
@@ -7,12 +7,19 @@ 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
12
+
13
+ ## [0.3.0] - 2022-09-11
14
+
15
+ ### Added
16
+
17
+ * to_proc()
18
+ * empty?()
10
19
  * filter()
11
20
  * filter!()
12
- * each_key()
13
- * each_value()
14
21
  * select()
15
- * select!
22
+ * select!()
16
23
 
17
24
  ## [0.2.1] - 2022-09-08
18
25
 
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.2.1)
5
+ VERSION 0.3.0)
6
6
 
7
7
  include(CheckSymbolExists)
8
8
 
data/Gemfile CHANGED
@@ -9,10 +9,13 @@ group :development do
9
9
  gem 'awesome_print', '~> 1.9'
10
10
  gem 'debase', '~> 0.2', platforms: [:mri_26, :mri_27]
11
11
  gem 'pry', '~> 0.14'
12
+ gem 'ruby-debug-ide', '~> 0.7'
13
+ gem 'solargraph', '~> 0.46'
14
+ end
15
+
16
+ group :test do
17
+ gem 'rspec', '~> 3.11.0'
12
18
  gem 'rubocop', '~> 1.35.0'
13
19
  gem 'rubocop-rake', '~> 0.6.0'
14
20
  gem 'rubocop-rspec', '~> 2.12.1'
15
- gem 'rspec', '~> 3.11.0'
16
- gem 'ruby-debug-ide', '~> 0.7'
17
- gem 'solargraph', '~> 0.46'
18
21
  end
data/README.md CHANGED
@@ -57,15 +57,24 @@ tree.height
57
57
 
58
58
  You must provide your own comparator for keys in `new` class method block.
59
59
 
60
- ### Methods
60
+ ### API methods
61
+
62
+ In general this class behave same as Hash
63
+
64
+ Implemented methods:
61
65
 
62
66
  * `[]= (alias: set)`
63
67
  * `[] (alias: get)`
64
68
  * `delete`
65
69
  * `size`
66
70
  * `height`
67
- * `each`
71
+ * `each` (NB! block is required)
68
72
  * `include?`
69
73
  * `clear`
70
74
  * `to_h`
71
75
  * `to_a`
76
+ * `to_proc`
77
+ * `filter` (alias: select)
78
+ * `filter!` (alias: select!)
79
+
80
+ You can mix in the `Enumerable` module if additional methods are needed.
@@ -26,6 +26,7 @@ add_library(instance OBJECT instance.c)
26
26
  add_library(comparator OBJECT comparator.c)
27
27
  add_library(iterators OBJECT iterators.c)
28
28
  add_library(conversion OBJECT conversion.c)
29
+ add_library(search OBJECT search.c)
29
30
 
30
31
  add_library(native_btree_interface
31
32
  STATIC
@@ -34,7 +35,8 @@ add_library(native_btree_interface
34
35
  $<TARGET_OBJECTS:comparator>
35
36
  $<TARGET_OBJECTS:instance>
36
37
  $<TARGET_OBJECTS:constructor>
37
- $<TARGET_OBJECTS:rbtree_type>)
38
+ $<TARGET_OBJECTS:rbtree_type>
39
+ $<TARGET_OBJECTS:search>)
38
40
 
39
41
  target_link_libraries(${EXT_NAME}
40
42
  PRIVATE
@@ -1,4 +1,3 @@
1
- #include <constructor.h>
2
1
  #include <comparator.h>
3
2
  #include <rbtree_type.h>
4
3
 
@@ -1,4 +1,5 @@
1
- #include <conversion.h>
1
+ #include <common.h>
2
+
2
3
 
3
4
  static gboolean
4
5
  rbtree_to_h_callback(gpointer key, gpointer value, gpointer data)
@@ -52,3 +53,26 @@ rbtree_to_a(VALUE self)
52
53
 
53
54
  return array;
54
55
  }
56
+
57
+
58
+ static VALUE
59
+ to_proc_proc(RB_BLOCK_CALL_FUNC_ARGLIST(key, callback_arg))
60
+ {
61
+ rb_check_arity(argc, 1, 1);
62
+ EXTRACT_RBTREE(callback_arg, rbtree);
63
+
64
+ VALUE value = (VALUE) g_tree_lookup(rbtree->gtree, (gconstpointer) key);
65
+
66
+ if (!value) {
67
+ return Qnil;
68
+ }
69
+
70
+ return value;
71
+ }
72
+
73
+
74
+ VALUE
75
+ rbtree_to_proc(VALUE self)
76
+ {
77
+ return rb_proc_new(to_proc_proc, self);
78
+ }
@@ -1,21 +1,19 @@
1
1
  #include <ruby.h>
2
2
  #include <glib.h>
3
+ #include <rbtree_type.h>
4
+ #include <native_btree.h>
5
+
3
6
 
4
7
  #ifndef _NATIVE_BTREE_COMMON_
5
8
  #define _NATIVE_BTREE_COMMON_
6
9
 
7
- #include <rbtree_type.h>
8
-
9
- #define NATIVE_BTREE_MODULE "NativeBtree"
10
- #define NATIVE_BTREE_CLASS "Btree"
11
-
12
10
  #define EXTRACT_RBTREE(from, to) \
13
11
  RBTree *to; \
14
- TypedData_Get_Struct(from, RBTree, &rbtree_type, rbtree)
12
+ TypedData_Get_Struct(from, RBTree, &rbtree_type, to)
15
13
 
16
14
  #define EXTRACT_RBTREE_SELF(to) EXTRACT_RBTREE(self, to)
17
15
 
18
- extern VALUE rbtree_class;
19
- extern VALUE rbtree_module;
16
+ extern VALUE native_btree_class;
17
+ extern VALUE native_btree_module;
20
18
 
21
19
  #endif //_NATIVE_BTREE_COMMON_
@@ -1,5 +1,7 @@
1
1
  #include <common.h>
2
2
 
3
-
4
- VALUE
5
- rbtree_each(VALUE self);
3
+ typedef struct {
4
+ VALUE block;
5
+ RBTree *tree;
6
+ gconstpointer something;
7
+ } RBTreeSearchData;
@@ -1,9 +1,50 @@
1
1
  #ifndef _NATIVE_BTREE_
2
2
 
3
- #include <common.h>
4
- #include <constructor.h>
5
- #include <instance.h>
6
- #include <iterators.h>
7
- #include <conversion.h>
3
+ #include <ruby.h>
4
+
5
+ VALUE
6
+ rbtree_initialize(VALUE self);
7
+
8
+ VALUE
9
+ rbtree_set(VALUE self, VALUE key, VALUE value);
10
+
11
+ VALUE
12
+ rbtree_get(VALUE self, VALUE key);
13
+
14
+ VALUE
15
+ rbtree_delete(VALUE self, VALUE key);
16
+
17
+ VALUE
18
+ rbtree_size(VALUE self);
19
+
20
+ VALUE
21
+ rbtree_height(VALUE self);
22
+
23
+ VALUE
24
+ rbtree_clear(VALUE self);
25
+
26
+ VALUE
27
+ rbtree_is_include(VALUE self, VALUE key);
28
+
29
+ VALUE
30
+ rbtree_each(VALUE self);
31
+
32
+ VALUE
33
+ rbtree_to_h(VALUE self);
34
+
35
+ VALUE
36
+ rbtree_to_a(VALUE self);
37
+
38
+ VALUE
39
+ rbtree_to_proc(VALUE self);
40
+
41
+ VALUE
42
+ rbtree_filter(VALUE self);
43
+
44
+ VALUE
45
+ rbtree_filter_bang(VALUE self);
46
+
47
+ VALUE
48
+ rbtree_is_empty(VALUE self);
8
49
 
9
50
  #endif // _NATIVE_BTREE_
@@ -3,7 +3,7 @@
3
3
 
4
4
  #include <common.h>
5
5
 
6
- #define NATIVE_TYPE_NAME "native_btree"
6
+ #define RBTREE_NATIVE_TYPE_NAME "native_btree"
7
7
 
8
8
  extern const rb_data_type_t rbtree_type;
9
9
 
@@ -1,4 +1,5 @@
1
- #include <instance.h>
1
+ #include <common.h>
2
+
2
3
 
3
4
  #ifndef HAVE_GTREE_REMOVE_ALL
4
5
 
@@ -124,3 +125,14 @@ rbtree_is_include(VALUE self, VALUE key)
124
125
 
125
126
  return Qtrue;
126
127
  }
128
+
129
+
130
+ VALUE
131
+ rbtree_is_empty(VALUE self)
132
+ {
133
+ EXTRACT_RBTREE_SELF(rbtree);
134
+
135
+ gint size = g_tree_nnodes(rbtree->gtree);
136
+
137
+ return size > 0 ? Qfalse : Qtrue;
138
+ }
@@ -1,4 +1,4 @@
1
- #include <iterators.h>
1
+ #include <common.h>
2
2
 
3
3
  static gboolean
4
4
  foraech_callbac(gpointer a, gpointer b, gpointer data)
@@ -1,28 +1,45 @@
1
1
  #include <native_btree.h>
2
+ #include <rbtree_type.h>
2
3
 
3
- VALUE rbtree_class;
4
- VALUE rbtree_module;
4
+ #define NATIVE_BTREE_MODULE "NativeBtree"
5
+ #define NATIVE_BTREE_CLASS "Btree"
6
+
7
+
8
+ VALUE native_btree_class;
9
+ VALUE native_btree_module;
5
10
 
6
11
 
7
12
  void
8
13
  Init_native_btree()
9
14
  {
10
- rbtree_module = rb_define_module(NATIVE_BTREE_MODULE);
11
- rbtree_class = rb_define_class_under(rbtree_module, NATIVE_BTREE_CLASS, rb_cObject);
12
-
13
- rb_define_alloc_func(rbtree_class, rbtree_alloc);
14
- rb_define_method(rbtree_class, "initialize", rbtree_initialize, 0);
15
-
16
- rb_define_method(rbtree_class, "[]=", rbtree_set, 2);
17
- rb_define_alias(rbtree_class, "set", "[]=");
18
- rb_define_method(rbtree_class, "[]", rbtree_get, 1);
19
- rb_define_alias(rbtree_class, "get", "[]");
20
- rb_define_method(rbtree_class, "delete", rbtree_delete, 1);
21
- rb_define_method(rbtree_class, "each", rbtree_each, 0);
22
- rb_define_method(rbtree_class, "size", rbtree_size, 0);
23
- rb_define_method(rbtree_class, "height", rbtree_height, 0);
24
- rb_define_method(rbtree_class, "clear", rbtree_clear, 0);
25
- rb_define_method(rbtree_class, "include?", rbtree_is_include, 1);
26
- rb_define_method(rbtree_class, "to_h", rbtree_to_h, 0);
27
- rb_define_method(rbtree_class, "to_a", rbtree_to_a, 0);
15
+ native_btree_module = rb_define_module(NATIVE_BTREE_MODULE);
16
+ native_btree_class = rb_define_class_under(
17
+ native_btree_module,
18
+ NATIVE_BTREE_CLASS,
19
+ rb_cObject
20
+ );
21
+
22
+ // rb_include_module(native_btree_class, rb_mEnumerable);
23
+
24
+ rb_define_alloc_func(native_btree_class, rbtree_alloc);
25
+ rb_define_method(native_btree_class, "initialize", rbtree_initialize, 0);
26
+
27
+ rb_define_method(native_btree_class, "[]=", rbtree_set, 2);
28
+ rb_define_alias(native_btree_class, "set", "[]=");
29
+ rb_define_method(native_btree_class, "[]", rbtree_get, 1);
30
+ rb_define_alias(native_btree_class, "get", "[]");
31
+ rb_define_method(native_btree_class, "delete", rbtree_delete, 1);
32
+ rb_define_method(native_btree_class, "each", rbtree_each, 0);
33
+ rb_define_method(native_btree_class, "size", rbtree_size, 0);
34
+ rb_define_method(native_btree_class, "height", rbtree_height, 0);
35
+ rb_define_method(native_btree_class, "clear", rbtree_clear, 0);
36
+ rb_define_method(native_btree_class, "include?", rbtree_is_include, 1);
37
+ rb_define_method(native_btree_class, "to_h", rbtree_to_h, 0);
38
+ rb_define_method(native_btree_class, "to_a", rbtree_to_a, 0);
39
+ rb_define_method(native_btree_class, "to_proc", rbtree_to_proc, 0);
40
+ rb_define_method(native_btree_class, "filter", rbtree_filter, 0);
41
+ rb_define_alias(native_btree_class, "select", "filter");
42
+ rb_define_method(native_btree_class, "filter!", rbtree_filter_bang, 0);
43
+ rb_define_alias(native_btree_class, "select!", "filter!");
44
+ rb_define_method(native_btree_class, "empty?", rbtree_is_empty, 0);
28
45
  }
@@ -4,7 +4,7 @@ const rb_data_type_t rbtree_type;
4
4
 
5
5
 
6
6
  static void
7
- rbtree_free(gpointer data)
7
+ rbtree_type_free(gpointer data)
8
8
  {
9
9
  RBTree *rbtree = (RBTree *) data;
10
10
 
@@ -24,7 +24,7 @@ rbtree_mark_callback(gpointer key, gpointer value, gpointer data)
24
24
 
25
25
 
26
26
  static void
27
- rbtree_mark(gpointer data)
27
+ rbtree_type_mark(gpointer data)
28
28
  {
29
29
  RBTree *rbtree = (RBTree *)data;
30
30
 
@@ -61,7 +61,7 @@ struct _GTreeNode
61
61
  */
62
62
 
63
63
  static size_t
64
- rbtree_size(gconstpointer data)
64
+ rbtree_type_size(gconstpointer data)
65
65
  {
66
66
  RBTree *rbtree = (RBTree *) data;
67
67
 
@@ -82,11 +82,11 @@ rbtree_size(gconstpointer data)
82
82
 
83
83
 
84
84
  const rb_data_type_t rbtree_type = {
85
- .wrap_struct_name = NATIVE_TYPE_NAME,
85
+ .wrap_struct_name = RBTREE_NATIVE_TYPE_NAME,
86
86
  .function = {
87
- .dmark = rbtree_mark,
88
- .dfree = rbtree_free,
89
- .dsize = rbtree_size,
87
+ .dmark = rbtree_type_mark,
88
+ .dfree = rbtree_type_free,
89
+ .dsize = rbtree_type_size,
90
90
  },
91
91
  .data = NULL,
92
92
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
@@ -0,0 +1,101 @@
1
+ #include <iterators.h>
2
+
3
+ VALUE native_btree_class;
4
+
5
+ static gboolean
6
+ filter_callback(gpointer a, gpointer b, gpointer data)
7
+ {
8
+ RBTreeSearchData *context = (RBTreeSearchData *) data;
9
+
10
+ VALUE compare_result = rb_funcall(
11
+ context->block,
12
+ rb_intern("call"),
13
+ 2,
14
+ (VALUE) b,
15
+ (VALUE) a
16
+ );
17
+
18
+ if (RTEST(compare_result)) {
19
+ g_tree_insert(context->tree->gtree, a, b);
20
+ }
21
+
22
+ return FALSE;
23
+ }
24
+
25
+ static gboolean
26
+ filter_bang_callback(gpointer a, gpointer b, gpointer data)
27
+ {
28
+ RBTreeSearchData *context = (RBTreeSearchData *) data;
29
+ GPtrArray *to_remove = (GPtrArray *) context->something;
30
+
31
+ VALUE compare_result = rb_funcall(
32
+ context->block,
33
+ rb_intern("call"),
34
+ 2,
35
+ (VALUE) b,
36
+ (VALUE) a
37
+ );
38
+
39
+ if (!RTEST(compare_result)) {
40
+ // Add to remove
41
+ g_ptr_array_add(to_remove, a);
42
+ }
43
+
44
+ return FALSE;
45
+ }
46
+
47
+ VALUE
48
+ rbtree_filter(VALUE self)
49
+ {
50
+ rb_need_block();
51
+ EXTRACT_RBTREE_SELF(rbtree);
52
+
53
+ VALUE block = rb_block_proc();
54
+
55
+ VALUE new_tree = rb_funcall_with_block(
56
+ native_btree_class,
57
+ rb_intern("new"),
58
+ 0,
59
+ NULL,
60
+ rbtree->comparator
61
+ );
62
+
63
+ EXTRACT_RBTREE(new_tree, new_rbtree);
64
+
65
+ RBTreeSearchData data = {
66
+ block,
67
+ new_rbtree,
68
+ NULL
69
+ };
70
+
71
+ g_tree_foreach(rbtree->gtree, filter_callback, &data);
72
+
73
+ return new_tree;
74
+ }
75
+
76
+ VALUE
77
+ rbtree_filter_bang(VALUE self)
78
+ {
79
+ rb_need_block();
80
+ EXTRACT_RBTREE_SELF(rbtree);
81
+
82
+ VALUE block = rb_block_proc();
83
+
84
+ GPtrArray *to_remove = g_ptr_array_new();
85
+
86
+ RBTreeSearchData data = {
87
+ block,
88
+ NULL,
89
+ (gconstpointer) to_remove
90
+ };
91
+
92
+ g_tree_foreach(rbtree->gtree, filter_bang_callback, &data);
93
+
94
+ for (size_t i = 0; i < to_remove->len; i++) {
95
+ g_tree_remove(rbtree->gtree, g_ptr_array_index(to_remove, i));
96
+ }
97
+
98
+ g_ptr_array_free(to_remove, TRUE);
99
+
100
+ return self;
101
+ }
@@ -1,3 +1,3 @@
1
1
  module NativeBtree
2
- VERSION = "0.2.1".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
data/spec/debug.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "../lib/native_btree/native_btree"
4
4
 
5
- tree = NativeBtree::Btree.new
5
+ tree = NativeBtree::Btree.new { |a, b| a - b }
6
6
 
7
7
  GC.start
8
8
 
@@ -17,7 +17,16 @@ GC.start
17
17
  block = ->(key) { "#{key} is not found" }
18
18
  puts tree.delete(77, &block)
19
19
 
20
- tree = null
20
+ tree2 = tree.filter!() { true }
21
+
22
+ puts tree.to_h
23
+
24
+ pr = tree.to_proc
25
+
26
+ puts pr
27
+ puts pr.call(10)
28
+ puts pr.call(16)
29
+
21
30
 
22
31
  GC.start
23
32
 
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe NativeBtree do
4
+
5
+ describe NativeBtree::Btree do
6
+ let(:tree) do
7
+ described_class.new do |a, b|
8
+ a - b
9
+ end
10
+ end
11
+
12
+ describe "to_ methods" do
13
+ describe "#to_a" do
14
+ it "respond to" do
15
+ expect(tree).to respond_to(:to_a)
16
+ end
17
+
18
+ it 'return Array' do
19
+ expect(tree.to_a).to be_kind_of(Array)
20
+ end
21
+
22
+ it 'has similar items' do
23
+ tree[2] = 22
24
+ tree[1] = 11
25
+ expect(tree.to_a()[0][1]).to be 11
26
+ end
27
+ end
28
+
29
+ describe "#to_h" do
30
+ it "respond to" do
31
+ expect(tree).to respond_to(:to_h)
32
+ end
33
+
34
+ it "return Hash" do
35
+ expect(tree.to_h).to be_kind_of(Hash)
36
+ end
37
+
38
+ it 'has similar keys' do
39
+ tree[2] = 22
40
+ tree[1] = 11
41
+ expect(tree.to_h()[1]).to be 11
42
+ end
43
+ end
44
+
45
+ describe '#to_proc' do
46
+ it 'respond to' do
47
+ expect(tree).to respond_to(:to_proc)
48
+ end
49
+
50
+ it 'return Proc' do
51
+ expect(tree.to_proc).to be_kind_of(Proc)
52
+ end
53
+
54
+ it 'return value for key' do
55
+ tree[2] = 22
56
+ tree[1] = 11
57
+ pr = tree.to_proc
58
+ expect(pr.call(1)).to be 11
59
+ end
60
+
61
+ it 'return null for non existent key' do
62
+ tree[2] = 22
63
+ tree[1] = 11
64
+ pr = tree.to_proc
65
+ expect(pr.call(12)).to be_nil
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end