rbtree 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|