| /** @file | |
| An ordered collection library interface. | |
| The library class provides a set of APIs to manage an ordered collection of | |
| items. | |
| Copyright (C) 2014, Red Hat, Inc. | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #ifndef __ORDERED_COLLECTION_LIB__ | |
| #define __ORDERED_COLLECTION_LIB__ | |
| #include <Base.h> | |
| // | |
| // Opaque structure for a collection. | |
| // | |
| typedef struct ORDERED_COLLECTION ORDERED_COLLECTION; | |
| // | |
| // Opaque structure for collection entries. | |
| // | |
| // Collection entries do not take ownership of the associated user structures, | |
| // they only link them. This makes it easy to link the same user structure into | |
| // several collections. If reference counting is required, the caller is | |
| // responsible for implementing it, as part of the user structure. | |
| // | |
| // A pointer-to-ORDERED_COLLECTION_ENTRY is considered an "iterator". Multiple, | |
| // simultaneous iterations are supported. | |
| // | |
| typedef struct ORDERED_COLLECTION_ENTRY ORDERED_COLLECTION_ENTRY; | |
| // | |
| // Altering the key field of an in-collection user structure (ie. the portion | |
| // of the user structure that ORDERED_COLLECTION_USER_COMPARE and | |
| // ORDERED_COLLECTION_KEY_COMPARE, below, read) is not allowed in-place. The | |
| // caller is responsible for bracketing the key change with the deletion and | |
| // the reinsertion of the user structure, so that the changed key value is | |
| // reflected in the collection. | |
| // | |
| /** | |
| Comparator function type for two user structures. | |
| @param[in] UserStruct1 Pointer to the first user structure. | |
| @param[in] UserStruct2 Pointer to the second user structure. | |
| @retval <0 If UserStruct1 compares less than UserStruct2. | |
| @retval 0 If UserStruct1 compares equal to UserStruct2. | |
| @retval >0 If UserStruct1 compares greater than UserStruct2. | |
| **/ | |
| typedef | |
| INTN | |
| (EFIAPI *ORDERED_COLLECTION_USER_COMPARE)( | |
| IN CONST VOID *UserStruct1, | |
| IN CONST VOID *UserStruct2 | |
| ); | |
| /** | |
| Compare a standalone key against a user structure containing an embedded key. | |
| @param[in] StandaloneKey Pointer to the bare key. | |
| @param[in] UserStruct Pointer to the user structure with the embedded | |
| key. | |
| @retval <0 If StandaloneKey compares less than UserStruct's key. | |
| @retval 0 If StandaloneKey compares equal to UserStruct's key. | |
| @retval >0 If StandaloneKey compares greater than UserStruct's key. | |
| **/ | |
| typedef | |
| INTN | |
| (EFIAPI *ORDERED_COLLECTION_KEY_COMPARE)( | |
| IN CONST VOID *StandaloneKey, | |
| IN CONST VOID *UserStruct | |
| ); | |
| // | |
| // Some functions below are read-only, while others are read-write. If any | |
| // write operation is expected to run concurrently with any other operation on | |
| // the same collection, then the caller is responsible for implementing locking | |
| // for the whole collection. | |
| // | |
| /** | |
| Retrieve the user structure linked by the specified collection entry. | |
| Read-only operation. | |
| @param[in] Entry Pointer to the collection entry whose associated user | |
| structure we want to retrieve. The caller is responsible | |
| for passing a non-NULL argument. | |
| @return Pointer to user structure linked by Entry. | |
| **/ | |
| VOID * | |
| EFIAPI | |
| OrderedCollectionUserStruct ( | |
| IN CONST ORDERED_COLLECTION_ENTRY *Entry | |
| ); | |
| /** | |
| Allocate and initialize the ORDERED_COLLECTION structure. | |
| @param[in] UserStructCompare This caller-provided function will be used to | |
| order two user structures linked into the | |
| collection, during the insertion procedure. | |
| @param[in] KeyCompare This caller-provided function will be used to | |
| order the standalone search key against user | |
| structures linked into the collection, during | |
| the lookup procedure. | |
| @retval NULL If allocation failed. | |
| @return Pointer to the allocated, initialized ORDERED_COLLECTION | |
| structure, otherwise. | |
| **/ | |
| ORDERED_COLLECTION * | |
| EFIAPI | |
| OrderedCollectionInit ( | |
| IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, | |
| IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare | |
| ); | |
| /** | |
| Check whether the collection is empty (has no entries). | |
| Read-only operation. | |
| @param[in] Collection The collection to check for emptiness. | |
| @retval TRUE The collection is empty. | |
| @retval FALSE The collection is not empty. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| OrderedCollectionIsEmpty ( | |
| IN CONST ORDERED_COLLECTION *Collection | |
| ); | |
| /** | |
| Uninitialize and release an empty ORDERED_COLLECTION structure. | |
| Read-write operation. | |
| It is the caller's responsibility to delete all entries from the collection | |
| before calling this function. | |
| @param[in] Collection The empty collection to uninitialize and release. | |
| **/ | |
| VOID | |
| EFIAPI | |
| OrderedCollectionUninit ( | |
| IN ORDERED_COLLECTION *Collection | |
| ); | |
| /** | |
| Look up the collection entry that links the user structure that matches the | |
| specified standalone key. | |
| Read-only operation. | |
| @param[in] Collection The collection to search for StandaloneKey. | |
| @param[in] StandaloneKey The key to locate among the user structures linked | |
| into Collection. StandaloneKey will be passed to | |
| ORDERED_COLLECTION_KEY_COMPARE. | |
| @retval NULL StandaloneKey could not be found. | |
| @return The collection entry that links to the user structure matching | |
| StandaloneKey, otherwise. | |
| **/ | |
| ORDERED_COLLECTION_ENTRY * | |
| EFIAPI | |
| OrderedCollectionFind ( | |
| IN CONST ORDERED_COLLECTION *Collection, | |
| IN CONST VOID *StandaloneKey | |
| ); | |
| /** | |
| Find the collection entry of the minimum user structure stored in the | |
| collection. | |
| Read-only operation. | |
| @param[in] Collection The collection to return the minimum entry of. The | |
| user structure linked by the minimum entry compares | |
| less than all other user structures in the collection. | |
| @retval NULL If Collection is empty. | |
| @return The collection entry that links the minimum user structure, | |
| otherwise. | |
| **/ | |
| ORDERED_COLLECTION_ENTRY * | |
| EFIAPI | |
| OrderedCollectionMin ( | |
| IN CONST ORDERED_COLLECTION *Collection | |
| ); | |
| /** | |
| Find the collection entry of the maximum user structure stored in the | |
| collection. | |
| Read-only operation. | |
| @param[in] Collection The collection to return the maximum entry of. The | |
| user structure linked by the maximum entry compares | |
| greater than all other user structures in the | |
| collection. | |
| @retval NULL If Collection is empty. | |
| @return The collection entry that links the maximum user structure, | |
| otherwise. | |
| **/ | |
| ORDERED_COLLECTION_ENTRY * | |
| EFIAPI | |
| OrderedCollectionMax ( | |
| IN CONST ORDERED_COLLECTION *Collection | |
| ); | |
| /** | |
| Get the collection entry of the least user structure that is greater than the | |
| one linked by Entry. | |
| Read-only operation. | |
| @param[in] Entry The entry to get the successor entry of. | |
| @retval NULL If Entry is NULL, or Entry is the maximum entry of its | |
| containing collection (ie. Entry has no successor entry). | |
| @return The collection entry linking the least user structure that is | |
| greater than the one linked by Entry, otherwise. | |
| **/ | |
| ORDERED_COLLECTION_ENTRY * | |
| EFIAPI | |
| OrderedCollectionNext ( | |
| IN CONST ORDERED_COLLECTION_ENTRY *Entry | |
| ); | |
| /** | |
| Get the collection entry of the greatest user structure that is less than the | |
| one linked by Entry. | |
| Read-only operation. | |
| @param[in] Entry The entry to get the predecessor entry of. | |
| @retval NULL If Entry is NULL, or Entry is the minimum entry of its | |
| containing collection (ie. Entry has no predecessor entry). | |
| @return The collection entry linking the greatest user structure that | |
| is less than the one linked by Entry, otherwise. | |
| **/ | |
| ORDERED_COLLECTION_ENTRY * | |
| EFIAPI | |
| OrderedCollectionPrev ( | |
| IN CONST ORDERED_COLLECTION_ENTRY *Entry | |
| ); | |
| /** | |
| Insert (link) a user structure into the collection, allocating a new | |
| collection entry. | |
| Read-write operation. | |
| @param[in,out] Collection The collection to insert UserStruct into. | |
| @param[out] Entry The meaning of this optional, output-only | |
| parameter depends on the return value of the | |
| function. | |
| When insertion is successful (RETURN_SUCCESS), | |
| Entry is set on output to the new collection entry | |
| that now links UserStruct. | |
| When insertion fails due to lack of memory | |
| (RETURN_OUT_OF_RESOURCES), Entry is not changed. | |
| When insertion fails due to key collision (ie. | |
| another user structure is already in the | |
| collection that compares equal to UserStruct), | |
| with return value RETURN_ALREADY_STARTED, then | |
| Entry is set on output to the entry that links the | |
| colliding user structure. This enables | |
| "find-or-insert" in one function call, or helps | |
| with later removal of the colliding element. | |
| @param[in] UserStruct The user structure to link into the collection. | |
| UserStruct is ordered against in-collection user | |
| structures with the | |
| ORDERED_COLLECTION_USER_COMPARE function. | |
| @retval RETURN_SUCCESS Insertion successful. A new collection entry | |
| has been allocated, linking UserStruct. The | |
| new collection entry is reported back in | |
| Entry (if the caller requested it). | |
| Existing ORDERED_COLLECTION_ENTRY pointers | |
| into Collection remain valid. For example, | |
| on-going iterations in the caller can | |
| continue with OrderedCollectionNext() / | |
| OrderedCollectionPrev(), and they will | |
| return the new entry at some point if user | |
| structure order dictates it. | |
| @retval RETURN_OUT_OF_RESOURCES The function failed to allocate memory for | |
| the new collection entry. The collection has | |
| not been changed. Existing | |
| ORDERED_COLLECTION_ENTRY pointers into | |
| Collection remain valid. | |
| @retval RETURN_ALREADY_STARTED A user structure has been found in the | |
| collection that compares equal to | |
| UserStruct. The entry linking the colliding | |
| user structure is reported back in Entry (if | |
| the caller requested it). The collection has | |
| not been changed. Existing | |
| ORDERED_COLLECTION_ENTRY pointers into | |
| Collection remain valid. | |
| **/ | |
| RETURN_STATUS | |
| EFIAPI | |
| OrderedCollectionInsert ( | |
| IN OUT ORDERED_COLLECTION *Collection, | |
| OUT ORDERED_COLLECTION_ENTRY **Entry OPTIONAL, | |
| IN VOID *UserStruct | |
| ); | |
| /** | |
| Delete an entry from the collection, unlinking the associated user structure. | |
| Read-write operation. | |
| @param[in,out] Collection The collection to delete Entry from. | |
| @param[in] Entry The collection entry to delete from Collection. | |
| The caller is responsible for ensuring that Entry | |
| belongs to Collection, and that Entry is non-NULL | |
| and valid. Entry is typically an earlier return | |
| value, or output parameter, of: | |
| - OrderedCollectionFind(), for deleting an entry | |
| by user structure key, | |
| - OrderedCollectionMin() / OrderedCollectionMax(), | |
| for deleting the minimum / maximum entry, | |
| - OrderedCollectionNext() / | |
| OrderedCollectionPrev(), for deleting an entry | |
| found during an iteration, | |
| - OrderedCollectionInsert() with return value | |
| RETURN_ALREADY_STARTED, for deleting an entry | |
| whose linked user structure caused collision | |
| during insertion. | |
| Existing ORDERED_COLLECTION_ENTRY pointers (ie. | |
| iterators) *different* from Entry remain valid. | |
| For example: | |
| - OrderedCollectionNext() / | |
| OrderedCollectionPrev() iterations in the caller | |
| can be continued from Entry, if | |
| OrderedCollectionNext() or | |
| OrderedCollectionPrev() is called on Entry | |
| *before* OrderedCollectionDelete() is. That is, | |
| fetch the successor / predecessor entry first, | |
| then delete Entry. | |
| - On-going iterations in the caller that would | |
| have otherwise returned Entry at some point, as | |
| dictated by user structure order, will correctly | |
| reflect the absence of Entry after | |
| OrderedCollectionDelete() is called | |
| mid-iteration. | |
| @param[out] UserStruct If the caller provides this optional output-only | |
| parameter, then on output it is set to the user | |
| structure originally linked by Entry (which is now | |
| freed). | |
| This is a convenience that may save the caller a | |
| OrderedCollectionUserStruct() invocation before | |
| calling OrderedCollectionDelete(), in order to | |
| retrieve the user structure being unlinked. | |
| **/ | |
| VOID | |
| EFIAPI | |
| OrderedCollectionDelete ( | |
| IN OUT ORDERED_COLLECTION *Collection, | |
| IN ORDERED_COLLECTION_ENTRY *Entry, | |
| OUT VOID **UserStruct OPTIONAL | |
| ); | |
| #endif |