Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.2 KiB

  1. //
  2. // SortString.cpp
  3. //
  4. #include "stdafx.h"
  5. #include "SortStr.h"
  6. #define ISDIGIT(ch) ((UINT)((char)(ch) - '0') <= 9)
  7. #define ROUND_UP(val, quantum) ((val) + (((quantum) - ((val) % (quantum))) % (quantum)))
  8. extern "C" BOOL SafeRealloc(LPVOID FAR* ppv, UINT cb)
  9. {
  10. LPVOID pv2;
  11. if (*ppv == NULL)
  12. {
  13. pv2 = malloc(cb);
  14. }
  15. else
  16. {
  17. pv2 = realloc(*ppv, cb);
  18. }
  19. if (pv2 == NULL)
  20. {
  21. return FALSE;
  22. }
  23. else
  24. {
  25. *ppv = pv2;
  26. return TRUE;
  27. }
  28. }
  29. extern "C" void SafeFree(LPVOID FAR* ppv)
  30. {
  31. if (*ppv)
  32. {
  33. free(*ppv);
  34. *ppv = NULL;
  35. }
  36. }
  37. extern "C" BOOL SafeGrowArray(LPVOID FAR* ppv, UINT FAR* pArrayMax, UINT nSizeWanted, UINT nGrowBy, UINT cbElement)
  38. {
  39. // Round up to next multiple of nGrowBy
  40. UINT newMax = ROUND_UP(nSizeWanted, nGrowBy);
  41. if (newMax > *pArrayMax)
  42. {
  43. if (!SafeRealloc(ppv, newMax * cbElement))
  44. return FALSE;
  45. *pArrayMax = newMax;
  46. }
  47. return TRUE;
  48. }
  49. // A custom compare routine that will put strings like "100+" after "9"
  50. int WINAPI CompareStringsWithNumbers(LPCTSTR psz1, LPCTSTR psz2)
  51. {
  52. if (ISDIGIT(*psz1) && ISDIGIT(*psz2))
  53. {
  54. int nVal1 = MyAtoi(psz1);
  55. int nVal2 = MyAtoi(psz2);
  56. if (nVal1 < nVal2)
  57. return -1;
  58. else if (nVal1 > nVal2)
  59. return 1;
  60. else
  61. {
  62. while (ISDIGIT(*psz1))
  63. psz1++;
  64. while (ISDIGIT(*psz2))
  65. psz2++;
  66. }
  67. }
  68. return lstrcmpi(psz1, psz2);
  69. }
  70. CSortedStringArray::CSortedStringArray(SORTSTRING_COMPARE_PROC pfnCustomCompare /*=NULL*/)
  71. {
  72. m_prgStrings = NULL;
  73. m_cStrings = 0;
  74. m_maxStrings = 0;
  75. if (pfnCustomCompare == NULL)
  76. pfnCustomCompare = lstrcmpi;
  77. m_pfnCompare = pfnCustomCompare;
  78. }
  79. CSortedStringArray::~CSortedStringArray()
  80. {
  81. for (int iString = m_cStrings-1; iString >= 0; iString--)
  82. {
  83. delete [] ((LPBYTE)m_prgStrings[iString] - sizeof(DWORD));
  84. }
  85. SafeFree((void**)&m_prgStrings);
  86. }
  87. int CSortedStringArray::Add(LPCTSTR psz, DWORD dwData)
  88. {
  89. for (int iItem = 0; iItem < m_cStrings; iItem++)
  90. {
  91. if ((*m_pfnCompare)(psz, m_prgStrings[iItem]) < 0)
  92. break;
  93. }
  94. if (SafeGrowArray((void**)&m_prgStrings, (UINT*)&m_maxStrings, (UINT)m_cStrings+1, 40, sizeof(LPTSTR)))
  95. {
  96. int cch = lstrlen(psz);
  97. LPTSTR pszNew = new TCHAR[ (cch+1)*sizeof(TCHAR) + sizeof(DWORD) ];
  98. if (pszNew)
  99. {
  100. memmove(&m_prgStrings[iItem+1], &m_prgStrings[iItem], (m_cStrings - iItem) * sizeof(LPTSTR));
  101. *((DWORD*)pszNew) = dwData;
  102. pszNew += sizeof(DWORD) / sizeof(TCHAR);
  103. lstrcpy(pszNew, psz);
  104. m_prgStrings[iItem] = pszNew;
  105. m_cStrings++;
  106. return iItem;
  107. }
  108. }
  109. return -1;
  110. }
  111. SORTSTRING_COMPARE_PROC CSortedStringArray::_pfnCompare;
  112. int __cdecl CSortedStringArray::_crtCompareHelper(const void* elem1, const void* elem2)
  113. {
  114. return _pfnCompare(*((LPCTSTR*)elem1), *((LPCTSTR*)elem2));
  115. }
  116. int CSortedStringArray::Find(LPCTSTR pszString) const
  117. {
  118. // REVIEW: This isn't safe if this function is called on multiple threads
  119. _pfnCompare = m_pfnCompare;
  120. LPTSTR* pResult = (LPTSTR*)bsearch(&pszString, m_prgStrings, m_cStrings, sizeof(LPTSTR), _crtCompareHelper);
  121. if (pResult == NULL)
  122. return -1;
  123. else
  124. return (int)(pResult - m_prgStrings);
  125. }