rbtree 0.4.1 → 0.4.2
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 +4 -4
- data/README +3 -6
- data/dict.c +309 -4
- data/dict.h +3 -3
- data/extconf.rb +2 -1
- data/rbtree.c +74 -73
- data/test.rb +17 -19
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35a51532a317785f995191b86990fd197d3a08d7
|
4
|
+
data.tar.gz: fc58dc292ed9763c6b8731ca2998c6affe591007
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75b7c55bd29b9341ae5969742855aa15893af18574d7c5ff734ea8e52b3e25f1ccb290c72bb27b58ae8e61db533b2d04b15cab80ff3e64239aee02f63591be35
|
7
|
+
data.tar.gz: d1b1c0def86af19fd6b6a2bdcf7e2147b3f0e1ea340276d283884ee50b7fe3bd91c5f55e7495dcda3652fd9443b55d930044ce007ab707dc196cca3f45834011
|
data/README
CHANGED
@@ -57,6 +57,9 @@ Run the following command.
|
|
57
57
|
$ sudo gem install rbtree
|
58
58
|
|
59
59
|
== Changes
|
60
|
+
=== 0.4.2
|
61
|
+
* Fixed build failure with Ruby 2.1.0.
|
62
|
+
|
60
63
|
=== 0.4.1
|
61
64
|
* Fixed a crash that could be triggered when GC happened.
|
62
65
|
|
@@ -78,9 +81,3 @@ dict.c and dict.h are modified copies that are originally in Kazlib
|
|
78
81
|
1.20 written by Kaz Kylheku. Its license is similar to the MIT
|
79
82
|
license. See dict.c and dict.h for the details. The web page of Kazlib
|
80
83
|
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,11 @@ 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')
|
12
13
|
if Hash.method_defined?(:flatten)
|
13
14
|
$defs << '-DHAVE_HASH_FLATTEN'
|
14
15
|
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
|
|
@@ -181,7 +184,7 @@ static VALUE
|
|
181
184
|
rbtree_alloc(VALUE klass)
|
182
185
|
{
|
183
186
|
dict_t* dict;
|
184
|
-
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free,
|
187
|
+
VALUE rbtree = Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, NULL);
|
185
188
|
RBTREE(rbtree) = ALLOC(rbtree_t);
|
186
189
|
MEMZERO(RBTREE(rbtree), rbtree_t, 1);
|
187
190
|
|
@@ -248,18 +251,18 @@ rbtree_s_create(int argc, VALUE* argv, VALUE klass)
|
|
248
251
|
if (!NIL_P(temp)) {
|
249
252
|
rbtree = rbtree_alloc(klass);
|
250
253
|
for (i = 0; i < RARRAY_LEN(temp); i++) {
|
251
|
-
VALUE v = rb_check_array_type(
|
254
|
+
VALUE v = rb_check_array_type(RARRAY_AREF(temp, i));
|
252
255
|
if (NIL_P(v)) {
|
253
256
|
rb_warn("wrong element type %s at %ld (expected Array)",
|
254
|
-
rb_obj_classname(
|
257
|
+
rb_obj_classname(RARRAY_AREF(temp, i)), i);
|
255
258
|
continue;
|
256
259
|
}
|
257
260
|
switch(RARRAY_LEN(v)) {
|
258
261
|
case 1:
|
259
|
-
rbtree_aset(rbtree,
|
262
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), Qnil);
|
260
263
|
break;
|
261
264
|
case 2:
|
262
|
-
rbtree_aset(rbtree,
|
265
|
+
rbtree_aset(rbtree, RARRAY_AREF(v, 0), RARRAY_AREF(v, 1));
|
263
266
|
break;
|
264
267
|
default:
|
265
268
|
rb_warn("invalid number of elements (%ld for 1..2)",
|
@@ -289,17 +292,14 @@ rbtree_initialize(int argc, VALUE* argv, VALUE self)
|
|
289
292
|
|
290
293
|
if (rb_block_given_p()) {
|
291
294
|
VALUE proc;
|
292
|
-
|
293
|
-
rbtree_argc_error(argc, 0, 0);
|
294
|
-
}
|
295
|
+
rbtree_check_argument_count(argc, 0, 0);
|
295
296
|
proc = rb_block_proc();
|
296
297
|
rbtree_check_proc_arity(proc, 2);
|
297
298
|
IFNONE(self) = proc;
|
298
299
|
FL_SET(self, RBTREE_PROC_DEFAULT);
|
299
300
|
} else {
|
300
|
-
|
301
|
-
|
302
|
-
} else if (argc == 1) {
|
301
|
+
rbtree_check_argument_count(argc, 0, 1);
|
302
|
+
if (argc == 1) {
|
303
303
|
IFNONE(self) = argv[0];
|
304
304
|
}
|
305
305
|
}
|
@@ -418,12 +418,9 @@ rbtree_fetch(int argc, VALUE* argv, VALUE self)
|
|
418
418
|
{
|
419
419
|
dnode_t* node;
|
420
420
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
if (rb_block_given_p()) {
|
425
|
-
rb_warn("block supersedes default value argument");
|
426
|
-
}
|
421
|
+
rbtree_check_argument_count(argc, 1, 2);
|
422
|
+
if (argc == 2 && rb_block_given_p()) {
|
423
|
+
rb_warn("block supersedes default value argument");
|
427
424
|
}
|
428
425
|
|
429
426
|
node = dict_lookup(DICT(self), TO_KEY(argv[0]));
|
@@ -464,9 +461,7 @@ rbtree_empty_p(VALUE self)
|
|
464
461
|
VALUE
|
465
462
|
rbtree_default(int argc, VALUE* argv, VALUE self)
|
466
463
|
{
|
467
|
-
|
468
|
-
rbtree_argc_error(argc, 0, 1);
|
469
|
-
}
|
464
|
+
rbtree_check_argument_count(argc, 0, 1);
|
470
465
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT)) {
|
471
466
|
if (argc == 0) {
|
472
467
|
return Qnil;
|
@@ -752,7 +747,11 @@ static void
|
|
752
747
|
copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
|
753
748
|
{
|
754
749
|
VALUE temp = rbtree_alloc(CLASS_OF(dest));
|
750
|
+
#ifdef HAVE_RB_OBJ_HIDE
|
751
|
+
rb_obj_hide(temp);
|
752
|
+
#else
|
755
753
|
RBASIC(temp)->klass = 0;
|
754
|
+
#endif
|
756
755
|
DICT(temp)->dict_compare = cmp_func;
|
757
756
|
CMP_PROC(temp) = cmp_proc;
|
758
757
|
|
@@ -763,6 +762,7 @@ copy_dict(VALUE src, VALUE dest, dict_comp_t cmp_func, VALUE cmp_proc)
|
|
763
762
|
DICT(dest) = t;
|
764
763
|
}
|
765
764
|
rbtree_free(RBTREE(temp));
|
765
|
+
RBTREE(temp) = NULL;
|
766
766
|
rb_gc_force_recycle(temp);
|
767
767
|
|
768
768
|
DICT(dest)->dict_context = RBTREE(dest);
|
@@ -840,9 +840,8 @@ VALUE
|
|
840
840
|
rbtree_index(VALUE self, VALUE value)
|
841
841
|
{
|
842
842
|
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));
|
843
|
+
const char* classname = rb_class2name(klass);
|
844
|
+
rb_warn("%s#index is deprecated; use %s#key", classname, classname);
|
846
845
|
return rbtree_key(self, value);
|
847
846
|
}
|
848
847
|
|
@@ -1163,6 +1162,14 @@ rbtree_merge(VALUE self, VALUE other)
|
|
1163
1162
|
return rbtree_update(rb_obj_dup(self), other);
|
1164
1163
|
}
|
1165
1164
|
|
1165
|
+
static each_return_t
|
1166
|
+
to_flat_ary_i(dnode_t* node, void* ary)
|
1167
|
+
{
|
1168
|
+
rb_ary_push((VALUE)ary, GET_KEY(node));
|
1169
|
+
rb_ary_push((VALUE)ary, GET_VAL(node));
|
1170
|
+
return EACH_NEXT;
|
1171
|
+
}
|
1172
|
+
|
1166
1173
|
/*
|
1167
1174
|
*
|
1168
1175
|
*/
|
@@ -1170,15 +1177,17 @@ VALUE
|
|
1170
1177
|
rbtree_flatten(int argc, VALUE* argv, VALUE self)
|
1171
1178
|
{
|
1172
1179
|
VALUE ary;
|
1173
|
-
|
1174
|
-
|
1175
|
-
ary =
|
1176
|
-
|
1177
|
-
|
1178
|
-
level =
|
1179
|
-
|
1180
|
+
|
1181
|
+
rbtree_check_argument_count(argc, 0, 1);
|
1182
|
+
ary = rb_ary_new2(dict_count(DICT(self)) * 2);
|
1183
|
+
rbtree_for_each(self, to_flat_ary_i, (void*)ary);
|
1184
|
+
if (argc == 1) {
|
1185
|
+
const int level = NUM2INT(argv[0]) - 1;
|
1186
|
+
if (level > 0) {
|
1187
|
+
argv[0] = INT2FIX(level);
|
1188
|
+
rb_funcall2(ary, id_flatten_bang, argc, argv);
|
1189
|
+
}
|
1180
1190
|
}
|
1181
|
-
rb_funcall2(ary, id_flatten_bang, argc, argv);
|
1182
1191
|
return ary;
|
1183
1192
|
}
|
1184
1193
|
|
@@ -1289,7 +1298,7 @@ rbtree_to_hash(VALUE self)
|
|
1289
1298
|
|
1290
1299
|
hash = rb_hash_new();
|
1291
1300
|
rbtree_for_each(self, to_hash_i, (void*)hash);
|
1292
|
-
|
1301
|
+
RHASH_SET_IFNONE(hash, IFNONE(self));
|
1293
1302
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
1294
1303
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
1295
1304
|
OBJ_INFECT(hash, self);
|
@@ -1308,10 +1317,10 @@ rbtree_to_rbtree(VALUE self)
|
|
1308
1317
|
static VALUE
|
1309
1318
|
rbtree_begin_inspect(VALUE self)
|
1310
1319
|
{
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
return
|
1320
|
+
VALUE result = rb_str_new2("#<");
|
1321
|
+
rb_str_cat2(result, rb_obj_classname(self));
|
1322
|
+
rb_str_cat2(result, ": ");
|
1323
|
+
return result;
|
1315
1324
|
}
|
1316
1325
|
|
1317
1326
|
static each_return_t
|
@@ -1480,8 +1489,8 @@ rbtree_bound_body(rbtree_bound_arg_t* arg)
|
|
1480
1489
|
static VALUE
|
1481
1490
|
rbtree_bound_size(VALUE self, VALUE args)
|
1482
1491
|
{
|
1483
|
-
VALUE key1 =
|
1484
|
-
VALUE key2 =
|
1492
|
+
VALUE key1 = RARRAY_AREF(args, 0);
|
1493
|
+
VALUE key2 = RARRAY_AREF(args, RARRAY_LEN(args) - 1);
|
1485
1494
|
dnode_t* lower_node = dict_lower_bound(DICT(self), TO_KEY(key1));
|
1486
1495
|
dnode_t* upper_node = dict_upper_bound(DICT(self), TO_KEY(key2));
|
1487
1496
|
dictcount_t count = 0;
|
@@ -1536,9 +1545,7 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
|
|
1536
1545
|
dnode_t* upper_node;
|
1537
1546
|
VALUE result;
|
1538
1547
|
|
1539
|
-
|
1540
|
-
rbtree_argc_error(argc, 1, 2);
|
1541
|
-
}
|
1548
|
+
rbtree_check_argument_count(argc, 1, 2);
|
1542
1549
|
|
1543
1550
|
RETURN_SIZED_ENUMERATOR(self, argc, argv, rbtree_bound_size);
|
1544
1551
|
|
@@ -1633,17 +1640,16 @@ rbtree_readjust(int argc, VALUE* argv, VALUE self)
|
|
1633
1640
|
rbtree_modify(self);
|
1634
1641
|
|
1635
1642
|
if (rb_block_given_p()) {
|
1636
|
-
|
1637
|
-
rbtree_argc_error(argc, 0, 0);
|
1638
|
-
}
|
1643
|
+
rbtree_check_argument_count(argc, 0, 0);
|
1639
1644
|
cmp_func = rbtree_user_cmp;
|
1640
1645
|
cmp_proc = rb_block_proc();
|
1641
1646
|
rbtree_check_proc_arity(cmp_proc, 2);
|
1642
1647
|
} else {
|
1648
|
+
rbtree_check_argument_count(argc, 0, 1);
|
1643
1649
|
if (argc == 0) {
|
1644
1650
|
cmp_func = DICT(self)->dict_compare;
|
1645
1651
|
cmp_proc = CMP_PROC(self);
|
1646
|
-
} else
|
1652
|
+
} else {
|
1647
1653
|
if (NIL_P(argv[0])) {
|
1648
1654
|
cmp_func = rbtree_cmp;
|
1649
1655
|
cmp_proc = Qnil;
|
@@ -1658,8 +1664,6 @@ rbtree_readjust(int argc, VALUE* argv, VALUE self)
|
|
1658
1664
|
cmp_proc = proc;
|
1659
1665
|
rbtree_check_proc_arity(cmp_proc, 2);
|
1660
1666
|
}
|
1661
|
-
} else {
|
1662
|
-
rbtree_argc_error(argc, 0, 1);
|
1663
1667
|
}
|
1664
1668
|
}
|
1665
1669
|
|
@@ -1828,14 +1832,6 @@ rbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
|
1828
1832
|
|
1829
1833
|
/*********************************************************************/
|
1830
1834
|
|
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
1835
|
/* :nodoc:
|
1840
1836
|
*
|
1841
1837
|
*/
|
@@ -1855,8 +1851,11 @@ rbtree_dump(VALUE self, VALUE limit)
|
|
1855
1851
|
rb_ary_push(ary, IFNONE(self));
|
1856
1852
|
|
1857
1853
|
result = rb_marshal_dump(ary, limit);
|
1854
|
+
#ifdef HAVE_RB_ARY_RESIZE
|
1855
|
+
rb_ary_resize(ary, 0);
|
1856
|
+
#else
|
1858
1857
|
rb_ary_clear(ary);
|
1859
|
-
|
1858
|
+
#endif
|
1860
1859
|
return result;
|
1861
1860
|
}
|
1862
1861
|
|
@@ -1868,16 +1867,18 @@ rbtree_s_load(VALUE klass, VALUE str)
|
|
1868
1867
|
{
|
1869
1868
|
VALUE rbtree = rbtree_alloc(klass);
|
1870
1869
|
VALUE ary = rb_marshal_load(str);
|
1871
|
-
VALUE* ptr = RARRAY_PTR(ary);
|
1872
1870
|
long len = RARRAY_LEN(ary) - 1;
|
1873
1871
|
long i;
|
1874
1872
|
|
1875
1873
|
for (i = 0; i < len; i += 2)
|
1876
|
-
rbtree_aset(rbtree,
|
1877
|
-
IFNONE(rbtree) =
|
1874
|
+
rbtree_aset(rbtree, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i + 1));
|
1875
|
+
IFNONE(rbtree) = RARRAY_AREF(ary, len);
|
1878
1876
|
|
1877
|
+
#ifdef HAVE_RB_ARY_RESIZE
|
1878
|
+
rb_ary_resize(ary, 0);
|
1879
|
+
#else
|
1879
1880
|
rb_ary_clear(ary);
|
1880
|
-
|
1881
|
+
#endif
|
1881
1882
|
return rbtree;
|
1882
1883
|
}
|
1883
1884
|
|
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
|
|
@@ -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.2
|
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-
|
11
|
+
date: 2013-12-26 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,27 +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
60
|
rubyforge_project: rbtree
|
61
|
-
rubygems_version: 2.
|
61
|
+
rubygems_version: 2.2.0
|
62
62
|
signing_key:
|
63
63
|
specification_version: 4
|
64
64
|
summary: A sorted associative collection.
|