You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
15 KiB
426 lines
15 KiB
4 years ago
|
/** @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.
|
||
|
|
||
|
This program and the accompanying materials are licensed and made available
|
||
|
under the terms and conditions of the BSD License that accompanies this
|
||
|
distribution. The full text of the license may be found at
|
||
|
http://opensource.org/licenses/bsd-license.php.
|
||
|
|
||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
|
||
|
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||
|
**/
|
||
|
|
||
|
#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
|