Skip to content

Commit

Permalink
ShellPkg/ShellCommandLib: add ShellSortFileList()
Browse files Browse the repository at this point in the history
Introduce the ShellSortFileList() function, for sorting an
EFI_SHELL_FILE_INFO list, by FileName or by FullName.

Duplicates can be kept in the same list, or separated out to a new list.
In either case, the relative order between duplicates does not change (the
sorting is stable).

For the sorting, use OrderedCollectionLib rather than SortLib:

- The PerformQuickSort() function from the latter has quadratic worst-case
  time complexity, plus it is implemented recursively (see
  "MdeModulePkg/Library/UefiSortLib/UefiSortLib.c"). It can also not
  return an error on memory allocation failure.

- In comparison, the Red-Black Tree instance of OrderedCollectionLib sorts
  in O(n*log(n)) worst-case time, contains no recursion with the default
  PcdValidateOrderedCollection=FALSE setting, and the OrderedCollectionLib
  class APIs return errors appropriately.

The OrderedCollectionLib APIs do not permit duplicates natively, but by
using lists as collection entries, stable sorting of duplicates can be
achieved.

Cc: Philippe Mathieu-Daudé <[email protected]>
Cc: Ray Ni <[email protected]>
Cc: Zhichao Gao <[email protected]>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3151
Signed-off-by: Laszlo Ersek <[email protected]>
Reviewed-by: Zhichao Gao <[email protected]>
Message-Id: <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
  • Loading branch information
lersek authored and mergify[bot] committed Jan 19, 2021
1 parent ef03e72 commit 101c55a
Show file tree
Hide file tree
Showing 5 changed files with 414 additions and 0 deletions.
81 changes: 81 additions & 0 deletions ShellPkg/Include/Library/ShellCommandLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,4 +714,85 @@ CatSDumpHex (
IN UINTN DataSize,
IN VOID *UserData
);

//
// Determines the ordering operation for ShellSortFileList().
//
typedef enum {
//
// Sort the EFI_SHELL_FILE_INFO objects by the FileName field, in increasing
// order, using gUnicodeCollation->StriColl().
//
ShellSortFileListByFileName,
//
// Sort the EFI_SHELL_FILE_INFO objects by the FullName field, in increasing
// order, using gUnicodeCollation->StriColl().
//
ShellSortFileListByFullName,
ShellSortFileListMax
} SHELL_SORT_FILE_LIST;

/**
Sort an EFI_SHELL_FILE_INFO list, optionally moving duplicates to a separate
list.
@param[in,out] FileList The list of EFI_SHELL_FILE_INFO objects to sort.
If FileList is NULL on input, then FileList is
considered an empty, hence already sorted, list.
Otherwise, if (*FileList) is NULL on input, then
EFI_INVALID_PARAMETER is returned.
Otherwise, the caller is responsible for having
initialized (*FileList)->Link with
InitializeListHead(). No other fields in the
(**FileList) head element are accessed by this
function.
On output, (*FileList) is sorted according to Order.
If Duplicates is NULL on input, then duplicate
elements are preserved, sorted stably, on
(*FileList). If Duplicates is not NULL on input,
then duplicates are moved (stably sorted) to the
new, dynamically allocated (*Duplicates) list.
@param[out] Duplicates If Duplicates is NULL on input, (*FileList) will be
a monotonically ordered list on output, with
duplicates stably sorted.
If Duplicates is not NULL on input, (*FileList) will
be a strictly monotonically oredered list on output,
with duplicates separated (stably sorted) to
(*Duplicates). All fields except Link will be
zero-initialized in the (**Duplicates) head element.
If no duplicates exist, then (*Duplicates) is set to
NULL on output.
@param[in] Order Determines the comparison operation between
EFI_SHELL_FILE_INFO objects.
@retval EFI_INVALID_PARAMETER (UINTN)Order is greater than or equal to
(UINTN)ShellSortFileListMax. Neither the
(*FileList) nor the (*Duplicates) list has
been modified.
@retval EFI_INVALID_PARAMETER (*FileList) was NULL on input. Neither the
(*FileList) nor the (*Duplicates) list has
been modified.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed. Neither the
(*FileList) nor the (*Duplicates) list has
been modified.
@retval EFI_SUCCESS Sorting successful, including the case when
FileList is NULL on input.
**/
EFI_STATUS
EFIAPI
ShellSortFileList (
IN OUT EFI_SHELL_FILE_INFO **FileList,
OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
IN SHELL_SORT_FILE_LIST Order
);
#endif //_SHELL_COMMAND_LIB_
Loading

0 comments on commit 101c55a

Please sign in to comment.