native_btree 0.1.0 → 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: 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