summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-09-14 17:59:13 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-10-05 10:32:07 -0400
commit93b643607c3d9a0775faaeb08e404f703a4200f7 (patch)
tree10b03b0189343ff1cc5d7ed11c7f035bf7319f2c
parenta71c65a45586b3f6cd5032016621d41d62a8c4f0 (diff)
downloadsssd-93b643607c3d9a0775faaeb08e404f703a4200f7.tar.gz
sssd-93b643607c3d9a0775faaeb08e404f703a4200f7.tar.xz
sssd-93b643607c3d9a0775faaeb08e404f703a4200f7.zip
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.
-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 8e4e97364..bd7186bd8 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 c116f481f..d0078d9e4 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 000000000..4d7a90428
--- /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 699479a33..767514bee 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