rbtree 0.4.1 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (8) hide show
  1. checksums.yaml +5 -5
  2. data/README +6 -16
  3. data/dict.c +309 -4
  4. data/dict.h +3 -3
  5. data/extconf.rb +4 -1
  6. data/rbtree.c +143 -134
  7. data/test.rb +18 -20
  8. metadata +10 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 42305188c5448bb5c684e198069f323816d32d5a
4
- data.tar.gz: f1d5608adf7f2c1d142048d5abbe499d11cc83a6
2
+ SHA256:
3
+ metadata.gz: d5bc8dc390afc34242d6cd951136f2d86c9a0bafc809ed93d39d0fdf6c8ea9c0
4
+ data.tar.gz: '059f888a97995d9bc64edcdafb504817b570e07df03c3385e5c5fe3e8bbc8f72'
5
5
  SHA512:
6
- metadata.gz: 892207ef1dc38a23044b15480bcd57a4ab722cc944131f1d56d1878aa668b539d0c10f6a0cdd6c52b7d3255e17c14fb466ed898a3bc56fbe0e15472da912a888
7
- data.tar.gz: c2a3503fcc68622ab775d421843b25d07afa7f1702e870ad57a600f3c06b904179c86d62bc6dd3d6c86e5948af09f95e37998de35fb7c8e48e00c4478fae9e15
6
+ metadata.gz: 9a27e36148fab48e03777b3151dc70ee69262da497263bf83cc25c3b9c6b8c7080857cd75c0d2ac8b3837f511d8a448565f1ae64b1da7740dd26b6ec4fca955a
7
+ data.tar.gz: 9f682a9ce24a0cd3ff101d91cc145fbed066de4788cbb5b25abecfc1604c0e0065d1dc5d35d0f35d10df911bde971ab9f18edafd84030ae5309ce578be6cbc35
data/README CHANGED
@@ -57,18 +57,14 @@ Run the following command.
57
57
  $ sudo gem install rbtree
58
58
 
59
59
  == Changes
60
- === 0.4.1
61
- * Fixed a crash that could be triggered when GC happened.
60
+ === 0.4.5
61
+ * Support Ruby 3.2.0-dev (development branch).
62
62
 
63
- === 0.4.0
63
+ === 0.4.4
64
+ * Remove the rb_safe_level warning on Ruby 2.7.
64
65
 
65
- * Fixed build failure with Ruby 2.0.0.
66
- * \#bound now returns an enumerator if no block is given.
67
- * \#select now returns a new MultiRBTree / RBTree.
68
- * Fixed a bug where \#reject could return nil.
69
- * \#to_s is now equivalent to \#inspect.
70
- * \#each now passes a two elements array as an argument to the given block.
71
- * Added new methods: \#default_proc=, \#flatten, \#keep_if, \#key, \#select! and \#to_h.
66
+ === 0.4.3
67
+ * Quick bug fixes for Ruby 3.
72
68
 
73
69
  == License
74
70
 
@@ -78,9 +74,3 @@ dict.c and dict.h are modified copies that are originally in Kazlib
78
74
  1.20 written by Kaz Kylheku. Its license is similar to the MIT
79
75
  license. See dict.c and dict.h for the details. The web page of Kazlib
80
76
  is at http://www.kylheku.com/~kaz/kazlib.html.
81
-
82
- == Contact
83
-
84
- Run the following command.
85
-
86
- $ ruby -e "puts 'YnVybmluZ2Rvd250aGVvcGVyYUB5YWhvby5jby5qcA==\n'.unpack('m')"
data/dict.c CHANGED
@@ -14,12 +14,12 @@
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.c,v 1.15 2005/10/06 05:16:35 kuma Exp $
18
- * $Name: $
17
+ * $Id: dict.c,v 1.40.2.7 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
  #include <stdlib.h>
@@ -29,7 +29,7 @@
29
29
  #include "dict.h"
30
30
 
31
31
  #ifdef KAZLIB_RCSID
32
- static const char rcsid[] = "$Id: dict.c,v 1.15 2005/10/06 05:16:35 kuma Exp $";
32
+ static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $";
33
33
  #endif
34
34
 
35
35
  /*
@@ -1190,3 +1190,308 @@ void dict_merge(dict_t *dest, dict_t *source)
1190
1190
  dict_clear(source);
1191
1191
  dict_load_end(&load);
1192
1192
  }
1193
+
1194
+ #ifdef KAZLIB_TEST_MAIN
1195
+
1196
+ #include <stdio.h>
1197
+ #include <string.h>
1198
+ #include <ctype.h>
1199
+ #include <stdarg.h>
1200
+
1201
+ typedef char input_t[256];
1202
+
1203
+ static int tokenize(char *string, ...)
1204
+ {
1205
+ char **tokptr;
1206
+ va_list arglist;
1207
+ int tokcount = 0;
1208
+
1209
+ va_start(arglist, string);
1210
+ tokptr = va_arg(arglist, char **);
1211
+ while (tokptr) {
1212
+ while (*string && isspace((unsigned char) *string))
1213
+ string++;
1214
+ if (!*string)
1215
+ break;
1216
+ *tokptr = string;
1217
+ while (*string && !isspace((unsigned char) *string))
1218
+ string++;
1219
+ tokptr = va_arg(arglist, char **);
1220
+ tokcount++;
1221
+ if (!*string)
1222
+ break;
1223
+ *string++ = 0;
1224
+ }
1225
+ va_end(arglist);
1226
+
1227
+ return tokcount;
1228
+ }
1229
+
1230
+ static int comparef(const void *key1, const void *key2)
1231
+ {
1232
+ return strcmp(key1, key2);
1233
+ }
1234
+
1235
+ static char *dupstring(char *str)
1236
+ {
1237
+ int sz = strlen(str) + 1;
1238
+ char *new = malloc(sz);
1239
+ if (new)
1240
+ memcpy(new, str, sz);
1241
+ return new;
1242
+ }
1243
+
1244
+ static dnode_t *new_node(void *c)
1245
+ {
1246
+ static dnode_t few[5];
1247
+ static int count;
1248
+
1249
+ if (count < 5)
1250
+ return few + count++;
1251
+
1252
+ return NULL;
1253
+ }
1254
+
1255
+ static void del_node(dnode_t *n, void *c)
1256
+ {
1257
+ }
1258
+
1259
+ static int prompt = 0;
1260
+
1261
+ static void construct(dict_t *d)
1262
+ {
1263
+ input_t in;
1264
+ int done = 0;
1265
+ dict_load_t dl;
1266
+ dnode_t *dn;
1267
+ char *tok1, *tok2, *val;
1268
+ const char *key;
1269
+ char *help =
1270
+ "p turn prompt on\n"
1271
+ "q finish construction\n"
1272
+ "a <key> <val> add new entry\n";
1273
+
1274
+ if (!dict_isempty(d))
1275
+ puts("warning: dictionary not empty!");
1276
+
1277
+ dict_load_begin(&dl, d);
1278
+
1279
+ while (!done) {
1280
+ if (prompt)
1281
+ putchar('>');
1282
+ fflush(stdout);
1283
+
1284
+ if (!fgets(in, sizeof(input_t), stdin))
1285
+ break;
1286
+
1287
+ switch (in[0]) {
1288
+ case '?':
1289
+ puts(help);
1290
+ break;
1291
+ case 'p':
1292
+ prompt = 1;
1293
+ break;
1294
+ case 'q':
1295
+ done = 1;
1296
+ break;
1297
+ case 'a':
1298
+ if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1299
+ puts("what?");
1300
+ break;
1301
+ }
1302
+ key = dupstring(tok1);
1303
+ val = dupstring(tok2);
1304
+ dn = dnode_create(val);
1305
+
1306
+ if (!key || !val || !dn) {
1307
+ puts("out of memory");
1308
+ free((void *) key);
1309
+ free(val);
1310
+ if (dn)
1311
+ dnode_destroy(dn);
1312
+ }
1313
+
1314
+ dict_load_next(&dl, dn, key);
1315
+ break;
1316
+ default:
1317
+ putchar('?');
1318
+ putchar('\n');
1319
+ break;
1320
+ }
1321
+ }
1322
+
1323
+ dict_load_end(&dl);
1324
+ }
1325
+
1326
+ int main(void)
1327
+ {
1328
+ input_t in;
1329
+ dict_t darray[10];
1330
+ dict_t *d = &darray[0];
1331
+ dnode_t *dn;
1332
+ int i;
1333
+ char *tok1, *tok2, *val;
1334
+ const char *key;
1335
+
1336
+ char *help =
1337
+ "a <key> <val> add value to dictionary\n"
1338
+ "d <key> delete value from dictionary\n"
1339
+ "l <key> lookup value in dictionary\n"
1340
+ "( <key> lookup lower bound\n"
1341
+ ") <key> lookup upper bound\n"
1342
+ "# <num> switch to alternate dictionary (0-9)\n"
1343
+ "j <num> <num> merge two dictionaries\n"
1344
+ "f free the whole dictionary\n"
1345
+ "k allow duplicate keys\n"
1346
+ "c show number of entries\n"
1347
+ "t dump whole dictionary in sort order\n"
1348
+ "m make dictionary out of sorted items\n"
1349
+ "p turn prompt on\n"
1350
+ "s switch to non-functioning allocator\n"
1351
+ "q quit";
1352
+
1353
+ for (i = 0; i < sizeof darray / sizeof *darray; i++)
1354
+ dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
1355
+
1356
+ for (;;) {
1357
+ if (prompt)
1358
+ putchar('>');
1359
+ fflush(stdout);
1360
+
1361
+ if (!fgets(in, sizeof(input_t), stdin))
1362
+ break;
1363
+
1364
+ switch(in[0]) {
1365
+ case '?':
1366
+ puts(help);
1367
+ break;
1368
+ case 'a':
1369
+ if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1370
+ puts("what?");
1371
+ break;
1372
+ }
1373
+ key = dupstring(tok1);
1374
+ val = dupstring(tok2);
1375
+
1376
+ if (!key || !val) {
1377
+ puts("out of memory");
1378
+ free((void *) key);
1379
+ free(val);
1380
+ }
1381
+
1382
+ if (!dict_alloc_insert(d, key, val)) {
1383
+ puts("dict_alloc_insert failed");
1384
+ free((void *) key);
1385
+ free(val);
1386
+ break;
1387
+ }
1388
+ break;
1389
+ case 'd':
1390
+ if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1391
+ puts("what?");
1392
+ break;
1393
+ }
1394
+ dn = dict_lookup(d, tok1);
1395
+ if (!dn) {
1396
+ puts("dict_lookup failed");
1397
+ break;
1398
+ }
1399
+ val = dnode_get(dn);
1400
+ key = dnode_getkey(dn);
1401
+ dict_delete_free(d, dn);
1402
+
1403
+ free(val);
1404
+ free((void *) key);
1405
+ break;
1406
+ case 'f':
1407
+ dict_free(d);
1408
+ break;
1409
+ case 'l':
1410
+ case '(':
1411
+ case ')':
1412
+ if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1413
+ puts("what?");
1414
+ break;
1415
+ }
1416
+ dn = 0;
1417
+ switch (in[0]) {
1418
+ case 'l':
1419
+ dn = dict_lookup(d, tok1);
1420
+ break;
1421
+ case '(':
1422
+ dn = dict_lower_bound(d, tok1);
1423
+ break;
1424
+ case ')':
1425
+ dn = dict_upper_bound(d, tok1);
1426
+ break;
1427
+ }
1428
+ if (!dn) {
1429
+ puts("lookup failed");
1430
+ break;
1431
+ }
1432
+ val = dnode_get(dn);
1433
+ puts(val);
1434
+ break;
1435
+ case 'm':
1436
+ construct(d);
1437
+ break;
1438
+ case 'k':
1439
+ dict_allow_dupes(d);
1440
+ break;
1441
+ case 'c':
1442
+ printf("%lu\n", (unsigned long) dict_count(d));
1443
+ break;
1444
+ case 't':
1445
+ for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1446
+ printf("%s\t%s\n", (char *) dnode_getkey(dn),
1447
+ (char *) dnode_get(dn));
1448
+ }
1449
+ break;
1450
+ case 'q':
1451
+ exit(0);
1452
+ break;
1453
+ case '\0':
1454
+ break;
1455
+ case 'p':
1456
+ prompt = 1;
1457
+ break;
1458
+ case 's':
1459
+ dict_set_allocator(d, new_node, del_node, NULL);
1460
+ break;
1461
+ case '#':
1462
+ if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1463
+ puts("what?");
1464
+ break;
1465
+ } else {
1466
+ int dictnum = atoi(tok1);
1467
+ if (dictnum < 0 || dictnum > 9) {
1468
+ puts("invalid number");
1469
+ break;
1470
+ }
1471
+ d = &darray[dictnum];
1472
+ }
1473
+ break;
1474
+ case 'j':
1475
+ if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1476
+ puts("what?");
1477
+ break;
1478
+ } else {
1479
+ int dict1 = atoi(tok1), dict2 = atoi(tok2);
1480
+ if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1481
+ puts("invalid number");
1482
+ break;
1483
+ }
1484
+ dict_merge(&darray[dict1], &darray[dict2]);
1485
+ }
1486
+ break;
1487
+ default:
1488
+ putchar('?');
1489
+ putchar('\n');
1490
+ break;
1491
+ }
1492
+ }
1493
+
1494
+ return 0;
1495
+ }
1496
+
1497
+ #endif
data/dict.h CHANGED
@@ -14,12 +14,12 @@
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
data/extconf.rb CHANGED
@@ -5,10 +5,13 @@ if enable_config('debug')
5
5
  else
6
6
  $defs << '-DNDEBUG'
7
7
  end
8
- have_header('ruby/st.h')
9
8
  have_func('rb_exec_recursive', 'ruby.h')
10
9
  have_func('rb_exec_recursive_paired', 'ruby.h')
11
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
+ have_func('rb_cData', 'ruby.h')
12
15
  if Hash.method_defined?(:flatten)
13
16
  $defs << '-DHAVE_HASH_FLATTEN'
14
17
  end
data/rbtree.c CHANGED
@@ -23,11 +23,12 @@
23
23
  #endif
24
24
  #endif
25
25
 
26
- #ifndef RHASH_TBL
27
- #define RHASH_TBL(h) RHASH(h)->tbl
26
+ #ifndef RARRAY_AREF
27
+ #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
28
28
  #endif
29
- #ifndef RHASH_IFNONE
30
- #define RHASH_IFNONE(h) RHASH(h)->ifnone
29
+
30
+ #ifndef RHASH_SET_IFNONE
31
+ #define RHASH_SET_IFNONE(h, v) (RHASH(h)->ifnone = (v))
31
32
  #endif
32
33
 
33
34
  VALUE RBTree;
@@ -100,15 +101,17 @@ rbtree_free_node(dnode_t* node, void* context)
100
101
  }
101
102
 
102
103
  static void
103
- rbtree_argc_error(const int argc, const int min, const int max)
104
- {
105
- const char* message = "wrong number of arguments";
106
- if (min == max) {
107
- rb_raise(rb_eArgError, "%s (%d for %d)", message, argc, min);
108
- } else if (max == INT_MAX) {
109
- rb_raise(rb_eArgError, "%s (%d for %d+)", message, argc, -min - 1);
110
- } else {
111
- rb_raise(rb_eArgError, "%s (%d for %d..%d)", message, argc, min, max);
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
+ }
112
115
  }
113
116
  }
114
117
 
@@ -173,25 +176,27 @@ rbtree_modify(VALUE self)
173
176
  if (ITER_LEV(self) > 0)
174
177
  rb_raise(rb_eTypeError, "can't modify rbtree during iteration");
175
178
  rb_check_frozen(self);
179
+ #if defined(HAVE_RB_SAFE_LEVEL) && !defined(RUBY_SAFE_LEVEL_MAX)
176
180
  if (!OBJ_TAINTED(self) && rb_safe_level() >= 4)
177
181
  rb_raise(rb_eSecurityError, "Insecure: can't modify rbtree");
182
+ #endif
178
183
  }
179
184
 
180
185
  static VALUE
181
186
  rbtree_alloc(VALUE klass)
182
187
  {
183
188
  dict_t* dict;
184
- VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, 0);
189
+ VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, NULL);
185
190
  RBTREE(rbtree) = ALLOC(rbtree_t);
186
191
  MEMZERO(RBTREE(rbtree), rbtree_t, 1);
187
-
192
+
188
193
  dict = ALLOC(dict_t);
189
194
  dict_init(dict, rbtree_cmp);
190
195
  dict_set_allocator(dict, rbtree_alloc_node, rbtree_free_node,
191
196
  RBTREE(rbtree));
192
197
  if (!RTEST(rb_class_inherited_p(klass, RBTree)))
193
198
  dict_allow_dupes(dict);
194
-
199
+
195
200
  DICT(rbtree) = dict;
196
201
  IFNONE(rbtree) = Qnil;
197
202
  CMP_PROC(rbtree) = Qnil;
@@ -221,45 +226,45 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
221
226
  {
222
227
  long i;
223
228
  VALUE rbtree;
224
-
229
+
225
230
  if (argc == 1) {
226
231
  VALUE temp;
227
-
232
+
228
233
  if (rb_obj_is_kind_of(argv[0], klass)) {
229
234
  rbtree = rbtree_alloc(klass);
230
235
  rbtree_update(rbtree, argv[0]);
231
236
  return rbtree;
232
237
  }
233
-
238
+
234
239
  if (RTEST(rb_class_inherited_p(klass, RBTree)) &&
235
240
  (rb_obj_is_kind_of(argv[0], MultiRBTree) && !rb_obj_is_kind_of(argv[0], RBTree))) {
236
-
241
+
237
242
  rb_raise(rb_eTypeError, "wrong argument type MultiRBTree (expected RBTree)");
238
243
  }
239
-
244
+
240
245
  temp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
241
246
  if (!NIL_P(temp)) {
242
247
  rbtree = rbtree_alloc(klass);
243
248
  rb_hash_foreach(temp, hash_to_rbtree_i, rbtree);
244
249
  return rbtree;
245
250
  }
246
-
251
+
247
252
  temp = rb_check_array_type(argv[0]);
248
253
  if (!NIL_P(temp)) {
249
254
  rbtree = rbtree_alloc(klass);
250
255
  for (i = 0; i < RARRAY_LEN(temp); i++) {
251
- VALUE v = rb_check_array_type(RARRAY_PTR(temp)[i]);
256
+ VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
252
257
  if (NIL_P(v)) {
253
258
  rb_warn("wrong element type %s at %ld (expected Array)",
254
- rb_obj_classname(RARRAY_PTR(temp)[i]), i);
259
+ rb_obj_classname(RARRAY_AREF(temp, i)), i);
255
260
  continue;
256
261
  }
257
262
  switch(RARRAY_LEN(v)) {
258
263
  case 1:
259
- rbtree_aset(rbtree, RARRAY_PTR(v)[0], Qnil);
264
+ rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
260
265
  break;
261
266
  case 2:
262
- rbtree_aset(rbtree, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
267
+ rbtree_aset(rbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
263
268
  break;
264
269
  default:
265
270
  rb_warn("invalid number of elements (%ld for 1..2)",
@@ -269,7 +274,7 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
269
274
  return rbtree;
270
275
  }
271
276
  }
272
-
277
+
273
278
  if (argc % 2 != 0)
274
279
  rb_raise(rb_eArgError, "odd number of arguments for %s", rb_class2name(klass));
275
280
 
@@ -289,17 +294,14 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
289
294
 
290
295
  if (rb_block_given_p()) {
291
296
  VALUE proc;
292
- if (argc > 0) {
293
- rbtree_argc_error(argc, 0, 0);
294
- }
297
+ rbtree_check_argument_count(argc, 0, 0);
295
298
  proc = rb_block_proc();
296
299
  rbtree_check_proc_arity(proc, 2);
297
300
  IFNONE(self) = proc;
298
301
  FL_SET(self, RBTREE_PROC_DEFAULT);
299
302
  } else {
300
- if (argc > 1) {
301
- rbtree_argc_error(argc, 1, 1);
302
- } else if (argc == 1) {
303
+ rbtree_check_argument_count(argc, 0, 1);
304
+ if (argc == 1) {
303
305
  IFNONE(self) = argv[0];
304
306
  }
305
307
  }
@@ -325,7 +327,7 @@ insert_node_body(rbtree_insert_arg_t* arg)
325
327
  {
326
328
  dict_t* dict = arg->dict;
327
329
  dnode_t* node = arg->node;
328
-
330
+
329
331
  if (dict_insert(dict, node, dnode_getkey(node))) {
330
332
  if (TYPE(GET_KEY(node)) == T_STRING) {
331
333
  arg->result = KeyAllocationFailed;
@@ -343,7 +345,7 @@ insert_node_ensure(rbtree_insert_arg_t* arg)
343
345
  {
344
346
  dict_t* dict = arg->dict;
345
347
  dnode_t* node = arg->node;
346
-
348
+
347
349
  switch (arg->result) {
348
350
  case InsertionSucceeded:
349
351
  break;
@@ -366,7 +368,7 @@ rbtree_insert(VALUE self, VALUE key, VALUE value)
366
368
 
367
369
  dnode_init(node, TO_VAL(value));
368
370
  node->dict_key = TO_KEY(key);
369
-
371
+
370
372
  arg.dict = dict;
371
373
  arg.node = node;
372
374
  arg.result = NoNodeInserted;
@@ -418,12 +420,9 @@ rbtree_fetch(int argc, VALUE* argv, VALUE self)
418
420
  {
419
421
  dnode_t* node;
420
422
 
421
- if (argc == 0 || argc > 2) {
422
- rbtree_argc_error(argc, 1, 2);
423
- } else if (argc == 2) {
424
- if (rb_block_given_p()) {
425
- rb_warn("block supersedes default value argument");
426
- }
423
+ rbtree_check_argument_count(argc, 1, 2);
424
+ if (argc == 2 && rb_block_given_p()) {
425
+ rb_warn("block supersedes default value argument");
427
426
  }
428
427
 
429
428
  node = dict_lookup(DICT(self), TO_KEY(argv[0]));
@@ -464,9 +463,7 @@ rbtree_empty_p(VALUE self)
464
463
  VALUE
465
464
  rbtree_default(int argc, VALUE* argv, VALUE self)
466
465
  {
467
- if (argc > 1) {
468
- rbtree_argc_error(argc, 0, 1);
469
- }
466
+ rbtree_check_argument_count(argc, 0, 1);
470
467
  if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
471
468
  if (argc == 0) {
472
469
  return Qnil;
@@ -506,14 +503,14 @@ VALUE
506
503
  rbtree_set_default_proc(VALUE self, VALUE proc)
507
504
  {
508
505
  VALUE temp;
509
-
506
+
510
507
  rbtree_modify(self);
511
508
  if (NIL_P(proc)) {
512
509
  IFNONE(self) = Qnil;
513
510
  FL_UNSET(self, RBTREE_PROC_DEFAULT);
514
511
  return Qnil;
515
512
  }
516
-
513
+
517
514
  temp = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
518
515
  if (NIL_P(temp)) {
519
516
  rb_raise(rb_eTypeError,
@@ -533,16 +530,16 @@ rbtree_recursive_equal(VALUE self, VALUE other, int recursive)
533
530
  dict_t* dict2 = DICT(other);
534
531
  dnode_t* node1;
535
532
  dnode_t* node2;
536
-
533
+
537
534
  if (recursive)
538
535
  return Qtrue;
539
536
  for (node1 = dict_first(dict1), node2 = dict_first(dict2);
540
537
  node1 != NULL && node2 != NULL;
541
538
  node1 = dict_next(dict1, node1), node2 = dict_next(dict2, node2)) {
542
-
539
+
543
540
  if (!rb_equal(GET_KEY(node1), GET_KEY(node2)) ||
544
541
  !rb_equal(GET_VAL(node1), GET_VAL(node2))) {
545
-
542
+
546
543
  return Qfalse;
547
544
  }
548
545
  }
@@ -562,7 +559,7 @@ rbtree_equal(VALUE self, VALUE other)
562
559
  if (dict_count(DICT(self)) != dict_count(DICT(other)) ||
563
560
  DICT(self)->dict_compare != DICT(other)->dict_compare ||
564
561
  CMP_PROC(self) != CMP_PROC(other)) {
565
-
562
+
566
563
  return Qfalse;
567
564
  }
568
565
  #if defined(HAVE_RB_EXEC_RECURSIVE_PAIRED)
@@ -604,7 +601,7 @@ rbtree_each_body(rbtree_each_arg_t* arg)
604
601
  dnode_t* node;
605
602
  dnode_t* first_node;
606
603
  dnode_t* (*next_func)(dict_t*, dnode_t*);
607
-
604
+
608
605
  if (arg->reverse) {
609
606
  first_node = dict_last(dict);
610
607
  next_func = dict_prev;
@@ -612,12 +609,12 @@ rbtree_each_body(rbtree_each_arg_t* arg)
612
609
  first_node = dict_first(dict);
613
610
  next_func = dict_next;
614
611
  }
615
-
612
+
616
613
  ITER_LEV(self)++;
617
614
  for (node = first_node;
618
615
  node != NULL;
619
616
  node = next_func(dict, node)) {
620
-
617
+
621
618
  if (arg->func(node, arg->arg) == EACH_STOP)
622
619
  break;
623
620
  }
@@ -752,7 +749,11 @@ static void
752
749
  copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
753
750
  {
754
751
  VALUE temp = rbtree_alloc(CLASS_OF(dest));
752
+ #ifdef HAVE_RB_OBJ_HIDE
753
+ rb_obj_hide(temp);
754
+ #else
755
755
  RBASIC(temp)->klass = 0;
756
+ #endif
756
757
  DICT(temp)->dict_compare = cmp_func;
757
758
  CMP_PROC(temp) = cmp_proc;
758
759
 
@@ -763,6 +764,7 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
763
764
  DICT(dest) = t;
764
765
  }
765
766
  rbtree_free(RBTREE(temp));
767
+ RBTREE(temp) = NULL;
766
768
  rb_gc_force_recycle(temp);
767
769
 
768
770
  DICT(dest)->dict_context = RBTREE(dest);
@@ -776,7 +778,7 @@ VALUE
776
778
  rbtree_initialize_copy(VALUE self, VALUE other)
777
779
  {
778
780
  rbtree_modify(self);
779
-
781
+
780
782
  if (self == other)
781
783
  return self;
782
784
  if (!rb_obj_is_kind_of(other, CLASS_OF(self))) {
@@ -784,9 +786,9 @@ rbtree_initialize_copy(VALUE self, VALUE other)
784
786
  rb_obj_classname(other),
785
787
  rb_obj_classname(self));
786
788
  }
787
-
789
+
788
790
  copy_dict(other, self, DICT(other)->dict_compare, CMP_PROC(other));
789
-
791
+
790
792
  IFNONE(self) = IFNONE(other);
791
793
  if (FL_TEST(other, RBTREE_PROC_DEFAULT))
792
794
  FL_SET(self, RBTREE_PROC_DEFAULT);
@@ -803,7 +805,7 @@ rbtree_values_at(int argc, VALUE* argv, VALUE self)
803
805
  {
804
806
  long i;
805
807
  VALUE ary = rb_ary_new2(argc);
806
-
808
+
807
809
  for (i = 0; i < argc; i++)
808
810
  rb_ary_push(ary, rbtree_aref(self, argv[i]));
809
811
  return ary;
@@ -840,9 +842,8 @@ VALUE
840
842
  rbtree_index(VALUE self, VALUE value)
841
843
  {
842
844
  VALUE klass = rb_obj_is_kind_of(self, RBTree) ? RBTree : MultiRBTree;
843
- volatile VALUE class_name = rb_class_name(klass);
844
- rb_warn("%s#index is deprecated; use %s#key",
845
- RSTRING_PTR(class_name), RSTRING_PTR(class_name));
845
+ const char* classname = rb_class2name(klass);
846
+ rb_warn("%s#index is deprecated; use %s#key", classname, classname);
846
847
  return rbtree_key(self, value);
847
848
  }
848
849
 
@@ -938,7 +939,7 @@ static VALUE
938
939
  rbtree_remove_if(VALUE self, const int if_true)
939
940
  {
940
941
  rbtree_remove_if_arg_t arg;
941
-
942
+
942
943
  RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
943
944
  rbtree_modify(self);
944
945
  arg.self = self;
@@ -975,7 +976,7 @@ VALUE
975
976
  rbtree_reject_bang(VALUE self)
976
977
  {
977
978
  dictcount_t count;
978
-
979
+
979
980
  RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
980
981
  count = dict_count(DICT(self));
981
982
  rbtree_delete_if(self);
@@ -991,14 +992,14 @@ VALUE
991
992
  rbtree_select_bang(VALUE self)
992
993
  {
993
994
  dictcount_t count;
994
-
995
+
995
996
  RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
996
997
  count = dict_count(DICT(self));
997
998
  rbtree_keep_if(self);
998
999
  if (count == dict_count(DICT(self)))
999
1000
  return Qnil;
1000
1001
  return self;
1001
-
1002
+
1002
1003
  }
1003
1004
 
1004
1005
  /*********************************************************************/
@@ -1014,7 +1015,7 @@ select_i(dnode_t* node, void* arg_)
1014
1015
  VALUE key = GET_KEY(node);
1015
1016
  VALUE value = GET_VAL(node);
1016
1017
  rbtree_select_if_arg_t* arg = arg_;
1017
-
1018
+
1018
1019
  if (RTEST(rb_yield_values(2, key, value)) == arg->if_true) {
1019
1020
  rbtree_aset(arg->result, key, value);
1020
1021
  }
@@ -1025,7 +1026,7 @@ static VALUE
1025
1026
  rbtree_select_if(VALUE self, const int if_true)
1026
1027
  {
1027
1028
  rbtree_select_if_arg_t arg;
1028
-
1029
+
1029
1030
  RETURN_SIZED_ENUMERATOR(self, 0, NULL, rbtree_size);
1030
1031
  arg.result = rbtree_alloc(CLASS_OF(self));
1031
1032
  arg.if_true = if_true;
@@ -1064,7 +1065,7 @@ rbtree_shift_pop(VALUE self, const int shift)
1064
1065
 
1065
1066
  if (dict_isempty(dict))
1066
1067
  return rb_funcall(self, id_default, 1, Qnil);
1067
-
1068
+
1068
1069
  if (shift)
1069
1070
  node = dict_last(dict);
1070
1071
  else
@@ -1146,7 +1147,7 @@ rbtree_update(VALUE self, VALUE other)
1146
1147
  rb_obj_classname(other),
1147
1148
  rb_obj_classname(self));
1148
1149
  }
1149
-
1150
+
1150
1151
  if (rb_block_given_p())
1151
1152
  rbtree_for_each(other, update_block_i, (void*)self);
1152
1153
  else
@@ -1163,6 +1164,14 @@ rbtree_merge(VALUE self, VALUE other)
1163
1164
  return rbtree_update(rb_obj_dup(self), other);
1164
1165
  }
1165
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
+
1166
1175
  /*
1167
1176
  *
1168
1177
  */
@@ -1170,15 +1179,17 @@ VALUE
1170
1179
  rbtree_flatten(int argc, VALUE* argv, VALUE self)
1171
1180
  {
1172
1181
  VALUE ary;
1173
- VALUE level;
1174
-
1175
- ary = rbtree_to_a(self);
1176
- if (argc == 0) {
1177
- argc = 1;
1178
- level = INT2FIX(1);
1179
- argv = &level;
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
+ }
1180
1192
  }
1181
- rb_funcall2(ary, id_flatten_bang, argc, argv);
1182
1193
  return ary;
1183
1194
  }
1184
1195
 
@@ -1286,10 +1297,10 @@ rbtree_to_hash(VALUE self)
1286
1297
  VALUE hash;
1287
1298
  if (!rb_obj_is_kind_of(self, RBTree))
1288
1299
  rb_raise(rb_eTypeError, "can't convert MultiRBTree to Hash");
1289
-
1300
+
1290
1301
  hash = rb_hash_new();
1291
1302
  rbtree_for_each(self, to_hash_i, (void*)hash);
1292
- RHASH_IFNONE(hash) = IFNONE(self);
1303
+ RHASH_SET_IFNONE(hash, IFNONE(self));
1293
1304
  if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1294
1305
  FL_SET(hash, HASH_PROC_DEFAULT);
1295
1306
  OBJ_INFECT(hash, self);
@@ -1308,10 +1319,10 @@ rbtree_to_rbtree(VALUE self)
1308
1319
  static VALUE
1309
1320
  rbtree_begin_inspect(VALUE self)
1310
1321
  {
1311
- volatile VALUE class_name = rb_class_name(CLASS_OF(self));
1312
- VALUE str = rb_str_new(NULL, RSTRING_LEN(class_name) + 4);
1313
- sprintf(RSTRING_PTR(str), "#<%s: ", RSTRING_PTR(class_name));
1314
- return str;
1322
+ VALUE result = rb_str_new2("#<");
1323
+ rb_str_cat2(result, rb_obj_classname(self));
1324
+ rb_str_cat2(result, ": ");
1325
+ return result;
1315
1326
  }
1316
1327
 
1317
1328
  static each_return_t
@@ -1342,7 +1353,7 @@ static VALUE
1342
1353
  inspect_rbtree(VALUE self, VALUE result)
1343
1354
  {
1344
1355
  VALUE str;
1345
-
1356
+
1346
1357
  rb_str_cat2(result, "{");
1347
1358
  RSTRING_PTR(result)[0] = '-';
1348
1359
  rbtree_for_each(self, inspect_i, (void*)result);
@@ -1353,7 +1364,7 @@ inspect_rbtree(VALUE self, VALUE result)
1353
1364
  rb_str_cat2(result, ", default=");
1354
1365
  rb_str_append(result, str);
1355
1366
  OBJ_INFECT(result, str);
1356
-
1367
+
1357
1368
  str = rb_inspect(CMP_PROC(self));
1358
1369
  rb_str_cat2(result, ", cmp_proc=");
1359
1370
  rb_str_append(result, str);
@@ -1480,24 +1491,24 @@ rbtree_bound_body(rbtree_bound_arg_t* arg)
1480
1491
  static VALUE
1481
1492
  rbtree_bound_size(VALUE self, VALUE args)
1482
1493
  {
1483
- VALUE key1 = RARRAY_PTR(args)[0];
1484
- VALUE key2 = RARRAY_PTR(args)[RARRAY_LEN(args) - 1];
1494
+ VALUE key1 = RARRAY_AREF(args, 0);
1495
+ VALUE key2 = RARRAY_AREF(args, RARRAY_LEN(args) - 1);
1485
1496
  dnode_t* lower_node = dict_lower_bound(DICT(self), TO_KEY(key1));
1486
1497
  dnode_t* upper_node = dict_upper_bound(DICT(self), TO_KEY(key2));
1487
1498
  dictcount_t count = 0;
1488
1499
  dnode_t* node;
1489
-
1500
+
1490
1501
  if (lower_node == NULL || upper_node == NULL ||
1491
1502
  DICT(self)->dict_compare(dnode_getkey(lower_node),
1492
1503
  dnode_getkey(upper_node),
1493
1504
  DICT(self)->dict_context) > 0) {
1494
1505
  return INT2FIX(0);
1495
1506
  }
1496
-
1507
+
1497
1508
  for (node = lower_node;
1498
1509
  node != NULL;
1499
1510
  node = dict_next(DICT(self), node)) {
1500
-
1511
+
1501
1512
  count++;
1502
1513
  if (node == upper_node) {
1503
1514
  break;
@@ -1524,7 +1535,7 @@ rbtree_bound_size(VALUE self, VALUE args)
1524
1535
  * mrbtree = MultiRBTree["az", 10, "ba", 20, "ba", 30, "bz", 40]
1525
1536
  * mrbtree.bound("ba").to_a # => [["ba", 20], ["ba", 30]]
1526
1537
  * mrbtree.bound("b", "c").to_a # => [["ba", 20], ["ba", 30], ["bz", 40]]
1527
- *
1538
+ *
1528
1539
  * # the lower bound ("ba") exceeds the upper bound ("az")
1529
1540
  * mrbtree.bound("b").to_a # => []
1530
1541
  */
@@ -1535,17 +1546,15 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
1535
1546
  dnode_t* lower_node;
1536
1547
  dnode_t* upper_node;
1537
1548
  VALUE result;
1538
-
1539
- if (argc == 0 || argc > 2) {
1540
- rbtree_argc_error(argc, 1, 2);
1541
- }
1542
-
1549
+
1550
+ rbtree_check_argument_count(argc, 1, 2);
1551
+
1543
1552
  RETURN_SIZED_ENUMERATOR(self, argc, argv, rbtree_bound_size);
1544
-
1553
+
1545
1554
  lower_node = dict_lower_bound(dict, TO_KEY(argv[0]));
1546
1555
  upper_node = dict_upper_bound(dict, TO_KEY(argv[argc - 1]));
1547
1556
  result = rb_block_given_p() ? self : rb_ary_new();
1548
-
1557
+
1549
1558
  if (lower_node == NULL || upper_node == NULL ||
1550
1559
  DICT(self)->dict_compare(dnode_getkey(lower_node),
1551
1560
  dnode_getkey(upper_node),
@@ -1570,7 +1579,7 @@ rbtree_first_last(VALUE self, const int first)
1570
1579
 
1571
1580
  if (dict_isempty(dict))
1572
1581
  return rb_funcall(self, id_default, 1, Qnil);
1573
-
1582
+
1574
1583
  if (first)
1575
1584
  node = dict_first(dict);
1576
1585
  else
@@ -1620,7 +1629,7 @@ rbtree_last(VALUE self)
1620
1629
  * rbtree = RBTree["a", 10, "b", 20]
1621
1630
  * rbtree.readjust {|a, b| b <=> a }
1622
1631
  * rbtree.first # => ["b", 20]
1623
- *
1632
+ *
1624
1633
  * rbtree.readjust(nil)
1625
1634
  * rbtree.first # => ["a", 10]
1626
1635
  */
@@ -1629,21 +1638,20 @@ rbtree_readjust(int argc, VALUE* argv, VALUE self)
1629
1638
  {
1630
1639
  dict_comp_t cmp_func = NULL;
1631
1640
  VALUE cmp_proc = Qnil;
1632
-
1641
+
1633
1642
  rbtree_modify(self);
1634
1643
 
1635
1644
  if (rb_block_given_p()) {
1636
- if (argc != 0) {
1637
- rbtree_argc_error(argc, 0, 0);
1638
- }
1645
+ rbtree_check_argument_count(argc, 0, 0);
1639
1646
  cmp_func = rbtree_user_cmp;
1640
1647
  cmp_proc = rb_block_proc();
1641
1648
  rbtree_check_proc_arity(cmp_proc, 2);
1642
1649
  } else {
1650
+ rbtree_check_argument_count(argc, 0, 1);
1643
1651
  if (argc == 0) {
1644
1652
  cmp_func = DICT(self)->dict_compare;
1645
1653
  cmp_proc = CMP_PROC(self);
1646
- } else if (argc == 1) {
1654
+ } else {
1647
1655
  if (NIL_P(argv[0])) {
1648
1656
  cmp_func = rbtree_cmp;
1649
1657
  cmp_proc = Qnil;
@@ -1658,8 +1666,6 @@ rbtree_readjust(int argc, VALUE* argv, VALUE self)
1658
1666
  cmp_proc = proc;
1659
1667
  rbtree_check_proc_arity(cmp_proc, 2);
1660
1668
  }
1661
- } else {
1662
- rbtree_argc_error(argc, 0, 1);
1663
1669
  }
1664
1670
  }
1665
1671
 
@@ -1724,7 +1730,7 @@ pp_pair(VALUE nil, pp_pair_arg_t* pair_arg)
1724
1730
  group_args[1] = INT2FIX(1);
1725
1731
  group_args[2] = rb_str_new(NULL, 0);
1726
1732
  group_args[3] = rb_str_new(NULL, 0);
1727
-
1733
+
1728
1734
  rb_funcall(pp, id_pp, 1, GET_KEY(pair_arg->node));
1729
1735
  rb_funcall(pp, id_text, 1, rb_str_new2("=>"));
1730
1736
  return rb_iterate(pp_group, (VALUE)&group_args, pp_value, (VALUE)pair_arg);
@@ -1741,21 +1747,21 @@ pp_each_pair_i(dnode_t* node, void* each_pair_arg_)
1741
1747
  pp_each_pair_arg_t* each_pair_arg = (pp_each_pair_arg_t*)each_pair_arg_;
1742
1748
  VALUE group_args[4];
1743
1749
  pp_pair_arg_t pair_arg;
1744
-
1750
+
1745
1751
  if (each_pair_arg->first) {
1746
1752
  each_pair_arg->first = 0;
1747
1753
  } else {
1748
1754
  rb_funcall(each_pair_arg->pp, id_comma_breakable, 0);
1749
1755
  }
1750
-
1756
+
1751
1757
  group_args[0] = each_pair_arg->pp;
1752
1758
  group_args[1] = INT2FIX(0);
1753
1759
  group_args[2] = rb_str_new(NULL, 0);
1754
1760
  group_args[3] = rb_str_new(NULL, 0);
1755
-
1761
+
1756
1762
  pair_arg.pp = each_pair_arg->pp;
1757
1763
  pair_arg.node = node;
1758
-
1764
+
1759
1765
  rb_iterate(pp_group, (VALUE)&group_args, pp_pair, (VALUE)&pair_arg);
1760
1766
  return EACH_NEXT;
1761
1767
  }
@@ -1779,13 +1785,13 @@ pp_rbtree(VALUE nil, pp_rbtree_arg_t* rbtree_arg)
1779
1785
  {
1780
1786
  VALUE pp = rbtree_arg->pp;
1781
1787
  VALUE rbtree = rbtree_arg->rbtree;
1782
-
1788
+
1783
1789
  VALUE group_args[4];
1784
1790
  group_args[0] = pp;
1785
1791
  group_args[1] = INT2FIX(1);
1786
1792
  group_args[2] = rb_str_new2("{");
1787
1793
  group_args[3] = rb_str_new2("}");
1788
-
1794
+
1789
1795
  rb_funcall(pp, id_text, 1, rb_str_new2(": "));
1790
1796
  rb_iterate(pp_group, (VALUE)&group_args, pp_each_pair, (VALUE)rbtree_arg);
1791
1797
  rb_funcall(pp, id_comma_breakable, 0);
@@ -1828,14 +1834,6 @@ rbtree_pretty_print_cycle(VALUE self, VALUE pp)
1828
1834
 
1829
1835
  /*********************************************************************/
1830
1836
 
1831
- static each_return_t
1832
- to_flat_ary_i(dnode_t* node, void* ary)
1833
- {
1834
- rb_ary_push((VALUE)ary, GET_KEY(node));
1835
- rb_ary_push((VALUE)ary, GET_VAL(node));
1836
- return EACH_NEXT;
1837
- }
1838
-
1839
1837
  /* :nodoc:
1840
1838
  *
1841
1839
  */
@@ -1844,19 +1842,22 @@ rbtree_dump(VALUE self, VALUE limit)
1844
1842
  {
1845
1843
  VALUE ary;
1846
1844
  VALUE result;
1847
-
1845
+
1848
1846
  if (FL_TEST(self, RBTREE_PROC_DEFAULT))
1849
1847
  rb_raise(rb_eTypeError, "can't dump rbtree with default proc");
1850
1848
  if (CMP_PROC(self) != Qnil)
1851
1849
  rb_raise(rb_eTypeError, "can't dump rbtree with comparison proc");
1852
-
1850
+
1853
1851
  ary = rb_ary_new2(dict_count(DICT(self)) * 2 + 1);
1854
1852
  rbtree_for_each(self, to_flat_ary_i, (void*)ary);
1855
1853
  rb_ary_push(ary, IFNONE(self));
1856
1854
 
1857
- result = 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
1858
1859
  rb_ary_clear(ary);
1859
- rb_gc_force_recycle(ary);
1860
+ #endif
1860
1861
  return result;
1861
1862
  }
1862
1863
 
@@ -1868,16 +1869,18 @@ rbtree_s_load(VALUE klass, VALUE str)
1868
1869
  {
1869
1870
  VALUE rbtree = rbtree_alloc(klass);
1870
1871
  VALUE ary = rb_marshal_load(str);
1871
- VALUE* ptr = RARRAY_PTR(ary);
1872
1872
  long len = RARRAY_LEN(ary) - 1;
1873
1873
  long i;
1874
-
1874
+
1875
1875
  for (i = 0; i < len; i += 2)
1876
- rbtree_aset(rbtree, ptr[i], ptr[i + 1]);
1877
- IFNONE(rbtree) = ptr[len];
1878
-
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
1879
1882
  rb_ary_clear(ary);
1880
- rb_gc_force_recycle(ary);
1883
+ #endif
1881
1884
  return rbtree;
1882
1885
  }
1883
1886
 
@@ -1894,7 +1897,13 @@ rbtree_s_load(VALUE klass, VALUE str)
1894
1897
  */
1895
1898
  void Init_rbtree()
1896
1899
  {
1897
- MultiRBTree = rb_define_class("MultiRBTree", rb_cData);
1900
+ MultiRBTree = rb_define_class("MultiRBTree",
1901
+ #ifdef HAVE_RB_CDATA
1902
+ rb_cData
1903
+ #else
1904
+ rb_cObject
1905
+ #endif
1906
+ );
1898
1907
  RBTree = rb_define_class("RBTree", MultiRBTree);
1899
1908
 
1900
1909
  rb_include_module(MultiRBTree, rb_mEnumerable);
@@ -1974,7 +1983,7 @@ void Init_rbtree()
1974
1983
 
1975
1984
  rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
1976
1985
  rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
1977
-
1986
+
1978
1987
  id_cmp = rb_intern("<=>");
1979
1988
  id_call = rb_intern("call");
1980
1989
  id_default = rb_intern("default");
data/test.rb CHANGED
@@ -11,6 +11,10 @@ class RBTreeTest < Test::Unit::TestCase
11
11
  @rbtree = RBTree[*%w(b B d D a A c C)]
12
12
  end
13
13
 
14
+ def have_enumerator?
15
+ defined?(Enumerable::Enumerator) or defined?(Enumerator)
16
+ end
17
+
14
18
  def test_new
15
19
  assert_nothing_raised {
16
20
  RBTree.new
@@ -250,12 +254,6 @@ class RBTreeTest < Test::Unit::TestCase
250
254
  b[1] = b
251
255
  assert_equal(a, b)
252
256
  end
253
-
254
- # a = RBTree.new
255
- # a[1] = a
256
- # b = RBTree.new
257
- # b[1] = a
258
- # assert_not_equal(a, b)
259
257
  end
260
258
 
261
259
  def test_fetch
@@ -304,7 +302,7 @@ class RBTreeTest < Test::Unit::TestCase
304
302
  }
305
303
  assert_equal(4, @rbtree.size)
306
304
 
307
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
305
+ if have_enumerator?
308
306
  enumerator = @rbtree.each
309
307
  assert_equal(%w(a A b B c C d D), enumerator.to_a.flatten)
310
308
  end
@@ -329,7 +327,7 @@ class RBTreeTest < Test::Unit::TestCase
329
327
  }
330
328
  assert_equal(4, @rbtree.size)
331
329
 
332
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
330
+ if have_enumerator?
333
331
  enumerator = @rbtree.each_key
334
332
  assert_equal(%w(a b c d), enumerator.to_a.flatten)
335
333
  end
@@ -354,7 +352,7 @@ class RBTreeTest < Test::Unit::TestCase
354
352
  }
355
353
  assert_equal(4, @rbtree.size)
356
354
 
357
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
355
+ if have_enumerator?
358
356
  enumerator = @rbtree.each_value
359
357
  assert_equal(%w(A B C D), enumerator.to_a.flatten)
360
358
  end
@@ -428,7 +426,7 @@ class RBTreeTest < Test::Unit::TestCase
428
426
  }
429
427
  assert_equal(0, @rbtree.size)
430
428
 
431
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
429
+ if have_enumerator?
432
430
  rbtree = RBTree[*%w(b B d D a A c C)]
433
431
  rbtree.delete_if.with_index {|(key, val), i| i < 2 }
434
432
  assert_equal(RBTree[*%w(c C d D)], rbtree)
@@ -440,7 +438,7 @@ class RBTreeTest < Test::Unit::TestCase
440
438
  assert_same(@rbtree, result)
441
439
  assert_equal(RBTree[*%w(a A b B)], @rbtree)
442
440
 
443
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
441
+ if have_enumerator?
444
442
  rbtree = RBTree[*%w(b B d D a A c C)]
445
443
  rbtree.keep_if.with_index {|(key, val), i| i < 2 }
446
444
  assert_equal(RBTree[*%w(a A b B)], rbtree)
@@ -456,7 +454,7 @@ class RBTreeTest < Test::Unit::TestCase
456
454
  assert_same(@rbtree, result)
457
455
  assert_equal(RBTree[*%w(c C d D)], result)
458
456
 
459
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
457
+ if have_enumerator?
460
458
  rbtree = RBTree[*%w(b B d D a A c C)]
461
459
  rbtree.reject!.with_index {|(key, val), i| i < 2 }
462
460
  assert_equal(RBTree[*%w(c C d D)], rbtree)
@@ -472,7 +470,7 @@ class RBTreeTest < Test::Unit::TestCase
472
470
  assert_equal(RBTree[*%w(c C d D)], result)
473
471
  assert_equal(4, @rbtree.size)
474
472
 
475
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
473
+ if have_enumerator?
476
474
  result = @rbtree.reject.with_index {|(key, val), i| i < 2 }
477
475
  assert_equal(RBTree[*%w(c C d D)], result)
478
476
  end
@@ -487,7 +485,7 @@ class RBTreeTest < Test::Unit::TestCase
487
485
  assert_same(@rbtree, result)
488
486
  assert_equal(RBTree[*%w(a A b B)], result)
489
487
 
490
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
488
+ if have_enumerator?
491
489
  rbtree = RBTree[*%w(b B d D a A c C)]
492
490
  rbtree.select!.with_index {|(key, val), i| i < 2 }
493
491
  assert_equal(RBTree[*%w(a A b B)], rbtree)
@@ -503,7 +501,7 @@ class RBTreeTest < Test::Unit::TestCase
503
501
  assert_equal(RBTree[*%w(a A b B)], result)
504
502
  assert_raises(ArgumentError) { @rbtree.select("c") }
505
503
 
506
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
504
+ if have_enumerator?
507
505
  result = @rbtree.select.with_index {|(key, val), i| i < 2 }
508
506
  assert_equal(RBTree[*%w(a A b B)], result)
509
507
  end
@@ -554,13 +552,13 @@ class RBTreeTest < Test::Unit::TestCase
554
552
  rbtree[["a"]] = ["A"]
555
553
  rbtree[[["b"]]] = [["B"]]
556
554
  assert_equal([["a"], ["A"], [["b"]], [["B"]]], rbtree.flatten)
557
- assert_equal([[["a"], ["A"]], [[["b"]], [["B"]]]], rbtree.flatten(0))
555
+ assert_equal([["a"], ["A"], [["b"]], [["B"]]], rbtree.flatten(0))
558
556
  assert_equal([["a"], ["A"], [["b"]], [["B"]]], rbtree.flatten(1))
559
557
  assert_equal(["a", "A", ["b"], ["B"]], rbtree.flatten(2))
560
558
  assert_equal(["a", "A", "b", "B"], rbtree.flatten(3))
561
559
 
562
560
  assert_raises(TypeError) { @rbtree.flatten("e") }
563
- assert_raises(ArgumentError) { @rbtree.flatten(2, 2) }
561
+ assert_raises(ArgumentError) { @rbtree.flatten(1, 2) }
564
562
  end
565
563
  end
566
564
 
@@ -622,7 +620,7 @@ class RBTreeTest < Test::Unit::TestCase
622
620
  tree, default, cmp_proc = match.to_a[1..-1]
623
621
  assert_equal(%({"a"=>"A", "b"=>"B", "c"=>"C", "d"=>"D"}), tree)
624
622
  assert_equal(%("e"), default)
625
- assert_match(/#<Proc:\w+(@#{__FILE__}:\d+)?>/o, cmp_proc)
623
+ assert_match(/#<Proc:\w+([@ ]#{__FILE__}:\d+)?>/o, cmp_proc)
626
624
 
627
625
  rbtree = RBTree.new
628
626
  assert_match(re, rbtree.send(method))
@@ -669,7 +667,7 @@ class RBTreeTest < Test::Unit::TestCase
669
667
  assert_equal([], rbtree.bound("Y", "Z").to_a)
670
668
  assert_equal([], rbtree.bound("f", "g").to_a)
671
669
  assert_equal([], rbtree.bound("f", "Z").to_a)
672
-
670
+
673
671
  if defined?(Enumerator) and Enumerator.method_defined?(:size)
674
672
  assert_equal(2, rbtree.bound("a", "c").size)
675
673
  assert_equal(1, rbtree.bound("a").size)
@@ -821,7 +819,7 @@ class RBTreeTest < Test::Unit::TestCase
821
819
  @rbtree.reverse_each { |key, val| result.push([key, val]) }
822
820
  assert_equal(%w(d D c C b B a A), result.flatten)
823
821
 
824
- if defined?(Enumerable::Enumerator) or defined?(Enumerator)
822
+ if have_enumerator?
825
823
  enumerator = @rbtree.reverse_each
826
824
  assert_equal(%w(d D c C b B a A), enumerator.to_a.flatten)
827
825
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbtree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - OZAWA Takuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-03-29 00:00:00.000000000 Z
11
+ date: 2022-02-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  A RBTree is a sorted associative collection that is implemented with a
@@ -38,29 +38,27 @@ licenses:
38
38
  metadata: {}
39
39
  post_install_message:
40
40
  rdoc_options:
41
- - --title
41
+ - "--title"
42
42
  - Ruby/RBTree
43
- - --main
43
+ - "--main"
44
44
  - README
45
- - --exclude
46
- - \A(?!README|rbtree\.c).*\z
45
+ - "--exclude"
46
+ - "\\A(?!README|rbtree\\.c).*\\z"
47
47
  require_paths:
48
48
  - lib
49
49
  required_ruby_version: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - '>='
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.8.6
54
54
  required_rubygems_version: !ruby/object:Gem::Requirement
55
55
  requirements:
56
- - - '>='
56
+ - - ">="
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
59
  requirements: []
60
- rubyforge_project: rbtree
61
- rubygems_version: 2.0.0
60
+ rubygems_version: 3.4.0.dev
62
61
  signing_key:
63
62
  specification_version: 4
64
63
  summary: A sorted associative collection.
65
- test_files:
66
- - test.rb
64
+ test_files: []