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