rbtree 0.2.1 → 0.4.3

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 +36 -72
  5. data/dict.c +364 -83
  6. data/dict.h +30 -6
  7. data/extconf.rb +11 -5
  8. data/rbtree.c +796 -470
  9. data/test.rb +313 -157
  10. metadata +42 -45
  11. data/ChangeLog +0 -483
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,11 +1,17 @@
1
1
  require 'mkmf'
2
2
 
3
- if $DEBUG
4
- $CFLAGS << ' -std=c89 -pedantic -Wall -Wno-long-long'
5
- $defs << ' -Dinline=__inline'
3
+ if enable_config('debug')
4
+ $CFLAGS << ' -g -std=c99 -pedantic -Wall'
6
5
  else
7
6
  $defs << '-DNDEBUG'
8
7
  end
9
-
10
- have_func('rb_enumeratorize')
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
11
17
  create_makefile('rbtree')
data/rbtree.c CHANGED
@@ -1,40 +1,56 @@
1
1
  /*
2
2
  * MIT License
3
- * Copyright (c) 2002-2004, 2007, 2009 OZAWA Takuma
3
+ * Copyright (c) 2002-2013 OZAWA Takuma
4
4
  */
5
5
  #include <ruby.h>
6
- #include <version.h>
6
+ #ifdef HAVE_RUBY_ST_H
7
+ #include <ruby/st.h>
8
+ #else
7
9
  #include <st.h>
8
- #include <stdarg.h>
10
+ #endif
9
11
  #include "dict.h"
10
12
 
11
13
  #define RBTREE_PROC_DEFAULT FL_USER2
12
14
  #define HASH_PROC_DEFAULT FL_USER2
13
15
 
14
- #ifndef HAVE_RB_ENUMERATORIZE
15
- #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
24
+ #endif
25
+
26
+ #ifndef RARRAY_AREF
27
+ #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
28
+ #endif
29
+
30
+ #ifndef RHASH_SET_IFNONE
31
+ #define RHASH_SET_IFNONE(h, v) (RHASH(h)->ifnone = (v))
16
32
  #endif
17
33
 
18
34
  VALUE RBTree;
19
35
  VALUE MultiRBTree;
20
36
 
21
- static ID id_bound;
22
37
  static ID id_cmp;
23
38
  static ID id_call;
24
39
  static ID id_default;
40
+ static ID id_flatten_bang;
25
41
 
26
42
  typedef struct {
27
43
  dict_t* dict;
28
44
  VALUE ifnone;
45
+ VALUE cmp_proc;
29
46
  int iter_lev;
30
47
  } rbtree_t;
31
48
 
32
49
  #define RBTREE(rbtree) DATA_PTR(rbtree)
33
50
  #define DICT(rbtree) ((rbtree_t*)RBTREE(rbtree))->dict
34
51
  #define IFNONE(rbtree) ((rbtree_t*)RBTREE(rbtree))->ifnone
52
+ #define CMP_PROC(rbtree) ((rbtree_t*)RBTREE(rbtree))->cmp_proc
35
53
  #define ITER_LEV(rbtree) ((rbtree_t*)RBTREE(rbtree))->iter_lev
36
- #define COMPARE(rbtree) DICT(rbtree)->dict_compare
37
- #define CONTEXT(rbtree) DICT(rbtree)->dict_context
38
54
 
39
55
  #define TO_KEY(arg) ((const void*)arg)
40
56
  #define TO_VAL(arg) ((void*)arg)
@@ -44,17 +60,11 @@ typedef struct {
44
60
 
45
61
  /*********************************************************************/
46
62
 
47
- static int
48
- cmpint(VALUE i, VALUE a, VALUE b)
49
- {
50
- return rb_cmpint(i, a, b);
51
- }
52
-
53
63
  static void
54
64
  rbtree_free(rbtree_t* rbtree)
55
65
  {
56
66
  dict_free_nodes(rbtree->dict);
57
- dict_destroy(rbtree->dict);
67
+ xfree(rbtree->dict);
58
68
  xfree(rbtree);
59
69
  }
60
70
 
@@ -73,9 +83,9 @@ rbtree_mark(rbtree_t* rbtree)
73
83
  rb_gc_mark(GET_KEY(node));
74
84
  rb_gc_mark(GET_VAL(node));
75
85
  }
76
- rb_gc_mark((VALUE)dict->dict_context);
77
86
  }
78
87
  rb_gc_mark(rbtree->ifnone);
88
+ rb_gc_mark(rbtree->cmp_proc);
79
89
  }
80
90
 
81
91
  static dnode_t*
@@ -91,63 +101,112 @@ rbtree_free_node(dnode_t* node, void* context)
91
101
  }
92
102
 
93
103
  static void
94
- rbtree_argc_error()
95
- {
96
- 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
97
131
  }
98
132
 
99
133
  static int
100
134
  rbtree_cmp(const void* key1, const void* key2, void* context)
101
135
  {
102
- VALUE ret;
136
+ VALUE result;
103
137
  if (TYPE(key1) == T_STRING && TYPE(key2) == T_STRING)
104
138
  return rb_str_cmp((VALUE)key1, (VALUE)key2);
105
- ret = rb_funcall((VALUE)key1, id_cmp, 1, (VALUE)key2);
106
- 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);
107
156
  }
108
157
 
109
158
  static int
110
- rbtree_user_cmp(const void* key1, const void* key2, void* cmp_proc)
159
+ rbtree_user_cmp(const void* key1, const void* key2, void* context)
111
160
  {
112
- VALUE ret = rb_funcall((VALUE)cmp_proc, id_call, 2,
113
- (VALUE)key1, (VALUE)key2);
114
- 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);
115
171
  }
116
172
 
117
173
  static void
118
174
  rbtree_modify(VALUE self)
119
175
  {
120
176
  if (ITER_LEV(self) > 0)
121
- rb_raise(rb_eTypeError, "can't modify rbtree in iteration");
122
- if (OBJ_FROZEN(self))
123
- rb_error_frozen("rbtree");
177
+ rb_raise(rb_eTypeError, "can't modify rbtree during iteration");
178
+ rb_check_frozen(self);
179
+ #ifdef HAVE_RB_SAFE_LEVEL
124
180
  if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
125
181
  rb_raise(rb_eSecurityError, "Insecure: can't modify rbtree");
182
+ #endif
126
183
  }
127
184
 
128
185
  static VALUE
129
186
  rbtree_alloc(VALUE klass)
130
187
  {
131
188
  dict_t* dict;
132
- VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, 0);
189
+ VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, NULL);
133
190
  RBTREE(rbtree) = ALLOC(rbtree_t);
134
191
  MEMZERO(RBTREE(rbtree), rbtree_t, 1);
135
192
 
136
- dict = dict_create(rbtree_cmp);
193
+ dict = ALLOC(dict_t);
194
+ dict_init(dict, rbtree_cmp);
137
195
  dict_set_allocator(dict, rbtree_alloc_node, rbtree_free_node,
138
- (void*)Qnil);
139
- if (klass == MultiRBTree)
196
+ RBTREE(rbtree));
197
+ if (!RTEST(rb_class_inherited_p(klass, RBTree)))
140
198
  dict_allow_dupes(dict);
141
-
199
+
142
200
  DICT(rbtree) = dict;
143
201
  IFNONE(rbtree) = Qnil;
202
+ CMP_PROC(rbtree) = Qnil;
144
203
  return rbtree;
145
204
  }
146
205
 
147
206
  VALUE rbtree_aset(VALUE, VALUE, VALUE);
148
- VALUE rbtree_clear(VALUE);
149
207
  VALUE rbtree_has_key(VALUE, VALUE);
150
208
  VALUE rbtree_update(VALUE, VALUE);
209
+ VALUE rbtree_to_a(VALUE);
151
210
 
152
211
  /*********************************************************************/
153
212
 
@@ -167,52 +226,57 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
167
226
  {
168
227
  long i;
169
228
  VALUE rbtree;
170
-
229
+
171
230
  if (argc == 1) {
172
- VALUE tmp;
173
-
174
- if (klass == RBTree && CLASS_OF(argv[0]) == MultiRBTree) {
175
- rb_raise(rb_eTypeError, "can't convert MultiRBTree to RBTree");
176
- }
177
-
231
+ VALUE temp;
232
+
178
233
  if (rb_obj_is_kind_of(argv[0], klass)) {
179
234
  rbtree = rbtree_alloc(klass);
180
235
  rbtree_update(rbtree, argv[0]);
181
236
  return rbtree;
182
237
  }
183
-
184
- tmp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
185
- 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)) {
186
247
  rbtree = rbtree_alloc(klass);
187
- st_foreach(RHASH(tmp)->tbl, hash_to_rbtree_i, rbtree);
248
+ rb_hash_foreach(temp, hash_to_rbtree_i, rbtree);
188
249
  return rbtree;
189
250
  }
190
-
191
- tmp = rb_check_array_type(argv[0]);
192
- if (!NIL_P(tmp)) {
251
+
252
+ temp = rb_check_array_type(argv[0]);
253
+ if (!NIL_P(temp)) {
193
254
  rbtree = rbtree_alloc(klass);
194
- for (i = 0; i < RARRAY(tmp)->len; i++) {
195
- VALUE v = rb_check_array_type(RARRAY(tmp)->ptr[i]);
255
+ for (i = 0; i < RARRAY_LEN(temp); i++) {
256
+ VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
196
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);
197
260
  continue;
198
261
  }
199
- switch(RARRAY(v)->len) {
262
+ switch(RARRAY_LEN(v)) {
200
263
  case 1:
201
- rbtree_aset(rbtree, RARRAY(v)->ptr[0], Qnil);
264
+ rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
202
265
  break;
203
266
  case 2:
204
- rbtree_aset(rbtree, RARRAY(v)->ptr[0], RARRAY(v)->ptr[1]);
267
+ rbtree_aset(rbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
205
268
  break;
206
269
  default:
207
- continue;
270
+ rb_warn("invalid number of elements (%ld for 1..2)",
271
+ RARRAY_LEN(v));
208
272
  }
209
273
  }
210
274
  return rbtree;
211
275
  }
212
276
  }
213
-
277
+
214
278
  if (argc % 2 != 0)
215
- rb_raise(rb_eArgError, "odd number of arguments for RBTree");
279
+ rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));
216
280
 
217
281
  rbtree = rbtree_alloc(klass);
218
282
  for (i = 0; i < argc; i += 2)
@@ -229,15 +293,17 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
229
293
  rbtree_modify(self);
230
294
 
231
295
  if (rb_block_given_p()) {
232
- if (argc > 0)
233
- rbtree_argc_error();
234
- 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;
235
301
  FL_SET(self, RBTREE_PROC_DEFAULT);
236
302
  } else {
237
- if (argc > 1)
238
- rbtree_argc_error();
239
- else if (argc == 1)
303
+ rbtree_check_argument_count(argc, 0, 1);
304
+ if (argc == 1) {
240
305
  IFNONE(self) = argv[0];
306
+ }
241
307
  }
242
308
  return self;
243
309
  }
@@ -245,42 +311,50 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
245
311
  /*********************************************************************/
246
312
 
247
313
  typedef enum {
248
- INITIAL_VALUE, NODE_NOT_FOUND, NODE_FOUND
249
- } insert_node_ret_t;
314
+ NoNodeInserted,
315
+ KeyAllocationFailed,
316
+ InsertionSucceeded
317
+ } insert_result_t;
250
318
 
251
319
  typedef struct {
252
320
  dict_t* dict;
253
321
  dnode_t* node;
254
- const void* key;
255
- insert_node_ret_t ret;
256
- } insert_node_t;
322
+ insert_result_t result;
323
+ } rbtree_insert_arg_t;
257
324
 
258
325
  static VALUE
259
- insert_node_body(insert_node_t* arg)
326
+ insert_node_body(rbtree_insert_arg_t* arg)
260
327
  {
261
- if (dict_insert(arg->dict, arg->node, arg->key))
262
- arg->ret = NODE_NOT_FOUND;
263
- else
264
- 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;
265
340
  return Qnil;
266
341
  }
267
342
 
268
343
  static VALUE
269
- insert_node_ensure(insert_node_t* arg)
344
+ insert_node_ensure(rbtree_insert_arg_t* arg)
270
345
  {
271
346
  dict_t* dict = arg->dict;
272
347
  dnode_t* node = arg->node;
273
- switch (arg->ret) {
274
- case INITIAL_VALUE:
275
- dict->dict_freenode(node, dict->dict_context);
276
- break;
277
- case NODE_NOT_FOUND:
278
- if (TYPE(arg->key) == T_STRING)
279
- node->dict_key = TO_KEY(rb_str_new4(GET_KEY(node)));
348
+
349
+ switch (arg->result) {
350
+ case InsertionSucceeded:
280
351
  break;
281
- case NODE_FOUND:
352
+ case NoNodeInserted:
282
353
  dict->dict_freenode(node, dict->dict_context);
283
354
  break;
355
+ case KeyAllocationFailed:
356
+ dict_delete_free(dict, node);
357
+ break;
284
358
  }
285
359
  return Qnil;
286
360
  }
@@ -288,16 +362,16 @@ insert_node_ensure(insert_node_t* arg)
288
362
  static void
289
363
  rbtree_insert(VALUE self, VALUE key, VALUE value)
290
364
  {
291
- insert_node_t arg;
365
+ rbtree_insert_arg_t arg;
292
366
  dict_t* dict = DICT(self);
293
367
  dnode_t* node = dict->dict_allocnode(dict->dict_context);
294
368
 
295
369
  dnode_init(node, TO_VAL(value));
370
+ node->dict_key = TO_KEY(key);
296
371
 
297
372
  arg.dict = dict;
298
373
  arg.node = node;
299
- arg.key = TO_KEY(key);
300
- arg.ret = INITIAL_VALUE;
374
+ arg.result = NoNodeInserted;
301
375
 
302
376
  rb_ensure(insert_node_body, (VALUE)&arg,
303
377
  insert_node_ensure, (VALUE)&arg);
@@ -333,7 +407,7 @@ rbtree_aref(VALUE self, VALUE key)
333
407
  {
334
408
  dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
335
409
  if (node == NULL)
336
- return rb_funcall(self, id_default, 1, key);
410
+ return rb_funcall2(self, id_default, 1, &key);
337
411
  else
338
412
  return GET_VAL(node);
339
413
  }
@@ -345,22 +419,23 @@ VALUE
345
419
  rbtree_fetch(int argc, VALUE* argv, VALUE self)
346
420
  {
347
421
  dnode_t* node;
348
- int block_given;
349
422
 
350
- if (argc == 0 || argc > 2)
351
- rbtree_argc_error();
352
- block_given = rb_block_given_p();
353
- if (block_given && argc == 2)
354
- rb_warn("block supersedes default value argument");
423
+ rbtree_check_argument_count(argc, 1, 2);
424
+ if (argc == 2 && rb_block_given_p()) {
425
+ rb_warn("block supersedes default value argument");
426
+ }
355
427
 
356
428
  node = dict_lookup(DICT(self), TO_KEY(argv[0]));
357
- if (node != NULL)
429
+ if (node != NULL) {
358
430
  return GET_VAL(node);
431
+ }
359
432
 
360
- if (block_given)
433
+ if (rb_block_given_p()) {
361
434
  return rb_yield(argv[0]);
362
- if (argc == 1)
435
+ }
436
+ if (argc == 1) {
363
437
  rb_raise(rb_eIndexError, "key not found");
438
+ }
364
439
  return argv[1];
365
440
  }
366
441
 
@@ -388,15 +463,12 @@ rbtree_empty_p(VALUE self)
388
463
  VALUE
389
464
  rbtree_default(int argc, VALUE* argv, VALUE self)
390
465
  {
391
- VALUE key = Qnil;
392
- if (argc == 1)
393
- key = argv[0];
394
- else if (argc > 1)
395
- rbtree_argc_error();
396
-
466
+ rbtree_check_argument_count(argc, 0, 1);
397
467
  if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
398
- if (argc == 0) return Qnil;
399
- 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]);
400
472
  }
401
473
  return IFNONE(self);
402
474
  }
@@ -424,10 +496,54 @@ rbtree_default_proc(VALUE self)
424
496
  return Qnil;
425
497
  }
426
498
 
427
- static int
428
- 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)
429
528
  {
430
- return rb_equal((VALUE)key1, (VALUE)key2);
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;
431
547
  }
432
548
 
433
549
  /*
@@ -436,13 +552,23 @@ value_eq(const void* key1, const void* key2)
436
552
  VALUE
437
553
  rbtree_equal(VALUE self, VALUE other)
438
554
  {
439
- int ret;
440
555
  if (self == other)
441
556
  return Qtrue;
442
557
  if (!rb_obj_is_kind_of(other, MultiRBTree))
443
558
  return Qfalse;
444
- ret = dict_equal(DICT(self), DICT(other), value_eq);
445
- 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
446
572
  }
447
573
 
448
574
  /*********************************************************************/
@@ -475,7 +601,7 @@ rbtree_each_body(rbtree_each_arg_t* arg)
475
601
  dnode_t* node;
476
602
  dnode_t* first_node;
477
603
  dnode_t* (*next_func)(dict_t*, dnode_t*);
478
-
604
+
479
605
  if (arg->reverse) {
480
606
  first_node = dict_last(dict);
481
607
  next_func = dict_prev;
@@ -483,12 +609,12 @@ rbtree_each_body(rbtree_each_arg_t* arg)
483
609
  first_node = dict_first(dict);
484
610
  next_func = dict_next;
485
611
  }
486
-
612
+
487
613
  ITER_LEV(self)++;
488
614
  for (node = first_node;
489
615
  node != NULL;
490
616
  node = next_func(dict, node)) {
491
-
617
+
492
618
  if (arg->func(node, arg->arg) == EACH_STOP)
493
619
  break;
494
620
  }
@@ -521,45 +647,29 @@ rbtree_reverse_for_each(VALUE self, each_callback_func func, void* arg)
521
647
 
522
648
  /*********************************************************************/
523
649
 
524
- static each_return_t
525
- each_i(dnode_t* node, void* arg)
526
- {
527
- rb_yield(ASSOC(node));
528
- return EACH_NEXT;
529
- }
530
-
531
- /*
532
- * call-seq:
533
- * rbtree.each {|key, value| block} => rbtree
534
- *
535
- * Calls block once for each key in order, passing the key and value
536
- * as a two-element array parameters.
537
- */
538
- VALUE
539
- rbtree_each(VALUE self)
540
- {
541
- RETURN_ENUMERATOR(self, 0, NULL);
542
- return rbtree_for_each(self, each_i, NULL);
543
- }
544
-
545
650
  static each_return_t
546
651
  each_pair_i(dnode_t* node, void* arg)
547
652
  {
548
- rb_yield_values(2, GET_KEY(node), GET_VAL(node));
653
+ rb_yield(ASSOC(node));
549
654
  return EACH_NEXT;
550
655
  }
551
656
 
552
657
  /*
553
658
  * call-seq:
659
+ * rbtree.each {|key, value| block} => rbtree
554
660
  * rbtree.each_pair {|key, value| block} => rbtree
661
+ * rbtree.each => enumerator
662
+ * rbtree.each_pair => enumerator
555
663
  *
556
- * 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
557
665
  * as parameters.
666
+ *
667
+ * Returns an enumerator if no block is given.
558
668
  */
559
669
  VALUE
560
670
  rbtree_each_pair(VALUE self)
561
671
  {
562
- RETURN_ENUMERATOR(self, 0, NULL);
672
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
563
673
  return rbtree_for_each(self, each_pair_i, NULL);
564
674
  }
565
675
 
@@ -573,14 +683,17 @@ each_key_i(dnode_t* node, void* arg)
573
683
  /*
574
684
  * call-seq:
575
685
  * rbtree.each_key {|key| block} => rbtree
686
+ * rbtree.each_key => enumerator
687
+ *
688
+ * Calls block once for each key in order, passing the key as a
689
+ * parameter.
576
690
  *
577
- * Calls block once for each key in order, passing the key as
578
- * parameters.
691
+ * Returns an enumerator if no block is given.
579
692
  */
580
693
  VALUE
581
694
  rbtree_each_key(VALUE self)
582
695
  {
583
- RETURN_ENUMERATOR(self, 0, NULL);
696
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
584
697
  return rbtree_for_each(self, each_key_i, NULL);
585
698
  }
586
699
 
@@ -594,28 +707,34 @@ each_value_i(dnode_t* node, void* arg)
594
707
  /*
595
708
  * call-seq:
596
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.
597
714
  *
598
- * Calls block once for each key in order, passing the value as
599
- * parameters.
715
+ * Returns an enumerator if no block is given.
600
716
  */
601
717
  VALUE
602
718
  rbtree_each_value(VALUE self)
603
719
  {
604
- RETURN_ENUMERATOR(self, 0, NULL);
720
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
605
721
  return rbtree_for_each(self, each_value_i, NULL);
606
722
  }
607
723
 
608
724
  /*
609
725
  * call-seq:
610
726
  * rbtree.reverse_each {|key, value| block} => rbtree
727
+ * rbtree.reverse_each => enumerator
611
728
  *
612
- * Calls block once for each key in reverse order, passing the key and
613
- * value as parameters.
729
+ * Calls block once for each key in reverse order, passing the
730
+ * key-value pair as parameters.
731
+ *
732
+ * Returns an enumerator if no block is given.
614
733
  */
615
734
  VALUE
616
735
  rbtree_reverse_each(VALUE self)
617
736
  {
618
- RETURN_ENUMERATOR(self, 0, NULL);
737
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
619
738
  return rbtree_reverse_for_each(self, each_pair_i, NULL);
620
739
  }
621
740
 
@@ -627,11 +746,17 @@ aset_i(dnode_t* node, void* self)
627
746
  }
628
747
 
629
748
  static void
630
- 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)
631
750
  {
632
751
  VALUE temp = rbtree_alloc(CLASS_OF(dest));
633
- COMPARE(temp) = cmp;
634
- 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
+
635
760
  rbtree_for_each(src, aset_i, (void*)temp);
636
761
  {
637
762
  dict_t* t = DICT(temp);
@@ -639,7 +764,11 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
639
764
  DICT(dest) = t;
640
765
  }
641
766
  rbtree_free(RBTREE(temp));
767
+ RBTREE(temp) = NULL;
642
768
  rb_gc_force_recycle(temp);
769
+
770
+ DICT(dest)->dict_context = RBTREE(dest);
771
+ CMP_PROC(dest) = cmp_proc;
643
772
  }
644
773
 
645
774
  /*
@@ -648,16 +777,18 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp, void* context)
648
777
  VALUE
649
778
  rbtree_initialize_copy(VALUE self, VALUE other)
650
779
  {
780
+ rbtree_modify(self);
781
+
651
782
  if (self == other)
652
783
  return self;
653
784
  if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
654
785
  rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
655
- rb_class2name(CLASS_OF(other)),
656
- rb_class2name(CLASS_OF(self)));
786
+ rb_obj_classname(other),
787
+ rb_obj_classname(self));
657
788
  }
658
-
659
- copy_dict(other, self, COMPARE(other), CONTEXT(other));
660
-
789
+
790
+ copy_dict(other, self, DICT(other)->dict_compare, CMP_PROC(other));
791
+
661
792
  IFNONE(self) = IFNONE(other);
662
793
  if (FL_TEST(other, RBTREE_PROC_DEFAULT))
663
794
  FL_SET(self, RBTREE_PROC_DEFAULT);
@@ -673,18 +804,21 @@ VALUE
673
804
  rbtree_values_at(int argc, VALUE* argv, VALUE self)
674
805
  {
675
806
  long i;
676
- VALUE ary = rb_ary_new();
677
-
807
+ VALUE ary = rb_ary_new2(argc);
808
+
678
809
  for (i = 0; i < argc; i++)
679
810
  rb_ary_push(ary, rbtree_aref(self, argv[i]));
680
811
  return ary;
681
812
  }
682
813
 
683
814
  static each_return_t
684
- select_i(dnode_t* node, void* ary)
815
+ key_i(dnode_t* node, void* args_)
685
816
  {
686
- if (RTEST(rb_yield_values(2, GET_KEY(node), GET_VAL(node))))
687
- 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
+ }
688
822
  return EACH_NEXT;
689
823
  }
690
824
 
@@ -692,25 +826,13 @@ select_i(dnode_t* node, void* ary)
692
826
  *
693
827
  */
694
828
  VALUE
695
- rbtree_select(VALUE self)
696
- {
697
- VALUE ary;
698
-
699
- RETURN_ENUMERATOR(self, 0, NULL);
700
- ary = rb_ary_new();
701
- rbtree_for_each(self, select_i, (void*)ary);
702
- return ary;
703
- }
704
-
705
- static each_return_t
706
- index_i(dnode_t* node, void* arg_)
829
+ rbtree_key(VALUE self, VALUE value)
707
830
  {
708
- VALUE* arg = (VALUE*)arg_;
709
- if (rb_equal(GET_VAL(node), arg[1])) {
710
- arg[0] = GET_KEY(node);
711
- return EACH_STOP;
712
- }
713
- 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];
714
836
  }
715
837
 
716
838
  /*
@@ -719,11 +841,10 @@ index_i(dnode_t* node, void* arg_)
719
841
  VALUE
720
842
  rbtree_index(VALUE self, VALUE value)
721
843
  {
722
- VALUE arg[2];
723
- arg[0] = Qnil;
724
- arg[1] = value;
725
- rbtree_for_each(self, index_i, (void*)&arg);
726
- 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);
727
848
  }
728
849
 
729
850
  /*
@@ -767,10 +888,11 @@ typedef struct {
767
888
  VALUE self;
768
889
  dnode_list_t* list;
769
890
  int raised;
770
- } rbtree_delete_if_arg_t;
891
+ int if_true;
892
+ } rbtree_remove_if_arg_t;
771
893
 
772
894
  static VALUE
773
- rbtree_delete_if_ensure(rbtree_delete_if_arg_t* arg)
895
+ rbtree_remove_if_ensure(rbtree_remove_if_arg_t* arg)
774
896
  {
775
897
  dict_t* dict = DICT(arg->self);
776
898
  dnode_list_t* list = arg->list;
@@ -788,7 +910,7 @@ rbtree_delete_if_ensure(rbtree_delete_if_arg_t* arg)
788
910
  }
789
911
 
790
912
  static VALUE
791
- rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
913
+ rbtree_remove_if_body(rbtree_remove_if_arg_t* arg)
792
914
  {
793
915
  VALUE self = arg->self;
794
916
  dict_t* dict = DICT(self);
@@ -800,7 +922,9 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
800
922
  node != NULL;
801
923
  node = dict_next(dict, node)) {
802
924
 
803
- 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) {
804
928
  dnode_list_t* l = ALLOC(dnode_list_t);
805
929
  l->node = node;
806
930
  l->prev = arg->list;
@@ -811,6 +935,20 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
811
935
  return self;
812
936
  }
813
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
+
814
952
  /*********************************************************************/
815
953
 
816
954
  /*
@@ -819,14 +957,16 @@ rbtree_delete_if_body(rbtree_delete_if_arg_t* arg)
819
957
  VALUE
820
958
  rbtree_delete_if(VALUE self)
821
959
  {
822
- rbtree_delete_if_arg_t arg;
823
-
824
- RETURN_ENUMERATOR(self, 0, NULL);
825
- rbtree_modify(self);
826
- arg.self = self;
827
- arg.list = NULL;
828
- return rb_ensure(rbtree_delete_if_body, (VALUE)&arg,
829
- 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);
830
970
  }
831
971
 
832
972
  /*
@@ -836,8 +976,8 @@ VALUE
836
976
  rbtree_reject_bang(VALUE self)
837
977
  {
838
978
  dictcount_t count;
839
-
840
- RETURN_ENUMERATOR(self, 0, NULL);
979
+
980
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
841
981
  count = dict_count(DICT(self));
842
982
  rbtree_delete_if(self);
843
983
  if (count == dict_count(DICT(self)))
@@ -845,13 +985,73 @@ rbtree_reject_bang(VALUE self)
845
985
  return self;
846
986
  }
847
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
+
848
1039
  /*
849
1040
  *
850
1041
  */
851
1042
  VALUE
852
1043
  rbtree_reject(VALUE self)
853
1044
  {
854
- 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);
855
1055
  }
856
1056
 
857
1057
  static VALUE
@@ -859,32 +1059,28 @@ rbtree_shift_pop(VALUE self, const int shift)
859
1059
  {
860
1060
  dict_t* dict = DICT(self);
861
1061
  dnode_t* node;
862
- VALUE ret;
1062
+ VALUE assoc;
863
1063
 
864
1064
  rbtree_modify(self);
865
1065
 
866
- if (dict_isempty(dict)) {
867
- if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
868
- return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
869
- }
870
- return IFNONE(self);
871
- }
1066
+ if (dict_isempty(dict))
1067
+ return rb_funcall(self, id_default, 1, Qnil);
872
1068
 
873
1069
  if (shift)
874
1070
  node = dict_last(dict);
875
1071
  else
876
1072
  node = dict_first(dict);
877
- ret = ASSOC(node);
1073
+ assoc = ASSOC(node);
878
1074
  dict_delete_free(dict, node);
879
- return ret;
1075
+ return assoc;
880
1076
  }
881
1077
 
882
1078
  /*
883
1079
  * call-seq:
884
- * rbtree.shift => array or object
1080
+ * rbtree.shift => array or object or nil
885
1081
  *
886
- * Removes the first(that is, the smallest) key-value pair and returns
887
- * it as a two-item array.
1082
+ * Removes the first (that is, the smallest) key-value pair and
1083
+ * returns it.
888
1084
  */
889
1085
  VALUE
890
1086
  rbtree_shift(VALUE self)
@@ -894,10 +1090,10 @@ rbtree_shift(VALUE self)
894
1090
 
895
1091
  /*
896
1092
  * call-seq:
897
- * rbtree.pop => array or object
1093
+ * rbtree.pop => array or object or nil
898
1094
  *
899
- * Removes the last(that is, the biggest) key-value pair and returns
900
- * it as a two-item array.
1095
+ * Removes the last (that is, the greatest) key-value pair and returns
1096
+ * it.
901
1097
  */
902
1098
  VALUE
903
1099
  rbtree_pop(VALUE self)
@@ -948,10 +1144,10 @@ rbtree_update(VALUE self, VALUE other)
948
1144
  return self;
949
1145
  if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
950
1146
  rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
951
- rb_class2name(CLASS_OF(other)),
952
- rb_class2name(CLASS_OF(self)));
1147
+ rb_obj_classname(other),
1148
+ rb_obj_classname(self));
953
1149
  }
954
-
1150
+
955
1151
  if (rb_block_given_p())
956
1152
  rbtree_for_each(other, update_block_i, (void*)self);
957
1153
  else
@@ -968,6 +1164,35 @@ rbtree_merge(VALUE self, VALUE other)
968
1164
  return rbtree_update(rb_obj_dup(self), other);
969
1165
  }
970
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
+
971
1196
  /*
972
1197
  *
973
1198
  */
@@ -978,11 +1203,11 @@ rbtree_has_key(VALUE self, VALUE key)
978
1203
  }
979
1204
 
980
1205
  static each_return_t
981
- has_value_i(dnode_t* node, void* arg_)
1206
+ has_value_i(dnode_t* node, void* args_)
982
1207
  {
983
- VALUE* arg = (VALUE*)arg_;
984
- if (rb_equal(GET_VAL(node), arg[1])) {
985
- arg[0] = Qtrue;
1208
+ VALUE* args = (VALUE*)args_;
1209
+ if (rb_equal(GET_VAL(node), args[1])) {
1210
+ args[0] = Qtrue;
986
1211
  return EACH_STOP;
987
1212
  }
988
1213
  return EACH_NEXT;
@@ -994,11 +1219,11 @@ has_value_i(dnode_t* node, void* arg_)
994
1219
  VALUE
995
1220
  rbtree_has_value(VALUE self, VALUE value)
996
1221
  {
997
- VALUE arg[2];
998
- arg[0] = Qfalse;
999
- arg[1] = value;
1000
- rbtree_for_each(self, has_value_i, (void*)&arg);
1001
- 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];
1002
1227
  }
1003
1228
 
1004
1229
  static each_return_t
@@ -1014,7 +1239,7 @@ keys_i(dnode_t* node, void* ary)
1014
1239
  VALUE
1015
1240
  rbtree_keys(VALUE self)
1016
1241
  {
1017
- VALUE ary = rb_ary_new();
1242
+ VALUE ary = rb_ary_new2(dict_count(DICT(self)));
1018
1243
  rbtree_for_each(self, keys_i, (void*)ary);
1019
1244
  return ary;
1020
1245
  }
@@ -1032,9 +1257,9 @@ values_i(dnode_t* node, void* ary)
1032
1257
  VALUE
1033
1258
  rbtree_values(VALUE self)
1034
1259
  {
1035
- VALUE ret = rb_ary_new();
1036
- rbtree_for_each(self, values_i, (void*)ret);
1037
- return ret;
1260
+ VALUE ary = rb_ary_new2(dict_count(DICT(self)));
1261
+ rbtree_for_each(self, values_i, (void*)ary);
1262
+ return ary;
1038
1263
  }
1039
1264
 
1040
1265
  static each_return_t
@@ -1050,7 +1275,7 @@ to_a_i(dnode_t* node, void* ary)
1050
1275
  VALUE
1051
1276
  rbtree_to_a(VALUE self)
1052
1277
  {
1053
- VALUE ary = rb_ary_new();
1278
+ VALUE ary = rb_ary_new2(dict_count(DICT(self)));
1054
1279
  rbtree_for_each(self, to_a_i, (void*)ary);
1055
1280
  OBJ_INFECT(ary, self);
1056
1281
  return ary;
@@ -1059,7 +1284,7 @@ rbtree_to_a(VALUE self)
1059
1284
  static each_return_t
1060
1285
  to_hash_i(dnode_t* node, void* hash)
1061
1286
  {
1062
- st_insert(RHASH(hash)->tbl, GET_KEY(node), GET_VAL(node));
1287
+ rb_hash_aset((VALUE)hash, GET_KEY(node), GET_VAL(node));
1063
1288
  return EACH_NEXT;
1064
1289
  }
1065
1290
 
@@ -1070,13 +1295,12 @@ VALUE
1070
1295
  rbtree_to_hash(VALUE self)
1071
1296
  {
1072
1297
  VALUE hash;
1073
- if (CLASS_OF(self) == MultiRBTree) {
1298
+ if (!rb_obj_is_kind_of(self, RBTree))
1074
1299
  rb_raise(rb_eTypeError, "can't convert MultiRBTree to Hash");
1075
- }
1076
-
1300
+
1077
1301
  hash = rb_hash_new();
1078
1302
  rbtree_for_each(self, to_hash_i, (void*)hash);
1079
- RHASH(hash)->ifnone = IFNONE(self);
1303
+ RHASH_SET_IFNONE(hash, IFNONE(self));
1080
1304
  if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1081
1305
  FL_SET(hash, HASH_PROC_DEFAULT);
1082
1306
  OBJ_INFECT(hash, self);
@@ -1095,78 +1319,69 @@ rbtree_to_rbtree(VALUE self)
1095
1319
  static VALUE
1096
1320
  rbtree_begin_inspect(VALUE self)
1097
1321
  {
1098
- const char* c = rb_class2name(CLASS_OF(self));
1099
- VALUE str = rb_str_new(0, strlen(c) + 5);
1100
- const size_t len = sprintf(RSTRING(str)->ptr, "#<%s: ", c);
1101
- RSTRING(str)->len = len;
1102
- return str;
1103
- }
1104
-
1105
- static VALUE
1106
- to_s_rbtree(VALUE self, VALUE nil)
1107
- {
1108
- return rb_ary_to_s(rbtree_to_a(self));
1109
- }
1110
-
1111
- /*
1112
- *
1113
- */
1114
- VALUE
1115
- rbtree_to_s(VALUE self)
1116
- {
1117
- if (rb_inspecting_p(self))
1118
- return rb_str_cat2(rbtree_begin_inspect(self), "...>");
1119
- return rb_protect_inspect(to_s_rbtree, self, Qnil);
1322
+ VALUE result = rb_str_new2("#<");
1323
+ rb_str_cat2(result, rb_obj_classname(self));
1324
+ rb_str_cat2(result, ": ");
1325
+ return result;
1120
1326
  }
1121
1327
 
1122
1328
  static each_return_t
1123
- inspect_i(dnode_t* node, void* ret_)
1329
+ inspect_i(dnode_t* node, void* result_)
1124
1330
  {
1125
- VALUE ret = (VALUE)ret_;
1331
+ VALUE result = (VALUE)result_;
1126
1332
  VALUE str;
1127
1333
 
1128
- if (RSTRING(ret)->ptr[0] == '-')
1129
- RSTRING(ret)->ptr[0] = '#';
1334
+ if (RSTRING_PTR(result)[0] == '-')
1335
+ RSTRING_PTR(result)[0] = '#';
1130
1336
  else
1131
- rb_str_cat2(ret, ", ");
1337
+ rb_str_cat2(result, ", ");
1132
1338
 
1133
1339
  str = rb_inspect(GET_KEY(node));
1134
- rb_str_append(ret, str);
1135
- OBJ_INFECT(ret, str);
1340
+ rb_str_append(result, str);
1341
+ OBJ_INFECT(result, str);
1136
1342
 
1137
- rb_str_cat2(ret, "=>");
1343
+ rb_str_cat2(result, "=>");
1138
1344
 
1139
1345
  str = rb_inspect(GET_VAL(node));
1140
- rb_str_append(ret, str);
1141
- OBJ_INFECT(ret, str);
1346
+ rb_str_append(result, str);
1347
+ OBJ_INFECT(result, str);
1142
1348
 
1143
1349
  return EACH_NEXT;
1144
1350
  }
1145
1351
 
1146
1352
  static VALUE
1147
- inspect_rbtree(VALUE self, VALUE ret)
1353
+ inspect_rbtree(VALUE self, VALUE result)
1148
1354
  {
1149
1355
  VALUE str;
1150
-
1151
- rb_str_cat2(ret, "{");
1152
- RSTRING(ret)->ptr[0] = '-';
1153
- rbtree_for_each(self, inspect_i, (void*)ret);
1154
- RSTRING(ret)->ptr[0] = '#';
1155
- 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, "}");
1156
1362
 
1157
1363
  str = rb_inspect(IFNONE(self));
1158
- rb_str_cat2(ret, ", default=");
1159
- rb_str_append(ret, str);
1160
- OBJ_INFECT(ret, str);
1161
-
1162
- str = rb_inspect((VALUE)CONTEXT(self));
1163
- rb_str_cat2(ret, ", cmp_proc=");
1164
- rb_str_append(ret, str);
1165
- OBJ_INFECT(ret, str);
1364
+ rb_str_cat2(result, ", default=");
1365
+ rb_str_append(result, str);
1366
+ OBJ_INFECT(result, str);
1367
+
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);
1166
1372
 
1167
- rb_str_cat2(ret, ">");
1168
- OBJ_INFECT(ret, self);
1169
- return ret;
1373
+ rb_str_cat2(result, ">");
1374
+ OBJ_INFECT(result, self);
1375
+ return result;
1376
+ }
1377
+
1378
+ static VALUE
1379
+ rbtree_inspect_recursive(VALUE self, VALUE arg, int recursive)
1380
+ {
1381
+ VALUE str = rbtree_begin_inspect(self);
1382
+ if (recursive)
1383
+ return rb_str_cat2(str, "...>");
1384
+ return inspect_rbtree(self, str);
1170
1385
  }
1171
1386
 
1172
1387
  /*
@@ -1175,19 +1390,32 @@ inspect_rbtree(VALUE self, VALUE ret)
1175
1390
  VALUE
1176
1391
  rbtree_inspect(VALUE self)
1177
1392
  {
1393
+ #ifdef HAVE_RB_EXEC_RECURSIVE
1394
+ return rb_exec_recursive(rbtree_inspect_recursive, self, Qnil);
1395
+ #else
1178
1396
  VALUE str = rbtree_begin_inspect(self);
1179
1397
  if (rb_inspecting_p(self))
1180
1398
  return rb_str_cat2(str, "...>");
1181
1399
  return rb_protect_inspect(inspect_rbtree, self, str);
1400
+ #endif
1182
1401
  }
1183
1402
 
1184
1403
  /*
1185
1404
  * call-seq:
1186
- * rbtree.lower_bound(key) => array
1405
+ * rbtree.lower_bound(key) => array or nil
1187
1406
  *
1188
- * Retruns key-value pair corresponding to the lowest key that is
1189
- * 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
1190
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
1191
1419
  */
1192
1420
  VALUE
1193
1421
  rbtree_lower_bound(VALUE self, VALUE key)
@@ -1200,11 +1428,20 @@ rbtree_lower_bound(VALUE self, VALUE key)
1200
1428
 
1201
1429
  /*
1202
1430
  * call-seq:
1203
- * 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]
1204
1442
  *
1205
- * Retruns key-value pair corresponding to the greatest key that is
1206
- * equal to or lower than the given key(inside of upper boundary). If
1207
- * there is no such key, returns nil.
1443
+ * # no key that is equal to or lower than "a"
1444
+ * rbtree.upper_bound("a") # => nil
1208
1445
  */
1209
1446
  VALUE
1210
1447
  rbtree_upper_bound(VALUE self, VALUE key)
@@ -1221,7 +1458,7 @@ typedef struct {
1221
1458
  VALUE self;
1222
1459
  dnode_t* lower_node;
1223
1460
  dnode_t* upper_node;
1224
- VALUE ret;
1461
+ VALUE result;
1225
1462
  } rbtree_bound_arg_t;
1226
1463
 
1227
1464
  static VALUE
@@ -1232,33 +1469,75 @@ rbtree_bound_body(rbtree_bound_arg_t* arg)
1232
1469
  dnode_t* lower_node = arg->lower_node;
1233
1470
  dnode_t* upper_node = arg->upper_node;
1234
1471
  const int block_given = rb_block_given_p();
1235
- VALUE ret = arg->ret;
1472
+ VALUE result = arg->result;
1236
1473
  dnode_t* node;
1237
1474
 
1238
1475
  ITER_LEV(self)++;
1239
- for (node = lower_node;;
1476
+ for (node = lower_node;
1477
+ node != NULL;
1240
1478
  node = dict_next(dict, node)) {
1241
1479
 
1242
1480
  if (block_given)
1243
1481
  rb_yield_values(2, GET_KEY(node), GET_VAL(node));
1244
1482
  else
1245
- rb_ary_push(ret, ASSOC(node));
1483
+ rb_ary_push(result, ASSOC(node));
1246
1484
  if (node == upper_node)
1247
1485
  break;
1248
1486
  }
1249
- return ret;
1487
+ return result;
1488
+ }
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);
1250
1518
  }
1519
+ #endif
1251
1520
 
1252
1521
  /*********************************************************************/
1253
1522
 
1254
1523
  /*
1255
1524
  * call-seq:
1256
- * rbtree.bound(key1, key2 = key1) => array
1257
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.
1258
1532
  *
1259
- * Returns an array containing key-value pairs between the result of
1260
- * MultiRBTree#lower_bound and MultiRBTree#upper_bound. If a block is
1261
- * given it calls the block once for each pair.
1533
+ * Returns an enumerator if no block is given.
1534
+ *
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 # => []
1262
1541
  */
1263
1542
  VALUE
1264
1543
  rbtree_bound(int argc, VALUE* argv, VALUE self)
@@ -1266,27 +1545,27 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
1266
1545
  dict_t* dict = DICT(self);
1267
1546
  dnode_t* lower_node;
1268
1547
  dnode_t* upper_node;
1269
- VALUE ret;
1270
-
1271
- if (argc == 0 || argc > 2)
1272
- rbtree_argc_error();
1273
-
1548
+ VALUE result;
1549
+
1550
+ rbtree_check_argument_count(argc, 1, 2);
1551
+
1552
+ RETURN_SIZED_ENUMERATOR(self, argc, argv, rbtree_bound_size);
1553
+
1274
1554
  lower_node = dict_lower_bound(dict, TO_KEY(argv[0]));
1275
1555
  upper_node = dict_upper_bound(dict, TO_KEY(argv[argc - 1]));
1276
- ret = rb_block_given_p() ? self : rb_ary_new();
1277
-
1556
+ result = rb_block_given_p() ? self : rb_ary_new();
1557
+
1278
1558
  if (lower_node == NULL || upper_node == NULL ||
1279
- COMPARE(self)(dnode_getkey(lower_node),
1280
- dnode_getkey(upper_node),
1281
- CONTEXT(self)) > 0) {
1282
- 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;
1283
1563
  } else {
1284
1564
  rbtree_bound_arg_t arg;
1285
1565
  arg.self = self;
1286
1566
  arg.lower_node = lower_node;
1287
1567
  arg.upper_node = upper_node;
1288
- arg.ret = ret;
1289
-
1568
+ arg.result = result;
1290
1569
  return rb_ensure(rbtree_bound_body, (VALUE)&arg,
1291
1570
  rbtree_each_ensure, self);
1292
1571
  }
@@ -1298,13 +1577,9 @@ rbtree_first_last(VALUE self, const int first)
1298
1577
  dict_t* dict = DICT(self);
1299
1578
  dnode_t* node;
1300
1579
 
1301
- if (dict_isempty(dict)) {
1302
- if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
1303
- return rb_funcall(IFNONE(self), id_call, 2, self, Qnil);
1304
- }
1305
- return IFNONE(self);
1306
- }
1307
-
1580
+ if (dict_isempty(dict))
1581
+ return rb_funcall(self, id_default, 1, Qnil);
1582
+
1308
1583
  if (first)
1309
1584
  node = dict_first(dict);
1310
1585
  else
@@ -1314,9 +1589,9 @@ rbtree_first_last(VALUE self, const int first)
1314
1589
 
1315
1590
  /*
1316
1591
  * call-seq:
1317
- * rbtree.first => array or object
1592
+ * rbtree.first => array or object or nil
1318
1593
  *
1319
- * Returns the first(that is, the smallest) key-value pair.
1594
+ * Returns the first (that is, the smallest) key-value pair.
1320
1595
  */
1321
1596
  VALUE
1322
1597
  rbtree_first(VALUE self)
@@ -1326,9 +1601,9 @@ rbtree_first(VALUE self)
1326
1601
 
1327
1602
  /*
1328
1603
  * call-seq:
1329
- * rbtree.last => array of object
1604
+ * rbtree.last => array or object or nil
1330
1605
  *
1331
- * Returns the last(that is, the biggest) key-value pair.
1606
+ * Returns the last (that is, the greatest) key-value pair.
1332
1607
  */
1333
1608
  VALUE
1334
1609
  rbtree_last(VALUE self)
@@ -1344,238 +1619,281 @@ rbtree_last(VALUE self)
1344
1619
  * rbtree.readjust {|key1, key2| block} => rbtree
1345
1620
  *
1346
1621
  * Sets a proc to compare keys and readjusts elements using the given
1347
- * block or a Proc object given as the argument. The block takes two
1348
- * arguments of a key and returns negative, 0, or positive depending
1349
- * on the first argument is less than, equal to, or greater than the
1350
- * second one. If no block is given it just readjusts elements using
1351
- * current comparison block. If nil is given as the argument it sets
1352
- * 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]
1353
1635
  */
1354
1636
  VALUE
1355
1637
  rbtree_readjust(int argc, VALUE* argv, VALUE self)
1356
1638
  {
1357
- dict_comp_t cmp = NULL;
1358
- void* context = NULL;
1359
-
1639
+ dict_comp_t cmp_func = NULL;
1640
+ VALUE cmp_proc = Qnil;
1641
+
1360
1642
  rbtree_modify(self);
1361
1643
 
1362
- if (argc == 0) {
1363
- if (rb_block_given_p()) {
1364
- cmp = rbtree_user_cmp;
1365
- context = (void*)rb_block_proc();
1366
- } else {
1367
- cmp = COMPARE(self);
1368
- context = CONTEXT(self);
1369
- }
1370
- } else if (argc == 1 && !rb_block_given_p()) {
1371
- if (argv[0] == Qnil) {
1372
- cmp = rbtree_cmp;
1373
- 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);
1374
1654
  } else {
1375
- if (CLASS_OF(argv[0]) != rb_cProc)
1376
- rb_raise(rb_eTypeError,
1377
- "wrong argument type %s (expected Proc)",
1378
- rb_class2name(CLASS_OF(argv[0])));
1379
- cmp = rbtree_user_cmp;
1380
- 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
+ }
1381
1669
  }
1382
- } else {
1383
- rbtree_argc_error();
1384
1670
  }
1385
1671
 
1386
1672
  if (dict_isempty(DICT(self))) {
1387
- COMPARE(self) = cmp;
1388
- CONTEXT(self) = context;
1673
+ DICT(self)->dict_compare = cmp_func;
1674
+ CMP_PROC(self) = cmp_proc;
1389
1675
  return self;
1390
1676
  }
1391
- copy_dict(self, self, cmp, context);
1677
+ copy_dict(self, self, cmp_func, cmp_proc);
1392
1678
  return self;
1393
1679
  }
1394
1680
 
1395
1681
  /*
1396
1682
  * call-seq:
1397
- * rbtree.cmp_proc => proc
1683
+ * rbtree.cmp_proc => proc or nil
1398
1684
  *
1399
- * 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.
1400
1688
  */
1401
1689
  VALUE
1402
1690
  rbtree_cmp_proc(VALUE self)
1403
1691
  {
1404
- return (VALUE)(CONTEXT(self));
1692
+ return CMP_PROC(self);
1405
1693
  }
1406
1694
 
1407
1695
  /*********************************************************************/
1408
1696
 
1697
+ static ID id_breakable;
1409
1698
  static ID id_comma_breakable;
1699
+ static ID id_group;
1410
1700
  static ID id_object_group;
1411
1701
  static ID id_pp;
1412
- static ID id_pp_hash;
1413
1702
  static ID id_text;
1414
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
+
1415
1711
  typedef struct {
1416
- VALUE rbtree;
1417
1712
  VALUE pp;
1418
- } pp_arg_t;
1713
+ dnode_t* node;
1714
+ } pp_pair_arg_t;
1419
1715
 
1420
1716
  static VALUE
1421
- pp_object_group(VALUE arg_)
1717
+ pp_value(VALUE nil, pp_pair_arg_t* pair_arg)
1422
1718
  {
1423
- pp_arg_t* arg = (pp_arg_t*)arg_;
1424
- 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);
1737
+ }
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
+
1774
+ static VALUE
1775
+ pp_each_pair(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
1776
+ {
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);
1425
1781
  }
1426
1782
 
1427
1783
  static VALUE
1428
- pp_block(VALUE nil, pp_arg_t* arg)
1784
+ pp_rbtree(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
1429
1785
  {
1430
- VALUE pp = arg->pp;
1431
- VALUE rbtree = arg->rbtree;
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("}");
1432
1794
 
1433
1795
  rb_funcall(pp, id_text, 1, rb_str_new2(": "));
1434
- rb_funcall(pp, id_pp_hash, 1, rbtree);
1796
+ rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
1435
1797
  rb_funcall(pp, id_comma_breakable, 0);
1436
1798
  rb_funcall(pp, id_text, 1, rb_str_new2("default="));
1437
1799
  rb_funcall(pp, id_pp, 1, IFNONE(rbtree));
1438
1800
  rb_funcall(pp, id_comma_breakable, 0);
1439
1801
  rb_funcall(pp, id_text, 1, rb_str_new2("cmp_proc="));
1440
- rb_funcall(pp, id_pp, 1, CONTEXT(rbtree));
1441
- 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);
1442
1810
  }
1443
1811
 
1444
1812
  /*********************************************************************/
1445
1813
 
1446
- /*
1447
- * Called by pretty printing function pp.
1814
+ /* :nodoc:
1815
+ *
1448
1816
  */
1449
1817
  VALUE
1450
1818
  rbtree_pretty_print(VALUE self, VALUE pp)
1451
1819
  {
1452
- pp_arg_t pp_arg;
1453
- pp_arg.rbtree = self;
1454
- pp_arg.pp = pp;
1455
-
1456
- return rb_iterate(pp_object_group, (VALUE)&pp_arg,
1457
- 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);
1458
1824
  }
1459
1825
 
1460
- /*
1461
- * Called by pretty printing function pp.
1826
+ /* :nodoc:
1827
+ *
1462
1828
  */
1463
1829
  VALUE
1464
1830
  rbtree_pretty_print_cycle(VALUE self, VALUE pp)
1465
1831
  {
1466
- return rb_funcall(pp, id_pp, 1, rbtree_inspect(self));
1832
+ return rb_funcall(pp, id_pp, 1, rbtree_inspect_recursive(self, Qnil, 1));
1467
1833
  }
1468
1834
 
1469
1835
  /*********************************************************************/
1470
1836
 
1471
- static each_return_t
1472
- to_flatten_ary_i(dnode_t* node, void* ary)
1473
- {
1474
- rb_ary_push((VALUE)ary, GET_KEY(node));
1475
- rb_ary_push((VALUE)ary, GET_VAL(node));
1476
- return EACH_NEXT;
1477
- }
1478
-
1479
- /*********************************************************************/
1480
-
1481
- /*
1482
- * Called by Marshal.dump.
1837
+ /* :nodoc:
1838
+ *
1483
1839
  */
1484
1840
  VALUE
1485
1841
  rbtree_dump(VALUE self, VALUE limit)
1486
1842
  {
1487
1843
  VALUE ary;
1488
- VALUE ret;
1489
-
1844
+ VALUE result;
1845
+
1490
1846
  if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1491
- rb_raise(rb_eTypeError, "cannot dump rbtree with default proc");
1492
- if ((VALUE)CONTEXT(self) != Qnil)
1493
- rb_raise(rb_eTypeError, "cannot dump rbtree with compare proc");
1494
-
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
+
1495
1851
  ary = rb_ary_new2(dict_count(DICT(self)) * 2 + 1);
1496
- rbtree_for_each(self, to_flatten_ary_i, (void*)ary);
1852
+ rbtree_for_each(self, to_flat_ary_i, (void*)ary);
1497
1853
  rb_ary_push(ary, IFNONE(self));
1498
1854
 
1499
- 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
1500
1859
  rb_ary_clear(ary);
1501
- rb_gc_force_recycle(ary);
1502
- return ret;
1860
+ #endif
1861
+ return result;
1503
1862
  }
1504
1863
 
1505
- /*
1506
- * Called by Marshal.load.
1864
+ /* :nodoc:
1865
+ *
1507
1866
  */
1508
1867
  VALUE
1509
1868
  rbtree_s_load(VALUE klass, VALUE str)
1510
1869
  {
1511
1870
  VALUE rbtree = rbtree_alloc(klass);
1512
1871
  VALUE ary = rb_marshal_load(str);
1513
- VALUE* ptr = RARRAY(ary)->ptr;
1514
- long len = RARRAY(ary)->len - 1;
1872
+ long len = RARRAY_LEN(ary) - 1;
1515
1873
  long i;
1516
-
1874
+
1517
1875
  for (i = 0; i < len; i += 2)
1518
- rbtree_aset(rbtree, ptr[i], ptr[i + 1]);
1519
- IFNONE(rbtree) = ptr[len];
1520
-
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
1521
1882
  rb_ary_clear(ary);
1522
- rb_gc_force_recycle(ary);
1883
+ #endif
1523
1884
  return rbtree;
1524
1885
  }
1525
1886
 
1526
1887
  /*********************************************************************/
1527
1888
 
1528
1889
  /*
1529
- * RBTree is a sorted associative collection that is implemented with
1530
- * Red-Black Tree. The elements of RBTree are ordered and its interface
1531
- * is the almost same as Hash, so simply you can consider RBTree sorted
1532
- * Hash.
1533
- *
1534
- * Red-Black Tree is a kind of binary tree that automatically balances
1535
- * by itself when a node is inserted or deleted. Thus the complexity
1536
- * for insert, search and delete is O(log N) in expected and worst
1537
- * case. On the other hand the complexity of Hash is O(1). Because
1538
- * Hash is unordered the data structure is more effective than
1539
- * Red-Black Tree as an associative collection.
1540
- *
1541
- * The elements of RBTree are sorted with natural ordering (by <=>
1542
- * method) of its keys or by a comparator(Proc) set by readjust
1543
- * method. It means all keys in RBTree should be comparable with each
1544
- * other. Or a comparator that takes two arguments of a key should return
1545
- * negative, 0, or positive depending on the first argument is less than,
1546
- * equal to, or greater than the second one.
1547
- *
1548
- * The interface of RBTree is the almost same as Hash and there are a
1549
- * few methods to take advantage of the ordering:
1550
- *
1551
- * * lower_bound, upper_bound, bound
1552
- * * first, last
1553
- * * shift, pop
1554
- * * reverse_each
1555
- *
1556
- * Note: while iterating RBTree (e.g. in a block of each method), it is
1557
- * not modifiable, or TypeError is thrown.
1558
- *
1559
- * RBTree supoorts pretty printing using pp.
1560
- *
1561
- * This library contains two classes. One is RBTree and the other is
1562
- * MultiRBTree that is a parent class of RBTree. RBTree does not allow
1563
- * duplications of keys but MultiRBTree does.
1564
- *
1565
- * require "rbtree"
1566
- *
1567
- * rbtree = RBTree["c", 10, "a", 20]
1568
- * rbtree["b"] = 30
1569
- * p rbtree["b"] # => 30
1570
- * rbtree.each do |k, v|
1571
- * p [k, v]
1572
- * end # => ["a", 20] ["b", 30] ["c", 10]
1573
- *
1574
- * mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
1575
- * p mrbtree.lower_bound("b") # => ["c", 10]
1576
- * mrbtree.bound("a", "d") do |k, v|
1577
- * p [k, v]
1578
- * 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.
1579
1897
  */
1580
1898
  void Init_rbtree()
1581
1899
  {
@@ -1592,10 +1910,11 @@ void Init_rbtree()
1592
1910
  rb_define_method(MultiRBTree, "initialize_copy", rbtree_initialize_copy, 1);
1593
1911
 
1594
1912
  rb_define_method(MultiRBTree, "to_a", rbtree_to_a, 0);
1595
- rb_define_method(MultiRBTree, "to_s", rbtree_to_s, 0);
1913
+ rb_define_method(MultiRBTree, "to_h", rbtree_to_hash, 0);
1596
1914
  rb_define_method(MultiRBTree, "to_hash", rbtree_to_hash, 0);
1597
1915
  rb_define_method(MultiRBTree, "to_rbtree", rbtree_to_rbtree, 0);
1598
1916
  rb_define_method(MultiRBTree, "inspect", rbtree_inspect, 0);
1917
+ rb_define_alias(MultiRBTree, "to_s", "inspect");
1599
1918
 
1600
1919
  rb_define_method(MultiRBTree, "==", rbtree_equal, 1);
1601
1920
  rb_define_method(MultiRBTree, "[]", rbtree_aref, 1);
@@ -1610,12 +1929,14 @@ void Init_rbtree()
1610
1929
  rb_define_method(MultiRBTree, "default", rbtree_default, -1);
1611
1930
  rb_define_method(MultiRBTree, "default=", rbtree_set_default, 1);
1612
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);
1613
1934
  rb_define_method(MultiRBTree, "index", rbtree_index, 1);
1614
1935
  rb_define_method(MultiRBTree, "empty?", rbtree_empty_p, 0);
1615
1936
  rb_define_method(MultiRBTree, "size", rbtree_size, 0);
1616
1937
  rb_define_method(MultiRBTree, "length", rbtree_size, 0);
1617
1938
 
1618
- rb_define_method(MultiRBTree, "each", rbtree_each, 0);
1939
+ rb_define_method(MultiRBTree, "each", rbtree_each_pair, 0);
1619
1940
  rb_define_method(MultiRBTree, "each_value", rbtree_each_value, 0);
1620
1941
  rb_define_method(MultiRBTree, "each_key", rbtree_each_key, 0);
1621
1942
  rb_define_method(MultiRBTree, "each_pair", rbtree_each_pair, 0);
@@ -1629,15 +1950,20 @@ void Init_rbtree()
1629
1950
  rb_define_method(MultiRBTree, "pop", rbtree_pop, 0);
1630
1951
  rb_define_method(MultiRBTree, "delete", rbtree_delete, 1);
1631
1952
  rb_define_method(MultiRBTree, "delete_if", rbtree_delete_if, 0);
1632
- rb_define_method(MultiRBTree, "select", rbtree_select, 0);
1953
+ rb_define_method(MultiRBTree, "keep_if", rbtree_keep_if, 0);
1633
1954
  rb_define_method(MultiRBTree, "reject", rbtree_reject, 0);
1634
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);
1635
1958
  rb_define_method(MultiRBTree, "clear", rbtree_clear, 0);
1636
1959
  rb_define_method(MultiRBTree, "invert", rbtree_invert, 0);
1637
1960
  rb_define_method(MultiRBTree, "update", rbtree_update, 1);
1638
1961
  rb_define_method(MultiRBTree, "merge!", rbtree_update, 1);
1639
1962
  rb_define_method(MultiRBTree, "merge", rbtree_merge, 1);
1640
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
1641
1967
 
1642
1968
  rb_define_method(MultiRBTree, "include?", rbtree_has_key, 1);
1643
1969
  rb_define_method(MultiRBTree, "member?", rbtree_has_key, 1);
@@ -1651,20 +1977,20 @@ void Init_rbtree()
1651
1977
 
1652
1978
  rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
1653
1979
  rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
1654
-
1655
- id_bound = rb_intern("bound");
1980
+
1656
1981
  id_cmp = rb_intern("<=>");
1657
1982
  id_call = rb_intern("call");
1658
1983
  id_default = rb_intern("default");
1659
-
1984
+ id_flatten_bang = rb_intern("flatten!");
1660
1985
 
1661
1986
  rb_define_method(MultiRBTree, "pretty_print", rbtree_pretty_print, 1);
1662
1987
  rb_define_method(MultiRBTree,
1663
1988
  "pretty_print_cycle", rbtree_pretty_print_cycle, 1);
1664
1989
 
1990
+ id_breakable = rb_intern("breakable");
1665
1991
  id_comma_breakable = rb_intern("comma_breakable");
1992
+ id_group = rb_intern("group");
1666
1993
  id_object_group = rb_intern("object_group");
1667
- id_pp_hash = rb_intern("pp_hash");
1668
- id_text = rb_intern("text");
1669
1994
  id_pp = rb_intern("pp");
1995
+ id_text = rb_intern("text");
1670
1996
  }