rbtree 0.3.0 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (11) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/MANIFEST +0 -1
  4. data/README +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
  }