Skip to content

Commit c77aa4d

Browse files
authored
Add ordered retrieval (#120)
Add ordered retrieval functions to the tree-based containers.
1 parent 6af6778 commit c77aa4d

12 files changed

Lines changed: 1013 additions & 0 deletions

File tree

src/include/map.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ bk_bool map_get(void *value, map me, void *key);
4545
bk_bool map_contains(map me, void *key);
4646
bk_bool map_remove(map me, void *key);
4747

48+
/* Retrieval */
49+
void *map_first(map me);
50+
void *map_last(map me);
51+
void *map_lower(map me, void *key);
52+
void *map_higher(map me, void *key);
53+
void *map_floor(map me, void *key);
54+
void *map_ceiling(map me, void *key);
55+
4856
/* Ending */
4957
void map_clear(map me);
5058
map map_destroy(map me);

src/include/multimap.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ bk_bool multimap_contains(multimap me, void *key);
5151
bk_bool multimap_remove(multimap me, void *key, void *value);
5252
bk_bool multimap_remove_all(multimap me, void *key);
5353

54+
/* Retrieval */
55+
void *multimap_first(multimap me);
56+
void *multimap_last(multimap me);
57+
void *multimap_lower(multimap me, void *key);
58+
void *multimap_higher(multimap me, void *key);
59+
void *multimap_floor(multimap me, void *key);
60+
void *multimap_ceiling(multimap me, void *key);
61+
5462
/* Ending */
5563
void multimap_clear(multimap me);
5664
multimap multimap_destroy(multimap me);

src/include/multiset.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ bk_bool multiset_contains(multiset me, void *key);
4747
bk_bool multiset_remove(multiset me, void *key);
4848
bk_bool multiset_remove_all(multiset me, void *key);
4949

50+
/* Retrieval */
51+
void *multiset_first(multiset me);
52+
void *multiset_last(multiset me);
53+
void *multiset_lower(multiset me, void *key);
54+
void *multiset_higher(multiset me, void *key);
55+
void *multiset_floor(multiset me, void *key);
56+
void *multiset_ceiling(multiset me, void *key);
57+
5058
/* Ending */
5159
void multiset_clear(multiset me);
5260
multiset multiset_destroy(multiset me);

src/include/set.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ bk_err set_put(set me, void *key);
4343
bk_bool set_contains(set me, void *key);
4444
bk_bool set_remove(set me, void *key);
4545

46+
/* Retrieval */
47+
void *set_first(set me);
48+
void *set_last(set me);
49+
void *set_lower(set me, void *key);
50+
void *set_higher(set me, void *key);
51+
void *set_floor(set me, void *key);
52+
void *set_ceiling(set me, void *key);
53+
4654
/* Ending */
4755
void set_clear(set me);
4856
set set_destroy(set me);

src/map.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,157 @@ bk_bool map_remove(map me, void *const key)
721721
return BK_TRUE;
722722
}
723723

724+
/**
725+
* Returns the first (lowest) key in this map. The returned key is a pointer to
726+
* the internally stored key, which should not be modified. Modifying it results
727+
* in undefined behaviour.
728+
*
729+
* @param me the map to get the key from
730+
*
731+
* @return the lowest key in this map, or NULL if it is empty
732+
*/
733+
void *map_first(map me)
734+
{
735+
char *traverse = me->root;
736+
char *traverse_left;
737+
if (!traverse) {
738+
return NULL;
739+
}
740+
memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size);
741+
while (traverse_left) {
742+
traverse = traverse_left;
743+
memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size);
744+
}
745+
return traverse + node_key_offset;
746+
}
747+
748+
/**
749+
* Returns the last (highest) key in this map. The returned key is a pointer to
750+
* the internally stored key, which should not be modified. Modifying it results
751+
* in undefined behaviour.
752+
*
753+
* @param me the map to get the key from
754+
*
755+
* @return the highest key in this map, or NULL if it is empty
756+
*/
757+
void *map_last(map me)
758+
{
759+
char *traverse = me->root;
760+
char *traverse_right;
761+
if (!traverse) {
762+
return NULL;
763+
}
764+
memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size);
765+
while (traverse_right) {
766+
traverse = traverse_right;
767+
memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size);
768+
}
769+
return traverse + node_key_offset;
770+
}
771+
772+
/**
773+
* Returns the key which is strictly lower than the comparison key. Meaning that
774+
* the highest key which is lower than the key used for comparison is returned.
775+
*
776+
* @param me the map to get the lower key from
777+
* @param key the key to use for comparison
778+
*
779+
* @return the key which is strictly lower, or NULL if it does not exist
780+
*/
781+
void *map_lower(map me, void *const key)
782+
{
783+
char *ret = NULL;
784+
char *traverse = me->root;
785+
while (traverse) {
786+
const int compare = me->comparator(traverse + node_key_offset, key);
787+
if (compare < 0) {
788+
ret = traverse + node_key_offset;
789+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
790+
} else {
791+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
792+
}
793+
}
794+
return ret;
795+
}
796+
797+
/**
798+
* Returns the key which is strictly higher than the comparison key. Meaning
799+
* that the lowest key which is higher than the key used for comparison is
800+
* returned.
801+
*
802+
* @param me the map to get the higher key from
803+
* @param key the key to use for comparison
804+
*
805+
* @return the key which is strictly higher, or NULL if it does not exist
806+
*/
807+
void *map_higher(map me, void *const key)
808+
{
809+
char *ret = NULL;
810+
char *traverse = me->root;
811+
while (traverse) {
812+
const int compare = me->comparator(traverse + node_key_offset, key);
813+
if (compare > 0) {
814+
ret = traverse + node_key_offset;
815+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
816+
} else {
817+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
818+
}
819+
}
820+
return ret;
821+
}
822+
823+
/**
824+
* Returns the key which is the floor of the comparison key. Meaning that the
825+
* the highest key which is lower or equal to the key used for comparison is
826+
* returned.
827+
*
828+
* @param me the map to get the floor key from
829+
* @param key the key to use for comparison
830+
*
831+
* @return the key which is the floor, or NULL if it does not exist
832+
*/
833+
void *map_floor(map me, void *const key)
834+
{
835+
char *ret = NULL;
836+
char *traverse = me->root;
837+
while (traverse) {
838+
const int compare = me->comparator(traverse + node_key_offset, key);
839+
if (compare <= 0) {
840+
ret = traverse + node_key_offset;
841+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
842+
} else {
843+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
844+
}
845+
}
846+
return ret;
847+
}
848+
849+
/**
850+
* Returns the key which is the ceiling of the comparison key. Meaning that the
851+
* the lowest key which is higher or equal to the key used for comparison is
852+
* returned.
853+
*
854+
* @param me the map to get the ceiling key from
855+
* @param key the key to use for comparison
856+
*
857+
* @return the key which is the ceiling, or NULL if it does not exist
858+
*/
859+
void *map_ceiling(map me, void *const key)
860+
{
861+
char *ret = NULL;
862+
char *traverse = me->root;
863+
while (traverse) {
864+
const int compare = me->comparator(traverse + node_key_offset, key);
865+
if (compare >= 0) {
866+
ret = traverse + node_key_offset;
867+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
868+
} else {
869+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
870+
}
871+
}
872+
return ret;
873+
}
874+
724875
/**
725876
* Clears the key-value pairs from the map.
726877
*

src/multimap.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,157 @@ bk_bool multimap_remove_all(multimap me, void *const key)
910910
return BK_TRUE;
911911
}
912912

913+
/**
914+
* Returns the first (lowest) key in this multi-map. The returned key is a
915+
* pointer to the internally stored key, which should not be modified. Modifying
916+
* it results in undefined behaviour.
917+
*
918+
* @param me the multi-map to get the key from
919+
*
920+
* @return the lowest key in this multi-map, or NULL if it is empty
921+
*/
922+
void *multimap_first(multimap me)
923+
{
924+
char *traverse = me->root;
925+
char *traverse_left;
926+
if (!traverse) {
927+
return NULL;
928+
}
929+
memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size);
930+
while (traverse_left) {
931+
traverse = traverse_left;
932+
memcpy(&traverse_left, traverse + node_left_child_offset, ptr_size);
933+
}
934+
return traverse + node_key_offset;
935+
}
936+
937+
/**
938+
* Returns the last (highest) key in this multi-map. The returned key is a
939+
* pointer to the internally stored key, which should not be modified. Modifying
940+
* it results in undefined behaviour.
941+
*
942+
* @param me the multi-map to get the key from
943+
*
944+
* @return the highest key in this multi-map, or NULL if it is empty
945+
*/
946+
void *multimap_last(multimap me)
947+
{
948+
char *traverse = me->root;
949+
char *traverse_right;
950+
if (!traverse) {
951+
return NULL;
952+
}
953+
memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size);
954+
while (traverse_right) {
955+
traverse = traverse_right;
956+
memcpy(&traverse_right, traverse + node_right_child_offset, ptr_size);
957+
}
958+
return traverse + node_key_offset;
959+
}
960+
961+
/**
962+
* Returns the key which is strictly lower than the comparison key. Meaning that
963+
* the highest key which is lower than the key used for comparison is returned.
964+
*
965+
* @param me the multi-map to get the lower key from
966+
* @param key the key to use for comparison
967+
*
968+
* @return the key which is strictly lower, or NULL if it does not exist
969+
*/
970+
void *multimap_lower(multimap me, void *const key)
971+
{
972+
char *ret = NULL;
973+
char *traverse = me->root;
974+
while (traverse) {
975+
const int compare = me->key_comparator(traverse + node_key_offset, key);
976+
if (compare < 0) {
977+
ret = traverse + node_key_offset;
978+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
979+
} else {
980+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
981+
}
982+
}
983+
return ret;
984+
}
985+
986+
/**
987+
* Returns the key which is strictly higher than the comparison key. Meaning
988+
* that the lowest key which is higher than the key used for comparison is
989+
* returned.
990+
*
991+
* @param me the multi-map to get the higher key from
992+
* @param key the key to use for comparison
993+
*
994+
* @return the key which is strictly higher, or NULL if it does not exist
995+
*/
996+
void *multimap_higher(multimap me, void *const key)
997+
{
998+
char *ret = NULL;
999+
char *traverse = me->root;
1000+
while (traverse) {
1001+
const int compare = me->key_comparator(traverse + node_key_offset, key);
1002+
if (compare > 0) {
1003+
ret = traverse + node_key_offset;
1004+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
1005+
} else {
1006+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
1007+
}
1008+
}
1009+
return ret;
1010+
}
1011+
1012+
/**
1013+
* Returns the key which is the floor of the comparison key. Meaning that the
1014+
* the highest key which is lower or equal to the key used for comparison is
1015+
* returned.
1016+
*
1017+
* @param me the multi-map to get the floor key from
1018+
* @param key the key to use for comparison
1019+
*
1020+
* @return the key which is the floor, or NULL if it does not exist
1021+
*/
1022+
void *multimap_floor(multimap me, void *const key)
1023+
{
1024+
char *ret = NULL;
1025+
char *traverse = me->root;
1026+
while (traverse) {
1027+
const int compare = me->key_comparator(traverse + node_key_offset, key);
1028+
if (compare <= 0) {
1029+
ret = traverse + node_key_offset;
1030+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
1031+
} else {
1032+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
1033+
}
1034+
}
1035+
return ret;
1036+
}
1037+
1038+
/**
1039+
* Returns the key which is the ceiling of the comparison key. Meaning that the
1040+
* the lowest key which is higher or equal to the key used for comparison is
1041+
* returned.
1042+
*
1043+
* @param me the multi-map to get the ceiling key from
1044+
* @param key the key to use for comparison
1045+
*
1046+
* @return the key which is the ceiling, or NULL if it does not exist
1047+
*/
1048+
void *multimap_ceiling(multimap me, void *const key)
1049+
{
1050+
char *ret = NULL;
1051+
char *traverse = me->root;
1052+
while (traverse) {
1053+
const int compare = me->key_comparator(traverse + node_key_offset, key);
1054+
if (compare >= 0) {
1055+
ret = traverse + node_key_offset;
1056+
memcpy(&traverse, traverse + node_left_child_offset, ptr_size);
1057+
} else {
1058+
memcpy(&traverse, traverse + node_right_child_offset, ptr_size);
1059+
}
1060+
}
1061+
return ret;
1062+
}
1063+
9131064
/**
9141065
* Clears the key-value pairs from the multi-map.
9151066
*

0 commit comments

Comments
 (0)