diff --git a/src/include/map.h b/src/include/map.h index 0734efd..d6db0c4 100644 --- a/src/include/map.h +++ b/src/include/map.h @@ -45,6 +45,14 @@ bk_bool map_get(void *value, map me, void *key); bk_bool map_contains(map me, void *key); bk_bool map_remove(map me, void *key); +/* Retrieval */ +void *map_first(map me); +void *map_last(map me); +void *map_lower(map me, void *key); +void *map_higher(map me, void *key); +void *map_floor(map me, void *key); +void *map_ceiling(map me, void *key); + /* Ending */ void map_clear(map me); map map_destroy(map me); diff --git a/src/include/multimap.h b/src/include/multimap.h index f233f4f..757d7e8 100644 --- a/src/include/multimap.h +++ b/src/include/multimap.h @@ -51,6 +51,14 @@ bk_bool multimap_contains(multimap me, void *key); bk_bool multimap_remove(multimap me, void *key, void *value); bk_bool multimap_remove_all(multimap me, void *key); +/* Retrieval */ +void *multimap_first(multimap me); +void *multimap_last(multimap me); +void *multimap_lower(multimap me, void *key); +void *multimap_higher(multimap me, void *key); +void *multimap_floor(multimap me, void *key); +void *multimap_ceiling(multimap me, void *key); + /* Ending */ void multimap_clear(multimap me); multimap multimap_destroy(multimap me); diff --git a/src/include/multiset.h b/src/include/multiset.h index c6bf006..7d1a394 100644 --- a/src/include/multiset.h +++ b/src/include/multiset.h @@ -47,6 +47,14 @@ bk_bool multiset_contains(multiset me, void *key); bk_bool multiset_remove(multiset me, void *key); bk_bool multiset_remove_all(multiset me, void *key); +/* Retrieval */ +void *multiset_first(multiset me); +void *multiset_last(multiset me); +void *multiset_lower(multiset me, void *key); +void *multiset_higher(multiset me, void *key); +void *multiset_floor(multiset me, void *key); +void *multiset_ceiling(multiset me, void *key); + /* Ending */ void multiset_clear(multiset me); multiset multiset_destroy(multiset me); diff --git a/src/include/set.h b/src/include/set.h index 73758df..8117d85 100644 --- a/src/include/set.h +++ b/src/include/set.h @@ -43,6 +43,14 @@ bk_err set_put(set me, void *key); bk_bool set_contains(set me, void *key); bk_bool set_remove(set me, void *key); +/* Retrieval */ +void *set_first(set me); +void *set_last(set me); +void *set_lower(set me, void *key); +void *set_higher(set me, void *key); +void *set_floor(set me, void *key); +void *set_ceiling(set me, void *key); + /* Ending */ void set_clear(set me); set set_destroy(set me); diff --git a/src/map.c b/src/map.c index 45d0764..d627577 100644 --- a/src/map.c +++ b/src/map.c @@ -721,6 +721,157 @@ bk_bool map_remove(map me, void *const key) return BK_TRUE; } +/** + * Returns the first (lowest) key in this map. The returned key is a pointer to + * the internally stored key, which should not be modified. Modifying it results + * in undefined behaviour. + * + * @param me the map to get the key from + * + * @return the lowest key in this map, or NULL if it is empty + */ +void *map_first(map me) +{ + char *traverse = me->root; + char *traverse_left; + if (!traverse) { + return NULL; + } + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + while (traverse_left) { + traverse = traverse_left; + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the last (highest) key in this map. The returned key is a pointer to + * the internally stored key, which should not be modified. Modifying it results + * in undefined behaviour. + * + * @param me the map to get the key from + * + * @return the highest key in this map, or NULL if it is empty + */ +void *map_last(map me) +{ + char *traverse = me->root; + char *traverse_right; + if (!traverse) { + return NULL; + } + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + while (traverse_right) { + traverse = traverse_right; + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the key which is strictly lower than the comparison key. Meaning that + * the highest key which is lower than the key used for comparison is returned. + * + * @param me the map to get the lower key from + * @param key the key to use for comparison + * + * @return the key which is strictly lower, or NULL if it does not exist + */ +void *map_lower(map me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare < 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is strictly higher than the comparison key. Meaning + * that the lowest key which is higher than the key used for comparison is + * returned. + * + * @param me the map to get the higher key from + * @param key the key to use for comparison + * + * @return the key which is strictly higher, or NULL if it does not exist + */ +void *map_higher(map me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare > 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the floor of the comparison key. Meaning that the + * the highest key which is lower or equal to the key used for comparison is + * returned. + * + * @param me the map to get the floor key from + * @param key the key to use for comparison + * + * @return the key which is the floor, or NULL if it does not exist + */ +void *map_floor(map me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare <= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the ceiling of the comparison key. Meaning that the + * the lowest key which is higher or equal to the key used for comparison is + * returned. + * + * @param me the map to get the ceiling key from + * @param key the key to use for comparison + * + * @return the key which is the ceiling, or NULL if it does not exist + */ +void *map_ceiling(map me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare >= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + /** * Clears the key-value pairs from the map. * diff --git a/src/multimap.c b/src/multimap.c index bf77c51..52cc00b 100644 --- a/src/multimap.c +++ b/src/multimap.c @@ -910,6 +910,157 @@ bk_bool multimap_remove_all(multimap me, void *const key) return BK_TRUE; } +/** + * Returns the first (lowest) key in this multi-map. The returned key is a + * pointer to the internally stored key, which should not be modified. Modifying + * it results in undefined behaviour. + * + * @param me the multi-map to get the key from + * + * @return the lowest key in this multi-map, or NULL if it is empty + */ +void *multimap_first(multimap me) +{ + char *traverse = me->root; + char *traverse_left; + if (!traverse) { + return NULL; + } + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + while (traverse_left) { + traverse = traverse_left; + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the last (highest) key in this multi-map. The returned key is a + * pointer to the internally stored key, which should not be modified. Modifying + * it results in undefined behaviour. + * + * @param me the multi-map to get the key from + * + * @return the highest key in this multi-map, or NULL if it is empty + */ +void *multimap_last(multimap me) +{ + char *traverse = me->root; + char *traverse_right; + if (!traverse) { + return NULL; + } + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + while (traverse_right) { + traverse = traverse_right; + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the key which is strictly lower than the comparison key. Meaning that + * the highest key which is lower than the key used for comparison is returned. + * + * @param me the multi-map to get the lower key from + * @param key the key to use for comparison + * + * @return the key which is strictly lower, or NULL if it does not exist + */ +void *multimap_lower(multimap me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->key_comparator(traverse + node_key_offset, key); + if (compare < 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is strictly higher than the comparison key. Meaning + * that the lowest key which is higher than the key used for comparison is + * returned. + * + * @param me the multi-map to get the higher key from + * @param key the key to use for comparison + * + * @return the key which is strictly higher, or NULL if it does not exist + */ +void *multimap_higher(multimap me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->key_comparator(traverse + node_key_offset, key); + if (compare > 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the floor of the comparison key. Meaning that the + * the highest key which is lower or equal to the key used for comparison is + * returned. + * + * @param me the multi-map to get the floor key from + * @param key the key to use for comparison + * + * @return the key which is the floor, or NULL if it does not exist + */ +void *multimap_floor(multimap me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->key_comparator(traverse + node_key_offset, key); + if (compare <= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the ceiling of the comparison key. Meaning that the + * the lowest key which is higher or equal to the key used for comparison is + * returned. + * + * @param me the multi-map to get the ceiling key from + * @param key the key to use for comparison + * + * @return the key which is the ceiling, or NULL if it does not exist + */ +void *multimap_ceiling(multimap me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->key_comparator(traverse + node_key_offset, key); + if (compare >= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + /** * Clears the key-value pairs from the multi-map. * diff --git a/src/multiset.c b/src/multiset.c index 401de75..0f22e10 100644 --- a/src/multiset.c +++ b/src/multiset.c @@ -763,6 +763,157 @@ bk_bool multiset_remove_all(multiset me, void *const key) return BK_TRUE; } +/** + * Returns the first (lowest) key in this multi-set. The returned key is a + * pointer to the internally stored key, which should not be modified. Modifying + * it results in undefined behaviour. + * + * @param me the multi-set to get the key from + * + * @return the lowest key in this multi-set, or NULL if it is empty + */ +void *multiset_first(multiset me) +{ + char *traverse = me->root; + char *traverse_left; + if (!traverse) { + return NULL; + } + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + while (traverse_left) { + traverse = traverse_left; + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the last (highest) key in this multi-set. The returned key is a + * pointer to the internally stored key, which should not be modified. Modifying + * it results in undefined behaviour. + * + * @param me the multi-set to get the key from + * + * @return the highest key in this multi-set, or NULL if it is empty + */ +void *multiset_last(multiset me) +{ + char *traverse = me->root; + char *traverse_right; + if (!traverse) { + return NULL; + } + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + while (traverse_right) { + traverse = traverse_right; + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the key which is strictly lower than the comparison key. Meaning that + * the highest key which is lower than the key used for comparison is returned. + * + * @param me the multi-set to get the lower key from + * @param key the key to use for comparison + * + * @return the key which is strictly lower, or NULL if it does not exist + */ +void *multiset_lower(multiset me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare < 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is strictly higher than the comparison key. Meaning + * that the lowest key which is higher than the key used for comparison is + * returned. + * + * @param me the multi-set to get the higher key from + * @param key the key to use for comparison + * + * @return the key which is strictly higher, or NULL if it does not exist + */ +void *multiset_higher(multiset me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare > 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the floor of the comparison key. Meaning that the + * the highest key which is lower or equal to the key used for comparison is + * returned. + * + * @param me the multi-set to get the floor key from + * @param key the key to use for comparison + * + * @return the key which is the floor, or NULL if it does not exist + */ +void *multiset_floor(multiset me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare <= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the ceiling of the comparison key. Meaning that the + * the lowest key which is higher or equal to the key used for comparison is + * returned. + * + * @param me the multi-set to get the ceiling key from + * @param key the key to use for comparison + * + * @return the key which is the ceiling, or NULL if it does not exist + */ +void *multiset_ceiling(multiset me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare >= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + /** * Clears the keys from the multiset. * diff --git a/src/set.c b/src/set.c index e9a4a62..686884a 100644 --- a/src/set.c +++ b/src/set.c @@ -684,6 +684,157 @@ bk_err set_remove(set me, void *const key) return BK_TRUE; } +/** + * Returns the first (lowest) key in this set. The returned key is a pointer to + * the internally stored key, which should not be modified. Modifying it results + * in undefined behaviour. + * + * @param me the set to get the key from + * + * @return the lowest key in this set, or NULL if it is empty + */ +void *set_first(set me) +{ + char *traverse = me->root; + char *traverse_left; + if (!traverse) { + return NULL; + } + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + while (traverse_left) { + traverse = traverse_left; + memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the last (highest) key in this set. The returned key is a pointer to + * the internally stored key, which should not be modified. Modifying it results + * in undefined behaviour. + * + * @param me the set to get the key from + * + * @return the highest key in this set, or NULL if it is empty + */ +void *set_last(set me) +{ + char *traverse = me->root; + char *traverse_right; + if (!traverse) { + return NULL; + } + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + while (traverse_right) { + traverse = traverse_right; + memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size); + } + return traverse + node_key_offset; +} + +/** + * Returns the key which is strictly lower than the comparison key. Meaning that + * the highest key which is lower than the key used for comparison is returned. + * + * @param me the set to get the lower key from + * @param key the key to use for comparison + * + * @return the key which is strictly lower, or NULL if it does not exist + */ +void *set_lower(set me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare < 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is strictly higher than the comparison key. Meaning + * that the lowest key which is higher than the key used for comparison is + * returned. + * + * @param me the set to get the higher key from + * @param key the key to use for comparison + * + * @return the key which is strictly higher, or NULL if it does not exist + */ +void *set_higher(set me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare > 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the floor of the comparison key. Meaning that the + * the highest key which is lower or equal to the key used for comparison is + * returned. + * + * @param me the set to get the floor key from + * @param key the key to use for comparison + * + * @return the key which is the floor, or NULL if it does not exist + */ +void *set_floor(set me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare <= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } + } + return ret; +} + +/** + * Returns the key which is the ceiling of the comparison key. Meaning that the + * the lowest key which is higher or equal to the key used for comparison is + * returned. + * + * @param me the set to get the ceiling key from + * @param key the key to use for comparison + * + * @return the key which is the ceiling, or NULL if it does not exist + */ +void *set_ceiling(set me, void *const key) +{ + char *ret = NULL; + char *traverse = me->root; + while (traverse) { + const int compare = me->comparator(traverse + node_key_offset, key); + if (compare >= 0) { + ret = traverse + node_key_offset; + memcpy(&traverse, traverse + node_left_child_offset, ptr_size); + } else { + memcpy(&traverse, traverse + node_right_child_offset, ptr_size); + } + } + return ret; +} + /** * Clears the keys from the set. * diff --git a/tst/test_map.c b/tst/test_map.c index f7fac6f..b891df9 100644 --- a/tst/test_map.c +++ b/tst/test_map.c @@ -601,6 +601,99 @@ static void test_big_object(void) assert(!map_destroy(me)); } +static void test_ordered_retrieval(void) +{ + int *get; + int val = 4; + map me = map_init(sizeof(int), sizeof(int), compare_int); + assert(!map_first(me)); + assert(!map_last(me)); + assert(map_put(me, &val, &val) == BK_OK); + get = map_first(me); + assert(val == *get); + get = map_last(me); + assert(val == *get); + val = 5; + assert(map_put(me, &val, &val) == BK_OK); + val = 3; + assert(map_put(me, &val, &val) == BK_OK); + get = map_first(me); + assert(3 == *get); + get = map_last(me); + assert(5 == *get); + /* Lower tests */ + val = 7; + get = map_lower(me, &val); + assert(5 == *get); + val = 6; + get = map_lower(me, &val); + assert(5 == *get); + val = 5; + get = map_lower(me, &val); + assert(4 == *get); + val = 4; + get = map_lower(me, &val); + assert(3 == *get); + val = 3; + get = map_lower(me, &val); + assert(!get); + /* Higher tests */ + val = 1; + get = map_higher(me, &val); + assert(3 == *get); + val = 2; + get = map_higher(me, &val); + assert(3 == *get); + val = 3; + get = map_higher(me, &val); + assert(4 == *get); + val = 4; + get = map_higher(me, &val); + assert(5 == *get); + val = 5; + get = map_higher(me, &val); + assert(!get); + /* Floor tests */ + val = 7; + get = map_floor(me, &val); + assert(5 == *get); + val = 6; + get = map_floor(me, &val); + assert(5 == *get); + val = 5; + get = map_floor(me, &val); + assert(5 == *get); + val = 4; + get = map_floor(me, &val); + assert(4 == *get); + val = 3; + get = map_floor(me, &val); + assert(3 == *get); + val = 2; + get = map_floor(me, &val); + assert(!get); + /* Ceiling tests */ + val = 1; + get = map_ceiling(me, &val); + assert(3 == *get); + val = 2; + get = map_ceiling(me, &val); + assert(3 == *get); + val = 3; + get = map_ceiling(me, &val); + assert(3 == *get); + val = 4; + get = map_ceiling(me, &val); + assert(4 == *get); + val = 5; + get = map_ceiling(me, &val); + assert(5 == *get); + val = 6; + get = map_ceiling(me, &val); + assert(!get); + map_destroy(me); +} + void test_map(void) { test_invalid_init(); @@ -617,4 +710,5 @@ void test_map(void) test_put_out_of_memory(); #endif test_big_object(); + test_ordered_retrieval(); } diff --git a/tst/test_multimap.c b/tst/test_multimap.c index e8cefa7..dee2a95 100644 --- a/tst/test_multimap.c +++ b/tst/test_multimap.c @@ -674,6 +674,100 @@ static void test_big_object(void) assert(!multimap_destroy(me)); } +static void test_ordered_retrieval(void) +{ + int *get; + int val = 4; + multimap me = multimap_init(sizeof(int), sizeof(int), compare_int, + compare_int); + assert(!multimap_first(me)); + assert(!multimap_last(me)); + assert(multimap_put(me, &val, &val) == BK_OK); + get = multimap_first(me); + assert(val == *get); + get = multimap_last(me); + assert(val == *get); + val = 5; + assert(multimap_put(me, &val, &val) == BK_OK); + val = 3; + assert(multimap_put(me, &val, &val) == BK_OK); + get = multimap_first(me); + assert(3 == *get); + get = multimap_last(me); + assert(5 == *get); + /* Lower tests */ + val = 7; + get = multimap_lower(me, &val); + assert(5 == *get); + val = 6; + get = multimap_lower(me, &val); + assert(5 == *get); + val = 5; + get = multimap_lower(me, &val); + assert(4 == *get); + val = 4; + get = multimap_lower(me, &val); + assert(3 == *get); + val = 3; + get = multimap_lower(me, &val); + assert(!get); + /* Higher tests */ + val = 1; + get = multimap_higher(me, &val); + assert(3 == *get); + val = 2; + get = multimap_higher(me, &val); + assert(3 == *get); + val = 3; + get = multimap_higher(me, &val); + assert(4 == *get); + val = 4; + get = multimap_higher(me, &val); + assert(5 == *get); + val = 5; + get = multimap_higher(me, &val); + assert(!get); + /* Floor tests */ + val = 7; + get = multimap_floor(me, &val); + assert(5 == *get); + val = 6; + get = multimap_floor(me, &val); + assert(5 == *get); + val = 5; + get = multimap_floor(me, &val); + assert(5 == *get); + val = 4; + get = multimap_floor(me, &val); + assert(4 == *get); + val = 3; + get = multimap_floor(me, &val); + assert(3 == *get); + val = 2; + get = multimap_floor(me, &val); + assert(!get); + /* Ceiling tests */ + val = 1; + get = multimap_ceiling(me, &val); + assert(3 == *get); + val = 2; + get = multimap_ceiling(me, &val); + assert(3 == *get); + val = 3; + get = multimap_ceiling(me, &val); + assert(3 == *get); + val = 4; + get = multimap_ceiling(me, &val); + assert(4 == *get); + val = 5; + get = multimap_ceiling(me, &val); + assert(5 == *get); + val = 6; + get = multimap_ceiling(me, &val); + assert(!get); + multimap_destroy(me); +} + void test_multimap(void) { test_invalid_init(); @@ -691,4 +785,5 @@ void test_multimap(void) test_put_out_of_memory(); #endif test_big_object(); + test_ordered_retrieval(); } diff --git a/tst/test_multiset.c b/tst/test_multiset.c index a1773f0..945d5e3 100644 --- a/tst/test_multiset.c +++ b/tst/test_multiset.c @@ -605,6 +605,99 @@ static void test_big_object(void) assert(!multiset_destroy(me)); } +static void test_ordered_retrieval(void) +{ + int *get; + int val = 4; + multiset me = multiset_init(sizeof(int), compare_int); + assert(!multiset_first(me)); + assert(!multiset_last(me)); + assert(multiset_put(me, &val) == BK_OK); + get = multiset_first(me); + assert(val == *get); + get = multiset_last(me); + assert(val == *get); + val = 5; + assert(multiset_put(me, &val) == BK_OK); + val = 3; + assert(multiset_put(me, &val) == BK_OK); + get = multiset_first(me); + assert(3 == *get); + get = multiset_last(me); + assert(5 == *get); + /* Lower tests */ + val = 7; + get = multiset_lower(me, &val); + assert(5 == *get); + val = 6; + get = multiset_lower(me, &val); + assert(5 == *get); + val = 5; + get = multiset_lower(me, &val); + assert(4 == *get); + val = 4; + get = multiset_lower(me, &val); + assert(3 == *get); + val = 3; + get = multiset_lower(me, &val); + assert(!get); + /* Higher tests */ + val = 1; + get = multiset_higher(me, &val); + assert(3 == *get); + val = 2; + get = multiset_higher(me, &val); + assert(3 == *get); + val = 3; + get = multiset_higher(me, &val); + assert(4 == *get); + val = 4; + get = multiset_higher(me, &val); + assert(5 == *get); + val = 5; + get = multiset_higher(me, &val); + assert(!get); + /* Floor tests */ + val = 7; + get = multiset_floor(me, &val); + assert(5 == *get); + val = 6; + get = multiset_floor(me, &val); + assert(5 == *get); + val = 5; + get = multiset_floor(me, &val); + assert(5 == *get); + val = 4; + get = multiset_floor(me, &val); + assert(4 == *get); + val = 3; + get = multiset_floor(me, &val); + assert(3 == *get); + val = 2; + get = multiset_floor(me, &val); + assert(!get); + /* Ceiling tests */ + val = 1; + get = multiset_ceiling(me, &val); + assert(3 == *get); + val = 2; + get = multiset_ceiling(me, &val); + assert(3 == *get); + val = 3; + get = multiset_ceiling(me, &val); + assert(3 == *get); + val = 4; + get = multiset_ceiling(me, &val); + assert(4 == *get); + val = 5; + get = multiset_ceiling(me, &val); + assert(5 == *get); + val = 6; + get = multiset_ceiling(me, &val); + assert(!get); + multiset_destroy(me); +} + void test_multiset(void) { test_invalid_init(); @@ -621,4 +714,5 @@ void test_multiset(void) test_put_out_of_memory(); #endif test_big_object(); + test_ordered_retrieval(); } diff --git a/tst/test_set.c b/tst/test_set.c index e07e7e9..304e721 100644 --- a/tst/test_set.c +++ b/tst/test_set.c @@ -574,6 +574,99 @@ static void test_big_object(void) assert(!set_destroy(me)); } +static void test_ordered_retrieval(void) +{ + int *get; + int val = 4; + set me = set_init(sizeof(int), compare_int); + assert(!set_first(me)); + assert(!set_last(me)); + assert(set_put(me, &val) == BK_OK); + get = set_first(me); + assert(val == *get); + get = set_last(me); + assert(val == *get); + val = 5; + assert(set_put(me, &val) == BK_OK); + val = 3; + assert(set_put(me, &val) == BK_OK); + get = set_first(me); + assert(3 == *get); + get = set_last(me); + assert(5 == *get); + /* Lower tests */ + val = 7; + get = set_lower(me, &val); + assert(5 == *get); + val = 6; + get = set_lower(me, &val); + assert(5 == *get); + val = 5; + get = set_lower(me, &val); + assert(4 == *get); + val = 4; + get = set_lower(me, &val); + assert(3 == *get); + val = 3; + get = set_lower(me, &val); + assert(!get); + /* Higher tests */ + val = 1; + get = set_higher(me, &val); + assert(3 == *get); + val = 2; + get = set_higher(me, &val); + assert(3 == *get); + val = 3; + get = set_higher(me, &val); + assert(4 == *get); + val = 4; + get = set_higher(me, &val); + assert(5 == *get); + val = 5; + get = set_higher(me, &val); + assert(!get); + /* Floor tests */ + val = 7; + get = set_floor(me, &val); + assert(5 == *get); + val = 6; + get = set_floor(me, &val); + assert(5 == *get); + val = 5; + get = set_floor(me, &val); + assert(5 == *get); + val = 4; + get = set_floor(me, &val); + assert(4 == *get); + val = 3; + get = set_floor(me, &val); + assert(3 == *get); + val = 2; + get = set_floor(me, &val); + assert(!get); + /* Ceiling tests */ + val = 1; + get = set_ceiling(me, &val); + assert(3 == *get); + val = 2; + get = set_ceiling(me, &val); + assert(3 == *get); + val = 3; + get = set_ceiling(me, &val); + assert(3 == *get); + val = 4; + get = set_ceiling(me, &val); + assert(4 == *get); + val = 5; + get = set_ceiling(me, &val); + assert(5 == *get); + val = 6; + get = set_ceiling(me, &val); + assert(!get); + set_destroy(me); +} + void test_set(void) { test_invalid_init(); @@ -589,4 +682,5 @@ void test_set(void) test_put_out_of_memory(); #endif test_big_object(); + test_ordered_retrieval(); }