diff options
Diffstat (limited to 'common/collection')
-rw-r--r-- | common/collection/Makefile.am | 1 | ||||
-rw-r--r-- | common/collection/collection.c | 1810 | ||||
-rw-r--r-- | common/collection/collection.h | 388 | ||||
-rw-r--r-- | common/collection/collection_cnv.c | 1266 | ||||
-rw-r--r-- | common/collection/collection_priv.h | 4 | ||||
-rw-r--r-- | common/collection/collection_ut.c | 169 | ||||
-rw-r--r-- | common/collection/configure.ac | 3 |
7 files changed, 2791 insertions, 850 deletions
diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am index 0b8d0d03..8df9fc6b 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 e2816e63..f7918879 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 687f468d..28622a50 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 00000000..ca9c483e --- /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 38d9012a..18688f9d 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 eabf5222..21f768be 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 da34da0a..504cd4d5 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 |