diff options
-rw-r--r-- | hash.c | 21 | ||||
-rw-r--r-- | hash.h | 1 | ||||
-rw-r--r-- | tests/010/hash.tl | 11 | ||||
-rw-r--r-- | txr.1 | 22 |
4 files changed, 54 insertions, 1 deletions
@@ -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)); @@ -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)) @@ -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 |