>From c0f775dba855fcc675cf2cf0691a5ce59b868a87 Mon Sep 17 00:00:00 2001
From: Dmitri Pal <dpal@redhat.com>
Date: Mon, 14 Sep 2009 17:59:13 -0400
Subject: [PATCH] COLLECTION Realigning collection code

Created a new module to hold functions
related to iterator and iterating
collections. Planning to add new functions
but the main collection module is already
too big. So this patch just moves code around
and fixes the build making foundation for
the next patch.
---
 common/collection/Makefile.am       |    1 +
 common/collection/collection.c      |  332 +-------------------------------
 common/collection/collection_iter.c |  362 +++++++++++++++++++++++++++++++++++
 common/collection/collection_priv.h |    7 +
 4 files changed, 372 insertions(+), 330 deletions(-)
 create mode 100644 common/collection/collection_iter.c

diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am
index 8e4e973..bd7186b 100644
--- a/common/collection/Makefile.am
+++ b/common/collection/Makefile.am
@@ -29,6 +29,7 @@ libcollection_la_SOURCES = \
     collection_queue.c \
     collection_stack.c \
     collection_cmp.c \
+    collection_iter.c \
     collection.h \
     collection_tools.h \
     collection_priv.h \
diff --git a/common/collection/collection.c b/common/collection/collection.c
index c116f48..d0078d9 100644
--- a/common/collection/collection.c
+++ b/common/collection/collection.c
@@ -204,8 +204,8 @@ void col_delete_item(struct collection_item *item)
 }
 
 /* A generic function to allocate a property item */
-static int col_allocate_item(struct collection_item **ci, const char *property,
-                             const void *item_data, int length, int type)
+int col_allocate_item(struct collection_item **ci, const char *property,
+                      const void *item_data, int length, int type)
 {
     struct collection_item *item = NULL;
 
@@ -2905,334 +2905,6 @@ int col_modify_item(struct collection_item *item,
 }
 
 
-
-/* Grow iteration stack */
-static int col_grow_stack(struct collection_iterator *iterator, unsigned desired)
-{
-    int grow_by = 0;
-    struct collection_item **temp;
-
-    TRACE_FLOW_STRING("col_grow_stack", "Entry.");
-
-    if (desired > iterator->stack_size) {
-        grow_by = (((desired - iterator->stack_size) / STACK_DEPTH_BLOCK) + 1) * STACK_DEPTH_BLOCK;
-        temp = (struct collection_item **)realloc(iterator->stack, grow_by * sizeof(struct collection_item *));
-        if (temp == NULL) {
-            TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM);
-            return ENOMEM;
-        }
-        iterator->stack = temp;
-        iterator->stack_size += grow_by;
-    }
-    TRACE_FLOW_STRING("col_grow_stack", "Exit.");
-    return EOK;
-}
-
-
-
-/* Bind iterator to a collection */
-int col_bind_iterator(struct collection_iterator **iterator,
-                      struct collection_item *ci,
-                      int mode_flags)
-{
-    int error;
-    struct collection_header *header;
-    struct collection_iterator *iter = NULL;
-
-    TRACE_FLOW_STRING("col_bind_iterator", "Entry.");
-
-    /* Do some argument checking first */
-    if ((iterator == NULL) || (ci == NULL)) {
-        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
-        return EINVAL;
-    }
-
-    iter = (struct collection_iterator *)malloc(sizeof(struct collection_iterator));
-    if (iter == NULL) {
-        TRACE_ERROR_NUMBER("Error allocating memory for the iterator.", ENOMEM);
-        return ENOMEM;
-    }
-
-    /* Allocate memory for the stack */
-    iter->stack = NULL;
-    iter->stack_size = 0;
-    iter->stack_depth = 0;
-    iter->item_level = 0;
-    iter->flags = mode_flags;
-
-    TRACE_INFO_NUMBER("Iterator flags", iter->flags);
-
-    /* Allocate memory for stack */
-    error = col_grow_stack(iter, 1);
-    if(error) {
-        free(iter);
-        TRACE_ERROR_NUMBER("Error growing stack.", error);
-        return error;
-    }
-
-    /* Create a special end item */
-    error = col_allocate_item(&(iter->end_item), "", NULL, 0, COL_TYPE_END);
-    if(error) {
-        free(iter);
-        TRACE_ERROR_NUMBER("Error allocating end item.", error);
-        return error;
-    }
-
-    /* Make sure that we tie iterator to the collection */
-    header = (struct collection_header *)ci->data;
-    header->reference_count++;
-    iter->top = ci;
-    *(iter->stack) = ci;
-    iter->stack_depth++;
-
-    *iterator = iter;
-
-    TRACE_FLOW_STRING("col_bind_iterator", "Exit");
-    return EOK;
-}
-
-/* Stop processing this subcollection and move to the next item in the
- * collection 'level' levels up.*/
-int col_iterate_up(struct collection_iterator *iterator, unsigned level)
-{
-    TRACE_FLOW_STRING("iterate_up", "Entry");
-
-    if (iterator == NULL) {
-        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
-        return EINVAL;
-    }
-
-    TRACE_INFO_NUMBER("Going up:", level);
-    TRACE_INFO_NUMBER("Current stack depth:", iterator->stack_depth);
-
-    /* If level is big just move to the top,
-     * that will end the iteration process.
-     */
-    if (level >= iterator->stack_depth) iterator->stack_depth = 0;
-    else iterator->stack_depth -= level;
-
-    TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
-    TRACE_FLOW_STRING("col_iterate_up", "Exit");
-    return EOK;
-}
-
-/* How deep are we relative to the top level.*/
-int col_get_iterator_depth(struct collection_iterator *iterator, int *depth)
-{
-    TRACE_FLOW_STRING("col_get_iterator_depth", "Entry");
-
-    if ((iterator == NULL) || (depth == NULL)) {
-        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
-        return EINVAL;
-    }
-
-    *depth = iterator->stack_depth - 1;
-
-    TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
-    TRACE_FLOW_STRING("col_get_iterator_depth","Exit");
-    return EOK;
-}
-
-/* What was the level of the last item we got? */
-int col_get_item_depth(struct collection_iterator *iterator, int *depth)
-{
-    TRACE_FLOW_STRING("col_get_item_depth", "Entry");
-
-    if ((iterator == NULL) || (depth == NULL)) {
-        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
-        return EINVAL;
-    }
-
-    *depth = iterator->item_level;
-
-    TRACE_INFO_NUMBER("Item level at the end:", iterator->item_level);
-    TRACE_FLOW_STRING("col_get_item_depth","Exit");
-    return EOK;
-}
-
-
-
-/* Unbind the iterator from the collection */
-void col_unbind_iterator(struct collection_iterator *iterator)
-{
-    TRACE_FLOW_STRING("col_unbind_iterator", "Entry.");
-    if (iterator != NULL) {
-        col_destroy_collection(iterator->top);
-        col_delete_item(iterator->end_item);
-        free(iterator->stack);
-        free(iterator);
-    }
-    TRACE_FLOW_STRING("col_unbind_iterator", "Exit");
-}
-
-/* Get items from the collection one by one following the tree */
-int col_iterate_collection(struct collection_iterator *iterator,
-                           struct collection_item **item)
-{
-    int error;
-    struct collection_item *current;
-    struct collection_item *other;
-
-    TRACE_FLOW_STRING("col_iterate_collection", "Entry.");
-
-    /* Check if we have storage for item */
-    if (item == NULL) {
-        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
-        return EINVAL;
-    }
-
-    while (1) {
-
-        TRACE_INFO_NUMBER("Stack depth:", iterator->stack_depth);
-
-        /* Are we done? */
-        if (iterator->stack_depth == 0) {
-            TRACE_FLOW_STRING("We are done.", "");
-            *item = NULL;
-            return EOK;
-        }
-
-        /* Is current item available */
-        current = iterator->stack[iterator->stack_depth - 1];
-        iterator->item_level = iterator->stack_depth - 1;
-
-        /* We are not done so check if we have an item  */
-        if (current != NULL) {
-
-            TRACE_INFO_STRING("Current item:", current->property);
-            TRACE_INFO_NUMBER("Current item type:", current->type);
-
-            /* Is this a collection reference */
-            if (current->type == COL_TYPE_COLLECTIONREF) {
-                /* We do follow references? */
-                TRACE_INFO_STRING("Current item:", "collection reference");
-                if ((iterator->flags & COL_TRAVERSE_IGNORE) == 0) {
-                    /* We should not ignore - then move on */
-                    TRACE_INFO_STRING("Collection references are not ignored", "");
-                    error = col_grow_stack(iterator, iterator->stack_depth + 1);
-                    if (error) {
-                        TRACE_ERROR_NUMBER("Error growing stack.", error);
-                        return error;
-                    }
-                    /* Do we need to go deeper than one level ? */
-                    if ((iterator->flags & COL_TRAVERSE_ONELEVEL) == 0) {
-                        TRACE_INFO_STRING("Need to go deeper", "");
-                        /* We need to go deeper... */
-                        /* Do we need to show headers but not reference? */
-                        if ((iterator->flags & COL_TRAVERSE_ONLYSUB) != 0) {
-                            TRACE_INFO_STRING("Instructed to show header not reference", "");
-                            other = *((struct collection_item **)current->data);
-                            iterator->stack[iterator->stack_depth] = other->next;
-                            iterator->item_level = iterator->stack_depth;
-                            *item = other;
-                        }
-                        /* Do we need to show both? */
-                        else if ((iterator->flags & COL_TRAVERSE_SHOWSUB) != 0) {
-                            TRACE_INFO_STRING("Instructed to show header and reference","");
-                            iterator->stack[iterator->stack_depth] = *((struct collection_item **)(current->data));
-                            *item = current;
-                            /* Do not need to adjust level here */
-                        }
-                        /* Do not show either */
-                        else if ((iterator->flags & COL_TRAVERSE_FLAT) != 0) {
-                            TRACE_INFO_STRING("Instructed not to show header and reference","");
-                            other = *((struct collection_item **)current->data);
-                            iterator->stack[iterator->stack_depth] = other->next;
-                            iterator->stack[iterator->stack_depth - 1] = current->next;
-                            iterator->stack_depth++;
-                            /* Do not need to adjust level here */
-                            continue;
-                        }
-                        /* We need to show reference only */
-                        else {
-                            TRACE_INFO_STRING("Instructed to show reference only", "");
-                            other = *((struct collection_item **)current->data);
-                            TRACE_INFO_STRING("Sub collection:", other->property);
-                            TRACE_INFO_NUMBER("Sub collection type:", other->type);
-                            iterator->stack[iterator->stack_depth] = other->next;
-                            if (other->next != NULL) {
-                                TRACE_INFO_STRING("Will show this item next time:", other->next->property);
-                                TRACE_INFO_NUMBER("Will show this item next time type:", other->next->type);
-                            }
-                            *item = current;
-                            TRACE_INFO_NUMBER("Level of the reference:", iterator->item_level);
-                            /* Do not need to adjust level here */
-                        }
-
-                        TRACE_INFO_STRING("We return item:", (*item)->property);
-                        TRACE_INFO_NUMBER("We return item type:", (*item)->type);
-                        TRACE_INFO_STRING("Moving to the next item on the previous item in stack", "");
-                        iterator->stack[iterator->stack_depth - 1] = current->next;
-                        iterator->stack_depth++;
-
-                    }
-                    else {
-                        TRACE_INFO_STRING("Instructed to parse just one level", "");
-                        /* On one level - just return current */
-                        *item = current;
-                        TRACE_INFO_STRING("Moving to the next item on one level", "");
-                        iterator->stack[iterator->stack_depth - 1] = current->next;
-                    }
-                    break;
-                }
-                else {
-                    /* We need to ignore references so move to the next item */
-                    TRACE_INFO_STRING("Stepping over the reference", "");
-                    iterator->stack[iterator->stack_depth - 1] = current->next;
-                    continue;
-                }
-            }
-            else {
-                /* Got a normal item - return it and move to the next one */
-                if ((current->type == COL_TYPE_COLLECTION) &&
-                    ((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
-                    (iterator->stack_depth > 1)) {
-                    TRACE_INFO_STRING("Header of the sub collection in flat case ", "");
-                    iterator->stack[iterator->stack_depth - 1] = current->next;
-                    continue;
-                }
-                else {
-                    TRACE_INFO_STRING("Simple item", "");
-                    *item = current;
-                    iterator->stack[iterator->stack_depth - 1] = current->next;
-                }
-                break;
-            }
-        }
-        else {
-            /* Item is NULL */
-            TRACE_INFO_STRING("Finished level", "moving to upper level");
-            iterator->stack_depth--;
-            /* Remember that item_level is zero based while depth is size
-             * so we decrease and then assign. */
-            TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
-            if ((iterator->flags & COL_TRAVERSE_END) != 0) {
-
-                /* Show end element
-                 * a) If we are flattening but at the top
-                 * b) We are not flattening
-                 */
-                if ((((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
-                     (iterator->stack_depth == 0)) ||
-                    ((iterator->flags & COL_TRAVERSE_FLAT) == 0)) {
-
-                    /* Return dummy entry to indicate the end of the collection */
-                    TRACE_INFO_STRING("Finished level", "told to return END");
-                    *item = iterator->end_item;
-                    break;
-                }
-            }
-            else {
-                /* Move to next level */
-                continue;
-            }
-        }
-    }
-
-    TRACE_FLOW_STRING("iterate_collection", "Exit");
-    return EOK;
-}
-
 /* Set collection class */
 int col_set_collection_class(struct collection_item *item,
                              unsigned cclass)
diff --git a/common/collection/collection_iter.c b/common/collection/collection_iter.c
new file mode 100644
index 0000000..4d7a904
--- /dev/null
+++ b/common/collection/collection_iter.c
@@ -0,0 +1,362 @@
+/*
+    COLLECTION LIBRARY
+
+    Implementation of the collection library iterator functions.
+
+    Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+    Collection Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Collection Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with Collection Library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include "config.h"
+#include "trace.h"
+
+/* The collection should use the real structures */
+#include "collection_priv.h"
+#include "collection.h"
+
+
+
+/* Grow iteration stack */
+static int col_grow_stack(struct collection_iterator *iterator, unsigned desired)
+{
+    int grow_by = 0;
+    struct collection_item **temp;
+
+    TRACE_FLOW_STRING("col_grow_stack", "Entry.");
+
+    if (desired > iterator->stack_size) {
+        grow_by = (((desired - iterator->stack_size) / STACK_DEPTH_BLOCK) + 1) * STACK_DEPTH_BLOCK;
+        temp = (struct collection_item **)realloc(iterator->stack, grow_by * sizeof(struct collection_item *));
+        if (temp == NULL) {
+            TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM);
+            return ENOMEM;
+        }
+        iterator->stack = temp;
+        iterator->stack_size += grow_by;
+    }
+    TRACE_FLOW_STRING("col_grow_stack", "Exit.");
+    return EOK;
+}
+
+
+
+/* Bind iterator to a collection */
+int col_bind_iterator(struct collection_iterator **iterator,
+                      struct collection_item *ci,
+                      int mode_flags)
+{
+    int error;
+    struct collection_header *header;
+    struct collection_iterator *iter = NULL;
+
+    TRACE_FLOW_STRING("col_bind_iterator", "Entry.");
+
+    /* Do some argument checking first */
+    if ((iterator == NULL) || (ci == NULL)) {
+        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+        return EINVAL;
+    }
+
+    iter = (struct collection_iterator *)malloc(sizeof(struct collection_iterator));
+    if (iter == NULL) {
+        TRACE_ERROR_NUMBER("Error allocating memory for the iterator.", ENOMEM);
+        return ENOMEM;
+    }
+
+    /* Allocate memory for the stack */
+    iter->stack = NULL;
+    iter->stack_size = 0;
+    iter->stack_depth = 0;
+    iter->item_level = 0;
+    iter->flags = mode_flags;
+
+    TRACE_INFO_NUMBER("Iterator flags", iter->flags);
+
+    /* Allocate memory for stack */
+    error = col_grow_stack(iter, 1);
+    if(error) {
+        free(iter);
+        TRACE_ERROR_NUMBER("Error growing stack.", error);
+        return error;
+    }
+
+    /* Create a special end item */
+    error = col_allocate_item(&(iter->end_item), "", NULL, 0, COL_TYPE_END);
+    if(error) {
+        free(iter);
+        TRACE_ERROR_NUMBER("Error allocating end item.", error);
+        return error;
+    }
+
+    /* Make sure that we tie iterator to the collection */
+    header = (struct collection_header *)ci->data;
+    header->reference_count++;
+    iter->top = ci;
+    *(iter->stack) = ci;
+    iter->stack_depth++;
+
+    *iterator = iter;
+
+    TRACE_FLOW_STRING("col_bind_iterator", "Exit");
+    return EOK;
+}
+
+/* Stop processing this subcollection and move to the next item in the
+ * collection 'level' levels up.*/
+int col_iterate_up(struct collection_iterator *iterator, unsigned level)
+{
+    TRACE_FLOW_STRING("iterate_up", "Entry");
+
+    if (iterator == NULL) {
+        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+        return EINVAL;
+    }
+
+    TRACE_INFO_NUMBER("Going up:", level);
+    TRACE_INFO_NUMBER("Current stack depth:", iterator->stack_depth);
+
+    /* If level is big just move to the top,
+     * that will end the iteration process.
+     */
+    if (level >= iterator->stack_depth) iterator->stack_depth = 0;
+    else iterator->stack_depth -= level;
+
+    TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
+    TRACE_FLOW_STRING("col_iterate_up", "Exit");
+    return EOK;
+}
+
+/* How deep are we relative to the top level.*/
+int col_get_iterator_depth(struct collection_iterator *iterator, int *depth)
+{
+    TRACE_FLOW_STRING("col_get_iterator_depth", "Entry");
+
+    if ((iterator == NULL) || (depth == NULL)) {
+        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+        return EINVAL;
+    }
+
+    *depth = iterator->stack_depth - 1;
+
+    TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
+    TRACE_FLOW_STRING("col_get_iterator_depth","Exit");
+    return EOK;
+}
+
+/* What was the level of the last item we got? */
+int col_get_item_depth(struct collection_iterator *iterator, int *depth)
+{
+    TRACE_FLOW_STRING("col_get_item_depth", "Entry");
+
+    if ((iterator == NULL) || (depth == NULL)) {
+        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+        return EINVAL;
+    }
+
+    *depth = iterator->item_level;
+
+    TRACE_INFO_NUMBER("Item level at the end:", iterator->item_level);
+    TRACE_FLOW_STRING("col_get_item_depth","Exit");
+    return EOK;
+}
+
+
+
+/* Unbind the iterator from the collection */
+void col_unbind_iterator(struct collection_iterator *iterator)
+{
+    TRACE_FLOW_STRING("col_unbind_iterator", "Entry.");
+    if (iterator != NULL) {
+        col_destroy_collection(iterator->top);
+        col_delete_item(iterator->end_item);
+        free(iterator->stack);
+        free(iterator);
+    }
+    TRACE_FLOW_STRING("col_unbind_iterator", "Exit");
+}
+
+/* Get items from the collection one by one following the tree */
+int col_iterate_collection(struct collection_iterator *iterator,
+                           struct collection_item **item)
+{
+    int error;
+    struct collection_item *current;
+    struct collection_item *other;
+
+    TRACE_FLOW_STRING("col_iterate_collection", "Entry.");
+
+    /* Check if we have storage for item */
+    if (item == NULL) {
+        TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+        return EINVAL;
+    }
+
+    while (1) {
+
+        TRACE_INFO_NUMBER("Stack depth:", iterator->stack_depth);
+
+        /* Are we done? */
+        if (iterator->stack_depth == 0) {
+            TRACE_FLOW_STRING("We are done.", "");
+            *item = NULL;
+            return EOK;
+        }
+
+        /* Is current item available */
+        current = iterator->stack[iterator->stack_depth - 1];
+        iterator->item_level = iterator->stack_depth - 1;
+
+        /* We are not done so check if we have an item  */
+        if (current != NULL) {
+
+            TRACE_INFO_STRING("Current item:", current->property);
+            TRACE_INFO_NUMBER("Current item type:", current->type);
+
+            /* Is this a collection reference */
+            if (current->type == COL_TYPE_COLLECTIONREF) {
+                /* We do follow references? */
+                TRACE_INFO_STRING("Current item:", "collection reference");
+                if ((iterator->flags & COL_TRAVERSE_IGNORE) == 0) {
+                    /* We should not ignore - then move on */
+                    TRACE_INFO_STRING("Collection references are not ignored", "");
+                    error = col_grow_stack(iterator, iterator->stack_depth + 1);
+                    if (error) {
+                        TRACE_ERROR_NUMBER("Error growing stack.", error);
+                        return error;
+                    }
+                    /* Do we need to go deeper than one level ? */
+                    if ((iterator->flags & COL_TRAVERSE_ONELEVEL) == 0) {
+                        TRACE_INFO_STRING("Need to go deeper", "");
+                        /* We need to go deeper... */
+                        /* Do we need to show headers but not reference? */
+                        if ((iterator->flags & COL_TRAVERSE_ONLYSUB) != 0) {
+                            TRACE_INFO_STRING("Instructed to show header not reference", "");
+                            other = *((struct collection_item **)current->data);
+                            iterator->stack[iterator->stack_depth] = other->next;
+                            iterator->item_level = iterator->stack_depth;
+                            *item = other;
+                        }
+                        /* Do we need to show both? */
+                        else if ((iterator->flags & COL_TRAVERSE_SHOWSUB) != 0) {
+                            TRACE_INFO_STRING("Instructed to show header and reference","");
+                            iterator->stack[iterator->stack_depth] = *((struct collection_item **)(current->data));
+                            *item = current;
+                            /* Do not need to adjust level here */
+                        }
+                        /* Do not show either */
+                        else if ((iterator->flags & COL_TRAVERSE_FLAT) != 0) {
+                            TRACE_INFO_STRING("Instructed not to show header and reference","");
+                            other = *((struct collection_item **)current->data);
+                            iterator->stack[iterator->stack_depth] = other->next;
+                            iterator->stack[iterator->stack_depth - 1] = current->next;
+                            iterator->stack_depth++;
+                            /* Do not need to adjust level here */
+                            continue;
+                        }
+                        /* We need to show reference only */
+                        else {
+                            TRACE_INFO_STRING("Instructed to show reference only", "");
+                            other = *((struct collection_item **)current->data);
+                            TRACE_INFO_STRING("Sub collection:", other->property);
+                            TRACE_INFO_NUMBER("Sub collection type:", other->type);
+                            iterator->stack[iterator->stack_depth] = other->next;
+                            if (other->next != NULL) {
+                                TRACE_INFO_STRING("Will show this item next time:", other->next->property);
+                                TRACE_INFO_NUMBER("Will show this item next time type:", other->next->type);
+                            }
+                            *item = current;
+                            TRACE_INFO_NUMBER("Level of the reference:", iterator->item_level);
+                            /* Do not need to adjust level here */
+                        }
+
+                        TRACE_INFO_STRING("We return item:", (*item)->property);
+                        TRACE_INFO_NUMBER("We return item type:", (*item)->type);
+                        TRACE_INFO_STRING("Moving to the next item on the previous item in stack", "");
+                        iterator->stack[iterator->stack_depth - 1] = current->next;
+                        iterator->stack_depth++;
+
+                    }
+                    else {
+                        TRACE_INFO_STRING("Instructed to parse just one level", "");
+                        /* On one level - just return current */
+                        *item = current;
+                        TRACE_INFO_STRING("Moving to the next item on one level", "");
+                        iterator->stack[iterator->stack_depth - 1] = current->next;
+                    }
+                    break;
+                }
+                else {
+                    /* We need to ignore references so move to the next item */
+                    TRACE_INFO_STRING("Stepping over the reference", "");
+                    iterator->stack[iterator->stack_depth - 1] = current->next;
+                    continue;
+                }
+            }
+            else {
+                /* Got a normal item - return it and move to the next one */
+                if ((current->type == COL_TYPE_COLLECTION) &&
+                    ((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
+                    (iterator->stack_depth > 1)) {
+                    TRACE_INFO_STRING("Header of the sub collection in flat case ", "");
+                    iterator->stack[iterator->stack_depth - 1] = current->next;
+                    continue;
+                }
+                else {
+                    TRACE_INFO_STRING("Simple item", "");
+                    *item = current;
+                    iterator->stack[iterator->stack_depth - 1] = current->next;
+                }
+                break;
+            }
+        }
+        else {
+            /* Item is NULL */
+            TRACE_INFO_STRING("Finished level", "moving to upper level");
+            iterator->stack_depth--;
+            /* Remember that item_level is zero based while depth is size
+             * so we decrease and then assign. */
+            TRACE_INFO_NUMBER("Stack depth at the end:", iterator->stack_depth);
+            if ((iterator->flags & COL_TRAVERSE_END) != 0) {
+
+                /* Show end element
+                 * a) If we are flattening but at the top
+                 * b) We are not flattening
+                 */
+                if ((((iterator->flags & COL_TRAVERSE_FLAT) != 0) &&
+                     (iterator->stack_depth == 0)) ||
+                    ((iterator->flags & COL_TRAVERSE_FLAT) == 0)) {
+
+                    /* Return dummy entry to indicate the end of the collection */
+                    TRACE_INFO_STRING("Finished level", "told to return END");
+                    *item = iterator->end_item;
+                    break;
+                }
+            }
+            else {
+                /* Move to next level */
+                continue;
+            }
+        }
+    }
+
+    TRACE_FLOW_STRING("iterate_collection", "Exit");
+    return EOK;
+}
diff --git a/common/collection/collection_priv.h b/common/collection/collection_priv.h
index 699479a..767514b 100644
--- a/common/collection/collection_priv.h
+++ b/common/collection/collection_priv.h
@@ -71,4 +71,11 @@ struct collection_header {
     unsigned cclass;
 };
 
+/* Internal function to allocate item */
+int col_allocate_item(struct collection_item **ci,
+                      const char *property,
+                      const void *item_data,
+                      int length,
+                      int type);
+
 #endif
-- 
1.5.5.6

