summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-09-14 12:52:23 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-10-05 10:32:06 -0400
commitc52f433eeb76edb9582b4b08586cd942578b7cab (patch)
tree361244b88138eb0ebe8867cafab4e67fb85728b1
parentc8afa2d4bd5ecd6cf5f4dc5d0cbedb9470ce848a (diff)
COLLECTION Adding item comparison and sorting
Needed item comparison functions and realized that the easiest way to test them would be using sorting. Since there already been a ticket #73 to do that I added function to sort collection based on different properties of the item. COLLECTION Fixing issues with comparisons COLLECTION Adding do-while to macro
-rw-r--r--collection/Makefile.am1
-rw-r--r--collection/collection.c2
-rw-r--r--collection/collection.h107
-rw-r--r--collection/collection_cmp.c436
-rw-r--r--collection/collection_tools.c2
-rw-r--r--collection/collection_ut.c147
-rw-r--r--collection/configure.ac7
7 files changed, 697 insertions, 5 deletions
diff --git a/collection/Makefile.am b/collection/Makefile.am
index 323a5cb..8e4e973 100644
--- a/collection/Makefile.am
+++ b/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/collection/collection.c b/collection/collection.c
index bccb50d..c116f48 100644
--- a/collection/collection.c
+++ b/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/collection/collection.h b/collection/collection.h
index dc59ea2..b4bbb2a 100644
--- a/collection/collection.h
+++ b/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/collection/collection_cmp.c b/collection/collection_cmp.c
new file mode 100644
index 0000000..c1f9017
--- /dev/null
+++ b/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/collection/collection_tools.c b/collection/collection_tools.c
index c3f00ea..503a1a8 100644
--- a/collection/collection_tools.c
+++ b/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/collection/collection_ut.c b/collection/collection_ut.c
index 050c6ef..c17f5bc 100644
--- a/collection/collection_ut.c
+++ b/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/collection/configure.ac b/collection/configure.ac
index 4858bc6..cf7a1ff 100644
--- a/collection/configure.ac
+++ b/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