rbtree 0.3.0 → 0.4.4

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