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.
194 lines
6.4 KiB
C++
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__)
|