summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/collection/Makefile.am1
-rw-r--r--common/collection/collection.c1810
-rw-r--r--common/collection/collection.h388
-rw-r--r--common/collection/collection_cnv.c1266
-rw-r--r--common/collection/collection_priv.h4
-rw-r--r--common/collection/collection_ut.c169
-rw-r--r--common/collection/configure.ac3
7 files changed, 2791 insertions, 850 deletions
diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am
index 0b8d0d035..8df9fc6b7 100644
--- a/common/collection/Makefile.am
+++ b/common/collection/Makefile.am
@@ -14,6 +14,7 @@ noinst_LTLIBRARIES = libcollection.la
libcollection_la_SOURCES = \
collection.c \
collection_tools.c \
+ collection_cnv.c \
collection.h \
collection_tools.h \
collection_priv.h \
diff --git a/common/collection/collection.c b/common/collection/collection.c
index e2816e638..f79188793 100644
--- a/common/collection/collection.c
+++ b/common/collection/collection.c
@@ -1,7 +1,7 @@
/*
COLLECTION LIBRARY
- Implemenation of the collection library interface.
+ Implementation of the collection library interface.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
@@ -25,6 +25,7 @@
#include <errno.h>
#include <ctype.h>
#include <time.h>
+#include "config.h"
#include "trace.h"
/* The collection should use the teal structures */
@@ -43,11 +44,21 @@
#define EINTR_INTERNAL 10000
-/* Potential subjest for management with libtools */
+/* Potential subject for management with libtools */
#define DATE_FORMAT "%c"
#define TIME_ARRAY_SIZE 100
+/* Magic numbers for hashing */
+#if SIZEOF_LONG == 8
+ #define FNV1a_prime 1099511628211ul
+ #define FNV1a_base 14695981039346656037ul
+#elif SIZEOF_LONG_LONG == 8
+ #define FNV1a_prime 1099511628211ull
+ #define FNV1a_base 14695981039346656037ull
+#else
+ #error "Platform cannot support 64-bit constant integers"
+#endif
/* Struct used for passing parameter for update operation */
struct update_property {
@@ -80,6 +91,15 @@ static int act_traverse_handler(struct collection_item *head,
void *custom_data,
int *stop);
+/* Traverse handler to find parent of the item */
+static int parent_traverse_handler(struct collection_item *head,
+ struct collection_item *previous,
+ struct collection_item *current,
+ void *traverse_data,
+ item_fn user_item_handler,
+ void *custom_data,
+ int *stop);
+
/* Traverse callback signature */
typedef int (*internal_item_fn)(struct collection_item *head,
struct collection_item *previous,
@@ -88,11 +108,29 @@ typedef int (*internal_item_fn)(struct collection_item *head,
item_fn user_item_handler,
void *custom_data,
int *stop);
+/* Function to walk_items */
+static int walk_items(struct collection_item *ci,
+ int mode_flags,
+ internal_item_fn traverse_handler,
+ void *traverse_data,
+ item_fn user_item_handler,
+ void *custom_data);
-/******************** SUPPLEMENTARY FUNCTIONS ****************************/
+/* Function to get sub collection */
+static int get_subcollection(const char *property,
+ int property_len,
+ int type,
+ void *data,
+ int length,
+ void *found,
+ int *dummy);
+/* Function to destroy collection */
+void destroy_collection(struct collection_item *ci);
+/******************** SUPPLEMENTARY FUNCTIONS ****************************/
/* BASIC OPERATIONS */
+
/* Function that checks if property can be added */
static int validate_property(const char *property)
{
@@ -113,14 +151,28 @@ static int validate_property(const char *property)
return invalid;
}
-
-
/* Function that cleans the item */
-static void delete_item(struct collection_item *item)
+void delete_item(struct collection_item *item)
{
+ struct collection_item *other_collection;
+
TRACE_FLOW_STRING("delete_item","Entry point.");
- if (item == NULL) return;
+ if (item == NULL) {
+ TRACE_FLOW_STRING("delete_item","Nothing to delete!");
+ return;
+ }
+
+ /* Handle external or embedded collection */
+ if(item->type == COL_TYPE_COLLECTIONREF) {
+ /* Our data is a pointer to a whole external collection so dereference
+ * it or delete */
+ other_collection = *((struct collection_item **)(item->data));
+ destroy_collection(other_collection);
+ }
+
+ TRACE_INFO_STRING("Deleting property:", item->property);
+ TRACE_INFO_NUMBER("Type:", item->type);
if (item->property != NULL) free(item->property);
if (item->data != NULL) free(item->data);
@@ -172,7 +224,18 @@ static int allocate_item(struct collection_item **ci, const char *property,
return error;
}
- item->property_len = strlen(item->property);
+ item->phash = FNV1a_base;
+ item->property_len = 0;
+
+ while (property[item->property_len] != 0) {
+ item->phash = item->phash ^ property[item->property_len];
+ item->phash *= FNV1a_prime;
+ item->property_len++;
+ }
+
+ TRACE_INFO_NUMBER("Item hash", item->phash);
+ TRACE_INFO_NUMBER("Item property length", item->property_len);
+ TRACE_INFO_NUMBER("Item property strlen", strlen(item->property));
/* Deal with data */
item->data = malloc(length);
@@ -200,126 +263,585 @@ static int allocate_item(struct collection_item **ci, const char *property,
return 0;
}
-/* Add item to the end of collection */
-/* Can add itself to itself - nice...*/
-static int add_item_to_collection(struct collection_item *collection,
- struct collection_item *item)
+/* Structure used to find things in collection */
+struct property_search {
+ const char *property;
+ uint64_t hash;
+ struct collection_item *parent;
+ int index;
+ int count;
+ int found;
+ int use_type;
+ int type;
+};
+
+/* Find the parent of the item with given name */
+static int find_property(struct collection_item *collection,
+ const char *refprop,
+ int index,
+ int use_type,
+ int type,
+ struct collection_item **parent)
+{
+ TRACE_FLOW_STRING("find_property", "Entry.");
+ struct property_search ps;
+ int i = 0;
+
+ *parent = NULL;
+
+ ps.property = refprop;
+ ps.hash = FNV1a_base;
+ ps.parent = NULL;
+ ps.index = index;
+ ps.count = 0;
+ ps.found = 0;
+ ps.use_type = use_type;
+ ps.type = type;
+
+ /* Create hash of the string to search */
+ while(refprop[i] != 0) {
+ ps.hash = ps.hash ^ refprop[i];
+ ps.hash *= FNV1a_prime;
+ i++;
+ }
+
+ /* We do not care about error here */
+ (void)walk_items(collection, COL_TRAVERSE_ONELEVEL, parent_traverse_handler,
+ (void *)parent, NULL, (void *)&ps);
+
+ if (*parent) {
+ /* Item is found in the collection */
+ TRACE_FLOW_STRING("find_property", "Exit - item found");
+ return 1;
+ }
+
+ /* Item is not found */
+ TRACE_FLOW_STRING("find_property", "Exit - item NOT found");
+ return 0;
+}
+
+
+
+/* Insert item into the current collection */
+int insert_item_into_current(struct collection_item *collection,
+ struct collection_item *item,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags)
{
- struct collection_header *header;
+ struct collection_header *header = NULL;
+ struct collection_item *parent = NULL;
+ struct collection_item *current = NULL;
+ int refindex = 0;
- TRACE_FLOW_STRING("add_item_to_collection", "Entry point.");
+ TRACE_FLOW_STRING("insert_item_into_current", "Entry point");
+
+ /* Do best effort on the item */
+ if ((!item) || (item->next)) {
+ TRACE_ERROR_STRING("Passed in item is invalid", "");
+ return EINVAL;
+ }
if (collection == NULL) {
- TRACE_INFO_STRING("add_item_to_collection",
+ TRACE_INFO_STRING("insert_item_into_current",
"Collection accepting is NULL");
- if ((item != NULL) && (item->type == COL_TYPE_COLLECTION)) {
+ if (item->type == COL_TYPE_COLLECTION) {
/* This is a special case of self creation */
- TRACE_INFO_STRING("add_item_to_collection",
+ TRACE_INFO_STRING("insert_item_into_current",
"Adding header item to new collection.");
collection = item;
}
}
-
- /* We can add items only to collections */
- if (collection->type != COL_TYPE_COLLECTION) {
- TRACE_ERROR_STRING("add_item_to_collection",
- "Attempt to add item to non collection.");
- TRACE_ERROR_STRING("Collection name:", collection->property);
- TRACE_ERROR_NUMBER("Collection type:", collection->type);
- return EINVAL;
+ else {
+ /* We can add items only to collections */
+ if (collection->type != COL_TYPE_COLLECTION) {
+ TRACE_ERROR_STRING("Attempt to add item to non collection.","");
+ TRACE_ERROR_STRING("Collection name:", collection->property);
+ TRACE_ERROR_NUMBER("Collection type:", collection->type);
+ return EINVAL;
+ }
}
+ /* After processing flags we can process disposition */
+
header = (struct collection_header *)collection->data;
- /* Link new item to the last item in the list if there any */
- if (header->last != NULL) header->last->next = item;
+ /* Check flags first */
+ switch(flags) {
+ case COL_INSERT_NOCHECK: /* No check - good just fall through */
+ TRACE_INFO_STRING("Insert without check", "");
+ break;
+ case COL_INSERT_DUPOVER: /* Find item and overwrite - ignore disposition */
+ if (find_property(collection, item->property, 0, 0, 0, &parent)) {
+ current = parent->next;
+ item->next = current->next;
+ parent->next = item;
+ delete_item(current);
+ header->count--;
+ TRACE_FLOW_STRING("insert_item_into_current", "Dup overwrite exit");
+ return EOK;
+ }
+ /* Not found so we fall thorough and add as requested */
+ break;
+
+ case COL_INSERT_DUPOVERT: /* Find item by name and type and overwrite - ignore disposition */
+ if (find_property(collection, item->property, 0, 1, item->type, &parent)) {
+ current = parent->next;
+ item->next = current->next;
+ parent->next = item;
+ delete_item(current);
+ header->count--;
+ TRACE_FLOW_STRING("insert_item_into_current", "Dup overwrite exit");
+ return EOK;
+ }
+ /* Not found so we fall thorough and add as requested */
+ break;
+
+ case COL_INSERT_DUPERROR: if (find_property(collection, item->property, 0, 0, 0, &parent)) {
+ /* Return error */
+ TRACE_ERROR_NUMBER("Duplicate property", EEXIST);
+ return EEXIST;
+ }
+ break;
+
+ case COL_INSERT_DUPERRORT: if (find_property(collection, item->property, 0, 1, item->type, &parent)) {
+ /* Return error */
+ TRACE_ERROR_NUMBER("Duplicate property of the same type", EEXIST);
+ return EEXIST;
+ }
+ break;
+
+ case COL_INSERT_DUPMOVE: /* Find item and delete */
+ if (find_property(collection, item->property, 0, 0, 0, &parent)) {
+ current = parent->next;
+ parent->next = current->next;
+ delete_item(current);
+ header->count--;
+ }
+ /* Now add item according to the disposition */
+ break;
+
+ case COL_INSERT_DUPMOVET: /* Find item and delete */
+ TRACE_INFO_STRING("Property:", item->property);
+ TRACE_INFO_NUMBER("Type:", item->type);
+ if (find_property(collection, item->property, 0, 1, item->type, &parent)) {
+ TRACE_INFO_NUMBER("Current:", (unsigned)(parent->next));
+ current = parent->next;
+ parent->next = current->next;
+ delete_item(current);
+ header->count--;
+ }
+ /* Now add item according to the disposition */
+ break;
+
+ default: /* The new ones should be added here */
+ TRACE_ERROR_NUMBER("Flag is not implemented", ENOSYS);
+ return ENOSYS;
+ }
+
+
+ switch (disposition) {
+ case COL_DSP_END: /* Link new item to the last item in the list if there any */
+ if (header->last != NULL) header->last->next = item;
+ /* Make sure we save a new last element */
+ header->last = item;
+ header->count++;
+ break;
+
+ case COL_DSP_FRONT: /* Same as above if there is header only */
+ if (header->count == 1) {
+ header->last->next = item;
+ header->last = item;
+ }
+ else {
+ item->next = collection->next;
+ collection->next = item;
+ }
+ header->count++;
+ break;
+
+ case COL_DSP_BEFORE: /* Check argument */
+ if (!refprop) {
+ TRACE_ERROR_STRING("In this case property is required", "");
+ return EINVAL;
+ }
+
+ /* We need to find property */
+ if (find_property(collection, refprop, 0, 0, 0, &parent)) {
+ item->next = parent->next;
+ parent->next = item;
+ header->count++;
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ case COL_DSP_AFTER: /* Check argument */
+ if (!refprop) {
+ TRACE_ERROR_STRING("In this case property is required", "");
+ return EINVAL;
+ }
+
+ /* We need to find property */
+ if (find_property(collection, refprop, 0, 0, 0, &parent)) {
+ parent = parent->next;
+ if (parent->next) {
+ /* It is not the last item */
+ item->next = parent->next;
+ parent->next = item;
+ }
+ else {
+ /* It is the last item */
+ header->last->next = item;
+ header->last = item;
+ }
+ header->count++;
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ case COL_DSP_INDEX: if(index == 0) {
+ /* Same is first */
+ if (header->count == 1) {
+ header->last->next = item;
+ header->last = item;
+ }
+ else {
+ item->next = collection->next;
+ collection->next = item;
+ }
+ }
+ else if(index >= header->count - 1) {
+ /* In this case add to the end */
+ if (header->last != NULL) header->last->next = item;
+ /* Make sure we save a new last element */
+ header->last = item;
+ }
+ else {
+ /* In the middle */
+ parent = collection;
+ /* Move to the right position counting */
+ while (index > 0) {
+ index--;
+ parent = parent->next;
+ }
+ item->next = parent->next;
+ parent->next = item;
+ }
+ header->count++;
+ break;
+
+ case COL_DSP_FIRSTDUP:
+ case COL_DSP_LASTDUP:
+ case COL_DSP_NDUP:
+
+ if (disposition == COL_DSP_FIRSTDUP) refindex = 0;
+ else if (disposition == COL_DSP_LASTDUP) refindex = -1;
+ else refindex = index;
+
+ /* We need to find property based on index */
+ if (find_property(collection, item->property, refindex, 0, 0, &parent)) {
+ item->next = parent->next;
+ parent->next = item;
+ header->count++;
+ if(header->last == parent) header->last = item;
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ default:
+ TRACE_ERROR_STRING("Disposition is not implemented", "");
+ return ENOSYS;
+
+ }
- /* Make sure we save a new last element */
- header->last = item;
- header->count++;
TRACE_INFO_STRING("Collection:", collection->property);
TRACE_INFO_STRING("Just added item is:", item->property);
TRACE_INFO_NUMBER("Item type.", item->type);
TRACE_INFO_NUMBER("Number of items in collection now is.", header->count);
- TRACE_FLOW_STRING("add_item_to_collection", "Success exit.");
+ TRACE_FLOW_STRING("insert_item_into_current", "Exit");
return EOK;
}
+/* Extract item from the current collection */
+int extract_item_from_current(struct collection_item *collection,
+ int disposition,
+ const char *refprop,
+ int index,
+ int type,
+ struct collection_item **ret_ref)
+{
+ struct collection_header *header = NULL;
+ struct collection_item *parent = NULL;
+ struct collection_item *current = NULL;
+ struct collection_item *found = NULL;
+ int refindex = 0;
+ int use_type = 0;
-/* TRAVERSE HANDLERS */
+ TRACE_FLOW_STRING("extract_item_current", "Entry point");
-/* Special handler to just set a flag if the item is found */
-inline static int is_in_item_handler(const char *property,
- int property_len,
- int type,
- void *data,
- int length,
- void *found,
- int *dummy)
-{
- TRACE_FLOW_STRING("is_in_item_handler", "Entry.");
- TRACE_INFO_STRING("Property:", property);
- TRACE_INFO_NUMBER("Property length:", property_len);
- TRACE_INFO_NUMBER("Type:", type);
- TRACE_INFO_NUMBER("Length:", length);
+ /* Check that collection is not empty */
+ if ((collection == NULL) || (collection->type != COL_TYPE_COLLECTION)) {
+ TRACE_ERROR_STRING("Collection can't be NULL", "");
+ return EINVAL;
+ }
- *((int *)(found)) = COL_MATCH;
+ header = (struct collection_header *)collection->data;
- TRACE_FLOW_STRING("is_in_item_handler", "Success Exit.");
+ /* Before moving forward we need to check if there is anything to extract */
+ if (header->count <= 1) {
+ TRACE_ERROR_STRING("Collection is empty.", "Nothing to extract.");
+ return ENOENT;
+ }
+
+ if (type != 0) use_type = 1;
+
+ switch (disposition) {
+ case COL_DSP_END: /* Extract last item in the list. */
+ parent = collection;
+ current = collection->next;
+ while (current->next != NULL) {
+ parent = current;
+ current = current->next;
+ }
+ *ret_ref = parent->next;
+ parent->next = NULL;
+ /* Special case - one data element */
+ if (header->count == 2) header->last = NULL;
+ else header->last = parent;
+ break;
+
+ case COL_DSP_FRONT: /* Extract first item in the list */
+ *ret_ref = collection->next;
+ collection->next = (*ret_ref)->next;
+ /* Special case - one data element */
+ if (header->count == 2) header->last = NULL;
+ break;
+
+ case COL_DSP_BEFORE: /* Check argument */
+ if (!refprop) {
+ TRACE_ERROR_STRING("In this case property is required", "");
+ return EINVAL;
+ }
+
+ /* We have to do it in two steps */
+ /* First find the property that is mentioned */
+ if (find_property(collection, refprop, 0, use_type, type, &found)) {
+ /* We found the requested property */
+ if (found->next == collection->next) {
+ /* The referenced property is the first in the list */
+ TRACE_ERROR_STRING("Nothing to extract. Lists starts with property", refprop);
+ return ENOENT;
+ }
+ /* Get to the parent of the item that is before the one that is found */
+ parent = collection;
+ current = collection->next;
+ while (current != found) {
+ parent = current;
+ current = current->next;
+ }
+ *ret_ref = current;
+ parent->next = current->next;
+
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ case COL_DSP_AFTER: /* Check argument */
+ if (!refprop) {
+ TRACE_ERROR_STRING("In this case property is required", "");
+ return EINVAL;
+ }
+
+ /* We need to find property */
+ if (find_property(collection, refprop, 0, use_type, type, &parent)) {
+ current = parent->next;
+ if (current->next) {
+ *ret_ref = current->next;
+ current->next = (*ret_ref)->next;
+ /* If we removed the last element adjust header */
+ if(current->next == NULL) header->last = parent;
+ }
+ else {
+ TRACE_ERROR_STRING("Property is last in the list", refprop);
+ return ENOENT;
+ }
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ case COL_DSP_INDEX: if (index == 0) {
+ *ret_ref = collection->next;
+ collection->next = (*ret_ref)->next;
+ /* Special case - one data element */
+ if (header->count == 2) header->last = NULL;
+ }
+ /* Index 0 stands for the first data element.
+ * Count includes header element.
+ */
+ else if (index >= (header->count - 1)) {
+ TRACE_ERROR_STRING("Index is out of boundaries", refprop);
+ return ENOENT;
+ }
+ else {
+ /* Loop till the element with right index */
+ refindex = 0;
+ parent = collection;
+ current = collection->next;
+ while (refindex < index) {
+ parent = current;
+ current = current->next;
+ refindex++;
+ }
+ *ret_ref = parent->next;
+ parent->next = (*ret_ref)->next;
+ /* If we removed the last element adjust header */
+ if (parent->next == NULL) header->last = parent;
+ }
+ break;
+
+ case COL_DSP_FIRSTDUP:
+ case COL_DSP_LASTDUP:
+ case COL_DSP_NDUP:
+
+ if (disposition == COL_DSP_FIRSTDUP) refindex = 0;
+ else if (disposition == COL_DSP_LASTDUP) refindex = -2;
+ else refindex = index;
+
+ /* We need to find property based on index */
+ if (find_property(collection, refprop, refindex, use_type, type, &parent)) {
+ *ret_ref = parent->next;
+ parent->next = (*ret_ref)->next;
+ /* If we removed the last element adjust header */
+ if(parent->next == NULL) header->last = parent;
+ }
+ else {
+ TRACE_ERROR_STRING("Property not found", refprop);
+ return ENOENT;
+ }
+ break;
+
+ default:
+ TRACE_ERROR_STRING("Disposition is not implemented", "");
+ return ENOSYS;
+
+ }
+
+
+ /* Clear item and reduce count */
+ (*ret_ref)->next = NULL;
+ header->count--;
+ TRACE_INFO_STRING("Collection:", (*ret_ref)->property);
+ TRACE_INFO_NUMBER("Item type.", (*ret_ref)->type);
+ TRACE_INFO_NUMBER("Number of items in collection now is.", header->count);
+
+ TRACE_FLOW_STRING("extract_item_from_current", "Exit");
return EOK;
}
-/* Special handler to retrieve the sub collection */
-inline static int get_subcollection(const char *property,
- int property_len,
- int type,
- void *data,
- int length,
- void *found,
- int *dummy)
+/* Extract item from the collection */
+int extract_item(struct collection_item *collection,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ int type,
+ struct collection_item **ret_ref)
{
- TRACE_FLOW_STRING("get_subcollection", "Entry.");
- TRACE_INFO_STRING("Property:", property);
- TRACE_INFO_NUMBER("Property length:", property_len);
- TRACE_INFO_NUMBER("Type:", type);
- TRACE_INFO_NUMBER("Length:", length);
+ struct collection_item *col = NULL;
+ int error = 0;
- *((struct collection_item **)(found)) = *((struct collection_item **)(data));
+ TRACE_FLOW_STRING("extract_item", "Entry point");
- TRACE_FLOW_STRING("get_subcollection","Success Exit.");
+ /* Check that collection is not empty */
+ if ((collection == NULL) || (collection->type != COL_TYPE_COLLECTION)) {
+ TRACE_ERROR_STRING("Collection can't be NULL", "");
+ return EINVAL;
+ }
- return EOK;
+ /* Get subcollection if needed */
+ if (subcollection == NULL) {
+ col = collection;
+ }
+ else {
+ TRACE_INFO_STRING("Subcollection id not null, searching", subcollection);
+ error = find_item_and_do(collection, subcollection,
+ COL_TYPE_COLLECTIONREF,
+ COL_TRAVERSE_DEFAULT,
+ get_subcollection, (void *)(&col),
+ COLLECTION_ACTION_FIND);
+ if (error) {
+ TRACE_ERROR_NUMBER("Search for subcollection returned error:", error);
+ return error;
+ }
-}
+ if (col == NULL) {
+ TRACE_ERROR_STRING("Search for subcollection returned NULL pointer", "");
+ return ENOENT;
+ }
+ }
-/* ADD PROPERTY */
+ /* Extract from the current collection */
+ error = extract_item_from_current(col,
+ disposition,
+ refprop,
+ index,
+ type,
+ ret_ref);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed extract item into current collection", error);
+ return error;
+ }
-/* Add a single property to a collection.
- * Returns a pointer to a newly allocated property */
-static struct collection_item *add_property(struct collection_item *collection,
- const char *subcollection,
- const char *property,
- void *item_data,
- int length,
- int type,
- int *error)
+ TRACE_FLOW_STRING("extract_item", "Exit");
+ return EOK;
+}
+
+
+/* Insert the item into the collection or subcollection */
+int insert_item(struct collection_item *collection,
+ const char *subcollection,
+ struct collection_item *item,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags)
{
- struct collection_item *item = NULL;
+ int error;
struct collection_item *acceptor = NULL;
- TRACE_FLOW_STRING("add_property", "Entry.");
- /* Allocate item */
+ TRACE_FLOW_STRING("insert_item", "Entry point.");
- TRACE_INFO_NUMBER("Property type to add", type);
- *error = allocate_item(&item, property, item_data, length, type);
- if (*error) return NULL;
+ /* Do best effort on the item */
+ if ((!item) || (item->next)) {
+ TRACE_ERROR_STRING("Passed in item is invalid", "");
+ return EINVAL;
+ }
- TRACE_INFO_STRING("Created item:", item->property);
- TRACE_INFO_NUMBER("Item has type:", item->type);
+ /* Check that collection is not empty */
+ if ((collection == NULL) && (item->type != COL_TYPE_COLLECTION)) {
+ TRACE_ERROR_STRING("Collection can't be NULL", "");
+ return EINVAL;
+ }
/* Add item to collection */
if (subcollection == NULL) {
@@ -327,35 +849,177 @@ static struct collection_item *add_property(struct collection_item *collection,
}
else {
TRACE_INFO_STRING("Subcollection id not null, searching", subcollection);
- *error = find_item_and_do(collection, subcollection,
- COL_TYPE_COLLECTIONREF,
- COL_TRAVERSE_DEFAULT,
- get_subcollection, (void *)(&acceptor),
- COLLECTION_ACTION_FIND);
- if (*error) {
- TRACE_ERROR_NUMBER("Search for subcollection returned error:", *error);
- delete_item(item);
- return NULL;
+ error = find_item_and_do(collection, subcollection,
+ COL_TYPE_COLLECTIONREF,
+ COL_TRAVERSE_DEFAULT,
+ get_subcollection, (void *)(&acceptor),
+ COLLECTION_ACTION_FIND);
+ if (error) {
+ TRACE_ERROR_NUMBER("Search for subcollection returned error:", error);
+ return error;
}
if (acceptor == NULL) {
TRACE_ERROR_STRING("Search for subcollection returned NULL pointer", "");
- delete_item(item);
- *error = ENOENT;
- return NULL;
+ return ENOENT;
}
}
- *error = add_item_to_collection(acceptor, item);
- if (*error) {
- TRACE_ERROR_NUMBER("Failed to add item to collection error:", *error);
+
+ /* Instert item to the current collection */
+ error = insert_item_into_current(acceptor,
+ item,
+ disposition,
+ refprop,
+ index,
+ flags);
+
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to insert item into current collection", error);
+ return error;
+ }
+
+ TRACE_FLOW_STRING("insert_item", "Exit");
+ return EOK;
+}
+
+
+/* Insert property with reference.
+ * This is internal function so we do not check parameters.
+ * See external wrapper below.
+ */
+static int insert_property_with_ref_int(struct collection_item *collection,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ int type,
+ void *data,
+ int length,
+ struct collection_item **ret_ref)
+{
+ struct collection_item *item = NULL;
+ int error;
+
+ TRACE_FLOW_STRING("insert_property_with_ref_int", "Entry point.");
+
+ /* Create a new property out of the given parameters */
+ error = allocate_item(&item, property, data, length, type);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to allocate item", error);
+ return error;
+ }
+
+ /* Send the property to the insert_item function */
+ error = insert_item(collection,
+ subcollection,
+ item,
+ disposition,
+ refprop,
+ index,
+ flags);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to insert item", error);
delete_item(item);
- return NULL;
+ return error;
+ }
+
+ if (ret_ref) *ret_ref = item;
+
+ TRACE_FLOW_STRING("insert_property_with_ref_int", "Exit");
+ return EOK;
+}
+
+/* This is public function so we need to check the validity
+ * of the arguments.
+ */
+int insert_property_with_ref(struct collection_item *collection,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ int type,
+ void *data,
+ int length,
+ struct collection_item **ret_ref)
+{
+ int error;
+
+ TRACE_FLOW_STRING("insert_property_with_ref", "Entry point.");
+
+ /* Check that collection is not empty */
+ if (collection == NULL) {
+ TRACE_ERROR_STRING("Collection cant be NULL", "");
+ return EINVAL;
}
- TRACE_FLOW_STRING("add_property", "Success Exit.");
- return item;
+ error = insert_property_with_ref_int(collection,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ type,
+ data,
+ length,
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_property_with_ref_int Returning:", error);
+ return error;
}
+/* TRAVERSE HANDLERS */
+
+/* Special handler to just set a flag if the item is found */
+static int is_in_item_handler(const char *property,
+ int property_len,
+ int type,
+ void *data,
+ int length,
+ void *found,
+ int *dummy)
+{
+ TRACE_FLOW_STRING("is_in_item_handler", "Entry.");
+ TRACE_INFO_STRING("Property:", property);
+ TRACE_INFO_NUMBER("Property length:", property_len);
+ TRACE_INFO_NUMBER("Type:", type);
+ TRACE_INFO_NUMBER("Length:", length);
+
+ *((int *)(found)) = COL_MATCH;
+
+ TRACE_FLOW_STRING("is_in_item_handler", "Success Exit.");
+
+ return EOK;
+}
+
+/* Special handler to retrieve the sub collection */
+static int get_subcollection(const char *property,
+ int property_len,
+ int type,
+ void *data,
+ int length,
+ void *found,
+ int *dummy)
+{
+ TRACE_FLOW_STRING("get_subcollection", "Entry.");
+ TRACE_INFO_STRING("Property:", property);
+ TRACE_INFO_NUMBER("Property length:", property_len);
+ TRACE_INFO_NUMBER("Type:", type);
+ TRACE_INFO_NUMBER("Length:", length);
+
+ *((struct collection_item **)(found)) = *((struct collection_item **)(data));
+
+ TRACE_FLOW_STRING("get_subcollection","Success Exit.");
+
+ return EOK;
+
+}
+
+
/* CLEANUP */
@@ -364,8 +1028,6 @@ static struct collection_item *add_property(struct collection_item *collection,
* as memory is freed!!! */
static void delete_collection(struct collection_item *ci)
{
- struct collection_item *other_collection;
-
TRACE_FLOW_STRING("delete_collection", "Entry.");
if (ci == NULL) {
@@ -377,14 +1039,6 @@ static void delete_collection(struct collection_item *ci)
delete_collection(ci->next);
- /* Handle external or embedded collection */
- if(ci->type == COL_TYPE_COLLECTIONREF) {
- /* Our data is a pointer to a whole external collection so dereference
- * it or delete */
- other_collection = *((struct collection_item **)(ci->data));
- destroy_collection(other_collection);
- }
-
/* Delete this item */
delete_item(ci);
TRACE_FLOW_STRING("delete_collection", "Exit.");
@@ -790,13 +1444,13 @@ static int update_current_item(struct collection_item *current,
/* Traverse handler for simple traverse function */
/* Handler must be able to deal with NULL current item */
-inline static int simple_traverse_handler(struct collection_item *head,
- struct collection_item *previous,
- struct collection_item *current,
- void *traverse_data,
- item_fn user_item_handler,
- void *custom_data,
- int *stop)
+static int simple_traverse_handler(struct collection_item *head,
+ struct collection_item *previous,
+ struct collection_item *current,
+ void *traverse_data,
+ item_fn user_item_handler,
+ void *custom_data,
+ int *stop)
{
int error = EOK;
@@ -816,6 +1470,80 @@ inline static int simple_traverse_handler(struct collection_item *head,
return error;
}
+/* Traverse handler for to find parent */
+static int parent_traverse_handler(struct collection_item *head,
+ struct collection_item *previous,
+ struct collection_item *current,
+ void *traverse_data,
+ item_fn user_item_handler,
+ void *custom_data,
+ int *stop)
+{
+ struct property_search *to_find;
+ int done = 0;
+ int match = 0;
+
+ TRACE_FLOW_STRING("parent_traverse_handler", "Entry.");
+
+ to_find = (struct property_search *)custom_data;
+
+ /* Check hashes first */
+ if(to_find->hash == current->phash) {
+
+ TRACE_INFO_NUMBER("Looking for HASH:", (unsigned)(to_find->hash));
+ TRACE_INFO_NUMBER("Current HASH:", (unsigned)(current->phash));
+
+ /* Check type if we are asked to use type */
+ if ((to_find->use_type) && (!(to_find->type & current->type))) {
+ TRACE_FLOW_STRING("parent_traverse_handler. Returning:","Exit. Hash is Ok, type is not");
+ return EOK;
+ }
+
+ /* Validate property. Make sure we include terminating 0 in the comparison */
+ if (strncasecmp(current->property, to_find->property, current->property_len + 1) == 0) {
+
+ match = 1;
+ to_find->found = 1;
+
+ /* Do the right thing based on index */
+ /* If index is 0 we are looking for the first value in the list of duplicate properties */
+ if (to_find->index == 0) done = 1;
+ /* If index is non zero we are looking for N-th instance of the dup property */
+ else if (to_find->index > 0) {
+ if (to_find->count == to_find->index) done = 1;
+ else {
+ /* Record found instance and move on */
+ to_find->parent = previous;
+ (to_find->count)++;
+ }
+ }
+ /* If we are looking for last instance just record it */
+ else to_find->parent = previous;
+ }
+ }
+
+ if (done) {
+ *stop = 1;
+ *((struct collection_item **)traverse_data) = previous;
+ }
+ else {
+ /* As soon as we found first non matching one but there was a match
+ * return the parent of the last found item.
+ */
+ if (((!match) || (current->next == NULL)) && (to_find->index != 0) && (to_find->found)) {
+ *stop = 1;
+ if (to_find->index == -2)
+ *((struct collection_item **)traverse_data) = to_find->parent;
+ else
+ *((struct collection_item **)traverse_data) = to_find->parent->next;
+ }
+ }
+
+
+ TRACE_FLOW_STRING("parent_traverse_handler. Returning:","Exit");
+ return EOK;
+}
+
/* Traverse callback for find & delete function */
static int act_traverse_handler(struct collection_item *head,
@@ -832,7 +1560,6 @@ static int act_traverse_handler(struct collection_item *head,
int length;
struct path_data *temp;
struct collection_header *header;
- struct collection_item *other;
char *property;
int property_len;
struct update_property *update_data;
@@ -934,13 +1661,6 @@ static int act_traverse_handler(struct collection_item *head,
/* Make sure we tell the caller we found a match */
if (custom_data != NULL)
*(int *)custom_data = COL_MATCH;
- /* Dereference external collections */
- if (current->type == COL_TYPE_COLLECTIONREF) {
- TRACE_INFO_STRING("Dereferencing a referenced collection.", "");
- other = *((struct collection_item **)current->data);
- header = (struct collection_header *)other->data;
- destroy_collection(other);
- }
/* Adjust header of the collection */
header = (struct collection_header *)head->data;
@@ -1027,18 +1747,35 @@ static int copy_traverse_handler(struct collection_item *head,
/* Add new item to a collection
* all references are now sub collections */
- add_property(parent, NULL, item->property,
- (void *)(&new_collection),
- sizeof(struct collection_item **),
- COL_TYPE_COLLECTIONREF, &error);
+ error = insert_property_with_ref_int(parent,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ item->property,
+ COL_TYPE_COLLECTIONREF,
+ (void *)(&new_collection),
+ sizeof(struct collection_item **),
+ NULL);
if (error) {
TRACE_ERROR_NUMBER("Add property returned error:", error);
return error;
}
}
else {
- add_property(parent, NULL, item->property,
- item->data, item->length, item->type, &error);
+
+ error = insert_property_with_ref_int(parent,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ item->property,
+ item->type,
+ item->data,
+ item->length,
+ NULL);
if (error) {
TRACE_ERROR_NUMBER("Add property returned error:", error);
return error;
@@ -1073,9 +1810,19 @@ int create_collection(struct collection_item **ci, const char *name,
header.cclass = cclass;
/* Create a collection type property */
- handle = add_property(NULL, NULL, name,
- &header, sizeof(header),
- COL_TYPE_COLLECTION, &error);
+ error = insert_property_with_ref_int(NULL,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ name,
+ COL_TYPE_COLLECTION,
+ &header,
+ sizeof(header),
+ &handle);
+
+
if (error) return error;
*ci = handle;
@@ -1120,361 +1867,6 @@ void destroy_collection(struct collection_item *ci)
}
-/* PROPERTIES */
-
-/* Add a string property.
- If length equals 0, the length is determined based on the string.
- Lenght INCLUDES the terminating 0 */
-inline int add_str_property(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- char *string, int length)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_str_property", "Entry.");
-
- if (length == 0)
- length = strlen(string) + 1;
-
- add_property(ci, subcollection, property,
- (void *)(string), length, COL_TYPE_STRING, &error);
-
- TRACE_FLOW_NUMBER("add_str_property returning", error);
- return error;
-}
-
-/* Add a binary property. */
-inline int add_binary_property(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- void *binary_data, int length)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_binary_property", "Entry.");
-
- add_property(ci, subcollection, property,
- binary_data, length, COL_TYPE_BINARY, &error);
-
- TRACE_FLOW_NUMBER("add_binary_property returning", error);
- return error;
-}
-
-/* Add an int property. */
-inline int add_int_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, int number)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_int_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&number), sizeof(int),
- COL_TYPE_INTEGER, &error);
-
- TRACE_FLOW_NUMBER("add_int_property returning", error);
- return error;
-}
-
-/* Add an unsigned int property. */
-inline int add_unsigned_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, unsigned int number)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_unsigned_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&number), sizeof(int), COL_TYPE_UNSIGNED, &error);
-
- TRACE_FLOW_NUMBER("add_unsigned_property returning", error);
- return error;
-}
-
-/* Add an long property. */
-inline int add_long_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, long number)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_long_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&number), sizeof(long), COL_TYPE_LONG, &error);
-
- TRACE_FLOW_NUMBER("add_long_property returning", error);
- return error;
-}
-
-/* Add an unsigned long property. */
-inline int add_ulong_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, unsigned long number)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_ulong_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&number), sizeof(long),
- COL_TYPE_ULONG, &error);
-
- TRACE_FLOW_NUMBER("add_ulong_property returning", error);
- return error;
-}
-
-/* Add a double property. */
-inline int add_double_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, double number)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_double_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&number), sizeof(double), COL_TYPE_DOUBLE, &error);
-
- TRACE_FLOW_NUMBER("add_double_property returning", error);
- return error;
-}
-
-/* Add a bool property. */
-inline int add_bool_property(struct collection_item *ci,
- const char *subcollection,
- const char *property, unsigned char logical)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_bool_property", "Entry.");
-
- add_property(ci, subcollection, property,
- (void *)(&logical), sizeof(unsigned char),
- COL_TYPE_BOOL, &error);
-
- TRACE_FLOW_NUMBER("add_bool_property returning", error);
- return error;
-}
-
-/* A function to add a property */
-inline int add_any_property(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- int type, void *data, int length)
-{
- int error = EOK;
-
- TRACE_FLOW_STRING("add_any_property", "Entry.");
-
- add_property(ci, subcollection, property, data, length, type, &error);
-
- TRACE_FLOW_NUMBER("add_any_property returning", error);
- return error;
-}
-
-/* Add a string property.
- If length equals 0, the length is determined based on the string.
- Lenght INCLUDES the terminating 0 */
-inline int add_str_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- char *string, int length,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_str_property_with_ref", "Entry.");
-
- if (length == 0) length = strlen(string) + 1;
-
- item = add_property(ci, subcollection, property,
- (void *)(string), length, COL_TYPE_STRING, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_str_property_with_ref returning", error);
- return error;
-}
-
-/* Add a binary property. */
-inline int add_binary_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- void *binary_data, int length,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_binary_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- binary_data, length, COL_TYPE_BINARY, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_binary_property_with_ref returning", error);
- return error;
-}
-
-/* Add an int property. */
-inline int add_int_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- int number,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_int_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&number), sizeof(int),
- COL_TYPE_INTEGER, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_int_property_with_ref returning", error);
- return error;
-}
-
-/* Add an unsigned int property. */
-inline int add_unsigned_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- unsigned int number,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_unsigned_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&number), sizeof(int),
- COL_TYPE_UNSIGNED, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_unsigned_property_with_ref returning", error);
- return error;
-}
-
-/* Add an long property. */
-inline int add_long_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- long number,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_long_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&number), sizeof(long), COL_TYPE_LONG, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_long_property_with_ref returning", error);
- return error;
-}
-
-/* Add an unsigned long property. */
-inline int add_ulong_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- unsigned long number,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_ulong_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&number), sizeof(long),
- COL_TYPE_ULONG, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_ulong_property_with_ref returning", error);
- return error;
-}
-
-/* Add a double property. */
-inline int add_double_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- double number,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_double_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&number), sizeof(double),
- COL_TYPE_DOUBLE, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_double_property_with_ref returning", error);
- return error;
-}
-
-/* Add a bool property. */
-inline int add_bool_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- unsigned char logical,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_bool_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- (void *)(&logical), sizeof(unsigned char),
- COL_TYPE_BOOL, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_bool_property_with_ref returning", error);
- return error;
-}
-
-/* A function to add a property */
-inline int add_any_property_with_ref(struct collection_item *ci,
- const char *subcollection,
- const char *property,
- int type,
- void *data,
- int length,
- struct collection_item **ref_ret)
-{
- int error = EOK;
- struct collection_item *item;
-
- TRACE_FLOW_STRING("add_any_property_with_ref", "Entry.");
-
- item = add_property(ci, subcollection, property,
- data, length, type, &error);
-
- if (ref_ret != NULL) *ref_ret = item;
-
- TRACE_FLOW_NUMBER("add_any_property_with_ref returning", error);
- return error;
-}
@@ -1602,6 +1994,7 @@ int get_reference_from_item(struct collection_item *ci,
/* ADDITION */
/* Add collection to collection */
+/* FIXME - allow to add collection to a collection with disposition */
int add_collection_to_collection(
struct collection_item *ci, /* Collection handle to with we add another collection */
const char *sub_collection_name, /* Name of the sub collection to which
@@ -1673,12 +2066,19 @@ int add_collection_to_collection(
collection_to_add->property);
/* Create a pointer to external collection */
/* For future thread safety: Transaction start -> */
- add_property(acceptor, NULL, name_to_use,
- (void *)(&collection_to_add),
- sizeof(struct collection_item **),
- COL_TYPE_COLLECTIONREF, &error);
-
- TRACE_INFO_NUMBER("Type of the header element after add_property:",
+ error = insert_property_with_ref_int(acceptor,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ name_to_use,
+ COL_TYPE_COLLECTIONREF,
+ (void *)(&collection_to_add),
+ sizeof(struct collection_item **),
+ NULL);
+
+ TRACE_INFO_NUMBER("Type of the header element after adding property:",
collection_to_add->type);
TRACE_INFO_STRING("Header name we just added.",
collection_to_add->property);
@@ -1707,10 +2107,18 @@ int add_collection_to_collection(
TRACE_INFO_STRING("Header name we are adding to.",
acceptor->property);
- add_property(acceptor, NULL, name_to_use,
- (void *)(&collection_to_add),
- sizeof(struct collection_item **),
- COL_TYPE_COLLECTIONREF, &error);
+ error = insert_property_with_ref_int(acceptor,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ name_to_use,
+ COL_TYPE_COLLECTIONREF,
+ (void *)(&collection_to_add),
+ sizeof(struct collection_item **),
+ NULL);
+
TRACE_INFO_NUMBER("Adding property returned:", error);
break;
@@ -1729,10 +2137,17 @@ int add_collection_to_collection(
TRACE_INFO_STRING("Acceptor collection.", acceptor->property);
TRACE_INFO_NUMBER("Acceptor collection type.", acceptor->type);
- add_property(acceptor, NULL, name_to_use,
- (void *)(&collection_copy),
- sizeof(struct collection_item **),
- COL_TYPE_COLLECTIONREF, &error);
+ error = insert_property_with_ref_int(acceptor,
+ NULL,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ name_to_use,
+ COL_TYPE_COLLECTIONREF,
+ (void *)(&collection_copy),
+ sizeof(struct collection_item **),
+ NULL);
/* -> Transaction end */
TRACE_INFO_NUMBER("Adding property returned:", error);
@@ -1750,10 +2165,10 @@ int add_collection_to_collection(
/* Function to traverse the entire collection including optionally
* sub collections */
-inline int traverse_collection(struct collection_item *ci,
- int mode_flags,
- item_fn item_handler,
- void *custom_data)
+int traverse_collection(struct collection_item *ci,
+ int mode_flags,
+ item_fn item_handler,
+ void *custom_data)
{
int error = EOK;
@@ -1774,11 +2189,11 @@ inline int traverse_collection(struct collection_item *ci,
/* CHECK */
/* Convenience function to check if specific property is in the collection */
-inline int is_item_in_collection(struct collection_item *ci,
- const char *property_to_find,
- int type,
- int mode_flags,
- int *found)
+int is_item_in_collection(struct collection_item *ci,
+ const char *property_to_find,
+ int type,
+ int mode_flags,
+ int *found)
{
int error;
@@ -1799,12 +2214,12 @@ inline int is_item_in_collection(struct collection_item *ci,
/* Search function. Looks up an item in the collection based on the property.
Essentually it is a traverse function with spacial traversing logic.
*/
-inline int get_item_and_do(struct collection_item *ci, /* Collection to find things in */
- const char *property_to_find, /* Name to match */
- int type, /* Type filter */
- int mode_flags, /* How to traverse the collection */
- item_fn item_handler, /* Function to call when the item is found */
- void *custom_data) /* Custom data passed around */
+int get_item_and_do(struct collection_item *ci, /* Collection to find things in */
+ const char *property_to_find, /* Name to match */
+ int type, /* Type filter */
+ int mode_flags, /* How to traverse the collection */
+ item_fn item_handler, /* Function to call when the item is found */
+ void *custom_data) /* Custom data passed around */
{
int error = EOK;
@@ -1822,11 +2237,11 @@ inline int get_item_and_do(struct collection_item *ci, /* Collection to fi
/* Get raw item */
-inline int get_item(struct collection_item *ci, /* Collection to find things in */
- const char *property_to_find, /* Name to match */
- int type, /* Type filter */
- int mode_flags, /* How to traverse the collection */
- struct collection_item **item) /* Found item */
+int get_item(struct collection_item *ci, /* Collection to find things in */
+ const char *property_to_find, /* Name to match */
+ int type, /* Type filter */
+ int mode_flags, /* How to traverse the collection */
+ struct collection_item **item) /* Found item */
{
int error = EOK;
@@ -1844,10 +2259,10 @@ inline int get_item(struct collection_item *ci, /* Collection to find thin
/* DELETE */
/* Delete property from the collection */
-inline int delete_property(struct collection_item *ci, /* Collection to find things in */
- const char *property_to_find, /* Name to match */
- int type, /* Type filter */
- int mode_flags) /* How to traverse the collection */
+int delete_property(struct collection_item *ci, /* Collection to find things in */
+ const char *property_to_find, /* Name to match */
+ int type, /* Type filter */
+ int mode_flags) /* How to traverse the collection */
{
int error = EOK;
int found;
@@ -1898,140 +2313,6 @@ int update_property(struct collection_item *ci, /* Collection to find things
return error;
}
-/* Update a string property in the collection.
- * Length should include the terminating 0 */
-inline int update_str_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- char *string,
- int length)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_str_property", "Entry.");
-
- if (length == 0) length = strlen(string) + 1;
- error = update_property(ci, property, COL_TYPE_STRING,
- (void *)string, length, mode_flags);
-
- TRACE_FLOW_NUMBER("update_str_property Returning", error);
- return error;
-}
-
-/* Update a binary property in the collection. */
-inline int update_binary_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- void *binary_data,
- int length)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_binary_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_BINARY,
- binary_data, length, mode_flags);
-
- TRACE_FLOW_NUMBER("update_binary_property Returning", error);
- return error;
-}
-
-/* Update an int property in the collection. */
-inline int update_int_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- int number)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_int_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_INTEGER,
- (void *)(&number), sizeof(int), mode_flags);
-
- TRACE_FLOW_NUMBER("update_int_property Returning", error);
- return error;
-}
-
-/* Update an unsigned int property. */
-inline int update_unsigned_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- unsigned int number)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_unsigned_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_UNSIGNED,
- (void *)(&number), sizeof(unsigned int),
- mode_flags);
-
- TRACE_FLOW_NUMBER("update_unsigned_property Returning", error);
- return error;
-}
-/* Update a long property. */
-inline int update_long_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- long number)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_long_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_LONG,
- (void *)(&number), sizeof(long), mode_flags);
-
- TRACE_FLOW_NUMBER("update_long_property Returning", error);
- return error;
-
-}
-
-/* Update an unsigned long property. */
-inline int update_ulong_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- unsigned long number)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_ulong_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_ULONG,
- (void *)(&number), sizeof(unsigned long),
- mode_flags);
-
- TRACE_FLOW_NUMBER("update_ulong_property Returning", error);
- return error;
-}
-
-/* Update a double property. */
-inline int update_double_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- double number)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_double_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_DOUBLE,
- (void *)(&number), sizeof(double), mode_flags);
-
- TRACE_FLOW_NUMBER("update_double_property Returning", error);
- return error;
-}
-
-/* Update a bool property. */
-inline int update_bool_property(struct collection_item *ci,
- const char *property,
- int mode_flags,
- unsigned char logical)
-{
- int error = EOK;
- TRACE_FLOW_STRING("update_bool_property", "Entry.");
-
- error = update_property(ci, property, COL_TYPE_BOOL,
- (void *)(&logical), sizeof(unsigned char),
- mode_flags);
-
- TRACE_FLOW_NUMBER("update_bool_property Returning", error);
- return error;
-}
/* Function to modify the item */
int modify_item(struct collection_item *item,
@@ -2050,6 +2331,10 @@ int modify_item(struct collection_item *item,
}
if (property != NULL) {
+ if (validate_property(property)) {
+ TRACE_ERROR_STRING("Invalid chracters in the property name", property);
+ return EINVAL;
+ }
free(item->property);
item->property = strdup(property);
if (item->property == NULL) {
@@ -2058,166 +2343,38 @@ int modify_item(struct collection_item *item,
}
}
- /* If type is different or same but it is string or binary we need to
- * replace the storage */
- if ((item->type != type) ||
- ((item->type == type) &&
- ((item->type == COL_TYPE_STRING) || (item->type == COL_TYPE_BINARY)))) {
- TRACE_INFO_STRING("Replacing item data buffer", "");
- free(item->data);
- item->data = malloc(length);
- if (item->data == NULL) {
- TRACE_ERROR_STRING("Failed to allocate memory", "");
- item->length = 0;
- return ENOMEM;
+ /* We need to change data ? */
+ if(length) {
+
+ /* If type is different or same but it is string or binary we need to
+ * replace the storage */
+ if ((item->type != type) ||
+ ((item->type == type) &&
+ ((item->type == COL_TYPE_STRING) || (item->type == COL_TYPE_BINARY)))) {
+ TRACE_INFO_STRING("Replacing item data buffer", "");
+ free(item->data);
+ item->data = malloc(length);
+ if (item->data == NULL) {
+ TRACE_ERROR_STRING("Failed to allocate memory", "");
+ item->length = 0;
+ return ENOMEM;
+ }
+ item->length = length;
}
- item->length = length;
- }
+ TRACE_INFO_STRING("Overwriting item data", "");
+ memcpy(item->data, data, item->length);
+ item->type = type;
- TRACE_INFO_STRING("Overwriting item data", "");
- memcpy(item->data, data, item->length);
- item->type = type;
-
- if (item->type == COL_TYPE_STRING)
- ((char *)(item->data))[item->length - 1] = '\0';
+ if (item->type == COL_TYPE_STRING)
+ ((char *)(item->data))[item->length - 1] = '\0';
+ }
TRACE_FLOW_STRING("modify_item", "Exit");
return EOK;
}
-/* Convinience functions that wrap modify_item(). */
-/* Modify item data to be str */
-inline int modify_str_item(struct collection_item *item,
- const char *property,
- char *string,
- int length)
-{
- int len;
- int error;
-
- TRACE_FLOW_STRING("modify_str_item", "Entry");
-
- if (length != 0)
- len = length;
- else
- len = strlen(string) + 1;
-
- error = modify_item(item, property, COL_TYPE_STRING, (void *)string, len);
-
- TRACE_FLOW_STRING("modify_str_item", "Exit");
- return error;
-}
-
-/* Modify item data to be binary */
-inline int modify_binary_item(struct collection_item *item,
- const char *property,
- void *binary_data,
- int length)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_binary_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_BINARY, binary_data, length);
-
- TRACE_FLOW_STRING("modify_binary_item", "Exit");
- return error;
-}
-
-/* Modify item data to be bool */
-inline int modify_bool_item(struct collection_item *item,
- const char *property,
- unsigned char logical)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_bool_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_BOOL, (void *)(&logical), 1);
-
- TRACE_FLOW_STRING("modify_bool_item", "Exit");
- return error;
-}
-
-/* Modify item data to be int */
-inline int modify_int_item(struct collection_item *item,
- const char *property,
- int number)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_int_item","Entry");
-
- error = modify_item(item, property, COL_TYPE_INTEGER,
- (void *)(&number), sizeof(int));
-
- TRACE_FLOW_STRING("modify_int_item", "Exit");
- return error;
-}
-
-/* Modify item data to be long */
-inline int modify_long_item(struct collection_item *item,
- const char *property,
- long number)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_long_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_LONG,
- (void *)(&number), sizeof(long));
-
- TRACE_FLOW_STRING("modify_long_item", "Exit");
- return error;
-}
-
-/* Modify item data to be unigned long */
-inline int modify_ulong_item(struct collection_item *item,
- const char *property,
- unsigned long number)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_ulong_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_ULONG,
- (void *)(&number), sizeof(unsigned long));
-
- TRACE_FLOW_STRING("modify_ulong_item", "Exit");
- return error;
-}
-
-inline int modify_unsigned_item(struct collection_item *item,
- const char *property,
- unsigned number)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_unsigned_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_UNSIGNED,
- (void *)(&number), sizeof(unsigned));
-
- TRACE_FLOW_STRING("modify_unsigned_item", "Exit");
- return error;
-}
-
-inline int modify_double_item(struct collection_item *item,
- const char *property,
- double number)
-{
- int error;
-
- TRACE_FLOW_STRING("modify_double_item", "Entry");
-
- error = modify_item(item, property, COL_TYPE_DOUBLE,
- (void *)(&number), sizeof(double));
-
- TRACE_FLOW_STRING("modify_double_item", "Exit");
- return error;
-}
/* Grow iteration stack */
@@ -2297,7 +2454,7 @@ int bind_iterator(struct collection_iterator **iterator,
/* Stop processing this subcollection and move to the next item in the
* collection 'level' levels up.*/
-inline int iterate_up(struct collection_iterator *iterator, int level)
+int iterate_up(struct collection_iterator *iterator, int level)
{
TRACE_FLOW_STRING("iterate_up", "Entry");
@@ -2314,8 +2471,9 @@ inline int iterate_up(struct collection_iterator *iterator, int level)
TRACE_FLOW_STRING("iterate_up", "Exit");
return EOK;
}
+
/* How deep are we relative to the top level.*/
-inline int get_iterator_depth(struct collection_iterator *iterator, int *depth)
+int get_iterator_depth(struct collection_iterator *iterator, int *depth)
{
TRACE_FLOW_STRING("iterate_up", "Entry");
@@ -2333,7 +2491,7 @@ inline int get_iterator_depth(struct collection_iterator *iterator, int *depth)
/* Unbind the iterator from the collection */
-inline void unbind_iterator(struct collection_iterator *iterator)
+void unbind_iterator(struct collection_iterator *iterator)
{
TRACE_FLOW_STRING("unbind_iterator", "Entry.");
if (iterator != NULL) {
@@ -2477,7 +2635,7 @@ int iterate_collection(struct collection_iterator *iterator,
}
/* Set collection class */
-inline int set_collection_class(struct collection_item *item, unsigned cclass)
+int set_collection_class(struct collection_item *item, unsigned cclass)
{
struct collection_header *header;
@@ -2495,8 +2653,8 @@ inline int set_collection_class(struct collection_item *item, unsigned cclass)
}
/* Get collection class */
-inline int get_collection_class(struct collection_item *item,
- unsigned *cclass)
+int get_collection_class(struct collection_item *item,
+ unsigned *cclass)
{
struct collection_header *header;
@@ -2514,8 +2672,8 @@ inline int get_collection_class(struct collection_item *item,
}
/* Get collection count */
-inline int get_collection_count(struct collection_item *item,
- unsigned *count)
+int get_collection_count(struct collection_item *item,
+ unsigned *count)
{
struct collection_header *header;
@@ -2535,7 +2693,7 @@ inline int get_collection_count(struct collection_item *item,
/* Convinience function to check if the collection is of the specific class */
/* In case of internal error assumes that collection is not of the right class */
-inline int is_of_class(struct collection_item *item, unsigned cclass)
+int is_of_class(struct collection_item *item, unsigned cclass)
{
int error = EOK;
unsigned ret_class = 0;
@@ -2550,26 +2708,26 @@ inline int is_of_class(struct collection_item *item, unsigned cclass)
}
/* Get propery */
-inline const char *get_item_property(struct collection_item *ci,int *property_len)
+const char *get_item_property(struct collection_item *ci,int *property_len)
{
if (property_len != NULL) *property_len = ci->property_len;
return ci->property;
}
/* Get type */
-inline int get_item_type(struct collection_item *ci)
+int get_item_type(struct collection_item *ci)
{
return ci->type;
}
/* Get length */
-inline int get_item_length(struct collection_item *ci)
+int get_item_length(struct collection_item *ci)
{
return ci->length;
}
/* Get data */
-inline const void *get_item_data(struct collection_item *ci)
+const void *get_item_data(struct collection_item *ci)
{
return ci->data;
}
diff --git a/common/collection/collection.h b/common/collection/collection.h
index 687f468d7..28622a505 100644
--- a/common/collection/collection.h
+++ b/common/collection/collection.h
@@ -48,6 +48,7 @@
Useful when traversing
collections */
+
/* Any data we deal with can't be longer than this */
/* FIXME - make it compile time option */
#define COL_MAX_DATA 65535
@@ -151,11 +152,11 @@ struct collection_iterator;
* empty.
* When you put items into a bag you do not see the contents of the bag.
* You just hold the bag. How many other bags inside this bag you do not know.
- * But you might know that you put a "valet" somewhere there.
- * You ask the bag you hold: "find my valet and give it to me".
- * get_item function will return you the item that is you "valet".
+ * But you might know that you put a "wallet" somewhere there.
+ * You ask the bag you hold: "find my wallet and give it to me".
+ * get_item function will return you the item that is your "wallet".
* You can then change something or just get information about the item you
- * retrieved. But in most cases you do not the valet itself. You want to get
+ * retrieved. But in most cases you do not the wallet itself. You want to get
* something from the vallet or put something into it. IMO money would be an
* obvious choice. To do this you use update_xxx_property functions.
* There might be a bag somewhere deep and you might want to add something to
@@ -163,13 +164,13 @@ struct collection_iterator;
* want the item to be added to. If this sub collection argument is NULL top
* level collection is assumed.
* The search in the collections users a dotted notation to refer to an item (or
- * property). You can search for "valet" and it will find any first instance of
- * the "valet" in your luggage. But you might have two valets. One is yours and
- * another is your significant other's. So you might say find "my.valet".
- * It will find valet in your bad (collection) named "my". This collection can
+ * property). You can search for "wallet" and it will find any first instance of
+ * the "wallet" in your luggage. But you might have two wallets. One is yours and
+ * another is your significant other's. So you might say find "my.wallet".
+ * It will find wallet in your bad (collection) named "my". This collection can
* be many levels deep inside other collections. You do not need to know the
* full path to get to it. But if you have the full path you can use the fill
- * path like this "luggage.newbags.my.valet".
+ * path like this "luggage.newbags.my.wallet".
* It is useful to be able to put bags into bags as well as get them out of each
* other. When the collection is created the header keeps a reference count on
* how many copies of the collection are known to the world. So one can put a
@@ -181,14 +182,27 @@ struct collection_iterator;
* use.
*/
-/* Function that creates an named collection */
+/* Function that creates a named collection */
int create_collection(struct collection_item **ci, const char *name,
unsigned cclass);
+/* Function that creates a named collection using a memory descriptor */
+/* FIXME - function is a placeholder. It is not implemented yet.
+ * will be added in future together with the definition of the
+ * descriptor structure.
+ * The purpose is to control the internal implementation of the collection
+ * a) Use hash table for faster searches if the collection is expected to be large.
+ * b) Define memory functions to use.
+ */
+/*
+int create_collection_ex(struct collection_item **ci, const char *name,
+ unsigned cclass, struct cdescriptor *descrptor);
+*/
+
/* Function that destroys a collection */
void destroy_collection(struct collection_item *ci);
-/* Family of functions that add properties to an event */
+/* Family of functions that add properties to a collection */
/* See details about subcollection argument above. */
/* Family includes the following convinience functions: */
/* Add a string property to collection. The length should include the
@@ -397,7 +411,7 @@ const void *get_item_data(struct collection_item *ci);
/* If you want to modify the item that you got as a result of iterating through collection
* or by calling get_item(). If you want to rename item provide a new name in the property
- * argument. If you want the data to remain unchanged use NULL as data parameter.
+ * argument. If you want the data to remain unchanged use 0 as length parameter.
* If item is a reference or collection the call will return error.
* Previous type and data of the item is destroyed.
*/
@@ -407,7 +421,14 @@ int modify_item(struct collection_item *item,
void *data,
int length);
-/* Convenience functions that wrap modify_tem(). */
+/* Rename the item */
+int modify_item_property(struct collection_item *item,
+ const char *property);
+
+/* Convenience functions that wrap modify_item().
+ * They always assign new value.
+ * To rename the property just use modify_item_property();
+ */
int modify_str_item(struct collection_item *item,
const char *property,
char *string,
@@ -499,9 +520,10 @@ int get_collection_class(struct collection_item *item, /* Collection */
/* Get collection count */
int get_collection_count(struct collection_item *item, /* Collection */
unsigned *count); /* Number of elements in
- this collection.
- Each subcollection is
- counted as 1 element.
+ * this collection.
+ * Each subcollection is
+ * counted as 1 element.
+ * Header is also counted.
*/
/* Convenience function to check if the collection is of the specific class */
@@ -510,5 +532,339 @@ int is_of_class(struct collection_item *item, /* Collection */
unsigned cclass); /* Class of the collection */
+/*
+ * Series of collection functions that allow using collection as a stack or a FIFO
+ */
+
+
+/* Extract the item from the collection */
+/* The header will not be considered for extraction. */
+int extract_item(struct collection_item *ci, /* Top collection */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Which to extract */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to extract. See notes. */
+ int type, /* Type filter */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+/* Similar extraction function as above just considers only one level. */
+int extract_item_from_current(struct collection_item *ci, /* Top collection */
+ int disposition, /* Which to extract */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to extract. See notes. */
+ int type, /* Type filter */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+/* Insert item to the collection */
+/* WARNING: Only use this function to insert items
+ * that were extracted using extract_item().
+ * NEVER use it with items that were returned
+ * by get_item() or add_xxx_property_with_ref() or
+ * with insert_xxx_property_with_ref().
+ * The fundamental difference is that when you extracted item
+ * using extract_item() it stops to be managed by a collection.
+ * With such item you can:
+ * a) Insert this item into another (or same) collection
+ * b) Get item information using get_item_xxx() functions.
+ * c) Destroy item using delete_item().
+ * You are required to do either a) or c) with such item.
+ */
+int insert_item(struct collection_item *collection, /* Top collection */
+ const char *subcollection, /* Sub collection */
+ struct collection_item *item, /* Item to insert */
+ int disposition, /* What should be the position of the item */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to extract. See notes. */
+ unsigned flags); /* Flags that control naming issues */
+
+/* Insert the item into the top level collection (similar to the function above)
+ * but does not provide access to the sub collection.
+ */
+int insert_item_into_current(struct collection_item *collection,
+ struct collection_item *item,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags);
+
+
+
+/* Function to delete the item */
+void delete_item(struct collection_item *item);
+
+/* Possible dispositions for insert, extract and delete function(s).
+ * Not all of these dispositions are implemented day one.
+ * If disposition is not implemented the function
+ * will return error ENOSYS.
+ */
+#define COL_DSP_END 0 /* Add property to the end of the collection */
+ /* Extract or delete last property in collection */
+#define COL_DSP_FRONT 1 /* Add property to the top of the collection */
+ /* Extract or delete firat property in collection */
+#define COL_DSP_BEFORE 2 /* Add property before other named property */
+ /* Extract or delete property that is before given
+ * property. If the given property is first
+ * in the list ENOENT is returned.
+ */
+#define COL_DSP_AFTER 3 /* Add property immediately after other named property */
+ /* Delete or extract property immediately after given
+ * property. If the given property is last in the list
+ * ENOENT is returned.
+ */
+#define COL_DSP_INDEX 4 /* Add, extract or delete property using index.
+ * See notes below.
+ */
+/* NOTE ABOUT USING: COL_DSP_INDEX. */
+/* The COL_DSP_INDEX adds the item as N-th item after header in the list.
+ * Index is zero based.
+ * If there are less than N items in the list the item is added to the end.
+ * The index value of 0 means that the item will be added immediately
+ * after the header. Index of 1 will mean that it is added after first data item and so on.
+ *
+ * In case of extraction or deletion the N-th item of the collection
+ * will be extracted or deleted.
+ * Index is zero based.
+ * If there are less than N+1 items in the list the function will return ENOENT.
+ */
+
+/* The following three dispositions operate only with list of duplicate
+ * properties that are going one after another.
+ * In case of addition the property name is taken from the item
+ * and the value refprop is ignored.
+ * In case of extraction or deletion the property name is taken
+ * from the refprop.
+ */
+#define COL_DSP_FIRSTDUP 5 /* Add property as a first dup of the given property */
+ /* In case of extraction or deletion extracts or deletes
+ * given property.
+ */
+#define COL_DSP_LASTDUP 6 /* Add property as a last dup of the given property */
+ /* In case of extraction or deletion extracts or deletes
+ * last duplicate property in the uninterrupted sequence of
+ * properties with the same name.
+ */
+#define COL_DSP_NDUP 7 /* Add property as a N-th dup (0- based) of the given property. */
+ /* In case of extraction or deletion extracts or deletes
+ * N-th (0-based) duplicate of the given property.
+ * If index is greater than number of duplicate
+ * properties in sequence ENOENT is returned.
+ * See more details below.
+ */
+
+/* Other dispositions might be possible in future. */
+
+/* The COL_DSP_NDUP is used in case of the multi value property
+ * to add a new property with the same name into specific place
+ * in the list of properties with the same name.
+ * The index of 0 will mean to add the property before the first instance of the property with the same name.
+ * If the property does not exist ENOENT will be returned.
+ * If the index is greater than the last property with the same name the item will be added
+ * immediately after last property with the same name.
+ */
+
+/* Flags that can be used with insert functions */
+#define COL_INSERT_NOCHECK 0 /* This is the default mode - no dup checks on insert */
+#define COL_INSERT_DUPOVER 1 /* Check for dup name and overwrite - position ignored */
+#define COL_INSERT_DUPOVERT 2 /* Check for dup name and type and overwrite - position ignored */
+#define COL_INSERT_DUPERROR 3 /* Return error EEXIST if the entry with the same name exists */
+#define COL_INSERT_DUPERRORT 4 /* Return error EEXIST if the entry with the same name and type exists */
+#define COL_INSERT_DUPMOVE 5 /* Check for dups, overwrite, extracts and
+ * then move to the position requested */
+#define COL_INSERT_DUPMOVET 6 /* Check for dup name and type, overwrite, extracts
+ * and then move to the position requested */
+
+/* In future can be made more complex */
+
+/* NOTE ABOUT FLAGS: Use of the DUP checking flags is costly since it requires a forward look up of the whole
+ * collection before the item is inserted. Do not use it until it is absolutely necessary.
+ */
+
+
+
+/* The attributes in the collection are always added to the end.
+ * The family of the insert_xxx(functions) provides
+ * much more flexibility than add_xxx_property_xxx() functions.
+ */
+
+/* Insert property with reference */
+int insert_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ int type, /* Data type */
+ void *data, /* Pointer to the data */
+ int length, /* Length of the data. For
+ * strings it includes the
+ * trailing 0
+ */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+
+int insert_str_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ char *string, /* String */
+ int length); /* Length */
+
+int insert_binary_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ void *binary_data, /* Binary data */
+ int length); /* Length */
+
+
+int insert_int_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ int number); /* Integer */
+
+
+int insert_unsinged_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned number); /* Unsigned */
+
+
+int insert_long_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ long number); /* Long */
+
+int insert_ulong_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned long number); /* Unsigned long */
+
+int insert_double_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ double number); /* Double */
+
+int insert_bool_property(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned char logical); /* Bool */
+
+
+
+int insert_str_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ char *string, /* String */
+ int length, /* Length */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+int insert_binary_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ void *binary_data, /* Binary data */
+ int length, /* Length */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+
+int insert_int_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ int number, /* Integer */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+
+int insert_unsinged_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned number, /* Unsigned */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+int insert_long_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ long number, /* Long */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+int insert_ulong_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned long number, /* Unsigned long */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+int insert_double_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ double number, /* Double */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
+int insert_bool_property_with_ref(struct collection_item *ci, /* A collection of items */
+ const char *subcollection, /* Sub collection */
+ int disposition, /* Where to insert */
+ const char *refprop, /* Property to relate to */
+ int index, /* Index of the property to add */
+ unsigned flags, /* Flags that control naming issues */
+ const char *property, /* Name */
+ unsigned char logical, /* Bool */
+ struct collection_item **ret_ref); /* Returns the reference back */
+
#endif
diff --git a/common/collection/collection_cnv.c b/common/collection/collection_cnv.c
new file mode 100644
index 000000000..ca9c483ed
--- /dev/null
+++ b/common/collection/collection_cnv.c
@@ -0,0 +1,1266 @@
+/*
+ COLLECTION LIBRARY
+
+ Convenience wrapper functions are implemented here.
+ They take a lot of space but pretty simple so they
+ are separated from the core logic.
+
+ 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 "trace.h"
+
+/* The collection should use the teal structures */
+#include "collection_priv.h"
+#include "collection.h"
+
+/* PROPERTIES */
+/* Insert string property with positioning */
+int insert_str_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ char *string,
+ int length)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_string_property", "Entry.");
+
+ if (length == 0) length = strlen(string) + 1;
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_STRING,
+ (void *)string,
+ length,
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_string_property returning", error);
+ return error;
+}
+
+/* Insert binary property with positioning */
+int insert_binary_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ void *binary_data,
+ int length)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_binary_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_BINARY,
+ binary_data,
+ length,
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_binary_property returning", error);
+ return error;
+}
+
+
+/* Insert integer property with positioning */
+int insert_int_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ int number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_int_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_INTEGER,
+ (void *)&number,
+ sizeof(int),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_int_property returning", error);
+ return error;
+}
+
+
+/* Insert unsigned property with positioning */
+int insert_unsigned_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_unsigned_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_LONG,
+ (void *)&number,
+ sizeof(unsigned),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_unsigned_property returning", error);
+ return error;
+}
+
+
+/* Insert long property with positioning */
+int insert_long_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ long number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_long_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_LONG,
+ (void *)&number,
+ sizeof(long),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_long_property returning", error);
+ return error;
+}
+
+/* Insert unsigned long property with positioning */
+int insert_ulong_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned long number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_ulong_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_ULONG,
+ (void *)&number,
+ sizeof(unsigned long),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_ulong_property returning", error);
+ return error;
+}
+
+/* Insert double property with positioning */
+int insert_double_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ double number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_double_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_DOUBLE,
+ (void *)&number,
+ sizeof(double),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_double_property returning", error);
+ return error;
+}
+
+/* Insert bool property with positioning */
+int insert_bool_property(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned char logical)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_bool_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_BOOL,
+ (void *)&logical,
+ sizeof(unsigned char),
+ NULL);
+
+ TRACE_FLOW_NUMBER("insert_bool_property returning", error);
+ return error;
+}
+
+
+/* Insert string property with positioning and reference. */
+int insert_str_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ char *string,
+ int length,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_string_property_with_ref", "Entry.");
+
+ if (length == 0) length = strlen(string) + 1;
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_STRING,
+ (void *)string,
+ length,
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_string_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert binary property with positioning and reference. */
+int insert_binary_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ void *binary_data,
+ int length,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_binary_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_BINARY,
+ (void *)binary_data,
+ length,
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_binary_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert int property with positioning and reference. */
+int insert_int_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ int number,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_int_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_INTEGER,
+ (void *)&number,
+ sizeof(int),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_int_property_with_ref returning", error);
+ return error;
+}
+
+
+/* Insert unsigned property with positioning and reference. */
+int insert_unsigned_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned number,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_unsigned_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_UNSIGNED,
+ (void *)&number,
+ sizeof(unsigned),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_unsigned_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert long property with positioning and reference. */
+int insert_long_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ long number,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_long_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_LONG,
+ (void *)&number,
+ sizeof(long),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_long_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert unsigned long property with positioning and reference. */
+int insert_ulong_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned long number,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_ulong_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_ULONG,
+ (void *)&number,
+ sizeof(unsigned long),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_ulong_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert double property with positioning and reference. */
+int insert_double_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ double number,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_double_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_DOUBLE,
+ (void *)&number,
+ sizeof(double),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_double_property_with_ref returning", error);
+ return error;
+}
+
+/* Insert bool property with positioning and reference. */
+int insert_bool_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ int disposition,
+ const char *refprop,
+ int index,
+ unsigned flags,
+ const char *property,
+ unsigned char logical,
+ struct collection_item **ret_ref)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("insert_bool_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ disposition,
+ refprop,
+ index,
+ flags,
+ property,
+ COL_TYPE_BOOL,
+ (void *)&logical,
+ sizeof(unsigned char),
+ ret_ref);
+
+ TRACE_FLOW_NUMBER("insert_bool_property_with_ref returning", error);
+ return error;
+}
+
+
+/* Add a string property. */
+int add_str_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ char *string,
+ int length)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_str_property", "Entry.");
+
+ error = insert_str_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ string,
+ length);
+
+ TRACE_FLOW_NUMBER("add_str_property returning", error);
+ return error;
+}
+
+/* Add a binary property. */
+int add_binary_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ void *binary_data,
+ int length)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_binary_property", "Entry.");
+
+ error = insert_binary_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ binary_data,
+ length);
+
+ TRACE_FLOW_NUMBER("add_binary_property returning", error);
+ return error;
+}
+
+/* Add an int property. */
+int add_int_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ int number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_int_property", "Entry.");
+
+ error = insert_int_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number);
+
+ TRACE_FLOW_NUMBER("add_int_property returning", error);
+ return error;
+}
+
+/* Add an unsigned int property. */
+int add_unsigned_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned int number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_unsigned_property", "Entry.");
+
+ error = insert_unsigned_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number);
+
+ TRACE_FLOW_NUMBER("add_unsigned_property returning", error);
+ return error;
+}
+
+/* Add an long property. */
+int add_long_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ long number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_long_property", "Entry.");
+
+
+ error = insert_long_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number);
+
+ TRACE_FLOW_NUMBER("add_long_property returning", error);
+ return error;
+}
+
+/* Add an unsigned long property. */
+int add_ulong_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned long number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_ulong_property", "Entry.");
+
+ error = insert_ulong_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number);
+
+ TRACE_FLOW_NUMBER("add_ulong_property returning", error);
+ return error;
+}
+
+/* Add a double property. */
+int add_double_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ double number)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_double_property", "Entry.");
+
+ error = insert_double_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number);
+
+ TRACE_FLOW_NUMBER("add_double_property returning", error);
+ return error;
+}
+
+/* Add a bool property. */
+int add_bool_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned char logical)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_bool_property", "Entry.");
+
+ error = insert_bool_property(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ logical);
+
+ TRACE_FLOW_NUMBER("add_bool_property returning", error);
+ return error;
+}
+
+/* A function to add a property */
+int add_any_property(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ int type,
+ void *data,
+ int length)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_any_property", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ type,
+ data,
+ length,
+ NULL);
+
+ TRACE_FLOW_NUMBER("add_any_property returning", error);
+ return error;
+}
+
+/* Add a string property with reference */
+inline int add_str_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ char *string, int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_str_property_with_ref", "Entry.");
+
+ error = insert_str_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ string,
+ length,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_str_property_with_ref returning", error);
+ return error;
+}
+
+/* Add a binary property with reference. */
+int add_binary_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ void *binary_data, int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_binary_property_with_ref", "Entry.");
+
+ error = insert_binary_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ binary_data,
+ length,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_binary_property_with_ref returning", error);
+ return error;
+}
+
+/* Add an int property with reference. */
+int add_int_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ int number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_int_property_with_ref", "Entry.");
+
+ error = insert_int_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_int_property_with_ref returning", error);
+ return error;
+}
+
+/* Add an unsigned int property with reference. */
+int add_unsigned_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned int number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_unsigned_property_with_ref", "Entry.");
+
+ error = insert_unsigned_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_unsigned_property_with_ref returning", error);
+ return error;
+}
+
+/* Add an long property with reference. */
+int add_long_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ long number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_long_property_with_ref", "Entry.");
+
+ error = insert_long_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_long_property_with_ref returning", error);
+ return error;
+}
+
+/* Add an unsigned long property with reference. */
+int add_ulong_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned long number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_ulong_property_with_ref", "Entry.");
+
+ error = insert_ulong_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_ulong_property_with_ref returning", error);
+ return error;
+}
+
+/* Add a double property with reference. */
+int add_double_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ double number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_double_property_with_ref", "Entry.");
+
+ error = insert_double_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ number,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_double_property_with_ref returning", error);
+ return error;
+}
+
+/* Add a bool property with reference. */
+int add_bool_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ unsigned char logical,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_bool_property_with_ref", "Entry.");
+
+ error = insert_bool_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ logical,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_bool_property_with_ref returning", error);
+ return error;
+}
+
+/* A function to add a property with reference. */
+int add_any_property_with_ref(struct collection_item *ci,
+ const char *subcollection,
+ const char *property,
+ int type,
+ void *data,
+ int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("add_any_property_with_ref", "Entry.");
+
+ error = insert_property_with_ref(ci,
+ subcollection,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0,
+ property,
+ type,
+ data,
+ length,
+ ref_ret);
+
+ TRACE_FLOW_NUMBER("add_any_property_with_ref returning", error);
+ return error;
+}
+
+
+/* Update a string property in the collection.
+ * Length should include the terminating 0 */
+int update_str_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ char *string,
+ int length)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_str_property", "Entry.");
+
+ if (length == 0) length = strlen(string) + 1;
+ error = update_property(ci, property, COL_TYPE_STRING,
+ (void *)string, length, mode_flags);
+
+ TRACE_FLOW_NUMBER("update_str_property Returning", error);
+ return error;
+}
+
+/* Update a binary property in the collection. */
+int update_binary_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ void *binary_data,
+ int length)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_binary_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_BINARY,
+ binary_data, length, mode_flags);
+
+ TRACE_FLOW_NUMBER("update_binary_property Returning", error);
+ return error;
+}
+
+/* Update an int property in the collection. */
+int update_int_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ int number)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_int_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_INTEGER,
+ (void *)(&number), sizeof(int), mode_flags);
+
+ TRACE_FLOW_NUMBER("update_int_property Returning", error);
+ return error;
+}
+
+/* Update an unsigned int property. */
+int update_unsigned_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ unsigned int number)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_unsigned_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_UNSIGNED,
+ (void *)(&number), sizeof(unsigned int),
+ mode_flags);
+
+ TRACE_FLOW_NUMBER("update_unsigned_property Returning", error);
+ return error;
+}
+
+/* Update a long property. */
+int update_long_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ long number)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_long_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_LONG,
+ (void *)(&number), sizeof(long), mode_flags);
+
+ TRACE_FLOW_NUMBER("update_long_property Returning", error);
+ return error;
+
+}
+
+/* Update an unsigned long property. */
+int update_ulong_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ unsigned long number)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_ulong_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_ULONG,
+ (void *)(&number), sizeof(unsigned long),
+ mode_flags);
+
+ TRACE_FLOW_NUMBER("update_ulong_property Returning", error);
+ return error;
+}
+
+/* Update a double property. */
+int update_double_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ double number)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_double_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_DOUBLE,
+ (void *)(&number), sizeof(double), mode_flags);
+
+ TRACE_FLOW_NUMBER("update_double_property Returning", error);
+ return error;
+}
+
+/* Update a bool property. */
+int update_bool_property(struct collection_item *ci,
+ const char *property,
+ int mode_flags,
+ unsigned char logical)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("update_bool_property", "Entry.");
+
+ error = update_property(ci, property, COL_TYPE_BOOL,
+ (void *)(&logical), sizeof(unsigned char),
+ mode_flags);
+
+ TRACE_FLOW_NUMBER("update_bool_property Returning", error);
+ return error;
+}
+
+/* Rename item */
+int modify_item_property(struct collection_item *item,
+ const char *property)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_item_property", "Entry");
+
+ error = modify_item(item, property, 0, NULL, 0);
+
+ TRACE_FLOW_STRING("modify_item_property", "Exit");
+ return error;
+}
+
+/* Convenience functions that wrap modify_item(). */
+/* Modify item data to be str */
+int modify_str_item(struct collection_item *item,
+ const char *property,
+ char *string,
+ int length)
+{
+ int len;
+ int error;
+
+ TRACE_FLOW_STRING("modify_str_item", "Entry");
+
+ if (length != 0) len = length;
+ else len = strlen(string) + 1;
+
+ error = modify_item(item, property, COL_TYPE_STRING, (void *)string, len);
+
+ TRACE_FLOW_STRING("modify_str_item", "Exit");
+ return error;
+}
+
+/* Modify item data to be binary */
+int modify_binary_item(struct collection_item *item,
+ const char *property,
+ void *binary_data,
+ int length)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_binary_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_BINARY, binary_data, length);
+
+ TRACE_FLOW_STRING("modify_binary_item", "Exit");
+ return error;
+}
+
+/* Modify item data to be bool */
+int modify_bool_item(struct collection_item *item,
+ const char *property,
+ unsigned char logical)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_bool_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_BOOL, (void *)(&logical), 1);
+
+ TRACE_FLOW_STRING("modify_bool_item", "Exit");
+ return error;
+}
+
+/* Modify item data to be int */
+int modify_int_item(struct collection_item *item,
+ const char *property,
+ int number)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_int_item","Entry");
+
+ error = modify_item(item, property, COL_TYPE_INTEGER,
+ (void *)(&number), sizeof(int));
+
+ TRACE_FLOW_STRING("modify_int_item", "Exit");
+ return error;
+}
+
+/* Modify item data to be long */
+int modify_long_item(struct collection_item *item,
+ const char *property,
+ long number)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_long_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_LONG,
+ (void *)(&number), sizeof(long));
+
+ TRACE_FLOW_STRING("modify_long_item", "Exit");
+ return error;
+}
+
+/* Modify item data to be unigned long */
+int modify_ulong_item(struct collection_item *item,
+ const char *property,
+ unsigned long number)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_ulong_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_ULONG,
+ (void *)(&number), sizeof(unsigned long));
+
+ TRACE_FLOW_STRING("modify_ulong_item", "Exit");
+ return error;
+}
+
+int modify_unsigned_item(struct collection_item *item,
+ const char *property,
+ unsigned number)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_unsigned_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_UNSIGNED,
+ (void *)(&number), sizeof(unsigned));
+
+ TRACE_FLOW_STRING("modify_unsigned_item", "Exit");
+ return error;
+}
+
+int modify_double_item(struct collection_item *item,
+ const char *property,
+ double number)
+{
+ int error;
+
+ TRACE_FLOW_STRING("modify_double_item", "Entry");
+
+ error = modify_item(item, property, COL_TYPE_DOUBLE,
+ (void *)(&number), sizeof(double));
+
+ TRACE_FLOW_STRING("modify_double_item", "Exit");
+ return error;
+}
diff --git a/common/collection/collection_priv.h b/common/collection/collection_priv.h
index 38d9012a6..18688f9dd 100644
--- a/common/collection/collection_priv.h
+++ b/common/collection/collection_priv.h
@@ -22,6 +22,8 @@
#ifndef COLLECTION_PRIV_H
#define COLLECTION_PRIV_H
+#include <stdint.h>
+
/* Define real strcutures */
/* Structure that holds one property.
* This structure should never be assumed and used directly other than
@@ -43,6 +45,7 @@ struct collection_item {
int type;
int length;
void *data;
+ uint64_t phash;
};
@@ -67,4 +70,3 @@ struct collection_header {
};
#endif
-
diff --git a/common/collection/collection_ut.c b/common/collection/collection_ut.c
index eabf52227..21f768bec 100644
--- a/common/collection/collection_ut.c
+++ b/common/collection/collection_ut.c
@@ -31,8 +31,8 @@
int ref_collection_test()
{
- struct collection_item *peer;
- struct collection_item *socket;
+ struct collection_item *peer = NULL;
+ struct collection_item *socket = NULL;
char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int error = EOK;
@@ -46,7 +46,7 @@ int ref_collection_test()
(error=add_str_property(peer,NULL,"hostname","peerhost.mytest.com",0)) ||
(error=add_str_property(peer,NULL,"IPv4","10.10.10.10",12)) || /* Expect trailing zero to be truncated */
(error=add_str_property(peer,NULL,"IPv6","bla:bla:bla:bla:bla:bla",0))) {
- printf("Failed to add property. Error %d",error);
+ printf("Failed to add property. Error %d\n",error);
destroy_collection(peer);
return error;
}
@@ -109,7 +109,7 @@ int ref_collection_test()
int single_collection_test()
{
- struct collection_item *handle;
+ struct collection_item *handle = NULL;
int error = EOK;
TRACE_FLOW_STRING("single_collection_test","Entry.");
@@ -165,8 +165,8 @@ int single_collection_test()
int add_collection_test()
{
- struct collection_item *peer;
- struct collection_item *socket;
+ struct collection_item *peer = NULL;
+ struct collection_item *socket = NULL;
char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int error = EOK;
@@ -692,6 +692,160 @@ int iterator_test()
}
+int insert_extract_test()
+{
+ struct collection_item *col;
+ struct collection_item *col2;
+ int error = EOK;
+ struct collection_item *item = (struct collection_item *)(NULL);
+
+ printf("\n\n==== INSERTION TEST ====\n\n");
+
+ if ((error = create_collection(&col, "insertion", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property1", "value1", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property2", "value2", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_FRONT,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property0", "value0", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_BEFORE,
+ "property0", 0, COL_INSERT_NOCHECK,
+ "property_-1", "value_-1", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_BEFORE,
+ "property1", 0, COL_INSERT_NOCHECK,
+ "property0_5", "value0_5", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_BEFORE,
+ "property2", 0, COL_INSERT_NOCHECK,
+ "property1_5", "value1_5", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_AFTER,
+ "property_-1", 0, COL_INSERT_NOCHECK,
+ "property_-0_5", "value_-0_5", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_AFTER,
+ "property1_5", 0, COL_INSERT_NOCHECK,
+ "property1_6", "value1_6", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_INDEX,
+ NULL, 10, COL_INSERT_NOCHECK,
+ "property10", "value10", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_INDEX,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property_-2", "value_-2", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_INDEX,
+ NULL, 1, COL_INSERT_NOCHECK,
+ "property_-1_5", "value_-1_5", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_FIRSTDUP,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property0", "value0firstdup", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_LASTDUP,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property0", "value0lastdup", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_NDUP,
+ NULL, 1, COL_INSERT_NOCHECK,
+ "property0", "value0middledup", 0)) ||
+ (error = insert_str_property(col, NULL, 0,
+ NULL, 0, COL_INSERT_DUPOVER ,
+ "property0", "value0firstdupupdate", 0)) ||
+ (error = insert_str_property(col, NULL, 0,
+ NULL, 0, COL_INSERT_DUPOVERT,
+ "property1", "value1update", 0)) ||
+ ((error = insert_str_property(col, NULL, 0,
+ NULL, 0, COL_INSERT_DUPERROR,
+ "property0", "does not matter", 0)) != EEXIST) ||
+ (error = insert_str_property(col, NULL, COL_DSP_NDUP,
+ NULL, 5, COL_INSERT_NOCHECK,
+ "property10", "value10dup", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_LASTDUP,
+ NULL, 0, COL_INSERT_NOCHECK,
+ "property10", "value10lastdup", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_END,
+ NULL, 0, COL_INSERT_DUPMOVET,
+ "property_-2", "value-2moved_to_bottom", 0)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_FRONT,
+ NULL, 0, COL_INSERT_DUPMOVE,
+ "property1_6", "value_1_6_moved_moved_to_front", 0))) {
+
+ printf("ERROR in the ITERATION TEST\n");
+ debug_collection(col,COL_TRAVERSE_DEFAULT);
+ destroy_collection(col);
+ return error;
+ }
+
+ printf("\n\nCollection:\n\n");
+ debug_collection(col,COL_TRAVERSE_DEFAULT);
+
+
+ printf("\n\n==== EXTRACTION TEST ====\n\n");
+
+ if ((error = create_collection(&col2, "extraction", 0)) ||
+ (error = extract_item(col, NULL, COL_DSP_FRONT,
+ NULL, 0, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_FRONT,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_END,
+ NULL, 0, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = insert_str_property(col, NULL, COL_DSP_INDEX,
+ NULL, 100, COL_INSERT_NOCHECK,
+ "property100", "value100", 0)) ||
+ (error = extract_item(col, NULL, COL_DSP_AFTER,
+ "property10", 0, COL_TYPE_STRING, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_BEFORE,
+ "property0", 0, COL_TYPE_STRING, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_INDEX,
+ NULL, 1, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_NDUP,
+ "property0", 1, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_LASTDUP,
+ "property0", 0, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT)) ||
+ (error = extract_item(col, NULL, COL_DSP_FIRSTDUP,
+ "property0", 0, 0, &item)) ||
+ (error = insert_item(col2, NULL, item, COL_DSP_END,
+ NULL, 0, COL_INSERT_NOCHECK)) ||
+ (debug_collection(col2,COL_TRAVERSE_DEFAULT))) {
+
+ printf("ERROR in the EXTRACTION TEST\n");
+ printf("Collection 1\n");
+ debug_collection(col,COL_TRAVERSE_DEFAULT);
+ printf("Collection 2\n");
+ debug_collection(col2,COL_TRAVERSE_DEFAULT);
+ destroy_collection(col);
+ destroy_collection(col2);
+ return error;
+ }
+
+ printf("Collection 1\n");
+ debug_collection(col,COL_TRAVERSE_DEFAULT);
+ printf("Collection 2\n");
+ debug_collection(col2,COL_TRAVERSE_DEFAULT);
+
+ destroy_collection(col2);
+ destroy_collection(col);
+
+
+ return EOK;
+}
+
+
/* Main function of the unit test */
int main()
@@ -703,7 +857,8 @@ int main()
(error=single_collection_test()) ||
(error=add_collection_test()) ||
(error=mixed_collection_test()) ||
- (error=iterator_test())) {
+ (error=iterator_test()) ||
+ (error=insert_extract_test())) {
printf("Failed!\n");
}
else printf("Success!\n");
diff --git a/common/collection/configure.ac b/common/collection/configure.ac
index da34da0a5..504cd4d5c 100644
--- a/common/collection/configure.ac
+++ b/common/collection/configure.ac
@@ -19,5 +19,8 @@ AC_ARG_ENABLE([trace],
[trace_level="0"])
AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])])
+AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
+
AC_CONFIG_FILES([Makefile collection.pc])
AC_OUTPUT