rbtree 0.4.1 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README +6 -16
- data/dict.c +309 -4
- data/dict.h +3 -3
- data/extconf.rb +4 -1
- data/rbtree.c +143 -134
- data/test.rb +18 -20
- metadata +10 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d5bc8dc390afc34242d6cd951136f2d86c9a0bafc809ed93d39d0fdf6c8ea9c0
|
4
|
+
data.tar.gz: '059f888a97995d9bc64edcdafb504817b570e07df03c3385e5c5fe3e8bbc8f72'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
61
|
-
*
|
60
|
+
=== 0.4.5
|
61
|
+
* Support Ruby 3.2.0-dev (development branch).
|
62
62
|
|
63
|
-
=== 0.4.
|
63
|
+
=== 0.4.4
|
64
|
+
* Remove the rb_safe_level warning on Ruby 2.7.
|
64
65
|
|
65
|
-
|
66
|
-
*
|
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.
|
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
|
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.
|
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.
|
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
|
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
|
27
|
-
#define
|
26
|
+
#ifndef RARRAY_AREF
|
27
|
+
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
28
28
|
#endif
|
29
|
-
|
30
|
-
#
|
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
|
-
|
104
|
-
{
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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,
|
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(
|
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(
|
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,
|
264
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
|
260
265
|
break;
|
261
266
|
case 2:
|
262
|
-
rbtree_aset(rbtree,
|
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
|
-
|
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
|
-
|
301
|
-
|
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
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1174
|
-
|
1175
|
-
ary =
|
1176
|
-
|
1177
|
-
|
1178
|
-
level =
|
1179
|
-
|
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
|
-
|
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
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
return
|
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 =
|
1484
|
-
VALUE key2 =
|
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
|
-
|
1540
|
-
|
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
|
-
|
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
|
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,
|
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
|
-
|
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,
|
1877
|
-
IFNONE(rbtree) =
|
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
|
-
|
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",
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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([[
|
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(
|
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+(
|
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
|
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.
|
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:
|
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
|
-
-
|
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
|
-
|
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: []
|