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.
521 lines
13 KiB
521 lines
13 KiB
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Filename : VarStr.h
|
|
// Purpose : To hold definition for CVarString
|
|
//
|
|
// Project : Persistent Query
|
|
// Component: Common
|
|
//
|
|
// Author : urib
|
|
//
|
|
// Log:
|
|
// Feb 2 1997 urib Creation
|
|
// Jun 19 1997 urib Add counted operators.
|
|
// Jun 24 1997 urib Fix bad const declarations.
|
|
// Dec 29 1997 urib Add includes.
|
|
// Feb 2 1999 yairh fix bug in SetMinimalSize.
|
|
// Feb 8 1999 urib Enable different built in sizes.
|
|
// Feb 25 1999 urib Add SizedStringCopy.
|
|
// Jul 5 1999 urib Fix SizedStringCopy..
|
|
// May 1 2000 urib Cleanup.
|
|
// Nov 23 2000 urib Fix a bug in counted copy and cat.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef VARSTR_H
|
|
#define VARSTR_H
|
|
|
|
#pragma once
|
|
|
|
#include "AutoPtr.h"
|
|
#include "Excption.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CVarString class definition
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <ULONG ulStackSize = 0x10>
|
|
class TVarString
|
|
{
|
|
public:
|
|
// Constructor - tips the implementation on the string size.
|
|
TVarString(ULONG ulInitialSize = 0);
|
|
// Constructor - copy this string.
|
|
TVarString(PCWSTR);
|
|
// Constructor - convert to UNICODE and copy this string.
|
|
TVarString(const PSZ);
|
|
// Copy Constructor
|
|
TVarString(const TVarString&);
|
|
~TVarString();
|
|
|
|
// Copy/Convert and copy the string.
|
|
TVarString& Cpy(PCWSTR);
|
|
TVarString& Cpy(const ULONG, PCWSTR);
|
|
TVarString& Cpy(const PSZ);
|
|
|
|
// Concatenate/Convert and concatenate the string to the existing string.
|
|
TVarString& Cat(PCWSTR);
|
|
TVarString& Cat(const ULONG, PCWSTR);
|
|
TVarString& Cat(const PSZ);
|
|
|
|
// Compare/Convert and compare the string to the existing string.
|
|
int Cmp(PCWSTR) const;
|
|
int Cmp(const PSZ) const;
|
|
|
|
// Return the string length.
|
|
ULONG Len() const;
|
|
|
|
// Allow access to the string memory.
|
|
operator PWSTR() const;
|
|
|
|
// Hint the implementation about the string size.
|
|
void SetMinimalSize(ULONG);
|
|
|
|
// Set a specific character
|
|
void SetCharacter(ULONG, WCHAR);
|
|
|
|
// Appends a backslash to the string if the last character is not a
|
|
// backslash.
|
|
void AppendBackslash();
|
|
|
|
// Appends a slash to the string if the last character is not a
|
|
// slash.
|
|
void AppendSlash();
|
|
|
|
protected:
|
|
// A predicate to see if memory is allocated or not.
|
|
bool IsAllocated();
|
|
|
|
// The allocation size
|
|
ULONG m_ulSize;
|
|
|
|
// This is the place for the standard string.
|
|
WCHAR m_rwchNormalString[ulStackSize + 1];
|
|
|
|
// If the string is becoming too big we will allocate space for it.
|
|
WCHAR* m_pTheString;
|
|
private:
|
|
TVarString&
|
|
operator=(const TVarString& vsOther)
|
|
{
|
|
Cpy(vsOther);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::TVarString(ULONG ulInitialSize)
|
|
:m_pTheString(m_rwchNormalString)
|
|
,m_ulSize(ulStackSize)
|
|
{
|
|
SetMinimalSize(ulInitialSize);
|
|
|
|
m_pTheString[0] = L'\0';
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::TVarString(PCWSTR pwsz)
|
|
:m_pTheString(m_rwchNormalString)
|
|
,m_ulSize(ulStackSize)
|
|
{
|
|
Cpy(pwsz);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::TVarString(const PSZ psz)
|
|
:m_pTheString(m_rwchNormalString)
|
|
,m_ulSize(ulStackSize)
|
|
{
|
|
Cpy(psz);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::TVarString(const TVarString<ulStackSize>& vsOther)
|
|
:m_pTheString(m_rwchNormalString)
|
|
,m_ulSize(ulStackSize)
|
|
{
|
|
Cpy(vsOther);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::~TVarString()
|
|
{
|
|
if (IsAllocated())
|
|
{
|
|
free(m_pTheString);
|
|
}
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
bool
|
|
TVarString<ulStackSize>::IsAllocated()
|
|
{
|
|
return m_pTheString != m_rwchNormalString;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
void
|
|
TVarString<ulStackSize>::SetMinimalSize(ULONG ulNewSize)
|
|
{
|
|
// We allocate a little more so if someone would like to add a slash
|
|
// or something, it will not cause us to realocate.
|
|
// On debug builds, I want to check for string overflows so I don't
|
|
// want the extra memory. Activating the reallocation mechanism is also'
|
|
// a good thing in debug builds.
|
|
#if !(defined(DEBUG))
|
|
ulNewSize++;
|
|
#endif
|
|
|
|
//
|
|
// if the new size is smaller then what we have - bye bye
|
|
//
|
|
if (ulNewSize > m_ulSize)
|
|
{
|
|
//
|
|
// We already allocated a string. Should change it's size
|
|
//
|
|
if (IsAllocated())
|
|
{
|
|
PWSTR pwszTemp = (PWSTR) realloc(
|
|
m_pTheString,
|
|
(ulNewSize + 1) * sizeof(WCHAR));
|
|
|
|
if (NULL == pwszTemp)
|
|
{
|
|
THROW_MEMORY_EXCEPTION();
|
|
}
|
|
|
|
//
|
|
// Save the new memory block.
|
|
//
|
|
m_pTheString = pwszTemp;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We move the string from the buffer to the allocation.
|
|
// Note that this is dangerous if someone took the buffer address.
|
|
// The user must always use the access method and never cache the
|
|
// string pointer.
|
|
//
|
|
m_pTheString = (PWSTR) malloc(sizeof(WCHAR) * (ulNewSize + 1));
|
|
if (NULL == m_pTheString)
|
|
{
|
|
THROW_MEMORY_EXCEPTION();
|
|
}
|
|
|
|
wcsncpy(m_pTheString, m_rwchNormalString, m_ulSize + 1);
|
|
}
|
|
|
|
m_ulSize = ulNewSize;
|
|
}
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cpy(PCWSTR pwsz)
|
|
{
|
|
return Cpy(wcslen(pwsz), pwsz);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cpy(const ULONG ulCount, PCWSTR pwsz)
|
|
{
|
|
SetMinimalSize(ulCount + 1);
|
|
|
|
wcsncpy(m_pTheString, pwsz, ulCount);
|
|
|
|
m_pTheString[ulCount] = L'\0';
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cpy(const PSZ psz)
|
|
{
|
|
int iLen;
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
SetMinimalSize(iLen);
|
|
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
m_pTheString,
|
|
iLen);
|
|
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cat(PCWSTR pwsz)
|
|
{
|
|
ULONG ulLength = wcslen(pwsz);
|
|
|
|
return Cat(ulLength, pwsz);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cat(const ULONG ulLength, PCWSTR pwsz)
|
|
{
|
|
ULONG ulCurrentLength = Len();
|
|
|
|
SetMinimalSize(ulCurrentLength + ulLength + 1);
|
|
|
|
wcsncpy(m_pTheString + ulCurrentLength, pwsz, ulLength);
|
|
|
|
m_pTheString[ulCurrentLength + ulLength] = L'\0';
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>&
|
|
TVarString<ulStackSize>::Cat(const PSZ psz)
|
|
{
|
|
ULONG ulCurrentLength = Len();
|
|
|
|
int iLen;
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
SetMinimalSize(iLen + ulCurrentLength);
|
|
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
m_pTheString + ulCurrentLength,
|
|
iLen);
|
|
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
int
|
|
TVarString<ulStackSize>::Cmp(PCWSTR pwsz) const
|
|
{
|
|
return wcscmp(m_pTheString, pwsz);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
int
|
|
TVarString<ulStackSize>::Cmp(const PSZ psz) const
|
|
{
|
|
int iLen;
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
CAutoMallocPointer<WCHAR> apBuffer = (PWSTR) malloc((iLen) * sizeof(WCHAR));
|
|
|
|
iLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
|
|
psz,
|
|
-1,
|
|
apBuffer.Get(),
|
|
iLen);
|
|
|
|
if (0 == iLen)
|
|
{
|
|
Assert(0 == iLen);
|
|
THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
|
|
return Cmp(apBuffer.Get());
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
ULONG
|
|
TVarString<ulStackSize>::Len() const
|
|
{
|
|
return wcslen(m_pTheString);
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
TVarString<ulStackSize>::operator PWSTR() const
|
|
{
|
|
return m_pTheString;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
void
|
|
TVarString<ulStackSize>::SetCharacter(ULONG ulIndex, WCHAR wch)
|
|
{
|
|
SetMinimalSize(ulIndex + 2); // index to size + null
|
|
|
|
if (L'\0' == m_pTheString[ulIndex])
|
|
{
|
|
m_pTheString[ulIndex + 1] = L'\0';
|
|
}
|
|
else if (L'\0' == wch)
|
|
{
|
|
}
|
|
|
|
m_pTheString[ulIndex] = wch;
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
void
|
|
TVarString<ulStackSize>::AppendSlash()
|
|
{
|
|
if (L'/' != m_pTheString[Len() - 1])
|
|
Cat(L"/");
|
|
}
|
|
|
|
template <ULONG ulStackSize>
|
|
inline
|
|
void
|
|
TVarString<ulStackSize>::AppendBackslash()
|
|
{
|
|
if (L'\\' != m_pTheString[Len() - 1])
|
|
Cat(L"\\");
|
|
}
|
|
|
|
typedef TVarString<4> CShortVarString;
|
|
typedef TVarString<16> CVarString;
|
|
typedef TVarString<256> CLongVarString;
|
|
typedef TVarString<1024> CHugeVarString;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// String related utilities definition
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Name : ::SizedStringCopy
|
|
// Purpose : This function copies ulSize wide characters from the source
|
|
// to the destination. It does not treat '\0' characters as
|
|
// end of string and does not append the end of string mark
|
|
// to the destination. Intended to be used instead of memcpy
|
|
// when copying wide string characters.
|
|
//
|
|
// Parameters:
|
|
// [in] PWSTR pwszTarget
|
|
// [in] PCWSTR pwszSource
|
|
// [in] ULONG ulSize
|
|
//
|
|
// Returns : PWSTR
|
|
//
|
|
// Log:
|
|
// Jan 2 2001 urib Creation
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
inline
|
|
PWSTR
|
|
SizedStringCopy(PWSTR pwszTarget, PCWSTR pwszSource, ULONG ulSize)
|
|
{
|
|
return (PWSTR) memcpy(
|
|
(void*)pwszTarget,
|
|
(void*)pwszSource,
|
|
ulSize * sizeof(pwszSource[0]));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Name : ::CoTaskDuplicateString
|
|
// Purpose : strdup. Throwing though.
|
|
//
|
|
// Parameters:
|
|
// [in] PCWSTR pwsz
|
|
//
|
|
// Returns : PWSTR
|
|
//
|
|
// Log:
|
|
// Dec 25 2000 urib Creation
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
inline
|
|
PWSTR CoTaskDuplicateString(PCWSTR pwsz)
|
|
{
|
|
CAutoTaskPointer<WCHAR> apTempName =
|
|
(PWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (1 + wcslen(pwsz)));
|
|
|
|
if (!apTempName.IsValid())
|
|
{
|
|
THROW_MEMORY_EXCEPTION();
|
|
}
|
|
|
|
wcscpy(apTempName.Get(), pwsz);
|
|
|
|
return apTempName.Detach();
|
|
}
|
|
|
|
#endif /* VARSTR_H */
|