rbtree 0.3.0 → 0.4.4
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 +38 -71
- data/dict.c +364 -83
- data/dict.h +30 -6
- data/extconf.rb +13 -2
- data/rbtree.c +772 -482
- data/test.rb +309 -182
- metadata +42 -45
- data/ChangeLog +0 -505
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,6 +1,17 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
if enable_config('debug')
|
4
|
+
$CFLAGS << ' -g -std=c99 -pedantic -Wall'
|
5
|
+
else
|
6
|
+
$defs << '-DNDEBUG'
|
7
|
+
end
|
5
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
|
6
17
|
create_makefile('rbtree')
|
data/rbtree.c
CHANGED
@@ -1,6 +1,6 @@
|
|
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
|
@@ -8,43 +8,49 @@
|
|
8
8
|
#else
|
9
9
|
#include <st.h>
|
10
10
|
#endif
|
11
|
-
#include <stdarg.h>
|
12
11
|
#include "dict.h"
|
13
12
|
|
14
13
|
#define RBTREE_PROC_DEFAULT FL_USER2
|
15
14
|
#define HASH_PROC_DEFAULT FL_USER2
|
16
15
|
|
17
|
-
#
|
18
|
-
#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
|
19
24
|
#endif
|
20
25
|
|
21
|
-
#ifndef
|
22
|
-
#define
|
26
|
+
#ifndef RARRAY_AREF
|
27
|
+
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
23
28
|
#endif
|
24
|
-
|
25
|
-
#
|
29
|
+
|
30
|
+
#ifndef RHASH_SET_IFNONE
|
31
|
+
#define RHASH_SET_IFNONE(h, v) (RHASH(h)->ifnone = (v))
|
26
32
|
#endif
|
27
33
|
|
28
34
|
VALUE RBTree;
|
29
35
|
VALUE MultiRBTree;
|
30
36
|
|
31
|
-
static ID id_bound;
|
32
37
|
static ID id_cmp;
|
33
38
|
static ID id_call;
|
34
39
|
static ID id_default;
|
40
|
+
static ID id_flatten_bang;
|
35
41
|
|
36
42
|
typedef struct {
|
37
43
|
dict_t* dict;
|
38
44
|
VALUE ifnone;
|
45
|
+
VALUE cmp_proc;
|
39
46
|
int iter_lev;
|
40
47
|
} rbtree_t;
|
41
48
|
|
42
49
|
#define RBTREE(rbtree) DATA_PTR(rbtree)
|
43
50
|
#define DICT(rbtree) ((rbtree_t*)RBTREE(rbtree))->dict
|
44
51
|
#define IFNONE(rbtree) ((rbtree_t*)RBTREE(rbtree))->ifnone
|
52
|
+
#define CMP_PROC(rbtree) ((rbtree_t*)RBTREE(rbtree))->cmp_proc
|
45
53
|
#define ITER_LEV(rbtree) ((rbtree_t*)RBTREE(rbtree))->iter_lev
|
46
|
-
#define COMPARE(rbtree) DICT(rbtree)->dict_compare
|
47
|
-
#define CONTEXT(rbtree) DICT(rbtree)->dict_context
|
48
54
|
|
49
55
|
#define TO_KEY(arg) ((const void*)arg)
|
50
56
|
#define TO_VAL(arg) ((void*)arg)
|
@@ -54,17 +60,11 @@ typedef struct {
|
|
54
60
|
|
55
61
|
/*********************************************************************/
|
56
62
|
|
57
|
-
static int
|
58
|
-
cmpint(VALUE i, VALUE a, VALUE b)
|
59
|
-
{
|
60
|
-
return rb_cmpint(i, a, b);
|
61
|
-
}
|
62
|
-
|
63
63
|
static void
|
64
64
|
rbtree_free(rbtree_t* rbtree)
|
65
65
|
{
|
66
66
|
dict_free_nodes(rbtree->dict);
|
67
|
-
|
67
|
+
xfree(rbtree->dict);
|
68
68
|
xfree(rbtree);
|
69
69
|
}
|
70
70
|
|
@@ -83,9 +83,9 @@ rbtree_mark(rbtree_t* rbtree)
|
|
83
83
|
rb_gc_mark(GET_KEY(node));
|
84
84
|
rb_gc_mark(GET_VAL(node));
|
85
85
|
}
|
86
|
-
rb_gc_mark((VALUE)dict->dict_context);
|
87
86
|
}
|
88
87
|
rb_gc_mark(rbtree->ifnone);
|
88
|
+
rb_gc_mark(rbtree->cmp_proc);
|
89
89
|
}
|
90
90
|
|
91
91
|
static dnode_t*
|
@@ -101,63 +101,112 @@ rbtree_free_node(dnode_t* node, void* context)
|
|
101
101
|
}
|
102
102
|
|
103
103
|
static void
|
104
|
-
|
105
|
-
{
|
106
|
-
|
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
|
107
131
|
}
|
108
132
|
|
109
133
|
static int
|
110
134
|
rbtree_cmp(const void* key1, const void* key2, void* context)
|
111
135
|
{
|
112
|
-
VALUE
|
136
|
+
VALUE result;
|
113
137
|
if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
|
114
138
|
return rb_str_cmp((VALUE)key1, (VALUE)key2);
|
115
|
-
|
116
|
-
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);
|
117
156
|
}
|
118
157
|
|
119
158
|
static int
|
120
|
-
rbtree_user_cmp(const void* key1, const void* key2, void*
|
159
|
+
rbtree_user_cmp(const void* key1, const void* key2, void* context)
|
121
160
|
{
|
122
|
-
|
123
|
-
|
124
|
-
|
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);
|
125
171
|
}
|
126
172
|
|
127
173
|
static void
|
128
174
|
rbtree_modify(VALUE self)
|
129
175
|
{
|
130
176
|
if (ITER_LEV(self) > 0)
|
131
|
-
rb_raise(rb_eTypeError, "can't modify rbtree
|
132
|
-
|
133
|
-
|
177
|
+
rb_raise(rb_eTypeError, "can't modify rbtree during iteration");
|
178
|
+
rb_check_frozen(self);
|
179
|
+
#if defined(HAVE_RB_SAFE_LEVEL) && !defined(RUBY_SAFE_LEVEL_MAX)
|
134
180
|
if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
|
135
181
|
rb_raise(rb_eSecurityError, "Insecure: can't modify rbtree");
|
182
|
+
#endif
|
136
183
|
}
|
137
184
|
|
138
185
|
static VALUE
|
139
186
|
rbtree_alloc(VALUE klass)
|
140
187
|
{
|
141
188
|
dict_t* dict;
|
142
|
-
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free,
|
189
|
+
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, NULL);
|
143
190
|
RBTREE(rbtree) = ALLOC(rbtree_t);
|
144
191
|
MEMZERO(RBTREE(rbtree), rbtree_t, 1);
|
145
192
|
|
146
|
-
dict =
|
193
|
+
dict = ALLOC(dict_t);
|
194
|
+
dict_init(dict, rbtree_cmp);
|
147
195
|
dict_set_allocator(dict, rbtree_alloc_node, rbtree_free_node,
|
148
|
-
(
|
149
|
-
if (klass
|
196
|
+
RBTREE(rbtree));
|
197
|
+
if (!RTEST(rb_class_inherited_p(klass, RBTree)))
|
150
198
|
dict_allow_dupes(dict);
|
151
|
-
|
199
|
+
|
152
200
|
DICT(rbtree) = dict;
|
153
201
|
IFNONE(rbtree) = Qnil;
|
202
|
+
CMP_PROC(rbtree) = Qnil;
|
154
203
|
return rbtree;
|
155
204
|
}
|
156
205
|
|
157
206
|
VALUE rbtree_aset(VALUE, VALUE, VALUE);
|
158
|
-
VALUE rbtree_clear(VALUE);
|
159
207
|
VALUE rbtree_has_key(VALUE, VALUE);
|
160
208
|
VALUE rbtree_update(VALUE, VALUE);
|
209
|
+
VALUE rbtree_to_a(VALUE);
|
161
210
|
|
162
211
|
/*********************************************************************/
|
163
212
|
|
@@ -177,52 +226,57 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
|
|
177
226
|
{
|
178
227
|
long i;
|
179
228
|
VALUE rbtree;
|
180
|
-
|
229
|
+
|
181
230
|
if (argc == 1) {
|
182
|
-
VALUE
|
183
|
-
|
184
|
-
if (klass == RBTree && CLASS_OF(argv[0]) == MultiRBTree) {
|
185
|
-
rb_raise(rb_eTypeError, "can't convert MultiRBTree to RBTree");
|
186
|
-
}
|
187
|
-
|
231
|
+
VALUE temp;
|
232
|
+
|
188
233
|
if (rb_obj_is_kind_of(argv[0], klass)) {
|
189
234
|
rbtree = rbtree_alloc(klass);
|
190
235
|
rbtree_update(rbtree, argv[0]);
|
191
236
|
return rbtree;
|
192
237
|
}
|
193
|
-
|
194
|
-
|
195
|
-
|
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)) {
|
196
247
|
rbtree = rbtree_alloc(klass);
|
197
|
-
|
248
|
+
rb_hash_foreach(temp, hash_to_rbtree_i, rbtree);
|
198
249
|
return rbtree;
|
199
250
|
}
|
200
|
-
|
201
|
-
|
202
|
-
if (!NIL_P(
|
251
|
+
|
252
|
+
temp = rb_check_array_type(argv[0]);
|
253
|
+
if (!NIL_P(temp)) {
|
203
254
|
rbtree = rbtree_alloc(klass);
|
204
|
-
for (i = 0; i < RARRAY_LEN(
|
205
|
-
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));
|
206
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);
|
207
260
|
continue;
|
208
261
|
}
|
209
262
|
switch(RARRAY_LEN(v)) {
|
210
263
|
case 1:
|
211
|
-
rbtree_aset(rbtree,
|
264
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
|
212
265
|
break;
|
213
266
|
case 2:
|
214
|
-
rbtree_aset(rbtree,
|
267
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
|
215
268
|
break;
|
216
269
|
default:
|
217
|
-
|
270
|
+
rb_warn("invalid number of elements (%ld for 1..2)",
|
271
|
+
RARRAY_LEN(v));
|
218
272
|
}
|
219
273
|
}
|
220
274
|
return rbtree;
|
221
275
|
}
|
222
276
|
}
|
223
|
-
|
277
|
+
|
224
278
|
if (argc % 2 != 0)
|
225
|
-
rb_raise(rb_eArgError, "odd number of arguments for
|
279
|
+
rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));
|
226
280
|
|
227
281
|
rbtree = rbtree_alloc(klass);
|
228
282
|
for (i = 0; i < argc; i += 2)
|
@@ -239,15 +293,17 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
|
|
239
293
|
rbtree_modify(self);
|
240
294
|
|
241
295
|
if (rb_block_given_p()) {
|
242
|
-
|
243
|
-
|
244
|
-
|
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;
|
245
301
|
FL_SET(self, RBTREE_PROC_DEFAULT);
|
246
302
|
} else {
|
247
|
-
|
248
|
-
|
249
|
-
else if (argc == 1)
|
303
|
+
rbtree_check_argument_count(argc, 0, 1);
|
304
|
+
if (argc == 1) {
|
250
305
|
IFNONE(self) = argv[0];
|
306
|
+
}
|
251
307
|
}
|
252
308
|
return self;
|
253
309
|
}
|
@@ -255,42 +311,50 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
|
|
255
311
|
/*********************************************************************/
|
256
312
|
|
257
313
|
typedef enum {
|
258
|
-
|
259
|
-
|
314
|
+
NoNodeInserted,
|
315
|
+
KeyAllocationFailed,
|
316
|
+
InsertionSucceeded
|
317
|
+
} insert_result_t;
|
260
318
|
|
261
319
|
typedef struct {
|
262
320
|
dict_t* dict;
|
263
321
|
dnode_t* node;
|
264
|
-
|
265
|
-
|
266
|
-
} insert_node_t;
|
322
|
+
insert_result_t result;
|
323
|
+
} rbtree_insert_arg_t;
|
267
324
|
|
268
325
|
static VALUE
|
269
|
-
insert_node_body(
|
326
|
+
insert_node_body(rbtree_insert_arg_t* arg)
|
270
327
|
{
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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;
|
275
340
|
return Qnil;
|
276
341
|
}
|
277
342
|
|
278
343
|
static VALUE
|
279
|
-
insert_node_ensure(
|
344
|
+
insert_node_ensure(rbtree_insert_arg_t* arg)
|
280
345
|
{
|
281
346
|
dict_t* dict = arg->dict;
|
282
347
|
dnode_t* node = arg->node;
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
break;
|
287
|
-
case NODE_NOT_FOUND:
|
288
|
-
if (TYPE(arg->key) == T_STRING)
|
289
|
-
node->dict_key = TO_KEY(rb_str_new4(GET_KEY(node)));
|
348
|
+
|
349
|
+
switch (arg->result) {
|
350
|
+
case InsertionSucceeded:
|
290
351
|
break;
|
291
|
-
case
|
352
|
+
case NoNodeInserted:
|
292
353
|
dict->dict_freenode(node, dict->dict_context);
|
293
354
|
break;
|
355
|
+
case KeyAllocationFailed:
|
356
|
+
dict_delete_free(dict, node);
|
357
|
+
break;
|
294
358
|
}
|
295
359
|
return Qnil;
|
296
360
|
}
|
@@ -298,16 +362,16 @@ insert_node_ensure(insert_node_t* arg)
|
|
298
362
|
static void
|
299
363
|
rbtree_insert(VALUE self, VALUE key, VALUE value)
|
300
364
|
{
|
301
|
-
|
365
|
+
rbtree_insert_arg_t arg;
|
302
366
|
dict_t* dict = DICT(self);
|
303
367
|
dnode_t* node = dict->dict_allocnode(dict->dict_context);
|
304
368
|
|
305
369
|
dnode_init(node, TO_VAL(value));
|
370
|
+
node->dict_key = TO_KEY(key);
|
306
371
|
|
307
372
|
arg.dict = dict;
|
308
373
|
arg.node = node;
|
309
|
-
arg.
|
310
|
-
arg.ret = INITIAL_VALUE;
|
374
|
+
arg.result = NoNodeInserted;
|
311
375
|
|
312
376
|
rb_ensure(insert_node_body, (VALUE)&arg,
|
313
377
|
insert_node_ensure, (VALUE)&arg);
|
@@ -343,7 +407,7 @@ rbtree_aref(VALUE self, VALUE key)
|
|
343
407
|
{
|
344
408
|
dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
|
345
409
|
if (node == NULL)
|
346
|
-
return
|
410
|
+
return rb_funcall2(self, id_default, 1, &key);
|
347
411
|
else
|
348
412
|
return GET_VAL(node);
|
349
413
|
}
|
@@ -355,22 +419,23 @@ VALUE
|
|
355
419
|
rbtree_fetch(int argc, VALUE* argv, VALUE self)
|
356
420
|
{
|
357
421
|
dnode_t* node;
|
358
|
-
int block_given;
|
359
422
|
|
360
|
-
|
361
|
-
|
362
|
-
block_given = rb_block_given_p();
|
363
|
-
if (block_given && argc == 2)
|
423
|
+
rbtree_check_argument_count(argc, 1, 2);
|
424
|
+
if (argc == 2 && rb_block_given_p()) {
|
364
425
|
rb_warn("block supersedes default value argument");
|
426
|
+
}
|
365
427
|
|
366
428
|
node = dict_lookup(DICT(self), TO_KEY(argv[0]));
|
367
|
-
if (node != NULL)
|
429
|
+
if (node != NULL) {
|
368
430
|
return GET_VAL(node);
|
431
|
+
}
|
369
432
|
|
370
|
-
if (
|
433
|
+
if (rb_block_given_p()) {
|
371
434
|
return rb_yield(argv[0]);
|
372
|
-
|
435
|
+
}
|
436
|
+
if (argc == 1) {
|
373
437
|
rb_raise(rb_eIndexError, "key not found");
|
438
|
+
}
|
374
439
|
return argv[1];
|
375
440
|
}
|
376
441
|
|
@@ -398,15 +463,12 @@ rbtree_empty_p(VALUE self)
|
|
398
463
|
VALUE
|
399
464
|
rbtree_default(int argc, VALUE* argv, VALUE self)
|
400
465
|
{
|
401
|
-
|
402
|
-
if (argc == 1)
|
403
|
-
key = argv[0];
|
404
|
-
else if (argc > 1)
|
405
|
-
rbtree_argc_error();
|
406
|
-
|
466
|
+
rbtree_check_argument_count(argc, 0, 1);
|
407
467
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
|
408
|
-
if (argc == 0)
|
409
|
-
|
468
|
+
if (argc == 0) {
|
469
|
+
return Qnil;
|
470
|
+
}
|
471
|
+
return rb_funcall(IFNONE(self), id_call, 2, self, argv[0]);
|
410
472
|
}
|
411
473
|
return IFNONE(self);
|
412
474
|
}
|
@@ -434,10 +496,54 @@ rbtree_default_proc(VALUE self)
|
|
434
496
|
return Qnil;
|
435
497
|
}
|
436
498
|
|
437
|
-
|
438
|
-
|
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)
|
439
528
|
{
|
440
|
-
|
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;
|
441
547
|
}
|
442
548
|
|
443
549
|
/*
|
@@ -446,13 +552,23 @@ value_eq(const void* key1, const void* key2)
|
|
446
552
|
VALUE
|
447
553
|
rbtree_equal(VALUE self, VALUE other)
|
448
554
|
{
|
449
|
-
int ret;
|
450
555
|
if (self == other)
|
451
556
|
return Qtrue;
|
452
557
|
if (!rb_obj_is_kind_of(other, MultiRBTree))
|
453
558
|
return Qfalse;
|
454
|
-
|
455
|
-
|
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
|
456
572
|
}
|
457
573
|
|
458
574
|
/*********************************************************************/
|
@@ -485,7 +601,7 @@ rbtree_each_body(rbtree_each_arg_t* arg)
|
|
485
601
|
dnode_t* node;
|
486
602
|
dnode_t* first_node;
|
487
603
|
dnode_t* (*next_func)(dict_t*, dnode_t*);
|
488
|
-
|
604
|
+
|
489
605
|
if (arg->reverse) {
|
490
606
|
first_node = dict_last(dict);
|
491
607
|
next_func = dict_prev;
|
@@ -493,12 +609,12 @@ rbtree_each_body(rbtree_each_arg_t* arg)
|
|
493
609
|
first_node = dict_first(dict);
|
494
610
|
next_func = dict_next;
|
495
611
|
}
|
496
|
-
|
612
|
+
|
497
613
|
ITER_LEV(self)++;
|
498
614
|
for (node = first_node;
|
499
615
|
node != NULL;
|
500
616
|
node = next_func(dict, node)) {
|
501
|
-
|
617
|
+
|
502
618
|
if (arg->func(node, arg->arg) == EACH_STOP)
|
503
619
|
break;
|
504
620
|
}
|
@@ -531,45 +647,29 @@ rbtree_reverse_for_each(VALUE self, each_callback_func func, void* arg)
|
|
531
647
|
|
532
648
|
/*********************************************************************/
|
533
649
|
|
534
|
-
static each_return_t
|
535
|
-
each_i(dnode_t* node, void* arg)
|
536
|
-
{
|
537
|
-
rb_yield(ASSOC(node));
|
538
|
-
return EACH_NEXT;
|
539
|
-
}
|
540
|
-
|
541
|
-
/*
|
542
|
-
* call-seq:
|
543
|
-
* rbtree.each {|key, value| block} => rbtree
|
544
|
-
*
|
545
|
-
* Calls block once for each key in order, passing the key and value
|
546
|
-
* as a two-element array parameters.
|
547
|
-
*/
|
548
|
-
VALUE
|
549
|
-
rbtree_each(VALUE self)
|
550
|
-
{
|
551
|
-
RETURN_ENUMERATOR(self, 0, NULL);
|
552
|
-
return rbtree_for_each(self, each_i, NULL);
|
553
|
-
}
|
554
|
-
|
555
650
|
static each_return_t
|
556
651
|
each_pair_i(dnode_t* node, void* arg)
|
557
652
|
{
|
558
|
-
|
653
|
+
rb_yield(ASSOC(node));
|
559
654
|
return EACH_NEXT;
|
560
655
|
}
|
561
656
|
|
562
657
|
/*
|
563
658
|
* call-seq:
|
659
|
+
* rbtree.each {|key, value| block} => rbtree
|
564
660
|
* rbtree.each_pair {|key, value| block} => rbtree
|
661
|
+
* rbtree.each => enumerator
|
662
|
+
* rbtree.each_pair => enumerator
|
565
663
|
*
|
566
|
-
* 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
|
567
665
|
* as parameters.
|
666
|
+
*
|
667
|
+
* Returns an enumerator if no block is given.
|
568
668
|
*/
|
569
669
|
VALUE
|
570
670
|
rbtree_each_pair(VALUE self)
|
571
671
|
{
|
572
|
-
|
672
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
573
673
|
return rbtree_for_each(self, each_pair_i, NULL);
|
574
674
|
}
|
575
675
|
|
@@ -583,14 +683,17 @@ each_key_i(dnode_t* node, void* arg)
|
|
583
683
|
/*
|
584
684
|
* call-seq:
|
585
685
|
* rbtree.each_key {|key| block} => rbtree
|
686
|
+
* rbtree.each_key => enumerator
|
586
687
|
*
|
587
|
-
* Calls block once for each key in order, passing the key as
|
588
|
-
*
|
688
|
+
* Calls block once for each key in order, passing the key as a
|
689
|
+
* parameter.
|
690
|
+
*
|
691
|
+
* Returns an enumerator if no block is given.
|
589
692
|
*/
|
590
693
|
VALUE
|
591
694
|
rbtree_each_key(VALUE self)
|
592
695
|
{
|
593
|
-
|
696
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
594
697
|
return rbtree_for_each(self, each_key_i, NULL);
|
595
698
|
}
|
596
699
|
|
@@ -604,28 +707,34 @@ each_value_i(dnode_t* node, void* arg)
|
|
604
707
|
/*
|
605
708
|
* call-seq:
|
606
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.
|
607
714
|
*
|
608
|
-
*
|
609
|
-
* parameters.
|
715
|
+
* Returns an enumerator if no block is given.
|
610
716
|
*/
|
611
717
|
VALUE
|
612
718
|
rbtree_each_value(VALUE self)
|
613
719
|
{
|
614
|
-
|
720
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
615
721
|
return rbtree_for_each(self, each_value_i, NULL);
|
616
722
|
}
|
617
723
|
|
618
724
|
/*
|
619
725
|
* call-seq:
|
620
726
|
* rbtree.reverse_each {|key, value| block} => rbtree
|
727
|
+
* rbtree.reverse_each => enumerator
|
728
|
+
*
|
729
|
+
* Calls block once for each key in reverse order, passing the
|
730
|
+
* key-value pair as parameters.
|
621
731
|
*
|
622
|
-
*
|
623
|
-
* value as parameters.
|
732
|
+
* Returns an enumerator if no block is given.
|
624
733
|
*/
|
625
734
|
VALUE
|
626
735
|
rbtree_reverse_each(VALUE self)
|
627
736
|
{
|
628
|
-
|
737
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
629
738
|
return rbtree_reverse_for_each(self, each_pair_i, NULL);
|
630
739
|
}
|
631
740
|
|
@@ -637,11 +746,17 @@ aset_i(dnode_t* node, void* self)
|
|
637
746
|
}
|
638
747
|
|
639
748
|
static void
|
640
|
-
copy_dict(VALUE src, VALUE dest, dict_comp_t
|
749
|
+
copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
|
641
750
|
{
|
642
751
|
VALUE temp = rbtree_alloc(CLASS_OF(dest));
|
643
|
-
|
644
|
-
|
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
|
+
|
645
760
|
rbtree_for_each(src, aset_i, (void*)temp);
|
646
761
|
{
|
647
762
|
dict_t* t = DICT(temp);
|
@@ -649,7 +764,11 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
|
|
649
764
|
DICT(dest) = t;
|
650
765
|
}
|
651
766
|
rbtree_free(RBTREE(temp));
|
767
|
+
RBTREE(temp) = NULL;
|
652
768
|
rb_gc_force_recycle(temp);
|
769
|
+
|
770
|
+
DICT(dest)->dict_context = RBTREE(dest);
|
771
|
+
CMP_PROC(dest) = cmp_proc;
|
653
772
|
}
|
654
773
|
|
655
774
|
/*
|
@@ -658,16 +777,18 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
|
|
658
777
|
VALUE
|
659
778
|
rbtree_initialize_copy(VALUE self, VALUE other)
|
660
779
|
{
|
780
|
+
rbtree_modify(self);
|
781
|
+
|
661
782
|
if (self == other)
|
662
783
|
return self;
|
663
784
|
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
664
785
|
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
665
|
-
|
666
|
-
|
786
|
+
rb_obj_classname(other),
|
787
|
+
rb_obj_classname(self));
|
667
788
|
}
|
668
|
-
|
669
|
-
copy_dict(other, self,
|
670
|
-
|
789
|
+
|
790
|
+
copy_dict(other, self, DICT(other)->dict_compare, CMP_PROC(other));
|
791
|
+
|
671
792
|
IFNONE(self) = IFNONE(other);
|
672
793
|
if (FL_TEST(other, RBTREE_PROC_DEFAULT))
|
673
794
|
FL_SET(self, RBTREE_PROC_DEFAULT);
|
@@ -683,18 +804,21 @@ VALUE
|
|
683
804
|
rbtree_values_at(int argc, VALUE* argv, VALUE self)
|
684
805
|
{
|
685
806
|
long i;
|
686
|
-
VALUE ary =
|
687
|
-
|
807
|
+
VALUE ary = rb_ary_new2(argc);
|
808
|
+
|
688
809
|
for (i = 0; i < argc; i++)
|
689
810
|
rb_ary_push(ary, rbtree_aref(self, argv[i]));
|
690
811
|
return ary;
|
691
812
|
}
|
692
813
|
|
693
814
|
static each_return_t
|
694
|
-
|
815
|
+
key_i(dnode_t* node, void* args_)
|
695
816
|
{
|
696
|
-
|
697
|
-
|
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
|
+
}
|
698
822
|
return EACH_NEXT;
|
699
823
|
}
|
700
824
|
|
@@ -702,25 +826,13 @@ select_i(dnode_t* node, void* ary)
|
|
702
826
|
*
|
703
827
|
*/
|
704
828
|
VALUE
|
705
|
-
|
829
|
+
rbtree_key(VALUE self, VALUE value)
|
706
830
|
{
|
707
|
-
VALUE
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
return ary;
|
713
|
-
}
|
714
|
-
|
715
|
-
static each_return_t
|
716
|
-
index_i(dnode_t* node, void* arg_)
|
717
|
-
{
|
718
|
-
VALUE* arg = (VALUE*)arg_;
|
719
|
-
if (rb_equal(GET_VAL(node), arg[1])) {
|
720
|
-
arg[0] = GET_KEY(node);
|
721
|
-
return EACH_STOP;
|
722
|
-
}
|
723
|
-
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];
|
724
836
|
}
|
725
837
|
|
726
838
|
/*
|
@@ -729,11 +841,10 @@ index_i(dnode_t* node, void* arg_)
|
|
729
841
|
VALUE
|
730
842
|
rbtree_index(VALUE self, VALUE value)
|
731
843
|
{
|
732
|
-
VALUE
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
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);
|
737
848
|
}
|
738
849
|
|
739
850
|
/*
|
@@ -777,10 +888,11 @@ typedef struct {
|
|
777
888
|
VALUE self;
|
778
889
|
dnode_list_t* list;
|
779
890
|
int raised;
|
780
|
-
|
891
|
+
int if_true;
|
892
|
+
} rbtree_remove_if_arg_t;
|
781
893
|
|
782
894
|
static VALUE
|
783
|
-
|
895
|
+
rbtree_remove_if_ensure(rbtree_remove_if_arg_t* arg)
|
784
896
|
{
|
785
897
|
dict_t* dict = DICT(arg->self);
|
786
898
|
dnode_list_t* list = arg->list;
|
@@ -798,7 +910,7 @@ rbtree_delete_if_ensure(rbtree_delete_if_arg_t* arg)
|
|
798
910
|
}
|
799
911
|
|
800
912
|
static VALUE
|
801
|
-
|
913
|
+
rbtree_remove_if_body(rbtree_remove_if_arg_t* arg)
|
802
914
|
{
|
803
915
|
VALUE self = arg->self;
|
804
916
|
dict_t* dict = DICT(self);
|
@@ -810,7 +922,9 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
810
922
|
node != NULL;
|
811
923
|
node = dict_next(dict, node)) {
|
812
924
|
|
813
|
-
|
925
|
+
VALUE key = GET_KEY(node);
|
926
|
+
VALUE value = GET_VAL(node);
|
927
|
+
if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
|
814
928
|
dnode_list_t* l = ALLOC(dnode_list_t);
|
815
929
|
l->node = node;
|
816
930
|
l->prev = arg->list;
|
@@ -821,6 +935,20 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
821
935
|
return self;
|
822
936
|
}
|
823
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
|
+
|
824
952
|
/*********************************************************************/
|
825
953
|
|
826
954
|
/*
|
@@ -829,14 +957,16 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
|
|
829
957
|
VALUE
|
830
958
|
rbtree_delete_if(VALUE self)
|
831
959
|
{
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
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);
|
840
970
|
}
|
841
971
|
|
842
972
|
/*
|
@@ -846,8 +976,8 @@ VALUE
|
|
846
976
|
rbtree_reject_bang(VALUE self)
|
847
977
|
{
|
848
978
|
dictcount_t count;
|
849
|
-
|
850
|
-
|
979
|
+
|
980
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
|
851
981
|
count = dict_count(DICT(self));
|
852
982
|
rbtree_delete_if(self);
|
853
983
|
if (count == dict_count(DICT(self)))
|
@@ -855,13 +985,73 @@ rbtree_reject_bang(VALUE self)
|
|
855
985
|
return self;
|
856
986
|
}
|
857
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
|
+
|
858
1039
|
/*
|
859
1040
|
*
|
860
1041
|
*/
|
861
1042
|
VALUE
|
862
1043
|
rbtree_reject(VALUE self)
|
863
1044
|
{
|
864
|
-
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);
|
865
1055
|
}
|
866
1056
|
|
867
1057
|
static VALUE
|
@@ -869,32 +1059,28 @@ rbtree_shift_pop(VALUE self, const int shift)
|
|
869
1059
|
{
|
870
1060
|
dict_t* dict = DICT(self);
|
871
1061
|
dnode_t* node;
|
872
|
-
VALUE
|
1062
|
+
VALUE assoc;
|
873
1063
|
|
874
1064
|
rbtree_modify(self);
|
875
1065
|
|
876
|
-
if (dict_isempty(dict))
|
877
|
-
|
878
|
-
return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
|
879
|
-
}
|
880
|
-
return IFNONE(self);
|
881
|
-
}
|
1066
|
+
if (dict_isempty(dict))
|
1067
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
882
1068
|
|
883
1069
|
if (shift)
|
884
1070
|
node = dict_last(dict);
|
885
1071
|
else
|
886
1072
|
node = dict_first(dict);
|
887
|
-
|
1073
|
+
assoc = ASSOC(node);
|
888
1074
|
dict_delete_free(dict, node);
|
889
|
-
return
|
1075
|
+
return assoc;
|
890
1076
|
}
|
891
1077
|
|
892
1078
|
/*
|
893
1079
|
* call-seq:
|
894
|
-
* rbtree.shift => array or object
|
1080
|
+
* rbtree.shift => array or object or nil
|
895
1081
|
*
|
896
|
-
* Removes the first(that is, the smallest) key-value pair and
|
897
|
-
* it
|
1082
|
+
* Removes the first (that is, the smallest) key-value pair and
|
1083
|
+
* returns it.
|
898
1084
|
*/
|
899
1085
|
VALUE
|
900
1086
|
rbtree_shift(VALUE self)
|
@@ -904,10 +1090,10 @@ rbtree_shift(VALUE self)
|
|
904
1090
|
|
905
1091
|
/*
|
906
1092
|
* call-seq:
|
907
|
-
* rbtree.pop => array or object
|
1093
|
+
* rbtree.pop => array or object or nil
|
908
1094
|
*
|
909
|
-
* Removes the last(that is, the
|
910
|
-
* it
|
1095
|
+
* Removes the last (that is, the greatest) key-value pair and returns
|
1096
|
+
* it.
|
911
1097
|
*/
|
912
1098
|
VALUE
|
913
1099
|
rbtree_pop(VALUE self)
|
@@ -958,10 +1144,10 @@ rbtree_update(VALUE self, VALUE other)
|
|
958
1144
|
return self;
|
959
1145
|
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
960
1146
|
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
961
|
-
|
962
|
-
|
1147
|
+
rb_obj_classname(other),
|
1148
|
+
rb_obj_classname(self));
|
963
1149
|
}
|
964
|
-
|
1150
|
+
|
965
1151
|
if (rb_block_given_p())
|
966
1152
|
rbtree_for_each(other, update_block_i, (void*)self);
|
967
1153
|
else
|
@@ -978,6 +1164,35 @@ rbtree_merge(VALUE self, VALUE other)
|
|
978
1164
|
return rbtree_update(rb_obj_dup(self), other);
|
979
1165
|
}
|
980
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
|
+
|
981
1196
|
/*
|
982
1197
|
*
|
983
1198
|
*/
|
@@ -988,11 +1203,11 @@ rbtree_has_key(VALUE self, VALUE key)
|
|
988
1203
|
}
|
989
1204
|
|
990
1205
|
static each_return_t
|
991
|
-
has_value_i(dnode_t* node, void*
|
1206
|
+
has_value_i(dnode_t* node, void* args_)
|
992
1207
|
{
|
993
|
-
VALUE*
|
994
|
-
if (rb_equal(GET_VAL(node),
|
995
|
-
|
1208
|
+
VALUE* args = (VALUE*)args_;
|
1209
|
+
if (rb_equal(GET_VAL(node), args[1])) {
|
1210
|
+
args[0] = Qtrue;
|
996
1211
|
return EACH_STOP;
|
997
1212
|
}
|
998
1213
|
return EACH_NEXT;
|
@@ -1004,11 +1219,11 @@ has_value_i(dnode_t* node, void* arg_)
|
|
1004
1219
|
VALUE
|
1005
1220
|
rbtree_has_value(VALUE self, VALUE value)
|
1006
1221
|
{
|
1007
|
-
VALUE
|
1008
|
-
|
1009
|
-
|
1010
|
-
rbtree_for_each(self, has_value_i,
|
1011
|
-
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];
|
1012
1227
|
}
|
1013
1228
|
|
1014
1229
|
static each_return_t
|
@@ -1024,7 +1239,7 @@ keys_i(dnode_t* node, void* ary)
|
|
1024
1239
|
VALUE
|
1025
1240
|
rbtree_keys(VALUE self)
|
1026
1241
|
{
|
1027
|
-
VALUE ary =
|
1242
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1028
1243
|
rbtree_for_each(self, keys_i, (void*)ary);
|
1029
1244
|
return ary;
|
1030
1245
|
}
|
@@ -1042,9 +1257,9 @@ values_i(dnode_t* node, void* ary)
|
|
1042
1257
|
VALUE
|
1043
1258
|
rbtree_values(VALUE self)
|
1044
1259
|
{
|
1045
|
-
VALUE
|
1046
|
-
rbtree_for_each(self, values_i, (void*)
|
1047
|
-
return
|
1260
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1261
|
+
rbtree_for_each(self, values_i, (void*)ary);
|
1262
|
+
return ary;
|
1048
1263
|
}
|
1049
1264
|
|
1050
1265
|
static each_return_t
|
@@ -1060,7 +1275,7 @@ to_a_i(dnode_t* node, void* ary)
|
|
1060
1275
|
VALUE
|
1061
1276
|
rbtree_to_a(VALUE self)
|
1062
1277
|
{
|
1063
|
-
VALUE ary =
|
1278
|
+
VALUE ary = rb_ary_new2(dict_count(DICT(self)));
|
1064
1279
|
rbtree_for_each(self, to_a_i, (void*)ary);
|
1065
1280
|
OBJ_INFECT(ary, self);
|
1066
1281
|
return ary;
|
@@ -1069,7 +1284,7 @@ rbtree_to_a(VALUE self)
|
|
1069
1284
|
static each_return_t
|
1070
1285
|
to_hash_i(dnode_t* node, void* hash)
|
1071
1286
|
{
|
1072
|
-
|
1287
|
+
rb_hash_aset((VALUE)hash, GET_KEY(node), GET_VAL(node));
|
1073
1288
|
return EACH_NEXT;
|
1074
1289
|
}
|
1075
1290
|
|
@@ -1080,13 +1295,12 @@ VALUE
|
|
1080
1295
|
rbtree_to_hash(VALUE self)
|
1081
1296
|
{
|
1082
1297
|
VALUE hash;
|
1083
|
-
if (
|
1298
|
+
if (!rb_obj_is_kind_of(self, RBTree))
|
1084
1299
|
rb_raise(rb_eTypeError, "can't convert MultiRBTree to Hash");
|
1085
|
-
|
1086
|
-
|
1300
|
+
|
1087
1301
|
hash = rb_hash_new();
|
1088
1302
|
rbtree_for_each(self, to_hash_i, (void*)hash);
|
1089
|
-
|
1303
|
+
RHASH_SET_IFNONE(hash, IFNONE(self));
|
1090
1304
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
1091
1305
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
1092
1306
|
OBJ_INFECT(hash, self);
|
@@ -1105,91 +1319,60 @@ rbtree_to_rbtree(VALUE self)
|
|
1105
1319
|
static VALUE
|
1106
1320
|
rbtree_begin_inspect(VALUE self)
|
1107
1321
|
{
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
return
|
1112
|
-
}
|
1113
|
-
|
1114
|
-
static VALUE
|
1115
|
-
to_s_rbtree(VALUE self, VALUE nil)
|
1116
|
-
{
|
1117
|
-
return rb_ary_to_s(rbtree_to_a(self));
|
1118
|
-
}
|
1119
|
-
|
1120
|
-
#ifdef HAVE_RB_EXEC_RECURSIVE
|
1121
|
-
static VALUE
|
1122
|
-
rbtree_to_s_recursive(VALUE self, VALUE arg, int recursive)
|
1123
|
-
{
|
1124
|
-
if (recursive)
|
1125
|
-
return rb_str_cat2(rbtree_begin_inspect(self), "...>");
|
1126
|
-
return to_s_rbtree(self, Qnil);
|
1127
|
-
}
|
1128
|
-
#endif
|
1129
|
-
|
1130
|
-
/*
|
1131
|
-
*
|
1132
|
-
*/
|
1133
|
-
VALUE
|
1134
|
-
rbtree_to_s(VALUE self)
|
1135
|
-
{
|
1136
|
-
#ifdef HAVE_RB_EXEC_RECURSIVE
|
1137
|
-
return rb_exec_recursive(rbtree_to_s_recursive, self, Qnil);
|
1138
|
-
#else
|
1139
|
-
if (rb_inspecting_p(self))
|
1140
|
-
return rb_str_cat2(rbtree_begin_inspect(self), "...>");
|
1141
|
-
return rb_protect_inspect(to_s_rbtree, self, Qnil);
|
1142
|
-
#endif
|
1322
|
+
VALUE result = rb_str_new2("#<");
|
1323
|
+
rb_str_cat2(result, rb_obj_classname(self));
|
1324
|
+
rb_str_cat2(result, ": ");
|
1325
|
+
return result;
|
1143
1326
|
}
|
1144
1327
|
|
1145
1328
|
static each_return_t
|
1146
|
-
inspect_i(dnode_t* node, void*
|
1329
|
+
inspect_i(dnode_t* node, void* result_)
|
1147
1330
|
{
|
1148
|
-
VALUE
|
1331
|
+
VALUE result = (VALUE)result_;
|
1149
1332
|
VALUE str;
|
1150
1333
|
|
1151
|
-
if (RSTRING_PTR(
|
1152
|
-
RSTRING_PTR(
|
1334
|
+
if (RSTRING_PTR(result)[0] == '-')
|
1335
|
+
RSTRING_PTR(result)[0] = '#';
|
1153
1336
|
else
|
1154
|
-
rb_str_cat2(
|
1337
|
+
rb_str_cat2(result, ", ");
|
1155
1338
|
|
1156
1339
|
str = rb_inspect(GET_KEY(node));
|
1157
|
-
rb_str_append(
|
1158
|
-
OBJ_INFECT(
|
1340
|
+
rb_str_append(result, str);
|
1341
|
+
OBJ_INFECT(result, str);
|
1159
1342
|
|
1160
|
-
rb_str_cat2(
|
1343
|
+
rb_str_cat2(result, "=>");
|
1161
1344
|
|
1162
1345
|
str = rb_inspect(GET_VAL(node));
|
1163
|
-
rb_str_append(
|
1164
|
-
OBJ_INFECT(
|
1346
|
+
rb_str_append(result, str);
|
1347
|
+
OBJ_INFECT(result, str);
|
1165
1348
|
|
1166
1349
|
return EACH_NEXT;
|
1167
1350
|
}
|
1168
1351
|
|
1169
1352
|
static VALUE
|
1170
|
-
inspect_rbtree(VALUE self, VALUE
|
1353
|
+
inspect_rbtree(VALUE self, VALUE result)
|
1171
1354
|
{
|
1172
1355
|
VALUE str;
|
1173
|
-
|
1174
|
-
rb_str_cat2(
|
1175
|
-
RSTRING_PTR(
|
1176
|
-
rbtree_for_each(self, inspect_i, (void*)
|
1177
|
-
RSTRING_PTR(
|
1178
|
-
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, "}");
|
1179
1362
|
|
1180
1363
|
str = rb_inspect(IFNONE(self));
|
1181
|
-
rb_str_cat2(
|
1182
|
-
rb_str_append(
|
1183
|
-
OBJ_INFECT(
|
1184
|
-
|
1185
|
-
str = rb_inspect((VALUE)CONTEXT(self));
|
1186
|
-
rb_str_cat2(ret, ", cmp_proc=");
|
1187
|
-
rb_str_append(ret, str);
|
1188
|
-
OBJ_INFECT(ret, str);
|
1364
|
+
rb_str_cat2(result, ", default=");
|
1365
|
+
rb_str_append(result, str);
|
1366
|
+
OBJ_INFECT(result, str);
|
1189
1367
|
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
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);
|
1372
|
+
|
1373
|
+
rb_str_cat2(result, ">");
|
1374
|
+
OBJ_INFECT(result, self);
|
1375
|
+
return result;
|
1193
1376
|
}
|
1194
1377
|
|
1195
1378
|
static VALUE
|
@@ -1219,11 +1402,20 @@ rbtree_inspect(VALUE self)
|
|
1219
1402
|
|
1220
1403
|
/*
|
1221
1404
|
* call-seq:
|
1222
|
-
* rbtree.lower_bound(key) => array
|
1405
|
+
* rbtree.lower_bound(key) => array or nil
|
1223
1406
|
*
|
1224
|
-
* Retruns key-value pair corresponding to the lowest key that is
|
1225
|
-
* 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
|
1226
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
|
1227
1419
|
*/
|
1228
1420
|
VALUE
|
1229
1421
|
rbtree_lower_bound(VALUE self, VALUE key)
|
@@ -1236,11 +1428,20 @@ rbtree_lower_bound(VALUE self, VALUE key)
|
|
1236
1428
|
|
1237
1429
|
/*
|
1238
1430
|
* call-seq:
|
1239
|
-
* 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]
|
1240
1442
|
*
|
1241
|
-
*
|
1242
|
-
*
|
1243
|
-
* there is no such key, returns nil.
|
1443
|
+
* # no key that is equal to or lower than "a"
|
1444
|
+
* rbtree.upper_bound("a") # => nil
|
1244
1445
|
*/
|
1245
1446
|
VALUE
|
1246
1447
|
rbtree_upper_bound(VALUE self, VALUE key)
|
@@ -1257,7 +1458,7 @@ typedef struct {
|
|
1257
1458
|
VALUE self;
|
1258
1459
|
dnode_t* lower_node;
|
1259
1460
|
dnode_t* upper_node;
|
1260
|
-
VALUE
|
1461
|
+
VALUE result;
|
1261
1462
|
} rbtree_bound_arg_t;
|
1262
1463
|
|
1263
1464
|
static VALUE
|
@@ -1268,33 +1469,75 @@ rbtree_bound_body(rbtree_bound_arg_t* arg)
|
|
1268
1469
|
dnode_t* lower_node = arg->lower_node;
|
1269
1470
|
dnode_t* upper_node = arg->upper_node;
|
1270
1471
|
const int block_given = rb_block_given_p();
|
1271
|
-
VALUE
|
1472
|
+
VALUE result = arg->result;
|
1272
1473
|
dnode_t* node;
|
1273
1474
|
|
1274
1475
|
ITER_LEV(self)++;
|
1275
|
-
for (node = lower_node
|
1476
|
+
for (node = lower_node;
|
1477
|
+
node != NULL;
|
1276
1478
|
node = dict_next(dict, node)) {
|
1277
1479
|
|
1278
1480
|
if (block_given)
|
1279
1481
|
rb_yield_values(2, GET_KEY(node), GET_VAL(node));
|
1280
1482
|
else
|
1281
|
-
rb_ary_push(
|
1483
|
+
rb_ary_push(result, ASSOC(node));
|
1282
1484
|
if (node == upper_node)
|
1283
1485
|
break;
|
1284
1486
|
}
|
1285
|
-
return
|
1487
|
+
return result;
|
1286
1488
|
}
|
1287
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);
|
1518
|
+
}
|
1519
|
+
#endif
|
1520
|
+
|
1288
1521
|
/*********************************************************************/
|
1289
1522
|
|
1290
1523
|
/*
|
1291
1524
|
* call-seq:
|
1292
|
-
* rbtree.bound(key1, key2 = key1) => array
|
1293
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.
|
1532
|
+
*
|
1533
|
+
* Returns an enumerator if no block is given.
|
1294
1534
|
*
|
1295
|
-
*
|
1296
|
-
*
|
1297
|
-
*
|
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 # => []
|
1298
1541
|
*/
|
1299
1542
|
VALUE
|
1300
1543
|
rbtree_bound(int argc, VALUE* argv, VALUE self)
|
@@ -1302,27 +1545,27 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
|
|
1302
1545
|
dict_t* dict = DICT(self);
|
1303
1546
|
dnode_t* lower_node;
|
1304
1547
|
dnode_t* upper_node;
|
1305
|
-
VALUE
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1548
|
+
VALUE result;
|
1549
|
+
|
1550
|
+
rbtree_check_argument_count(argc, 1, 2);
|
1551
|
+
|
1552
|
+
RETURN_SIZED_ENUMERATOR(self, argc, argv, rbtree_bound_size);
|
1553
|
+
|
1310
1554
|
lower_node = dict_lower_bound(dict, TO_KEY(argv[0]));
|
1311
1555
|
upper_node = dict_upper_bound(dict, TO_KEY(argv[argc - 1]));
|
1312
|
-
|
1313
|
-
|
1556
|
+
result = rb_block_given_p() ? self : rb_ary_new();
|
1557
|
+
|
1314
1558
|
if (lower_node == NULL || upper_node == NULL ||
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
return
|
1559
|
+
DICT(self)->dict_compare(dnode_getkey(lower_node),
|
1560
|
+
dnode_getkey(upper_node),
|
1561
|
+
DICT(self)->dict_context) > 0) {
|
1562
|
+
return result;
|
1319
1563
|
} else {
|
1320
1564
|
rbtree_bound_arg_t arg;
|
1321
1565
|
arg.self = self;
|
1322
1566
|
arg.lower_node = lower_node;
|
1323
1567
|
arg.upper_node = upper_node;
|
1324
|
-
arg.
|
1325
|
-
|
1568
|
+
arg.result = result;
|
1326
1569
|
return rb_ensure(rbtree_bound_body, (VALUE)&arg,
|
1327
1570
|
rbtree_each_ensure, self);
|
1328
1571
|
}
|
@@ -1334,13 +1577,9 @@ rbtree_first_last(VALUE self, const int first)
|
|
1334
1577
|
dict_t* dict = DICT(self);
|
1335
1578
|
dnode_t* node;
|
1336
1579
|
|
1337
|
-
if (dict_isempty(dict))
|
1338
|
-
|
1339
|
-
|
1340
|
-
}
|
1341
|
-
return IFNONE(self);
|
1342
|
-
}
|
1343
|
-
|
1580
|
+
if (dict_isempty(dict))
|
1581
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
1582
|
+
|
1344
1583
|
if (first)
|
1345
1584
|
node = dict_first(dict);
|
1346
1585
|
else
|
@@ -1350,9 +1589,9 @@ rbtree_first_last(VALUE self, const int first)
|
|
1350
1589
|
|
1351
1590
|
/*
|
1352
1591
|
* call-seq:
|
1353
|
-
* rbtree.first => array or object
|
1592
|
+
* rbtree.first => array or object or nil
|
1354
1593
|
*
|
1355
|
-
* Returns the first(that is, the smallest) key-value pair.
|
1594
|
+
* Returns the first (that is, the smallest) key-value pair.
|
1356
1595
|
*/
|
1357
1596
|
VALUE
|
1358
1597
|
rbtree_first(VALUE self)
|
@@ -1362,9 +1601,9 @@ rbtree_first(VALUE self)
|
|
1362
1601
|
|
1363
1602
|
/*
|
1364
1603
|
* call-seq:
|
1365
|
-
* rbtree.last => array
|
1604
|
+
* rbtree.last => array or object or nil
|
1366
1605
|
*
|
1367
|
-
* Returns the last(that is, the
|
1606
|
+
* Returns the last (that is, the greatest) key-value pair.
|
1368
1607
|
*/
|
1369
1608
|
VALUE
|
1370
1609
|
rbtree_last(VALUE self)
|
@@ -1380,121 +1619,212 @@ rbtree_last(VALUE self)
|
|
1380
1619
|
* rbtree.readjust {|key1, key2| block} => rbtree
|
1381
1620
|
*
|
1382
1621
|
* Sets a proc to compare keys and readjusts elements using the given
|
1383
|
-
* block or a Proc object given as
|
1384
|
-
*
|
1385
|
-
*
|
1386
|
-
* second one. If no block is given
|
1387
|
-
* current comparison block. If nil is given as
|
1388
|
-
* 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]
|
1389
1635
|
*/
|
1390
1636
|
VALUE
|
1391
1637
|
rbtree_readjust(int argc, VALUE* argv, VALUE self)
|
1392
1638
|
{
|
1393
|
-
dict_comp_t
|
1394
|
-
|
1395
|
-
|
1639
|
+
dict_comp_t cmp_func = NULL;
|
1640
|
+
VALUE cmp_proc = Qnil;
|
1641
|
+
|
1396
1642
|
rbtree_modify(self);
|
1397
1643
|
|
1398
|
-
if (
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
cmp = rbtree_cmp;
|
1409
|
-
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);
|
1410
1654
|
} else {
|
1411
|
-
if (
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
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
|
+
}
|
1417
1669
|
}
|
1418
|
-
} else {
|
1419
|
-
rbtree_argc_error();
|
1420
1670
|
}
|
1421
1671
|
|
1422
1672
|
if (dict_isempty(DICT(self))) {
|
1423
|
-
|
1424
|
-
|
1673
|
+
DICT(self)->dict_compare = cmp_func;
|
1674
|
+
CMP_PROC(self) = cmp_proc;
|
1425
1675
|
return self;
|
1426
1676
|
}
|
1427
|
-
copy_dict(self, self,
|
1677
|
+
copy_dict(self, self, cmp_func, cmp_proc);
|
1428
1678
|
return self;
|
1429
1679
|
}
|
1430
1680
|
|
1431
1681
|
/*
|
1432
1682
|
* call-seq:
|
1433
|
-
* rbtree.cmp_proc => proc
|
1683
|
+
* rbtree.cmp_proc => proc or nil
|
1434
1684
|
*
|
1435
|
-
* 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.
|
1436
1688
|
*/
|
1437
1689
|
VALUE
|
1438
1690
|
rbtree_cmp_proc(VALUE self)
|
1439
1691
|
{
|
1440
|
-
return (
|
1692
|
+
return CMP_PROC(self);
|
1441
1693
|
}
|
1442
1694
|
|
1443
1695
|
/*********************************************************************/
|
1444
1696
|
|
1697
|
+
static ID id_breakable;
|
1445
1698
|
static ID id_comma_breakable;
|
1699
|
+
static ID id_group;
|
1446
1700
|
static ID id_object_group;
|
1447
1701
|
static ID id_pp;
|
1448
|
-
static ID id_pp_hash;
|
1449
1702
|
static ID id_text;
|
1450
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
|
+
|
1451
1711
|
typedef struct {
|
1452
|
-
VALUE rbtree;
|
1453
1712
|
VALUE pp;
|
1454
|
-
|
1713
|
+
dnode_t* node;
|
1714
|
+
} pp_pair_arg_t;
|
1455
1715
|
|
1456
1716
|
static VALUE
|
1457
|
-
|
1717
|
+
pp_value(VALUE nil, pp_pair_arg_t* pair_arg)
|
1458
1718
|
{
|
1459
|
-
|
1460
|
-
|
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);
|
1461
1737
|
}
|
1462
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
|
+
|
1463
1774
|
static VALUE
|
1464
|
-
|
1775
|
+
pp_each_pair(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
|
1465
1776
|
{
|
1466
|
-
|
1467
|
-
|
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);
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
static VALUE
|
1784
|
+
pp_rbtree(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
|
1785
|
+
{
|
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("}");
|
1468
1794
|
|
1469
1795
|
rb_funcall(pp, id_text, 1, rb_str_new2(": "));
|
1470
|
-
|
1796
|
+
rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
|
1471
1797
|
rb_funcall(pp, id_comma_breakable, 0);
|
1472
1798
|
rb_funcall(pp, id_text, 1, rb_str_new2("default="));
|
1473
1799
|
rb_funcall(pp, id_pp, 1, IFNONE(rbtree));
|
1474
1800
|
rb_funcall(pp, id_comma_breakable, 0);
|
1475
1801
|
rb_funcall(pp, id_text, 1, rb_str_new2("cmp_proc="));
|
1476
|
-
rb_funcall(pp, id_pp, 1,
|
1477
|
-
|
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);
|
1478
1810
|
}
|
1479
1811
|
|
1480
1812
|
/*********************************************************************/
|
1481
1813
|
|
1482
|
-
/*
|
1483
|
-
*
|
1814
|
+
/* :nodoc:
|
1815
|
+
*
|
1484
1816
|
*/
|
1485
1817
|
VALUE
|
1486
1818
|
rbtree_pretty_print(VALUE self, VALUE pp)
|
1487
1819
|
{
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
return rb_iterate(pp_object_group, (VALUE)&pp_arg,
|
1493
|
-
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);
|
1494
1824
|
}
|
1495
1825
|
|
1496
|
-
/*
|
1497
|
-
*
|
1826
|
+
/* :nodoc:
|
1827
|
+
*
|
1498
1828
|
*/
|
1499
1829
|
VALUE
|
1500
1830
|
rbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
@@ -1504,114 +1834,66 @@ rbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
|
1504
1834
|
|
1505
1835
|
/*********************************************************************/
|
1506
1836
|
|
1507
|
-
|
1508
|
-
|
1509
|
-
{
|
1510
|
-
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1511
|
-
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1512
|
-
return EACH_NEXT;
|
1513
|
-
}
|
1514
|
-
|
1515
|
-
/*********************************************************************/
|
1516
|
-
|
1517
|
-
/*
|
1518
|
-
* Called by Marshal.dump.
|
1837
|
+
/* :nodoc:
|
1838
|
+
*
|
1519
1839
|
*/
|
1520
1840
|
VALUE
|
1521
1841
|
rbtree_dump(VALUE self, VALUE limit)
|
1522
1842
|
{
|
1523
1843
|
VALUE ary;
|
1524
|
-
VALUE
|
1525
|
-
|
1844
|
+
VALUE result;
|
1845
|
+
|
1526
1846
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
1527
|
-
rb_raise(rb_eTypeError, "
|
1528
|
-
if ((
|
1529
|
-
rb_raise(rb_eTypeError, "
|
1530
|
-
|
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
|
+
|
1531
1851
|
ary = rb_ary_new2(dict_count(DICT(self)) * 2 + 1);
|
1532
|
-
rbtree_for_each(self,
|
1852
|
+
rbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1533
1853
|
rb_ary_push(ary, IFNONE(self));
|
1534
1854
|
|
1535
|
-
|
1855
|
+
result = rb_marshal_dump(ary, Qnil);
|
1856
|
+
#ifdef HAVE_RB_ARY_RESIZE
|
1857
|
+
rb_ary_resize(ary, 0);
|
1858
|
+
#else
|
1536
1859
|
rb_ary_clear(ary);
|
1537
|
-
|
1538
|
-
return
|
1860
|
+
#endif
|
1861
|
+
return result;
|
1539
1862
|
}
|
1540
1863
|
|
1541
|
-
/*
|
1542
|
-
*
|
1864
|
+
/* :nodoc:
|
1865
|
+
*
|
1543
1866
|
*/
|
1544
1867
|
VALUE
|
1545
1868
|
rbtree_s_load(VALUE klass, VALUE str)
|
1546
1869
|
{
|
1547
1870
|
VALUE rbtree = rbtree_alloc(klass);
|
1548
1871
|
VALUE ary = rb_marshal_load(str);
|
1549
|
-
VALUE* ptr = RARRAY_PTR(ary);
|
1550
1872
|
long len = RARRAY_LEN(ary) - 1;
|
1551
1873
|
long i;
|
1552
|
-
|
1874
|
+
|
1553
1875
|
for (i = 0; i < len; i += 2)
|
1554
|
-
rbtree_aset(rbtree,
|
1555
|
-
IFNONE(rbtree) =
|
1556
|
-
|
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
|
1557
1882
|
rb_ary_clear(ary);
|
1558
|
-
|
1883
|
+
#endif
|
1559
1884
|
return rbtree;
|
1560
1885
|
}
|
1561
1886
|
|
1562
1887
|
/*********************************************************************/
|
1563
1888
|
|
1564
1889
|
/*
|
1565
|
-
*
|
1566
|
-
*
|
1567
|
-
*
|
1568
|
-
|
1569
|
-
|
1570
|
-
*
|
1571
|
-
*
|
1572
|
-
* for insert, search and delete is O(log N) in expected and worst
|
1573
|
-
* case. On the other hand the complexity of Hash is O(1). Because
|
1574
|
-
* Hash is unordered the data structure is more effective than
|
1575
|
-
* Red-Black Tree as an associative collection.
|
1576
|
-
*
|
1577
|
-
* The elements of RBTree are sorted with natural ordering (by <=>
|
1578
|
-
* method) of its keys or by a comparator(Proc) set by readjust
|
1579
|
-
* method. It means all keys in RBTree should be comparable with each
|
1580
|
-
* other. Or a comparator that takes two arguments of a key should return
|
1581
|
-
* negative, 0, or positive depending on the first argument is less than,
|
1582
|
-
* equal to, or greater than the second one.
|
1583
|
-
*
|
1584
|
-
* The interface of RBTree is the almost same as Hash and there are a
|
1585
|
-
* few methods to take advantage of the ordering:
|
1586
|
-
*
|
1587
|
-
* * lower_bound, upper_bound, bound
|
1588
|
-
* * first, last
|
1589
|
-
* * shift, pop
|
1590
|
-
* * reverse_each
|
1591
|
-
*
|
1592
|
-
* Note: while iterating RBTree (e.g. in a block of each method), it is
|
1593
|
-
* not modifiable, or TypeError is thrown.
|
1594
|
-
*
|
1595
|
-
* RBTree supoorts pretty printing using pp.
|
1596
|
-
*
|
1597
|
-
* This library contains two classes. One is RBTree and the other is
|
1598
|
-
* MultiRBTree that is a parent class of RBTree. RBTree does not allow
|
1599
|
-
* duplications of keys but MultiRBTree does.
|
1600
|
-
*
|
1601
|
-
* require "rbtree"
|
1602
|
-
*
|
1603
|
-
* rbtree = RBTree["c", 10, "a", 20]
|
1604
|
-
* rbtree["b"] = 30
|
1605
|
-
* p rbtree["b"] # => 30
|
1606
|
-
* rbtree.each do |k, v|
|
1607
|
-
* p [k, v]
|
1608
|
-
* end # => ["a", 20] ["b", 30] ["c", 10]
|
1609
|
-
*
|
1610
|
-
* mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
|
1611
|
-
* p mrbtree.lower_bound("b") # => ["c", 10]
|
1612
|
-
* mrbtree.bound("a", "d") do |k, v|
|
1613
|
-
* p [k, v]
|
1614
|
-
* 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.
|
1615
1897
|
*/
|
1616
1898
|
void Init_rbtree()
|
1617
1899
|
{
|
@@ -1628,10 +1910,11 @@ void Init_rbtree()
|
|
1628
1910
|
rb_define_method(MultiRBTree, "initialize_copy", rbtree_initialize_copy, 1);
|
1629
1911
|
|
1630
1912
|
rb_define_method(MultiRBTree, "to_a", rbtree_to_a, 0);
|
1631
|
-
rb_define_method(MultiRBTree, "
|
1913
|
+
rb_define_method(MultiRBTree, "to_h", rbtree_to_hash, 0);
|
1632
1914
|
rb_define_method(MultiRBTree, "to_hash", rbtree_to_hash, 0);
|
1633
1915
|
rb_define_method(MultiRBTree, "to_rbtree", rbtree_to_rbtree, 0);
|
1634
1916
|
rb_define_method(MultiRBTree, "inspect", rbtree_inspect, 0);
|
1917
|
+
rb_define_alias(MultiRBTree, "to_s", "inspect");
|
1635
1918
|
|
1636
1919
|
rb_define_method(MultiRBTree, "==", rbtree_equal, 1);
|
1637
1920
|
rb_define_method(MultiRBTree, "[]", rbtree_aref, 1);
|
@@ -1646,12 +1929,14 @@ void Init_rbtree()
|
|
1646
1929
|
rb_define_method(MultiRBTree, "default", rbtree_default, -1);
|
1647
1930
|
rb_define_method(MultiRBTree, "default=", rbtree_set_default, 1);
|
1648
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);
|
1649
1934
|
rb_define_method(MultiRBTree, "index", rbtree_index, 1);
|
1650
1935
|
rb_define_method(MultiRBTree, "empty?", rbtree_empty_p, 0);
|
1651
1936
|
rb_define_method(MultiRBTree, "size", rbtree_size, 0);
|
1652
1937
|
rb_define_method(MultiRBTree, "length", rbtree_size, 0);
|
1653
1938
|
|
1654
|
-
rb_define_method(MultiRBTree, "each",
|
1939
|
+
rb_define_method(MultiRBTree, "each", rbtree_each_pair, 0);
|
1655
1940
|
rb_define_method(MultiRBTree, "each_value", rbtree_each_value, 0);
|
1656
1941
|
rb_define_method(MultiRBTree, "each_key", rbtree_each_key, 0);
|
1657
1942
|
rb_define_method(MultiRBTree, "each_pair", rbtree_each_pair, 0);
|
@@ -1665,15 +1950,20 @@ void Init_rbtree()
|
|
1665
1950
|
rb_define_method(MultiRBTree, "pop", rbtree_pop, 0);
|
1666
1951
|
rb_define_method(MultiRBTree, "delete", rbtree_delete, 1);
|
1667
1952
|
rb_define_method(MultiRBTree, "delete_if", rbtree_delete_if, 0);
|
1668
|
-
rb_define_method(MultiRBTree, "
|
1953
|
+
rb_define_method(MultiRBTree, "keep_if", rbtree_keep_if, 0);
|
1669
1954
|
rb_define_method(MultiRBTree, "reject", rbtree_reject, 0);
|
1670
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);
|
1671
1958
|
rb_define_method(MultiRBTree, "clear", rbtree_clear, 0);
|
1672
1959
|
rb_define_method(MultiRBTree, "invert", rbtree_invert, 0);
|
1673
1960
|
rb_define_method(MultiRBTree, "update", rbtree_update, 1);
|
1674
1961
|
rb_define_method(MultiRBTree, "merge!", rbtree_update, 1);
|
1675
1962
|
rb_define_method(MultiRBTree, "merge", rbtree_merge, 1);
|
1676
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
|
1677
1967
|
|
1678
1968
|
rb_define_method(MultiRBTree, "include?", rbtree_has_key, 1);
|
1679
1969
|
rb_define_method(MultiRBTree, "member?", rbtree_has_key, 1);
|
@@ -1687,20 +1977,20 @@ void Init_rbtree()
|
|
1687
1977
|
|
1688
1978
|
rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
|
1689
1979
|
rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
|
1690
|
-
|
1691
|
-
id_bound = rb_intern("bound");
|
1980
|
+
|
1692
1981
|
id_cmp = rb_intern("<=>");
|
1693
1982
|
id_call = rb_intern("call");
|
1694
1983
|
id_default = rb_intern("default");
|
1695
|
-
|
1984
|
+
id_flatten_bang = rb_intern("flatten!");
|
1696
1985
|
|
1697
1986
|
rb_define_method(MultiRBTree, "pretty_print", rbtree_pretty_print, 1);
|
1698
1987
|
rb_define_method(MultiRBTree,
|
1699
1988
|
"pretty_print_cycle", rbtree_pretty_print_cycle, 1);
|
1700
1989
|
|
1990
|
+
id_breakable = rb_intern("breakable");
|
1701
1991
|
id_comma_breakable = rb_intern("comma_breakable");
|
1992
|
+
id_group = rb_intern("group");
|
1702
1993
|
id_object_group = rb_intern("object_group");
|
1703
|
-
id_pp_hash = rb_intern("pp_hash");
|
1704
|
-
id_text = rb_intern("text");
|
1705
1994
|
id_pp = rb_intern("pp");
|
1995
|
+
id_text = rb_intern("text");
|
1706
1996
|
}
|