Windows2003-3790/shell/ext/hnw/shared/sortstr.cpp
2020-09-30 16:53:55 +02:00

147 lines
3.2 KiB
C++

//
// 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);
}