rbtree 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (11) hide show
  1. data/ChangeLog +425 -0
  2. data/LICENSE +22 -0
  3. data/MANIFEST +10 -0
  4. data/README +78 -0
  5. data/depend +2 -0
  6. data/dict.c +1216 -0
  7. data/dict.h +123 -0
  8. data/extconf.rb +34 -0
  9. data/rbtree.c +1691 -0
  10. data/test.rb +895 -0
  11. metadata +58 -0
data/dict.h ADDED
@@ -0,0 +1,123 @@
1
+ /*
2
+ * Dictionary Abstract Data Type
3
+ * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
4
+ *
5
+ * Free Software License:
6
+ *
7
+ * All rights are reserved by the author, with the following exceptions:
8
+ * Permission is granted to freely reproduce and distribute this software,
9
+ * possibly in exchange for a fee, provided that this copyright notice appears
10
+ * intact. Permission is also granted to adapt this software to produce
11
+ * derivative works, as long as the modified versions carry this copyright
12
+ * notice and additional notices stating that the work has been modified.
13
+ * This source code may be translated into executable form and incorporated
14
+ * into proprietary software; there is no requirement for such software to
15
+ * contain a copyright notice related to this source.
16
+ *
17
+ * $Id: dict.h,v 1.9 2005/10/06 05:16:35 kuma Exp $
18
+ * $Name: $
19
+ */
20
+
21
+ /*
22
+ * Modified for Ruby/RBTree by OZAWA Takuma.
23
+ */
24
+
25
+ #ifndef DICT_H
26
+ #define DICT_H
27
+
28
+ #include <limits.h>
29
+
30
+ /*
31
+ * Blurb for inclusion into C++ translation units
32
+ */
33
+
34
+ #ifdef __cplusplus
35
+ extern "C" {
36
+ #endif
37
+
38
+ typedef unsigned long dictcount_t;
39
+ #define DICTCOUNT_T_MAX ULONG_MAX
40
+
41
+ /*
42
+ * The dictionary is implemented as a red-black tree
43
+ */
44
+
45
+ typedef enum { dnode_red, dnode_black } dnode_color_t;
46
+
47
+ typedef struct dnode_t {
48
+ struct dnode_t *dict_left;
49
+ struct dnode_t *dict_right;
50
+ struct dnode_t *dict_parent;
51
+ dnode_color_t dict_color;
52
+ const void *dict_key;
53
+ void *dict_data;
54
+ } dnode_t;
55
+
56
+ typedef int (*dict_comp_t)(const void *, const void *, void *);
57
+ typedef dnode_t *(*dnode_alloc_t)(void *);
58
+ typedef void (*dnode_free_t)(dnode_t *, void *);
59
+
60
+ typedef int (*dict_value_eql_t)(const void *, const void *);
61
+
62
+ typedef struct dict_t {
63
+ dnode_t dict_nilnode;
64
+ dictcount_t dict_nodecount;
65
+ dict_comp_t dict_compare;
66
+ dnode_alloc_t dict_allocnode;
67
+ dnode_free_t dict_freenode;
68
+ void *dict_context;
69
+ int dict_dupes;
70
+ } dict_t;
71
+
72
+ typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
73
+
74
+ typedef struct dict_load_t {
75
+ dict_t *dict_dictptr;
76
+ dnode_t dict_nilnode;
77
+ } dict_load_t;
78
+
79
+ extern dict_t *dict_create(dict_comp_t);
80
+ extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
81
+ extern void dict_destroy(dict_t *);
82
+ extern void dict_free_nodes(dict_t *);
83
+ extern void dict_free(dict_t *);
84
+ extern dict_t *dict_init(dict_t *, dict_comp_t);
85
+ extern void dict_init_like(dict_t *, const dict_t *);
86
+ extern int dict_verify(dict_t *);
87
+ extern int dict_similar(const dict_t *, const dict_t *);
88
+ extern dnode_t *dict_lookup(dict_t *, const void *);
89
+ extern dnode_t *dict_lower_bound(dict_t *, const void *);
90
+ extern dnode_t *dict_upper_bound(dict_t *, const void *);
91
+ extern int dict_insert(dict_t *, dnode_t *, const void *);
92
+ extern dnode_t *dict_delete(dict_t *, dnode_t *);
93
+ extern int dict_alloc_insert(dict_t *, const void *, void *);
94
+ extern void dict_delete_free(dict_t *, dnode_t *);
95
+ extern dnode_t *dict_first(dict_t *);
96
+ extern dnode_t *dict_last(dict_t *);
97
+ extern dnode_t *dict_next(dict_t *, dnode_t *);
98
+ extern dnode_t *dict_prev(dict_t *, dnode_t *);
99
+ extern dictcount_t dict_count(dict_t *);
100
+ extern int dict_isempty(dict_t *);
101
+ extern int dict_isfull(dict_t *);
102
+ extern int dict_contains(dict_t *, dnode_t *);
103
+ extern void dict_allow_dupes(dict_t *);
104
+ extern int dnode_is_in_a_dict(dnode_t *);
105
+ extern dnode_t *dnode_create(void *);
106
+ extern dnode_t *dnode_init(dnode_t *, void *);
107
+ extern void dnode_destroy(dnode_t *);
108
+ extern void *dnode_get(dnode_t *);
109
+ extern const void *dnode_getkey(dnode_t *);
110
+ extern void dnode_put(dnode_t *, void *);
111
+ extern void dict_process(dict_t *, void *, dnode_process_t);
112
+ extern void dict_load_begin(dict_load_t *, dict_t *);
113
+ extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
114
+ extern void dict_load_end(dict_load_t *);
115
+ extern void dict_merge(dict_t *, dict_t *);
116
+
117
+ int dict_equal(dict_t*, dict_t*, dict_value_eql_t);
118
+
119
+ #ifdef __cplusplus
120
+ }
121
+ #endif
122
+
123
+ #endif
@@ -0,0 +1,34 @@
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+
4
+ if Config::CONFIG['CC'] =~ /gcc/
5
+ $CFLAGS << ' -std=c89 -pedantic -Wall -Wno-long-long'
6
+ end
7
+
8
+ $defs << '-DNDEBUG'
9
+
10
+ print 'checking for allocation framework... '
11
+ if Object.respond_to?(:allocate)
12
+ print "yes\n"
13
+ $defs << '-DHAVE_OBJECT_ALLOCATE'
14
+ else
15
+ print "no\n"
16
+ end
17
+
18
+ have_func('rb_obj_init_copy')
19
+ have_func('rb_block_proc')
20
+ have_func('rb_yield_values')
21
+ have_func('rb_marshal_dump')
22
+ have_func('rb_marshal_load')
23
+
24
+ print 'checking for inline keyword... '
25
+ inline = ['inline', '__inline', '__inline__', ''].find {|e|
26
+ try_link(<<EOS)
27
+ int main() { return 0; }
28
+ #{e} void foo() {}
29
+ EOS
30
+ }
31
+ print "#{inline}\n"
32
+ $defs << "-Dinline=#{inline}"
33
+
34
+ create_makefile('rbtree')
@@ -0,0 +1,1691 @@
1
+ /*
2
+ * MIT License
3
+ * Copyright (c) 2002-2004, 2007 OZAWA Takuma
4
+ */
5
+ #include <ruby.h>
6
+ #include <version.h>
7
+ #include <st.h>
8
+ #include <stdarg.h>
9
+ #include "dict.h"
10
+
11
+ #define RBTREE_IN_ITERATION FL_USER1
12
+ #define RBTREE_PROC_DEFAULT FL_USER2
13
+ #define HASH_PROC_DEFAULT FL_USER2
14
+
15
+ #ifndef ULONG2NUM
16
+ #define ULONG2NUM UINT2NUM
17
+ #endif
18
+
19
+ VALUE RBTree;
20
+ VALUE MultiRBTree;
21
+
22
+ static ID id_bound;
23
+ static ID id_cmp;
24
+ static ID id_call;
25
+ static ID id_default;
26
+
27
+ #ifndef HAVE_RB_MARSHAL_DUMP
28
+ static VALUE rb_mMarshal;
29
+ static ID id_dump;
30
+ static ID id_load;
31
+ #endif
32
+
33
+ typedef struct {
34
+ dict_t* dict;
35
+ VALUE ifnone;
36
+ int iter_lev;
37
+ } rbtree_t;
38
+
39
+ #define RBTREE(rbtree) DATA_PTR(rbtree)
40
+ #define DICT(rbtree) ((rbtree_t*)RBTREE(rbtree))->dict
41
+ #define IFNONE(rbtree) ((rbtree_t*)RBTREE(rbtree))->ifnone
42
+ #define ITER_LEV(rbtree) ((rbtree_t*)RBTREE(rbtree))->iter_lev
43
+ #define COMPARE(rbtree) DICT(rbtree)->dict_compare
44
+ #define CONTEXT(rbtree) DICT(rbtree)->dict_context
45
+
46
+ #define TO_KEY(arg) ((const void*)arg)
47
+ #define TO_VAL(arg) ((void*)arg)
48
+ #define GET_KEY(dnode) ((VALUE)dnode_getkey(dnode))
49
+ #define GET_VAL(dnode) ((VALUE)dnode_get(dnode))
50
+ #define ASSOC(dnode) rb_assoc_new(GET_KEY(dnode), GET_VAL(dnode))
51
+
52
+ /*********************************************************************/
53
+
54
+ #ifndef HAVE_RB_BLOCK_PROC
55
+ static VALUE
56
+ rb_block_proc()
57
+ {
58
+ return rb_f_lambda();
59
+ }
60
+ #endif
61
+
62
+ #ifndef HAVE_RB_YIELD_VALUES
63
+ static VALUE
64
+ rb_yield_values(int n, ...)
65
+ {
66
+ int i;
67
+ va_list ap;
68
+ VALUE ary = rb_ary_new2(n);
69
+
70
+ va_start(ap, n);
71
+ for (i = 0; i < n; i++)
72
+ rb_ary_push(ary, va_arg(ap, VALUE));
73
+ va_end(ap);
74
+ return rb_yield(ary);
75
+ }
76
+ #endif
77
+
78
+ static int
79
+ cmpint(VALUE i, VALUE a, VALUE b)
80
+ {
81
+ #if RUBY_VERSION_CODE >= 180
82
+ return rb_cmpint(i, a, b);
83
+ #else
84
+ return rb_cmpint(i);
85
+ #endif
86
+ }
87
+
88
+
89
+ static void
90
+ rbtree_free(rbtree_t* rbtree)
91
+ {
92
+ dict_free_nodes(rbtree->dict);
93
+ dict_destroy(rbtree->dict);
94
+ xfree(rbtree);
95
+ }
96
+
97
+ static void
98
+ rbtree_mark(rbtree_t* rbtree)
99
+ {
100
+ if (rbtree == NULL) return;
101
+
102
+ if (rbtree->dict != NULL) {
103
+ dict_t* dict = rbtree->dict;
104
+ dnode_t* node;
105
+ for (node = dict_first(dict);
106
+ node != NULL;
107
+ node = dict_next(dict, node)) {
108
+
109
+ rb_gc_mark(GET_KEY(node));
110
+ rb_gc_mark(GET_VAL(node));
111
+ }
112
+ rb_gc_mark((VALUE)dict->dict_context);
113
+ }
114
+ rb_gc_mark(rbtree->ifnone);
115
+ }
116
+
117
+ static dnode_t*
118
+ rbtree_alloc_node(void* context)
119
+ {
120
+ return ALLOC(dnode_t);
121
+ }
122
+
123
+ static void
124
+ rbtree_free_node(dnode_t* node, void* context)
125
+ {
126
+ xfree(node);
127
+ }
128
+
129
+ static void
130
+ rbtree_argc_error()
131
+ {
132
+ rb_raise(rb_eArgError, "wrong number of arguments");
133
+ }
134
+
135
+ static int
136
+ rbtree_cmp(const void* key1, const void* key2, void* context)
137
+ {
138
+ VALUE ret;
139
+ if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
140
+ return rb_str_cmp((VALUE)key1, (VALUE)key2);
141
+ ret = rb_funcall((VALUE)key1, id_cmp, 1, (VALUE)key2);
142
+ return cmpint(ret, (VALUE)key1, (VALUE)key2);
143
+ }
144
+
145
+ static int
146
+ rbtree_user_cmp(const void* key1, const void* key2, void* cmp_proc)
147
+ {
148
+ VALUE ret = rb_funcall((VALUE)cmp_proc, id_call, 2,
149
+ (VALUE)key1, (VALUE)key2);
150
+ return cmpint(ret, (VALUE)key1, (VALUE)key2);
151
+ }
152
+
153
+ static void
154
+ rbtree_modify(VALUE self)
155
+ {
156
+ if (ITER_LEV(self) > 0)
157
+ rb_raise(rb_eTypeError, "can't modify rbtree in iteration");
158
+ if (OBJ_FROZEN(self))
159
+ rb_error_frozen("rbtree");
160
+ if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
161
+ rb_raise(rb_eSecurityError, "Insecure: can't modify rbtree");
162
+ }
163
+
164
+ static VALUE
165
+ rbtree_alloc(VALUE klass)
166
+ {
167
+ dict_t* dict;
168
+ VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, 0);
169
+ RBTREE(rbtree) = ALLOC(rbtree_t);
170
+ MEMZERO(RBTREE(rbtree), rbtree_t, 1);
171
+
172
+ dict = dict_create(rbtree_cmp);
173
+ dict_set_allocator(dict, rbtree_alloc_node, rbtree_free_node,
174
+ (void*)Qnil);
175
+ if (klass == MultiRBTree)
176
+ dict_allow_dupes(dict);
177
+
178
+ DICT(rbtree) = dict;
179
+ IFNONE(rbtree) = Qnil;
180
+ return rbtree;
181
+ }
182
+
183
+ VALUE rbtree_aset(VALUE, VALUE, VALUE);
184
+ VALUE rbtree_clear(VALUE);
185
+ VALUE rbtree_has_key(VALUE, VALUE);
186
+ VALUE rbtree_update(VALUE, VALUE);
187
+
188
+ /*********************************************************************/
189
+
190
+ #ifndef HAVE_OBJECT_ALLOCATE
191
+ /*
192
+ *
193
+ */
194
+ VALUE
195
+ rbtree_s_new(int argc, VALUE* argv, VALUE klass)
196
+ {
197
+ VALUE rbtree = rbtree_alloc(klass);
198
+ rb_obj_call_init(rbtree, argc, argv);
199
+ return rbtree;
200
+ }
201
+ #endif
202
+
203
+ static int
204
+ hash_to_rbtree_i(VALUE key, VALUE value, VALUE rbtree)
205
+ {
206
+ if (key != Qundef)
207
+ rbtree_aset(rbtree, key, value);
208
+ return ST_CONTINUE;
209
+ }
210
+
211
+ /*
212
+ *
213
+ */
214
+ VALUE
215
+ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
216
+ {
217
+ int i;
218
+ VALUE rbtree;
219
+
220
+ if (argc == 1) {
221
+ if (rb_obj_is_kind_of(argv[0], klass)) {
222
+ rbtree = rbtree_alloc(klass);
223
+ rbtree_update(rbtree, argv[0]);
224
+ return rbtree;
225
+ } else if (TYPE(argv[0]) == T_HASH) {
226
+ rbtree = rbtree_alloc(klass);
227
+ st_foreach(RHASH(argv[0])->tbl, hash_to_rbtree_i, rbtree);
228
+ return rbtree;
229
+ }
230
+ }
231
+
232
+ if (argc % 2 != 0)
233
+ rb_raise(rb_eArgError, "odd number of arguments for RBTree");
234
+
235
+ rbtree = rbtree_alloc(klass);
236
+ for (i = 0; i < argc; i += 2)
237
+ rbtree_aset(rbtree, argv[i], argv[i + 1]);
238
+ return rbtree;
239
+ }
240
+
241
+ /*
242
+ *
243
+ */
244
+ VALUE
245
+ rbtree_initialize(int argc, VALUE* argv, VALUE self)
246
+ {
247
+ rbtree_modify(self);
248
+
249
+ if (rb_block_given_p()) {
250
+ if (argc > 0)
251
+ rbtree_argc_error();
252
+ IFNONE(self) = rb_block_proc();
253
+ FL_SET(self, RBTREE_PROC_DEFAULT);
254
+ } else {
255
+ if (argc > 1)
256
+ rbtree_argc_error();
257
+ else if (argc == 1)
258
+ IFNONE(self) = argv[0];
259
+ }
260
+ return self;
261
+ }
262
+
263
+ /*********************************************************************/
264
+
265
+ typedef enum {
266
+ INITIAL_VALUE, NODE_NOT_FOUND, NODE_FOUND
267
+ } insert_node_ret_t;
268
+
269
+ typedef struct {
270
+ dict_t* dict;
271
+ dnode_t* node;
272
+ const void* key;
273
+ insert_node_ret_t ret;
274
+ } insert_node_t;
275
+
276
+ static VALUE
277
+ insert_node_body(insert_node_t* arg)
278
+ {
279
+ if (dict_insert(arg->dict, arg->node, arg->key))
280
+ arg->ret = NODE_NOT_FOUND;
281
+ else
282
+ arg->ret = NODE_FOUND;
283
+ return Qnil;
284
+ }
285
+
286
+ static VALUE
287
+ insert_node_ensure(insert_node_t* arg)
288
+ {
289
+ dict_t* dict = arg->dict;
290
+ dnode_t* node = arg->node;
291
+ switch (arg->ret) {
292
+ case INITIAL_VALUE:
293
+ dict->dict_freenode(node, dict->dict_context);
294
+ break;
295
+ case NODE_NOT_FOUND:
296
+ if (TYPE(arg->key) == T_STRING)
297
+ node->dict_key = TO_KEY(rb_str_new4(GET_KEY(node)));
298
+ break;
299
+ case NODE_FOUND:
300
+ dict->dict_freenode(node, dict->dict_context);
301
+ break;
302
+ }
303
+ return Qnil;
304
+ }
305
+
306
+ static void
307
+ rbtree_insert(VALUE self, VALUE key, VALUE value)
308
+ {
309
+ insert_node_t arg;
310
+ dict_t* dict = DICT(self);
311
+ dnode_t* node = dict->dict_allocnode(dict->dict_context);
312
+
313
+ dnode_init(node, TO_VAL(value));
314
+
315
+ arg.dict = dict;
316
+ arg.node = node;
317
+ arg.key = TO_KEY(key);
318
+ arg.ret = INITIAL_VALUE;
319
+
320
+ rb_ensure(insert_node_body, (VALUE)&arg,
321
+ insert_node_ensure, (VALUE)&arg);
322
+ }
323
+
324
+ /*********************************************************************/
325
+
326
+ /*
327
+ *
328
+ */
329
+ VALUE
330
+ rbtree_aset(VALUE self, VALUE key, VALUE value)
331
+ {
332
+ rbtree_modify(self);
333
+
334
+ if (dict_isfull(DICT(self))) {
335
+ dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
336
+ if (node == NULL)
337
+ rb_raise(rb_eIndexError, "rbtree full");
338
+ else
339
+ dnode_put(node, TO_VAL(value));
340
+ return value;
341
+ }
342
+ rbtree_insert(self, key, value);
343
+ return value;
344
+ }
345
+
346
+ /*
347
+ *
348
+ */
349
+ VALUE
350
+ rbtree_aref(VALUE self, VALUE key)
351
+ {
352
+ dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
353
+ if (node == NULL)
354
+ return rb_funcall(self, id_default, 1, key);
355
+ else
356
+ return GET_VAL(node);
357
+ }
358
+
359
+ /*
360
+ *
361
+ */
362
+ VALUE
363
+ rbtree_fetch(int argc, VALUE* argv, VALUE self)
364
+ {
365
+ dnode_t* node;
366
+ int block_given;
367
+
368
+ if (argc == 0 || argc > 2)
369
+ rbtree_argc_error();
370
+ block_given = rb_block_given_p();
371
+ if (block_given && argc == 2)
372
+ rb_warn("block supersedes default value argument");
373
+
374
+ node = dict_lookup(DICT(self), TO_KEY(argv[0]));
375
+ if (node != NULL)
376
+ return GET_VAL(node);
377
+
378
+ if (block_given)
379
+ return rb_yield(argv[0]);
380
+ if (argc == 1)
381
+ rb_raise(rb_eIndexError, "key not found");
382
+ return argv[1];
383
+ }
384
+
385
+ /*
386
+ *
387
+ */
388
+ VALUE
389
+ rbtree_size(VALUE self)
390
+ {
391
+ return ULONG2NUM(dict_count(DICT(self)));
392
+ }
393
+
394
+ /*
395
+ *
396
+ */
397
+ VALUE
398
+ rbtree_empty_p(VALUE self)
399
+ {
400
+ return dict_isempty(DICT(self)) ? Qtrue : Qfalse;
401
+ }
402
+
403
+ /*
404
+ *
405
+ */
406
+ VALUE
407
+ rbtree_default(int argc, VALUE* argv, VALUE self)
408
+ {
409
+ VALUE key = Qnil;
410
+ if (argc == 1)
411
+ key = argv[0];
412
+ else if (argc > 1)
413
+ rbtree_argc_error();
414
+
415
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
416
+ if (argc == 0) return Qnil;
417
+ return rb_funcall(IFNONE(self), id_call, 2, self, key);
418
+ }
419
+ return IFNONE(self);
420
+ }
421
+
422
+ /*
423
+ *
424
+ */
425
+ VALUE
426
+ rbtree_set_default(VALUE self, VALUE ifnone)
427
+ {
428
+ rbtree_modify(self);
429
+ IFNONE(self) = ifnone;
430
+ FL_UNSET(self, RBTREE_PROC_DEFAULT);
431
+ return ifnone;
432
+ }
433
+
434
+ /*
435
+ *
436
+ */
437
+ VALUE
438
+ rbtree_default_proc(VALUE self)
439
+ {
440
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT))
441
+ return IFNONE(self);
442
+ return Qnil;
443
+ }
444
+
445
+ static int
446
+ value_eq(const void* key1, const void* key2)
447
+ {
448
+ return rb_equal((VALUE)key1, (VALUE)key2);
449
+ }
450
+
451
+ /*
452
+ *
453
+ */
454
+ VALUE
455
+ rbtree_equal(VALUE self, VALUE other)
456
+ {
457
+ int ret;
458
+ if (self == other)
459
+ return Qtrue;
460
+ if (!rb_obj_is_kind_of(other, MultiRBTree))
461
+ return Qfalse;
462
+ ret = dict_equal(DICT(self), DICT(other), value_eq);
463
+ return ret ? Qtrue : Qfalse;
464
+ }
465
+
466
+ /*********************************************************************/
467
+
468
+ typedef enum {
469
+ EACH_NEXT, EACH_STOP
470
+ } each_return_t;
471
+
472
+ typedef each_return_t (*each_callback_func)(dnode_t*, void*);
473
+
474
+ typedef struct {
475
+ VALUE self;
476
+ each_callback_func func;
477
+ void* arg;
478
+ int reverse;
479
+ } rbtree_each_arg_t;
480
+
481
+ static VALUE
482
+ rbtree_each_ensure(VALUE self)
483
+ {
484
+ ITER_LEV(self)--;
485
+ return Qnil;
486
+ }
487
+
488
+ static VALUE
489
+ rbtree_each_body(rbtree_each_arg_t* arg)
490
+ {
491
+ VALUE self = arg->self;
492
+ dict_t* dict = DICT(self);
493
+ dnode_t* node;
494
+ dnode_t* first_node;
495
+ dnode_t* (*next_func)(dict_t*, dnode_t*);
496
+
497
+ if (arg->reverse) {
498
+ first_node = dict_last(dict);
499
+ next_func = dict_prev;
500
+ } else {
501
+ first_node = dict_first(dict);
502
+ next_func = dict_next;
503
+ }
504
+
505
+ ITER_LEV(self)++;
506
+ for (node = first_node;
507
+ node != NULL;
508
+ node = next_func(dict, node)) {
509
+
510
+ if (arg->func(node, arg->arg) == EACH_STOP)
511
+ break;
512
+ }
513
+ return self;
514
+ }
515
+
516
+ static VALUE
517
+ rbtree_for_each(VALUE self, each_callback_func func, void* arg)
518
+ {
519
+ rbtree_each_arg_t each_arg;
520
+ each_arg.self = self;
521
+ each_arg.func = func;
522
+ each_arg.arg = arg;
523
+ each_arg.reverse = 0;
524
+ return rb_ensure(rbtree_each_body, (VALUE)&each_arg,
525
+ rbtree_each_ensure, self);
526
+ }
527
+
528
+ static VALUE
529
+ rbtree_reverse_for_each(VALUE self, each_callback_func func, void* arg)
530
+ {
531
+ rbtree_each_arg_t each_arg;
532
+ each_arg.self = self;
533
+ each_arg.func = func;
534
+ each_arg.arg = arg;
535
+ each_arg.reverse = 1;
536
+ return rb_ensure(rbtree_each_body, (VALUE)&each_arg,
537
+ rbtree_each_ensure, self);
538
+ }
539
+
540
+ /*********************************************************************/
541
+
542
+ static each_return_t
543
+ each_i(dnode_t* node, void* arg)
544
+ {
545
+ rb_yield(ASSOC(node));
546
+ return EACH_NEXT;
547
+ }
548
+
549
+ /*
550
+ * call-seq:
551
+ * rbtree.each {|key, value| block} => rbtree
552
+ *
553
+ * Calls block once for each key in order, passing the key and value
554
+ * as a two-element array parameters.
555
+ */
556
+ VALUE
557
+ rbtree_each(VALUE self)
558
+ {
559
+ return rbtree_for_each(self, each_i, NULL);
560
+ }
561
+
562
+ static each_return_t
563
+ each_pair_i(dnode_t* node, void* arg)
564
+ {
565
+ rb_yield_values(2, GET_KEY(node), GET_VAL(node));
566
+ return EACH_NEXT;
567
+ }
568
+
569
+ /*
570
+ * call-seq:
571
+ * rbtree.each_pair {|key, value| block} => rbtree
572
+ *
573
+ * Calls block once for each key in order, passing the key and value
574
+ * as parameters.
575
+ */
576
+ VALUE
577
+ rbtree_each_pair(VALUE self)
578
+ {
579
+ return rbtree_for_each(self, each_pair_i, NULL);
580
+ }
581
+
582
+ static each_return_t
583
+ each_key_i(dnode_t* node, void* arg)
584
+ {
585
+ rb_yield(GET_KEY(node));
586
+ return EACH_NEXT;
587
+ }
588
+
589
+ /*
590
+ * call-seq:
591
+ * rbtree.each_key {|key| block} => rbtree
592
+ *
593
+ * Calls block once for each key in order, passing the key as
594
+ * parameters.
595
+ */
596
+ VALUE
597
+ rbtree_each_key(VALUE self)
598
+ {
599
+ return rbtree_for_each(self, each_key_i, NULL);
600
+ }
601
+
602
+ static each_return_t
603
+ each_value_i(dnode_t* node, void* arg)
604
+ {
605
+ rb_yield(GET_VAL(node));
606
+ return EACH_NEXT;
607
+ }
608
+
609
+ /*
610
+ * call-seq:
611
+ * rbtree.each_value {|value| block} => rbtree
612
+ *
613
+ * Calls block once for each key in order, passing the value as
614
+ * parameters.
615
+ */
616
+ VALUE
617
+ rbtree_each_value(VALUE self)
618
+ {
619
+ return rbtree_for_each(self, each_value_i, NULL);
620
+ }
621
+
622
+ /*
623
+ * call-seq:
624
+ * rbtree.reverse_each {|key, value| block} => rbtree
625
+ *
626
+ * Calls block once for each key in reverse order, passing the key and
627
+ * value as parameters.
628
+ */
629
+ VALUE
630
+ rbtree_reverse_each(VALUE self)
631
+ {
632
+ return rbtree_reverse_for_each(self, each_pair_i, NULL);
633
+ }
634
+
635
+ static each_return_t
636
+ aset_i(dnode_t* node, void* self)
637
+ {
638
+ rbtree_aset((VALUE)self, GET_KEY(node), GET_VAL(node));
639
+ return EACH_NEXT;
640
+ }
641
+
642
+ static void
643
+ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
644
+ {
645
+ VALUE temp = rbtree_alloc(CLASS_OF(dest));
646
+ COMPARE(temp) = cmp;
647
+ CONTEXT(temp) = context;
648
+ rbtree_for_each(src, aset_i, (void*)temp);
649
+ {
650
+ dict_t* t = DICT(temp);
651
+ DICT(temp) = DICT(dest);
652
+ DICT(dest) = t;
653
+ }
654
+ rbtree_free(RBTREE(temp));
655
+ rb_gc_force_recycle(temp);
656
+ }
657
+
658
+ /*
659
+ *
660
+ */
661
+ VALUE
662
+ rbtree_initialize_copy(VALUE self, VALUE other)
663
+ {
664
+ if (self == other)
665
+ return self;
666
+ if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
667
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
668
+ rb_class2name(CLASS_OF(other)),
669
+ rb_class2name(CLASS_OF(self)));
670
+ }
671
+
672
+ copy_dict(other, self, COMPARE(other), CONTEXT(other));
673
+
674
+ IFNONE(self) = IFNONE(other);
675
+ if (FL_TEST(other, RBTREE_PROC_DEFAULT))
676
+ FL_SET(self, RBTREE_PROC_DEFAULT);
677
+ else
678
+ FL_UNSET(self, RBTREE_PROC_DEFAULT);
679
+ return self;
680
+ }
681
+
682
+ #ifndef HAVE_RB_OBJ_INIT_COPY
683
+ /*
684
+ *
685
+ */
686
+ VALUE
687
+ rbtree_clone(VALUE self)
688
+ {
689
+ VALUE clone = rbtree_alloc(CLASS_OF(self));
690
+ rbtree_initialize_copy(clone, self);
691
+ return clone;
692
+ }
693
+ #endif
694
+
695
+ /*
696
+ *
697
+ */
698
+ VALUE
699
+ rbtree_values_at(int argc, VALUE* argv, VALUE self)
700
+ {
701
+ int i;
702
+ VALUE ary = rb_ary_new();
703
+
704
+ for (i = 0; i < argc; i++)
705
+ rb_ary_push(ary, rbtree_aref(self, argv[i]));
706
+ return ary;
707
+ }
708
+
709
+ static each_return_t
710
+ select_i(dnode_t* node, void* ary)
711
+ {
712
+ if (RTEST(rb_yield_values(2, GET_KEY(node), GET_VAL(node))))
713
+ rb_ary_push((VALUE)ary, ASSOC(node));
714
+ return EACH_NEXT;
715
+ }
716
+
717
+ /*
718
+ *
719
+ */
720
+ VALUE
721
+ rbtree_select(VALUE self)
722
+ {
723
+ VALUE ary = rb_ary_new();
724
+ rbtree_for_each(self, select_i, (void*)ary);
725
+ return ary;
726
+ }
727
+
728
+ static each_return_t
729
+ index_i(dnode_t* node, void* arg_)
730
+ {
731
+ VALUE* arg = (VALUE*)arg_;
732
+ if (rb_equal(GET_VAL(node), arg[1])) {
733
+ arg[0] = GET_KEY(node);
734
+ return EACH_STOP;
735
+ }
736
+ return EACH_NEXT;
737
+ }
738
+
739
+ /*
740
+ *
741
+ */
742
+ VALUE
743
+ rbtree_index(VALUE self, VALUE value)
744
+ {
745
+ VALUE arg[2];
746
+ arg[0] = Qnil;
747
+ arg[1] = value;
748
+ rbtree_for_each(self, index_i, (void*)&arg);
749
+ return arg[0];
750
+ }
751
+
752
+ /*
753
+ *
754
+ */
755
+ VALUE
756
+ rbtree_clear(VALUE self)
757
+ {
758
+ rbtree_modify(self);
759
+ dict_free_nodes(DICT(self));
760
+ return self;
761
+ }
762
+
763
+ /*
764
+ *
765
+ */
766
+ VALUE
767
+ rbtree_delete(VALUE self, VALUE key)
768
+ {
769
+ dict_t* dict = DICT(self);
770
+ dnode_t* node;
771
+ VALUE value;
772
+
773
+ rbtree_modify(self);
774
+ node = dict_lookup(dict, TO_KEY(key));
775
+ if (node == NULL)
776
+ return rb_block_given_p() ? rb_yield(key) : Qnil;
777
+ value = GET_VAL(node);
778
+ dict_delete_free(dict, node);
779
+ return value;
780
+ }
781
+
782
+ /*********************************************************************/
783
+
784
+ typedef struct dnode_list_t_ {
785
+ struct dnode_list_t_* prev;
786
+ dnode_t* node;
787
+ } dnode_list_t;
788
+
789
+ typedef struct {
790
+ VALUE self;
791
+ dnode_list_t* list;
792
+ int raised;
793
+ } rbtree_delete_if_arg_t;
794
+
795
+ static VALUE
796
+ rbtree_delete_if_ensure(rbtree_delete_if_arg_t* arg)
797
+ {
798
+ dict_t* dict = DICT(arg->self);
799
+ dnode_list_t* list = arg->list;
800
+
801
+ if (--ITER_LEV(arg->self) == 0) {
802
+ while (list != NULL) {
803
+ dnode_list_t* l = list;
804
+ if (!arg->raised)
805
+ dict_delete_free(dict, l->node);
806
+ list = l->prev;
807
+ xfree(l);
808
+ }
809
+ }
810
+ return Qnil;
811
+ }
812
+
813
+ static VALUE
814
+ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
815
+ {
816
+ VALUE self = arg->self;
817
+ dict_t* dict = DICT(self);
818
+ dnode_t* node;
819
+
820
+ arg->raised = 1;
821
+ ITER_LEV(self)++;
822
+ for (node = dict_first(dict);
823
+ node != NULL;
824
+ node = dict_next(dict, node)) {
825
+
826
+ if (RTEST(rb_yield_values(2, GET_KEY(node), GET_VAL(node)))) {
827
+ dnode_list_t* l = ALLOC(dnode_list_t);
828
+ l->node = node;
829
+ l->prev = arg->list;
830
+ arg->list = l;
831
+ }
832
+ }
833
+ arg->raised = 0;
834
+ return self;
835
+ }
836
+
837
+ /*********************************************************************/
838
+
839
+ /*
840
+ *
841
+ */
842
+ VALUE
843
+ rbtree_delete_if(VALUE self)
844
+ {
845
+ rbtree_delete_if_arg_t arg;
846
+
847
+ rbtree_modify(self);
848
+ arg.self = self;
849
+ arg.list = NULL;
850
+ return rb_ensure(rbtree_delete_if_body, (VALUE)&arg,
851
+ rbtree_delete_if_ensure, (VALUE)&arg);
852
+ }
853
+
854
+ /*
855
+ *
856
+ */
857
+ VALUE
858
+ rbtree_reject_bang(VALUE self)
859
+ {
860
+ const dictcount_t count = dict_count(DICT(self));
861
+ rbtree_delete_if(self);
862
+ if (count == dict_count(DICT(self)))
863
+ return Qnil;
864
+ return self;
865
+ }
866
+
867
+ /*
868
+ *
869
+ */
870
+ VALUE
871
+ rbtree_reject(VALUE self)
872
+ {
873
+ return rbtree_reject_bang(rb_obj_dup(self));
874
+ }
875
+
876
+ static VALUE
877
+ rbtree_shift_pop(VALUE self, const int mode)
878
+ {
879
+ dict_t* dict = DICT(self);
880
+ dnode_t* node;
881
+ VALUE ret;
882
+
883
+ rbtree_modify(self);
884
+
885
+ if (dict_isempty(dict)) {
886
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
887
+ return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
888
+ }
889
+ return IFNONE(self);
890
+ }
891
+
892
+ if (mode == 0)
893
+ node = dict_first(dict);
894
+ else
895
+ node = dict_last(dict);
896
+ ret = ASSOC(node);
897
+ dict_delete_free(dict, node);
898
+ return ret;
899
+ }
900
+
901
+ /*
902
+ * call-seq:
903
+ * rbtree.shift => array or object
904
+ *
905
+ * Removes the first(that is, the smallest) key-value pair and returns
906
+ * it as a two-item array.
907
+ */
908
+ VALUE
909
+ rbtree_shift(VALUE self)
910
+ {
911
+ return rbtree_shift_pop(self, 0);
912
+ }
913
+
914
+ /*
915
+ * call-seq:
916
+ * rbtree.pop => array or object
917
+ *
918
+ * Removes the last(that is, the biggest) key-value pair and returns
919
+ * it as a two-item array.
920
+ */
921
+ VALUE
922
+ rbtree_pop(VALUE self)
923
+ {
924
+ return rbtree_shift_pop(self, 1);
925
+ }
926
+
927
+ static each_return_t
928
+ invert_i(dnode_t* node, void* rbtree)
929
+ {
930
+ rbtree_aset((VALUE)rbtree, GET_VAL(node), GET_KEY(node));
931
+ return EACH_NEXT;
932
+ }
933
+
934
+ /*
935
+ *
936
+ */
937
+ VALUE
938
+ rbtree_invert(VALUE self)
939
+ {
940
+ VALUE rbtree = rbtree_alloc(CLASS_OF(self));
941
+ rbtree_for_each(self, invert_i, (void*)rbtree);
942
+ return rbtree;
943
+ }
944
+
945
+ static each_return_t
946
+ update_block_i(dnode_t* node, void* self_)
947
+ {
948
+ VALUE self = (VALUE)self_;
949
+ VALUE key = GET_KEY(node);
950
+ VALUE value = GET_VAL(node);
951
+
952
+ if (rbtree_has_key(self, key))
953
+ value = rb_yield_values(3, key, rbtree_aref(self, key), value);
954
+ rbtree_aset(self, key, value);
955
+ return EACH_NEXT;
956
+ }
957
+
958
+ /*
959
+ *
960
+ */
961
+ VALUE
962
+ rbtree_update(VALUE self, VALUE other)
963
+ {
964
+ rbtree_modify(self);
965
+
966
+ if (self == other)
967
+ return self;
968
+ if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
969
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
970
+ rb_class2name(CLASS_OF(other)),
971
+ rb_class2name(CLASS_OF(self)));
972
+ }
973
+
974
+ if (rb_block_given_p())
975
+ rbtree_for_each(other, update_block_i, (void*)self);
976
+ else
977
+ rbtree_for_each(other, aset_i, (void*)self);
978
+ return self;
979
+ }
980
+
981
+ /*
982
+ *
983
+ */
984
+ VALUE
985
+ rbtree_merge(VALUE self, VALUE other)
986
+ {
987
+ return rbtree_update(rb_obj_dup(self), other);
988
+ }
989
+
990
+ /*
991
+ *
992
+ */
993
+ VALUE
994
+ rbtree_has_key(VALUE self, VALUE key)
995
+ {
996
+ return dict_lookup(DICT(self), TO_KEY(key)) == NULL ? Qfalse : Qtrue;
997
+ }
998
+
999
+ static each_return_t
1000
+ has_value_i(dnode_t* node, void* arg_)
1001
+ {
1002
+ VALUE* arg = (VALUE*)arg_;
1003
+ if (rb_equal(GET_VAL(node), arg[1])) {
1004
+ arg[0] = Qtrue;
1005
+ return EACH_STOP;
1006
+ }
1007
+ return EACH_NEXT;
1008
+ }
1009
+
1010
+ /*
1011
+ *
1012
+ */
1013
+ VALUE
1014
+ rbtree_has_value(VALUE self, VALUE value)
1015
+ {
1016
+ VALUE arg[2];
1017
+ arg[0] = Qfalse;
1018
+ arg[1] = value;
1019
+ rbtree_for_each(self, has_value_i, (void*)&arg);
1020
+ return arg[0];
1021
+ }
1022
+
1023
+ static each_return_t
1024
+ keys_i(dnode_t* node, void* ary)
1025
+ {
1026
+ rb_ary_push((VALUE)ary, GET_KEY(node));
1027
+ return EACH_NEXT;
1028
+ }
1029
+
1030
+ /*
1031
+ *
1032
+ */
1033
+ VALUE
1034
+ rbtree_keys(VALUE self)
1035
+ {
1036
+ VALUE ary = rb_ary_new();
1037
+ rbtree_for_each(self, keys_i, (void*)ary);
1038
+ return ary;
1039
+ }
1040
+
1041
+ static each_return_t
1042
+ values_i(dnode_t* node, void* ary)
1043
+ {
1044
+ rb_ary_push((VALUE)ary, GET_VAL(node));
1045
+ return EACH_NEXT;
1046
+ }
1047
+
1048
+ /*
1049
+ *
1050
+ */
1051
+ VALUE
1052
+ rbtree_values(VALUE self)
1053
+ {
1054
+ VALUE ret = rb_ary_new();
1055
+ rbtree_for_each(self, values_i, (void*)ret);
1056
+ return ret;
1057
+ }
1058
+
1059
+ static each_return_t
1060
+ to_a_i(dnode_t* node, void* ary)
1061
+ {
1062
+ rb_ary_push((VALUE)ary, ASSOC(node));
1063
+ return EACH_NEXT;
1064
+ }
1065
+
1066
+ /*
1067
+ *
1068
+ */
1069
+ VALUE
1070
+ rbtree_to_a(VALUE self)
1071
+ {
1072
+ VALUE ary = rb_ary_new();
1073
+ rbtree_for_each(self, to_a_i, (void*)ary);
1074
+ OBJ_INFECT(ary, self);
1075
+ return ary;
1076
+ }
1077
+
1078
+ static each_return_t
1079
+ to_hash_i(dnode_t* node, void* hash)
1080
+ {
1081
+ st_insert(RHASH(hash)->tbl, GET_KEY(node), GET_VAL(node));
1082
+ return EACH_NEXT;
1083
+ }
1084
+
1085
+ /*
1086
+ *
1087
+ */
1088
+ VALUE
1089
+ rbtree_to_hash(VALUE self)
1090
+ {
1091
+ VALUE hash = rb_hash_new();
1092
+ rbtree_for_each(self, to_hash_i, (void*)hash);
1093
+ RHASH(hash)->ifnone = IFNONE(self);
1094
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1095
+ FL_SET(hash, HASH_PROC_DEFAULT);
1096
+ OBJ_INFECT(hash, self);
1097
+ return hash;
1098
+ }
1099
+
1100
+ /*
1101
+ *
1102
+ */
1103
+ VALUE
1104
+ rbtree_to_rbtree(VALUE self)
1105
+ {
1106
+ return self;
1107
+ }
1108
+
1109
+ static VALUE
1110
+ rbtree_begin_inspect(VALUE self)
1111
+ {
1112
+ const char* c = rb_class2name(CLASS_OF(self));
1113
+ VALUE str = rb_str_new(0, strlen(c) + 5);
1114
+ const size_t len = sprintf(RSTRING(str)->ptr, "#<%s: ", c);
1115
+ RSTRING(str)->len = len;
1116
+ return str;
1117
+ }
1118
+
1119
+ static VALUE
1120
+ to_s_rbtree(VALUE self, VALUE nil)
1121
+ {
1122
+ return rb_ary_to_s(rbtree_to_a(self));
1123
+ }
1124
+
1125
+ /*
1126
+ *
1127
+ */
1128
+ VALUE
1129
+ rbtree_to_s(VALUE self)
1130
+ {
1131
+ if (rb_inspecting_p(self))
1132
+ return rb_str_cat2(rbtree_begin_inspect(self), "...>");
1133
+ return rb_protect_inspect(to_s_rbtree, self, Qnil);
1134
+ }
1135
+
1136
+ static each_return_t
1137
+ inspect_i(dnode_t* node, void* ret_)
1138
+ {
1139
+ VALUE ret = (VALUE)ret_;
1140
+ VALUE str;
1141
+
1142
+ if (RSTRING(ret)->ptr[0] == '-')
1143
+ RSTRING(ret)->ptr[0] = '#';
1144
+ else
1145
+ rb_str_cat2(ret, ", ");
1146
+
1147
+ str = rb_inspect(GET_KEY(node));
1148
+ rb_str_append(ret, str);
1149
+ OBJ_INFECT(ret, str);
1150
+
1151
+ rb_str_cat2(ret, "=>");
1152
+
1153
+ str = rb_inspect(GET_VAL(node));
1154
+ rb_str_append(ret, str);
1155
+ OBJ_INFECT(ret, str);
1156
+
1157
+ return EACH_NEXT;
1158
+ }
1159
+
1160
+ static VALUE
1161
+ inspect_rbtree(VALUE self, VALUE ret)
1162
+ {
1163
+ VALUE str;
1164
+
1165
+ rb_str_cat2(ret, "{");
1166
+ RSTRING(ret)->ptr[0] = '-';
1167
+ rbtree_for_each(self, inspect_i, (void*)ret);
1168
+ RSTRING(ret)->ptr[0] = '#';
1169
+ rb_str_cat2(ret, "}");
1170
+
1171
+ str = rb_inspect(IFNONE(self));
1172
+ rb_str_cat2(ret, ", default=");
1173
+ rb_str_append(ret, str);
1174
+ OBJ_INFECT(ret, str);
1175
+
1176
+ str = rb_inspect((VALUE)CONTEXT(self));
1177
+ rb_str_cat2(ret, ", cmp_proc=");
1178
+ rb_str_append(ret, str);
1179
+ OBJ_INFECT(ret, str);
1180
+
1181
+ rb_str_cat2(ret, ">");
1182
+ OBJ_INFECT(ret, self);
1183
+ return ret;
1184
+ }
1185
+
1186
+ /*
1187
+ *
1188
+ */
1189
+ VALUE
1190
+ rbtree_inspect(VALUE self)
1191
+ {
1192
+ VALUE str = rbtree_begin_inspect(self);
1193
+ if (rb_inspecting_p(self))
1194
+ return rb_str_cat2(str, "...>");
1195
+ return rb_protect_inspect(inspect_rbtree, self, str);
1196
+ }
1197
+
1198
+ /*
1199
+ * call-seq:
1200
+ * rbtree.lower_bound(key) => array
1201
+ *
1202
+ * Retruns key-value pair corresponding to the lowest key that is
1203
+ * equal to or greater than the given key(inside of lower
1204
+ * boundary). If there is no such key, returns nil.
1205
+ */
1206
+ VALUE
1207
+ rbtree_lower_bound(VALUE self, VALUE key)
1208
+ {
1209
+ dnode_t* node = dict_lower_bound(DICT(self), TO_KEY(key));
1210
+ if (node == NULL)
1211
+ return Qnil;
1212
+ return ASSOC(node);
1213
+ }
1214
+
1215
+ /*
1216
+ * call-seq:
1217
+ * rbtree.upper_bound(key) => array
1218
+ *
1219
+ * Retruns key-value pair corresponding to the greatest key that is
1220
+ * equal to or lower than the given key(inside of upper boundary). If
1221
+ * there is no such key, returns nil.
1222
+ */
1223
+ VALUE
1224
+ rbtree_upper_bound(VALUE self, VALUE key)
1225
+ {
1226
+ dnode_t* node = dict_upper_bound(DICT(self), TO_KEY(key));
1227
+ if (node == NULL)
1228
+ return Qnil;
1229
+ return ASSOC(node);
1230
+ }
1231
+
1232
+ /*********************************************************************/
1233
+
1234
+ typedef struct {
1235
+ VALUE self;
1236
+ dnode_t* lower_node;
1237
+ dnode_t* upper_node;
1238
+ VALUE ret;
1239
+ } rbtree_bound_arg_t;
1240
+
1241
+ static VALUE
1242
+ rbtree_bound_body(rbtree_bound_arg_t* arg)
1243
+ {
1244
+ VALUE self = arg->self;
1245
+ dict_t* dict = DICT(self);
1246
+ dnode_t* lower_node = arg->lower_node;
1247
+ dnode_t* upper_node = arg->upper_node;
1248
+ const int block_given = rb_block_given_p();
1249
+ VALUE ret = arg->ret;
1250
+ dnode_t* node;
1251
+
1252
+ ITER_LEV(self)++;
1253
+ for (node = lower_node;;
1254
+ node = dict_next(dict, node)) {
1255
+
1256
+ if (block_given)
1257
+ rb_yield_values(2, GET_KEY(node), GET_VAL(node));
1258
+ else
1259
+ rb_ary_push(ret, ASSOC(node));
1260
+ if (node == upper_node)
1261
+ break;
1262
+ }
1263
+ return ret;
1264
+ }
1265
+
1266
+ /*********************************************************************/
1267
+
1268
+ /*
1269
+ * call-seq:
1270
+ * rbtree.bound(key1, key2 = key1) => array
1271
+ * rbtree.bound(key1, key2 = key1) {|key, value| block} => rbtree
1272
+ *
1273
+ * Returns an array containing key-value pairs between the result of
1274
+ * MultiRBTree#lower_bound and MultiRBTree#upper_bound. If a block is
1275
+ * given it calls the block once for each pair.
1276
+ */
1277
+ VALUE
1278
+ rbtree_bound(int argc, VALUE* argv, VALUE self)
1279
+ {
1280
+ dict_t* dict = DICT(self);
1281
+ dnode_t* lower_node;
1282
+ dnode_t* upper_node;
1283
+ VALUE ret;
1284
+
1285
+ if (argc == 0 || argc > 2)
1286
+ rbtree_argc_error();
1287
+
1288
+ lower_node = dict_lower_bound(dict, TO_KEY(argv[0]));
1289
+ upper_node = dict_upper_bound(dict, TO_KEY(argv[argc - 1]));
1290
+ ret = rb_block_given_p() ? self : rb_ary_new();
1291
+
1292
+ if (lower_node == NULL || upper_node == NULL ||
1293
+ COMPARE(self)(dnode_getkey(lower_node),
1294
+ dnode_getkey(upper_node),
1295
+ CONTEXT(self)) > 0) {
1296
+ return ret;
1297
+ } else {
1298
+ rbtree_bound_arg_t arg;
1299
+ arg.self = self;
1300
+ arg.lower_node = lower_node;
1301
+ arg.upper_node = upper_node;
1302
+ arg.ret = ret;
1303
+
1304
+ return rb_ensure(rbtree_bound_body, (VALUE)&arg,
1305
+ rbtree_each_ensure, self);
1306
+ }
1307
+ }
1308
+
1309
+ static VALUE
1310
+ rbtree_first_last(VALUE self, const int mode)
1311
+ {
1312
+ dict_t* dict = DICT(self);
1313
+ dnode_t* node;
1314
+
1315
+ if (dict_isempty(dict)) {
1316
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
1317
+ return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
1318
+ }
1319
+ return IFNONE(self);
1320
+ }
1321
+
1322
+ if (mode == 0)
1323
+ node = dict_first(dict);
1324
+ else
1325
+ node = dict_last(dict);
1326
+ return ASSOC(node);
1327
+ }
1328
+
1329
+ /*
1330
+ * call-seq:
1331
+ * rbtree.first => array or object
1332
+ *
1333
+ * Returns the first(that is, the smallest) key-value pair.
1334
+ */
1335
+ VALUE
1336
+ rbtree_first(VALUE self)
1337
+ {
1338
+ return rbtree_first_last(self, 0);
1339
+ }
1340
+
1341
+ /*
1342
+ * call-seq:
1343
+ * rbtree.last => array of object
1344
+ *
1345
+ * Returns the last(that is, the biggest) key-value pair.
1346
+ */
1347
+ VALUE
1348
+ rbtree_last(VALUE self)
1349
+ {
1350
+ return rbtree_first_last(self, 1);
1351
+ }
1352
+
1353
+ /*
1354
+ * call-seq:
1355
+ * rbtree.readjust => rbtree
1356
+ * rbtree.readjust(nil) => rbtree
1357
+ * rbtree.readjust(proc) => rbtree
1358
+ * rbtree.readjust {|key1, key2| block} => rbtree
1359
+ *
1360
+ * Sets a proc to compare keys and readjusts elements using the given
1361
+ * block or a Proc object given as the argument. The block takes two
1362
+ * key arguments and returns negative, 0, or positive depending on the
1363
+ * first argument is less than, equal to, or greater than the second
1364
+ * one. If no block is given it just readjusts elements using current
1365
+ * comparison block. If nil is given as the argument it sets default
1366
+ * comparison block.
1367
+ */
1368
+ VALUE
1369
+ rbtree_readjust(int argc, VALUE* argv, VALUE self)
1370
+ {
1371
+ dict_comp_t cmp = NULL;
1372
+ void* context = NULL;
1373
+
1374
+ rbtree_modify(self);
1375
+
1376
+ if (argc == 0) {
1377
+ if (rb_block_given_p()) {
1378
+ cmp = rbtree_user_cmp;
1379
+ context = (void*)rb_block_proc();
1380
+ } else {
1381
+ cmp = COMPARE(self);
1382
+ context = CONTEXT(self);
1383
+ }
1384
+ } else if (argc == 1 && !rb_block_given_p()) {
1385
+ if (argv[0] == Qnil) {
1386
+ cmp = rbtree_cmp;
1387
+ context = (void*)Qnil;
1388
+ } else {
1389
+ if (CLASS_OF(argv[0]) != rb_cProc)
1390
+ rb_raise(rb_eTypeError,
1391
+ "wrong argument type %s (expected Proc)",
1392
+ rb_class2name(CLASS_OF(argv[0])));
1393
+ cmp = rbtree_user_cmp;
1394
+ context = (void*)argv[0];
1395
+ }
1396
+ } else {
1397
+ rbtree_argc_error();
1398
+ }
1399
+
1400
+ if (dict_isempty(DICT(self))) {
1401
+ COMPARE(self) = cmp;
1402
+ CONTEXT(self) = context;
1403
+ return self;
1404
+ }
1405
+ copy_dict(self, self, cmp, context);
1406
+ return self;
1407
+ }
1408
+
1409
+ /*
1410
+ * call-seq:
1411
+ * rbtree.cmp_proc => proc
1412
+ *
1413
+ * Returns the comparison block that is given by MultiRBTree#readjust.
1414
+ */
1415
+ VALUE
1416
+ rbtree_cmp_proc(VALUE self)
1417
+ {
1418
+ return (VALUE)(CONTEXT(self));
1419
+ }
1420
+
1421
+ /*********************************************************************/
1422
+
1423
+ static ID id_comma_breakable;
1424
+ static ID id_object_group;
1425
+ static ID id_pp;
1426
+ static ID id_pp_hash;
1427
+ static ID id_text;
1428
+
1429
+ typedef struct {
1430
+ VALUE rbtree;
1431
+ VALUE pp;
1432
+ } pp_arg_t;
1433
+
1434
+ static VALUE
1435
+ pp_object_group(VALUE arg_)
1436
+ {
1437
+ pp_arg_t* arg = (pp_arg_t*)arg_;
1438
+ return rb_funcall(arg->pp, id_object_group, 1, arg->rbtree);
1439
+ }
1440
+
1441
+ static VALUE
1442
+ pp_block(VALUE nil, pp_arg_t* arg)
1443
+ {
1444
+ VALUE pp = arg->pp;
1445
+ VALUE rbtree = arg->rbtree;
1446
+
1447
+ rb_funcall(pp, id_text, 1, rb_str_new2(": "));
1448
+ rb_funcall(pp, id_pp_hash, 1, rbtree);
1449
+ rb_funcall(pp, id_comma_breakable, 0);
1450
+ rb_funcall(pp, id_text, 1, rb_str_new2("default="));
1451
+ rb_funcall(pp, id_pp, 1, IFNONE(rbtree));
1452
+ rb_funcall(pp, id_comma_breakable, 0);
1453
+ rb_funcall(pp, id_text, 1, rb_str_new2("cmp_proc="));
1454
+ rb_funcall(pp, id_pp, 1, CONTEXT(rbtree));
1455
+ return pp;
1456
+ }
1457
+
1458
+ /*********************************************************************/
1459
+
1460
+ /*
1461
+ * Called by pretty printing function pp.
1462
+ */
1463
+ VALUE
1464
+ rbtree_pretty_print(VALUE self, VALUE pp)
1465
+ {
1466
+ pp_arg_t pp_arg;
1467
+ pp_arg.rbtree = self;
1468
+ pp_arg.pp = pp;
1469
+
1470
+ return rb_iterate(pp_object_group, (VALUE)&pp_arg,
1471
+ pp_block, (VALUE)&pp_arg);
1472
+ }
1473
+
1474
+ /*
1475
+ * Called by pretty printing function pp.
1476
+ */
1477
+ VALUE
1478
+ rbtree_pretty_print_cycle(VALUE self, VALUE pp)
1479
+ {
1480
+ return rb_funcall(pp, id_pp, 1, rbtree_inspect(self));
1481
+ }
1482
+
1483
+ /*********************************************************************/
1484
+
1485
+ #ifndef HAVE_RB_MARSHAL_DUMP
1486
+ static VALUE
1487
+ rb_marshal_dump(VALUE obj, VALUE port)
1488
+ {
1489
+ return rb_funcall(rb_mMarshal, id_dump, 2, obj, port);
1490
+ }
1491
+
1492
+ static VALUE
1493
+ rb_marshal_load(VALUE port)
1494
+ {
1495
+ return rb_funcall(rb_mMarshal, id_load, 1, port);
1496
+ }
1497
+ #endif
1498
+
1499
+ static each_return_t
1500
+ to_flatten_ary_i(dnode_t* node, void* ary)
1501
+ {
1502
+ rb_ary_push((VALUE)ary, GET_KEY(node));
1503
+ rb_ary_push((VALUE)ary, GET_VAL(node));
1504
+ return EACH_NEXT;
1505
+ }
1506
+
1507
+ /*********************************************************************/
1508
+
1509
+ /*
1510
+ * Called by Marshal.dump.
1511
+ */
1512
+ VALUE
1513
+ rbtree_dump(VALUE self, VALUE limit)
1514
+ {
1515
+ VALUE ary;
1516
+ VALUE ret;
1517
+
1518
+ if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1519
+ rb_raise(rb_eTypeError, "cannot dump rbtree with default proc");
1520
+ if ((VALUE)CONTEXT(self) != Qnil)
1521
+ rb_raise(rb_eTypeError, "cannot dump rbtree with compare proc");
1522
+
1523
+ ary = rb_ary_new2(dict_count(DICT(self)) * 2 + 1);
1524
+ rbtree_for_each(self, to_flatten_ary_i, (void*)ary);
1525
+ rb_ary_push(ary, IFNONE(self));
1526
+
1527
+ ret = rb_marshal_dump(ary, limit);
1528
+ rb_ary_clear(ary);
1529
+ rb_gc_force_recycle(ary);
1530
+ return ret;
1531
+ }
1532
+
1533
+ /*
1534
+ * Called by Marshal.load.
1535
+ */
1536
+ VALUE
1537
+ rbtree_s_load(VALUE klass, VALUE str)
1538
+ {
1539
+ VALUE rbtree = rbtree_alloc(klass);
1540
+ VALUE ary = rb_marshal_load(str);
1541
+ VALUE* ptr = RARRAY(ary)->ptr;
1542
+ long len = RARRAY(ary)->len - 1;
1543
+ long i;
1544
+
1545
+ for (i = 0; i < len; i += 2)
1546
+ rbtree_aset(rbtree, ptr[i], ptr[i + 1]);
1547
+ IFNONE(rbtree) = ptr[len];
1548
+
1549
+ rb_ary_clear(ary);
1550
+ rb_gc_force_recycle(ary);
1551
+ return rbtree;
1552
+ }
1553
+
1554
+ /*********************************************************************/
1555
+
1556
+ /*
1557
+ * RBTree is a sorted associative collection using Red-Black Tree as
1558
+ * the internal data structure. The elements of RBTree are ordered and
1559
+ * the interface is the almost same as Hash, so simply you can
1560
+ * consider RBTree sorted Hash.
1561
+ *
1562
+ * Red-Black Tree is a kind of binary tree that automatically balances
1563
+ * by itself when a node is inserted or deleted. Thus the complexity
1564
+ * for insert, search and delete is O(log N) in expected and worst
1565
+ * case. On the other hand the complexity of Hash is O(1). Because
1566
+ * Hash is unordered the data structure is more effective than
1567
+ * Red-Black Tree as an associative collection.
1568
+ *
1569
+ * The interface of RBTree is the almost same as Hash although there
1570
+ * are some limitations.
1571
+ *
1572
+ * * While iterating (e.g. in RBTree#each block), RBTree is
1573
+ * unmodifiable.
1574
+ *
1575
+ * * Comparison is done using <=> method of key objects. So all types
1576
+ * of keys in RBTree should be comparable each other or an arbitrary
1577
+ * Proc might be set by RBTree#readjust.
1578
+ *
1579
+ * RBTree has a few searching methods that Hash doesn't have. They are
1580
+ * RBTree#lower_bound, RBTree#upper_bound and RBTree#bound. See
1581
+ * document of each method for details.
1582
+ *
1583
+ * Pretty printing is available for RBTree by using pp.rb. The output
1584
+ * of pp is easier than p to read. Just call Kernel#pp for the object.
1585
+ *
1586
+ * MultiRBTree that allows duplicates of keys is also available.
1587
+ */
1588
+ void Init_rbtree()
1589
+ {
1590
+ MultiRBTree = rb_define_class("MultiRBTree", rb_cData);
1591
+ RBTree = rb_define_class("RBTree", MultiRBTree);
1592
+
1593
+ rb_include_module(MultiRBTree, rb_mEnumerable);
1594
+
1595
+ #ifdef HAVE_OBJECT_ALLOCATE
1596
+ rb_define_alloc_func(MultiRBTree, rbtree_alloc);
1597
+ #else
1598
+ rb_define_singleton_method(MultiRBTree, "new", rbtree_s_new, -1);
1599
+ #endif
1600
+ rb_define_singleton_method(MultiRBTree, "[]", rbtree_s_create, -1);
1601
+
1602
+ rb_define_method(MultiRBTree, "initialize", rbtree_initialize, -1);
1603
+
1604
+ #ifdef HAVE_RB_OBJ_INIT_COPY
1605
+ rb_define_method(MultiRBTree, "initialize_copy", rbtree_initialize_copy, 1);
1606
+ #else
1607
+ rb_define_method(MultiRBTree, "clone", rbtree_clone, 0);
1608
+ #endif
1609
+
1610
+ rb_define_method(MultiRBTree, "to_a", rbtree_to_a, 0);
1611
+ rb_define_method(MultiRBTree, "to_s", rbtree_to_s, 0);
1612
+ rb_define_method(MultiRBTree, "to_hash", rbtree_to_hash, 0);
1613
+ rb_define_method(MultiRBTree, "to_rbtree", rbtree_to_rbtree, 0);
1614
+ rb_define_method(MultiRBTree, "inspect", rbtree_inspect, 0);
1615
+
1616
+ rb_define_method(MultiRBTree, "==", rbtree_equal, 1);
1617
+ rb_define_method(MultiRBTree, "[]", rbtree_aref, 1);
1618
+ rb_define_method(MultiRBTree, "fetch", rbtree_fetch, -1);
1619
+ rb_define_method(MultiRBTree, "lower_bound", rbtree_lower_bound, 1);
1620
+ rb_define_method(MultiRBTree, "upper_bound", rbtree_upper_bound, 1);
1621
+ rb_define_method(MultiRBTree, "bound", rbtree_bound, -1);
1622
+ rb_define_method(MultiRBTree, "first", rbtree_first, 0);
1623
+ rb_define_method(MultiRBTree, "last", rbtree_last, 0);
1624
+ rb_define_method(MultiRBTree, "[]=", rbtree_aset, 2);
1625
+ rb_define_method(MultiRBTree, "store", rbtree_aset, 2);
1626
+ rb_define_method(MultiRBTree, "default", rbtree_default, -1);
1627
+ rb_define_method(MultiRBTree, "default=", rbtree_set_default, 1);
1628
+ rb_define_method(MultiRBTree, "default_proc", rbtree_default_proc, 0);
1629
+ rb_define_method(MultiRBTree, "index", rbtree_index, 1);
1630
+ rb_define_method(MultiRBTree, "empty?", rbtree_empty_p, 0);
1631
+ rb_define_method(MultiRBTree, "size", rbtree_size, 0);
1632
+ rb_define_method(MultiRBTree, "length", rbtree_size, 0);
1633
+
1634
+ rb_define_method(MultiRBTree, "each", rbtree_each, 0);
1635
+ rb_define_method(MultiRBTree, "each_value", rbtree_each_value, 0);
1636
+ rb_define_method(MultiRBTree, "each_key", rbtree_each_key, 0);
1637
+ rb_define_method(MultiRBTree, "each_pair", rbtree_each_pair, 0);
1638
+ rb_define_method(MultiRBTree, "reverse_each", rbtree_reverse_each, 0);
1639
+
1640
+ rb_define_method(MultiRBTree, "keys", rbtree_keys, 0);
1641
+ rb_define_method(MultiRBTree, "values", rbtree_values, 0);
1642
+ rb_define_method(MultiRBTree, "values_at", rbtree_values_at, -1);
1643
+
1644
+ rb_define_method(MultiRBTree, "shift", rbtree_shift, 0);
1645
+ rb_define_method(MultiRBTree, "pop", rbtree_pop, 0);
1646
+ rb_define_method(MultiRBTree, "delete", rbtree_delete, 1);
1647
+ rb_define_method(MultiRBTree, "delete_if", rbtree_delete_if, 0);
1648
+ rb_define_method(MultiRBTree, "select", rbtree_select, 0);
1649
+ rb_define_method(MultiRBTree, "reject", rbtree_reject, 0);
1650
+ rb_define_method(MultiRBTree, "reject!", rbtree_reject_bang, 0);
1651
+ rb_define_method(MultiRBTree, "clear", rbtree_clear, 0);
1652
+ rb_define_method(MultiRBTree, "invert", rbtree_invert, 0);
1653
+ rb_define_method(MultiRBTree, "update", rbtree_update, 1);
1654
+ rb_define_method(MultiRBTree, "merge!", rbtree_update, 1);
1655
+ rb_define_method(MultiRBTree, "merge", rbtree_merge, 1);
1656
+ rb_define_method(MultiRBTree, "replace", rbtree_initialize_copy, 1);
1657
+
1658
+ rb_define_method(MultiRBTree, "include?", rbtree_has_key, 1);
1659
+ rb_define_method(MultiRBTree, "member?", rbtree_has_key, 1);
1660
+ rb_define_method(MultiRBTree, "has_key?", rbtree_has_key, 1);
1661
+ rb_define_method(MultiRBTree, "has_value?", rbtree_has_value, 1);
1662
+ rb_define_method(MultiRBTree, "key?", rbtree_has_key, 1);
1663
+ rb_define_method(MultiRBTree, "value?", rbtree_has_value, 1);
1664
+
1665
+ rb_define_method(MultiRBTree, "readjust", rbtree_readjust, -1);
1666
+ rb_define_method(MultiRBTree, "cmp_proc", rbtree_cmp_proc, 0);
1667
+
1668
+ rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
1669
+ rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
1670
+ #ifndef HAVE_RB_MARSHAL_DUMP
1671
+ rb_mMarshal = rb_path2class("Marshal");
1672
+ id_dump = rb_intern("dump");
1673
+ id_load = rb_intern("load");
1674
+ #endif
1675
+
1676
+ id_bound = rb_intern("bound");
1677
+ id_cmp = rb_intern("<=>");
1678
+ id_call = rb_intern("call");
1679
+ id_default = rb_intern("default");
1680
+
1681
+
1682
+ rb_define_method(MultiRBTree, "pretty_print", rbtree_pretty_print, 1);
1683
+ rb_define_method(MultiRBTree,
1684
+ "pretty_print_cycle", rbtree_pretty_print_cycle, 1);
1685
+
1686
+ id_comma_breakable = rb_intern("comma_breakable");
1687
+ id_object_group = rb_intern("object_group");
1688
+ id_pp_hash = rb_intern("pp_hash");
1689
+ id_text = rb_intern("text");
1690
+ id_pp = rb_intern("pp");
1691
+ }