rbtree 0.3.0 → 0.4.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. 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
  }