llrbtree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }