Class: LLRBTree

Inherits:
Data
  • Object
show all
Includes:
Enumerable
Defined in:
ext/llrbtree/llrbtree.c,
lib/llrbtree/version.rb,
ext/llrbtree/llrbtree.c

Overview

A sorted associative collection that cannot contain duplicate keys.

Constant Summary collapse

VERSION =
'0.0.3'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'ext/llrbtree/llrbtree.c', line 273

VALUE
llrbtree_initialize(int argc, VALUE* argv, VALUE self)
{
    llrbtree_modify(self);

    if (rb_block_given_p()) {
        VALUE proc;
        llrbtree_check_argument_count(argc, 0, 0);
        proc = rb_block_proc();
        llrbtree_check_proc_arity(proc, 2);
        IFNONE(self) = proc;
        FL_SET(self, LLRBTREE_PROC_DEFAULT);
    } else {
        llrbtree_check_argument_count(argc, 0, 1);
        if (argc == 1) {
            IFNONE(self) = argv[0];
        }
    }
    return self;
}

Class Method Details

.[](*args) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'ext/llrbtree/llrbtree.c', line 213

VALUE
llrbtree_s_create(int argc, VALUE* argv, VALUE klass)
{
    long i;
    VALUE llrbtree;

    if (argc == 1) {
        VALUE temp;

        if (rb_obj_is_kind_of(argv[0], klass)) {
            llrbtree = llrbtree_alloc(klass);
            llrbtree_update(llrbtree, argv[0]);
            return llrbtree;
        }

        temp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
        if (!NIL_P(temp)) {
            llrbtree = llrbtree_alloc(klass);
            rb_hash_foreach(temp, hash_to_llrbtree_i, llrbtree);
            return llrbtree;
        }

        temp = rb_check_array_type(argv[0]);
        if (!NIL_P(temp)) {
            llrbtree = llrbtree_alloc(klass);
            for (i = 0; i < RARRAY_LEN(temp); i++) {
                VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
                if (NIL_P(v)) {
                    rb_warn("wrong element type %s at %ld (expected Array)",
                            rb_obj_classname(RARRAY_AREF(temp, i)), i);
                    continue;
                }
                switch(RARRAY_LEN(v)) {
                case 1:
                    llrbtree_aset(llrbtree, RARRAY_AREF(v, 0), Qnil);
                    break;
                case 2:
                    llrbtree_aset(llrbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
                    break;
                default:
                    rb_warn("invalid number of elements (%ld for 1..2)",
                            RARRAY_LEN(v));
                }
            }
            return llrbtree;
        }
    }

    if (argc % 2 != 0)
        rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));

    llrbtree = llrbtree_alloc(klass);
    for (i = 0; i < argc; i += 2)
        llrbtree_aset(llrbtree, argv[i], argv[i + 1]);
    return llrbtree;
}

._load(str) ⇒ Object

:nodoc:



1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
# File 'ext/llrbtree/llrbtree.c', line 1821

VALUE
llrbtree_s_load(VALUE klass, VALUE str)
{
    VALUE llrbtree = llrbtree_alloc(klass);
    VALUE ary = rb_marshal_load(str);
    long len = RARRAY_LEN(ary) - 1;
    long i;

    for (i = 0; i < len; i += 2)
        llrbtree_aset(llrbtree, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i + 1));
    IFNONE(llrbtree) = RARRAY_AREF(ary, len);

    rb_ary_resize(ary, 0);
    return llrbtree;
}

Instance Method Details

#==(other) ⇒ Object



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
# File 'ext/llrbtree/llrbtree.c', line 535

VALUE
llrbtree_equal(VALUE self, VALUE other)
{
    if (self == other)
        return Qtrue;
    if (!rb_obj_is_kind_of(other, LLRBTree))
        return Qfalse;
    if (TREE(self)->node_count != TREE(other)->node_count ||
        TREE(self)->compare != TREE(other)->compare ||
        CMP_PROC(self) != CMP_PROC(other)) {

        return Qfalse;
    }
    return rb_exec_recursive_paired(llrbtree_recursive_equal, self, other, other);
}

#[](key) ⇒ Object



388
389
390
391
392
393
394
395
396
# File 'ext/llrbtree/llrbtree.c', line 388

VALUE
llrbtree_aref(VALUE self, VALUE key)
{
    node_t* node = tree_lookup(TREE(self), TO_KEY(key));
    if (node == NULL)
        return rb_funcall2(self, id_default, 1, &key);
    else
        return GET_VAL(node);
}

#[]=(key, value) ⇒ Object



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'ext/llrbtree/llrbtree.c', line 368

VALUE
llrbtree_aset(VALUE self, VALUE key, VALUE value)
{
    llrbtree_modify(self);

    if (tree_isfull(TREE(self))) {
        node_t* node = tree_lookup(TREE(self), TO_KEY(key));
        if (node == NULL)
            rb_raise(rb_eIndexError, "llrbtree full");
        else
            node->data = TO_VAL(value);
        return value;
    }
    llrbtree_insert(self, key, value);
    return value;
}

#_dump(limit) ⇒ Object

:nodoc:



1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
# File 'ext/llrbtree/llrbtree.c', line 1798

VALUE
llrbtree_dump(VALUE self, VALUE limit)
{
    VALUE ary;
    VALUE result;

    if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
        rb_raise(rb_eTypeError, "can't dump llrbtree with default proc");
    if (CMP_PROC(self) != Qnil)
        rb_raise(rb_eTypeError, "can't dump llrbtree with comparison proc");

    ary = rb_ary_new2(TREE(self)->node_count * 2 + 1);
    llrbtree_for_each(self, to_flat_ary_i, (void*)ary);
    rb_ary_push(ary, IFNONE(self));

    result = rb_funcall(rb_const_get(rb_cObject, id_marshal), id_dump, 2, ary, limit);
    rb_ary_resize(ary, 0);
    return result;
}

#bound(key1, key2 = key1) {|key, value| ... } ⇒ Object #bound(key1, key2 = key1) ⇒ Object

Calls block once for each key between the result of llrbtree.lower_bound(key1) and llrbtree.upper_bound(key2) in order, passing the key-value pair as parameters. If the lower bound exceeds the upper bound, block is not called.

Returns an enumerator if no block is given.

llrbtree = LLRBTree["a", "A", "b", "B", "c", "C"]
llrbtree.bound("a").to_a # => [["a", "A"]]
llrbtree.bound("b", "d").to_a # => [["b", "B"], ["c", "C"]]

Overloads:

  • #bound(key1, key2 = key1) {|key, value| ... } ⇒ Object

    Yields:



1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
# File 'ext/llrbtree/llrbtree.c', line 1500

VALUE
llrbtree_bound(int argc, VALUE* argv, VALUE self)
{
    tree_t* tree = TREE(self);
    node_t* lower_node;
    node_t* upper_node;
    VALUE result;

    llrbtree_check_argument_count(argc, 1, 2);

    RETURN_SIZED_ENUMERATOR(self, argc, argv, llrbtree_bound_size);

    lower_node = tree_lower_bound(tree, TO_KEY(argv[0]));
    upper_node = tree_upper_bound(tree, TO_KEY(argv[argc - 1]));
    result = rb_block_given_p() ? self : rb_ary_new();

    if (lower_node == NULL || upper_node == NULL ||
        TREE(self)->compare(lower_node->key,
                                 upper_node->key,
                                 TREE(self)->context) > 0) {
        return result;
    } else {
        llrbtree_bound_arg_t arg;
        arg.self = self;
        arg.lower_node = lower_node;
        arg.upper_node = upper_node;
        arg.result = result;
        return rb_ensure(llrbtree_bound_body, (VALUE)&arg,
                         llrbtree_each_ensure, self);
    }
}

#clearObject



825
826
827
828
829
830
831
# File 'ext/llrbtree/llrbtree.c', line 825

VALUE
llrbtree_clear(VALUE self)
{
    llrbtree_modify(self);
    tree_free(TREE(self));
    return self;
}

#cmp_procProc?

Returns the comparison block that is set by LLRBTree#readjust. If the default comparison block is set, returns nil.

Returns:

  • (Proc, nil)


1647
1648
1649
1650
1651
# File 'ext/llrbtree/llrbtree.c', line 1647

VALUE
llrbtree_cmp_proc(VALUE self)
{
    return CMP_PROC(self);
}

#default(*args) ⇒ Object



446
447
448
449
450
451
452
453
454
455
456
457
# File 'ext/llrbtree/llrbtree.c', line 446

VALUE
llrbtree_default(int argc, VALUE* argv, VALUE self)
{
    llrbtree_check_argument_count(argc, 0, 1);
    if (FL_TEST(self, LLRBTREE_PROC_DEFAULT)) {
        if (argc == 0) {
            return Qnil;
        }
        return rb_funcall(IFNONE(self), id_call, 2, self, argv[0]);
    }
    return IFNONE(self);
}

#default=(ifnone) ⇒ Object



462
463
464
465
466
467
468
469
# File 'ext/llrbtree/llrbtree.c', line 462

VALUE
llrbtree_set_default(VALUE self, VALUE ifnone)
{
    llrbtree_modify(self);
    IFNONE(self) = ifnone;
    FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
    return ifnone;
}

#default_procObject



474
475
476
477
478
479
480
# File 'ext/llrbtree/llrbtree.c', line 474

VALUE
llrbtree_default_proc(VALUE self)
{
    if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
        return IFNONE(self);
    return Qnil;
}

#default_proc=(proc) ⇒ Object



485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'ext/llrbtree/llrbtree.c', line 485

VALUE
llrbtree_set_default_proc(VALUE self, VALUE proc)
{
    VALUE temp;

    llrbtree_modify(self);
    if (NIL_P(proc)) {
        IFNONE(self) = Qnil;
        FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
        return Qnil;
    }

    temp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
    if (NIL_P(temp)) {
        rb_raise(rb_eTypeError,
                 "wrong default_proc type %s (expected Proc)",
                 rb_obj_classname(proc));
    }
    llrbtree_check_proc_arity(temp, 2);
    IFNONE(self) = temp;
    FL_SET(self, LLRBTREE_PROC_DEFAULT);
    return proc;
}

#delete(key) ⇒ Object



836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'ext/llrbtree/llrbtree.c', line 836

VALUE
llrbtree_delete(VALUE self, VALUE key)
{
    tree_t* tree = TREE(self);
    void* deleted_data = NULL;

    llrbtree_modify(self);
    deleted_data = tree_delete(tree, TO_KEY(key));
    if (deleted_data == NULL)
        return rb_block_given_p() ? rb_yield(key) : Qnil;

    return (VALUE)deleted_data;
}

#delete_ifObject



927
928
929
930
931
# File 'ext/llrbtree/llrbtree.c', line 927

VALUE
llrbtree_delete_if(VALUE self)
{
    return llrbtree_remove_if(self, 1);
}

#each {|key, value| ... } ⇒ Object #each_pair {|key, value| ... } ⇒ Object #eachObject #each_pairObject

Calls block once for each key in order, passing the key-value pair as parameters.

Returns an enumerator if no block is given.

Overloads:

  • #each {|key, value| ... } ⇒ Object

    Yields:

  • #each_pair {|key, value| ... } ⇒ Object

    Yields:



646
647
648
649
650
651
# File 'ext/llrbtree/llrbtree.c', line 646

VALUE
llrbtree_each_pair(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    return llrbtree_for_each(self, each_pair_i, NULL);
}

#each_key {|key| ... } ⇒ Object #each_keyObject

Calls block once for each key in order, passing the key as a parameter.

Returns an enumerator if no block is given.

Overloads:

  • #each_key {|key| ... } ⇒ Object

    Yields:



670
671
672
673
674
675
# File 'ext/llrbtree/llrbtree.c', line 670

VALUE
llrbtree_each_key(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    return llrbtree_for_each(self, each_key_i, NULL);
}

#each {|key, value| ... } ⇒ Object #each_pair {|key, value| ... } ⇒ Object #eachObject #each_pairObject

Calls block once for each key in order, passing the key-value pair as parameters.

Returns an enumerator if no block is given.

Overloads:

  • #each {|key, value| ... } ⇒ Object

    Yields:

  • #each_pair {|key, value| ... } ⇒ Object

    Yields:



646
647
648
649
650
651
# File 'ext/llrbtree/llrbtree.c', line 646

VALUE
llrbtree_each_pair(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    return llrbtree_for_each(self, each_pair_i, NULL);
}

#each_value {|value| ... } ⇒ Object #each_valueObject

Calls block once for each key in order, passing the value as a parameter.

Returns an enumerator if no block is given.

Overloads:

  • #each_value {|value| ... } ⇒ Object

    Yields:

    • (value)


694
695
696
697
698
699
# File 'ext/llrbtree/llrbtree.c', line 694

VALUE
llrbtree_each_value(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    return llrbtree_for_each(self, each_value_i, NULL);
}

#empty?Boolean

Returns:

  • (Boolean)


437
438
439
440
441
# File 'ext/llrbtree/llrbtree.c', line 437

VALUE
llrbtree_empty_p(VALUE self)
{
    return tree_isempty(TREE(self)) ? Qtrue : Qfalse;
}

#fetch(*args) ⇒ Object



401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'ext/llrbtree/llrbtree.c', line 401

VALUE
llrbtree_fetch(int argc, VALUE* argv, VALUE self)
{
    node_t* node;

    llrbtree_check_argument_count(argc, 1, 2);
    if (argc == 2 && rb_block_given_p()) {
        rb_warn("block supersedes default value argument");
    }

    node = tree_lookup(TREE(self), TO_KEY(argv[0]));
    if (node != NULL) {
        return GET_VAL(node);
    }

    if (rb_block_given_p()) {
        return rb_yield(argv[0]);
    }
    if (argc == 1) {
        rb_raise(rb_eIndexError, "key not found");
    }
    return argv[1];
}

#firstArray, ...

Returns the first (that is, the smallest) key-value pair.

Returns:

  • (Array, Object, nil)


1554
1555
1556
1557
1558
# File 'ext/llrbtree/llrbtree.c', line 1554

VALUE
llrbtree_first(VALUE self)
{
    return llrbtree_first_last(self, 1);
}

#flatten(*args) ⇒ Object



1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
# File 'ext/llrbtree/llrbtree.c', line 1148

VALUE
llrbtree_flatten(int argc, VALUE* argv, VALUE self)
{
    VALUE ary;

    llrbtree_check_argument_count(argc, 0, 1);
    ary = rb_ary_new2(TREE(self)->node_count * 2);
    llrbtree_for_each(self, to_flat_ary_i, (void*)ary);
    if (argc == 1) {
        const int level = NUM2INT(argv[0]) - 1;
        if (level > 0) {
            argv[0] = INT2FIX(level);
            rb_funcall2(ary, id_flatten_bang, argc, argv);
        }
    }
    return ary;
}

#has_key?(key) ⇒ Boolean

Returns:

  • (Boolean)


1169
1170
1171
1172
1173
# File 'ext/llrbtree/llrbtree.c', line 1169

VALUE
llrbtree_has_key(VALUE self, VALUE key)
{
    return tree_lookup(TREE(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
}

#has_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


1189
1190
1191
1192
1193
1194
1195
1196
1197
# File 'ext/llrbtree/llrbtree.c', line 1189

VALUE
llrbtree_has_value(VALUE self, VALUE value)
{
    VALUE args[2];
    args[0] = Qfalse;
    args[1] = value;
    llrbtree_for_each(self, has_value_i, &args);
    return args[0];
}

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


1169
1170
1171
1172
1173
# File 'ext/llrbtree/llrbtree.c', line 1169

VALUE
llrbtree_has_key(VALUE self, VALUE key)
{
    return tree_lookup(TREE(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
}

#index(value) ⇒ Object



814
815
816
817
818
819
820
# File 'ext/llrbtree/llrbtree.c', line 814

VALUE
llrbtree_index(VALUE self, VALUE value)
{
    const char* classname = rb_class2name(LLRBTree);
    rb_warn("%s#index is deprecated; use %s#key", classname, classname);
    return llrbtree_key(self, value);
}

#initialize_copy(other) ⇒ Object



750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
# File 'ext/llrbtree/llrbtree.c', line 750

VALUE
llrbtree_initialize_copy(VALUE self, VALUE other)
{
    llrbtree_modify(self);

    if (self == other)
        return self;
    if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
                 rb_obj_classname(other),
                 rb_obj_classname(self));
    }

    copy_tree(other, self, TREE(other)->compare, CMP_PROC(other));

    IFNONE(self) = IFNONE(other);
    if (FL_TEST(other, LLRBTREE_PROC_DEFAULT))
        FL_SET(self, LLRBTREE_PROC_DEFAULT);
    else
        FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
    return self;
}

#inspectObject Also known as: to_s



1357
1358
1359
1360
1361
# File 'ext/llrbtree/llrbtree.c', line 1357

VALUE
llrbtree_inspect(VALUE self)
{
    return rb_exec_recursive(llrbtree_inspect_recursive, self, Qnil);
}

#invertObject



1084
1085
1086
1087
1088
1089
1090
# File 'ext/llrbtree/llrbtree.c', line 1084

VALUE
llrbtree_invert(VALUE self)
{
    VALUE llrbtree = llrbtree_alloc(CLASS_OF(self));
    llrbtree_for_each(self, invert_i, (void*)llrbtree);
    return llrbtree;
}

#keep_ifObject



936
937
938
939
940
# File 'ext/llrbtree/llrbtree.c', line 936

VALUE
llrbtree_keep_if(VALUE self)
{
    return llrbtree_remove_if(self, 0);
}

#key(value) ⇒ Object



801
802
803
804
805
806
807
808
809
# File 'ext/llrbtree/llrbtree.c', line 801

VALUE
llrbtree_key(VALUE self, VALUE value)
{
    VALUE args[2];
    args[0] = Qnil;
    args[1] = value;
    llrbtree_for_each(self, key_i, &args);
    return args[0];
}

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


1169
1170
1171
1172
1173
# File 'ext/llrbtree/llrbtree.c', line 1169

VALUE
llrbtree_has_key(VALUE self, VALUE key)
{
    return tree_lookup(TREE(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
}

#keysObject



1209
1210
1211
1212
1213
1214
1215
# File 'ext/llrbtree/llrbtree.c', line 1209

VALUE
llrbtree_keys(VALUE self)
{
    VALUE ary = rb_ary_new2(TREE(self)->node_count);
    llrbtree_for_each(self, keys_i, (void*)ary);
    return ary;
}

#lastArray, ...

Returns the last (that is, the greatest) key-value pair.

Returns:

  • (Array, Object, nil)


1566
1567
1568
1569
1570
# File 'ext/llrbtree/llrbtree.c', line 1566

VALUE
llrbtree_last(VALUE self)
{
    return llrbtree_first_last(self, 0);
}

#lengthObject



428
429
430
431
432
# File 'ext/llrbtree/llrbtree.c', line 428

VALUE
llrbtree_size(VALUE self)
{
    return ULONG2NUM(TREE(self)->node_count);
}

#lower_bound(key) ⇒ Array?

Retruns the key-value pair corresponding to the lowest key that is equal to or greater than the given key (inside the lower boundary). If there is no such key, returns nil.

llrbtree = LLRBTree["az", 10, "ba", 20]
llrbtree.lower_bound("ba") # => ["ba", 20]

# "ba" is the lowest key that is greater than "b"
llrbtree.lower_bound("b") # => ["ba", 20]

# no key that is equal to or greater than "c"
llrbtree.lower_bound("c") # => nil

Returns:

  • (Array, nil)


1380
1381
1382
1383
1384
1385
1386
1387
# File 'ext/llrbtree/llrbtree.c', line 1380

VALUE
llrbtree_lower_bound(VALUE self, VALUE key)
{
    node_t* node = tree_lower_bound(TREE(self), TO_KEY(key));
    if (node == NULL)
        return Qnil;
    return ASSOC(node);
}

#member?(key) ⇒ Boolean

Returns:

  • (Boolean)


1169
1170
1171
1172
1173
# File 'ext/llrbtree/llrbtree.c', line 1169

VALUE
llrbtree_has_key(VALUE self, VALUE key)
{
    return tree_lookup(TREE(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
}

#merge(other) ⇒ Object



1131
1132
1133
1134
1135
# File 'ext/llrbtree/llrbtree.c', line 1131

VALUE
llrbtree_merge(VALUE self, VALUE other)
{
    return llrbtree_update(rb_obj_dup(self), other);
}

#merge!(other) ⇒ Object



1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
# File 'ext/llrbtree/llrbtree.c', line 1108

VALUE
llrbtree_update(VALUE self, VALUE other)
{
    llrbtree_modify(self);

    if (self == other)
        return self;
    if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
                 rb_obj_classname(other),
                 rb_obj_classname(self));
    }

    if (rb_block_given_p())
        llrbtree_for_each(other, update_block_i, (void*)self);
    else
        llrbtree_for_each(other, aset_i, (void*)self);
    return self;
}

#popArray, ...

Removes the last (that is, the greatest) key-value pair and returns it.

Returns:

  • (Array, Object, nil)


1068
1069
1070
1071
1072
# File 'ext/llrbtree/llrbtree.c', line 1068

VALUE
llrbtree_pop(VALUE self)
{
    return llrbtree_shift_pop(self, 1);
}

#pretty_print(pp) ⇒ Object

:nodoc:



1775
1776
1777
1778
1779
1780
1781
1782
# File 'ext/llrbtree/llrbtree.c', line 1775

VALUE
llrbtree_pretty_print(VALUE self, VALUE pp)
{
    pp_llrbtree_arg_t arg;
    arg.llrbtree = self;
    arg.pp = pp;
    return rb_iterate(pp_llrbtree_group, (VALUE)&arg, pp_llrbtree, (VALUE)&arg);
}

#pretty_print_cycle(pp) ⇒ Object

:nodoc:



1787
1788
1789
1790
1791
# File 'ext/llrbtree/llrbtree.c', line 1787

VALUE
llrbtree_pretty_print_cycle(VALUE self, VALUE pp)
{
    return rb_funcall(pp, id_pp, 1, llrbtree_inspect_recursive(self, Qnil, 1));
}

#readjustObject #readjust(nil) ⇒ Object #readjust(proc) ⇒ Object #readjust {|key1, key2| ... } ⇒ Object

Sets a proc to compare keys and readjusts elements using the given block or a Proc object given as an argument. The block takes two keys and returns a negative integer, 0, or a positive integer as the first argument is less than, equal to, or greater than the second one. If no block is given, just readjusts elements using the current comparison block. If nil is given as an argument the default comparison block that uses the <=> method is set.

llrbtree = LLRBTree["a", 10, "b", 20]
llrbtree.readjust {|a, b| b <=> a }
llrbtree.first # => ["b", 20]

llrbtree.readjust(nil)
llrbtree.first # => ["a", 10]

Overloads:

  • #readjust {|key1, key2| ... } ⇒ Object

    Yields:

    • (key1, key2)


1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
# File 'ext/llrbtree/llrbtree.c', line 1594

VALUE
llrbtree_readjust(int argc, VALUE* argv, VALUE self)
{
    compare_t cmp_func = NULL;
    VALUE cmp_proc = Qnil;

    llrbtree_modify(self);

    if (rb_block_given_p()) {
        llrbtree_check_argument_count(argc, 0, 0);
        cmp_func = llrbtree_user_cmp;
        cmp_proc = rb_block_proc();
        llrbtree_check_proc_arity(cmp_proc, 2);
    } else {
        llrbtree_check_argument_count(argc, 0, 1);
        if (argc == 0) {
            cmp_func = TREE(self)->compare;
            cmp_proc = CMP_PROC(self);
        } else {
            if (NIL_P(argv[0])) {
                cmp_func = llrbtree_cmp;
                cmp_proc = Qnil;
            } else {
                VALUE proc = rb_check_convert_type(argv[0], T_DATA, "Proc", "to_proc");
                if (NIL_P(proc)) {
                    rb_raise(rb_eTypeError,
                             "wrong cmp_proc type %s (expected Proc)",
                             rb_obj_classname(argv[0]));
                }
                cmp_func = llrbtree_user_cmp;
                cmp_proc = proc;
                llrbtree_check_proc_arity(cmp_proc, 2);
            }
        }
    }

    if (tree_isempty(TREE(self))) {
        TREE(self)->compare = cmp_func;
        CMP_PROC(self) = cmp_proc;
        return self;
    }
    copy_tree(self, self, cmp_func, cmp_proc);
    return self;
}

#rejectObject



1012
1013
1014
1015
1016
# File 'ext/llrbtree/llrbtree.c', line 1012

VALUE
llrbtree_reject(VALUE self)
{
    return llrbtree_select_if(self, 0);
}

#reject!Object



945
946
947
948
949
950
951
952
953
954
955
956
# File 'ext/llrbtree/llrbtree.c', line 945

VALUE
llrbtree_reject_bang(VALUE self)
{
    node_count_t count;

    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    count = TREE(self)->node_count;
    llrbtree_delete_if(self);
    if (count == TREE(self)->node_count)
        return Qnil;
    return self;
}

#replace(other) ⇒ Object



750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
# File 'ext/llrbtree/llrbtree.c', line 750

VALUE
llrbtree_initialize_copy(VALUE self, VALUE other)
{
    llrbtree_modify(self);

    if (self == other)
        return self;
    if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
                 rb_obj_classname(other),
                 rb_obj_classname(self));
    }

    copy_tree(other, self, TREE(other)->compare, CMP_PROC(other));

    IFNONE(self) = IFNONE(other);
    if (FL_TEST(other, LLRBTREE_PROC_DEFAULT))
        FL_SET(self, LLRBTREE_PROC_DEFAULT);
    else
        FL_UNSET(self, LLRBTREE_PROC_DEFAULT);
    return self;
}

#reverse_each {|key, value| ... } ⇒ Object #reverse_eachObject

Calls block once for each key in reverse order, passing the key-value pair as parameters.

Returns an enumerator if no block is given.

Overloads:

  • #reverse_each {|key, value| ... } ⇒ Object

    Yields:



711
712
713
714
715
716
# File 'ext/llrbtree/llrbtree.c', line 711

VALUE
llrbtree_reverse_each(VALUE self)
{
    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    return llrbtree_reverse_for_each(self, each_pair_i, NULL);
}

#selectObject



1021
1022
1023
1024
1025
# File 'ext/llrbtree/llrbtree.c', line 1021

VALUE
llrbtree_select(VALUE self)
{
    return llrbtree_select_if(self, 1);
}

#select!Object



961
962
963
964
965
966
967
968
969
970
971
972
973
# File 'ext/llrbtree/llrbtree.c', line 961

VALUE
llrbtree_select_bang(VALUE self)
{
    node_count_t count;

    RETURN_SIZED_ENUMERATOR(self, 0, NULL, llrbtree_size);
    count = TREE(self)->node_count;
    llrbtree_keep_if(self);
    if (count == TREE(self)->node_count)
        return Qnil;
    return self;

}

#shiftArray, ...

Removes the first (that is, the smallest) key-value pair and returns it.

Returns:

  • (Array, Object, nil)


1055
1056
1057
1058
1059
# File 'ext/llrbtree/llrbtree.c', line 1055

VALUE
llrbtree_shift(VALUE self)
{
    return llrbtree_shift_pop(self, 0);
}

#sizeObject



428
429
430
431
432
# File 'ext/llrbtree/llrbtree.c', line 428

VALUE
llrbtree_size(VALUE self)
{
    return ULONG2NUM(TREE(self)->node_count);
}

#store(key, value) ⇒ Object



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'ext/llrbtree/llrbtree.c', line 368

VALUE
llrbtree_aset(VALUE self, VALUE key, VALUE value)
{
    llrbtree_modify(self);

    if (tree_isfull(TREE(self))) {
        node_t* node = tree_lookup(TREE(self), TO_KEY(key));
        if (node == NULL)
            rb_raise(rb_eIndexError, "llrbtree full");
        else
            node->data = TO_VAL(value);
        return value;
    }
    llrbtree_insert(self, key, value);
    return value;
}

#to_aObject



1245
1246
1247
1248
1249
1250
1251
1252
# File 'ext/llrbtree/llrbtree.c', line 1245

VALUE
llrbtree_to_a(VALUE self)
{
    VALUE ary = rb_ary_new2(TREE(self)->node_count);
    llrbtree_for_each(self, to_a_i, (void*)ary);
    OBJ_INFECT(ary, self);
    return ary;
}

#to_hObject



1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
# File 'ext/llrbtree/llrbtree.c', line 1264

VALUE
llrbtree_to_hash(VALUE self)
{
    VALUE hash;
    hash = rb_hash_new();
    llrbtree_for_each(self, to_hash_i, (void*)hash);
    RHASH_SET_IFNONE(hash, IFNONE(self));
    if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
        FL_SET(hash, HASH_PROC_DEFAULT);
    OBJ_INFECT(hash, self);
    return hash;
}

#to_hashObject



1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
# File 'ext/llrbtree/llrbtree.c', line 1264

VALUE
llrbtree_to_hash(VALUE self)
{
    VALUE hash;
    hash = rb_hash_new();
    llrbtree_for_each(self, to_hash_i, (void*)hash);
    RHASH_SET_IFNONE(hash, IFNONE(self));
    if (FL_TEST(self, LLRBTREE_PROC_DEFAULT))
        FL_SET(hash, HASH_PROC_DEFAULT);
    OBJ_INFECT(hash, self);
    return hash;
}

#to_llrbtreeObject



1280
1281
1282
1283
1284
# File 'ext/llrbtree/llrbtree.c', line 1280

VALUE
llrbtree_to_llrbtree(VALUE self)
{
    return self;
}

#update(other) ⇒ Object



1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
# File 'ext/llrbtree/llrbtree.c', line 1108

VALUE
llrbtree_update(VALUE self, VALUE other)
{
    llrbtree_modify(self);

    if (self == other)
        return self;
    if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
        rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
                 rb_obj_classname(other),
                 rb_obj_classname(self));
    }

    if (rb_block_given_p())
        llrbtree_for_each(other, update_block_i, (void*)self);
    else
        llrbtree_for_each(other, aset_i, (void*)self);
    return self;
}

#upper_bound(key) ⇒ Array?

Retruns the key-value pair corresponding to the greatest key that is equal to or lower than the given key (inside the upper boundary). If there is no such key, returns nil.

llrbtree = LLRBTree["az", 10, "ba", 20]
llrbtree.upper_bound("ba") # => ["ba", 20]

# "az" is the greatest key that is lower than "b"
llrbtree.upper_bound("b") # => ["az", 10]

# no key that is equal to or lower than "a"
llrbtree.upper_bound("a") # => nil

Returns:

  • (Array, nil)


1406
1407
1408
1409
1410
1411
1412
1413
# File 'ext/llrbtree/llrbtree.c', line 1406

VALUE
llrbtree_upper_bound(VALUE self, VALUE key)
{
    node_t* node = tree_upper_bound(TREE(self), TO_KEY(key));
    if (node == NULL)
        return Qnil;
    return ASSOC(node);
}

#value?(value) ⇒ Boolean

Returns:

  • (Boolean)


1189
1190
1191
1192
1193
1194
1195
1196
1197
# File 'ext/llrbtree/llrbtree.c', line 1189

VALUE
llrbtree_has_value(VALUE self, VALUE value)
{
    VALUE args[2];
    args[0] = Qfalse;
    args[1] = value;
    llrbtree_for_each(self, has_value_i, &args);
    return args[0];
}

#valuesObject



1227
1228
1229
1230
1231
1232
1233
# File 'ext/llrbtree/llrbtree.c', line 1227

VALUE
llrbtree_values(VALUE self)
{
    VALUE ary = rb_ary_new2(TREE(self)->node_count);
    llrbtree_for_each(self, values_i, (void*)ary);
    return ary;
}

#values_at(*args) ⇒ Object



776
777
778
779
780
781
782
783
784
785
# File 'ext/llrbtree/llrbtree.c', line 776

VALUE
llrbtree_values_at(int argc, VALUE* argv, VALUE self)
{
    long i;
    VALUE ary = rb_ary_new2(argc);

    for (i = 0; i < argc; i++)
        rb_ary_push(ary, llrbtree_aref(self, argv[i]));
    return ary;
}