Iteration methods for GLib containers



If you're like me you hate to use special foreach/traverse routines
that are annoying to use (annoying because you have to write a
special-purpose traversal routine or wrapper routine just to iterate
through a collection).  I vastly prefer to iterate in a for loop.

I wrote some code to create a "GIter" type that can be used to iterate
over arbitrary types of collections in a uniform manner.  It works
like this:

{
    GHashTable *hash;
    GIter *hi;
    gpointer key;
    GKeyValue kv;

    hash = g_hash_table_new(...);
    /* Insert a bunch of stuff... */

    /* Iterate over values */
    for (foo = g_iter_first(&hi, hash, g_hash_table_iter);
         foo;
         foo = g_iter_next(hi))
    {
        /* do stuff */
    }
    g_iter_destroy(hi);

    /* Iterate over keys */
    for (key = g_iter_first_key(&hi, hash, g_hash_table_iter);
         key; key = g_iter_next_key(hi)) ... etc
    g_iter_destroy(hi);

    /* Iterate over key/value pairs */
    for (kv = g_iter_first_keyval(&hi, hash, g_hash_table_iter);
         kv.value; kv = g_iter_next_keyval(hi)) ... etc
    g_iter_destroy(hi);

    /* Iterate through unknown data type w/ arbitrary method */
    for (foo = g_iter_first(&hi, collection, collections_method);
         etc...
}

This is much more preferable, at least to me, than...

typedef struct {
    /* store everything random func needs... */
} random_struct;

static void random_func(gpointer key, gpointer value,
                        gpointer user_data)
{
    /* cast pointers, do what we need to... */
}

{ ...
    random_struct rs = { stack, blah };
    g_hash_table_foreach(hash, random_func, &rs);
}

The idea is to have a generic "iterator" which provides a clean and
easy-to-use interface to any kind of collection.  An "iteration method"
(which relies on intimate knowledge of the collection-type) provides a
way to iterate to the generic iterator interface (by providing functions
for init, next, prev, etc., methods).  Conceivably collections could
have lots of different iteration methods.  F.e., GTree could have
g_tree_iter_in_order, g_tree_iter_pre_order, etc, methods.

I've written code to provide iterators for GHashTables and a
g_tree_iter_pre_order method for GTree (which required minor
modification of the GTree data type, unfortunately, for efficient use
--- I didn't feel like building a stack during iteration so I added a
"parent" field to all GTreeNodes to avoid that).  Adding other iteration
methods for other data types would be pretty easy.

The API might need some refinement, plus the code I wrote, but it's a
neat-ish hack, and makes working with GLib container types much more
enjoyable (I think).

If anyone is at all interested I will post mail the couple of source
files (approx. 11K I think) to the list.

-- Steve Lawler




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]