Camel.Iterator

CamelIterator is a simple interface for iterators. Although it is defined in Evolution/Camel.Object, it is not used currently except in the disksummary branch, where it is used extensively.

Iterators are designed to be simple to setup and simple to use. The next function should handle any refcounting or memory management, so that the calling function has a usable pointer until next is called again, or the iterator is freed or reset. A simple vtable is used rather than a full-blown class, so they are easier to create. There is also limited functionality to avoid overcomplicating them.

Camel.IteratorVTable

Currently, all virtual methods except free MUST be intialised.

 struct _CamelIteratorVTable {
        void (*free)(void *it);
        const void *(*next)(void *it, CamelException *ex);
        void (*reset)(void *it);
        int (*length)(void *it);
 };
  • free: Must free any fields allocated. The base object will always be freed by g_free.

  • next: Go to the next item. Return NULL if there are none, or if there is an error, and set the Evolution/Camel.Exception as appropriate.

  • reset: The next call to next will again return the first item.

  • length: Estimate the number of items. This can be used for progress reporting, but it must be aware that the implementation may not be able to calculate it accurately.

Examples

There are also extensive examples in the disksummary-branch code.

Example: a GPtrArray iterator

This example implements a simple iterator which walks a GPtrArray. It doesn't do any memory management on the pointers the GPtrArray implements, although that would be simple to add.

 struct _gpiter {
        GPtrArray *array;
        int index;
 }
 
 static void gpi_free(void *it) {
        struct _gpiter *iter = it;
 
        g_ptr_array_free(iter->array);
 }
 
 static const void *gpi_next(void *it, CamelException *ex) {
        struct _gpiter *iter = it;
 
        if (iter->array->len < iter->index)
                return iter->array->pdata[iter->index++];
        else
                return NULL;
 }
 
 static void *gpi_reset(void *it) {
        struct _gpiter *iter = it;
 
        iter->index = 0;
 }
 
 static int gpi_length(void *it) {
        struct _gpiter *iter = it;
 
        return iter->array->len;
 }
 
 static struct _CamelIteratorVTable gpi_vtable = {
        .free = gpi_free,
        .next = gpi_next,
        .reset = gpi_reset,
        .length = gpi_length
 }
 
 CamelIterator *gptrarray_iterator_new(GPtrArray *array)
 {
        struct _gpiter *iter = camel_terator_new(&gpi_vtable, sizeof(*iter));
 
        iter->array = array;
 
        return iter;
 }

Note that it also steals the array.

This example is untested.

Notes

The Evolution/Camel.Index code uses its own cursor/iterators, it could probably be changed to use CamelIterator instead.

Apps/Evolution/Camel.Iterator (last edited 2013-08-08 22:50:12 by WilliamJonMcCann)