|
|
//
// SortString.cpp
//
#include "stdafx.h"
#include "SortStr.h"
#define ISDIGIT(ch) ((UINT)((char)(ch) - '0') <= 9)
#define ROUND_UP(val, quantum) ((val) + (((quantum) - ((val) % (quantum))) % (quantum)))
extern "C" BOOL SafeRealloc(LPVOID FAR* ppv, UINT cb) { LPVOID pv2;
if (*ppv == NULL) { pv2 = malloc(cb); } else { pv2 = realloc(*ppv, cb); }
if (pv2 == NULL) { return FALSE; } else { *ppv = pv2; return TRUE; } }
extern "C" void SafeFree(LPVOID FAR* ppv) { if (*ppv) { free(*ppv); *ppv = NULL; } }
extern "C" BOOL SafeGrowArray(LPVOID FAR* ppv, UINT FAR* pArrayMax, UINT nSizeWanted, UINT nGrowBy, UINT cbElement) { // Round up to next multiple of nGrowBy
UINT newMax = ROUND_UP(nSizeWanted, nGrowBy); if (newMax > *pArrayMax) { if (!SafeRealloc(ppv, newMax * cbElement)) return FALSE; *pArrayMax = newMax; } return TRUE; }
// A custom compare routine that will put strings like "100+" after "9"
int WINAPI CompareStringsWithNumbers(LPCTSTR psz1, LPCTSTR psz2) { if (ISDIGIT(*psz1) && ISDIGIT(*psz2)) { int nVal1 = MyAtoi(psz1); int nVal2 = MyAtoi(psz2);
if (nVal1 < nVal2) return -1; else if (nVal1 > nVal2) return 1; else { while (ISDIGIT(*psz1)) psz1++; while (ISDIGIT(*psz2)) psz2++; } }
return lstrcmpi(psz1, psz2); }
CSortedStringArray::CSortedStringArray(SORTSTRING_COMPARE_PROC pfnCustomCompare /*=NULL*/) { m_prgStrings = NULL; m_cStrings = 0; m_maxStrings = 0;
if (pfnCustomCompare == NULL) pfnCustomCompare = lstrcmpi; m_pfnCompare = pfnCustomCompare; }
CSortedStringArray::~CSortedStringArray() { for (int iString = m_cStrings-1; iString >= 0; iString--) { delete [] ((LPBYTE)m_prgStrings[iString] - sizeof(DWORD)); } SafeFree((void**)&m_prgStrings); }
int CSortedStringArray::Add(LPCTSTR psz, DWORD dwData) { for (int iItem = 0; iItem < m_cStrings; iItem++) { if ((*m_pfnCompare)(psz, m_prgStrings[iItem]) < 0) break; }
if (SafeGrowArray((void**)&m_prgStrings, (UINT*)&m_maxStrings, (UINT)m_cStrings+1, 40, sizeof(LPTSTR))) { int cch = lstrlen(psz); LPTSTR pszNew = new TCHAR[ (cch+1)*sizeof(TCHAR) + sizeof(DWORD) ]; if (pszNew) { memmove(&m_prgStrings[iItem+1], &m_prgStrings[iItem], (m_cStrings - iItem) * sizeof(LPTSTR)); *((DWORD*)pszNew) = dwData; pszNew += sizeof(DWORD) / sizeof(TCHAR); lstrcpy(pszNew, psz); m_prgStrings[iItem] = pszNew;
m_cStrings++; return iItem; } }
return -1; }
SORTSTRING_COMPARE_PROC CSortedStringArray::_pfnCompare;
int __cdecl CSortedStringArray::_crtCompareHelper(const void* elem1, const void* elem2) { return _pfnCompare(*((LPCTSTR*)elem1), *((LPCTSTR*)elem2)); }
int CSortedStringArray::Find(LPCTSTR pszString) const { // REVIEW: This isn't safe if this function is called on multiple threads
_pfnCompare = m_pfnCompare; LPTSTR* pResult = (LPTSTR*)bsearch(&pszString, m_prgStrings, m_cStrings, sizeof(LPTSTR), _crtCompareHelper); if (pResult == NULL) return -1; else return (int)(pResult - m_prgStrings); }
|