Home | History | Annotate | Download | only in Library
      1 /** @file
      2   An ordered collection library interface.
      3 
      4   The library class provides a set of APIs to manage an ordered collection of
      5   items.
      6 
      7   Copyright (C) 2014, Red Hat, Inc.
      8 
      9   This program and the accompanying materials are licensed and made available
     10   under the terms and conditions of the BSD License that accompanies this
     11   distribution. The full text of the license may be found at
     12   http://opensource.org/licenses/bsd-license.php.
     13 
     14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
     15   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 **/
     17 
     18 #ifndef __ORDERED_COLLECTION_LIB__
     19 #define __ORDERED_COLLECTION_LIB__
     20 
     21 #include <Base.h>
     22 
     23 //
     24 // Opaque structure for a collection.
     25 //
     26 typedef struct ORDERED_COLLECTION ORDERED_COLLECTION;
     27 
     28 //
     29 // Opaque structure for collection entries.
     30 //
     31 // Collection entries do not take ownership of the associated user structures,
     32 // they only link them. This makes it easy to link the same user structure into
     33 // several collections. If reference counting is required, the caller is
     34 // responsible for implementing it, as part of the user structure.
     35 //
     36 // A pointer-to-ORDERED_COLLECTION_ENTRY is considered an "iterator". Multiple,
     37 // simultaneous iterations are supported.
     38 //
     39 typedef struct ORDERED_COLLECTION_ENTRY ORDERED_COLLECTION_ENTRY;
     40 
     41 //
     42 // Altering the key field of an in-collection user structure (ie. the portion
     43 // of the user structure that ORDERED_COLLECTION_USER_COMPARE and
     44 // ORDERED_COLLECTION_KEY_COMPARE, below, read) is not allowed in-place. The
     45 // caller is responsible for bracketing the key change with the deletion and
     46 // the reinsertion of the user structure, so that the changed key value is
     47 // reflected in the collection.
     48 //
     49 
     50 /**
     51   Comparator function type for two user structures.
     52 
     53   @param[in] UserStruct1  Pointer to the first user structure.
     54 
     55   @param[in] UserStruct2  Pointer to the second user structure.
     56 
     57   @retval <0  If UserStruct1 compares less than UserStruct2.
     58 
     59   @retval  0  If UserStruct1 compares equal to UserStruct2.
     60 
     61   @retval >0  If UserStruct1 compares greater than UserStruct2.
     62 **/
     63 typedef
     64 INTN
     65 (EFIAPI *ORDERED_COLLECTION_USER_COMPARE)(
     66   IN CONST VOID *UserStruct1,
     67   IN CONST VOID *UserStruct2
     68   );
     69 
     70 /**
     71   Compare a standalone key against a user structure containing an embedded key.
     72 
     73   @param[in] StandaloneKey  Pointer to the bare key.
     74 
     75   @param[in] UserStruct     Pointer to the user structure with the embedded
     76                             key.
     77 
     78   @retval <0  If StandaloneKey compares less than UserStruct's key.
     79 
     80   @retval  0  If StandaloneKey compares equal to UserStruct's key.
     81 
     82   @retval >0  If StandaloneKey compares greater than UserStruct's key.
     83 **/
     84 typedef
     85 INTN
     86 (EFIAPI *ORDERED_COLLECTION_KEY_COMPARE)(
     87   IN CONST VOID *StandaloneKey,
     88   IN CONST VOID *UserStruct
     89   );
     90 
     91 
     92 //
     93 // Some functions below are read-only, while others are read-write. If any
     94 // write operation is expected to run concurrently with any other operation on
     95 // the same collection, then the caller is responsible for implementing locking
     96 // for the whole collection.
     97 //
     98 
     99 /**
    100   Retrieve the user structure linked by the specified collection entry.
    101 
    102   Read-only operation.
    103 
    104   @param[in] Entry  Pointer to the collection entry whose associated user
    105                     structure we want to retrieve. The caller is responsible
    106                     for passing a non-NULL argument.
    107 
    108   @return  Pointer to user structure linked by Entry.
    109 **/
    110 VOID *
    111 EFIAPI
    112 OrderedCollectionUserStruct (
    113   IN CONST ORDERED_COLLECTION_ENTRY *Entry
    114   );
    115 
    116 
    117 /**
    118   Allocate and initialize the ORDERED_COLLECTION structure.
    119 
    120   @param[in]  UserStructCompare  This caller-provided function will be used to
    121                                  order two user structures linked into the
    122                                  collection, during the insertion procedure.
    123 
    124   @param[in]  KeyCompare         This caller-provided function will be used to
    125                                  order the standalone search key against user
    126                                  structures linked into the collection, during
    127                                  the lookup procedure.
    128 
    129   @retval NULL  If allocation failed.
    130 
    131   @return       Pointer to the allocated, initialized ORDERED_COLLECTION
    132                 structure, otherwise.
    133 **/
    134 ORDERED_COLLECTION *
    135 EFIAPI
    136 OrderedCollectionInit (
    137   IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare,
    138   IN ORDERED_COLLECTION_KEY_COMPARE  KeyCompare
    139   );
    140 
    141 
    142 /**
    143   Check whether the collection is empty (has no entries).
    144 
    145   Read-only operation.
    146 
    147   @param[in] Collection  The collection to check for emptiness.
    148 
    149   @retval TRUE   The collection is empty.
    150 
    151   @retval FALSE  The collection is not empty.
    152 **/
    153 BOOLEAN
    154 EFIAPI
    155 OrderedCollectionIsEmpty (
    156   IN CONST ORDERED_COLLECTION *Collection
    157   );
    158 
    159 
    160 /**
    161   Uninitialize and release an empty ORDERED_COLLECTION structure.
    162 
    163   Read-write operation.
    164 
    165   It is the caller's responsibility to delete all entries from the collection
    166   before calling this function.
    167 
    168   @param[in] Collection  The empty collection to uninitialize and release.
    169 **/
    170 VOID
    171 EFIAPI
    172 OrderedCollectionUninit (
    173   IN ORDERED_COLLECTION *Collection
    174   );
    175 
    176 
    177 /**
    178   Look up the collection entry that links the user structure that matches the
    179   specified standalone key.
    180 
    181   Read-only operation.
    182 
    183   @param[in] Collection     The collection to search for StandaloneKey.
    184 
    185   @param[in] StandaloneKey  The key to locate among the user structures linked
    186                             into Collection. StandaloneKey will be passed to
    187                             ORDERED_COLLECTION_KEY_COMPARE.
    188 
    189   @retval NULL  StandaloneKey could not be found.
    190 
    191   @return       The collection entry that links to the user structure matching
    192                 StandaloneKey, otherwise.
    193 **/
    194 ORDERED_COLLECTION_ENTRY *
    195 EFIAPI
    196 OrderedCollectionFind (
    197   IN CONST ORDERED_COLLECTION *Collection,
    198   IN CONST VOID               *StandaloneKey
    199   );
    200 
    201 
    202 /**
    203   Find the collection entry of the minimum user structure stored in the
    204   collection.
    205 
    206   Read-only operation.
    207 
    208   @param[in] Collection  The collection to return the minimum entry of. The
    209                          user structure linked by the minimum entry compares
    210                          less than all other user structures in the collection.
    211 
    212   @retval NULL  If Collection is empty.
    213 
    214   @return       The collection entry that links the minimum user structure,
    215                 otherwise.
    216 **/
    217 ORDERED_COLLECTION_ENTRY *
    218 EFIAPI
    219 OrderedCollectionMin (
    220   IN CONST ORDERED_COLLECTION *Collection
    221   );
    222 
    223 
    224 /**
    225   Find the collection entry of the maximum user structure stored in the
    226   collection.
    227 
    228   Read-only operation.
    229 
    230   @param[in] Collection  The collection to return the maximum entry of. The
    231                          user structure linked by the maximum entry compares
    232                          greater than all other user structures in the
    233                          collection.
    234 
    235   @retval NULL  If Collection is empty.
    236 
    237   @return       The collection entry that links the maximum user structure,
    238                 otherwise.
    239 **/
    240 ORDERED_COLLECTION_ENTRY *
    241 EFIAPI
    242 OrderedCollectionMax (
    243   IN CONST ORDERED_COLLECTION *Collection
    244   );
    245 
    246 
    247 /**
    248   Get the collection entry of the least user structure that is greater than the
    249   one linked by Entry.
    250 
    251   Read-only operation.
    252 
    253   @param[in] Entry  The entry to get the successor entry of.
    254 
    255   @retval NULL  If Entry is NULL, or Entry is the maximum entry of its
    256                 containing collection (ie. Entry has no successor entry).
    257 
    258   @return       The collection entry linking the least user structure that is
    259                 greater than the one linked by Entry, otherwise.
    260 **/
    261 ORDERED_COLLECTION_ENTRY *
    262 EFIAPI
    263 OrderedCollectionNext (
    264   IN CONST ORDERED_COLLECTION_ENTRY *Entry
    265   );
    266 
    267 
    268 /**
    269   Get the collection entry of the greatest user structure that is less than the
    270   one linked by Entry.
    271 
    272   Read-only operation.
    273 
    274   @param[in] Entry  The entry to get the predecessor entry of.
    275 
    276   @retval NULL  If Entry is NULL, or Entry is the minimum entry of its
    277                 containing collection (ie. Entry has no predecessor entry).
    278 
    279   @return       The collection entry linking the greatest user structure that
    280                 is less than the one linked by Entry, otherwise.
    281 **/
    282 ORDERED_COLLECTION_ENTRY *
    283 EFIAPI
    284 OrderedCollectionPrev (
    285   IN CONST ORDERED_COLLECTION_ENTRY *Entry
    286   );
    287 
    288 
    289 /**
    290   Insert (link) a user structure into the collection, allocating a new
    291   collection entry.
    292 
    293   Read-write operation.
    294 
    295   @param[in,out] Collection  The collection to insert UserStruct into.
    296 
    297   @param[out]    Entry       The meaning of this optional, output-only
    298                              parameter depends on the return value of the
    299                              function.
    300 
    301                              When insertion is successful (RETURN_SUCCESS),
    302                              Entry is set on output to the new collection entry
    303                              that now links UserStruct.
    304 
    305                              When insertion fails due to lack of memory
    306                              (RETURN_OUT_OF_RESOURCES), Entry is not changed.
    307 
    308                              When insertion fails due to key collision (ie.
    309                              another user structure is already in the
    310                              collection that compares equal to UserStruct),
    311                              with return value RETURN_ALREADY_STARTED, then
    312                              Entry is set on output to the entry that links the
    313                              colliding user structure. This enables
    314                              "find-or-insert" in one function call, or helps
    315                              with later removal of the colliding element.
    316 
    317   @param[in]     UserStruct  The user structure to link into the collection.
    318                              UserStruct is ordered against in-collection user
    319                              structures with the
    320                              ORDERED_COLLECTION_USER_COMPARE function.
    321 
    322   @retval RETURN_SUCCESS           Insertion successful. A new collection entry
    323                                    has been allocated, linking UserStruct. The
    324                                    new collection entry is reported back in
    325                                    Entry (if the caller requested it).
    326 
    327                                    Existing ORDERED_COLLECTION_ENTRY pointers
    328                                    into Collection remain valid. For example,
    329                                    on-going iterations in the caller can
    330                                    continue with OrderedCollectionNext() /
    331                                    OrderedCollectionPrev(), and they will
    332                                    return the new entry at some point if user
    333                                    structure order dictates it.
    334 
    335   @retval RETURN_OUT_OF_RESOURCES  The function failed to allocate memory for
    336                                    the new collection entry. The collection has
    337                                    not been changed. Existing
    338                                    ORDERED_COLLECTION_ENTRY pointers into
    339                                    Collection remain valid.
    340 
    341   @retval RETURN_ALREADY_STARTED   A user structure has been found in the
    342                                    collection that compares equal to
    343                                    UserStruct. The entry linking the colliding
    344                                    user structure is reported back in Entry (if
    345                                    the caller requested it). The collection has
    346                                    not been changed. Existing
    347                                    ORDERED_COLLECTION_ENTRY pointers into
    348                                    Collection remain valid.
    349 **/
    350 RETURN_STATUS
    351 EFIAPI
    352 OrderedCollectionInsert (
    353   IN OUT ORDERED_COLLECTION       *Collection,
    354   OUT    ORDERED_COLLECTION_ENTRY **Entry      OPTIONAL,
    355   IN     VOID                     *UserStruct
    356   );
    357 
    358 
    359 /**
    360   Delete an entry from the collection, unlinking the associated user structure.
    361 
    362   Read-write operation.
    363 
    364   @param[in,out] Collection  The collection to delete Entry from.
    365 
    366   @param[in]     Entry       The collection entry to delete from Collection.
    367                              The caller is responsible for ensuring that Entry
    368                              belongs to Collection, and that Entry is non-NULL
    369                              and valid. Entry is typically an earlier return
    370                              value, or output parameter, of:
    371 
    372                              - OrderedCollectionFind(), for deleting an entry
    373                                by user structure key,
    374 
    375                              - OrderedCollectionMin() / OrderedCollectionMax(),
    376                                for deleting the minimum / maximum entry,
    377 
    378                              - OrderedCollectionNext() /
    379                                OrderedCollectionPrev(), for deleting an entry
    380                                found during an iteration,
    381 
    382                              - OrderedCollectionInsert() with return value
    383                                RETURN_ALREADY_STARTED, for deleting an entry
    384                                whose linked user structure caused collision
    385                                during insertion.
    386 
    387                              Existing ORDERED_COLLECTION_ENTRY pointers (ie.
    388                              iterators) *different* from Entry remain valid.
    389                              For example:
    390 
    391                              - OrderedCollectionNext() /
    392                                OrderedCollectionPrev() iterations in the caller
    393                                can be continued from Entry, if
    394                                OrderedCollectionNext() or
    395                                OrderedCollectionPrev() is called on Entry
    396                                *before* OrderedCollectionDelete() is. That is,
    397                                fetch the successor / predecessor entry first,
    398                                then delete Entry.
    399 
    400                              - On-going iterations in the caller that would
    401                                have otherwise returned Entry at some point, as
    402                                dictated by user structure order, will correctly
    403                                reflect the absence of Entry after
    404                                OrderedCollectionDelete() is called
    405                                mid-iteration.
    406 
    407   @param[out]    UserStruct  If the caller provides this optional output-only
    408                              parameter, then on output it is set to the user
    409                              structure originally linked by Entry (which is now
    410                              freed).
    411 
    412                              This is a convenience that may save the caller a
    413                              OrderedCollectionUserStruct() invocation before
    414                              calling OrderedCollectionDelete(), in order to
    415                              retrieve the user structure being unlinked.
    416 **/
    417 VOID
    418 EFIAPI
    419 OrderedCollectionDelete (
    420   IN OUT ORDERED_COLLECTION       *Collection,
    421   IN     ORDERED_COLLECTION_ENTRY *Entry,
    422   OUT    VOID                     **UserStruct OPTIONAL
    423   );
    424 
    425 #endif
    426