196 lines
3.7 KiB
C
196 lines
3.7 KiB
C
|
#include "stdafx.h"
|
||
|
|
||
|
#define STRSAFE_NO_DEPRECATE
|
||
|
#include <Strsafe.h>
|
||
|
|
||
|
#define CurAlloc Reserved[0]
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
MultiString_Init(MultiString *ms,
|
||
|
DWORD dwInitLen)
|
||
|
{
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
|
||
|
if (!ms) {
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (dwInitLen) {
|
||
|
ms->CurAlloc = dwInitLen;
|
||
|
ms->Values = HeapAlloc(hHeap,
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
sizeof(LPTSTR) * dwInitLen);
|
||
|
if (!ms->Values) return FALSE;
|
||
|
ms->Count = 0;
|
||
|
} else {
|
||
|
// Otherwise, this amounts to a zero-out
|
||
|
ZeroMemory(ms, sizeof(MultiString));
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
__inline static LPTSTR
|
||
|
CreateStrCopy(LPCTSTR szStr)
|
||
|
{
|
||
|
HRESULT hrRes;
|
||
|
LPTSTR szNewCopy;
|
||
|
// dwLen needs to include the NULL terminator
|
||
|
size_t dwLen = _tcslen(szStr) + 1;
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
|
||
|
// Allocate the new string
|
||
|
szNewCopy = HeapAlloc(hHeap,
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
sizeof(TCHAR) * dwLen);
|
||
|
if (!szNewCopy) return NULL;
|
||
|
|
||
|
// Copy the actual data over
|
||
|
hrRes = StringCchCopy(szNewCopy,
|
||
|
dwLen,
|
||
|
szStr);
|
||
|
if (FAILED(hrRes)) {
|
||
|
HeapFree(hHeap, 0, szNewCopy);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return szNewCopy;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MultiString_Append(MultiString *ms,
|
||
|
LPCTSTR szNew)
|
||
|
{
|
||
|
LPTSTR szNewCopy = NULL;
|
||
|
DWORD dwNewLen;
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
|
||
|
if (!ms || !szNew) {
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwNewLen = (DWORD)_tcslen(szNew) + 1;
|
||
|
|
||
|
// Do we need to allocate more room for pointers?
|
||
|
if (ms->Values == NULL) {
|
||
|
// Oops, we have nothing! Let's allocate a couple
|
||
|
if (!MultiString_Init(ms, 3)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else if (ms->CurAlloc == ms->Count) {
|
||
|
DWORD dwNewAlloc = ms->CurAlloc + 3;
|
||
|
LPTSTR *pszNew = HeapReAlloc(hHeap,
|
||
|
0,
|
||
|
ms->Values,
|
||
|
sizeof(LPTSTR) * dwNewAlloc);
|
||
|
if (!pszNew) {
|
||
|
// ReAlloc failed :<
|
||
|
return FALSE;
|
||
|
}
|
||
|
ms->CurAlloc = dwNewAlloc;
|
||
|
ms->Values = pszNew;
|
||
|
}
|
||
|
|
||
|
szNewCopy = CreateStrCopy(szNew);
|
||
|
if (!szNewCopy) return FALSE;
|
||
|
|
||
|
// All set, append to the end and increment Count
|
||
|
ms->Values[ms->Count++] = szNewCopy;
|
||
|
ms->TotalLength += dwNewLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MultiString_Remove(MultiString *ms,
|
||
|
DWORD dwIdx)
|
||
|
{
|
||
|
DWORD dwLen = 0;
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
|
||
|
if (!ms) return FALSE;
|
||
|
|
||
|
if (dwIdx >= ms->Count) {
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
return FALSE;
|
||
|
} else if (ms->Values[dwIdx] != NULL) {
|
||
|
dwLen = (DWORD)_tcslen(ms->Values[dwIdx]) + 1;
|
||
|
|
||
|
HeapFree(hHeap, 0, ms->Values[dwIdx]);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Shift down the remaining strings
|
||
|
if (dwIdx < ms->Count - 1) {
|
||
|
size_t i;
|
||
|
for (i = dwIdx; i < ms->Count - 1; i++) {
|
||
|
ms->Values[i] = ms->Values[i + 1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ms->Count--;
|
||
|
ms->TotalLength -= dwLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MultiString_Replace(MultiString *ms,
|
||
|
DWORD dwIdx,
|
||
|
LPCTSTR szNew)
|
||
|
{
|
||
|
DWORD dwOldLen = 0,
|
||
|
dwNewLen = 0;
|
||
|
LPTSTR szTmp;
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
|
||
|
if (!ms || !szNew) return FALSE;
|
||
|
|
||
|
if (dwIdx >= ms->Count) {
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwNewLen = (DWORD)_tcslen(szNew) + 1;
|
||
|
|
||
|
// Create the copied new string
|
||
|
szTmp = CreateStrCopy(szNew);
|
||
|
if (!szTmp) return FALSE;
|
||
|
|
||
|
// Perform the switcheroo
|
||
|
if (ms->Values[dwIdx] != NULL) {
|
||
|
dwOldLen = (DWORD)_tcslen(ms->Values[dwIdx]) + 1;
|
||
|
|
||
|
HeapFree(hHeap, 0, ms->Values[dwIdx]);
|
||
|
}
|
||
|
|
||
|
ms->Values[dwIdx] = szTmp;
|
||
|
ms->TotalLength = ms->TotalLength + dwNewLen - dwOldLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
MultiString_Dispose(MultiString *ms)
|
||
|
{
|
||
|
HANDLE hHeap = GetProcessHeap();
|
||
|
DWORD i;
|
||
|
|
||
|
if (!ms) return;
|
||
|
|
||
|
if (ms->Values != NULL) {
|
||
|
for (i = 0; i < ms->Count; i++) {
|
||
|
HeapFree(hHeap, 0, ms->Values[i]);
|
||
|
}
|
||
|
|
||
|
HeapFree(hHeap, 0, ms->Values);
|
||
|
ms->Values = NULL;
|
||
|
}
|
||
|
ms->Count = 0;
|
||
|
ms->CurAlloc = 0;
|
||
|
|
||
|
return;
|
||
|
}
|