rbtree 0.4.1 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|