llrbtree 0.0.1
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/.gitignore +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/README.md +38 -0
- data/Rakefile +17 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/llrbtree/depend +2 -0
- data/ext/llrbtree/extconf.rb +8 -0
- data/ext/llrbtree/llrbtree.c +1942 -0
- data/ext/llrbtree/tree.c +478 -0
- data/ext/llrbtree/tree.h +63 -0
- data/lib/llrbtree/version.rb +3 -0
- data/lib/llrbtree.rb +2 -0
- data/llrbtree.gemspec +25 -0
- metadata +116 -0
@@ -0,0 +1,1942 @@
|
|
1
|
+
/*
|
2
|
+
* MIT License
|
3
|
+
* Copyright (c) 2002-2013 OZAWA Takuma
|
4
|
+
*/
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <ruby/st.h>
|
7
|
+
#include "tree.h"
|
8
|
+
|
9
|
+
#define LLRBTREE_PROC_DEFAULT FL_USER2
|
10
|
+
#define HASH_PROC_DEFAULT FL_USER2
|
11
|
+
|
12
|
+
#ifdef RETURN_SIZED_ENUMERATOR
|
13
|
+
#define HAVE_SIZED_ENUMERATOR
|
14
|
+
#else
|
15
|
+
#ifdef RETURN_ENUMERATOR
|
16
|
+
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) RETURN_ENUMERATOR(obj, argc, argv)
|
17
|
+
#else
|
18
|
+
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) ((void)0)
|
19
|
+
#endif
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifndef RARRAY_AREF
|
23
|
+
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifndef RHASH_SET_IFNONE
|
27
|
+
#define RHASH_SET_IFNONE(h, v) (RHASH(h)->ifnone = (v))
|
28
|
+
#endif
|
29
|
+
|
30
|
+
VALUE LLRBTree;
|
31
|
+
|
32
|
+
static ID id_cmp;
|
33
|
+
static ID id_call;
|
34
|
+
static ID id_default;
|
35
|
+
static ID id_flatten_bang;
|
36
|
+
static ID id_marshal;
|
37
|
+
static ID id_dump;
|
38
|
+
|
39
|
+
typedef struct {
|
40
|
+
tree_t* tree;
|
41
|
+
VALUE ifnone;
|
42
|
+
VALUE cmp_proc;
|
43
|
+
int iter_lev;
|
44
|
+
} llrbtree_t;
|
45
|
+
|
46
|
+
#define LLRBTREE(llrbtree) DATA_PTR(llrbtree)
|
47
|
+
#define TREE(llrbtree) ((llrbtree_t*)LLRBTREE(llrbtree))->tree
|
48
|
+
#define IFNONE(llrbtree) ((llrbtree_t*)LLRBTREE(llrbtree))->ifnone
|
49
|
+
#define CMP_PROC(llrbtree) ((llrbtree_t*)LLRBTREE(llrbtree))->cmp_proc
|
50
|
+
#define ITER_LEV(llrbtree) ((llrbtree_t*)LLRBTREE(llrbtree))->iter_lev
|
51
|
+
|
52
|
+
#define TO_KEY(arg) ((const void*)arg)
|
53
|
+
#define TO_VAL(arg) ((void*)arg)
|
54
|
+
#define GET_KEY(node) ((VALUE)node->key)
|
55
|
+
#define GET_VAL(node) ((VALUE)node->data)
|
56
|
+
#define ASSOC(node) rb_assoc_new(GET_KEY(node), GET_VAL(node))
|
57
|
+
|
58
|
+
/*********************************************************************/
|
59
|
+
|
60
|
+
static void
|
61
|
+
llrbtree_free(llrbtree_t* llrbtree)
|
62
|
+
{
|
63
|
+
tree_free(llrbtree->tree);
|
64
|
+
xfree(llrbtree->tree);
|
65
|
+
xfree(llrbtree);
|
66
|
+
}
|
67
|
+
|
68
|
+
static void
|
69
|
+
llrbtree_mark(llrbtree_t* llrbtree)
|
70
|
+
{
|
71
|
+
if (llrbtree == NULL) return;
|
72
|
+
|
73
|
+
if (llrbtree->tree != NULL) {
|
74
|
+
tree_t* tree = llrbtree->tree;
|
75
|
+
node_t* node;
|
76
|
+
for (node = tree_first(tree);
|
77
|
+
node != NULL;
|
78
|
+
node = tree_next(tree, node)) {
|
79
|
+
|
80
|
+
rb_gc_mark(GET_KEY(node));
|
81
|
+
rb_gc_mark(GET_VAL(node));
|
82
|
+
}
|
83
|
+
}
|
84
|
+
rb_gc_mark(llrbtree->ifnone);
|
85
|
+
rb_gc_mark(llrbtree->cmp_proc);
|
86
|
+
}
|
87
|
+
|
88
|
+
static node_t*
|
89
|
+
llrbtree_alloc_node(void* context)
|
90
|
+
{
|
91
|
+
return ALLOC(node_t);
|
92
|
+
}
|
93
|
+
|
94
|
+
static void
|
95
|
+
llrbtree_free_node(node_t* node, void* context)
|
96
|
+
{
|
97
|
+
xfree(node);
|
98
|
+
}
|
99
|
+
|
100
|
+
static void
|
101
|
+
llrbtree_check_argument_count(const int argc, const int min, const int max)
|
102
|
+
{
|
103
|
+
if (argc < min || argc > max) {
|
104
|
+
static const char* const message = "wrong number of arguments";
|
105
|
+
if (min == max) {
|
106
|
+
rb_raise(rb_eArgError, "%s (%d for %d)", message, argc, min);
|
107
|
+
} else if (max == INT_MAX) {
|
108
|
+
rb_raise(rb_eArgError, "%s (%d for %d+)", message, argc, -min - 1);
|
109
|
+
} else {
|
110
|
+
rb_raise(rb_eArgError, "%s (%d for %d..%d)", message, argc, min, max);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
static void
|
116
|
+
llrbtree_check_proc_arity(VALUE proc, const int expected)
|
117
|
+
{
|
118
|
+
if (rb_proc_lambda_p(proc)) {
|
119
|
+
const int arity = rb_proc_arity(proc);
|
120
|
+
const int min = arity < 0 ? -arity - 1 : arity;
|
121
|
+
const int max = arity < 0 ? INT_MAX : arity;
|
122
|
+
if (expected < min || expected > max) {
|
123
|
+
rb_raise(rb_eTypeError, "proc takes %d arguments", expected);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
static int
|
129
|
+
llrbtree_cmp(const void* key1, const void* key2, void* context)
|
130
|
+
{
|
131
|
+
VALUE result;
|
132
|
+
if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
|
133
|
+
return rb_str_cmp((VALUE)key1, (VALUE)key2);
|
134
|
+
result = rb_funcall2((VALUE)key1, id_cmp, 1, (VALUE*)&key2);
|
135
|
+
return rb_cmpint(result, (VALUE)key1, (VALUE)key2);
|
136
|
+
}
|
137
|
+
|
138
|
+
static VALUE
|
139
|
+
llrbtree_user_cmp_ensure(llrbtree_t* llrbtree)
|
140
|
+
{
|
141
|
+
llrbtree->iter_lev--;
|
142
|
+
return Qnil;
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE
|
146
|
+
llrbtree_user_cmp_body(VALUE* args)
|
147
|
+
{
|
148
|
+
llrbtree_t* llrbtree = (llrbtree_t*)args[2];
|
149
|
+
llrbtree->iter_lev++;
|
150
|
+
return rb_funcall2(llrbtree->cmp_proc, id_call, 2, args);
|
151
|
+
}
|
152
|
+
|
153
|
+
static int
|
154
|
+
llrbtree_user_cmp(const void* key1, const void* key2, void* context)
|
155
|
+
{
|
156
|
+
llrbtree_t* llrbtree = (llrbtree_t*)context;
|
157
|
+
VALUE args[3];
|
158
|
+
VALUE result;
|
159
|
+
|
160
|
+
args[0] = (VALUE)key1;
|
161
|
+
args[1] = (VALUE)key2;
|
162
|
+
args[2] = (VALUE)llrbtree;
|
163
|
+
result = rb_ensure(llrbtree_user_cmp_body, (VALUE)&args,
|
164
|
+
llrbtree_user_cmp_ensure, (VALUE)llrbtree);
|
165
|
+
return rb_cmpint(result, (VALUE)key1, (VALUE)key2);
|
166
|
+
}
|
167
|
+
|
168
|
+
static void
|
169
|
+
llrbtree_modify(VALUE self)
|
170
|
+
{
|
171
|
+
if (ITER_LEV(self) > 0)
|
172
|
+
rb_raise(rb_eTypeError, "can't modify llrbtree during iteration");
|
173
|
+
rb_check_frozen(self);
|
174
|
+
if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
|
175
|
+
rb_raise(rb_eSecurityError, "Insecure: can't modify llrbtree");
|
176
|
+
}
|
177
|
+
|
178
|
+
static VALUE
|
179
|
+
llrbtree_alloc(VALUE klass)
|
180
|
+
{
|
181
|
+
tree_t* tree;
|
182
|
+
VALUE llrbtree = Data_Wrap_Struct(klass, llrbtree_mark, llrbtree_free, NULL);
|
183
|
+
LLRBTREE(llrbtree) = ALLOC(llrbtree_t);
|
184
|
+
MEMZERO(LLRBTREE(llrbtree), llrbtree_t, 1);
|
185
|
+
|
186
|
+
tree = ALLOC(tree_t);
|
187
|
+
tree_init(tree, llrbtree_cmp, llrbtree_alloc_node, llrbtree_free_node, LLRBTREE(llrbtree));
|
188
|
+
|
189
|
+
TREE(llrbtree) = tree;
|
190
|
+
IFNONE(llrbtree) = Qnil;
|
191
|
+
CMP_PROC(llrbtree) = Qnil;
|
192
|
+
return llrbtree;
|
193
|
+
}
|
194
|
+
|
195
|
+
VALUE llrbtree_aset(VALUE, VALUE, VALUE);
|
196
|
+
VALUE llrbtree_has_key(VALUE, VALUE);
|
197
|
+
VALUE llrbtree_update(VALUE, VALUE);
|
198
|
+
VALUE llrbtree_to_a(VALUE);
|
199
|
+
|
200
|
+
/*********************************************************************/
|
201
|
+
|
202
|
+
static int
|
203
|
+
hash_to_llrbtree_i(VALUE key, VALUE value, VALUE llrbtree)
|
204
|
+
{
|
205
|
+
if (key != Qundef)
|
206
|
+
llrbtree_aset(llrbtree, key, value);
|
207
|
+
return ST_CONTINUE;
|
208
|
+
}
|
209
|
+
|
210
|
+
/*
|
211
|
+
*
|
212
|
+
*/
|
213
|
+
VALUE
|
214
|
+
llrbtree_s_create(int argc, VALUE* argv, VALUE klass)
|
215
|
+
{
|
216
|
+
long i;
|
217
|
+
VALUE llrbtree;
|
218
|
+
|
219
|
+
if (argc == 1) {
|
220
|
+
VALUE temp;
|
221
|
+
|
222
|
+
if (rb_obj_is_kind_of(argv[0], klass)) {
|
223
|
+
llrbtree = llrbtree_alloc(klass);
|
224
|
+
llrbtree_update(llrbtree, argv[0]);
|
225
|
+
return llrbtree;
|
226
|
+
}
|
227
|
+
|
228
|
+
temp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
|
229
|
+
if (!NIL_P(temp)) {
|
230
|
+
llrbtree = llrbtree_alloc(klass);
|
231
|
+
rb_hash_foreach(temp, hash_to_llrbtree_i, llrbtree);
|
232
|
+
return llrbtree;
|
233
|
+
}
|
234
|
+
|
235
|
+
temp = rb_check_array_type(argv[0]);
|
236
|
+
if (!NIL_P(temp)) {
|
237
|
+
llrbtree = llrbtree_alloc(klass);
|
238
|
+
for (i = 0; i < RARRAY_LEN(temp); i++) {
|
239
|
+
VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
|
240
|
+
if (NIL_P(v)) {
|
241
|
+
rb_warn("wrong element type %s at %ld (expected Array)",
|
242
|
+
rb_obj_classname(RARRAY_AREF(temp, i)), i);
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
switch(RARRAY_LEN(v)) {
|
246
|
+
case 1:
|
247
|
+
llrbtree_aset(llrbtree, RARRAY_AREF(v, 0), Qnil);
|
248
|
+
break;
|
249
|
+
case 2:
|
250
|
+
llrbtree_aset(llrbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
|
251
|
+
break;
|
252
|
+
default:
|
253
|
+
rb_warn("invalid number of elements (%ld for 1..2)",
|
254
|
+
RARRAY_LEN(v));
|
255
|
+
}
|
256
|
+
}
|
257
|
+
return llrbtree;
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
if (argc % 2 != 0)
|
262
|
+
rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));
|
263
|
+
|
264
|
+
llrbtree = llrbtree_alloc(klass);
|
265
|
+
for (i = 0; i < argc; i += 2)
|
266
|
+
llrbtree_aset(llrbtree, argv[i], argv[i + 1]);
|
267
|
+
return llrbtree;
|
268
|
+
}
|
269
|
+
|
270
|
+
/*
|
271
|
+
*
|
272
|
+
*/
|
273
|
+
VALUE
|
274
|
+
llrbtree_initialize(int argc, VALUE* argv, VALUE self)
|
275
|
+
{
|
276
|
+
llrbtree_modify(self);
|
277
|
+
|
278
|
+
if (rb_block_given_p()) {
|
279
|
+
VALUE proc;
|
280
|
+
llrbtree_check_argument_count(argc, 0, 0);
|
281
|
+
proc = rb_block_proc();
|
282
|
+
llrbtree_check_proc_arity(proc, 2);
|
283
|
+
IFNONE(self) = proc;
|
284
|
+
FL_SET(self, LLRBTREE_PROC_DEFAULT);
|
285
|
+
} else {
|
286
|
+
llrbtree_check_argument_count(argc, 0, 1);
|
287
|
+
if (argc == 1) {
|
288
|
+
IFNONE(self) = argv[0];
|
289
|
+
}
|
290
|
+
}
|
291
|
+
return self;
|
292
|
+
}
|
293
|
+
|
294
|
+
/*********************************************************************/
|
295
|
+
|
296
|
+
typedef enum {
|
297
|
+
NoNodeInserted,
|
298
|
+
KeyAllocationFailed,
|
299
|
+
InsertionSucceeded
|
300
|
+
} insert_result_t;
|
301
|
+
|
302
|
+
typedef struct {
|
303
|
+
tree_t* tree;
|
304
|
+
node_t* node;
|
305
|
+
insert_result_t result;
|
306
|
+
} llrbtree_insert_arg_t;
|
307
|
+
|
308
|
+
static VALUE
|
309
|
+
insert_node_body(llrbtree_insert_arg_t* arg)
|
310
|
+
{
|
311
|
+
tree_t* tree = arg->tree;
|
312
|
+
node_t* node = arg->node;
|
313
|
+
|
314
|
+
if (tree_insert(tree, node, node->key)) {
|
315
|
+
if (TYPE(GET_KEY(node)) == T_STRING) {
|
316
|
+
arg->result = KeyAllocationFailed;
|
317
|
+
node->key = TO_KEY(rb_str_new4(GET_KEY(node)));
|
318
|
+
}
|
319
|
+
} else {
|
320
|
+
tree->free_node(node, tree->context);
|
321
|
+
}
|
322
|
+
arg->result = InsertionSucceeded;
|
323
|
+
return Qnil;
|
324
|
+
}
|
325
|
+
|
326
|
+
static VALUE
|
327
|
+
insert_node_ensure(llrbtree_insert_arg_t* arg)
|
328
|
+
{
|
329
|
+
tree_t* tree = arg->tree;
|
330
|
+
node_t* node = arg->node;
|
331
|
+
|
332
|
+
switch (arg->result) {
|
333
|
+
case InsertionSucceeded:
|
334
|
+
break;
|
335
|
+
case NoNodeInserted:
|
336
|
+
tree->free_node(node, tree->context);
|
337
|
+
break;
|
338
|
+
case KeyAllocationFailed:
|
339
|
+
tree_delete(tree, node->key);
|
340
|
+
break;
|
341
|
+
}
|
342
|
+
return Qnil;
|
343
|
+
}
|
344
|
+
|
345
|
+
static void
|
346
|
+
llrbtree_insert(VALUE self, VALUE key, VALUE value)
|
347
|
+
{
|
348
|
+
llrbtree_insert_arg_t arg;
|
349
|
+
tree_t* tree = TREE(self);
|
350
|
+
node_t* node = tree->alloc_node(tree->context);
|
351
|
+
|
352
|
+
node_init(node, TO_VAL(value));
|
353
|
+
node->key = TO_KEY(key);
|
354
|
+
|
355
|
+
arg.tree = tree;
|
356
|
+
arg.node = node;
|
357
|
+
arg.result = NoNodeInserted;
|
358
|
+
|
359
|
+
rb_ensure(insert_node_body, (VALUE)&arg,
|
360
|
+
insert_node_ensure, (VALUE)&arg);
|
361
|
+
}
|
362
|
+
|
363
|
+
/*********************************************************************/
|
364
|
+
|
365
|
+
/*
|
366
|
+
*
|
367
|
+
*/
|
368
|
+
VALUE
|
369
|
+
llrbtree_aset(VALUE self, VALUE key, VALUE value)
|
370
|
+
{
|
371
|
+
llrbtree_modify(self);
|
372
|
+
|
373
|
+
if (tree_isfull(TREE(self))) {
|
374
|
+
node_t* node = tree_lookup(TREE(self), TO_KEY(key));
|
375
|
+
if (node == NULL)
|
376
|
+
rb_raise(rb_eIndexError, "llrbtree full");
|
377
|
+
else
|
378
|
+
node->data = TO_VAL(value);
|
379
|
+
return value;
|
380
|
+
}
|
381
|
+
llrbtree_insert(self, key, value);
|
382
|
+
return value;
|
383
|
+
}
|
384
|
+
|
385
|
+
/*
|
386
|
+
*
|
387
|
+
*/
|
388
|
+
VALUE
|
389
|
+
llrbtree_aref(VALUE self, VALUE key)
|
390
|
+
{
|
391
|
+
node_t* node = tree_lookup(TREE(self), TO_KEY(key));
|
392
|
+
if (node == NULL)
|
393
|
+
return rb_funcall2(self, id_default, 1, &key);
|
394
|
+
else
|
395
|
+
return GET_VAL(node);
|
396
|
+
}
|
397
|
+
|
398
|
+
/*
|
399
|
+
*
|
400
|
+
*/
|
401
|
+
VALUE
|
402
|
+
llrbtree_fetch(int argc, VALUE* argv, VALUE self)
|
403
|
+
{
|
404
|
+
node_t* node;
|
405
|
+
|
406
|
+
llrbtree_check_argument_count(argc, 1, 2);
|
407
|
+
if (argc == 2 && rb_block_given_p()) {
|
408
|
+
rb_warn("block supersedes default value argument");
|
409
|
+
}
|
410
|
+
|
411
|
+
node = tree_lookup(TREE(self), TO_KEY(argv[0]));
|
412
|
+
if (node != NULL) {
|
413
|
+
return GET_VAL(node);
|
414
|
+
}
|
415
|
+
|
416
|
+
if (rb_block_given_p()) {
|
417
|
+
return rb_yield(argv[0]);
|
418
|
+
}
|
419
|
+
if (argc == 1) {
|
420
|
+
rb_raise(rb_eIndexError, "key not found");
|
421
|
+
}
|
422
|
+
return argv[1];
|
423
|
+
}
|
424
|
+
|
425
|
+
/*
|
426
|
+
*
|
427
|
+
*/
|
428
|
+
VALUE
|
429
|
+
llrbtree_size(VALUE self)
|
430
|
+
{
|
431
|
+
return ULONG2NUM(TREE(self)->node_count);
|
432
|
+
}
|
433
|
+
|
434
|
+
/*
|
435
|
+
*
|
436
|
+
*/
|
437
|
+
VALUE
|
438
|
+
llrbtree_empty_p(VALUE self)
|
439
|
+
{
|
440
|
+
return tree_isempty(TREE(self)) ? Qtrue : Qfalse;
|
441
|
+
}
|
442
|
+
|
443
|
+
/*
|
444
|
+
*
|
445
|
+
*/
|
446
|
+
VALUE
|
447
|
+
llrbtree_default(int argc, VALUE* argv, VALUE self)
|
448
|
+
{
|
449
|
+
llrbtree_check_argument_count(argc, 0, 1);
|
450
|
+
if (FL_TEST(self, LLRBTREE_PROC_DEFAULT)) {
|
451
|
+
if (argc == 0) {
|
452
|
+
return Qnil;
|
453
|
+
}
|
454
|
+
return rb_funcall(IFNONE(self), id_call, 2, self, argv[0]);
|
455
|
+
}
|
456
|
+
return IFNONE(self);
|
457
|
+
}
|
458
|
+
|
459
|
+
/*
|
460
|
+
*
|
461
|
+
*/
|
462
|
+
VALUE
|
463
|
+
llrbtree_set_default(VALUE self, VALUE ifnone)
|
464
|
+
{
|
465
|
+
llrbtree_modify(self);
|
466
|
+
IFNONE(self) = ifnone;
|
467
|
+
FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
|
468
|
+
return ifnone;
|
469
|
+
}
|
470
|
+
|
471
|
+
/*
|
472
|
+
*
|
473
|
+
*/
|
474
|
+
VALUE
|
475
|
+
llrbtree_default_proc(VALUE self)
|
476
|
+
{
|
477
|
+
if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
|
478
|
+
return IFNONE(self);
|
479
|
+
return Qnil;
|
480
|
+
}
|
481
|
+
|
482
|
+
/*
|
483
|
+
*
|
484
|
+
*/
|
485
|
+
VALUE
|
486
|
+
llrbtree_set_default_proc(VALUE self, VALUE proc)
|
487
|
+
{
|
488
|
+
VALUE temp;
|
489
|
+
|
490
|
+
llrbtree_modify(self);
|
491
|
+
if (NIL_P(proc)) {
|
492
|
+
IFNONE(self) = Qnil;
|
493
|
+
FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
|
494
|
+
return Qnil;
|
495
|
+
}
|
496
|
+
|
497
|
+
temp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
498
|
+
if (NIL_P(temp)) {
|
499
|
+
rb_raise(rb_eTypeError,
|
500
|
+
"wrong default_proc type %s (expected Proc)",
|
501
|
+
rb_obj_classname(proc));
|
502
|
+
}
|
503
|
+
llrbtree_check_proc_arity(temp, 2);
|
504
|
+
IFNONE(self) = temp;
|
505
|
+
FL_SET(self, LLRBTREE_PROC_DEFAULT);
|
506
|
+
return proc;
|
507
|
+
}
|
508
|
+
|
509
|
+
static VALUE
|
510
|
+
llrbtree_recursive_equal(VALUE self, VALUE other, int recursive)
|
511
|
+
{
|
512
|
+
tree_t* tree1 = TREE(self);
|
513
|
+
tree_t* tree2 = TREE(other);
|
514
|
+
node_t* node1;
|
515
|
+
node_t* node2;
|
516
|
+
|
517
|
+
if (recursive)
|
518
|
+
return Qtrue;
|
519
|
+
for (node1 = tree_first(tree1), node2 = tree_first(tree2);
|
520
|
+
node1 != NULL && node2 != NULL;
|
521
|
+
node1 = tree_next(tree1, node1), node2 = tree_next(tree2, node2)) {
|
522
|
+
|
523
|
+
if (!rb_equal(GET_KEY(node1), GET_KEY(node2)) ||
|
524
|
+
!rb_equal(GET_VAL(node1), GET_VAL(node2))) {
|
525
|
+
|
526
|
+
return Qfalse;
|
527
|
+
}
|
528
|
+
}
|
529
|
+
return Qtrue;
|
530
|
+
}
|
531
|
+
|
532
|
+
/*
|
533
|
+
*
|
534
|
+
*/
|
535
|
+
VALUE
|
536
|
+
llrbtree_equal(VALUE self, VALUE other)
|
537
|
+
{
|
538
|
+
if (self == other)
|
539
|
+
return Qtrue;
|
540
|
+
if (!rb_obj_is_kind_of(other, LLRBTree))
|
541
|
+
return Qfalse;
|
542
|
+
if (TREE(self)->node_count != TREE(other)->node_count ||
|
543
|
+
TREE(self)->compare != TREE(other)->compare ||
|
544
|
+
CMP_PROC(self) != CMP_PROC(other)) {
|
545
|
+
|
546
|
+
return Qfalse;
|
547
|
+
}
|
548
|
+
return rb_exec_recursive_paired(llrbtree_recursive_equal, self, other, other);
|
549
|
+
}
|
550
|
+
|
551
|
+
/*********************************************************************/
|
552
|
+
|
553
|
+
typedef enum {
|
554
|
+
EACH_NEXT, EACH_STOP
|
555
|
+
} each_return_t;
|
556
|
+
|
557
|
+
typedef each_return_t (*each_callback_func)(node_t*, void*);
|
558
|
+
|
559
|
+
typedef struct {
|
560
|
+
VALUE self;
|
561
|
+
each_callback_func func;
|
562
|
+
void* arg;
|
563
|
+
int reverse;
|
564
|
+
} llrbtree_each_arg_t;
|
565
|
+
|
566
|
+
static VALUE
|
567
|
+
llrbtree_each_ensure(VALUE self)
|
568
|
+
{
|
569
|
+
ITER_LEV(self)--;
|
570
|
+
return Qnil;
|
571
|
+
}
|
572
|
+
|
573
|
+
static VALUE
|
574
|
+
llrbtree_each_body(llrbtree_each_arg_t* arg)
|
575
|
+
{
|
576
|
+
VALUE self = arg->self;
|
577
|
+
tree_t* tree = TREE(self);
|
578
|
+
node_t* node;
|
579
|
+
node_t* first_node;
|
580
|
+
node_t* (*next_func)(tree_t*, node_t*);
|
581
|
+
|
582
|
+
if (arg->reverse) {
|
583
|
+
first_node = tree_last(tree);
|
584
|
+
next_func = tree_prev;
|
585
|
+
} else {
|
586
|
+
first_node = tree_first(tree);
|
587
|
+
next_func = tree_next;
|
588
|
+
}
|
589
|
+
|
590
|
+
ITER_LEV(self)++;
|
591
|
+
for (node = first_node;
|
592
|
+
node != NULL;
|
593
|
+
node = next_func(tree, node)) {
|
594
|
+
|
595
|
+
if (arg->func(node, arg->arg) == EACH_STOP)
|
596
|
+
break;
|
597
|
+
}
|
598
|
+
return self;
|
599
|
+
}
|
600
|
+
|
601
|
+
static VALUE
|
602
|
+
llrbtree_for_each(VALUE self, each_callback_func func, void* arg)
|
603
|
+
{
|
604
|
+
llrbtree_each_arg_t each_arg;
|
605
|
+
each_arg.self = self;
|
606
|
+
each_arg.func = func;
|
607
|
+
each_arg.arg = arg;
|
608
|
+
each_arg.reverse = 0;
|
609
|
+
return rb_ensure(llrbtree_each_body, (VALUE)&each_arg,
|
610
|
+
llrbtree_each_ensure, self);
|
611
|
+
}
|
612
|
+
|
613
|
+
static VALUE
|
614
|
+
llrbtree_reverse_for_each(VALUE self, each_callback_func func, void* arg)
|
615
|
+
{
|
616
|
+
llrbtree_each_arg_t each_arg;
|
617
|
+
each_arg.self = self;
|
618
|
+
each_arg.func = func;
|
619
|
+
each_arg.arg = arg;
|
620
|
+
each_arg.reverse = 1;
|
621
|
+
return rb_ensure(llrbtree_each_body, (VALUE)&each_arg,
|
622
|
+
llrbtree_each_ensure, self);
|
623
|
+
}
|
624
|
+
|
625
|
+
/*********************************************************************/
|
626
|
+
|
627
|
+
static each_return_t
|
628
|
+
each_pair_i(node_t* node, void* arg)
|
629
|
+
{
|
630
|
+
rb_yield(ASSOC(node));
|
631
|
+
return EACH_NEXT;
|
632
|
+
}
|
633
|
+
|
634
|
+
/*
|
635
|
+
* call-seq:
|
636
|
+
* llrbtree.each {|key, value| block} => llrbtree
|
637
|
+
* llrbtree.each_pair {|key, value| block} => llrbtree
|
638
|
+
* llrbtree.each => enumerator
|
639
|
+
* llrbtree.each_pair => enumerator
|
640
|
+
*
|
641
|
+
* Calls block once for each key in order, passing the key-value pair
|
642
|
+
* as parameters.
|
643
|
+
*
|
644
|
+
* Returns an enumerator if no block is given.
|
645
|
+
*/
|
646
|
+
VALUE
|
647
|
+
llrbtree_each_pair(VALUE self)
|
648
|
+
{
|
649
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
650
|
+
return llrbtree_for_each(self, each_pair_i, NULL);
|
651
|
+
}
|
652
|
+
|
653
|
+
static each_return_t
|
654
|
+
each_key_i(node_t* node, void* arg)
|
655
|
+
{
|
656
|
+
rb_yield(GET_KEY(node));
|
657
|
+
return EACH_NEXT;
|
658
|
+
}
|
659
|
+
|
660
|
+
/*
|
661
|
+
* call-seq:
|
662
|
+
* llrbtree.each_key {|key| block} => llrbtree
|
663
|
+
* llrbtree.each_key => enumerator
|
664
|
+
*
|
665
|
+
* Calls block once for each key in order, passing the key as a
|
666
|
+
* parameter.
|
667
|
+
*
|
668
|
+
* Returns an enumerator if no block is given.
|
669
|
+
*/
|
670
|
+
VALUE
|
671
|
+
llrbtree_each_key(VALUE self)
|
672
|
+
{
|
673
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
674
|
+
return llrbtree_for_each(self, each_key_i, NULL);
|
675
|
+
}
|
676
|
+
|
677
|
+
static each_return_t
|
678
|
+
each_value_i(node_t* node, void* arg)
|
679
|
+
{
|
680
|
+
rb_yield(GET_VAL(node));
|
681
|
+
return EACH_NEXT;
|
682
|
+
}
|
683
|
+
|
684
|
+
/*
|
685
|
+
* call-seq:
|
686
|
+
* llrbtree.each_value {|value| block} => llrbtree
|
687
|
+
* llrbtree.each_value => enumerator
|
688
|
+
*
|
689
|
+
* Calls block once for each key in order, passing the value as a
|
690
|
+
* parameter.
|
691
|
+
*
|
692
|
+
* Returns an enumerator if no block is given.
|
693
|
+
*/
|
694
|
+
VALUE
|
695
|
+
llrbtree_each_value(VALUE self)
|
696
|
+
{
|
697
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
698
|
+
return llrbtree_for_each(self, each_value_i, NULL);
|
699
|
+
}
|
700
|
+
|
701
|
+
/*
|
702
|
+
* call-seq:
|
703
|
+
* llrbtree.reverse_each {|key, value| block} => llrbtree
|
704
|
+
* llrbtree.reverse_each => enumerator
|
705
|
+
*
|
706
|
+
* Calls block once for each key in reverse order, passing the
|
707
|
+
* key-value pair as parameters.
|
708
|
+
*
|
709
|
+
* Returns an enumerator if no block is given.
|
710
|
+
*/
|
711
|
+
VALUE
|
712
|
+
llrbtree_reverse_each(VALUE self)
|
713
|
+
{
|
714
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
715
|
+
return llrbtree_reverse_for_each(self, each_pair_i, NULL);
|
716
|
+
}
|
717
|
+
|
718
|
+
static each_return_t
|
719
|
+
aset_i(node_t* node, void* self)
|
720
|
+
{
|
721
|
+
llrbtree_aset((VALUE)self, GET_KEY(node), GET_VAL(node));
|
722
|
+
return EACH_NEXT;
|
723
|
+
}
|
724
|
+
|
725
|
+
static void
|
726
|
+
copy_tree(VALUE src, VALUE dest, compare_t cmp_func, VALUE cmp_proc)
|
727
|
+
{
|
728
|
+
VALUE temp = llrbtree_alloc(CLASS_OF(dest));
|
729
|
+
rb_obj_hide(temp);
|
730
|
+
TREE(temp)->compare = cmp_func;
|
731
|
+
CMP_PROC(temp) = cmp_proc;
|
732
|
+
|
733
|
+
llrbtree_for_each(src, aset_i, (void*)temp);
|
734
|
+
{
|
735
|
+
tree_t* t = TREE(temp);
|
736
|
+
TREE(temp) = TREE(dest);
|
737
|
+
TREE(dest) = t;
|
738
|
+
}
|
739
|
+
llrbtree_free(LLRBTREE(temp));
|
740
|
+
LLRBTREE(temp) = NULL;
|
741
|
+
rb_gc_force_recycle(temp);
|
742
|
+
|
743
|
+
TREE(dest)->context = LLRBTREE(dest);
|
744
|
+
CMP_PROC(dest) = cmp_proc;
|
745
|
+
}
|
746
|
+
|
747
|
+
/*
|
748
|
+
*
|
749
|
+
*/
|
750
|
+
VALUE
|
751
|
+
llrbtree_initialize_copy(VALUE self, VALUE other)
|
752
|
+
{
|
753
|
+
llrbtree_modify(self);
|
754
|
+
|
755
|
+
if (self == other)
|
756
|
+
return self;
|
757
|
+
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
758
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
759
|
+
rb_obj_classname(other),
|
760
|
+
rb_obj_classname(self));
|
761
|
+
}
|
762
|
+
|
763
|
+
copy_tree(other, self, TREE(other)->compare, CMP_PROC(other));
|
764
|
+
|
765
|
+
IFNONE(self) = IFNONE(other);
|
766
|
+
if (FL_TEST(other, LLRBTREE_PROC_DEFAULT))
|
767
|
+
FL_SET(self, LLRBTREE_PROC_DEFAULT);
|
768
|
+
else
|
769
|
+
FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
|
770
|
+
return self;
|
771
|
+
}
|
772
|
+
|
773
|
+
/*
|
774
|
+
*
|
775
|
+
*/
|
776
|
+
VALUE
|
777
|
+
llrbtree_values_at(int argc, VALUE* argv, VALUE self)
|
778
|
+
{
|
779
|
+
long i;
|
780
|
+
VALUE ary = rb_ary_new2(argc);
|
781
|
+
|
782
|
+
for (i = 0; i < argc; i++)
|
783
|
+
rb_ary_push(ary, llrbtree_aref(self, argv[i]));
|
784
|
+
return ary;
|
785
|
+
}
|
786
|
+
|
787
|
+
static each_return_t
|
788
|
+
key_i(node_t* node, void* args_)
|
789
|
+
{
|
790
|
+
VALUE* args = (VALUE*)args_;
|
791
|
+
if (rb_equal(GET_VAL(node), args[1])) {
|
792
|
+
args[0] = GET_KEY(node);
|
793
|
+
return EACH_STOP;
|
794
|
+
}
|
795
|
+
return EACH_NEXT;
|
796
|
+
}
|
797
|
+
|
798
|
+
/*
|
799
|
+
*
|
800
|
+
*/
|
801
|
+
VALUE
|
802
|
+
llrbtree_key(VALUE self, VALUE value)
|
803
|
+
{
|
804
|
+
VALUE args[2];
|
805
|
+
args[0] = Qnil;
|
806
|
+
args[1] = value;
|
807
|
+
llrbtree_for_each(self, key_i, &args);
|
808
|
+
return args[0];
|
809
|
+
}
|
810
|
+
|
811
|
+
/*
|
812
|
+
*
|
813
|
+
*/
|
814
|
+
VALUE
|
815
|
+
llrbtree_index(VALUE self, VALUE value)
|
816
|
+
{
|
817
|
+
const char* classname = rb_class2name(LLRBTree);
|
818
|
+
rb_warn("%s#index is deprecated; use %s#key", classname, classname);
|
819
|
+
return llrbtree_key(self, value);
|
820
|
+
}
|
821
|
+
|
822
|
+
/*
|
823
|
+
*
|
824
|
+
*/
|
825
|
+
VALUE
|
826
|
+
llrbtree_clear(VALUE self)
|
827
|
+
{
|
828
|
+
llrbtree_modify(self);
|
829
|
+
tree_free(TREE(self));
|
830
|
+
return self;
|
831
|
+
}
|
832
|
+
|
833
|
+
/*
|
834
|
+
*
|
835
|
+
*/
|
836
|
+
VALUE
|
837
|
+
llrbtree_delete(VALUE self, VALUE key)
|
838
|
+
{
|
839
|
+
tree_t* tree = TREE(self);
|
840
|
+
node_t* node;
|
841
|
+
VALUE value;
|
842
|
+
|
843
|
+
llrbtree_modify(self);
|
844
|
+
node = tree_lookup(tree, TO_KEY(key));
|
845
|
+
if (node == NULL)
|
846
|
+
return rb_block_given_p() ? rb_yield(key) : Qnil;
|
847
|
+
value = GET_VAL(node);
|
848
|
+
tree_delete(tree, TO_KEY(key));
|
849
|
+
return value;
|
850
|
+
}
|
851
|
+
|
852
|
+
/*********************************************************************/
|
853
|
+
|
854
|
+
typedef struct node_list_t_ {
|
855
|
+
struct node_list_t_* prev;
|
856
|
+
node_t* node;
|
857
|
+
} node_list_t;
|
858
|
+
|
859
|
+
typedef struct {
|
860
|
+
VALUE self;
|
861
|
+
node_list_t* list;
|
862
|
+
int raised;
|
863
|
+
int if_true;
|
864
|
+
} llrbtree_remove_if_arg_t;
|
865
|
+
|
866
|
+
static VALUE
|
867
|
+
llrbtree_remove_if_ensure(llrbtree_remove_if_arg_t* arg)
|
868
|
+
{
|
869
|
+
tree_t* tree = TREE(arg->self);
|
870
|
+
node_list_t* list = arg->list;
|
871
|
+
|
872
|
+
if (--ITER_LEV(arg->self) == 0) {
|
873
|
+
while (list != NULL) {
|
874
|
+
node_list_t* l = list;
|
875
|
+
if (!arg->raised)
|
876
|
+
tree_delete(tree, l->node->key);
|
877
|
+
list = l->prev;
|
878
|
+
xfree(l);
|
879
|
+
}
|
880
|
+
}
|
881
|
+
return Qnil;
|
882
|
+
}
|
883
|
+
|
884
|
+
static VALUE
|
885
|
+
llrbtree_remove_if_body(llrbtree_remove_if_arg_t* arg)
|
886
|
+
{
|
887
|
+
VALUE self = arg->self;
|
888
|
+
tree_t* tree = TREE(self);
|
889
|
+
node_t* node;
|
890
|
+
|
891
|
+
arg->raised = 1;
|
892
|
+
ITER_LEV(self)++;
|
893
|
+
for (node = tree_first(tree);
|
894
|
+
node != NULL;
|
895
|
+
node = tree_next(tree, node)) {
|
896
|
+
|
897
|
+
VALUE key = GET_KEY(node);
|
898
|
+
VALUE value = GET_VAL(node);
|
899
|
+
if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
|
900
|
+
node_list_t* l = ALLOC(node_list_t);
|
901
|
+
l->node = node;
|
902
|
+
l->prev = arg->list;
|
903
|
+
arg->list = l;
|
904
|
+
}
|
905
|
+
}
|
906
|
+
arg->raised = 0;
|
907
|
+
return self;
|
908
|
+
}
|
909
|
+
|
910
|
+
static VALUE
|
911
|
+
llrbtree_remove_if(VALUE self, const int if_true)
|
912
|
+
{
|
913
|
+
llrbtree_remove_if_arg_t arg;
|
914
|
+
|
915
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
916
|
+
llrbtree_modify(self);
|
917
|
+
arg.self = self;
|
918
|
+
arg.list = NULL;
|
919
|
+
arg.if_true = if_true;
|
920
|
+
return rb_ensure(llrbtree_remove_if_body, (VALUE)&arg,
|
921
|
+
llrbtree_remove_if_ensure, (VALUE)&arg);
|
922
|
+
}
|
923
|
+
|
924
|
+
/*********************************************************************/
|
925
|
+
|
926
|
+
/*
|
927
|
+
*
|
928
|
+
*/
|
929
|
+
VALUE
|
930
|
+
llrbtree_delete_if(VALUE self)
|
931
|
+
{
|
932
|
+
return llrbtree_remove_if(self, 1);
|
933
|
+
}
|
934
|
+
|
935
|
+
/*
|
936
|
+
*
|
937
|
+
*/
|
938
|
+
VALUE
|
939
|
+
llrbtree_keep_if(VALUE self)
|
940
|
+
{
|
941
|
+
return llrbtree_remove_if(self, 0);
|
942
|
+
}
|
943
|
+
|
944
|
+
/*
|
945
|
+
*
|
946
|
+
*/
|
947
|
+
VALUE
|
948
|
+
llrbtree_reject_bang(VALUE self)
|
949
|
+
{
|
950
|
+
node_count_t count;
|
951
|
+
|
952
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
953
|
+
count = TREE(self)->node_count;
|
954
|
+
llrbtree_delete_if(self);
|
955
|
+
if (count == TREE(self)->node_count)
|
956
|
+
return Qnil;
|
957
|
+
return self;
|
958
|
+
}
|
959
|
+
|
960
|
+
/*
|
961
|
+
*
|
962
|
+
*/
|
963
|
+
VALUE
|
964
|
+
llrbtree_select_bang(VALUE self)
|
965
|
+
{
|
966
|
+
node_count_t count;
|
967
|
+
|
968
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
969
|
+
count = TREE(self)->node_count;
|
970
|
+
llrbtree_keep_if(self);
|
971
|
+
if (count == TREE(self)->node_count)
|
972
|
+
return Qnil;
|
973
|
+
return self;
|
974
|
+
|
975
|
+
}
|
976
|
+
|
977
|
+
/*********************************************************************/
|
978
|
+
|
979
|
+
typedef struct {
|
980
|
+
VALUE result;
|
981
|
+
int if_true;
|
982
|
+
} llrbtree_select_if_arg_t;
|
983
|
+
|
984
|
+
static each_return_t
|
985
|
+
select_i(node_t* node, void* arg_)
|
986
|
+
{
|
987
|
+
VALUE key = GET_KEY(node);
|
988
|
+
VALUE value = GET_VAL(node);
|
989
|
+
llrbtree_select_if_arg_t* arg = arg_;
|
990
|
+
|
991
|
+
if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
|
992
|
+
llrbtree_aset(arg->result, key, value);
|
993
|
+
}
|
994
|
+
return EACH_NEXT;
|
995
|
+
}
|
996
|
+
|
997
|
+
static VALUE
|
998
|
+
llrbtree_select_if(VALUE self, const int if_true)
|
999
|
+
{
|
1000
|
+
llrbtree_select_if_arg_t arg;
|
1001
|
+
|
1002
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
|
1003
|
+
arg.result = llrbtree_alloc(CLASS_OF(self));
|
1004
|
+
arg.if_true = if_true;
|
1005
|
+
llrbtree_for_each(self, select_i, &arg);
|
1006
|
+
return arg.result;
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
/*********************************************************************/
|
1010
|
+
|
1011
|
+
/*
|
1012
|
+
*
|
1013
|
+
*/
|
1014
|
+
VALUE
|
1015
|
+
llrbtree_reject(VALUE self)
|
1016
|
+
{
|
1017
|
+
return llrbtree_select_if(self, 0);
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
/*
|
1021
|
+
*
|
1022
|
+
*/
|
1023
|
+
VALUE
|
1024
|
+
llrbtree_select(VALUE self)
|
1025
|
+
{
|
1026
|
+
return llrbtree_select_if(self, 1);
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
static VALUE
|
1030
|
+
llrbtree_shift_pop(VALUE self, const int shift)
|
1031
|
+
{
|
1032
|
+
tree_t* tree = TREE(self);
|
1033
|
+
node_t* node;
|
1034
|
+
VALUE assoc;
|
1035
|
+
|
1036
|
+
llrbtree_modify(self);
|
1037
|
+
|
1038
|
+
if (tree_isempty(tree))
|
1039
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
1040
|
+
|
1041
|
+
if (shift)
|
1042
|
+
node = tree_last(tree);
|
1043
|
+
else
|
1044
|
+
node = tree_first(tree);
|
1045
|
+
assoc = ASSOC(node);
|
1046
|
+
tree_delete(tree, node->key);
|
1047
|
+
return assoc;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
/*
|
1051
|
+
* call-seq:
|
1052
|
+
* llrbtree.shift => array or object or nil
|
1053
|
+
*
|
1054
|
+
* Removes the first (that is, the smallest) key-value pair and
|
1055
|
+
* returns it.
|
1056
|
+
*/
|
1057
|
+
VALUE
|
1058
|
+
llrbtree_shift(VALUE self)
|
1059
|
+
{
|
1060
|
+
return llrbtree_shift_pop(self, 0);
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
/*
|
1064
|
+
* call-seq:
|
1065
|
+
* llrbtree.pop => array or object or nil
|
1066
|
+
*
|
1067
|
+
* Removes the last (that is, the greatest) key-value pair and returns
|
1068
|
+
* it.
|
1069
|
+
*/
|
1070
|
+
VALUE
|
1071
|
+
llrbtree_pop(VALUE self)
|
1072
|
+
{
|
1073
|
+
return llrbtree_shift_pop(self, 1);
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
static each_return_t
|
1077
|
+
invert_i(node_t* node, void* llrbtree)
|
1078
|
+
{
|
1079
|
+
llrbtree_aset((VALUE)llrbtree, GET_VAL(node), GET_KEY(node));
|
1080
|
+
return EACH_NEXT;
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
/*
|
1084
|
+
*
|
1085
|
+
*/
|
1086
|
+
VALUE
|
1087
|
+
llrbtree_invert(VALUE self)
|
1088
|
+
{
|
1089
|
+
VALUE llrbtree = llrbtree_alloc(CLASS_OF(self));
|
1090
|
+
llrbtree_for_each(self, invert_i, (void*)llrbtree);
|
1091
|
+
return llrbtree;
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
static each_return_t
|
1095
|
+
update_block_i(node_t* node, void* self_)
|
1096
|
+
{
|
1097
|
+
VALUE self = (VALUE)self_;
|
1098
|
+
VALUE key = GET_KEY(node);
|
1099
|
+
VALUE value = GET_VAL(node);
|
1100
|
+
|
1101
|
+
if (llrbtree_has_key(self, key))
|
1102
|
+
value = rb_yield_values(3, key, llrbtree_aref(self, key), value);
|
1103
|
+
llrbtree_aset(self, key, value);
|
1104
|
+
return EACH_NEXT;
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
/*
|
1108
|
+
*
|
1109
|
+
*/
|
1110
|
+
VALUE
|
1111
|
+
llrbtree_update(VALUE self, VALUE other)
|
1112
|
+
{
|
1113
|
+
llrbtree_modify(self);
|
1114
|
+
|
1115
|
+
if (self == other)
|
1116
|
+
return self;
|
1117
|
+
if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
|
1118
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
1119
|
+
rb_obj_classname(other),
|
1120
|
+
rb_obj_classname(self));
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
if (rb_block_given_p())
|
1124
|
+
llrbtree_for_each(other, update_block_i, (void*)self);
|
1125
|
+
else
|
1126
|
+
llrbtree_for_each(other, aset_i, (void*)self);
|
1127
|
+
return self;
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
/*
|
1131
|
+
*
|
1132
|
+
*/
|
1133
|
+
VALUE
|
1134
|
+
llrbtree_merge(VALUE self, VALUE other)
|
1135
|
+
{
|
1136
|
+
return llrbtree_update(rb_obj_dup(self), other);
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
static each_return_t
|
1140
|
+
to_flat_ary_i(node_t* node, void* ary)
|
1141
|
+
{
|
1142
|
+
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1143
|
+
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1144
|
+
return EACH_NEXT;
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
/*
|
1148
|
+
*
|
1149
|
+
*/
|
1150
|
+
VALUE
|
1151
|
+
llrbtree_flatten(int argc, VALUE* argv, VALUE self)
|
1152
|
+
{
|
1153
|
+
VALUE ary;
|
1154
|
+
|
1155
|
+
llrbtree_check_argument_count(argc, 0, 1);
|
1156
|
+
ary = rb_ary_new2(TREE(self)->node_count * 2);
|
1157
|
+
llrbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1158
|
+
if (argc == 1) {
|
1159
|
+
const int level = NUM2INT(argv[0]) - 1;
|
1160
|
+
if (level > 0) {
|
1161
|
+
argv[0] = INT2FIX(level);
|
1162
|
+
rb_funcall2(ary, id_flatten_bang, argc, argv);
|
1163
|
+
}
|
1164
|
+
}
|
1165
|
+
return ary;
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
/*
|
1169
|
+
*
|
1170
|
+
*/
|
1171
|
+
VALUE
|
1172
|
+
llrbtree_has_key(VALUE self, VALUE key)
|
1173
|
+
{
|
1174
|
+
return tree_lookup(TREE(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
static each_return_t
|
1178
|
+
has_value_i(node_t* node, void* args_)
|
1179
|
+
{
|
1180
|
+
VALUE* args = (VALUE*)args_;
|
1181
|
+
if (rb_equal(GET_VAL(node), args[1])) {
|
1182
|
+
args[0] = Qtrue;
|
1183
|
+
return EACH_STOP;
|
1184
|
+
}
|
1185
|
+
return EACH_NEXT;
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
/*
|
1189
|
+
*
|
1190
|
+
*/
|
1191
|
+
VALUE
|
1192
|
+
llrbtree_has_value(VALUE self, VALUE value)
|
1193
|
+
{
|
1194
|
+
VALUE args[2];
|
1195
|
+
args[0] = Qfalse;
|
1196
|
+
args[1] = value;
|
1197
|
+
llrbtree_for_each(self, has_value_i, &args);
|
1198
|
+
return args[0];
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
static each_return_t
|
1202
|
+
keys_i(node_t* node, void* ary)
|
1203
|
+
{
|
1204
|
+
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1205
|
+
return EACH_NEXT;
|
1206
|
+
}
|
1207
|
+
|
1208
|
+
/*
|
1209
|
+
*
|
1210
|
+
*/
|
1211
|
+
VALUE
|
1212
|
+
llrbtree_keys(VALUE self)
|
1213
|
+
{
|
1214
|
+
VALUE ary = rb_ary_new2(TREE(self)->node_count);
|
1215
|
+
llrbtree_for_each(self, keys_i, (void*)ary);
|
1216
|
+
return ary;
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
static each_return_t
|
1220
|
+
values_i(node_t* node, void* ary)
|
1221
|
+
{
|
1222
|
+
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1223
|
+
return EACH_NEXT;
|
1224
|
+
}
|
1225
|
+
|
1226
|
+
/*
|
1227
|
+
*
|
1228
|
+
*/
|
1229
|
+
VALUE
|
1230
|
+
llrbtree_values(VALUE self)
|
1231
|
+
{
|
1232
|
+
VALUE ary = rb_ary_new2(TREE(self)->node_count);
|
1233
|
+
llrbtree_for_each(self, values_i, (void*)ary);
|
1234
|
+
return ary;
|
1235
|
+
}
|
1236
|
+
|
1237
|
+
static each_return_t
|
1238
|
+
to_a_i(node_t* node, void* ary)
|
1239
|
+
{
|
1240
|
+
rb_ary_push((VALUE)ary, ASSOC(node));
|
1241
|
+
return EACH_NEXT;
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
/*
|
1245
|
+
*
|
1246
|
+
*/
|
1247
|
+
VALUE
|
1248
|
+
llrbtree_to_a(VALUE self)
|
1249
|
+
{
|
1250
|
+
VALUE ary = rb_ary_new2(TREE(self)->node_count);
|
1251
|
+
llrbtree_for_each(self, to_a_i, (void*)ary);
|
1252
|
+
OBJ_INFECT(ary, self);
|
1253
|
+
return ary;
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
static each_return_t
|
1257
|
+
to_hash_i(node_t* node, void* hash)
|
1258
|
+
{
|
1259
|
+
rb_hash_aset((VALUE)hash, GET_KEY(node), GET_VAL(node));
|
1260
|
+
return EACH_NEXT;
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
/*
|
1264
|
+
*
|
1265
|
+
*/
|
1266
|
+
VALUE
|
1267
|
+
llrbtree_to_hash(VALUE self)
|
1268
|
+
{
|
1269
|
+
VALUE hash;
|
1270
|
+
hash = rb_hash_new();
|
1271
|
+
llrbtree_for_each(self, to_hash_i, (void*)hash);
|
1272
|
+
RHASH_SET_IFNONE(hash, IFNONE(self));
|
1273
|
+
if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
|
1274
|
+
FL_SET(hash, HASH_PROC_DEFAULT);
|
1275
|
+
OBJ_INFECT(hash, self);
|
1276
|
+
return hash;
|
1277
|
+
}
|
1278
|
+
|
1279
|
+
/*
|
1280
|
+
*
|
1281
|
+
*/
|
1282
|
+
VALUE
|
1283
|
+
llrbtree_to_llrbtree(VALUE self)
|
1284
|
+
{
|
1285
|
+
return self;
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
static VALUE
|
1289
|
+
llrbtree_begin_inspect(VALUE self)
|
1290
|
+
{
|
1291
|
+
VALUE result = rb_str_new2("#<");
|
1292
|
+
rb_str_cat2(result, rb_obj_classname(self));
|
1293
|
+
rb_str_cat2(result, ": ");
|
1294
|
+
return result;
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
static each_return_t
|
1298
|
+
inspect_i(node_t* node, void* result_)
|
1299
|
+
{
|
1300
|
+
VALUE result = (VALUE)result_;
|
1301
|
+
VALUE str;
|
1302
|
+
|
1303
|
+
if (RSTRING_PTR(result)[0] == '-')
|
1304
|
+
RSTRING_PTR(result)[0] = '#';
|
1305
|
+
else
|
1306
|
+
rb_str_cat2(result, ", ");
|
1307
|
+
|
1308
|
+
str = rb_inspect(GET_KEY(node));
|
1309
|
+
rb_str_append(result, str);
|
1310
|
+
OBJ_INFECT(result, str);
|
1311
|
+
|
1312
|
+
rb_str_cat2(result, "=>");
|
1313
|
+
|
1314
|
+
str = rb_inspect(GET_VAL(node));
|
1315
|
+
rb_str_append(result, str);
|
1316
|
+
OBJ_INFECT(result, str);
|
1317
|
+
|
1318
|
+
return EACH_NEXT;
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
static VALUE
|
1322
|
+
inspect_llrbtree(VALUE self, VALUE result)
|
1323
|
+
{
|
1324
|
+
VALUE str;
|
1325
|
+
|
1326
|
+
rb_str_cat2(result, "{");
|
1327
|
+
RSTRING_PTR(result)[0] = '-';
|
1328
|
+
llrbtree_for_each(self, inspect_i, (void*)result);
|
1329
|
+
RSTRING_PTR(result)[0] = '#';
|
1330
|
+
rb_str_cat2(result, "}");
|
1331
|
+
|
1332
|
+
str = rb_inspect(IFNONE(self));
|
1333
|
+
rb_str_cat2(result, ", default=");
|
1334
|
+
rb_str_append(result, str);
|
1335
|
+
OBJ_INFECT(result, str);
|
1336
|
+
|
1337
|
+
str = rb_inspect(CMP_PROC(self));
|
1338
|
+
rb_str_cat2(result, ", cmp_proc=");
|
1339
|
+
rb_str_append(result, str);
|
1340
|
+
OBJ_INFECT(result, str);
|
1341
|
+
|
1342
|
+
rb_str_cat2(result, ">");
|
1343
|
+
OBJ_INFECT(result, self);
|
1344
|
+
return result;
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
static VALUE
|
1348
|
+
llrbtree_inspect_recursive(VALUE self, VALUE arg, int recursive)
|
1349
|
+
{
|
1350
|
+
VALUE str = llrbtree_begin_inspect(self);
|
1351
|
+
if (recursive)
|
1352
|
+
return rb_str_cat2(str, "...>");
|
1353
|
+
return inspect_llrbtree(self, str);
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
/*
|
1357
|
+
*
|
1358
|
+
*/
|
1359
|
+
VALUE
|
1360
|
+
llrbtree_inspect(VALUE self)
|
1361
|
+
{
|
1362
|
+
return rb_exec_recursive(llrbtree_inspect_recursive, self, Qnil);
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
/*
|
1366
|
+
* call-seq:
|
1367
|
+
* llrbtree.lower_bound(key) => array or nil
|
1368
|
+
*
|
1369
|
+
* Retruns the key-value pair corresponding to the lowest key that is
|
1370
|
+
* equal to or greater than the given key (inside the lower
|
1371
|
+
* boundary). If there is no such key, returns nil.
|
1372
|
+
*
|
1373
|
+
* llrbtree = LLRBTree["az", 10, "ba", 20]
|
1374
|
+
* llrbtree.lower_bound("ba") # => ["ba", 20]
|
1375
|
+
*
|
1376
|
+
* # "ba" is the lowest key that is greater than "b"
|
1377
|
+
* llrbtree.lower_bound("b") # => ["ba", 20]
|
1378
|
+
*
|
1379
|
+
* # no key that is equal to or greater than "c"
|
1380
|
+
* llrbtree.lower_bound("c") # => nil
|
1381
|
+
*/
|
1382
|
+
VALUE
|
1383
|
+
llrbtree_lower_bound(VALUE self, VALUE key)
|
1384
|
+
{
|
1385
|
+
node_t* node = tree_lower_bound(TREE(self), TO_KEY(key));
|
1386
|
+
if (node == NULL)
|
1387
|
+
return Qnil;
|
1388
|
+
return ASSOC(node);
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
/*
|
1392
|
+
* call-seq:
|
1393
|
+
* llrbtree.upper_bound(key) => array or nil
|
1394
|
+
*
|
1395
|
+
* Retruns the key-value pair corresponding to the greatest key that
|
1396
|
+
* is equal to or lower than the given key (inside the upper
|
1397
|
+
* boundary). If there is no such key, returns nil.
|
1398
|
+
*
|
1399
|
+
* llrbtree = LLRBTree["az", 10, "ba", 20]
|
1400
|
+
* llrbtree.upper_bound("ba") # => ["ba", 20]
|
1401
|
+
*
|
1402
|
+
* # "az" is the greatest key that is lower than "b"
|
1403
|
+
* llrbtree.upper_bound("b") # => ["az", 10]
|
1404
|
+
*
|
1405
|
+
* # no key that is equal to or lower than "a"
|
1406
|
+
* llrbtree.upper_bound("a") # => nil
|
1407
|
+
*/
|
1408
|
+
VALUE
|
1409
|
+
llrbtree_upper_bound(VALUE self, VALUE key)
|
1410
|
+
{
|
1411
|
+
node_t* node = tree_upper_bound(TREE(self), TO_KEY(key));
|
1412
|
+
if (node == NULL)
|
1413
|
+
return Qnil;
|
1414
|
+
return ASSOC(node);
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
/*********************************************************************/
|
1418
|
+
|
1419
|
+
typedef struct {
|
1420
|
+
VALUE self;
|
1421
|
+
node_t* lower_node;
|
1422
|
+
node_t* upper_node;
|
1423
|
+
VALUE result;
|
1424
|
+
} llrbtree_bound_arg_t;
|
1425
|
+
|
1426
|
+
static VALUE
|
1427
|
+
llrbtree_bound_body(llrbtree_bound_arg_t* arg)
|
1428
|
+
{
|
1429
|
+
VALUE self = arg->self;
|
1430
|
+
tree_t* tree = TREE(self);
|
1431
|
+
node_t* lower_node = arg->lower_node;
|
1432
|
+
node_t* upper_node = arg->upper_node;
|
1433
|
+
const int block_given = rb_block_given_p();
|
1434
|
+
VALUE result = arg->result;
|
1435
|
+
node_t* node;
|
1436
|
+
|
1437
|
+
ITER_LEV(self)++;
|
1438
|
+
for (node = lower_node;
|
1439
|
+
node != NULL;
|
1440
|
+
node = tree_next(tree, node)) {
|
1441
|
+
|
1442
|
+
if (block_given)
|
1443
|
+
rb_yield_values(2, GET_KEY(node), GET_VAL(node));
|
1444
|
+
else
|
1445
|
+
rb_ary_push(result, ASSOC(node));
|
1446
|
+
if (node == upper_node)
|
1447
|
+
break;
|
1448
|
+
}
|
1449
|
+
return result;
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
#ifdef HAVE_SIZED_ENUMERATOR
|
1453
|
+
static VALUE
|
1454
|
+
llrbtree_bound_size(VALUE self, VALUE args)
|
1455
|
+
{
|
1456
|
+
VALUE key1 = RARRAY_AREF(args, 0);
|
1457
|
+
VALUE key2 = RARRAY_AREF(args, RARRAY_LEN(args) - 1);
|
1458
|
+
node_t* lower_node = tree_lower_bound(TREE(self), TO_KEY(key1));
|
1459
|
+
node_t* upper_node = tree_upper_bound(TREE(self), TO_KEY(key2));
|
1460
|
+
node_count_t count = 0;
|
1461
|
+
node_t* node;
|
1462
|
+
|
1463
|
+
if (lower_node == NULL || upper_node == NULL ||
|
1464
|
+
TREE(self)->compare(lower_node->key,
|
1465
|
+
upper_node->key,
|
1466
|
+
TREE(self)->context) > 0) {
|
1467
|
+
return INT2FIX(0);
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
for (node = lower_node;
|
1471
|
+
node != NULL;
|
1472
|
+
node = tree_next(TREE(self), node)) {
|
1473
|
+
|
1474
|
+
count++;
|
1475
|
+
if (node == upper_node) {
|
1476
|
+
break;
|
1477
|
+
}
|
1478
|
+
}
|
1479
|
+
return ULONG2NUM(count);
|
1480
|
+
}
|
1481
|
+
#endif
|
1482
|
+
|
1483
|
+
/*********************************************************************/
|
1484
|
+
|
1485
|
+
/*
|
1486
|
+
* call-seq:
|
1487
|
+
* llrbtree.bound(key1, key2 = key1) {|key, value| block} => llrbtree
|
1488
|
+
* llrbtree.bound(key1, key2 = key1) => enumerator
|
1489
|
+
*
|
1490
|
+
* Calls block once for each key between the result of
|
1491
|
+
* llrbtree.lower_bound(key1) and llrbtree.upper_bound(key2) in order,
|
1492
|
+
* passing the key-value pair as parameters. If the lower bound
|
1493
|
+
* exceeds the upper bound, block is not called.
|
1494
|
+
*
|
1495
|
+
* Returns an enumerator if no block is given.
|
1496
|
+
*
|
1497
|
+
* llrbtree = LLRBTree["a", "A", "b", "B", "c", "C"]
|
1498
|
+
* llrbtree.bound("a").to_a # => [["a", "A"]]
|
1499
|
+
* llrbtree.bound("b", "d").to_a # => [["b", "B"], ["c", "C"]]
|
1500
|
+
*
|
1501
|
+
*/
|
1502
|
+
VALUE
|
1503
|
+
llrbtree_bound(int argc, VALUE* argv, VALUE self)
|
1504
|
+
{
|
1505
|
+
tree_t* tree = TREE(self);
|
1506
|
+
node_t* lower_node;
|
1507
|
+
node_t* upper_node;
|
1508
|
+
VALUE result;
|
1509
|
+
|
1510
|
+
llrbtree_check_argument_count(argc, 1, 2);
|
1511
|
+
|
1512
|
+
RETURN_SIZED_ENUMERATOR(self, argc, argv, llrbtree_bound_size);
|
1513
|
+
|
1514
|
+
lower_node = tree_lower_bound(tree, TO_KEY(argv[0]));
|
1515
|
+
upper_node = tree_upper_bound(tree, TO_KEY(argv[argc - 1]));
|
1516
|
+
result = rb_block_given_p() ? self : rb_ary_new();
|
1517
|
+
|
1518
|
+
if (lower_node == NULL || upper_node == NULL ||
|
1519
|
+
TREE(self)->compare(lower_node->key,
|
1520
|
+
upper_node->key,
|
1521
|
+
TREE(self)->context) > 0) {
|
1522
|
+
return result;
|
1523
|
+
} else {
|
1524
|
+
llrbtree_bound_arg_t arg;
|
1525
|
+
arg.self = self;
|
1526
|
+
arg.lower_node = lower_node;
|
1527
|
+
arg.upper_node = upper_node;
|
1528
|
+
arg.result = result;
|
1529
|
+
return rb_ensure(llrbtree_bound_body, (VALUE)&arg,
|
1530
|
+
llrbtree_each_ensure, self);
|
1531
|
+
}
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
static VALUE
|
1535
|
+
llrbtree_first_last(VALUE self, const int first)
|
1536
|
+
{
|
1537
|
+
tree_t* tree = TREE(self);
|
1538
|
+
node_t* node;
|
1539
|
+
|
1540
|
+
if (tree_isempty(tree))
|
1541
|
+
return rb_funcall(self, id_default, 1, Qnil);
|
1542
|
+
|
1543
|
+
if (first)
|
1544
|
+
node = tree_first(tree);
|
1545
|
+
else
|
1546
|
+
node = tree_last(tree);
|
1547
|
+
return ASSOC(node);
|
1548
|
+
}
|
1549
|
+
|
1550
|
+
/*
|
1551
|
+
* call-seq:
|
1552
|
+
* llrbtree.first => array or object or nil
|
1553
|
+
*
|
1554
|
+
* Returns the first (that is, the smallest) key-value pair.
|
1555
|
+
*/
|
1556
|
+
VALUE
|
1557
|
+
llrbtree_first(VALUE self)
|
1558
|
+
{
|
1559
|
+
return llrbtree_first_last(self, 1);
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
/*
|
1563
|
+
* call-seq:
|
1564
|
+
* llrbtree.last => array or object or nil
|
1565
|
+
*
|
1566
|
+
* Returns the last (that is, the greatest) key-value pair.
|
1567
|
+
*/
|
1568
|
+
VALUE
|
1569
|
+
llrbtree_last(VALUE self)
|
1570
|
+
{
|
1571
|
+
return llrbtree_first_last(self, 0);
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
/*
|
1575
|
+
* call-seq:
|
1576
|
+
* llrbtree.readjust => llrbtree
|
1577
|
+
* llrbtree.readjust(nil) => llrbtree
|
1578
|
+
* llrbtree.readjust(proc) => llrbtree
|
1579
|
+
* llrbtree.readjust {|key1, key2| block} => llrbtree
|
1580
|
+
*
|
1581
|
+
* Sets a proc to compare keys and readjusts elements using the given
|
1582
|
+
* block or a Proc object given as an argument. The block takes two
|
1583
|
+
* keys and returns a negative integer, 0, or a positive integer as
|
1584
|
+
* the first argument is less than, equal to, or greater than the
|
1585
|
+
* second one. If no block is given, just readjusts elements using the
|
1586
|
+
* current comparison block. If nil is given as an argument the
|
1587
|
+
* default comparison block that uses the <=> method is set.
|
1588
|
+
*
|
1589
|
+
* llrbtree = LLRBTree["a", 10, "b", 20]
|
1590
|
+
* llrbtree.readjust {|a, b| b <=> a }
|
1591
|
+
* llrbtree.first # => ["b", 20]
|
1592
|
+
*
|
1593
|
+
* llrbtree.readjust(nil)
|
1594
|
+
* llrbtree.first # => ["a", 10]
|
1595
|
+
*/
|
1596
|
+
VALUE
|
1597
|
+
llrbtree_readjust(int argc, VALUE* argv, VALUE self)
|
1598
|
+
{
|
1599
|
+
compare_t cmp_func = NULL;
|
1600
|
+
VALUE cmp_proc = Qnil;
|
1601
|
+
|
1602
|
+
llrbtree_modify(self);
|
1603
|
+
|
1604
|
+
if (rb_block_given_p()) {
|
1605
|
+
llrbtree_check_argument_count(argc, 0, 0);
|
1606
|
+
cmp_func = llrbtree_user_cmp;
|
1607
|
+
cmp_proc = rb_block_proc();
|
1608
|
+
llrbtree_check_proc_arity(cmp_proc, 2);
|
1609
|
+
} else {
|
1610
|
+
llrbtree_check_argument_count(argc, 0, 1);
|
1611
|
+
if (argc == 0) {
|
1612
|
+
cmp_func = TREE(self)->compare;
|
1613
|
+
cmp_proc = CMP_PROC(self);
|
1614
|
+
} else {
|
1615
|
+
if (NIL_P(argv[0])) {
|
1616
|
+
cmp_func = llrbtree_cmp;
|
1617
|
+
cmp_proc = Qnil;
|
1618
|
+
} else {
|
1619
|
+
VALUE proc = rb_check_convert_type(argv[0], T_DATA, "Proc", "to_proc");
|
1620
|
+
if (NIL_P(proc)) {
|
1621
|
+
rb_raise(rb_eTypeError,
|
1622
|
+
"wrong cmp_proc type %s (expected Proc)",
|
1623
|
+
rb_obj_classname(argv[0]));
|
1624
|
+
}
|
1625
|
+
cmp_func = llrbtree_user_cmp;
|
1626
|
+
cmp_proc = proc;
|
1627
|
+
llrbtree_check_proc_arity(cmp_proc, 2);
|
1628
|
+
}
|
1629
|
+
}
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
if (tree_isempty(TREE(self))) {
|
1633
|
+
TREE(self)->compare = cmp_func;
|
1634
|
+
CMP_PROC(self) = cmp_proc;
|
1635
|
+
return self;
|
1636
|
+
}
|
1637
|
+
copy_tree(self, self, cmp_func, cmp_proc);
|
1638
|
+
return self;
|
1639
|
+
}
|
1640
|
+
|
1641
|
+
/*
|
1642
|
+
* call-seq:
|
1643
|
+
* llrbtree.cmp_proc => proc or nil
|
1644
|
+
*
|
1645
|
+
* Returns the comparison block that is set by
|
1646
|
+
* LLRBTree#readjust. If the default comparison block is set,
|
1647
|
+
* returns nil.
|
1648
|
+
*/
|
1649
|
+
VALUE
|
1650
|
+
llrbtree_cmp_proc(VALUE self)
|
1651
|
+
{
|
1652
|
+
return CMP_PROC(self);
|
1653
|
+
}
|
1654
|
+
|
1655
|
+
/*********************************************************************/
|
1656
|
+
|
1657
|
+
static ID id_breakable;
|
1658
|
+
static ID id_comma_breakable;
|
1659
|
+
static ID id_group;
|
1660
|
+
static ID id_object_group;
|
1661
|
+
static ID id_pp;
|
1662
|
+
static ID id_text;
|
1663
|
+
|
1664
|
+
static VALUE
|
1665
|
+
pp_group(VALUE args_)
|
1666
|
+
{
|
1667
|
+
VALUE* args = (VALUE*)args_;
|
1668
|
+
return rb_funcall(args[0], id_group, 3, args[1], args[2], args[3]);
|
1669
|
+
}
|
1670
|
+
|
1671
|
+
typedef struct {
|
1672
|
+
VALUE pp;
|
1673
|
+
node_t* node;
|
1674
|
+
} pp_pair_arg_t;
|
1675
|
+
|
1676
|
+
static VALUE
|
1677
|
+
pp_value(VALUE nil, pp_pair_arg_t* pair_arg)
|
1678
|
+
{
|
1679
|
+
VALUE pp = pair_arg->pp;
|
1680
|
+
rb_funcall(pp, id_breakable, 1, rb_str_new(NULL, 0));
|
1681
|
+
return rb_funcall(pp, id_pp, 1, GET_VAL(pair_arg->node));
|
1682
|
+
}
|
1683
|
+
|
1684
|
+
static VALUE
|
1685
|
+
pp_pair(VALUE nil, pp_pair_arg_t* pair_arg)
|
1686
|
+
{
|
1687
|
+
VALUE pp = pair_arg->pp;
|
1688
|
+
VALUE group_args[4];
|
1689
|
+
group_args[0] = pp;
|
1690
|
+
group_args[1] = INT2FIX(1);
|
1691
|
+
group_args[2] = rb_str_new(NULL, 0);
|
1692
|
+
group_args[3] = rb_str_new(NULL, 0);
|
1693
|
+
|
1694
|
+
rb_funcall(pp, id_pp, 1, GET_KEY(pair_arg->node));
|
1695
|
+
rb_funcall(pp, id_text, 1, rb_str_new2("=>"));
|
1696
|
+
return rb_iterate(pp_group, (VALUE)&group_args, pp_value, (VALUE)pair_arg);
|
1697
|
+
}
|
1698
|
+
|
1699
|
+
typedef struct {
|
1700
|
+
VALUE pp;
|
1701
|
+
int first;
|
1702
|
+
} pp_each_pair_arg_t;
|
1703
|
+
|
1704
|
+
static each_return_t
|
1705
|
+
pp_each_pair_i(node_t* node, void* each_pair_arg_)
|
1706
|
+
{
|
1707
|
+
pp_each_pair_arg_t* each_pair_arg = (pp_each_pair_arg_t*)each_pair_arg_;
|
1708
|
+
VALUE group_args[4];
|
1709
|
+
pp_pair_arg_t pair_arg;
|
1710
|
+
|
1711
|
+
if (each_pair_arg->first) {
|
1712
|
+
each_pair_arg->first = 0;
|
1713
|
+
} else {
|
1714
|
+
rb_funcall(each_pair_arg->pp, id_comma_breakable, 0);
|
1715
|
+
}
|
1716
|
+
|
1717
|
+
group_args[0] = each_pair_arg->pp;
|
1718
|
+
group_args[1] = INT2FIX(0);
|
1719
|
+
group_args[2] = rb_str_new(NULL, 0);
|
1720
|
+
group_args[3] = rb_str_new(NULL, 0);
|
1721
|
+
|
1722
|
+
pair_arg.pp = each_pair_arg->pp;
|
1723
|
+
pair_arg.node = node;
|
1724
|
+
|
1725
|
+
rb_iterate(pp_group, (VALUE)&group_args, pp_pair, (VALUE)&pair_arg);
|
1726
|
+
return EACH_NEXT;
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
typedef struct {
|
1730
|
+
VALUE pp;
|
1731
|
+
VALUE llrbtree;
|
1732
|
+
} pp_llrbtree_arg_t;
|
1733
|
+
|
1734
|
+
static VALUE
|
1735
|
+
pp_each_pair(VALUE nil, pp_llrbtree_arg_t* llrbtree_arg)
|
1736
|
+
{
|
1737
|
+
pp_each_pair_arg_t each_pair_arg;
|
1738
|
+
each_pair_arg.pp = llrbtree_arg->pp;
|
1739
|
+
each_pair_arg.first = 1;
|
1740
|
+
return llrbtree_for_each(llrbtree_arg->llrbtree, pp_each_pair_i, &each_pair_arg);
|
1741
|
+
}
|
1742
|
+
|
1743
|
+
static VALUE
|
1744
|
+
pp_llrbtree(VALUE nil, pp_llrbtree_arg_t* llrbtree_arg)
|
1745
|
+
{
|
1746
|
+
VALUE pp = llrbtree_arg->pp;
|
1747
|
+
VALUE llrbtree = llrbtree_arg->llrbtree;
|
1748
|
+
|
1749
|
+
VALUE group_args[4];
|
1750
|
+
group_args[0] = pp;
|
1751
|
+
group_args[1] = INT2FIX(1);
|
1752
|
+
group_args[2] = rb_str_new2("{");
|
1753
|
+
group_args[3] = rb_str_new2("}");
|
1754
|
+
|
1755
|
+
rb_funcall(pp, id_text, 1, rb_str_new2(": "));
|
1756
|
+
rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)llrbtree_arg);
|
1757
|
+
rb_funcall(pp, id_comma_breakable, 0);
|
1758
|
+
rb_funcall(pp, id_text, 1, rb_str_new2("default="));
|
1759
|
+
rb_funcall(pp, id_pp, 1, IFNONE(llrbtree));
|
1760
|
+
rb_funcall(pp, id_comma_breakable, 0);
|
1761
|
+
rb_funcall(pp, id_text, 1, rb_str_new2("cmp_proc="));
|
1762
|
+
return rb_funcall(pp, id_pp, 1, CMP_PROC(llrbtree));
|
1763
|
+
}
|
1764
|
+
|
1765
|
+
static VALUE
|
1766
|
+
pp_llrbtree_group(VALUE arg_)
|
1767
|
+
{
|
1768
|
+
pp_llrbtree_arg_t* arg = (pp_llrbtree_arg_t*)arg_;
|
1769
|
+
return rb_funcall(arg->pp, id_object_group, 1, arg->llrbtree);
|
1770
|
+
}
|
1771
|
+
|
1772
|
+
/*********************************************************************/
|
1773
|
+
|
1774
|
+
/* :nodoc:
|
1775
|
+
*
|
1776
|
+
*/
|
1777
|
+
VALUE
|
1778
|
+
llrbtree_pretty_print(VALUE self, VALUE pp)
|
1779
|
+
{
|
1780
|
+
pp_llrbtree_arg_t arg;
|
1781
|
+
arg.llrbtree = self;
|
1782
|
+
arg.pp = pp;
|
1783
|
+
return rb_iterate(pp_llrbtree_group, (VALUE)&arg, pp_llrbtree, (VALUE)&arg);
|
1784
|
+
}
|
1785
|
+
|
1786
|
+
/* :nodoc:
|
1787
|
+
*
|
1788
|
+
*/
|
1789
|
+
VALUE
|
1790
|
+
llrbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
1791
|
+
{
|
1792
|
+
return rb_funcall(pp, id_pp, 1, llrbtree_inspect_recursive(self, Qnil, 1));
|
1793
|
+
}
|
1794
|
+
|
1795
|
+
/*********************************************************************/
|
1796
|
+
|
1797
|
+
/* :nodoc:
|
1798
|
+
*
|
1799
|
+
*/
|
1800
|
+
VALUE
|
1801
|
+
llrbtree_dump(VALUE self, VALUE limit)
|
1802
|
+
{
|
1803
|
+
VALUE ary;
|
1804
|
+
VALUE result;
|
1805
|
+
|
1806
|
+
if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
|
1807
|
+
rb_raise(rb_eTypeError, "can't dump llrbtree with default proc");
|
1808
|
+
if (CMP_PROC(self) != Qnil)
|
1809
|
+
rb_raise(rb_eTypeError, "can't dump llrbtree with comparison proc");
|
1810
|
+
|
1811
|
+
ary = rb_ary_new2(TREE(self)->node_count * 2 + 1);
|
1812
|
+
llrbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1813
|
+
rb_ary_push(ary, IFNONE(self));
|
1814
|
+
|
1815
|
+
result = rb_funcall(rb_const_get(rb_cObject, id_marshal), id_dump, 2, ary, limit);
|
1816
|
+
rb_ary_resize(ary, 0);
|
1817
|
+
return result;
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
/* :nodoc:
|
1821
|
+
*
|
1822
|
+
*/
|
1823
|
+
VALUE
|
1824
|
+
llrbtree_s_load(VALUE klass, VALUE str)
|
1825
|
+
{
|
1826
|
+
VALUE llrbtree = llrbtree_alloc(klass);
|
1827
|
+
VALUE ary = rb_marshal_load(str);
|
1828
|
+
long len = RARRAY_LEN(ary) - 1;
|
1829
|
+
long i;
|
1830
|
+
|
1831
|
+
for (i = 0; i < len; i += 2)
|
1832
|
+
llrbtree_aset(llrbtree, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i + 1));
|
1833
|
+
IFNONE(llrbtree) = RARRAY_AREF(ary, len);
|
1834
|
+
|
1835
|
+
rb_ary_resize(ary, 0);
|
1836
|
+
return llrbtree;
|
1837
|
+
}
|
1838
|
+
|
1839
|
+
/*********************************************************************/
|
1840
|
+
/*
|
1841
|
+
* Document-class: LLRBTree
|
1842
|
+
*
|
1843
|
+
* A sorted associative collection that cannot contain duplicate keys.
|
1844
|
+
*/
|
1845
|
+
void Init_llrbtree()
|
1846
|
+
{
|
1847
|
+
LLRBTree = rb_define_class("LLRBTree", rb_cData);
|
1848
|
+
|
1849
|
+
rb_include_module(LLRBTree, rb_mEnumerable);
|
1850
|
+
|
1851
|
+
rb_define_alloc_func(LLRBTree, llrbtree_alloc);
|
1852
|
+
|
1853
|
+
rb_define_singleton_method(LLRBTree, "[]", llrbtree_s_create, -1);
|
1854
|
+
|
1855
|
+
rb_define_method(LLRBTree, "initialize", llrbtree_initialize, -1);
|
1856
|
+
rb_define_method(LLRBTree, "initialize_copy", llrbtree_initialize_copy, 1);
|
1857
|
+
|
1858
|
+
rb_define_method(LLRBTree, "to_a", llrbtree_to_a, 0);
|
1859
|
+
rb_define_method(LLRBTree, "to_h", llrbtree_to_hash, 0);
|
1860
|
+
rb_define_method(LLRBTree, "to_hash", llrbtree_to_hash, 0);
|
1861
|
+
rb_define_method(LLRBTree, "to_llrbtree", llrbtree_to_llrbtree, 0);
|
1862
|
+
rb_define_method(LLRBTree, "inspect", llrbtree_inspect, 0);
|
1863
|
+
rb_define_alias(LLRBTree, "to_s", "inspect");
|
1864
|
+
|
1865
|
+
rb_define_method(LLRBTree, "==", llrbtree_equal, 1);
|
1866
|
+
rb_define_method(LLRBTree, "[]", llrbtree_aref, 1);
|
1867
|
+
rb_define_method(LLRBTree, "fetch", llrbtree_fetch, -1);
|
1868
|
+
rb_define_method(LLRBTree, "lower_bound", llrbtree_lower_bound, 1);
|
1869
|
+
rb_define_method(LLRBTree, "upper_bound", llrbtree_upper_bound, 1);
|
1870
|
+
rb_define_method(LLRBTree, "bound", llrbtree_bound, -1);
|
1871
|
+
rb_define_method(LLRBTree, "first", llrbtree_first, 0);
|
1872
|
+
rb_define_method(LLRBTree, "last", llrbtree_last, 0);
|
1873
|
+
rb_define_method(LLRBTree, "[]=", llrbtree_aset, 2);
|
1874
|
+
rb_define_method(LLRBTree, "store", llrbtree_aset, 2);
|
1875
|
+
rb_define_method(LLRBTree, "default", llrbtree_default, -1);
|
1876
|
+
rb_define_method(LLRBTree, "default=", llrbtree_set_default, 1);
|
1877
|
+
rb_define_method(LLRBTree, "default_proc", llrbtree_default_proc, 0);
|
1878
|
+
rb_define_method(LLRBTree, "default_proc=", llrbtree_set_default_proc, 1);
|
1879
|
+
rb_define_method(LLRBTree, "key", llrbtree_key, 1);
|
1880
|
+
rb_define_method(LLRBTree, "index", llrbtree_index, 1);
|
1881
|
+
rb_define_method(LLRBTree, "empty?", llrbtree_empty_p, 0);
|
1882
|
+
rb_define_method(LLRBTree, "size", llrbtree_size, 0);
|
1883
|
+
rb_define_method(LLRBTree, "length", llrbtree_size, 0);
|
1884
|
+
|
1885
|
+
rb_define_method(LLRBTree, "each", llrbtree_each_pair, 0);
|
1886
|
+
rb_define_method(LLRBTree, "each_value", llrbtree_each_value, 0);
|
1887
|
+
rb_define_method(LLRBTree, "each_key", llrbtree_each_key, 0);
|
1888
|
+
rb_define_method(LLRBTree, "each_pair", llrbtree_each_pair, 0);
|
1889
|
+
rb_define_method(LLRBTree, "reverse_each", llrbtree_reverse_each, 0);
|
1890
|
+
|
1891
|
+
rb_define_method(LLRBTree, "keys", llrbtree_keys, 0);
|
1892
|
+
rb_define_method(LLRBTree, "values", llrbtree_values, 0);
|
1893
|
+
rb_define_method(LLRBTree, "values_at", llrbtree_values_at, -1);
|
1894
|
+
|
1895
|
+
rb_define_method(LLRBTree, "shift", llrbtree_shift, 0);
|
1896
|
+
rb_define_method(LLRBTree, "pop", llrbtree_pop, 0);
|
1897
|
+
rb_define_method(LLRBTree, "delete", llrbtree_delete, 1);
|
1898
|
+
rb_define_method(LLRBTree, "delete_if", llrbtree_delete_if, 0);
|
1899
|
+
rb_define_method(LLRBTree, "keep_if", llrbtree_keep_if, 0);
|
1900
|
+
rb_define_method(LLRBTree, "reject", llrbtree_reject, 0);
|
1901
|
+
rb_define_method(LLRBTree, "reject!", llrbtree_reject_bang, 0);
|
1902
|
+
rb_define_method(LLRBTree, "select", llrbtree_select, 0);
|
1903
|
+
rb_define_method(LLRBTree, "select!", llrbtree_select_bang, 0);
|
1904
|
+
rb_define_method(LLRBTree, "clear", llrbtree_clear, 0);
|
1905
|
+
rb_define_method(LLRBTree, "invert", llrbtree_invert, 0);
|
1906
|
+
rb_define_method(LLRBTree, "update", llrbtree_update, 1);
|
1907
|
+
rb_define_method(LLRBTree, "merge!", llrbtree_update, 1);
|
1908
|
+
rb_define_method(LLRBTree, "merge", llrbtree_merge, 1);
|
1909
|
+
rb_define_method(LLRBTree, "replace", llrbtree_initialize_copy, 1);
|
1910
|
+
rb_define_method(LLRBTree, "flatten", llrbtree_flatten, -1);
|
1911
|
+
|
1912
|
+
rb_define_method(LLRBTree, "include?", llrbtree_has_key, 1);
|
1913
|
+
rb_define_method(LLRBTree, "member?", llrbtree_has_key, 1);
|
1914
|
+
rb_define_method(LLRBTree, "has_key?", llrbtree_has_key, 1);
|
1915
|
+
rb_define_method(LLRBTree, "has_value?", llrbtree_has_value, 1);
|
1916
|
+
rb_define_method(LLRBTree, "key?", llrbtree_has_key, 1);
|
1917
|
+
rb_define_method(LLRBTree, "value?", llrbtree_has_value, 1);
|
1918
|
+
|
1919
|
+
rb_define_method(LLRBTree, "readjust", llrbtree_readjust, -1);
|
1920
|
+
rb_define_method(LLRBTree, "cmp_proc", llrbtree_cmp_proc, 0);
|
1921
|
+
|
1922
|
+
rb_define_method(LLRBTree, "_dump", llrbtree_dump, 1);
|
1923
|
+
rb_define_singleton_method(LLRBTree, "_load", llrbtree_s_load, 1);
|
1924
|
+
|
1925
|
+
id_cmp = rb_intern("<=>");
|
1926
|
+
id_call = rb_intern("call");
|
1927
|
+
id_default = rb_intern("default");
|
1928
|
+
id_flatten_bang = rb_intern("flatten!");
|
1929
|
+
id_marshal = rb_intern("Marshal");
|
1930
|
+
id_dump = rb_intern("dump");
|
1931
|
+
|
1932
|
+
rb_define_method(LLRBTree, "pretty_print", llrbtree_pretty_print, 1);
|
1933
|
+
rb_define_method(LLRBTree,
|
1934
|
+
"pretty_print_cycle", llrbtree_pretty_print_cycle, 1);
|
1935
|
+
|
1936
|
+
id_breakable = rb_intern("breakable");
|
1937
|
+
id_comma_breakable = rb_intern("comma_breakable");
|
1938
|
+
id_group = rb_intern("group");
|
1939
|
+
id_object_group = rb_intern("object_group");
|
1940
|
+
id_pp = rb_intern("pp");
|
1941
|
+
id_text = rb_intern("text");
|
1942
|
+
}
|