[Minor] [minor commit] r669 - trunk/include/minor
jimb at red-bean.com
jimb at red-bean.com
Tue Oct 24 05:25:45 CDT 2006
Author: jimb
Date: Tue Oct 24 05:25:45 2006
New Revision: 669
Modified:
trunk/include/minor/hash-tables.h
Log:
First cut at hash table iteration interface.
Modified: trunk/include/minor/hash-tables.h
==============================================================================
--- trunk/include/minor/hash-tables.h (original)
+++ trunk/include/minor/hash-tables.h Tue Oct 24 05:25:45 2006
@@ -48,4 +48,87 @@
If SRC and DEST are not both hash tables, abort. */
void mn_hash_table_merge (mn_call_t *, mn_ref_t *dest, mn_ref_t *src);
+
+/* A hash table iterator represents a subset of entries in a hash
+ table. There are five essential operations used with iterators:
+
+ - Given a hash table, you can call mn_hash_table_iter to get an
+ iterator representing all its entries.
+
+ - If an iterator represents a non-empty subset of a table's
+ entries, it has a "current entry". Given the iterator and the
+ table, you can get the current entry's key and value with
+ mn_hash_iter_key and mn_hash_iter_value. If the iterator is
+ empty, these functions return NULL.
+
+ The hash table implementation gets to pick the "current entry"
+ from the iterator's subset however it pleases. However, a given
+ iterator's current entry doesn't change unless the hash table
+ itself does.
+
+ - Given an iterator I, you can get a new iterator J whose subset is
+ the same as I, but with the current entry removed.
+ mn_hash_iter_next does this, and frees I.
+
+ - You can free an iterator with mn_free_hash_iter.
+
+ This means you can loop over the entries of a hash table H in a
+ call C with code like this:
+
+ mn_hash_iter_t *i;
+ mn_ref_t *key;
+
+ for (i = mn_hash_table_iter (C, H);
+ key = mn_hash_iter_key (C, H, i);
+ i = mn_hash_iter_next (C, H, i))
+ ...;
+ mn_free_hash_iter (C, H, i);
+
+ You could just as well use mn_hash_iter_value in the loop's
+ condition.
+
+ Adding entries to or removing entries from a hash table doesn't
+ invalidate iterators on that hash table, but it may change the
+ subsets they refer to arbitrarily, which is just as bad. (These
+ operations could cause the hash table to be resized, which scatters
+ entries about arbitrarily. As far as I can tell, Python
+ dictionaries have the same restriction, so I'm assuming it's not
+ fatal; if that's not so, let me know.)
+
+ I'm torn: in the current implementation of hash tables, iterators
+ are just integers; we cast back and forth between mn_hash_iter_t *
+ and an integer type, so there's really no storage behind it at all.
+ mn_free_hash_iter is a no-op. But that may not always be so, and
+ we don't want to commit to a particular representation; hash tables
+ with buckets, for example, would need something more complex. */
+
+/* The type of an iterator over a hash table. */
+typedef struct mn_hash_iter_t mn_hash_iter_t;
+
+/* Return an iterator representing all entries in TABLE. If TABLE is
+ not a hash table, abort. */
+mn_hash_iter_t *mn_hash_table_iter (mn_call *, mn_ref_t *table);
+
+/* If ITER's subset of TABLE is not empty, return the key / value of
+ ITER's current entry. If ITER's subset is entry, return NULL. If
+ TABLE is not a hash table, abort. */
+mn_ref_t *mn_hash_iter_key (mn_call_t *, mn_ref_t *table,
+ mn_hash_iter_t *iter);
+mn_ref_t *mn_hash_iter_value (mn_call_t *, mn_ref_t *table,
+ mn_hash_iter_t *iter);
+
+/* Free ITER, and return a new iterator representing the same subset
+ of TABLE's entries that ITER did, but with ITER's current entry
+ removed. */
+mn_hash_iter_t *mn_hash_iter_next (mn_call_t *, mn_ref_t *table,
+ mn_hash_iter_t *iter);
+
+/* Return a new iterator representing the same subset of TABLE as ITER. */
+mn_hash_iter_t *mn_copy_hash_iter (mn_call_t *, mn_ref_t *table,
+ mn_hash_iter_t *iter);
+
+/* Free ITER. */
+void mn_free_hash_iter (mn_call_t *, mn_ref_t *table, mn_hash_iter_t *iter);
+
+
#endif /* MN_HASH_H */
More information about the Minor
mailing list