summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-10-29 23:12:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-10-29 23:12:48 -0700
commitd131be5ddd9758bc497ed5eb686b21d05b8aa5c8 (patch)
tree9a0d0b3836f2410c2609bf7c032a8c4e2ca4168e /hash.c
parent5f5d7f2e69b9f80dcbbe3f6e0626e4664db70364 (diff)
downloadtxr-d131be5ddd9758bc497ed5eb686b21d05b8aa5c8.tar.gz
txr-d131be5ddd9758bc497ed5eb686b21d05b8aa5c8.tar.bz2
txr-d131be5ddd9758bc497ed5eb686b21d05b8aa5c8.zip
hash: stack-allocated iterators.
* hash.c (hash_iter_init, us_hash_iter_init, hash_iter_next, hash_iter_peek): New static functions, made from hash_begin, hash_next and hash_peek internals. (hash_begin, hash_next, hash_peek): Turned into wrappers for hash_iter_init, hash_iter_next, hash_iter_peek. (maphash, group_by, group_reduce, hash_uni, hash_diff, hash_symdiff, hash_isec, hash_subset, hash_update, hash_revget, hash_invert): Use stack-allocated struct hash_iter instead of heap allocated object from hash_begin.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c167
1 files changed, 105 insertions, 62 deletions
diff --git a/hash.c b/hash.c
index b7320ba6..20c869bf 100644
--- a/hash.c
+++ b/hash.c
@@ -1051,28 +1051,28 @@ static struct cobj_ops hash_iter_ops = cobj_ops_init(eq,
hash_iter_mark,
cobj_eq_hash_op);
-val hash_begin(val hash)
+static void hash_iter_init(struct hash_iter *hi, val hash, val self)
{
- val self = lit("hash-begin");
- val hi_obj;
struct hash *h = coerce(struct hash *, cobj_handle(self, hash, hash_s));
- struct hash_iter *hi = coerce(struct hash_iter *, chk_malloc(sizeof *hi));
+ hi->next = 0;
+ hi->chain = -1;
+ hi->cons = nil;
+ hi->hash = hash;
+ h->usecount++;
+}
+static void us_hash_iter_init(struct hash_iter *hi, val hash)
+{
+ struct hash *h = coerce(struct hash *, hash->co.handle);
hi->next = 0;
- hi->hash = nil;
hi->chain = -1;
hi->cons = nil;
- hi_obj = cobj(coerce(mem_t *, hi), hash_iter_s, &hash_iter_ops);
hi->hash = hash;
h->usecount++;
- return hi_obj;
}
-val hash_next(val iter)
+static val hash_iter_next(struct hash_iter *hi, val iter)
{
- val self = lit("hash-next");
- struct hash_iter *hi = coerce(struct hash_iter *,
- cobj_handle(self, iter, hash_iter_s));
val hash = hi->hash;
struct hash *h = hash ? coerce(struct hash *, hash->co.handle) : 0;
@@ -1091,11 +1091,8 @@ val hash_next(val iter)
return us_car(hi->cons);
}
-val hash_peek(val iter)
+static val hash_iter_peek(struct hash_iter *hi)
{
- val self = lit("hash-peek");
- struct hash_iter *hi = coerce(struct hash_iter *,
- cobj_handle(self, iter, hash_iter_s));
val hash = hi->hash;
struct hash *h = hash ? coerce(struct hash *, hash->co.handle) : 0;
cnum chain = hi->chain;
@@ -1116,12 +1113,47 @@ val hash_peek(val iter)
return us_car(cell);
}
+val hash_begin(val hash)
+{
+ val self = lit("hash-begin");
+ val hi_obj;
+ struct hash_iter *hi = coerce(struct hash_iter *, chk_malloc(sizeof *hi));
+ hash_iter_init(hi, hash, self);
+ hi_obj = cobj(coerce(mem_t *, hi), hash_iter_s, &hash_iter_ops);
+ gc_hint(hash);
+ return hi_obj;
+}
+
+val hash_next(val iter)
+{
+ val self = lit("hash-next");
+ struct hash_iter *hi = coerce(struct hash_iter *,
+ cobj_handle(self, iter, hash_iter_s));
+ return hash_iter_next(hi, iter);
+}
+
+
+val hash_peek(val iter)
+{
+ val self = lit("hash-peek");
+ struct hash_iter *hi = coerce(struct hash_iter *,
+ cobj_handle(self, iter, hash_iter_s));
+ return hash_iter_peek(hi);
+}
+
val maphash(val fun, val hash)
{
- val iter = hash_begin(hash);
+ val self = lit("maphash");
+ struct hash_iter hi;
val cell;
- while ((cell = hash_next(iter)) != nil)
+
+ hash_iter_init(&hi, hash, self);
+
+ gc_hint(hash);
+
+ while ((cell = hash_iter_next(&hi, 0)) != nil)
funcall2(fun, us_car(cell), us_cdr(cell));
+
return nil;
}
@@ -1409,10 +1441,12 @@ val group_by(val func, val seq, struct args *hashv_args)
}
{
- val iter = hash_begin(hash);
+ struct hash_iter hi;
val cell;
- while ((cell = hash_next(iter)) != nil)
+ us_hash_iter_init(&hi, hash);
+
+ while ((cell = hash_iter_next(&hi, 0)) != nil)
us_rplacd(cell, nreverse(us_cdr(cell)));
return hash;
@@ -1454,10 +1488,11 @@ val group_reduce(val hash, val by_fun, val reduce_fun, val seq,
}
if (!null_or_missing_p(filter_fun)) {
- val iter = hash_begin(hash);
+ struct hash_iter hi;
val cell;
+ hash_iter_init(&hi, hash, self);
- while ((cell = hash_next(iter)) != nil)
+ while ((cell = hash_iter_next(&hi, 0)) != nil)
us_rplacd(cell, funcall1(filter_fun, us_cdr(cell)));
}
@@ -1545,19 +1580,18 @@ val hash_uni(val hash1, val hash2, val joinfun)
{
val hout = make_similar_hash(hash1);
- val hiter, entry;
+ val entry;
+ struct hash_iter hi;
- for (hiter = hash_begin(hash2), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash2, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
sethash(hout, us_car(entry), us_cdr(entry));
}
- for (hiter = hash_begin(hash1), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash1, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
if (missingp(joinfun)) {
sethash(hout, us_car(entry), us_cdr(entry));
} else {
@@ -1586,12 +1620,12 @@ val hash_diff(val hash1, val hash2)
{
val hout = copy_hash(hash1);
- val hiter, entry;
+ val entry;
+ struct hash_iter hi;
- for (hiter = hash_begin(hash2), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash2, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
remhash(hout, us_car(entry));
}
@@ -1611,20 +1645,18 @@ val hash_symdiff(val hash1, val hash2)
{
val hout = make_similar_hash(hash1);
- val hiter, entry;
+ val entry;
+ struct hash_iter hi;
- for (hiter = hash_begin(hash1), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
- if (!gethash_e(self, hash2, us_car(entry)))
+ hash_iter_init(&hi, hash1, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) { if (!gethash_e(self, hash2, us_car(entry)))
sethash(hout, us_car(entry), us_cdr(entry));
}
- for (hiter = hash_begin(hash2), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash2, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
if (!gethash_e(self, hash1, us_car(entry)))
sethash(hout, us_car(entry), us_cdr(entry));
}
@@ -1645,12 +1677,12 @@ val hash_isec(val hash1, val hash2, val joinfun)
{
val hout = make_similar_hash(hash1);
- val hiter, entry;
+ val entry;
+ struct hash_iter hi;
- for (hiter = hash_begin(hash1), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash1, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
val found = gethash_e(self, hash2, us_car(entry));
if (found) {
if (missingp(joinfun))
@@ -1666,12 +1698,13 @@ val hash_isec(val hash1, val hash2, val joinfun)
val hash_subset(val hash1, val hash2)
{
- val hiter, entry;
+ val self = lit("hash-subset");
+ val entry;
+ struct hash_iter hi;
- for (hiter = hash_begin(hash1), entry = hash_next(hiter);
- entry;
- entry = hash_next(hiter))
- {
+ hash_iter_init(&hi, hash1, self);
+
+ for (entry = hash_iter_next(&hi, 0); entry; entry = hash_iter_next(&hi, 0)) {
if (!inhash(hash2, us_car(entry), colon_k))
return nil;
}
@@ -1687,12 +1720,17 @@ val hash_proper_subset(val hash1, val hash2)
val hash_update(val hash, val fun)
{
- val iter = hash_begin(hash);
+ val self = lit("hash-subset");
val cell;
- while ((cell = hash_next(iter)) != nil) {
+ struct hash_iter hi;
+
+ hash_iter_init(&hi, hash, self);
+
+ while ((cell = hash_iter_next(&hi, 0)) != nil) {
loc ptr = mkloc(*us_cdr_p(cell), cell);
set(ptr, funcall1(fun, deref(ptr)));
}
+
return hash;
}
@@ -1721,13 +1759,16 @@ val hash_update_1(val hash, val key, val fun, val init)
val hash_revget(val hash, val value, val test, val keyfun)
{
- val iter = hash_begin(hash);
+ val self = lit("hash-revget");
val cell;
+ struct hash_iter hi;
+
+ hash_iter_init(&hi, hash, self);
test = default_arg(test, eql_f);
keyfun = default_arg(keyfun, identity_f);
- while ((cell = hash_next(iter)) != nil) {
+ while ((cell = hash_iter_next(&hi, 0)) != nil) {
if (funcall2(test, value, funcall1(keyfun, us_cdr(cell))))
return us_car(cell);
}
@@ -1739,18 +1780,20 @@ val hash_invert(val hash, val joinfun, val unitfun, struct args *hashv_args)
{
val self = lit("hash-invert");
val hout = hashv(hashv_args);
- val iter = hash_begin(hash);
val jfun = default_arg(joinfun, identity_star_f);
val ufun = default_arg(unitfun, identity_f);
val cell;
+ struct hash_iter hi;
+
+ hash_iter_init(&hi, hash, self);
if (jfun == identity_star_f && ufun == identity_f) {
- while ((cell = hash_next(iter)) != nil) {
+ while ((cell = hash_iter_next(&hi, 0)) != nil) {
us_cons_bind(k, v, cell);
sethash(hout, v, k);
}
} else {
- while ((cell = hash_next(iter)) != nil) {
+ while ((cell = hash_iter_next(&hi, 0)) != nil) {
us_cons_bind(k, v, cell);
val new_p;
loc place = gethash_l(self, hout, v, mkcloc(new_p));