native_btree 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a71b1e34d117e61eb4ef28533f3d4371447b942e81bbfaa23b85af4fc81210ad
4
- data.tar.gz: 45b6b186bb06e9a58d5a26871f8ebb97dce6f3bffeeccb02169ea43dca972f86
3
+ metadata.gz: 1dbf5cc77f1056fc6f84cf49496c233b9a3ecd9c62a0d82149cce9804a80edd7
4
+ data.tar.gz: eb1f55db08e767f443b02751258fb749ae991eb98e5426a8d5c81714c66ebd49
5
5
  SHA512:
6
- metadata.gz: 3bea00617a86a99ad538d31825538ff2547748b30e377e55dcfa98134a25777a0cf33466405395c99836e9bba337f2177ec2d033efc7a4cca17fbe615c087d82
7
- data.tar.gz: 1d9ab5a418e9a9ad1e865ff31c1b126b738f2f546b35278fe483df1e357f8fccf427f9234fdc9ce031075d61956b28600af669aa7187d8b2d7f06a6146ff252d
6
+ metadata.gz: 7753f72aa3babc2151d74ae4bad29fb7c43e41cd7cf8b3bc9348e4b6e9be3c156d2ecc78fd2e689ca099e27df8bdee376550cbbc16b97ef15f15c431e8c5c093
7
+ data.tar.gz: d1992054500ad7207aea7186a0aa9bd3099cf013983c2596f5c2b5289ca5c8129f4ceeea4bf9ddf0777eb019b4dfc70be3b0feb571d741bb148af1f68de6e754
data/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
1
8
  ## [Unreleased]
2
9
 
3
- ## [0.1.0.alpha1] - 2022-08-20
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?()
19
+ * filter()
20
+ * filter!()
21
+ * select()
22
+ * select!()
23
+
24
+ ## [0.2.1] - 2022-09-08
25
+
26
+ ### Changed
27
+
28
+ * Legacy CMake versions support
29
+
30
+ ## [0.2.0] - 2022-09-07
31
+
32
+ ### Changed
33
+
34
+ * Small refactoring
35
+
36
+ ### Added
4
37
 
5
- - Initial release
38
+ * to_a()
39
+ * to_h()
40
+ * clear()
41
+ * include?()
data/CMakeLists.txt CHANGED
@@ -1,9 +1,10 @@
1
- cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)
1
+ cmake_minimum_required(VERSION 3.5)
2
2
 
3
3
  project(ruby-native-btree
4
4
  LANGUAGES C
5
- VERSION 0.1.0
6
- HOMEPAGE_URL https://github.com/unixs/ruby-native-btree)
5
+ VERSION 0.3.0)
6
+
7
+ include(CheckSymbolExists)
7
8
 
8
9
  set(REQUIRED_RUBY_VERSION 2.6.0)
9
10
 
@@ -35,9 +36,17 @@ find_package(PkgConfig REQUIRED)
35
36
 
36
37
  # Find Ruby
37
38
  find_package(Ruby ${REQUIRED_RUBY_VERSION} REQUIRED)
38
- include_directories(${Ruby_INCLUDE_DIRS})
39
- link_libraries(${Ruby_LIBRARIES})
40
- message("Ruby_INCLUDE_DIRS: ${Ruby_INCLUDE_DIRS}")
39
+
40
+ if(CMAKE_VERSION VERSION_GREATER "3.17.100")
41
+ include_directories(${Ruby_INCLUDE_DIRS})
42
+ link_libraries(${Ruby_LIBRARIES})
43
+ message(STATUS "Ruby_INCLUDE_DIRS: ${Ruby_INCLUDE_DIRS}")
44
+ else()
45
+ message(WARNING "Old CMake. Legacy FindRuby macro is used.")
46
+ include_directories(${RUBY_INCLUDE_DIRS})
47
+ link_libraries(${RUBY_LIBRARIES})
48
+ message(STATUS "RUBY_INCLUDE_DIRS: ${RUBY_INCLUDE_DIRS}")
49
+ endif()
41
50
 
42
51
  message(STATUS "Find Ruby deps.")
43
52
 
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
@@ -1,12 +1,33 @@
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
+ [![Gem Version](https://badge.fury.io/rb/native_btree.svg)](https://badge.fury.io/rb/native_btree)
5
+ [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
6
+
4
7
 
5
8
  [GTree - balanced binary tree from GLib library](https://docs.gtk.org/glib/struct.Tree.html)
6
9
 
7
10
  In most cases it will behave same as Hash, but keys will be ordered by passed comparator.
8
11
 
9
- ## Basic usage:
12
+ ## Requirements
13
+
14
+ * **CMake** build tool version **>= 3.14.0**
15
+ * `pkg-config` tool
16
+ * **GLib** library
17
+ * On Ubuntu run:
18
+ ```bash
19
+ sudo apt-get install pkg-config cmake libglib2.0-dev
20
+ ```
21
+ * On MacOS run:
22
+ ```
23
+ brew install pkg-config cmake glib
24
+ ```
25
+ * On FreeBSD use pkg or ports.
26
+ * On windows use Google. I don't really know how it can work at this moment... But i think it's possible
27
+
28
+ **Check CMake tool version!**
29
+
30
+ ## Basic usage
10
31
 
11
32
  ```ruby
12
33
  require 'native_btree'
@@ -36,11 +57,24 @@ tree.height
36
57
 
37
58
  You must provide your own comparator for keys in `new` class method block.
38
59
 
39
- ### Methods
60
+ ### API methods
61
+
62
+ In general this class behave same as Hash
63
+
64
+ Implemented methods:
40
65
 
41
66
  * `[]= (alias: set)`
42
67
  * `[] (alias: get)`
43
68
  * `delete`
44
69
  * `size`
45
70
  * `height`
46
- * `each`
71
+ * `each` (NB! block is required)
72
+ * `include?`
73
+ * `clear`
74
+ * `to_h`
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.
data/Rakefile CHANGED
@@ -28,7 +28,8 @@ namespace :cmake do
28
28
 
29
29
  desc "Configure ext CMake project"
30
30
  task :configure do
31
- sh "cmake -S . -B #{BUILD_DIR}"
31
+ sh "mkdir #{BUILD_DIR} || true"
32
+ sh "cd #{BUILD_DIR} && cmake .."
32
33
  end
33
34
 
34
35
  desc "Build ext CMake project"
@@ -7,22 +7,39 @@ pkg_check_modules(GLIB2 REQUIRED glib-2.0)
7
7
 
8
8
  include_directories(include ${GLIB2_INCLUDE_DIRS})
9
9
 
10
+ list(APPEND CMAKE_REQUIRED_LIBRARIES ${GLIB2_LDFLAGS})
11
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS})
12
+ check_symbol_exists(g_tree_remove_all "glib.h" HAVE_GTREE_REMOVE_ALL)
13
+
14
+ if(HAVE_GTREE_REMOVE_ALL)
15
+ add_compile_definitions(HAVE_GTREE_REMOVE_ALL)
16
+ endif()
17
+
18
+
19
+ add_library(${EXT_NAME}
20
+ SHARED
21
+ native_btree.c)
22
+
10
23
  add_library(rbtree_type OBJECT rbtree_type.c)
11
24
  add_library(constructor OBJECT constructor.c)
12
25
  add_library(instance OBJECT instance.c)
13
26
  add_library(comparator OBJECT comparator.c)
14
27
  add_library(iterators OBJECT iterators.c)
28
+ add_library(conversion OBJECT conversion.c)
29
+ add_library(search OBJECT search.c)
15
30
 
16
- add_library(${EXT_NAME}
17
- SHARED
18
- native_btree.c)
31
+ add_library(native_btree_interface
32
+ STATIC
33
+ $<TARGET_OBJECTS:conversion>
34
+ $<TARGET_OBJECTS:iterators>
35
+ $<TARGET_OBJECTS:comparator>
36
+ $<TARGET_OBJECTS:instance>
37
+ $<TARGET_OBJECTS:constructor>
38
+ $<TARGET_OBJECTS:rbtree_type>
39
+ $<TARGET_OBJECTS:search>)
19
40
 
20
41
  target_link_libraries(${EXT_NAME}
21
42
  PRIVATE
22
- iterators
23
- rbtree_type
24
- constructor
25
- instance
26
- comparator
43
+ native_btree_interface
27
44
  ${GLIB2_LDFLAGS})
28
- #set_target_properties(${EXT_NAME} PROPERTIES BUNDLE TRUE)
45
+
@@ -1,4 +1,3 @@
1
- #include <constructor.h>
2
1
  #include <comparator.h>
3
2
  #include <rbtree_type.h>
4
3
 
@@ -0,0 +1,78 @@
1
+ #include <common.h>
2
+
3
+
4
+ static gboolean
5
+ rbtree_to_h_callback(gpointer key, gpointer value, gpointer data)
6
+ {
7
+ VALUE hash = (VALUE) data;
8
+
9
+ rb_hash_aset(hash, (VALUE) key, (VALUE) value);
10
+
11
+ return FALSE;
12
+ }
13
+
14
+
15
+ static gboolean
16
+ rbtree_to_a_callback(gpointer key, gpointer value, gpointer data)
17
+ {
18
+ VALUE array = (VALUE) data;
19
+ VALUE array2 = rb_ary_new2(2);
20
+
21
+ rb_ary_push(array2, (VALUE) key);
22
+ rb_ary_push(array2, (VALUE) value);
23
+
24
+ rb_ary_push(array, array2);
25
+
26
+ return FALSE;
27
+ }
28
+
29
+
30
+ VALUE
31
+ rbtree_to_h(VALUE self)
32
+ {
33
+ EXTRACT_RBTREE_SELF(rbtree);
34
+
35
+ VALUE hash = rb_hash_new();
36
+
37
+ g_tree_foreach(rbtree->gtree, rbtree_to_h_callback, (gpointer) hash);
38
+
39
+ return hash;
40
+ }
41
+
42
+
43
+ VALUE
44
+ rbtree_to_a(VALUE self)
45
+ {
46
+ EXTRACT_RBTREE_SELF(rbtree);
47
+
48
+ gint tree_size = g_tree_nnodes(rbtree->gtree);
49
+
50
+ VALUE array = rb_ary_new2(tree_size);
51
+
52
+ g_tree_foreach(rbtree->gtree, rbtree_to_a_callback, (gpointer) array);
53
+
54
+ return array;
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,46 +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>
3
+ #include <ruby.h>
7
4
 
8
- /*
9
5
  VALUE
10
- btree_new(VALUE klass);
6
+ rbtree_initialize(VALUE self);
11
7
 
12
8
  VALUE
13
- btree_init(VALUE self);
9
+ rbtree_set(VALUE self, VALUE key, VALUE value);
14
10
 
15
11
  VALUE
16
- btree_size(VALUE self);
12
+ rbtree_get(VALUE self, VALUE key);
17
13
 
18
14
  VALUE
19
- btree_height(VALUE self);
15
+ rbtree_delete(VALUE self, VALUE key);
20
16
 
21
17
  VALUE
22
- btree_set(VALUE self, VALUE key, VALUE value);
18
+ rbtree_size(VALUE self);
23
19
 
24
20
  VALUE
25
- btree_get(VALUE self, VALUE key);
21
+ rbtree_height(VALUE self);
26
22
 
27
23
  VALUE
28
- btree_delete(VALUE self, VALUE key);
24
+ rbtree_clear(VALUE self);
29
25
 
30
26
  VALUE
31
- btree_clear(VALUE self);
27
+ rbtree_is_include(VALUE self, VALUE key);
32
28
 
33
29
  VALUE
34
- btree_has(VALUE self, VALUE key);
30
+ rbtree_each(VALUE self);
35
31
 
36
32
  VALUE
37
- btree_each(VALUE self);
33
+ rbtree_to_h(VALUE self);
38
34
 
39
35
  VALUE
40
- btree_cmp(VALUE self, VALUE tree2);
36
+ rbtree_to_a(VALUE self);
41
37
 
42
38
  VALUE
43
- btree_equal(VALUE self, VALUE tree2);
44
- */
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);
45
49
 
46
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,18 @@
1
- #include <instance.h>
1
+ #include <common.h>
2
+
3
+
4
+ #ifndef HAVE_GTREE_REMOVE_ALL
5
+
6
+ static gboolean
7
+ rbtree_remove_node(gpointer key, gpointer val, gpointer data) {
8
+ RBTree *rbtree = (RBTree *) data;
9
+
10
+ g_tree_remove(rbtree->gtree, key);
11
+
12
+ return FALSE;
13
+ }
14
+
15
+ #endif
2
16
 
3
17
 
4
18
  VALUE
@@ -81,3 +95,44 @@ rbtree_size(VALUE self)
81
95
 
82
96
  return result;
83
97
  }
98
+
99
+
100
+ VALUE
101
+ rbtree_clear(VALUE self)
102
+ {
103
+ EXTRACT_RBTREE_SELF(rbtree);
104
+
105
+ #ifdef HAVE_GTREE_REMOVE_ALL
106
+ g_tree_remove_all(rbtree->gtree);
107
+ #else
108
+ g_tree_foreach(rbtree->gtree, rbtree_remove_node, (gpointer) rbtree);
109
+ #endif
110
+
111
+ return self;
112
+ }
113
+
114
+
115
+ VALUE
116
+ rbtree_is_include(VALUE self, VALUE key)
117
+ {
118
+ EXTRACT_RBTREE_SELF(rbtree);
119
+
120
+ gpointer exists = g_tree_lookup(rbtree->gtree, (gconstpointer) key);
121
+
122
+ if (exists == NULL) {
123
+ return Qfalse;
124
+ }
125
+
126
+ return Qtrue;
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,29 +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
-
19
- rb_define_method(rbtree_class, "[]", rbtree_get, 1);
20
- rb_define_alias(rbtree_class, "get", "[]");
21
-
22
- rb_define_method(rbtree_class, "delete", rbtree_delete, 1);
23
-
24
- rb_define_method(rbtree_class, "each", rbtree_each, 0);
25
-
26
- rb_define_method(rbtree_class, "size", rbtree_size, 0);
27
- rb_define_method(rbtree_class, "height", rbtree_height, 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
  }
29
-
@@ -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
+ }
Binary file
@@ -1,3 +1,3 @@
1
1
  module NativeBtree
2
- VERSION = "0.1.0".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
@@ -137,102 +137,53 @@ RSpec.describe NativeBtree do
137
137
  end
138
138
 
139
139
  describe "#clear method" do
140
- xit "respond to" do
141
- expect(described_cless.respond_to?(:clear)).to be true
140
+ it "respond to" do
141
+ expect(tree).to respond_to(:clear)
142
142
  end
143
- end
144
143
 
145
- describe "#filter method" do
146
- xit "respond to" do
147
- expect(described_cless.respond_to?(:filter)).to be true
144
+ it 'clear tree' do
145
+ tree[1] = 11
146
+ tree[2] = 22
147
+ tree[3] = 33
148
+ expect(tree.size).to be 3
149
+ tree.clear()
150
+ expect(tree.size).to be 0
148
151
  end
149
- end
150
152
 
151
- describe "#filter! method" do
152
- xit "respond to" do
153
- expect(described_cless.respond_to?(:filter!)).to be true
153
+ it 'return self' do
154
+ tree[1] = 11
155
+ expect(tree.clear()).to be tree
154
156
  end
155
157
  end
156
158
 
157
159
  describe "#include? method" do
158
- xit "respond to" do
159
- expect(described_cless.respond_to?(:include?)).to be true
160
- end
161
- end
162
-
163
- describe "to_ methods" do
164
- describe "#to_a" do
165
- xit "respond to" do
166
- expect(described_cless.respond_to?(:to_a)).to be true
167
- end
168
- end
169
-
170
- describe "#to_h" do
171
- xit "respond to" do
172
- expect(described_cless.respond_to?(:to_h)).to be true
173
- end
174
- end
175
- end
176
-
177
- describe "#each method" do
178
160
  it "respond to" do
179
- expect(tree).to respond_to(:each)
161
+ expect(tree).to respond_to(:include?)
180
162
  end
181
163
 
182
- it 'yield in to block value first' do
183
- tree[2] = 22
184
-
185
- value = nil
186
- tree.each { |v| value = v }
187
-
188
- expect(value).to be 22
189
- end
190
-
191
- it 'yield in to block key second' do
192
- tree[2] = 22
193
-
194
- key = nil
195
- tree.each { |_v, k| key = k }
196
-
197
- expect(key).to be 2
198
- end
199
-
200
- it 'yield ordered keys' do
201
- tree[16] = 16
202
- tree[0] = 0
203
- tree[5] = 5
204
- tree[-4] = -4
205
- tree[7] = 7
206
-
207
- check = [-4, 0, 5, 7, 16]
208
- result = []
209
- tree.each { |value| result << value }
210
-
211
- expect(result).to eq(check)
164
+ it 'return true is key exists' do
165
+ tree[3] = 33
166
+ expect(tree.include?(3)).to be true
212
167
  end
213
- end
214
168
 
215
- describe "#each_key method" do
216
- xit "respond to" do
217
- expect(described_cless.respond_to?(:each_key)).to be true
169
+ it 'return false if key not exists' do
170
+ tree[3] = 33
171
+ expect(tree.include?(4)).to be false
218
172
  end
219
173
  end
220
174
 
221
- describe "#each_value method" do
222
- xit "respond to" do
223
- expect(described_cless.respond_to?(:each_value)).to be true
175
+ describe "#empty? method" do
176
+ it 'respond to' do
177
+ expect(tree).to respond_to(:empty?)
224
178
  end
225
- end
226
179
 
227
- describe "#select method" do
228
- xit "respond to" do
229
- expect(described_cless.respond_to?(:select)).to be true
180
+ it 'return false if nodes exists' do
181
+ tree[3] = 33
182
+ expect(tree.empty?).to be false
230
183
  end
231
- end
232
184
 
233
- describe "#select! method" do
234
- xit "respond to" do
235
- expect(described_cless.respond_to?(:select!)).to be true
185
+ it 'return true if nodes not exists' do
186
+ expect(tree.empty?).to be true
236
187
  end
237
188
  end
238
189
  end
@@ -0,0 +1,62 @@
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 "#each method" do
13
+ it "respond to" do
14
+ expect(tree).to respond_to(:each)
15
+ end
16
+
17
+ it 'yield in to block value first' do
18
+ tree[2] = 22
19
+
20
+ value = nil
21
+ tree.each { |v| value = v }
22
+
23
+ expect(value).to be 22
24
+ end
25
+
26
+ it 'yield in to block key second' do
27
+ tree[2] = 22
28
+
29
+ key = nil
30
+ tree.each { |_v, k| key = k }
31
+
32
+ expect(key).to be 2
33
+ end
34
+
35
+ it 'yield ordered keys' do
36
+ tree[16] = 16
37
+ tree[0] = 0
38
+ tree[5] = 5
39
+ tree[-4] = -4
40
+ tree[7] = 7
41
+
42
+ check = [-4, 0, 5, 7, 16]
43
+ result = []
44
+ tree.each { |value| result << value }
45
+
46
+ expect(result).to eq(check)
47
+ end
48
+ end
49
+
50
+ describe "#each_key method" do
51
+ xit "respond to" do
52
+ expect(described_cless.respond_to?(:each_key)).to be true
53
+ end
54
+ end
55
+
56
+ describe "#each_value method" do
57
+ xit "respond to" do
58
+ expect(described_cless.respond_to?(:each_value)).to be true
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,118 @@
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 "#filter method" do
13
+ it "respond to" do
14
+ expect(tree).to respond_to(:filter)
15
+ end
16
+
17
+ it 'raise error if block not given' do
18
+ expect { tree.filter() }.to raise_error(LocalJumpError)
19
+ end
20
+
21
+ it 'return Btree instance' do
22
+ expect(tree.filter() { nil }).to be_kind_of(described_class)
23
+ end
24
+
25
+ it 'filter tree by values' do
26
+ tree[1] = 11
27
+ tree[5] = 90
28
+ tree[2] = 32
29
+ tree[100] = 15
30
+ tree[46] = 8
31
+
32
+ expect(tree.filter { |v| v > 20 }.to_a).to match_array([[2, 32], [5, 90]])
33
+ end
34
+
35
+ it 'filter tree by keys' do
36
+ tree[1] = 11
37
+ tree[5] = 90
38
+ tree[2] = 32
39
+ tree[100] = 15
40
+ tree[46] = 8
41
+
42
+ expect(tree.filter { |_v, k| k > 20 }.to_a).to match_array([[46, 8], [100, 15]])
43
+ end
44
+
45
+ it 'return new object' do
46
+ tree[1] = 11
47
+ tree[5] = 90
48
+ tree[2] = 32
49
+ tree[100] = 15
50
+ tree[46] = 8
51
+
52
+ result = tree.filter { |_v, k| k > 20 }
53
+
54
+ expect(tree.equal?(result)).to be false
55
+ end
56
+
57
+ end
58
+
59
+ describe "#filter! method" do
60
+ it "respond to" do
61
+ expect(tree).to respond_to(:filter!)
62
+ end
63
+
64
+ it 'raise error if block not given' do
65
+ expect { tree.filter!() }.to raise_error(LocalJumpError)
66
+ end
67
+
68
+ it 'return Btree instance' do
69
+ expect(tree.filter!() { nil }).to be_kind_of(described_class)
70
+ end
71
+
72
+ it 'return origin tree' do
73
+ tree[1] = 11
74
+ tree[5] = 90
75
+ tree[2] = 32
76
+ tree[100] = 15
77
+ tree[46] = 8
78
+
79
+ result = tree.filter! { |_v, k| k > 20 }
80
+
81
+ expect(tree.equal?(result)).to be true
82
+ end
83
+
84
+ it 'filter tree by values' do
85
+ tree[1] = 11
86
+ tree[5] = 90
87
+ tree[2] = 32
88
+ tree[100] = 15
89
+ tree[46] = 8
90
+
91
+ expect(tree.filter! { |v| v > 20 }.to_a).to match_array([[2, 32], [5, 90]])
92
+ end
93
+
94
+ it 'filter tree by keys' do
95
+ tree[1] = 11
96
+ tree[5] = 90
97
+ tree[2] = 32
98
+ tree[100] = 15
99
+ tree[46] = 8
100
+
101
+ expect(tree.filter! { |_v, k| k > 20 }.to_a).to match_array([[46, 8], [100, 15]])
102
+ end
103
+
104
+ end
105
+
106
+ describe "#select method" do
107
+ it "respond to" do
108
+ expect(tree).to respond_to(:select)
109
+ end
110
+ end
111
+
112
+ describe "#select! method" do
113
+ it "respond to" do
114
+ expect(tree).to respond_to(:select!)
115
+ end
116
+ end
117
+ end
118
+ 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.1.0
4
+ version: 0.3.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-05 00:00:00.000000000 Z
11
+ date: 2022-09-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby bindings to GTree balanced binary tree from GLib library.
14
14
  email:
@@ -27,12 +27,10 @@ files:
27
27
  - ext/native_btree/CMakeLists.txt
28
28
  - ext/native_btree/comparator.c
29
29
  - ext/native_btree/constructor.c
30
+ - ext/native_btree/conversion.c
30
31
  - ext/native_btree/extconf_cmake.rb
31
- - ext/native_btree/include/btree.h
32
32
  - ext/native_btree/include/common.h
33
33
  - ext/native_btree/include/comparator.h
34
- - ext/native_btree/include/constructor.h
35
- - ext/native_btree/include/instance.h
36
34
  - ext/native_btree/include/iterators.h
37
35
  - ext/native_btree/include/native_btree.h
38
36
  - ext/native_btree/include/rbtree_type.h
@@ -40,15 +38,18 @@ files:
40
38
  - ext/native_btree/iterators.c
41
39
  - ext/native_btree/native_btree.c
42
40
  - ext/native_btree/rbtree_type.c
41
+ - ext/native_btree/search.c
43
42
  - lib/native_btree.rb
44
43
  - lib/native_btree/native_btree.bundle
45
- - lib/native_btree/native_btree.so
46
44
  - lib/native_btree/version.rb
47
45
  - native_btree.gemspec
48
46
  - spec/debug.rb
49
47
  - spec/native_btree_class_spec.rb
48
+ - spec/native_btree_conversion_spec.rb
50
49
  - spec/native_btree_instance_spec.rb
50
+ - spec/native_btree_iterators_spec.rb
51
51
  - spec/native_btree_module_spec.rb
52
+ - spec/native_btree_search_spec.rb
52
53
  - spec/spec_helper.rb
53
54
  homepage: https://github.com/unixs/ruby-native-btree
54
55
  licenses:
@@ -1,63 +0,0 @@
1
- #include <string>
2
- #include <ruby.h>
3
- #include <glib.h>
4
-
5
- using namespace std;
6
-
7
- class BTree {
8
- public:
9
- BTree(VALUE comparator);
10
- ~BTree();
11
-
12
- // get
13
- VALUE const &operator[](VALUE key) const;
14
- // set
15
- void operator[](VALUE key);
16
-
17
- gint
18
- height();
19
-
20
- gint
21
- size();
22
-
23
- bool
24
- del(VALUE key);
25
-
26
- void
27
- clear();
28
-
29
- bool
30
- has(VALUE key);
31
-
32
- void
33
- mark();
34
-
35
- void
36
- set(VALUE key, VALUE value);
37
-
38
- VALUE
39
- get(VALUE key);
40
-
41
- void
42
- each(VALUE block);
43
-
44
- void
45
- each(GTraverseFunc func, gpointer data);
46
-
47
- private:
48
- GTree *tree;
49
- VALUE comparator;
50
-
51
- void
52
- markMyRValues();
53
-
54
- static gint
55
- nativeComparator(gconstpointer keyA, gconstpointer keyB, gpointer tree);
56
-
57
- static gint
58
- markRValue(gpointer key, gpointer value, gpointer not_used);
59
-
60
- static gboolean
61
- traverseFunc(gpointer k, gpointer v, gpointer data);
62
- };
63
-
@@ -1,11 +0,0 @@
1
- #include <common.h>
2
-
3
- #ifndef _NATIVE_BTREE_CONSTRUCTOR_
4
- #define _NATIVE_BTREE_CONSTRUCTOR_
5
-
6
-
7
-
8
- VALUE rbtree_alloc(VALUE self);
9
- VALUE rbtree_initialize(VALUE self);
10
-
11
- #endif //_NATIVE_BTREE_COMMON_H_
@@ -1,16 +0,0 @@
1
- #include <common.h>
2
-
3
- VALUE
4
- rbtree_set(VALUE self, VALUE key, VALUE value);
5
-
6
- VALUE
7
- rbtree_get(VALUE self, VALUE key);
8
-
9
- VALUE
10
- rbtree_delete(VALUE self, VALUE key);
11
-
12
- VALUE
13
- rbtree_size(VALUE self);
14
-
15
- VALUE
16
- rbtree_height(VALUE self);
Binary file