summaryrefslogtreecommitdiff
path: root/common/collection
diff options
context:
space:
mode:
Diffstat (limited to 'common/collection')
-rw-r--r--common/collection/Makefile.am1
-rw-r--r--common/collection/collection.c2
-rw-r--r--common/collection/collection.h107
-rw-r--r--common/collection/collection_cmp.c436
-rw-r--r--common/collection/collection_tools.c2
-rw-r--r--common/collection/collection_ut.c147
-rw-r--r--common/collection/configure.ac7
7 files changed, 697 insertions, 5 deletions
diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am
index 323a5cb0..8e4e9736 100644
--- a/common/collection/Makefile.am
+++ b/common/collection/Makefile.am
@@ -28,6 +28,7 @@ libcollection_la_SOURCES = \
collection_cnv.c \
collection_queue.c \
collection_stack.c \
+ collection_cmp.c \
collection.h \
collection_tools.h \
collection_priv.h \
diff --git a/common/collection/collection.c b/common/collection/collection.c
index bccb50df..c116f481 100644
--- a/common/collection/collection.c
+++ b/common/collection/collection.c
@@ -28,7 +28,7 @@
#include "config.h"
#include "trace.h"
-/* The collection should use the teal structures */
+/* The collection should use the real structures */
#include "collection_priv.h"
#include "collection.h"
diff --git a/common/collection/collection.h b/common/collection/collection.h
index dc59ea2f..b4bbb2a4 100644
--- a/common/collection/collection.h
+++ b/common/collection/collection.h
@@ -501,6 +501,113 @@ uint64_t col_get_item_hash(struct collection_item *ci);
*/
uint64_t col_make_hash(const char *string, int *length);
+/* Compare two items.
+ * The second item is evaluated against the first.
+ * Function returns 0 if two items are the same
+ * and non-zero otherwise.
+ * The in_flags is a bit mask that defines
+ * how the items should be compared.
+ * See below the list of conbstants
+ * defined for this purpose.
+ * If items are different they might be orderable
+ * or not. For example one can order items by name
+ * but not by type.
+ * If the result of the function is non-zero
+ * the out_flags (if provided) will be
+ * set to indicate if the second item is greater
+ * then the first.
+ */
+int col_compare_items(struct collection_item *first,
+ struct collection_item *second,
+ unsigned in_flags,
+ unsigned *out_flags);
+
+/********* Possible valies for input flags ********/
+/* How to compare properties?
+ * The following 4 flags are mutually exclusive
+ */
+#define COL_CMPIN_PROP_EQU 0x000000004 /* Properties should be same */
+#define COL_CMPIN_PROP_BEG 0x000000005 /* Properties start same */
+#define COL_CMPIN_PROP_MID 0x000000006 /* One is substring of another */
+#define COL_CMPIN_PROP_END 0x000000007 /* One property ends with another */
+
+/* Make sure that there is a dot.
+ * Useful with _BEG, _MID and _END flags to check that the there is
+ * a dot (if present) in the right place (before, after or both).
+ * For example the first item is named "foo.bar" and the second
+ * is "bar". Using _END the "bar" will be found but if _DOT flag is
+ * used too the function will also check if there was a "." before the found
+ * string in this case.
+ * Ignored in case of _EQU.
+ */
+#define COL_CMPIN_PROP_DOT 0x000000008
+
+/* Compare property lenghts */
+#define COL_CMPIN_PROP_LEN 0x000000010
+
+/* Compare types */
+#define COL_CMPIN_TYPE 0x000000020
+
+/* Compare data len */
+#define COL_CMPIN_DATA_LEN 0x000000040
+
+/* Compare data (up to the length of the second one)
+ * if type is the same. If type is different
+ * function will assume data is different
+ * without performing actual comparison.
+ */
+#define COL_CMPIN_DATA 0x000000080
+
+/********* Possible values for output flags *********/
+/* If _EQU was specified and the property of the second item
+ * is greater the following bit will be set
+ */
+#define COL_CMPOUT_PROP_STR 0x00000001
+/* If we were told to compare property lengths
+ * and second is longer this bit will be set
+ */
+#define COL_CMPOUT_PROP_LEN 0x00000002
+/* If we were told to compare data lengths
+ * and second is longer this bit will be set
+ */
+#define COL_CMPOUT_DATA_LEN 0x00000004
+/* If we were told to compare data
+ * and types are the same then
+ * if the second one is greater this bit will
+ * be set. If data is binary flag is never set
+ */
+#define COL_CMPOUT_DATA 0x00000008
+
+
+/* Sort collection.
+ * cmp_flags are the same as in_flags for the compare
+ * function. The sort_flags is an OR of the costants
+ * defined below.
+ * If the subcollections are included in sorting
+ * each collection is sorted separately (this is not a global sort).
+ * It might be dangerous to sort subcollections if
+ * subcollection is not owned by current collection.
+ * If it is a reference to an external collection
+ * there might be an issue. To skip the collections that
+ * externally referenced use MYSUB flag.
+ * Keep in mind that if the collection
+ * has two references to the same other
+ * collection it is impossible to detect
+ * this situation. If MYSUB is used in this
+ * case such collection will be ignored
+ * If MYSUB is not used the collection
+ * will be sorted more than once.
+ */
+int col_sort_collection(struct collection_item *col,
+ unsigned cmp_flags,
+ unsigned sort_flags);
+
+/* Sort flags */
+#define COL_SORT_ASC 0x00000000
+#define COL_SORT_DESC 0x00000001
+#define COL_SORT_SUB 0x00000002
+#define COL_SORT_MYSUB 0x00000004
+
/* If you want to modify the item that you got as a result of iterating through collection
* or by calling col_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 0 as length parameter.
diff --git a/common/collection/collection_cmp.c b/common/collection/collection_cmp.c
new file mode 100644
index 00000000..c1f9017d
--- /dev/null
+++ b/common/collection/collection_cmp.c
@@ -0,0 +1,436 @@
+/*
+ COLLECTION LIBRARY
+
+ Function to compare items.
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ Collection Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Collection Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with Collection Library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include "config.h"
+#include "trace.h"
+
+/* The collection should use the real structures */
+#include "collection_priv.h"
+#include "collection.h"
+
+#define NONZERO 1
+#define PROP_MSK 0x000000007
+
+
+#define TYPED_MATCH(type) \
+ do { \
+ if (*((type *)(first->data)) != *((type *)(second->data))) { \
+ result = NONZERO; \
+ if ((out_flags) && \
+ (*((type *)(first->data)) < *((type *)(second->data)))) { \
+ *out_flags |= COL_CMPOUT_DATA; \
+ } \
+ } \
+ } while(0)
+
+
+/* Function to compare two items */
+int col_compare_items(struct collection_item *first,
+ struct collection_item *second,
+ unsigned in_flags,
+ unsigned *out_flags)
+{
+ int result = 0;
+ unsigned mode;
+ int cmpres = 0;
+ char *substr;
+
+ TRACE_FLOW_STRING("col_compare_items", "Entry.");
+
+ /* If any of the arguments is NULL return
+ * that they are different.
+ */
+ if ((first == NULL) || (second == NULL)) {
+ TRACE_INFO_STRING("One of the items is NULL", "");
+ return NONZERO;
+ }
+
+ /* Check if we are told to compare something */
+ if (!in_flags) {
+ TRACE_INFO_NUMBER("No flags specified", in_flags);
+ return NONZERO;
+ }
+
+ if (out_flags) *out_flags = 0;
+
+ /* Start comparison */
+ mode = in_flags & PROP_MSK;
+ if (mode > 0 ) {
+ /* We are told to compare the properties */
+ switch(mode) {
+
+ case COL_CMPIN_PROP_EQU: /* looking for exact match */
+
+ /* Compare hashes and lengths first */
+ if ((first->phash == first->phash) &&
+ (first->property_len == second->property_len)) {
+ /* Collections are case insensitive, sorry... */
+ cmpres = strncasecmp(first->property,
+ second->property,
+ second->property_len);
+ if (cmpres != 0) {
+ result = NONZERO;
+ if (cmpres < 0) {
+ /* Second is greater */
+ if (out_flags) *out_flags |= COL_CMPOUT_PROP_STR;
+ }
+ }
+ }
+ else {
+ result = NONZERO;
+ /* They are different so check if we need to compare? */
+ if (out_flags) {
+ cmpres = strncasecmp(first->property,
+ second->property,
+ second->property_len);
+ if (cmpres < 0) {
+ /* Second is greater */
+ *out_flags |= COL_CMPOUT_PROP_STR;
+ }
+ }
+ }
+ break;
+
+ case COL_CMPIN_PROP_BEG: /* looking for beginning */
+
+ /* Compare lengths first */
+ if (first->property_len >= second->property_len) {
+ cmpres = strncasecmp(first->property,
+ second->property,
+ second->property_len);
+ if (cmpres == 0) {
+ /* Check we need to validate for dot */
+ if (in_flags & COL_CMPIN_PROP_DOT) {
+ if ((first->property[second->property_len] != '\0') &&
+ (first->property[second->property_len] != '.')) {
+ result = NONZERO;
+ }
+ }
+ }
+ else result = NONZERO;
+ }
+ else result = NONZERO;
+ break;
+
+ case COL_CMPIN_PROP_MID: /* looking for middle */
+
+ /* Compare lengths first */
+ if (first->property_len >= second->property_len) {
+ substr = strcasestr(first->property, second->property);
+ if (substr != NULL) {
+ /* Check we need to validate for dot */
+ if (in_flags & COL_CMPIN_PROP_DOT) {
+ /* Check if we have a dot before or after */
+ if (((substr != first->property) &&
+ (first->property[(substr - first->property) - 1] != '.')) ||
+ ((substr[second->property_len] != '\0') &&
+ (substr[second->property_len] != '.'))) {
+ result = NONZERO;
+ }
+ }
+ }
+ else result = NONZERO;
+ }
+ else result = NONZERO;
+ break;
+
+ case COL_CMPIN_PROP_END: /* looking for end */
+
+ /* Compare lengths first */
+ if (first->property_len >= second->property_len) {
+ substr = first->property + (first->property_len - second->property_len);
+ cmpres = strncasecmp(substr,
+ second->property,
+ second->property_len);
+ if (cmpres == 0) {
+ /* Check we need to validate for dot */
+ if (in_flags & COL_CMPIN_PROP_DOT) {
+ if ((substr != first->property) &&
+ (first->property[(substr - first->property) - 1] != '.')) {
+ result = NONZERO;
+ }
+ }
+ }
+ else result = NONZERO;
+ }
+ else result = NONZERO;
+ break;
+
+ default: result = NONZERO;
+ break;
+ }
+ }
+
+ /* Check if we are told to compare property lengths */
+ if (in_flags & COL_CMPIN_PROP_LEN) {
+ if (first->property_len != second->property_len) {
+ result = NONZERO;
+ /* Do we need to tell who is greater? */
+ if ((out_flags) && (first->property_len < second->property_len)) {
+ *out_flags |= COL_CMPOUT_PROP_LEN;
+ }
+ }
+ }
+
+ /* Check if we are told to compare types */
+ if (in_flags & COL_CMPIN_TYPE) {
+ if (first->type != second->type) result = NONZERO;
+ }
+
+ /* Check if we need to compare data length */
+ if (in_flags & COL_CMPIN_DATA_LEN) {
+ if (first->length != second->length) {
+ result = NONZERO;
+ /* Do we need to tell who is greater? */
+ if ((out_flags) && (first->length < second->length)) {
+ *out_flags |= COL_CMPOUT_DATA_LEN;
+ }
+ }
+ }
+
+ /* Check if we need to compare data */
+ if (in_flags & COL_CMPIN_DATA) {
+ if (first->type == second->type) {
+ switch(first->type) {
+
+ case COL_TYPE_STRING:
+ if (first->length == second->length) {
+ cmpres = strncmp((const char *)first->data,
+ (const char *)second->data,
+ first->length);
+
+ if (cmpres != 0) {
+ result = NONZERO;
+ if (cmpres < 0) {
+ /* Second is greater */
+ if (out_flags) *out_flags |= COL_CMPOUT_DATA;
+ }
+ }
+
+ }
+ else result = NONZERO;
+ break;
+
+ case COL_TYPE_BINARY:
+ if (first->length == second->length) {
+ cmpres = memcmp(first->data,
+ second->data,
+ first->length);
+
+ if (cmpres != 0) result = NONZERO;
+ }
+ else result = NONZERO;
+ break;
+
+ case COL_TYPE_INTEGER:
+ /* Use macro to match data */
+ TYPED_MATCH(int);
+ break;
+
+ case COL_TYPE_UNSIGNED:
+ /* Use macro to match data */
+ TYPED_MATCH(unsigned);
+ break;
+
+ case COL_TYPE_LONG:
+ /* Use macro to match data */
+ TYPED_MATCH(long);
+ break;
+
+ case COL_TYPE_ULONG:
+ /* Use macro to match data */
+ TYPED_MATCH(unsigned long);
+ break;
+
+ case COL_TYPE_DOUBLE:
+ /* Use macro to match data */
+ TYPED_MATCH(double);
+ break;
+
+ case COL_TYPE_BOOL:
+ /* Use macro to match data */
+ TYPED_MATCH(unsigned char);
+ break;
+
+ /* These are never same */
+ case COL_TYPE_COLLECTION:
+ case COL_TYPE_COLLECTIONREF:
+ case COL_TYPE_END:
+ default:
+ result = NONZERO;
+ break;
+ }
+
+ }
+ else result = NONZERO;
+ }
+
+ TRACE_FLOW_NUMBER("col_compare_items. Exit. Returning:", result);
+ return result;
+}
+
+/* Sort collection */
+int col_sort_collection(struct collection_item *col,
+ unsigned cmp_flags,
+ unsigned sort_flags)
+{
+ int error = EOK;
+
+ struct collection_item *current;
+ struct collection_header *header;
+ struct collection_item **array;
+ struct collection_item *temp_item;
+ struct collection_item *other;
+ size_t size;
+ int ind, last;
+ int i, j;
+ int res;
+ unsigned out_flags;
+
+ TRACE_FLOW_STRING("col_sort_collection", "Entry.");
+
+ TRACE_INFO_NUMBER("Comparison flags:", cmp_flags);
+ TRACE_INFO_NUMBER("Sort flags:", sort_flags);
+
+ if ((col == NULL) || (col->type != COL_TYPE_COLLECTION)) {
+ TRACE_ERROR_STRING("Collecton must not ne NULL", "");
+ return EINVAL;
+ }
+
+ /* This will be a fast and simple implementation for now */
+ header = (struct collection_header *)(col->data);
+
+ if ((sort_flags & COL_SORT_SUB) &&
+ (sort_flags & COL_SORT_MYSUB) &&
+ (header->reference_count > 1)) {
+ TRACE_FLOW_STRING("col_sort_collection", "Exit.");
+ return error;
+ }
+
+ size = sizeof(struct collection_item *) * (header->count - 1);
+ array = (struct collection_item **)malloc(size);
+ if (array == NULL) {
+ TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM);
+ return ENOMEM;
+ }
+
+ /* Fill array */
+ current = col->next;
+ ind = 0;
+ while (current != NULL) {
+ TRACE_INFO_STRING("Item:", current->property);
+ array[ind] = current;
+ if ((sort_flags & COL_SORT_SUB) &&
+ (array[ind]->type == COL_TYPE_COLLECTIONREF)) {
+ /* If we found a subcollection and we need to sort it
+ * then sort it.
+ */
+ other = *((struct collection_item **)(array[ind]->data));
+ error = col_sort_collection(other, cmp_flags, sort_flags);
+ if (error) {
+ TRACE_ERROR_NUMBER("Subcollection sort failed", error);
+ free(array);
+ return error;
+ }
+ }
+ ind++;
+ current = current->next;
+ }
+
+ last = ind - 1;
+
+ for (i = 0; i < last; i++) {
+
+ TRACE_INFO_STRING("Arg1:", array[i]->property);
+ TRACE_INFO_STRING("Arg2:", array[i + 1]->property);
+
+ res = col_compare_items(array[i],
+ array[i + 1],
+ cmp_flags,
+ &out_flags);
+
+ TRACE_INFO_STRING("Result:", ((res == 0) ? "same" : "different"));
+ TRACE_INFO_NUMBER("Out flags", out_flags);
+
+ /* If they are not same and second is not greater
+ * in any way then we need to swap them */
+ if ((res != 0) && (out_flags == 0)) {
+ /* Swap */
+ TRACE_INFO_STRING("Swapping:", "");
+ TRACE_INFO_STRING("Item:", array[i]->property);
+ TRACE_INFO_STRING("Item:", array[i + 1]->property);
+
+ temp_item = array[i];
+ array[i] = array[i + 1];
+ array[i + 1] = temp_item;
+
+ /* But we need to go up bubbling this item
+ */
+ j = i;
+ while (j > 0) {
+ res = col_compare_items(array[j - 1],
+ array[j],
+ cmp_flags,
+ &out_flags);
+ /* If they are not same and second is not greater
+ * in any way then we need to swap them */
+ if ((res != 0) && (out_flags == 0)) {
+ /* Swap */
+ temp_item = array[j - 1];
+ array[j - 1] = array[j];
+ array[j] = temp_item;
+ }
+ else break;
+ j--;
+ }
+ }
+ }
+
+ /* Build the chain back */
+ if (sort_flags & COL_SORT_DESC) {
+ col->next = array[last];
+ for (i = last; i > 0 ; i--) {
+ array[i]->next = array[i - 1];
+ }
+ array[0]->next = NULL;
+ header->last = array[0];
+ }
+ else {
+ col->next = array[0];
+ for (i = 0; i < last ; i++) {
+ array[i]->next = array[i + 1];
+ }
+ array[last]->next = NULL;
+ header->last = array[last];
+ }
+
+ free(array);
+
+ TRACE_FLOW_STRING("col_sort_collection", "Exit.");
+ return error;
+
+}
diff --git a/common/collection/collection_tools.c b/common/collection/collection_tools.c
index c3f00eaf..503a1a8c 100644
--- a/common/collection/collection_tools.c
+++ b/common/collection/collection_tools.c
@@ -117,7 +117,7 @@ int col_debug_handle(const char *property,
(nest_level -1) * 4, "",
property,
length,
- (*((unsigned char *)(data)) == '\0') ? "flase" : "true",
+ (*((unsigned char *)(data)) == '\0') ? "false" : "true",
nest_level);
break;
case COL_TYPE_COLLECTION:
diff --git a/common/collection/collection_ut.c b/common/collection/collection_ut.c
index 050c6ef1..c17f5bc7 100644
--- a/common/collection/collection_ut.c
+++ b/common/collection/collection_ut.c
@@ -1323,9 +1323,9 @@ int search_test(void)
(error = col_add_collection_to_collection(level1, NULL, NULL, level2, COL_ADD_MODE_REFERENCE)) ||
(error = col_create_collection(&level3, "level3", 0)) ||
(error = col_add_collection_to_collection(level1, "level2", NULL, level3, COL_ADD_MODE_REFERENCE)) ||
- (error = col_create_collection(&level4, "level4", 0)) ||
+ (error = col_create_collection(&level4, "leveL4", 0)) ||
(error = col_add_collection_to_collection(level1, "level3", NULL, level4, COL_ADD_MODE_REFERENCE)) ||
- (error = col_add_int_property(level1, "level4", "id", 1)) ||
+ (error = col_add_int_property(level1, "leveL4", "id", 1)) ||
(error = col_add_long_property(level1, "level3", "packets", 100000000L)) ||
(error = col_add_binary_property(level1, "level2", "stack", binary_dump, sizeof(binary_dump)))) {
col_destroy_collection(level1);
@@ -1424,6 +1424,146 @@ int search_test(void)
return EOK;
}
+/* Sort test */
+int sort_test(void)
+{
+ struct collection_item *level1 = NULL;
+ struct collection_item *level2a = NULL;
+ struct collection_item *level2b = NULL;
+ struct collection_item *level3 = NULL;
+ int error = 0;
+
+ printf("\n\n==== SORT TEST ====\n\n");
+
+ if ((error = col_create_collection(&level1, "level1", 0)) ||
+ (error = col_create_collection(&level2a, "level2a", 0)) ||
+ (error = col_add_collection_to_collection(level1, NULL, NULL, level2a, COL_ADD_MODE_REFERENCE)) ||
+ (error = col_create_collection(&level2b, "level2b", 0)) ||
+ (error = col_add_collection_to_collection(level1, NULL, NULL, level2b, COL_ADD_MODE_REFERENCE)) ||
+ (error = col_create_collection(&level3, "level3", 0)) ||
+ (error = col_add_collection_to_collection(level1, "level2a", NULL, level3, COL_ADD_MODE_REFERENCE)) ||
+ (error = col_add_collection_to_collection(level1, "level2b", NULL, level3, COL_ADD_MODE_REFERENCE)) ||
+ (error = col_add_int_property(level1, NULL, "int3", 1)) ||
+ (error = col_add_int_property(level1, NULL, "int2", 2)) ||
+ (error = col_add_int_property(level1, NULL, "int1", 3)) ||
+ (error = col_add_bool_property(level1, NULL, "bool3", 1)) ||
+ (error = col_add_bool_property(level1, NULL, "bool2", 1)) ||
+ (error = col_add_bool_property(level1, NULL, "bool1", 0)) ||
+ (error = col_add_unsigned_property(level1, NULL, "unsigned1", 2)) ||
+ (error = col_add_unsigned_property(level1, NULL, "unsigned3", 1)) ||
+ (error = col_add_unsigned_property(level1, NULL, "unsigned2", 3)) ||
+ (error = col_add_long_property(level1, NULL, "long3", 1)) ||
+ (error = col_add_long_property(level1, NULL, "long2", 2)) ||
+ (error = col_add_long_property(level1, NULL, "long1", 3)) ||
+ (error = col_add_ulong_property(level1, NULL, "ulong1", 2)) ||
+ (error = col_add_ulong_property(level1, NULL, "ulong3", 1)) ||
+ (error = col_add_ulong_property(level1, NULL, "ulong2", 3)) ||
+ (error = col_add_double_property(level1, NULL, "double1", 2.2)) ||
+ (error = col_add_double_property(level1, NULL, "double3", 1.1)) ||
+ (error = col_add_double_property(level1, NULL, "double2", 3.3)) ||
+ (error = col_add_int_property(level3, NULL, "int3L3", 1)) ||
+ (error = col_add_int_property(level3, NULL, "int2L3", 2)) ||
+ (error = col_add_int_property(level3, NULL, "int1L3", 3)) ||
+ (error = col_add_unsigned_property(level1, "level2a!level3", "unsigned1L3", 2)) ||
+ (error = col_add_unsigned_property(level1, "level2a!level3", "unsigned3L3", 1)) ||
+ (error = col_add_unsigned_property(level1, "level2a!level3", "unsigned2L3", 3)) ||
+ (error = col_add_long_property(level1, "level2b!level3", "long3L3", 1)) ||
+ (error = col_add_long_property(level1, "level2b!level3", "long2L3", 2)) ||
+ (error = col_add_long_property(level1, "level2b!level3", "long1L3", 3)) ||
+ (error = col_add_ulong_property(level1, "level3", "ulong1L3", 2)) ||
+ (error = col_add_ulong_property(level1, "level3", "ulong3L3", 1)) ||
+ (error = col_add_ulong_property(level1, "level3", "ulong2L3", 3)) ||
+ (error = col_add_bool_property(level3, NULL, "bool3", 1)) ||
+ (error = col_add_bool_property(level3, NULL, "bool2", 1)) ||
+ (error = col_add_bool_property(level3, NULL, "bool1", 0)) ||
+ (error = col_add_double_property(level3, NULL, "double1L3", 2.2)) ||
+ (error = col_add_double_property(level3, NULL, "double3L3", 1.1)) ||
+ (error = col_add_double_property(level3, NULL, "double2L3", 3.3))) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed to build test. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nUNSORTED COLLECTION\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ error = col_sort_collection(level1, COL_CMPIN_PROP_EQU, COL_SORT_SUB | COL_SORT_MYSUB);
+ if (error) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed sort. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nSORTED BUT SKIPPING REFERENCES\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ error = col_sort_collection(level1, COL_CMPIN_PROP_EQU, COL_SORT_SUB);
+ if (error) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed sort. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nSORTED BUT NOT SKIPPING REFERENCES\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ error = col_sort_collection(level1, COL_CMPIN_DATA_LEN, COL_SORT_SUB | COL_SORT_DESC);
+ if (error) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed sort. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nSORTED DESC NOT SKIPPING BY LENGTH OF DATA\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ error = col_sort_collection(level1, COL_CMPIN_PROP_LEN, COL_SORT_SUB | COL_SORT_DESC);
+ if (error) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed sort. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nSORTED DESC NOT SKIPPING BY LENGTH OF PROPERTY\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ error = col_sort_collection(level1, COL_CMPIN_DATA, COL_SORT_SUB | COL_SORT_DESC);
+ if (error) {
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+ printf("Failed sort. Error %d\n", error);
+ return error;
+ }
+
+ printf("\nSORTED DESC NOT SKIPPING BY DATA\n\n");
+ col_debug_collection(level1, COL_TRAVERSE_DEFAULT);
+
+ col_destroy_collection(level1);
+ col_destroy_collection(level2a);
+ col_destroy_collection(level2b);
+ col_destroy_collection(level3);
+
+ printf("\n\n==== SORT TEST END ====\n\n");
+
+ return EOK;
+}
/* Main function of the unit test */
@@ -1439,7 +1579,8 @@ int main(int argc, char *argv[])
(error = iterator_test()) ||
(error = insert_extract_test()) ||
(error = delete_test()) ||
- (error = search_test())) {
+ (error = search_test()) ||
+ (error = sort_test())) {
printf("Failed!\n");
}
else printf("Success!\n");
diff --git a/common/collection/configure.ac b/common/collection/configure.ac
index 4858bc61..cf7a1ff3 100644
--- a/common/collection/configure.ac
+++ b/common/collection/configure.ac
@@ -24,5 +24,12 @@ AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TR
AC_CHECK_SIZEOF([long])
AC_CHECK_SIZEOF([long long])
+AC_CHECK_FUNC([strcasestr],
+ AC_DEFINE([HAVE_STRCASESTR],
+ [1],
+ [Define if strcasestr exists]),
+ AC_MSG_ERROR("Platform must support strcasestr"))
+
+
AC_CONFIG_FILES([Makefile collection.pc])
AC_OUTPUT