rbtree 0.2.1 → 0.4.3
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 +7 -0
- data/LICENSE +1 -1
- data/MANIFEST +0 -1
- data/README +36 -72
- data/dict.c +364 -83
- data/dict.h +30 -6
- data/extconf.rb +11 -5
- data/rbtree.c +796 -470
- data/test.rb +313 -157
- metadata +42 -45
- data/ChangeLog +0 -483
data/dict.h
CHANGED
@@ -14,18 +14,21 @@
|
|
14
14
|
* into proprietary software; there is no requirement for such software to
|
15
15
|
* contain a copyright notice related to this source.
|
16
16
|
*
|
17
|
-
* $Id: dict.h,v 1.
|
18
|
-
* $Name:
|
17
|
+
* $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $
|
18
|
+
* $Name: kazlib_1_20 $
|
19
19
|
*/
|
20
20
|
|
21
21
|
/*
|
22
|
-
* Modified for Ruby/RBTree
|
22
|
+
* Modified for Ruby/RBTree.
|
23
23
|
*/
|
24
24
|
|
25
25
|
#ifndef DICT_H
|
26
26
|
#define DICT_H
|
27
27
|
|
28
28
|
#include <limits.h>
|
29
|
+
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
30
|
+
#include "sfx.h"
|
31
|
+
#endif
|
29
32
|
|
30
33
|
/*
|
31
34
|
* Blurb for inclusion into C++ translation units
|
@@ -45,21 +48,24 @@ typedef unsigned long dictcount_t;
|
|
45
48
|
typedef enum { dnode_red, dnode_black } dnode_color_t;
|
46
49
|
|
47
50
|
typedef struct dnode_t {
|
51
|
+
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
48
52
|
struct dnode_t *dict_left;
|
49
53
|
struct dnode_t *dict_right;
|
50
54
|
struct dnode_t *dict_parent;
|
51
55
|
dnode_color_t dict_color;
|
52
56
|
const void *dict_key;
|
53
57
|
void *dict_data;
|
58
|
+
#else
|
59
|
+
int dict_dummy;
|
60
|
+
#endif
|
54
61
|
} dnode_t;
|
55
62
|
|
56
63
|
typedef int (*dict_comp_t)(const void *, const void *, void *);
|
57
64
|
typedef dnode_t *(*dnode_alloc_t)(void *);
|
58
65
|
typedef void (*dnode_free_t)(dnode_t *, void *);
|
59
66
|
|
60
|
-
typedef int (*dict_value_eql_t)(const void *, const void *);
|
61
|
-
|
62
67
|
typedef struct dict_t {
|
68
|
+
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
63
69
|
dnode_t dict_nilnode;
|
64
70
|
dictcount_t dict_nodecount;
|
65
71
|
dict_comp_t dict_compare;
|
@@ -67,13 +73,20 @@ typedef struct dict_t {
|
|
67
73
|
dnode_free_t dict_freenode;
|
68
74
|
void *dict_context;
|
69
75
|
int dict_dupes;
|
76
|
+
#else
|
77
|
+
int dict_dummmy;
|
78
|
+
#endif
|
70
79
|
} dict_t;
|
71
80
|
|
72
81
|
typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
|
73
82
|
|
74
83
|
typedef struct dict_load_t {
|
84
|
+
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
75
85
|
dict_t *dict_dictptr;
|
76
86
|
dnode_t dict_nilnode;
|
87
|
+
#else
|
88
|
+
int dict_dummmy;
|
89
|
+
#endif
|
77
90
|
} dict_load_t;
|
78
91
|
|
79
92
|
extern dict_t *dict_create(dict_comp_t);
|
@@ -114,7 +127,18 @@ extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
|
|
114
127
|
extern void dict_load_end(dict_load_t *);
|
115
128
|
extern void dict_merge(dict_t *, dict_t *);
|
116
129
|
|
117
|
-
|
130
|
+
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
|
131
|
+
#ifdef KAZLIB_SIDEEFFECT_DEBUG
|
132
|
+
#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
|
133
|
+
#else
|
134
|
+
#define dict_isfull(D) ((D)->dict_nodecount == DICTCOUNT_T_MAX)
|
135
|
+
#endif
|
136
|
+
#define dict_count(D) ((D)->dict_nodecount)
|
137
|
+
#define dict_isempty(D) ((D)->dict_nodecount == 0)
|
138
|
+
#define dnode_get(N) ((N)->dict_data)
|
139
|
+
#define dnode_getkey(N) ((N)->dict_key)
|
140
|
+
#define dnode_put(N, X) ((N)->dict_data = (X))
|
141
|
+
#endif
|
118
142
|
|
119
143
|
#ifdef __cplusplus
|
120
144
|
}
|
data/extconf.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
if
|
4
|
-
$CFLAGS << ' -std=
|
5
|
-
$defs << ' -Dinline=__inline'
|
3
|
+
if enable_config('debug')
|
4
|
+
$CFLAGS << ' -g -std=c99 -pedantic -Wall'
|
6
5
|
else
|
7
6
|
$defs << '-DNDEBUG'
|
8
7
|
end
|
9
|
-
|
10
|
-
have_func('
|
8
|
+
have_func('rb_exec_recursive', 'ruby.h')
|
9
|
+
have_func('rb_exec_recursive_paired', 'ruby.h')
|
10
|
+
have_func('rb_proc_lambda_p', 'ruby.h')
|
11
|
+
have_func('rb_ary_resize', 'ruby.h')
|
12
|
+
have_func('rb_obj_hide', 'ruby.h')
|
13
|
+
have_func('rb_safe_level', 'ruby.h')
|
14
|
+
if Hash.method_defined?(:flatten)
|
15
|
+
$defs << '-DHAVE_HASH_FLATTEN'
|
16
|
+
end
|
11
17
|
create_makefile('rbtree')
|
data/rbtree.c
CHANGED
@@ -1,40 +1,56 @@
|
|
1
1
|
/*
|
2
2
|
* MIT License
|
3
|
-
* Copyright (c) 2002-
|
3
|
+
* Copyright (c) 2002-2013 OZAWA Takuma
|
4
4
|
*/
|
5
5
|
#include <ruby.h>
|
6
|
-
#
|
6
|
+
#ifdef HAVE_RUBY_ST_H
|
7
|
+
#include <ruby/st.h>
|
8
|
+
#else
|
7
9
|
#include <st.h>
|
8
|
-
#
|
10
|
+
#endif
|
9
11
|
#include "dict.h"
|
10
12
|
|
11
13
|
#define RBTREE_PROC_DEFAULT FL_USER2
|
12
14
|
#define HASH_PROC_DEFAULT FL_USER2
|
13
15
|
|
14
|
-
#
|
15
|
-
#define
|
16
|
+
#ifdef RETURN_SIZED_ENUMERATOR
|
17
|
+
#define HAVE_SIZED_ENUMERATOR
|
18
|
+
#else
|
19
|
+
#ifdef RETURN_ENUMERATOR
|
20
|
+
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) RETURN_ENUMERATOR(obj, argc, argv)
|
21
|
+
#else
|
22
|
+
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) ((void)0)
|
23
|
+
#endif
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifndef RARRAY_AREF
|
27
|
+
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#ifndef RHASH_SET_IFNONE
|
31
|
+
#define RHASH_SET_IFNONE(h, v) (RHASH(h)->ifnone = (v))
|
16
32
|
#endif
|
17
33
|
|
18
34
|
VALUE RBTree;
|
19
35
|
VALUE MultiRBTree;
|
20
36
|
|
21
|
-
static ID id_bound;
|
22
37
|
static ID id_cmp;
|
23
38
|
static ID id_call;
|
24
39
|
static ID id_default;
|
40
|
+
static ID id_flatten_bang;
|
25
41
|
|
26
42
|
typedef struct {
|
27
43
|
dict_t* dict;
|
28
44
|
VALUE ifnone;
|
45
|
+
VALUE cmp_proc;
|
29
46
|
int iter_lev;
|
30
47
|
} rbtree_t;
|
31
48
|
|
32
49
|
#define RBTREE(rbtree) DATA_PTR(rbtree)
|
33
50
|
#define DICT(rbtree) ((rbtree_t*)RBTREE(rbtree))->dict
|
34
51
|
#define IFNONE(rbtree) ((rbtree_t*)RBTREE(rbtree))->ifnone
|
52
|
+
#define CMP_PROC(rbtree) ((rbtree_t*)RBTREE(rbtree))->cmp_proc
|
35
53
|
#define ITER_LEV(rbtree) ((rbtree_t*)RBTREE(rbtree))->iter_lev
|
36
|
-
#define COMPARE(rbtree) DICT(rbtree)->dict_compare
|
37
|
-
#define CONTEXT(rbtree) DICT(rbtree)->dict_context
|
38
54
|
|
39
55
|
#define TO_KEY(arg) ((const void*)arg)
|
40
56
|
#define TO_VAL(arg) ((void*)arg)
|
@@ -44,17 +60,11 @@ typedef struct {
|
|
44
60
|
|
45
61
|
/*********************************************************************/
|
46
62
|
|
47
|
-
static int
|
48
|
-
cmpint(VALUE i, VALUE a, VALUE b)
|
49
|
-
{
|
50
|
-
return rb_cmpint(i, a, b);
|
51
|
-
}
|
52
|
-
|
53
63
|
static void
|
54
64
|
rbtree_free(rbtree_t* rbtree)
|
55
65
|
{
|
56
66
|
dict_free_nodes(rbtree->dict);
|
57
|
-
|
67
|
+
xfree(rbtree->dict);
|
58
68
|
xfree(rbtree);
|
59
69
|
}
|
60
70
|
|
@@ -73,9 +83,9 @@ rbtree_mark(rbtree_t* rbtree)
|
|
73
83
|
rb_gc_mark(GET_KEY(node));
|
74
84
|
rb_gc_mark(GET_VAL(node));
|
75
85
|
}
|
76
|
-
rb_gc_mark((VALUE)dict->dict_context);
|
77
86
|
}
|
78
87
|
rb_gc_mark(rbtree->ifnone);
|
88
|
+
rb_gc_mark(rbtree->cmp_proc);
|
79
89
|
}
|
80
90
|
|
81
91
|
static dnode_t*
|
@@ -91,63 +101,112 @@ rbtree_free_node(dnode_t* node, void* context)
|
|
91
101
|
}
|
92
102
|
|
93
103
|
static void
|
94
|
-
|
95
|
-
{
|
96
|
-
|
104
|
+
rbtree_check_argument_count(const int argc, const int min, const int max)
|
105
|
+
{
|
106
|
+
if (argc < min || argc > max) {
|
107
|
+
static const char* const message = "wrong number of arguments";
|
108
|
+
if (min == max) {
|
109
|
+
rb_raise(rb_eArgError, "%s (%d for %d)", message, argc, min);
|
110
|
+
} else if (max == INT_MAX) {
|
111
|
+
rb_raise(rb_eArgError, "%s (%d for %d+)", message, argc, -min - 1);
|
112
|
+
} else {
|
113
|
+
rb_raise(rb_eArgError, "%s (%d for %d..%d)", message, argc, min, max);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
static void
|
119
|
+
rbtree_check_proc_arity(VALUE proc, const int expected)
|
120
|
+
{
|
121
|
+
#ifdef HAVE_RB_PROC_LAMBDA_P
|
122
|
+
if (rb_proc_lambda_p(proc)) {
|
123
|
+
const int arity = rb_proc_arity(proc);
|
124
|
+
const int min = arity < 0 ? -arity - 1 : arity;
|
125
|
+
const int max = arity < 0 ? INT_MAX : arity;
|
126
|
+
if (expected < min || expected > max) {
|
127
|
+
rb_raise(rb_eTypeError, "proc takes %d arguments", expected);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
#endif
|
97
131
|
}
|
98
132
|
|
99
133
|
static int
|
100
134
|
rbtree_cmp(const void* key1, const void* key2, void* context)
|
101
135
|
{
|
102
|
-
VALUE
|
136
|
+
VALUE result;
|
103
137
|
if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
|
104
138
|
return rb_str_cmp((VALUE)key1, (VALUE)key2);
|
105
|
-
|
106
|
-
return
|
139
|
+
result = rb_funcall2((VALUE)key1, id_cmp, 1, (VALUE*)&key2);
|
140
|
+
return rb_cmpint(result, (VALUE)key1, (VALUE)key2);
|
141
|
+
}
|
142
|
+
|
143
|
+
static VALUE
|
144
|
+
rbtree_user_cmp_ensure(rbtree_t* rbtree)
|
145
|
+
{
|
146
|
+
rbtree->iter_lev--;
|
147
|
+
return Qnil;
|
148
|
+
}
|
149
|
+
|
150
|
+
static VALUE
|
151
|
+
rbtree_user_cmp_body(VALUE* args)
|
152
|
+
{
|
153
|
+
rbtree_t* rbtree = (rbtree_t*)args[2];
|
154
|
+
rbtree->iter_lev++;
|
155
|
+
return rb_funcall2(rbtree->cmp_proc, id_call, 2, args);
|
107
156
|
}
|
108
157
|
|
109
158
|
static int
|
110
|
-
rbtree_user_cmp(const void* key1, const void* key2, void*
|
159
|
+
rbtree_user_cmp(const void* key1, const void* key2, void* context)
|
111
160
|
{
|
112
|
-
|
113
|
-
|
114
|
-
|
161
|
+
rbtree_t* rbtree = (rbtree_t*)context;
|
162
|
+
VALUE args[3];
|
163
|
+
VALUE result;
|
164
|
+
|
165
|
+
args[0] = (VALUE)key1;
|
166
|
+
args[1] = (VALUE)key2;
|
167
|
+
args[2] = (VALUE)rbtree;
|
168
|
+
result = rb_ensure(rbtree_user_cmp_body, (VALUE)&args,
|
169
|
+
rbtree_user_cmp_ensure, (VALUE)rbtree);
|
170
|
+
return rb_cmpint(result, (VALUE)key1, (VALUE)key2);
|
115
171
|
}
|
116
172
|
|
117
173
|
static void
|
118
174
|
rbtree_modify(VALUE self)
|
119
175
|
{
|
120
176
|
if (ITER_LEV(self) > 0)
|
121
|
-
rb_raise(rb_eTypeError, "can't modify rbtree
|
122
|
-
|
123
|
-
|
177
|
+
rb_raise(rb_eTypeError, "can't modify rbtree during iteration");
|
178
|
+
rb_check_frozen(self);
|
179
|
+
#ifdef HAVE_RB_SAFE_LEVEL
|
124
180
|
if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
|
125
181
|
rb_raise(rb_eSecurityError, "Insecure: can't modify rbtree");
|
182
|
+
#endif
|
126
183
|
}
|
127
184
|
|
128
185
|
static VALUE
|
129
186
|
rbtree_alloc(VALUE klass)
|
130
187
|
{
|
131
188
|
dict_t* dict;
|
132
|
-
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free,
|
189
|
+
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, NULL);
|
133
190
|
RBTREE(rbtree) = ALLOC(rbtree_t);
|
134
191
|
MEMZERO(RBTREE(rbtree), rbtree_t, 1);
|
135
192
|
|
136
|
-
dict =
|
193
|
+
dict = ALLOC(dict_t);
|
194
|
+
dict_init(dict, rbtree_cmp);
|
137
195
|
dict_set_allocator(dict, rbtree_alloc_node, rbtree_free_node,
|
138
|
-
(
|
139
|
-
if (klass
|
196
|
+
RBTREE(rbtree));
|
197
|
+
if (!RTEST(rb_class_inherited_p(klass, RBTree)))
|
140
198
|
dict_allow_dupes(dict);
|
141
|
-
|
199
|
+
|
142
200
|
DICT(rbtree) = dict;
|
143
201
|
IFNONE(rbtree) = Qnil;
|
202
|
+
CMP_PROC(rbtree) = Qnil;
|
144
203
|
return rbtree;
|
145
204
|
}
|
146
205
|
|
147
206
|
VALUE rbtree_aset(VALUE, VALUE, VALUE);
|
148
|
-
VALUE rbtree_clear(VALUE);
|
149
207
|
VALUE rbtree_has_key(VALUE, VALUE);
|
150
208
|
VALUE rbtree_update(VALUE, VALUE);
|
209
|
+
VALUE rbtree_to_a(VALUE);
|
151
210
|
|
152
211
|
/*********************************************************************/
|
153
212
|
|
@@ -167,52 +226,57 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
|
|
167
226
|
{
|
168
227
|
long i;
|
169
228
|
VALUE rbtree;
|
170
|
-
|
229
|
+
|
171
230
|
if (argc == 1) {
|
172
|
-
VALUE
|
173
|
-
|
174
|
-
if (klass == RBTree && CLASS_OF(argv[0]) == MultiRBTree) {
|
175
|
-
rb_raise(rb_eTypeError, "can't convert MultiRBTree to RBTree");
|
176
|
-
}
|
177
|
-
|
231
|
+
VALUE temp;
|
232
|
+
|
178
233
|
if (rb_obj_is_kind_of(argv[0], klass)) {
|
179
234
|
rbtree = rbtree_alloc(klass);
|
180
235
|
rbtree_update(rbtree, argv[0]);
|
181
236
|
return rbtree;
|
182
237
|
}
|
183
|
-
|
184
|
-
|
185
|
-
|
238
|
+
|
239
|
+
if (RTEST(rb_class_inherited_p(klass, RBTree)) &&
|
240
|
+
(rb_obj_is_kind_of(argv[0], MultiRBTree) && !rb_obj_is_kind_of(argv[0], RBTree))) {
|
241
|
+
|
242
|
+
rb_raise(rb_eTypeError, "wrong argument type MultiRBTree (expected RBTree)");
|
243
|
+
}
|
244
|
+
|
245
|
+
temp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
|
246
|
+
if (!NIL_P(temp)) {
|
186
247
|
rbtree = rbtree_alloc(klass);
|
187
|
-
|
248
|
+
rb_hash_foreach(temp, hash_to_rbtree_i, rbtree);
|
188
249
|
return rbtree;
|
189
250
|
}
|
190
|
-
|
191
|
-
|
192
|
-
if (!NIL_P(
|
251
|
+
|
252
|
+
temp = rb_check_array_type(argv[0]);
|
253
|
+
if (!NIL_P(temp)) {
|
193
254
|
rbtree = rbtree_alloc(klass);
|
194
|
-
for (i = 0; i <
|
195
|
-
VALUE v = rb_check_array_type(
|
255
|
+
for (i = 0; i < RARRAY_LEN(temp); i++) {
|
256
|
+
VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
|
196
257
|
if (NIL_P(v)) {
|
258
|
+
rb_warn("wrong element type %s at %ld (expected Array)",
|
259
|
+
rb_obj_classname(RARRAY_AREF(temp, i)), i);
|
197
260
|
continue;
|
198
261
|
}
|
199
|
-
switch(
|
262
|
+
switch(RARRAY_LEN(v)) {
|
200
263
|
case 1:
|
201
|
-
rbtree_aset(rbtree,
|
264
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
|
202
265
|
break;
|
203
266
|
case 2:
|
204
|
-
rbtree_aset(rbtree,
|
267
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
|
205
268
|
break;
|
206
269
|
default:
|
207
|
-
|
270
|
+
rb_warn("invalid number of elements (%ld for 1..2)",
|
271
|
+
RARRAY_LEN(v));
|
208
272
|
}
|
209
273
|
}
|
210
274
|
return rbtree;
|
211
275
|
}
|
212
276
|
}
|
213
|
-
|
277
|
+
|
214
278
|
if (argc % 2 != 0)
|
215
|
-
rb_raise(rb_eArgError, "odd number of arguments for
|
279
|
+
rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));
|
216
280
|
|
217
281
|
rbtree = rbtree_alloc(klass);
|
218
282
|
for (i = 0; i < argc; i += 2)
|
@@ -229,15 +293,17 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
|
|
229
293
|
rbtree_modify(self);
|
230
294
|
|
231
295
|
if (rb_block_given_p()) {
|
232
|
-
|
233
|
-
|
234
|
-
|
296
|
+
VALUE proc;
|
297
|
+
rbtree_check_argument_count(argc, 0, 0);
|
298
|
+
proc = rb_block_proc();
|
299
|
+
rbtree_check_proc_arity(proc, 2);
|
300
|
+
IFNONE(self) = proc;
|
235
301
|
FL_SET(self, RBTREE_PROC_DEFAULT);
|
236
302
|
} else {
|
237
|
-
|
238
|
-
|
239
|
-
else if (argc == 1)
|
303
|
+
rbtree_check_argument_count(argc, 0, 1);
|
304
|
+
if (argc == 1) {
|
240
305
|
IFNONE(self) = argv[0];
|
306
|
+
}
|
241
307
|
}
|
242
308
|
return self;
|
243
309
|
}
|
@@ -245,42 +311,50 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
|
|
245
311
|
/*********************************************************************/
|
246
312
|
|
247
313
|
typedef enum {
|
248
|
-
|
249
|
-
|
314
|
+
NoNodeInserted,
|
315
|
+
KeyAllocationFailed,
|
316
|
+
InsertionSucceeded
|
317
|
+
} insert_result_t;
|
250
318
|
|
251
319
|
typedef struct {
|
252
320
|
dict_t* dict;
|
253
321
|
dnode_t* node;
|
254
|
-
|
255
|
-
|
256
|
-
} insert_node_t;
|
322
|
+
insert_result_t result;
|
323
|
+
} rbtree_insert_arg_t;
|
257
324
|
|
258
325
|
static VALUE
|
259
|
-
insert_node_body(
|
326
|
+
insert_node_body(rbtree_insert_arg_t* arg)
|
260
327
|
{
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
328
|
+
dict_t* dict = arg->dict;
|
329
|
+
dnode_t* node = arg->node;
|
330
|
+
|
331
|
+
if (dict_insert(dict, node, dnode_getkey(node))) {
|
332
|
+
if (TYPE(GET_KEY(node)) == T_STRING) {
|
333
|
+
arg->result = KeyAllocationFailed;
|
334
|
+
node->dict_key = TO_KEY(rb_str_new4(GET_KEY(node)));
|
335
|
+
}
|
336
|
+
} else {
|
337
|
+
dict->dict_freenode(node, dict->dict_context);
|
338
|
+
}
|
339
|
+
arg->result = InsertionSucceeded;
|
265
340
|
return Qnil;
|
266
341
|
}
|
267
342
|
|
268
343
|
static VALUE
|
269
|
-
insert_node_ensure(
|
344
|
+
insert_node_ensure(rbtree_insert_arg_t* arg)
|
270
345
|
{
|
271
346
|
dict_t* dict = arg->dict;
|
272
347
|
dnode_t* node = arg->node;
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
break;
|
277
|
-
case NODE_NOT_FOUND:
|
278
|
-
if (TYPE(arg->key) == T_STRING)
|
279
|
-
node->dict_key = TO_KEY(rb_str_new4(GET_KEY(node)));
|
348
|
+
|
349
|
+
switch (arg->result) {
|
350
|
+
case InsertionSucceeded:
|
280
351
|
break;
|
281
|
-
case
|
352
|
+
case NoNodeInserted:
|
282
353
|
dict->dict_freenode(node, dict->dict_context);
|
283
354
|
break;
|
355
|
+
case KeyAllocationFailed:
|
356
|
+
dict_delete_free(dict, node);
|
357
|
+
break;
|
284
358
|
}
|
285
359
|
return Qnil;
|
286
360
|
}
|
@@ -288,16 +362,16 @@ insert_node_ensure(insert_node_t* arg)
|
|
288
362
|
static void
|
289
363
|
rbtree_insert(VALUE self, VALUE key, VALUE value)
|
290
364
|
{
|
291
|
-
|
365
|
+
rbtree_insert_arg_t arg;
|
292
366
|
dict_t* dict = DICT(self);
|
293
367
|
dnode_t* node = dict->dict_allocnode(dict->dict_context);
|
294
368
|
|
295
369
|
dnode_init(node, TO_VAL(value));
|
370
|
+
node->dict_key = TO_KEY(key);
|
296
371
|
|
297
372
|
arg.dict = dict;
|
298
373
|
arg.node = node;
|
299
|
-
arg.
|
300
|
-
arg.ret = INITIAL_VALUE;
|
374
|
+
arg.result = NoNodeInserted;
|
301
375
|
|
302
376
|
rb_ensure(insert_node_body, (VALUE)&arg,
|
303
377
|
insert_node_ensure, (VALUE)&arg);
|
@@ -333,7 +407,7 @@ rbtree_aref(VALUE self, VALUE key)
|
|
333
407
|
{
|
334
408
|
dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
|
335
409
|
if (node == NULL)
|
336
|
-
return
|
410
|
+
return rb_funcall2(self, id_default, 1, &key);
|
337
411
|
else
|
338
412
|
return GET_VAL(node);
|
339
413
|
}
|
@@ -345,22 +419,23 @@ VALUE
|
|
345
419
|
rbtree_fetch(int argc, VALUE* argv, VALUE self)
|
346
420
|
{
|
347
421
|
dnode_t* node;
|
348
|
-
int block_given;
|
349
422
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
rb_warn("block supersedes default value argument");
|
423
|
+
rbtree_check_argument_count(argc, 1, 2);
|
424
|
+
if (argc == 2 && rb_block_given_p()) {
|
425
|
+
rb_warn("block supersedes default value argument");
|
426
|
+
}
|
355
427
|
|
356
428
|
node = dict_lookup(DICT(self), TO_KEY(argv[0]));
|
357
|
-
if (node != NULL)
|
429
|
+
if (node != NULL) {
|
358
430
|
return GET_VAL(node);
|
431
|
+
}
|
359
432
|
|
360
|
-
if (
|
433
|
+
if (rb_block_given_p()) {
|
361
434
|
return rb_yield(argv[0]);
|
362
|
-
|
435
|
+
}
|
436
|
+
if (argc == 1) {
|
363
437
|
rb_raise(rb_eIndexError, "key not found");
|
438
|
+
}
|
364
439
|
return argv[1];
|
365
440
|
}
|
366
441
|
|
@@ -388,15 +463,12 @@ rbtree_empty_p(VALUE self)
|
|
388
463
|
VALUE
|
389
464
|
rbtree_default(int argc, VALUE* argv, VALUE self)
|
390
465
|
{
|
391
|
-
|
392
|
-
if (argc == 1)
|
393
|
-
key = argv[0];
|
394
|
-
else if (argc > 1)
|
395
|
-
rbtree_argc_error();
|
396
|
-
|
466
|
+
rbtree_check_argument_count(argc, 0, 1);
|
397
467
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
|
398
|
-
if (argc == 0)
|
399
|
-
|
468
|
+
if (argc == 0) {
|
469
|
+
return Qnil;
|
470
|
+
}
|
471
|
+
return rb_funcall(IFNONE(self), id_call, 2, self, argv[0]);
|
400
472
|
}
|
401
473
|
return IFNONE(self);
|
402
474
|
}
|
@@ -424,10 +496,54 @@ rbtree_default_proc(VALUE self)
|
|
424
496
|
return Qnil;
|
425
497
|
}
|
426
498
|
|
427
|
-
|
428
|
-
|
499
|
+
/*
|
500
|
+
*
|
501
|
+
*/
|
502
|
+
VALUE
|
503
|
+
rbtree_set_default_proc(VALUE self, VALUE proc)
|
504
|
+
{
|
505
|
+
VALUE temp;
|
506
|
+
|
507
|
+
rbtree_modify(self);
|
508
|
+
if (NIL_P(proc)) {
|
509
|
+
IFNONE(self) = Qnil;
|
510
|
+
FL_UNSET(self, RBTREE_PROC_DEFAULT);
|
511
|
+
return Qnil;
|
512
|
+
}
|
513
|
+
|
514
|
+
temp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
515
|
+
if (NIL_P(temp)) {
|
516
|
+
rb_raise(rb_eTypeError,
|
517
|
+
"wrong default_proc type %s (expected Proc)",
|
518
|
+
rb_obj_classname(proc));
|
519
|
+
}
|
520
|
+
rbtree_check_proc_arity(temp, 2);
|
521
|
+
IFNONE(self) = temp;
|
522
|
+
FL_SET(self, RBTREE_PROC_DEFAULT);
|
523
|
+
return proc;
|
524
|
+
}
|
525
|
+
|
526
|
+
static VALUE
|
527
|
+
rbtree_recursive_equal(VALUE self, VALUE other, int recursive)
|
429
528
|
{
|
430
|
-
|
529
|
+
dict_t* dict1 = DICT(self);
|
530
|
+
dict_t* dict2 = DICT(other);
|
531
|
+
dnode_t* node1;
|
532
|
+
dnode_t* node2;
|
533
|
+
|
534
|
+
if (recursive)
|
535
|
+
return Qtrue;
|
536
|
+
for (node1 = dict_first(dict1), node2 = dict_first(dict2);
|
537
|
+
node1 != NULL && node2 != NULL;
|
538
|
+
node1 = dict_next(dict1, node1), node2 = dict_next(dict2, node2)) {
|
539
|
+
|
540
|
+
if (!rb_equal(GET_KEY(node1), GET_KEY(node2)) ||
|
541
|
+
!rb_equal(GET_VAL(node1), GET_VAL(node2))) {
|
542
|
+
|
543
|
+
return Qfalse;
|
544
|
+
}
|
545
|
+
}
|
546
|
+
return Qtrue;
|
431
547
|
}
|
432
548
|
|
433
549
|
/*
|
@@ -436,13 +552,23 @@ value_eq(const void* key1, const void* key2)
|
|
436
552
|
VALUE
|
437
553
|
rbtree_equal(VALUE self, VALUE other)
|
438
554
|
{
|
439
|
-
int ret;
|
440
555
|
if (self == other)
|
441
556
|
return Qtrue;
|
442
557
|
if (!rb_obj_is_kind_of(other, MultiRBTree))
|
443
558
|
return Qfalse;
|
444
|
-
|
445
|
-
|
559
|
+
if (dict_count(DICT(self)) != dict_count(DICT(other)) ||
|
560
|
+
DICT(self)->dict_compare != DICT(other)->dict_compare ||
|
561
|
+
CMP_PROC(self) != CMP_PROC(other)) {
|
562
|
+
|
563
|
+
return Qfalse;
|
564
|
+
}
|
565
|
+
#if defined(HAVE_RB_EXEC_RECURSIVE_PAIRED)
|
566
|
+
return rb_exec_recursive_paired(rbtree_recursive_equal, self, other, other);
|
567
|
+
#elif defined(HAVE_RB_EXEC_RECURSIVE)
|
568
|
+
return rb_exec_recursive(rbtree_recursive_equal, self, other);
|
569
|
+
#else
|
570
|
+
return rbtree_recursive_equal(self, other, 0);
|
571
|
+
#endif
|
446
572
|
}
|
447
573
|
|
448
574
|
/*********************************************************************/
|
@@ -475,7 +601,7 @@ rbtree_each_body(rbtree_each_arg_t* arg)
|
|
475
601
|
dnode_t* node;
|
476
602
|
dnode_t* first_node;
|
477
603
|
dnode_t* (*next_func)(dict_t*, dnode_t*);
|
478
|
-
|
604
|
+
|
479
605
|
if (arg->reverse) {
|
480
606
|
first_node = dict_last(dict);
|
481
607
|
next_func = dict_prev;
|
@@ -483,12 +609,12 @@ rbtree_each_body(rbtree_each_arg_t* arg)
|
|
483
609
|
first_node = dict_first(dict);
|
484
610
|
next_func = dict_next;
|
485
611
|
}
|
486
|
-
|
612
|
+
|
487
613
|
ITER_LEV(self)++;
|
488
614
|
for (node = first_node;
|
489
615
|
node != NULL;
|
490
616
|
node = next_func(dict, node)) {
|
491
|
-
|
617
|
+
|
492
618
|
if (arg->func(node, arg->arg) == EACH_STOP)
|
493
619
|
break;
|
494
620
|
}
|
@@ -521,45 +647,29 @@ rbtree_reverse_for_each(VALUE self, each_callback_func func, void* arg)
|
|
521
647
|
|
522
648
|
/*********************************************************************/
|
523
649
|
|
524
|
-
static each_return_t
|
525
|
-
each_i(dnode_t* node, void* arg)
|
526
|
-
{
|
527
|
-
rb_yield(ASSOC(node));
|
528
|
-
return EACH_NEXT;
|
529
|
-
}
|
530
|
-
|
531
|
-
/*
|
532
|
-
* call-seq:
|
533
|
-
* rbtree.each {|key, value| block} => rbtree
|
534
|
-
*
|
535
|
-
* Calls block once for each key in order, passing the key and value
|
536
|
-
* as a two-element array parameters.
|
537
|
-
*/
|
538
|
-
VALUE
|
539
|
-
rbtree_each(VALUE self)
|
540
|
-
{
|
541
|
-
RETURN_ENUMERATOR(self, 0, NULL);
|
542
|
-
return rbtree_for_each(self, each_i, NULL);
|
543
|
-
}
|
544
|
-
|
545
650
|
static each_return_t
|
546
651
|
each_pair_i(dnode_t* node, void* arg)
|
547
652
|
{
|
548
|
-
|
653
|
+
rb_yield(ASSOC(node));
|
549
654
|
return EACH_NEXT;
|
550
655
|
}
|
551
656
|
|
552
657
|
/*
|
553
658
|
* call-seq:
|
659
|
+
* rbtree.each {|key, value| block} => rbtree
|
554
660
|
* rbtree.each_pair {|key, value| block} => rbtree
|
661
|
+
* rbtree.each => enumerator
|
662
|
+
* rbtree.each_pair => enumerator
|
555
663
|
*
|
556
|
-
* Calls block once for each key in order, passing the key
|
664
|
+
* Calls block once for each key in order, passing the key-value pair
|
557
665
|
* as parameters.
|
666
|
+
*
|
667
|
+
* Returns an enumerator if no block is given.
|
558
668
|
*/
|
559
669
|
VALUE
|
560
670
|
rbtree_each_pair(VALUE self)
|
561
671
|
{
|
562
|
-
|
672
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
563
673
|
return rbtree_for_each(self, each_pair_i, NULL);
|
564
674
|
}
|
565
675
|
|
@@ -573,14 +683,17 @@ each_key_i(dnode_t* node, void* arg)
|
|
573
683
|
/*
|
574
684
|
* call-seq:
|
575
685
|
* rbtree.each_key {|key| block} => rbtree
|
686
|
+
* rbtree.each_key => enumerator
|
687
|
+
*
|
688
|
+
* Calls block once for each key in order, passing the key as a
|
689
|
+
* parameter.
|
576
690
|
*
|
577
|
-
*
|
578
|
-
* parameters.
|
691
|
+
* Returns an enumerator if no block is given.
|
579
692
|
*/
|
580
693
|
VALUE
|
581
694
|
rbtree_each_key(VALUE self)
|
582
695
|
{
|
583
|
-
|
696
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
584
697
|
return rbtree_for_each(self, each_key_i, NULL);
|
585
698
|
}
|
586
699
|
|
@@ -594,28 +707,34 @@ each_value_i(dnode_t* node, void* arg)
|
|
594
707
|
/*
|
595
708
|
* call-seq:
|
596
709
|
* rbtree.each_value {|value| block} => rbtree
|
710
|
+
* rbtree.each_value => enumerator
|
711
|
+
*
|
712
|
+
* Calls block once for each key in order, passing the value as a
|
713
|
+
* parameter.
|
597
714
|
*
|
598
|
-
*
|
599
|
-
* parameters.
|
715
|
+
* Returns an enumerator if no block is given.
|
600
716
|
*/
|
601
717
|
VALUE
|
602
718
|
rbtree_each_value(VALUE self)
|
603
719
|
{
|
604
|
-
|
720
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
605
721
|
return rbtree_for_each(self, each_value_i, NULL);
|
606
722
|
}
|
607
723
|
|
608
724
|
/*
|
609
725
|
* call-seq:
|
610
726
|
* rbtree.reverse_each {|key, value| block} => rbtree
|
727
|
+
* rbtree.reverse_each => enumerator
|
611
728
|
*
|
612
|
-
* Calls block once for each key in reverse order, passing the
|
613
|
-
* value as parameters.
|
729
|
+
* Calls block once for each key in reverse order, passing the
|
730
|
+
* key-value pair as parameters.
|
731
|
+
*
|
732
|
+
* Returns an enumerator if no block is given.
|
614
733
|
*/
|
615
734
|
VALUE
|
616
735
|
rbtree_reverse_each(VALUE self)
|
617
736
|
{
|
618
|
-
|
737
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
619
738
|
return rbtree_reverse_for_each(self, each_pair_i, NULL);
|
620
739
|
}
|
621
740
|
|
@@ -627,11 +746,17 @@ aset_i(dnode_t* node, void* self)
|
|
627
746
|
}
|
628
747
|
|
629
748
|
static void
|
630
|
-
copy_dict(VALUE src, VALUE dest, dict_comp_t
|
749
|
+
copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
|
631
750
|
{
|
632
751
|
VALUE temp = rbtree_alloc(CLASS_OF(dest));
|
633
|
-
|
634
|
-
|
752
|
+
#ifdef HAVE_RB_OBJ_HIDE
|
753
|
+
rb_obj_hide(temp);
|
754
|
+
#else
|
755
|
+
RBASIC(temp)->klass = 0;
|
756
|
+
#endif
|
757
|
+
DICT(temp)->dict_compare = cmp_func;
|
758
|
+
CMP_PROC(temp) = cmp_proc;
|
759
|
+
|
635
760
|
rbtree_for_each(src, aset_i, (void*)temp);
|
636
761
|
{
|
637
762
|
dict_t* t = DICT(temp);
|
@@ -639,7 +764,11 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
|
|
639
764
|
DICT(dest) = t;
|
640
765
|
}
|
641
766
|
rbtree_free(RBTREE(temp));
|
767
|
+
RBTREE(temp) = NULL;
|
642
768
|
rb_gc_force_recycle(temp);
|
769
|
+
|
770
|
+
DICT(dest)->dict_context = RBTREE(dest);
|
771
|
+
CMP_PROC(dest) = cmp_proc;
|
643
772
|
}
|
644
773
|
|
645
774
|
/*
|
@@ -648,16 +777,18 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
|
|
648
777
|
VALUE
|
649
778
|
rbtree_initialize_copy(VALUE self, VALUE other)
|
650
779
|
{
|
780
|
+
rbtree_modify(self);
|
781
|
+
|
651
782
|
if (self == other)
|
652
783
|
return self;
|
653
784
|
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
654
785
|
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
655
|
-
|
656
|
-
|
786
|
+
rb_obj_classname(other),
|
787
|
+
rb_obj_classname(self));
|
657
788
|
}
|
658
|
-
|
659
|
-
copy_dict(other, self,
|
660
|
-
|
789
|
+
|
790
|
+
copy_dict(other, self, DICT(other)->dict_compare, CMP_PROC(other));
|
791
|
+
|
661
792
|
IFNONE(self) = IFNONE(other);
|
662
793
|
if (FL_TEST(other, RBTREE_PROC_DEFAULT))
|
663
794
|
FL_SET(self, RBTREE_PROC_DEFAULT);
|
@@ -673,18 +804,21 @@ VALUE
|
|
673
804
|
rbtree_values_at(int argc, VALUE* argv, VALUE self)
|
674
805
|
{
|
675
806
|
long i;
|
676
|
-
VALUE ary =
|
677
|
-
|
807
|
+
VALUE ary = rb_ary_new2(argc);
|
808
|
+
|
678
809
|
for (i = 0; i < argc; i++)
|
679
810
|
rb_ary_push(ary, rbtree_aref(self, argv[i]));
|
680
811
|
return ary;
|
681
812
|
}
|
682
813
|
|
683
814
|
static each_return_t
|
684
|
-
|
815
|
+
key_i(dnode_t* node, void* args_)
|
685
816
|
{
|
686
|
-
|
687
|
-
|
817
|
+
VALUE* args = (VALUE*)args_;
|
818
|
+
if (rb_equal(GET_VAL(node), args[1])) {
|
819
|
+
args[0] = GET_KEY(node);
|
820
|
+
return EACH_STOP;
|
821
|
+
}
|
688
822
|
return EACH_NEXT;
|
689
823
|
}
|
690
824
|
|
@@ -692,25 +826,13 @@ select_i(dnode_t* node, void* ary)
|
|
692
826
|
*
|
693
827
|
*/
|
694
828
|
VALUE
|
695
|
-
|
696
|
-
{
|
697
|
-
VALUE ary;
|
698
|
-
|
699
|
-
RETURN_ENUMERATOR(self, 0, NULL);
|
700
|
-
ary = rb_ary_new();
|
701
|
-
rbtree_for_each(self, select_i, (void*)ary);
|
702
|
-
return ary;
|
703
|
-
}
|
704
|
-
|
705
|
-
static each_return_t
|
706
|
-
index_i(dnode_t* node, void* arg_)
|
829
|
+
rbtree_key(VALUE self, VALUE value)
|
707
830
|
{
|
708
|
-
VALUE
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
return EACH_NEXT;
|
831
|
+
VALUE args[2];
|
832
|
+
args[0] = Qnil;
|
833
|
+
args[1] = value;
|
834
|
+
rbtree_for_each(self, key_i, &args);
|
835
|
+
return args[0];
|
714
836
|
}
|
715
837
|
|
716
838
|
/*
|
@@ -719,11 +841,10 @@ index_i(dnode_t* node, void* arg_)
|
|
719
841
|
VALUE
|
720
842
|
rbtree_index(VALUE self, VALUE value)
|
721
843
|
{
|
722
|
-
VALUE
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
return arg[0];
|
844
|
+
VALUE klass = rb_obj_is_kind_of(self, RBTree) ? RBTree : MultiRBTree;
|
845
|
+
const char* classname = rb_class2name(klass);
|
846
|
+
rb_warn("%s#index is deprecated; use %s#key", classname, classname);
|
847
|
+
return rbtree_key(self, value);
|
727
848
|
}
|
728
849
|
|
729
850
|
/*
|
@@ -767,10 +888,11 @@ typedef struct {
|
|
767
888
|
VALUE self;
|
768
889
|
dnode_list_t* list;
|
769
890
|
int raised;
|
770
|
-
|
891
|
+
int if_true;
|
892
|
+
} rbtree_remove_if_arg_t;
|
771
893
|
|
772
894
|
static VALUE
|
773
|
-
|
895
|
+
rbtree_remove_if_ensure(rbtree_remove_if_arg_t* arg)
|
774
896
|
{
|
775
897
|
dict_t* dict = DICT(arg->self);
|
776
898
|
dnode_list_t* list = arg->list;
|
@@ -788,7 +910,7 @@ rbtree_delete_if_ensure(rbtree_delete_if_arg_t* arg)
|
|
788
910
|
}
|
789
911
|
|
790
912
|
static VALUE
|
791
|
-
|
913
|
+
rbtree_remove_if_body(rbtree_remove_if_arg_t* arg)
|
792
914
|
{
|
793
915
|
VALUE self = arg->self;
|
794
916
|
dict_t* dict = DICT(self);
|
@@ -800,7 +922,9 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
800
922
|
node != NULL;
|
801
923
|
node = dict_next(dict, node)) {
|
802
924
|
|
803
|
-
|
925
|
+
VALUE key = GET_KEY(node);
|
926
|
+
VALUE value = GET_VAL(node);
|
927
|
+
if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
|
804
928
|
dnode_list_t* l = ALLOC(dnode_list_t);
|
805
929
|
l->node = node;
|
806
930
|
l->prev = arg->list;
|
@@ -811,6 +935,20 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
811
935
|
return self;
|
812
936
|
}
|
813
937
|
|
938
|
+
static VALUE
|
939
|
+
rbtree_remove_if(VALUE self, const int if_true)
|
940
|
+
{
|
941
|
+
rbtree_remove_if_arg_t arg;
|
942
|
+
|
943
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
944
|
+
rbtree_modify(self);
|
945
|
+
arg.self = self;
|
946
|
+
arg.list = NULL;
|
947
|
+
arg.if_true = if_true;
|
948
|
+
return rb_ensure(rbtree_remove_if_body, (VALUE)&arg,
|
949
|
+
rbtree_remove_if_ensure, (VALUE)&arg);
|
950
|
+
}
|
951
|
+
|
814
952
|
/*********************************************************************/
|
815
953
|
|
816
954
|
/*
|
@@ -819,14 +957,16 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
819
957
|
VALUE
|
820
958
|
rbtree_delete_if(VALUE self)
|
821
959
|
{
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
960
|
+
return rbtree_remove_if(self, 1);
|
961
|
+
}
|
962
|
+
|
963
|
+
/*
|
964
|
+
*
|
965
|
+
*/
|
966
|
+
VALUE
|
967
|
+
rbtree_keep_if(VALUE self)
|
968
|
+
{
|
969
|
+
return rbtree_remove_if(self, 0);
|
830
970
|
}
|
831
971
|
|
832
972
|
/*
|
@@ -836,8 +976,8 @@ VALUE
|
|
836
976
|
rbtree_reject_bang(VALUE self)
|
837
977
|
{
|
838
978
|
dictcount_t count;
|
839
|
-
|
840
|
-
|
979
|
+
|
980
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
841
981
|
count = dict_count(DICT(self));
|
842
982
|
rbtree_delete_if(self);
|
843
983
|
if (count == dict_count(DICT(self)))
|
@@ -845,13 +985,73 @@ rbtree_reject_bang(VALUE self)
|
|
845
985
|
return self;
|
846
986
|
}
|
847
987
|
|
988
|
+
/*
|
989
|
+
*
|
990
|
+
*/
|
991
|
+
VALUE
|
992
|
+
rbtree_select_bang(VALUE self)
|
993
|
+
{
|
994
|
+
dictcount_t count;
|
995
|
+
|
996
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
997
|
+
count = dict_count(DICT(self));
|
998
|
+
rbtree_keep_if(self);
|
999
|
+
if (count == dict_count(DICT(self)))
|
1000
|
+
return Qnil;
|
1001
|
+
return self;
|
1002
|
+
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
/*********************************************************************/
|
1006
|
+
|
1007
|
+
typedef struct {
|
1008
|
+
VALUE result;
|
1009
|
+
int if_true;
|
1010
|
+
} rbtree_select_if_arg_t;
|
1011
|
+
|
1012
|
+
static each_return_t
|
1013
|
+
select_i(dnode_t* node, void* arg_)
|
1014
|
+
{
|
1015
|
+
VALUE key = GET_KEY(node);
|
1016
|
+
VALUE value = GET_VAL(node);
|
1017
|
+
rbtree_select_if_arg_t* arg = arg_;
|
1018
|
+
|
1019
|
+
if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
|
1020
|
+
rbtree_aset(arg->result, key, value);
|
1021
|
+
}
|
1022
|
+
return EACH_NEXT;
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
static VALUE
|
1026
|
+
rbtree_select_if(VALUE self, const int if_true)
|
1027
|
+
{
|
1028
|
+
rbtree_select_if_arg_t arg;
|
1029
|
+
|
1030
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
1031
|
+
arg.result = rbtree_alloc(CLASS_OF(self));
|
1032
|
+
arg.if_true = if_true;
|
1033
|
+
rbtree_for_each(self, select_i, &arg);
|
1034
|
+
return arg.result;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
/*********************************************************************/
|
1038
|
+
|
848
1039
|
/*
|
849
1040
|
*
|
850
1041
|
*/
|
851
1042
|
VALUE
|
852
1043
|
rbtree_reject(VALUE self)
|
853
1044
|
{
|
854
|
-
return
|
1045
|
+
return rbtree_select_if(self, 0);
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
/*
|
1049
|
+
*
|
1050
|
+
*/
|
1051
|
+
VALUE
|
1052
|
+
rbtree_select(VALUE self)
|
1053
|
+
{
|
1054
|
+
return rbtree_select_if(self, 1);
|
855
1055
|
}
|
856
1056
|
|
857
1057
|
static VALUE
|
@@ -859,32 +1059,28 @@ rbtree_shift_pop(VALUE self, const int shift)
|
|
859
1059
|
{
|
860
1060
|
dict_t* dict = DICT(self);
|
861
1061
|
dnode_t* node;
|
862
|
-
VALUE
|
1062
|
+
VALUE assoc;
|
863
1063
|
|
864
1064
|
rbtree_modify(self);
|
865
1065
|
|
866
|
-
if (dict_isempty(dict))
|
867
|
-
|
868
|
-
return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
|
869
|
-
}
|
870
|
-
return IFNONE(self);
|
871
|
-
}
|
1066
|
+
if (dict_isempty(dict))
|
1067
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
872
1068
|
|
873
1069
|
if (shift)
|
874
1070
|
node = dict_last(dict);
|
875
1071
|
else
|
876
1072
|
node = dict_first(dict);
|
877
|
-
|
1073
|
+
assoc = ASSOC(node);
|
878
1074
|
dict_delete_free(dict, node);
|
879
|
-
return
|
1075
|
+
return assoc;
|
880
1076
|
}
|
881
1077
|
|
882
1078
|
/*
|
883
1079
|
* call-seq:
|
884
|
-
* rbtree.shift => array or object
|
1080
|
+
* rbtree.shift => array or object or nil
|
885
1081
|
*
|
886
|
-
* Removes the first(that is, the smallest) key-value pair and
|
887
|
-
* it
|
1082
|
+
* Removes the first (that is, the smallest) key-value pair and
|
1083
|
+
* returns it.
|
888
1084
|
*/
|
889
1085
|
VALUE
|
890
1086
|
rbtree_shift(VALUE self)
|
@@ -894,10 +1090,10 @@ rbtree_shift(VALUE self)
|
|
894
1090
|
|
895
1091
|
/*
|
896
1092
|
* call-seq:
|
897
|
-
* rbtree.pop => array or object
|
1093
|
+
* rbtree.pop => array or object or nil
|
898
1094
|
*
|
899
|
-
* Removes the last(that is, the
|
900
|
-
* it
|
1095
|
+
* Removes the last (that is, the greatest) key-value pair and returns
|
1096
|
+
* it.
|
901
1097
|
*/
|
902
1098
|
VALUE
|
903
1099
|
rbtree_pop(VALUE self)
|
@@ -948,10 +1144,10 @@ rbtree_update(VALUE self, VALUE other)
|
|
948
1144
|
return self;
|
949
1145
|
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
950
1146
|
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
951
|
-
|
952
|
-
|
1147
|
+
rb_obj_classname(other),
|
1148
|
+
rb_obj_classname(self));
|
953
1149
|
}
|
954
|
-
|
1150
|
+
|
955
1151
|
if (rb_block_given_p())
|
956
1152
|
rbtree_for_each(other, update_block_i, (void*)self);
|
957
1153
|
else
|
@@ -968,6 +1164,35 @@ rbtree_merge(VALUE self, VALUE other)
|
|
968
1164
|
return rbtree_update(rb_obj_dup(self), other);
|
969
1165
|
}
|
970
1166
|
|
1167
|
+
static each_return_t
|
1168
|
+
to_flat_ary_i(dnode_t* node, void* ary)
|
1169
|
+
{
|
1170
|
+
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1171
|
+
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1172
|
+
return EACH_NEXT;
|
1173
|
+
}
|
1174
|
+
|
1175
|
+
/*
|
1176
|
+
*
|
1177
|
+
*/
|
1178
|
+
VALUE
|
1179
|
+
rbtree_flatten(int argc, VALUE* argv, VALUE self)
|
1180
|
+
{
|
1181
|
+
VALUE ary;
|
1182
|
+
|
1183
|
+
rbtree_check_argument_count(argc, 0, 1);
|
1184
|
+
ary = rb_ary_new2(dict_count(DICT(self)) * 2);
|
1185
|
+
rbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1186
|
+
if (argc == 1) {
|
1187
|
+
const int level = NUM2INT(argv[0]) - 1;
|
1188
|
+
if (level > 0) {
|
1189
|
+
argv[0] = INT2FIX(level);
|
1190
|
+
rb_funcall2(ary, id_flatten_bang, argc, argv);
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
return ary;
|
1194
|
+
}
|
1195
|
+
|
971
1196
|
/*
|
972
1197
|
*
|
973
1198
|
*/
|
@@ -978,11 +1203,11 @@ rbtree_has_key(VALUE self, VALUE key)
|
|
978
1203
|
}
|
979
1204
|
|
980
1205
|
static each_return_t
|
981
|
-
has_value_i(dnode_t* node, void*
|
1206
|
+
has_value_i(dnode_t* node, void* args_)
|
982
1207
|
{
|
983
|
-
VALUE*
|
984
|
-
if (rb_equal(GET_VAL(node),
|
985
|
-
|
1208
|
+
VALUE* args = (VALUE*)args_;
|
1209
|
+
if (rb_equal(GET_VAL(node), args[1])) {
|
1210
|
+
args[0] = Qtrue;
|
986
1211
|
return EACH_STOP;
|
987
1212
|
}
|
988
1213
|
return EACH_NEXT;
|
@@ -994,11 +1219,11 @@ has_value_i(dnode_t* node, void* arg_)
|
|
994
1219
|
VALUE
|
995
1220
|
rbtree_has_value(VALUE self, VALUE value)
|
996
1221
|
{
|
997
|
-
VALUE
|
998
|
-
|
999
|
-
|
1000
|
-
rbtree_for_each(self, has_value_i,
|
1001
|
-
return
|
1222
|
+
VALUE args[2];
|
1223
|
+
args[0] = Qfalse;
|
1224
|
+
args[1] = value;
|
1225
|
+
rbtree_for_each(self, has_value_i, &args);
|
1226
|
+
return args[0];
|
1002
1227
|
}
|
1003
1228
|
|
1004
1229
|
static each_return_t
|
@@ -1014,7 +1239,7 @@ keys_i(dnode_t* node, void* ary)
|
|
1014
1239
|
VALUE
|
1015
1240
|
rbtree_keys(VALUE self)
|
1016
1241
|
{
|
1017
|
-
VALUE ary =
|
1242
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1018
1243
|
rbtree_for_each(self, keys_i, (void*)ary);
|
1019
1244
|
return ary;
|
1020
1245
|
}
|
@@ -1032,9 +1257,9 @@ values_i(dnode_t* node, void* ary)
|
|
1032
1257
|
VALUE
|
1033
1258
|
rbtree_values(VALUE self)
|
1034
1259
|
{
|
1035
|
-
VALUE
|
1036
|
-
rbtree_for_each(self, values_i, (void*)
|
1037
|
-
return
|
1260
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1261
|
+
rbtree_for_each(self, values_i, (void*)ary);
|
1262
|
+
return ary;
|
1038
1263
|
}
|
1039
1264
|
|
1040
1265
|
static each_return_t
|
@@ -1050,7 +1275,7 @@ to_a_i(dnode_t* node, void* ary)
|
|
1050
1275
|
VALUE
|
1051
1276
|
rbtree_to_a(VALUE self)
|
1052
1277
|
{
|
1053
|
-
VALUE ary =
|
1278
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1054
1279
|
rbtree_for_each(self, to_a_i, (void*)ary);
|
1055
1280
|
OBJ_INFECT(ary, self);
|
1056
1281
|
return ary;
|
@@ -1059,7 +1284,7 @@ rbtree_to_a(VALUE self)
|
|
1059
1284
|
static each_return_t
|
1060
1285
|
to_hash_i(dnode_t* node, void* hash)
|
1061
1286
|
{
|
1062
|
-
|
1287
|
+
rb_hash_aset((VALUE)hash, GET_KEY(node), GET_VAL(node));
|
1063
1288
|
return EACH_NEXT;
|
1064
1289
|
}
|
1065
1290
|
|
@@ -1070,13 +1295,12 @@ VALUE
|
|
1070
1295
|
rbtree_to_hash(VALUE self)
|
1071
1296
|
{
|
1072
1297
|
VALUE hash;
|
1073
|
-
if (
|
1298
|
+
if (!rb_obj_is_kind_of(self, RBTree))
|
1074
1299
|
rb_raise(rb_eTypeError, "can't convert MultiRBTree to Hash");
|
1075
|
-
|
1076
|
-
|
1300
|
+
|
1077
1301
|
hash = rb_hash_new();
|
1078
1302
|
rbtree_for_each(self, to_hash_i, (void*)hash);
|
1079
|
-
|
1303
|
+
RHASH_SET_IFNONE(hash, IFNONE(self));
|
1080
1304
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
1081
1305
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
1082
1306
|
OBJ_INFECT(hash, self);
|
@@ -1095,78 +1319,69 @@ rbtree_to_rbtree(VALUE self)
|
|
1095
1319
|
static VALUE
|
1096
1320
|
rbtree_begin_inspect(VALUE self)
|
1097
1321
|
{
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
return str;
|
1103
|
-
}
|
1104
|
-
|
1105
|
-
static VALUE
|
1106
|
-
to_s_rbtree(VALUE self, VALUE nil)
|
1107
|
-
{
|
1108
|
-
return rb_ary_to_s(rbtree_to_a(self));
|
1109
|
-
}
|
1110
|
-
|
1111
|
-
/*
|
1112
|
-
*
|
1113
|
-
*/
|
1114
|
-
VALUE
|
1115
|
-
rbtree_to_s(VALUE self)
|
1116
|
-
{
|
1117
|
-
if (rb_inspecting_p(self))
|
1118
|
-
return rb_str_cat2(rbtree_begin_inspect(self), "...>");
|
1119
|
-
return rb_protect_inspect(to_s_rbtree, self, Qnil);
|
1322
|
+
VALUE result = rb_str_new2("#<");
|
1323
|
+
rb_str_cat2(result, rb_obj_classname(self));
|
1324
|
+
rb_str_cat2(result, ": ");
|
1325
|
+
return result;
|
1120
1326
|
}
|
1121
1327
|
|
1122
1328
|
static each_return_t
|
1123
|
-
inspect_i(dnode_t* node, void*
|
1329
|
+
inspect_i(dnode_t* node, void* result_)
|
1124
1330
|
{
|
1125
|
-
VALUE
|
1331
|
+
VALUE result = (VALUE)result_;
|
1126
1332
|
VALUE str;
|
1127
1333
|
|
1128
|
-
if (
|
1129
|
-
|
1334
|
+
if (RSTRING_PTR(result)[0] == '-')
|
1335
|
+
RSTRING_PTR(result)[0] = '#';
|
1130
1336
|
else
|
1131
|
-
rb_str_cat2(
|
1337
|
+
rb_str_cat2(result, ", ");
|
1132
1338
|
|
1133
1339
|
str = rb_inspect(GET_KEY(node));
|
1134
|
-
rb_str_append(
|
1135
|
-
OBJ_INFECT(
|
1340
|
+
rb_str_append(result, str);
|
1341
|
+
OBJ_INFECT(result, str);
|
1136
1342
|
|
1137
|
-
rb_str_cat2(
|
1343
|
+
rb_str_cat2(result, "=>");
|
1138
1344
|
|
1139
1345
|
str = rb_inspect(GET_VAL(node));
|
1140
|
-
rb_str_append(
|
1141
|
-
OBJ_INFECT(
|
1346
|
+
rb_str_append(result, str);
|
1347
|
+
OBJ_INFECT(result, str);
|
1142
1348
|
|
1143
1349
|
return EACH_NEXT;
|
1144
1350
|
}
|
1145
1351
|
|
1146
1352
|
static VALUE
|
1147
|
-
inspect_rbtree(VALUE self, VALUE
|
1353
|
+
inspect_rbtree(VALUE self, VALUE result)
|
1148
1354
|
{
|
1149
1355
|
VALUE str;
|
1150
|
-
|
1151
|
-
rb_str_cat2(
|
1152
|
-
|
1153
|
-
rbtree_for_each(self, inspect_i, (void*)
|
1154
|
-
|
1155
|
-
rb_str_cat2(
|
1356
|
+
|
1357
|
+
rb_str_cat2(result, "{");
|
1358
|
+
RSTRING_PTR(result)[0] = '-';
|
1359
|
+
rbtree_for_each(self, inspect_i, (void*)result);
|
1360
|
+
RSTRING_PTR(result)[0] = '#';
|
1361
|
+
rb_str_cat2(result, "}");
|
1156
1362
|
|
1157
1363
|
str = rb_inspect(IFNONE(self));
|
1158
|
-
rb_str_cat2(
|
1159
|
-
rb_str_append(
|
1160
|
-
OBJ_INFECT(
|
1161
|
-
|
1162
|
-
str = rb_inspect((
|
1163
|
-
rb_str_cat2(
|
1164
|
-
rb_str_append(
|
1165
|
-
OBJ_INFECT(
|
1364
|
+
rb_str_cat2(result, ", default=");
|
1365
|
+
rb_str_append(result, str);
|
1366
|
+
OBJ_INFECT(result, str);
|
1367
|
+
|
1368
|
+
str = rb_inspect(CMP_PROC(self));
|
1369
|
+
rb_str_cat2(result, ", cmp_proc=");
|
1370
|
+
rb_str_append(result, str);
|
1371
|
+
OBJ_INFECT(result, str);
|
1166
1372
|
|
1167
|
-
rb_str_cat2(
|
1168
|
-
OBJ_INFECT(
|
1169
|
-
return
|
1373
|
+
rb_str_cat2(result, ">");
|
1374
|
+
OBJ_INFECT(result, self);
|
1375
|
+
return result;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
static VALUE
|
1379
|
+
rbtree_inspect_recursive(VALUE self, VALUE arg, int recursive)
|
1380
|
+
{
|
1381
|
+
VALUE str = rbtree_begin_inspect(self);
|
1382
|
+
if (recursive)
|
1383
|
+
return rb_str_cat2(str, "...>");
|
1384
|
+
return inspect_rbtree(self, str);
|
1170
1385
|
}
|
1171
1386
|
|
1172
1387
|
/*
|
@@ -1175,19 +1390,32 @@ inspect_rbtree(VALUE self, VALUE ret)
|
|
1175
1390
|
VALUE
|
1176
1391
|
rbtree_inspect(VALUE self)
|
1177
1392
|
{
|
1393
|
+
#ifdef HAVE_RB_EXEC_RECURSIVE
|
1394
|
+
return rb_exec_recursive(rbtree_inspect_recursive, self, Qnil);
|
1395
|
+
#else
|
1178
1396
|
VALUE str = rbtree_begin_inspect(self);
|
1179
1397
|
if (rb_inspecting_p(self))
|
1180
1398
|
return rb_str_cat2(str, "...>");
|
1181
1399
|
return rb_protect_inspect(inspect_rbtree, self, str);
|
1400
|
+
#endif
|
1182
1401
|
}
|
1183
1402
|
|
1184
1403
|
/*
|
1185
1404
|
* call-seq:
|
1186
|
-
* rbtree.lower_bound(key) => array
|
1405
|
+
* rbtree.lower_bound(key) => array or nil
|
1187
1406
|
*
|
1188
|
-
* Retruns key-value pair corresponding to the lowest key that is
|
1189
|
-
* equal to or greater than the given key(inside
|
1407
|
+
* Retruns the key-value pair corresponding to the lowest key that is
|
1408
|
+
* equal to or greater than the given key (inside the lower
|
1190
1409
|
* boundary). If there is no such key, returns nil.
|
1410
|
+
*
|
1411
|
+
* rbtree = RBTree["az", 10, "ba", 20]
|
1412
|
+
* rbtree.lower_bound("ba") # => ["ba", 20]
|
1413
|
+
*
|
1414
|
+
* # "ba" is the lowest key that is greater than "b"
|
1415
|
+
* rbtree.lower_bound("b") # => ["ba", 20]
|
1416
|
+
*
|
1417
|
+
* # no key that is equal to or greater than "c"
|
1418
|
+
* rbtree.lower_bound("c") # => nil
|
1191
1419
|
*/
|
1192
1420
|
VALUE
|
1193
1421
|
rbtree_lower_bound(VALUE self, VALUE key)
|
@@ -1200,11 +1428,20 @@ rbtree_lower_bound(VALUE self, VALUE key)
|
|
1200
1428
|
|
1201
1429
|
/*
|
1202
1430
|
* call-seq:
|
1203
|
-
* rbtree.upper_bound(key) => array
|
1431
|
+
* rbtree.upper_bound(key) => array or nil
|
1432
|
+
*
|
1433
|
+
* Retruns the key-value pair corresponding to the greatest key that
|
1434
|
+
* is equal to or lower than the given key (inside the upper
|
1435
|
+
* boundary). If there is no such key, returns nil.
|
1436
|
+
*
|
1437
|
+
* rbtree = RBTree["az", 10, "ba", 20]
|
1438
|
+
* rbtree.upper_bound("ba") # => ["ba", 20]
|
1439
|
+
*
|
1440
|
+
* # "az" is the greatest key that is lower than "b"
|
1441
|
+
* rbtree.upper_bound("b") # => ["az", 10]
|
1204
1442
|
*
|
1205
|
-
*
|
1206
|
-
*
|
1207
|
-
* there is no such key, returns nil.
|
1443
|
+
* # no key that is equal to or lower than "a"
|
1444
|
+
* rbtree.upper_bound("a") # => nil
|
1208
1445
|
*/
|
1209
1446
|
VALUE
|
1210
1447
|
rbtree_upper_bound(VALUE self, VALUE key)
|
@@ -1221,7 +1458,7 @@ typedef struct {
|
|
1221
1458
|
VALUE self;
|
1222
1459
|
dnode_t* lower_node;
|
1223
1460
|
dnode_t* upper_node;
|
1224
|
-
VALUE
|
1461
|
+
VALUE result;
|
1225
1462
|
} rbtree_bound_arg_t;
|
1226
1463
|
|
1227
1464
|
static VALUE
|
@@ -1232,33 +1469,75 @@ rbtree_bound_body(rbtree_bound_arg_t* arg)
|
|
1232
1469
|
dnode_t* lower_node = arg->lower_node;
|
1233
1470
|
dnode_t* upper_node = arg->upper_node;
|
1234
1471
|
const int block_given = rb_block_given_p();
|
1235
|
-
VALUE
|
1472
|
+
VALUE result = arg->result;
|
1236
1473
|
dnode_t* node;
|
1237
1474
|
|
1238
1475
|
ITER_LEV(self)++;
|
1239
|
-
for (node = lower_node
|
1476
|
+
for (node = lower_node;
|
1477
|
+
node != NULL;
|
1240
1478
|
node = dict_next(dict, node)) {
|
1241
1479
|
|
1242
1480
|
if (block_given)
|
1243
1481
|
rb_yield_values(2, GET_KEY(node), GET_VAL(node));
|
1244
1482
|
else
|
1245
|
-
rb_ary_push(
|
1483
|
+
rb_ary_push(result, ASSOC(node));
|
1246
1484
|
if (node == upper_node)
|
1247
1485
|
break;
|
1248
1486
|
}
|
1249
|
-
return
|
1487
|
+
return result;
|
1488
|
+
}
|
1489
|
+
|
1490
|
+
#ifdef HAVE_SIZED_ENUMERATOR
|
1491
|
+
static VALUE
|
1492
|
+
rbtree_bound_size(VALUE self, VALUE args)
|
1493
|
+
{
|
1494
|
+
VALUE key1 = RARRAY_AREF(args, 0);
|
1495
|
+
VALUE key2 = RARRAY_AREF(args, RARRAY_LEN(args) - 1);
|
1496
|
+
dnode_t* lower_node = dict_lower_bound(DICT(self), TO_KEY(key1));
|
1497
|
+
dnode_t* upper_node = dict_upper_bound(DICT(self), TO_KEY(key2));
|
1498
|
+
dictcount_t count = 0;
|
1499
|
+
dnode_t* node;
|
1500
|
+
|
1501
|
+
if (lower_node == NULL || upper_node == NULL ||
|
1502
|
+
DICT(self)->dict_compare(dnode_getkey(lower_node),
|
1503
|
+
dnode_getkey(upper_node),
|
1504
|
+
DICT(self)->dict_context) > 0) {
|
1505
|
+
return INT2FIX(0);
|
1506
|
+
}
|
1507
|
+
|
1508
|
+
for (node = lower_node;
|
1509
|
+
node != NULL;
|
1510
|
+
node = dict_next(DICT(self), node)) {
|
1511
|
+
|
1512
|
+
count++;
|
1513
|
+
if (node == upper_node) {
|
1514
|
+
break;
|
1515
|
+
}
|
1516
|
+
}
|
1517
|
+
return ULONG2NUM(count);
|
1250
1518
|
}
|
1519
|
+
#endif
|
1251
1520
|
|
1252
1521
|
/*********************************************************************/
|
1253
1522
|
|
1254
1523
|
/*
|
1255
1524
|
* call-seq:
|
1256
|
-
* rbtree.bound(key1, key2 = key1) => array
|
1257
1525
|
* rbtree.bound(key1, key2 = key1) {|key, value| block} => rbtree
|
1526
|
+
* rbtree.bound(key1, key2 = key1) => enumerator
|
1527
|
+
*
|
1528
|
+
* Calls block once for each key between the result of
|
1529
|
+
* rbtree.lower_bound(key1) and rbtree.upper_bound(key2) in order,
|
1530
|
+
* passing the key-value pair as parameters. If the lower bound
|
1531
|
+
* exceeds the upper bound, block is not called.
|
1258
1532
|
*
|
1259
|
-
* Returns an
|
1260
|
-
*
|
1261
|
-
*
|
1533
|
+
* Returns an enumerator if no block is given.
|
1534
|
+
*
|
1535
|
+
* mrbtree = MultiRBTree["az", 10, "ba", 20, "ba", 30, "bz", 40]
|
1536
|
+
* mrbtree.bound("ba").to_a # => [["ba", 20], ["ba", 30]]
|
1537
|
+
* mrbtree.bound("b", "c").to_a # => [["ba", 20], ["ba", 30], ["bz", 40]]
|
1538
|
+
*
|
1539
|
+
* # the lower bound ("ba") exceeds the upper bound ("az")
|
1540
|
+
* mrbtree.bound("b").to_a # => []
|
1262
1541
|
*/
|
1263
1542
|
VALUE
|
1264
1543
|
rbtree_bound(int argc, VALUE* argv, VALUE self)
|
@@ -1266,27 +1545,27 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
|
|
1266
1545
|
dict_t* dict = DICT(self);
|
1267
1546
|
dnode_t* lower_node;
|
1268
1547
|
dnode_t* upper_node;
|
1269
|
-
VALUE
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1548
|
+
VALUE result;
|
1549
|
+
|
1550
|
+
rbtree_check_argument_count(argc, 1, 2);
|
1551
|
+
|
1552
|
+
RETURN_SIZED_ENUMERATOR(self, argc, argv, rbtree_bound_size);
|
1553
|
+
|
1274
1554
|
lower_node = dict_lower_bound(dict, TO_KEY(argv[0]));
|
1275
1555
|
upper_node = dict_upper_bound(dict, TO_KEY(argv[argc - 1]));
|
1276
|
-
|
1277
|
-
|
1556
|
+
result = rb_block_given_p() ? self : rb_ary_new();
|
1557
|
+
|
1278
1558
|
if (lower_node == NULL || upper_node == NULL ||
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
return
|
1559
|
+
DICT(self)->dict_compare(dnode_getkey(lower_node),
|
1560
|
+
dnode_getkey(upper_node),
|
1561
|
+
DICT(self)->dict_context) > 0) {
|
1562
|
+
return result;
|
1283
1563
|
} else {
|
1284
1564
|
rbtree_bound_arg_t arg;
|
1285
1565
|
arg.self = self;
|
1286
1566
|
arg.lower_node = lower_node;
|
1287
1567
|
arg.upper_node = upper_node;
|
1288
|
-
arg.
|
1289
|
-
|
1568
|
+
arg.result = result;
|
1290
1569
|
return rb_ensure(rbtree_bound_body, (VALUE)&arg,
|
1291
1570
|
rbtree_each_ensure, self);
|
1292
1571
|
}
|
@@ -1298,13 +1577,9 @@ rbtree_first_last(VALUE self, const int first)
|
|
1298
1577
|
dict_t* dict = DICT(self);
|
1299
1578
|
dnode_t* node;
|
1300
1579
|
|
1301
|
-
if (dict_isempty(dict))
|
1302
|
-
|
1303
|
-
|
1304
|
-
}
|
1305
|
-
return IFNONE(self);
|
1306
|
-
}
|
1307
|
-
|
1580
|
+
if (dict_isempty(dict))
|
1581
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
1582
|
+
|
1308
1583
|
if (first)
|
1309
1584
|
node = dict_first(dict);
|
1310
1585
|
else
|
@@ -1314,9 +1589,9 @@ rbtree_first_last(VALUE self, const int first)
|
|
1314
1589
|
|
1315
1590
|
/*
|
1316
1591
|
* call-seq:
|
1317
|
-
* rbtree.first => array or object
|
1592
|
+
* rbtree.first => array or object or nil
|
1318
1593
|
*
|
1319
|
-
* Returns the first(that is, the smallest) key-value pair.
|
1594
|
+
* Returns the first (that is, the smallest) key-value pair.
|
1320
1595
|
*/
|
1321
1596
|
VALUE
|
1322
1597
|
rbtree_first(VALUE self)
|
@@ -1326,9 +1601,9 @@ rbtree_first(VALUE self)
|
|
1326
1601
|
|
1327
1602
|
/*
|
1328
1603
|
* call-seq:
|
1329
|
-
* rbtree.last => array
|
1604
|
+
* rbtree.last => array or object or nil
|
1330
1605
|
*
|
1331
|
-
* Returns the last(that is, the
|
1606
|
+
* Returns the last (that is, the greatest) key-value pair.
|
1332
1607
|
*/
|
1333
1608
|
VALUE
|
1334
1609
|
rbtree_last(VALUE self)
|
@@ -1344,238 +1619,281 @@ rbtree_last(VALUE self)
|
|
1344
1619
|
* rbtree.readjust {|key1, key2| block} => rbtree
|
1345
1620
|
*
|
1346
1621
|
* Sets a proc to compare keys and readjusts elements using the given
|
1347
|
-
* block or a Proc object given as
|
1348
|
-
*
|
1349
|
-
*
|
1350
|
-
* second one. If no block is given
|
1351
|
-
* current comparison block. If nil is given as
|
1352
|
-
* default comparison block.
|
1622
|
+
* block or a Proc object given as an argument. The block takes two
|
1623
|
+
* keys and returns a negative integer, 0, or a positive integer as
|
1624
|
+
* the first argument is less than, equal to, or greater than the
|
1625
|
+
* second one. If no block is given, just readjusts elements using the
|
1626
|
+
* current comparison block. If nil is given as an argument the
|
1627
|
+
* default comparison block that uses the <=> method is set.
|
1628
|
+
*
|
1629
|
+
* rbtree = RBTree["a", 10, "b", 20]
|
1630
|
+
* rbtree.readjust {|a, b| b <=> a }
|
1631
|
+
* rbtree.first # => ["b", 20]
|
1632
|
+
*
|
1633
|
+
* rbtree.readjust(nil)
|
1634
|
+
* rbtree.first # => ["a", 10]
|
1353
1635
|
*/
|
1354
1636
|
VALUE
|
1355
1637
|
rbtree_readjust(int argc, VALUE* argv, VALUE self)
|
1356
1638
|
{
|
1357
|
-
dict_comp_t
|
1358
|
-
|
1359
|
-
|
1639
|
+
dict_comp_t cmp_func = NULL;
|
1640
|
+
VALUE cmp_proc = Qnil;
|
1641
|
+
|
1360
1642
|
rbtree_modify(self);
|
1361
1643
|
|
1362
|
-
if (
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
cmp = rbtree_cmp;
|
1373
|
-
context = (void*)Qnil;
|
1644
|
+
if (rb_block_given_p()) {
|
1645
|
+
rbtree_check_argument_count(argc, 0, 0);
|
1646
|
+
cmp_func = rbtree_user_cmp;
|
1647
|
+
cmp_proc = rb_block_proc();
|
1648
|
+
rbtree_check_proc_arity(cmp_proc, 2);
|
1649
|
+
} else {
|
1650
|
+
rbtree_check_argument_count(argc, 0, 1);
|
1651
|
+
if (argc == 0) {
|
1652
|
+
cmp_func = DICT(self)->dict_compare;
|
1653
|
+
cmp_proc = CMP_PROC(self);
|
1374
1654
|
} else {
|
1375
|
-
if (
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1655
|
+
if (NIL_P(argv[0])) {
|
1656
|
+
cmp_func = rbtree_cmp;
|
1657
|
+
cmp_proc = Qnil;
|
1658
|
+
} else {
|
1659
|
+
VALUE proc = rb_check_convert_type(argv[0], T_DATA, "Proc", "to_proc");
|
1660
|
+
if (NIL_P(proc)) {
|
1661
|
+
rb_raise(rb_eTypeError,
|
1662
|
+
"wrong cmp_proc type %s (expected Proc)",
|
1663
|
+
rb_obj_classname(argv[0]));
|
1664
|
+
}
|
1665
|
+
cmp_func = rbtree_user_cmp;
|
1666
|
+
cmp_proc = proc;
|
1667
|
+
rbtree_check_proc_arity(cmp_proc, 2);
|
1668
|
+
}
|
1381
1669
|
}
|
1382
|
-
} else {
|
1383
|
-
rbtree_argc_error();
|
1384
1670
|
}
|
1385
1671
|
|
1386
1672
|
if (dict_isempty(DICT(self))) {
|
1387
|
-
|
1388
|
-
|
1673
|
+
DICT(self)->dict_compare = cmp_func;
|
1674
|
+
CMP_PROC(self) = cmp_proc;
|
1389
1675
|
return self;
|
1390
1676
|
}
|
1391
|
-
copy_dict(self, self,
|
1677
|
+
copy_dict(self, self, cmp_func, cmp_proc);
|
1392
1678
|
return self;
|
1393
1679
|
}
|
1394
1680
|
|
1395
1681
|
/*
|
1396
1682
|
* call-seq:
|
1397
|
-
* rbtree.cmp_proc => proc
|
1683
|
+
* rbtree.cmp_proc => proc or nil
|
1398
1684
|
*
|
1399
|
-
* Returns the comparison block that is
|
1685
|
+
* Returns the comparison block that is set by
|
1686
|
+
* MultiRBTree#readjust. If the default comparison block is set,
|
1687
|
+
* returns nil.
|
1400
1688
|
*/
|
1401
1689
|
VALUE
|
1402
1690
|
rbtree_cmp_proc(VALUE self)
|
1403
1691
|
{
|
1404
|
-
return (
|
1692
|
+
return CMP_PROC(self);
|
1405
1693
|
}
|
1406
1694
|
|
1407
1695
|
/*********************************************************************/
|
1408
1696
|
|
1697
|
+
static ID id_breakable;
|
1409
1698
|
static ID id_comma_breakable;
|
1699
|
+
static ID id_group;
|
1410
1700
|
static ID id_object_group;
|
1411
1701
|
static ID id_pp;
|
1412
|
-
static ID id_pp_hash;
|
1413
1702
|
static ID id_text;
|
1414
1703
|
|
1704
|
+
static VALUE
|
1705
|
+
pp_group(VALUE args_)
|
1706
|
+
{
|
1707
|
+
VALUE* args = (VALUE*)args_;
|
1708
|
+
return rb_funcall(args[0], id_group, 3, args[1], args[2], args[3]);
|
1709
|
+
}
|
1710
|
+
|
1415
1711
|
typedef struct {
|
1416
|
-
VALUE rbtree;
|
1417
1712
|
VALUE pp;
|
1418
|
-
|
1713
|
+
dnode_t* node;
|
1714
|
+
} pp_pair_arg_t;
|
1419
1715
|
|
1420
1716
|
static VALUE
|
1421
|
-
|
1717
|
+
pp_value(VALUE nil, pp_pair_arg_t* pair_arg)
|
1422
1718
|
{
|
1423
|
-
|
1424
|
-
|
1719
|
+
VALUE pp = pair_arg->pp;
|
1720
|
+
rb_funcall(pp, id_breakable, 1, rb_str_new(NULL, 0));
|
1721
|
+
return rb_funcall(pp, id_pp, 1, GET_VAL(pair_arg->node));
|
1722
|
+
}
|
1723
|
+
|
1724
|
+
static VALUE
|
1725
|
+
pp_pair(VALUE nil, pp_pair_arg_t* pair_arg)
|
1726
|
+
{
|
1727
|
+
VALUE pp = pair_arg->pp;
|
1728
|
+
VALUE group_args[4];
|
1729
|
+
group_args[0] = pp;
|
1730
|
+
group_args[1] = INT2FIX(1);
|
1731
|
+
group_args[2] = rb_str_new(NULL, 0);
|
1732
|
+
group_args[3] = rb_str_new(NULL, 0);
|
1733
|
+
|
1734
|
+
rb_funcall(pp, id_pp, 1, GET_KEY(pair_arg->node));
|
1735
|
+
rb_funcall(pp, id_text, 1, rb_str_new2("=>"));
|
1736
|
+
return rb_iterate(pp_group, (VALUE)&group_args, pp_value, (VALUE)pair_arg);
|
1737
|
+
}
|
1738
|
+
|
1739
|
+
typedef struct {
|
1740
|
+
VALUE pp;
|
1741
|
+
int first;
|
1742
|
+
} pp_each_pair_arg_t;
|
1743
|
+
|
1744
|
+
static each_return_t
|
1745
|
+
pp_each_pair_i(dnode_t* node, void* each_pair_arg_)
|
1746
|
+
{
|
1747
|
+
pp_each_pair_arg_t* each_pair_arg = (pp_each_pair_arg_t*)each_pair_arg_;
|
1748
|
+
VALUE group_args[4];
|
1749
|
+
pp_pair_arg_t pair_arg;
|
1750
|
+
|
1751
|
+
if (each_pair_arg->first) {
|
1752
|
+
each_pair_arg->first = 0;
|
1753
|
+
} else {
|
1754
|
+
rb_funcall(each_pair_arg->pp, id_comma_breakable, 0);
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
group_args[0] = each_pair_arg->pp;
|
1758
|
+
group_args[1] = INT2FIX(0);
|
1759
|
+
group_args[2] = rb_str_new(NULL, 0);
|
1760
|
+
group_args[3] = rb_str_new(NULL, 0);
|
1761
|
+
|
1762
|
+
pair_arg.pp = each_pair_arg->pp;
|
1763
|
+
pair_arg.node = node;
|
1764
|
+
|
1765
|
+
rb_iterate(pp_group, (VALUE)&group_args, pp_pair, (VALUE)&pair_arg);
|
1766
|
+
return EACH_NEXT;
|
1767
|
+
}
|
1768
|
+
|
1769
|
+
typedef struct {
|
1770
|
+
VALUE pp;
|
1771
|
+
VALUE rbtree;
|
1772
|
+
} pp_rbtree_arg_t;
|
1773
|
+
|
1774
|
+
static VALUE
|
1775
|
+
pp_each_pair(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
|
1776
|
+
{
|
1777
|
+
pp_each_pair_arg_t each_pair_arg;
|
1778
|
+
each_pair_arg.pp = rbtree_arg->pp;
|
1779
|
+
each_pair_arg.first = 1;
|
1780
|
+
return rbtree_for_each(rbtree_arg->rbtree, pp_each_pair_i, &each_pair_arg);
|
1425
1781
|
}
|
1426
1782
|
|
1427
1783
|
static VALUE
|
1428
|
-
|
1784
|
+
pp_rbtree(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
|
1429
1785
|
{
|
1430
|
-
VALUE pp =
|
1431
|
-
VALUE rbtree =
|
1786
|
+
VALUE pp = rbtree_arg->pp;
|
1787
|
+
VALUE rbtree = rbtree_arg->rbtree;
|
1788
|
+
|
1789
|
+
VALUE group_args[4];
|
1790
|
+
group_args[0] = pp;
|
1791
|
+
group_args[1] = INT2FIX(1);
|
1792
|
+
group_args[2] = rb_str_new2("{");
|
1793
|
+
group_args[3] = rb_str_new2("}");
|
1432
1794
|
|
1433
1795
|
rb_funcall(pp, id_text, 1, rb_str_new2(": "));
|
1434
|
-
|
1796
|
+
rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
|
1435
1797
|
rb_funcall(pp, id_comma_breakable, 0);
|
1436
1798
|
rb_funcall(pp, id_text, 1, rb_str_new2("default="));
|
1437
1799
|
rb_funcall(pp, id_pp, 1, IFNONE(rbtree));
|
1438
1800
|
rb_funcall(pp, id_comma_breakable, 0);
|
1439
1801
|
rb_funcall(pp, id_text, 1, rb_str_new2("cmp_proc="));
|
1440
|
-
rb_funcall(pp, id_pp, 1,
|
1441
|
-
|
1802
|
+
return rb_funcall(pp, id_pp, 1, CMP_PROC(rbtree));
|
1803
|
+
}
|
1804
|
+
|
1805
|
+
static VALUE
|
1806
|
+
pp_rbtree_group(VALUE arg_)
|
1807
|
+
{
|
1808
|
+
pp_rbtree_arg_t* arg = (pp_rbtree_arg_t*)arg_;
|
1809
|
+
return rb_funcall(arg->pp, id_object_group, 1, arg->rbtree);
|
1442
1810
|
}
|
1443
1811
|
|
1444
1812
|
/*********************************************************************/
|
1445
1813
|
|
1446
|
-
/*
|
1447
|
-
*
|
1814
|
+
/* :nodoc:
|
1815
|
+
*
|
1448
1816
|
*/
|
1449
1817
|
VALUE
|
1450
1818
|
rbtree_pretty_print(VALUE self, VALUE pp)
|
1451
1819
|
{
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
return rb_iterate(pp_object_group, (VALUE)&pp_arg,
|
1457
|
-
pp_block, (VALUE)&pp_arg);
|
1820
|
+
pp_rbtree_arg_t arg;
|
1821
|
+
arg.rbtree = self;
|
1822
|
+
arg.pp = pp;
|
1823
|
+
return rb_iterate(pp_rbtree_group, (VALUE)&arg, pp_rbtree, (VALUE)&arg);
|
1458
1824
|
}
|
1459
1825
|
|
1460
|
-
/*
|
1461
|
-
*
|
1826
|
+
/* :nodoc:
|
1827
|
+
*
|
1462
1828
|
*/
|
1463
1829
|
VALUE
|
1464
1830
|
rbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
1465
1831
|
{
|
1466
|
-
return rb_funcall(pp, id_pp, 1,
|
1832
|
+
return rb_funcall(pp, id_pp, 1, rbtree_inspect_recursive(self, Qnil, 1));
|
1467
1833
|
}
|
1468
1834
|
|
1469
1835
|
/*********************************************************************/
|
1470
1836
|
|
1471
|
-
|
1472
|
-
|
1473
|
-
{
|
1474
|
-
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1475
|
-
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1476
|
-
return EACH_NEXT;
|
1477
|
-
}
|
1478
|
-
|
1479
|
-
/*********************************************************************/
|
1480
|
-
|
1481
|
-
/*
|
1482
|
-
* Called by Marshal.dump.
|
1837
|
+
/* :nodoc:
|
1838
|
+
*
|
1483
1839
|
*/
|
1484
1840
|
VALUE
|
1485
1841
|
rbtree_dump(VALUE self, VALUE limit)
|
1486
1842
|
{
|
1487
1843
|
VALUE ary;
|
1488
|
-
VALUE
|
1489
|
-
|
1844
|
+
VALUE result;
|
1845
|
+
|
1490
1846
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
1491
|
-
rb_raise(rb_eTypeError, "
|
1492
|
-
if ((
|
1493
|
-
rb_raise(rb_eTypeError, "
|
1494
|
-
|
1847
|
+
rb_raise(rb_eTypeError, "can't dump rbtree with default proc");
|
1848
|
+
if (CMP_PROC(self) != Qnil)
|
1849
|
+
rb_raise(rb_eTypeError, "can't dump rbtree with comparison proc");
|
1850
|
+
|
1495
1851
|
ary = rb_ary_new2(dict_count(DICT(self)) * 2 + 1);
|
1496
|
-
rbtree_for_each(self,
|
1852
|
+
rbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1497
1853
|
rb_ary_push(ary, IFNONE(self));
|
1498
1854
|
|
1499
|
-
|
1855
|
+
result = rb_marshal_dump(ary, Qnil);
|
1856
|
+
#ifdef HAVE_RB_ARY_RESIZE
|
1857
|
+
rb_ary_resize(ary, 0);
|
1858
|
+
#else
|
1500
1859
|
rb_ary_clear(ary);
|
1501
|
-
|
1502
|
-
return
|
1860
|
+
#endif
|
1861
|
+
return result;
|
1503
1862
|
}
|
1504
1863
|
|
1505
|
-
/*
|
1506
|
-
*
|
1864
|
+
/* :nodoc:
|
1865
|
+
*
|
1507
1866
|
*/
|
1508
1867
|
VALUE
|
1509
1868
|
rbtree_s_load(VALUE klass, VALUE str)
|
1510
1869
|
{
|
1511
1870
|
VALUE rbtree = rbtree_alloc(klass);
|
1512
1871
|
VALUE ary = rb_marshal_load(str);
|
1513
|
-
|
1514
|
-
long len = RARRAY(ary)->len - 1;
|
1872
|
+
long len = RARRAY_LEN(ary) - 1;
|
1515
1873
|
long i;
|
1516
|
-
|
1874
|
+
|
1517
1875
|
for (i = 0; i < len; i += 2)
|
1518
|
-
rbtree_aset(rbtree,
|
1519
|
-
IFNONE(rbtree) =
|
1520
|
-
|
1876
|
+
rbtree_aset(rbtree, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i + 1));
|
1877
|
+
IFNONE(rbtree) = RARRAY_AREF(ary, len);
|
1878
|
+
|
1879
|
+
#ifdef HAVE_RB_ARY_RESIZE
|
1880
|
+
rb_ary_resize(ary, 0);
|
1881
|
+
#else
|
1521
1882
|
rb_ary_clear(ary);
|
1522
|
-
|
1883
|
+
#endif
|
1523
1884
|
return rbtree;
|
1524
1885
|
}
|
1525
1886
|
|
1526
1887
|
/*********************************************************************/
|
1527
1888
|
|
1528
1889
|
/*
|
1529
|
-
*
|
1530
|
-
*
|
1531
|
-
*
|
1532
|
-
|
1533
|
-
|
1534
|
-
*
|
1535
|
-
*
|
1536
|
-
* for insert, search and delete is O(log N) in expected and worst
|
1537
|
-
* case. On the other hand the complexity of Hash is O(1). Because
|
1538
|
-
* Hash is unordered the data structure is more effective than
|
1539
|
-
* Red-Black Tree as an associative collection.
|
1540
|
-
*
|
1541
|
-
* The elements of RBTree are sorted with natural ordering (by <=>
|
1542
|
-
* method) of its keys or by a comparator(Proc) set by readjust
|
1543
|
-
* method. It means all keys in RBTree should be comparable with each
|
1544
|
-
* other. Or a comparator that takes two arguments of a key should return
|
1545
|
-
* negative, 0, or positive depending on the first argument is less than,
|
1546
|
-
* equal to, or greater than the second one.
|
1547
|
-
*
|
1548
|
-
* The interface of RBTree is the almost same as Hash and there are a
|
1549
|
-
* few methods to take advantage of the ordering:
|
1550
|
-
*
|
1551
|
-
* * lower_bound, upper_bound, bound
|
1552
|
-
* * first, last
|
1553
|
-
* * shift, pop
|
1554
|
-
* * reverse_each
|
1555
|
-
*
|
1556
|
-
* Note: while iterating RBTree (e.g. in a block of each method), it is
|
1557
|
-
* not modifiable, or TypeError is thrown.
|
1558
|
-
*
|
1559
|
-
* RBTree supoorts pretty printing using pp.
|
1560
|
-
*
|
1561
|
-
* This library contains two classes. One is RBTree and the other is
|
1562
|
-
* MultiRBTree that is a parent class of RBTree. RBTree does not allow
|
1563
|
-
* duplications of keys but MultiRBTree does.
|
1564
|
-
*
|
1565
|
-
* require "rbtree"
|
1566
|
-
*
|
1567
|
-
* rbtree = RBTree["c", 10, "a", 20]
|
1568
|
-
* rbtree["b"] = 30
|
1569
|
-
* p rbtree["b"] # => 30
|
1570
|
-
* rbtree.each do |k, v|
|
1571
|
-
* p [k, v]
|
1572
|
-
* end # => ["a", 20] ["b", 30] ["c", 10]
|
1573
|
-
*
|
1574
|
-
* mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
|
1575
|
-
* p mrbtree.lower_bound("b") # => ["c", 10]
|
1576
|
-
* mrbtree.bound("a", "d") do |k, v|
|
1577
|
-
* p [k, v]
|
1578
|
-
* end # => ["a", 20] ["a", 40] ["c", 10]
|
1890
|
+
* Document-class: MultiRBTree
|
1891
|
+
*
|
1892
|
+
* A sorted associative collection that can contain duplicate keys.
|
1893
|
+
*/
|
1894
|
+
/*
|
1895
|
+
* A sorted associative collection that cannot contain duplicate
|
1896
|
+
* keys. RBTree is a subclass of MultiRBTree.
|
1579
1897
|
*/
|
1580
1898
|
void Init_rbtree()
|
1581
1899
|
{
|
@@ -1592,10 +1910,11 @@ void Init_rbtree()
|
|
1592
1910
|
rb_define_method(MultiRBTree, "initialize_copy", rbtree_initialize_copy, 1);
|
1593
1911
|
|
1594
1912
|
rb_define_method(MultiRBTree, "to_a", rbtree_to_a, 0);
|
1595
|
-
rb_define_method(MultiRBTree, "
|
1913
|
+
rb_define_method(MultiRBTree, "to_h", rbtree_to_hash, 0);
|
1596
1914
|
rb_define_method(MultiRBTree, "to_hash", rbtree_to_hash, 0);
|
1597
1915
|
rb_define_method(MultiRBTree, "to_rbtree", rbtree_to_rbtree, 0);
|
1598
1916
|
rb_define_method(MultiRBTree, "inspect", rbtree_inspect, 0);
|
1917
|
+
rb_define_alias(MultiRBTree, "to_s", "inspect");
|
1599
1918
|
|
1600
1919
|
rb_define_method(MultiRBTree, "==", rbtree_equal, 1);
|
1601
1920
|
rb_define_method(MultiRBTree, "[]", rbtree_aref, 1);
|
@@ -1610,12 +1929,14 @@ void Init_rbtree()
|
|
1610
1929
|
rb_define_method(MultiRBTree, "default", rbtree_default, -1);
|
1611
1930
|
rb_define_method(MultiRBTree, "default=", rbtree_set_default, 1);
|
1612
1931
|
rb_define_method(MultiRBTree, "default_proc", rbtree_default_proc, 0);
|
1932
|
+
rb_define_method(MultiRBTree, "default_proc=", rbtree_set_default_proc, 1);
|
1933
|
+
rb_define_method(MultiRBTree, "key", rbtree_key, 1);
|
1613
1934
|
rb_define_method(MultiRBTree, "index", rbtree_index, 1);
|
1614
1935
|
rb_define_method(MultiRBTree, "empty?", rbtree_empty_p, 0);
|
1615
1936
|
rb_define_method(MultiRBTree, "size", rbtree_size, 0);
|
1616
1937
|
rb_define_method(MultiRBTree, "length", rbtree_size, 0);
|
1617
1938
|
|
1618
|
-
rb_define_method(MultiRBTree, "each",
|
1939
|
+
rb_define_method(MultiRBTree, "each", rbtree_each_pair, 0);
|
1619
1940
|
rb_define_method(MultiRBTree, "each_value", rbtree_each_value, 0);
|
1620
1941
|
rb_define_method(MultiRBTree, "each_key", rbtree_each_key, 0);
|
1621
1942
|
rb_define_method(MultiRBTree, "each_pair", rbtree_each_pair, 0);
|
@@ -1629,15 +1950,20 @@ void Init_rbtree()
|
|
1629
1950
|
rb_define_method(MultiRBTree, "pop", rbtree_pop, 0);
|
1630
1951
|
rb_define_method(MultiRBTree, "delete", rbtree_delete, 1);
|
1631
1952
|
rb_define_method(MultiRBTree, "delete_if", rbtree_delete_if, 0);
|
1632
|
-
rb_define_method(MultiRBTree, "
|
1953
|
+
rb_define_method(MultiRBTree, "keep_if", rbtree_keep_if, 0);
|
1633
1954
|
rb_define_method(MultiRBTree, "reject", rbtree_reject, 0);
|
1634
1955
|
rb_define_method(MultiRBTree, "reject!", rbtree_reject_bang, 0);
|
1956
|
+
rb_define_method(MultiRBTree, "select", rbtree_select, 0);
|
1957
|
+
rb_define_method(MultiRBTree, "select!", rbtree_select_bang, 0);
|
1635
1958
|
rb_define_method(MultiRBTree, "clear", rbtree_clear, 0);
|
1636
1959
|
rb_define_method(MultiRBTree, "invert", rbtree_invert, 0);
|
1637
1960
|
rb_define_method(MultiRBTree, "update", rbtree_update, 1);
|
1638
1961
|
rb_define_method(MultiRBTree, "merge!", rbtree_update, 1);
|
1639
1962
|
rb_define_method(MultiRBTree, "merge", rbtree_merge, 1);
|
1640
1963
|
rb_define_method(MultiRBTree, "replace", rbtree_initialize_copy, 1);
|
1964
|
+
#ifdef HAVE_HASH_FLATTEN
|
1965
|
+
rb_define_method(MultiRBTree, "flatten", rbtree_flatten, -1);
|
1966
|
+
#endif
|
1641
1967
|
|
1642
1968
|
rb_define_method(MultiRBTree, "include?", rbtree_has_key, 1);
|
1643
1969
|
rb_define_method(MultiRBTree, "member?", rbtree_has_key, 1);
|
@@ -1651,20 +1977,20 @@ void Init_rbtree()
|
|
1651
1977
|
|
1652
1978
|
rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
|
1653
1979
|
rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
|
1654
|
-
|
1655
|
-
id_bound = rb_intern("bound");
|
1980
|
+
|
1656
1981
|
id_cmp = rb_intern("<=>");
|
1657
1982
|
id_call = rb_intern("call");
|
1658
1983
|
id_default = rb_intern("default");
|
1659
|
-
|
1984
|
+
id_flatten_bang = rb_intern("flatten!");
|
1660
1985
|
|
1661
1986
|
rb_define_method(MultiRBTree, "pretty_print", rbtree_pretty_print, 1);
|
1662
1987
|
rb_define_method(MultiRBTree,
|
1663
1988
|
"pretty_print_cycle", rbtree_pretty_print_cycle, 1);
|
1664
1989
|
|
1990
|
+
id_breakable = rb_intern("breakable");
|
1665
1991
|
id_comma_breakable = rb_intern("comma_breakable");
|
1992
|
+
id_group = rb_intern("group");
|
1666
1993
|
id_object_group = rb_intern("object_group");
|
1667
|
-
id_pp_hash = rb_intern("pp_hash");
|
1668
|
-
id_text = rb_intern("text");
|
1669
1994
|
id_pp = rb_intern("pp");
|
1995
|
+
id_text = rb_intern("text");
|
1670
1996
|
}
|