#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 >::bsearch(key,ptr,count) #define TBSEARCH_SAMEVALUEUNSIGNED(TYPE,key,ptr,count) TBSEARCH >::bsearch(key,ptr,count) #define TBSEARCH_SAMEMEM(TYPE,pKey,ptr,count) TBSEARCH >::bsearch(pKey,ptr,count) #define TBSEARCH_SAMEPTR(TYPE,pKey,ptr,count) TBSEARCH >::bsearch(pKey,ptr,count) #define TBRANGE_SAMEVALUE(TYPE,key,ptr,count,bRange) TBRANGE >::GetIndexViaKey(key,ptr,count,bRange) #define TBRANGE_SAMEVALUEUNSIGNED(TYPE,key,ptr,count,bRange) TBRANGE >::GetIndexViaKey(key,ptr,count,bRange) #define TBRANGE_SAMEMEM(TYPE,pKey,ptr,count,bRange) TBRANGE >::GetIndexViaKey(pKey,ptr,count,bRange) #define TBRANGE_SAMEPTR(TYPE,pKey,ptr,count,bRange) TBRANGE >::GetIndexViaKey(pKey,ptr,count,bRange) template struct TBsearchSameDiff { static int FASTAPICALLCONVENTION Compare(KEY key, const TYPE* pb) { return key - *pb; } }; template 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 struct TBsearchSameMEM { static int FASTAPICALLCONVENTION Compare(KEY key, const TYPE* pb) { return memcmp(key, pb, sizeof(TYPE)); } }; template 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 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__)