From 213d60b7200b7c1a1085fb239becd8e2f977b6e3 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 18 Jun 2024 02:42:57 -0700 Subject: New function: copy-hash-iter. * hash.c (hash_iter_ops): Use copy_hash_iter as the clone operation. (copy_hash_iter): New function. * hash.h (copy_hash_iter): Declared. * tests/010/hash.tl: New tests. * txr.1: Documented. --- hash.c | 21 ++++++++++++++++++++- hash.h | 1 + tests/010/hash.tl | 11 +++++++++++ txr.1 | 22 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/hash.c b/hash.c index 6b62854d..58732193 100644 --- a/hash.c +++ b/hash.c @@ -1283,7 +1283,7 @@ static struct cobj_ops hash_iter_ops = cobj_ops_init(eq, cobj_destroy_free_op, hash_iter_mark, cobj_eq_hash_op, - 0); + copy_hash_iter); void hash_iter_init(struct hash_iter *hi, val hash, val self) { @@ -1402,6 +1402,24 @@ val hash_reset(val iter, val hash) return iter; } +val copy_hash_iter(val iter) +{ + val self = lit("copy-hash-iter"); + val hi_obj; + struct hash_iter *ohi = coerce(struct hash_iter *, + cobj_handle(self, iter, hash_iter_cls)); + struct hash_iter *nhi = coerce(struct hash_iter *, + chk_copy_obj(coerce(mem_t *, ohi), + sizeof *ohi)); + struct hash *h = coerce(struct hash *, cobj_handle(self, ohi->hash, + hash_cls)); + + hi_obj = cobj(coerce(mem_t *, nhi), hash_iter_cls, &hash_iter_ops); + h->usecount++; + gc_hint(iter); + return hi_obj; +} + val maphash(val fun, val hash) { val self = lit("maphash"); @@ -2309,6 +2327,7 @@ void hash_init(void) reg_fun(intern(lit("hash-next"), user_package), func_n1(hash_next)); reg_fun(intern(lit("hash-peek"), user_package), func_n1(hash_peek)); reg_fun(intern(lit("hash-reset"), user_package), func_n2(hash_reset)); + reg_fun(intern(lit("copy-hash-iter"), user_package), func_n1(copy_hash_iter)); reg_fun(intern(lit("set-hash-traversal-limit"), system_package), func_n1(set_hash_traversal_limit)); reg_fun(intern(lit("gen-hash-seed"), user_package), func_n0(gen_hash_seed)); diff --git a/hash.h b/hash.h index 36efde14..724c8aa2 100644 --- a/hash.h +++ b/hash.h @@ -77,6 +77,7 @@ val hash_begin(val hash); val hash_next(val iter); val hash_peek(val iter); val hash_reset(val iter, val hash); +val copy_hash_iter(val iter); val hash_eql(val obj); val hash_equal(val obj, val seed); val hashv(struct args *args); diff --git a/tests/010/hash.tl b/tests/010/hash.tl index d6a8542b..bd37e180 100644 --- a/tests/010/hash.tl +++ b/tests/010/hash.tl @@ -92,3 +92,14 @@ (eql (hash-equal (expt 2 128)) (hash-equal (expt 2 128))) t (eql (hash-eql "abc") (hash-eql "abc")) nil (eql (hash-eql (expt 2 128)) (hash-eql (expt 2 128))) t) + +(let* ((h #H(() (a 1) (b 2) (c 3) (d 4))) + (hi1 (hash-begin h)) + (hi2 (progn (hash-next hi1) (copy-hash-iter hi1)))) + (mvtest + (hash-next hi1) (hash-next hi2) + (hash-next hi2) (hash-next hi1) + (hash-next hi1) (hash-next hi2) + (hash-next hi2) (hash-next hi1) + (hash-next hi1) nil + (hash-next hi2) nil)) diff --git a/txr.1 b/txr.1 index 32aacb6f..fde65f54 100644 --- a/txr.1 +++ b/txr.1 @@ -21557,6 +21557,10 @@ as if by: .mono .meti (copy-search-tree << object ) .onom +.coIP hash-iter +.mono +.meti (copy-hash-iter << object ) +.onom .coIP tree-iter .mono .meti (copy-tree-iter << object ) @@ -58514,6 +58518,24 @@ to .code nil if there is no next value. +.coNP Function @ copy-hash-iter +.synb +.mets (copy-hash-iter << iter ) +.syne +.desc +The +.code copy-hash-iter +function creates and returns a duplicate of the +.meta iter +object, which must be a hash iterator returned by +.codn hash-begin . + +The returned object has the same state as the original; it references the same +traversal position in the same hash. However, it is independent of the original. +Calls to +.code hash-next +on the original have no effect on the duplicate and vice versa. + .coNP Special Variable @ *hash-seed* .desc The -- cgit v1.2.3