mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 12:34:47 +00:00
Add ordered retrieval (#120)
Add ordered retrieval functions to the tree-based containers.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
151
src/map.c
151
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.
|
||||
*
|
||||
|
||||
151
src/multimap.c
151
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.
|
||||
*
|
||||
|
||||
151
src/multiset.c
151
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.
|
||||
*
|
||||
|
||||
151
src/set.c
151
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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user