rbtree 0.3.0 → 0.4.0

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