libcollection  0.6.0
Functions
Iterator interface

Functions

int col_bind_iterator (struct collection_iterator **iterator, struct collection_item *ci, int mode_flags)
 Bind iterator to a collection. More...
 
void col_unbind_iterator (struct collection_iterator *iterator)
 Unbind the iterator from the collection. More...
 
int col_iterate_collection (struct collection_iterator *iterator, struct collection_item **item)
 Iterate collection. More...
 
int col_iterate_up (struct collection_iterator *iterator, unsigned level)
 Move up. More...
 
int col_get_iterator_depth (struct collection_iterator *iterator, int *depth)
 Get current depth. More...
 
int col_get_item_depth (struct collection_iterator *iterator, int *depth)
 Get depth of the last returned item. More...
 
void col_pin_iterator (struct collection_iterator *iterator)
 Pin iterator. More...
 
void col_rewind_iterator (struct collection_iterator *iterator)
 Rewind iterator. More...
 

Detailed Description

The functions in this section allow iterating through a collection in a loop where the caller implements the loop. It is different from the search and traverse functions described in other sections because those functions implement the loop themselves and call provided callback in a specific situation.

Function Documentation

int col_bind_iterator ( struct collection_iterator **  iterator,
struct collection_item ci,
int  mode_flags 
)

Bind iterator to a collection.

This function creates an iterator object and binds it to the collection.

Parameters
[out]iteratorNewly created iterator object.
[in]ciCollection to iterate.
[in]mode_flagsFlags define how to traverse the collection. For more information see constants defining traverse modes.
Returns
0 - Iterator was created successfully.
ENOMEM - No memory.
EINVAL - The value of some of the arguments is invalid.
void col_unbind_iterator ( struct collection_iterator iterator)

Unbind the iterator from the collection.

Parameters
[in]iteratorIterator object to free.
int col_iterate_collection ( struct collection_iterator iterator,
struct collection_item **  item 
)

Iterate collection.

Advance to next item in the collection. After the iterator is bound it does not point to any item in the collection. Use this function in the loop to step through all items in the collection. See unit test for code examples.

Parameters
[in]iteratorIterator object to use.
[out]itemPointer to the collection item. Do not destroy or alter this pointer in any ways. To access the internals of the item use item management functions. The value of the item will be set to NULL if the end of the collection is reached.
Returns
0 - Item was successfully retrieved.
EINVAL - The value of some of the arguments is invalid.
int col_iterate_up ( struct collection_iterator iterator,
unsigned  level 
)

Move up.

Stop processing this sub collection and move to the next item in the collection some levels up.

Parameters
[in]iteratorIterator object to use.
[in]levelIndicates how many levels up you want to jump. If 0 - call is a no op. If the depth is less then requested level the iterator will get to the 0 level and next call to col_iterate_collection will return NULL item.
Returns
0 - Iterator was successfully repositioned.
EINVAL - The value of some of the arguments is invalid.
int col_get_iterator_depth ( struct collection_iterator iterator,
int *  depth 
)

Get current depth.

How deep are we relative to the top level? This function will report depth that in some cases might look misleading. The reason is that traverse flags affect the internal level we are on at each moment. For example the default traverse behavior is to show references to the sub collections. So when the item reference is returned the depth automatically adjusted to level inside the sub collection. So if function is called in this situation the level returned will denote the level inside collection. Now imagine that this collection is empty so the attempt to read element will push you automatically one level up (in absence of the COL_TRAVERSE_END flag). If in this situation you encounter another collection the reference will be returned and level automatically adjusted to level inside the collection. The point is that the level is reliable only after a data item was returned. To avoid this ambiguity another function col_get_item_depth was introduced.

Parameters
[in]iteratorIterator object to use.
[in]depthThe variable will receive the depth the iterator is on. The value is 0 if the iterator is on the top level.
Returns
0 - Success.
EINVAL - The value of some of the arguments is invalid.
int col_get_item_depth ( struct collection_iterator iterator,
int *  depth 
)

Get depth of the last returned item.

Parameters
[in]iteratorIterator object to use.
[in]depthThe variable will receive the depth the iterator is on. Item from the top level will have depth equal to 0. The value of 0 will also be returned if no item was read so far.
Returns
0 - Success.
EINVAL - The value of some of the arguments is invalid.
void col_pin_iterator ( struct collection_iterator iterator)

Pin iterator.

Pins down the iterator to loop around current point.

This feature allows some search optimization. The idea is to be able to put a 'pin' into a specific place while iterating the collection and make this place a new "wrap around" place for the collection. This means that next time you iterate this collection you will start iterating from the next item and the item you got before setting pin will be the last in your iteration cycle.

Here is the example:

Assume you have two collections that you need to compare and perform some action on collection 1 based on the presence of the item in collection 2.

  • Collection1 = A, B, C, D, E, F
  • Collection2 = A, C, F

The usual approach is to try A from collection 1 against A, B, C from collection 2. "A" will be found right away. But to find "F" it has to be compared to "A" and "C" first. The fact that the collections are to some extent ordered can in some cases help to reduce the number of comparisons. If we found "C" in the list we can put a "pin" into the collection there causing the iterator to warp at this "pin" point. Since "D" and "E" are not in the second collection we will have to make same amount of comparisons in traditional or "pinned" case to not find them. To find "F" in pinned case there will be just one comparison.

  • Traditional case = 1 + 3 + 2 + 3 + 3 + 3 = 15
  • Pinned case = 1 + 3 + 1 + 3 + 3 + 1 = 12

It is a 20% comparison reduction.

Parameters
[in]iteratorIterator object to use.
void col_rewind_iterator ( struct collection_iterator iterator)

Rewind iterator.

Rewinds iterator to the current pin point which is by default the beginning of the collection until changed by col_pin_iterator function.

Parameters
[in]iteratorIterator object to use.