Files
firestorm/Gameleap/code/mw4/Code/MW4Application/bsearch.inl
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

194 lines
6.4 KiB
C++

#if !defined(__BSEARCH__)
#define __BSEARCH__
// stealed from bsearch.c
#if !defined(FASTAPICALLCONVENTION)
#if defined(_WINDOWS)
#ifdef WIN32
#define FASTAPICALLCONVENTION __fastcall
#else // !WIN32
#define FASTAPICALLCONVENTION PASCAL
#endif // WIN32
#else // !defined(_WINDOWS)
#define FASTAPICALLCONVENTION
#endif // defined(_WINDOWS)
#endif // !defined(TSORTCALL)
#define TBSEARCH_SAMEVALUE(TYPE,key,ptr,count) TBSEARCH<TYPE, TYPE, TBsearchSameDiff<TYPE,TYPE> >::bsearch(key,ptr,count)
#define TBSEARCH_SAMEVALUEUNSIGNED(TYPE,key,ptr,count) TBSEARCH<TYPE, TYPE, TBsearchSameDiffUnsigned<TYPE,TYPE> >::bsearch(key,ptr,count)
#define TBSEARCH_SAMEMEM(TYPE,pKey,ptr,count) TBSEARCH<const TYPE*, TYPE, TBsearchSameMEM<const TYPE*,TYPE> >::bsearch(pKey,ptr,count)
#define TBSEARCH_SAMEPTR(TYPE,pKey,ptr,count) TBSEARCH<const TYPE*, TYPE, TBsearchSameDiffUnsigned<const TYPE,TYPE> >::bsearch(pKey,ptr,count)
#define TBRANGE_SAMEVALUE(TYPE,key,ptr,count,bRange) TBRANGE<TYPE, TYPE, TBsearchSameDiff<TYPE,TYPE> >::GetIndexViaKey(key,ptr,count,bRange)
#define TBRANGE_SAMEVALUEUNSIGNED(TYPE,key,ptr,count,bRange) TBRANGE<TYPE, TYPE, TBsearchSameDiffUnsigned<TYPE,TYPE> >::GetIndexViaKey(key,ptr,count,bRange)
#define TBRANGE_SAMEMEM(TYPE,pKey,ptr,count,bRange) TBRANGE<const TYPE*, TYPE, TBsearchSameMEM<const TYPE*,TYPE> >::GetIndexViaKey(pKey,ptr,count,bRange)
#define TBRANGE_SAMEPTR(TYPE,pKey,ptr,count,bRange) TBRANGE<const TYPE*, TYPE, TBsearchSameDiffUnsigned<const TYPE,TYPE> >::GetIndexViaKey(pKey,ptr,count,bRange)
template <class KEY, class TYPE>
struct TBsearchSameDiff
{
static int FASTAPICALLCONVENTION Compare(KEY key, const TYPE* pb)
{
return key - *pb;
}
};
template <class KEY, class TYPE>
struct TBsearchSameDiffUnsigned
{
static int FASTAPICALLCONVENTION Compare(KEY key, const TYPE* pb)
{
TYPE tmp = *pb;
if (key != tmp) {
if (key > tmp)
return +1;
return -1;
}
return 0;
}
};
template <class KEY, class TYPE>
struct TBsearchSameMEM
{
static int FASTAPICALLCONVENTION Compare(KEY key, const TYPE* pb)
{
return memcmp(key, pb, sizeof(TYPE));
}
};
template <class KEY, class TYPE, class COMP>
struct TBSEARCH
{
public:
public:
static TYPE* FASTAPICALLCONVENTION bsearch(KEY key, const TYPE* base, size_t num)
{
/***
*TYPE *bsearch() - do a binary search on an array
*
*Purpose:
* Does a binary search of a sorted array for a key.
*
*Entry:
* const char *key - key to search for
* const char *base - base of sorted array to search
* unsigned int num - number of elements in array
*
*Exit:
* if key is found:
* returns pointer to occurrence of key in array
* if key is not found:
* returns NULL
*
*Exceptions:
*
*******************************************************************************/
BYTE *lo = (BYTE *)base;
BYTE *hi = (BYTE *)base + (num - 1) * sizeof(TYPE);
BYTE *mid;
size_t half;
int result;
while(lo <= hi) {
if ((half = num / 2) != 0) {
mid = lo + (num & 1 ? half : (half - 1)) * sizeof(TYPE);
if ((result = COMP::Compare(key, (const TYPE*)mid)) == 0)
return (TYPE*)mid;
else if (result < 0) {
hi = mid - sizeof(TYPE);
num = num & 1 ? half : half-1;
} else {
lo = mid + sizeof(TYPE);
num = half;
}
} else if (num)
return (TYPE*)(COMP::Compare(key, (const TYPE*)lo) ? NULL : lo);
else
break;
}
return NULL;
}
};
template <class KEY, class TYPE, class COMP>
struct TBRANGE
{
public:
public:
static int FASTAPICALLCONVENTION GetIndexViaKey(KEY key, const TYPE* base, int nSize, BOOL bRange = FALSE)
{
if (nSize > 0) {
int nNum = nSize;
const TYPE* pStart = &base[0];
const TYPE* pLo = pStart;
const TYPE* pHi = &pStart[nNum - 1];
const TYPE* pMd;
int nHalf;
int nIndex;
int nDiffer;
while(pLo <= pHi) {
nHalf = nNum / 2;
if (nHalf) {
int nNum2 = nNum & 1 ? nHalf : (nHalf - 1);
pMd = &pLo[nNum2];
nDiffer = COMP::Compare(key, pMd);
if (nDiffer) {
if (nDiffer > 0) {
pLo = &pMd[1];
nNum = nHalf;
} else {
nNum = nNum2;
if (!nNum) {
if (bRange) {
nIndex = pLo - pStart;
goto check_1below;
}
break;
}
pHi = &pMd[-1];
}
} else {
nIndex = pMd - pStart;
pLo = pMd;
goto check_before;
}
} else {
ASSERT(nNum == 1);
nDiffer = COMP::Compare(key, pLo);
nIndex = pLo - pStart;
if (bRange) {
if (nDiffer < 0) {
check_1below:
if (0 < nIndex) {
pLo--;
if (COMP::Compare(key, pLo) >= 0) {
ASSERT(COMP::Compare(key, pLo) != 0);
nIndex--;
goto check_before;
}
}
break;
}
} else {
if (nDiffer != 0)
break;
}
check_before:
return nIndex;
}
}
}
return -1;
}
};
#endif // !defined(__BSEARCH__)