mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 12:53:33 +00:00
130 lines
4.1 KiB
C
130 lines
4.1 KiB
C
/*
|
|
* PROJECT: ReactOS Console Configuration DLL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/cpl/console/utils.c
|
|
* PURPOSE: Utility functions
|
|
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
|
*/
|
|
|
|
#include "console.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
/*
|
|
* A function that locates the insertion point (index) for a given value 'Value'
|
|
* in a list 'List' to maintain its sorted order by increasing values.
|
|
*
|
|
* - When 'BisectRightOrLeft' == TRUE, the bisection is performed to the right,
|
|
* i.e. the returned insertion point comes after (to the right of) any existing
|
|
* entries of 'Value' in 'List'.
|
|
* The returned insertion point 'i' partitions the list 'List' into two halves
|
|
* such that:
|
|
* all(val <= Value for val in List[start:i[) for the left side, and
|
|
* all(val > Value for val in List[i:end+1[) for the right side.
|
|
*
|
|
* - When 'BisectRightOrLeft' == FALSE, the bisection is performed to the left,
|
|
* i.e. the returned insertion point comes before (to the left of) any existing
|
|
* entries of 'Value' in 'List'.
|
|
* The returned insertion point 'i' partitions the list 'List' into two halves
|
|
* such that:
|
|
* all(val < Value for val in List[start:i[) for the left side, and
|
|
* all(val >= Value for val in List[i:end+1[) for the right side.
|
|
*
|
|
* The exact value of List[i] may, or may not, be equal to Value, depending on
|
|
* whether or not 'Value' is actually present on the list.
|
|
*/
|
|
UINT
|
|
BisectListSortedByValueEx(
|
|
IN PLIST_CTL ListCtl,
|
|
IN ULONG_PTR Value,
|
|
IN UINT itemStart,
|
|
IN UINT itemEnd,
|
|
OUT PUINT pValueItem OPTIONAL,
|
|
IN BOOL BisectRightOrLeft)
|
|
{
|
|
UINT iItemStart, iItemEnd, iItem;
|
|
ULONG_PTR itemData;
|
|
|
|
/* Sanity checks */
|
|
if (itemStart > itemEnd)
|
|
return CB_ERR; // Fail
|
|
|
|
/* Initialize */
|
|
iItemStart = itemStart;
|
|
iItemEnd = itemEnd;
|
|
iItem = iItemStart;
|
|
|
|
if (pValueItem)
|
|
*pValueItem = CB_ERR;
|
|
|
|
while (iItemStart <= iItemEnd)
|
|
{
|
|
/*
|
|
* Bisect. Note the following:
|
|
* - if iItemEnd == iItemStart + 1, then iItem == iItemStart;
|
|
* - if iItemStart == iItemEnd, then iItemStart == iItem == iItemEnd.
|
|
* In all but the last case, iItemStart <= iItem < iItemEnd.
|
|
*/
|
|
iItem = (iItemStart + iItemEnd) / 2;
|
|
|
|
itemData = ListCtl->GetData(ListCtl, iItem);
|
|
if (itemData == CB_ERR)
|
|
return CB_ERR; // Fail
|
|
|
|
if (Value == itemData)
|
|
{
|
|
/* Found a candidate */
|
|
if (pValueItem)
|
|
*pValueItem = iItem;
|
|
|
|
/*
|
|
* Try to find the last element (if BisectRightOrLeft == TRUE)
|
|
* or the first element (if BisectRightOrLeft == FALSE).
|
|
*/
|
|
if (BisectRightOrLeft)
|
|
{
|
|
iItemStart = iItem + 1; // iItemStart may be > iItemEnd
|
|
}
|
|
else
|
|
{
|
|
if (iItem <= itemStart) break;
|
|
iItemEnd = iItem - 1; // iItemEnd may be < iItemStart, i.e. iItemStart may be > iItemEnd
|
|
}
|
|
}
|
|
else if (Value < itemData)
|
|
{
|
|
if (iItem <= itemStart) break;
|
|
/* The value should be before iItem */
|
|
iItemEnd = iItem - 1; // iItemEnd may be < iItemStart, i.e. iItemStart may be > iItemEnd, if iItem == iItemStart.
|
|
}
|
|
else // if (itemData < Value)
|
|
{
|
|
/* The value should be after iItem */
|
|
iItemStart = iItem + 1; // iItemStart may be > iItemEnd, if iItem == iItemEnd.
|
|
}
|
|
|
|
/* Here, iItemStart may be == iItemEnd */
|
|
}
|
|
|
|
return iItemStart;
|
|
}
|
|
|
|
UINT
|
|
BisectListSortedByValue(
|
|
IN PLIST_CTL ListCtl,
|
|
IN ULONG_PTR Value,
|
|
OUT PUINT pValueItem OPTIONAL,
|
|
IN BOOL BisectRightOrLeft)
|
|
{
|
|
INT iItemEnd = ListCtl->GetCount(ListCtl);
|
|
if (iItemEnd == CB_ERR || iItemEnd <= 0)
|
|
return CB_ERR; // Fail
|
|
|
|
return BisectListSortedByValueEx(ListCtl, Value,
|
|
0, (UINT)(iItemEnd - 1),
|
|
pValueItem,
|
|
BisectRightOrLeft);
|
|
}
|