summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/collection/Makefile.am1
-rw-r--r--common/collection/collection.c332
-rw-r--r--common/collection/collection_iter.c362
-rw-r--r--common/collection/collection_priv.h7
4 files changed, 372 insertions, 330 deletions
diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am
index 8e4e9736..bd7186bd 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 c116f481..d0078d9e 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 00000000..4d7a9042
--- /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 699479a3..767514be 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