diff options
author | Dmitri Pal <dpal@redhat.com> | 2009-09-14 12:52:23 -0400 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2009-10-05 10:32:06 -0400 |
commit | a71c65a45586b3f6cd5032016621d41d62a8c4f0 (patch) | |
tree | 3cfa4bd303fcb5cdf9c540a7190eebb9768f961b | |
parent | 4e0314ecad0fb649bcc2d6384a84ae818ef7c972 (diff) | |
download | sssd-a71c65a45586b3f6cd5032016621d41d62a8c4f0.tar.gz sssd-a71c65a45586b3f6cd5032016621d41d62a8c4f0.tar.xz sssd-a71c65a45586b3f6cd5032016621d41d62a8c4f0.zip |
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-- | common/collection/Makefile.am | 1 | ||||
-rw-r--r-- | common/collection/collection.c | 2 | ||||
-rw-r--r-- | common/collection/collection.h | 107 | ||||
-rw-r--r-- | common/collection/collection_cmp.c | 436 | ||||
-rw-r--r-- | common/collection/collection_tools.c | 2 | ||||
-rw-r--r-- | common/collection/collection_ut.c | 147 | ||||
-rw-r--r-- | common/collection/configure.ac | 7 |
7 files changed, 697 insertions, 5 deletions
diff --git a/common/collection/Makefile.am b/common/collection/Makefile.am index 323a5cb0e..8e4e97364 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 bccb50df5..c116f481f 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 dc59ea2f9..b4bbb2a4b 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 000000000..c1f9017d0 --- /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 c3f00eafb..503a1a8c4 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 050c6ef1e..c17f5bc7b 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 4858bc61f..cf7a1ff3c 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 |