mirror of
https://github.com/reactos/reactos.git
synced 2024-08-01 00:58:16 +00:00
[ATL]
- Add support for CAtlString and all its supporting base classes. - It doesn't do much more than assign wchat_t arrarys and call LoadString, but it's a full base to start adding more methods as people decide to. svn path=/trunk/; revision=69332
This commit is contained in:
parent
c43914c6a7
commit
d3519a4284
|
@ -204,8 +204,99 @@ public:
|
||||||
{
|
{
|
||||||
return m_hInstResource;
|
return m_hInstResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HINSTANCE SetResourceInstance(HINSTANCE hInst)
|
||||||
|
{
|
||||||
|
return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst));
|
||||||
|
}
|
||||||
|
|
||||||
|
HINSTANCE GetHInstanceAt(int i);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CAtlBaseModule _AtlBaseModule;
|
extern CAtlBaseModule _AtlBaseModule;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
// String Resource helper functions
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4200)
|
||||||
|
struct ATLSTRINGRESOURCEIMAGE
|
||||||
|
{
|
||||||
|
WORD nLength;
|
||||||
|
WCHAR achString[];
|
||||||
|
};
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage(
|
||||||
|
_In_ HINSTANCE hInstance,
|
||||||
|
_In_ HRSRC hResource,
|
||||||
|
_In_ UINT id)
|
||||||
|
{
|
||||||
|
const ATLSTRINGRESOURCEIMAGE* pImage;
|
||||||
|
const ATLSTRINGRESOURCEIMAGE* pImageEnd;
|
||||||
|
ULONG nResourceSize;
|
||||||
|
HGLOBAL hGlobal;
|
||||||
|
UINT iIndex;
|
||||||
|
|
||||||
|
hGlobal = ::LoadResource(hInstance, hResource);
|
||||||
|
if (hGlobal == NULL) return NULL;
|
||||||
|
|
||||||
|
pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource(hGlobal);
|
||||||
|
if (pImage == NULL) return NULL;
|
||||||
|
|
||||||
|
nResourceSize = ::SizeofResource(hInstance, hResource);
|
||||||
|
pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + nResourceSize);
|
||||||
|
iIndex = id & 0x000f;
|
||||||
|
|
||||||
|
while ((iIndex > 0) && (pImage < pImageEnd))
|
||||||
|
{
|
||||||
|
pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + (sizeof(ATLSTRINGRESOURCEIMAGE) + (pImage->nLength * sizeof(WCHAR))));
|
||||||
|
iIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pImage >= pImageEnd) return NULL;
|
||||||
|
if (pImage->nLength == 0) return NULL;
|
||||||
|
|
||||||
|
return pImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage(
|
||||||
|
_In_ HINSTANCE hInstance,
|
||||||
|
_In_ UINT id) throw()
|
||||||
|
{
|
||||||
|
HRSRC hResource;
|
||||||
|
hResource = ::FindResourceW(hInstance, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast<WORD>(~0))), (LPWSTR)RT_STRING);
|
||||||
|
if (hResource == NULL) return NULL;
|
||||||
|
return _AtlGetStringResourceImage(hInstance, hResource, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage(
|
||||||
|
_In_ HINSTANCE hInstance,
|
||||||
|
_In_ UINT id,
|
||||||
|
_In_ WORD wLanguage)
|
||||||
|
{
|
||||||
|
HRSRC hResource;
|
||||||
|
hResource = ::FindResourceExW(hInstance, (LPWSTR)RT_STRING, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast<WORD>(~0))), wLanguage);
|
||||||
|
if (hResource == NULL) return NULL;
|
||||||
|
return _AtlGetStringResourceImage(hInstance, hResource, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline HINSTANCE AtlFindStringResourceInstance(
|
||||||
|
UINT nID,
|
||||||
|
WORD wLanguage = 0)
|
||||||
|
{
|
||||||
|
const ATLSTRINGRESOURCEIMAGE* strRes = NULL;
|
||||||
|
HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0);
|
||||||
|
|
||||||
|
for (int i = 1; hInst != NULL && strRes == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++))
|
||||||
|
{
|
||||||
|
strRes = AtlGetStringResourceImage(hInst, nID, wLanguage);
|
||||||
|
if (strRes != NULL) return hInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace ATL
|
}; // namespace ATL
|
||||||
|
|
|
@ -8,125 +8,388 @@
|
||||||
|
|
||||||
namespace ATL
|
namespace ATL
|
||||||
{
|
{
|
||||||
struct CStringData;
|
struct CStringData;
|
||||||
|
|
||||||
__interface IAtlStringMgr
|
__interface IAtlStringMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
_Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
|
||||||
|
CStringData* Allocate(
|
||||||
|
_In_ int nAllocLength,
|
||||||
|
_In_ int nCharSize
|
||||||
|
);
|
||||||
|
|
||||||
|
void Free(
|
||||||
|
_Inout_ CStringData* pData
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
|
||||||
|
CStringData* Reallocate(
|
||||||
|
_Inout_ CStringData* pData,
|
||||||
|
_In_ int nAllocLength,
|
||||||
|
_In_ int nCharSize
|
||||||
|
);
|
||||||
|
|
||||||
|
CStringData* GetNilString(void);
|
||||||
|
IAtlStringMgr* Clone(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CStringData
|
||||||
|
{
|
||||||
|
IAtlStringMgr* pStringMgr;
|
||||||
|
int nAllocLength;
|
||||||
|
int nDataLength;
|
||||||
|
long nRefs;
|
||||||
|
|
||||||
|
void* data() throw()
|
||||||
{
|
{
|
||||||
public:
|
return (this + 1);
|
||||||
|
}
|
||||||
|
|
||||||
_Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
|
void AddRef() throw()
|
||||||
CStringData* Allocate(
|
|
||||||
_In_ int nAllocLength,
|
|
||||||
_In_ int nCharSize) throw();
|
|
||||||
|
|
||||||
void Free(_Inout_ CStringData* pData) throw();
|
|
||||||
|
|
||||||
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
|
|
||||||
CStringData* Reallocate(
|
|
||||||
_Inout_ CStringData* pData,
|
|
||||||
_In_ int nAllocLength,
|
|
||||||
_In_ int nCharSize) throw();
|
|
||||||
|
|
||||||
CStringData* GetNilString() throw();
|
|
||||||
|
|
||||||
IAtlStringMgr* Clone() throw();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CStringData
|
|
||||||
{
|
{
|
||||||
IAtlStringMgr* pStringMgr;
|
ATLASSERT(nRefs > 0);
|
||||||
int nDataLength;
|
_InterlockedIncrement(&nRefs);
|
||||||
int nAllocLength;
|
}
|
||||||
long nRefs;
|
|
||||||
|
|
||||||
void* data() throw()
|
void Release() throw()
|
||||||
|
{
|
||||||
|
ATLASSERT(nRefs != 0);
|
||||||
|
|
||||||
|
if (_InterlockedDecrement(&nRefs) <= 0)
|
||||||
{
|
{
|
||||||
return (this + 1);
|
pStringMgr->Free(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AddRef() throw()
|
bool IsLocked() const throw()
|
||||||
|
{
|
||||||
|
return (nRefs < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsShared() const throw()
|
||||||
|
{
|
||||||
|
return (nRefs > 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CNilStringData :
|
||||||
|
public CStringData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CNilStringData() throw()
|
||||||
|
{
|
||||||
|
pStringMgr = NULL;
|
||||||
|
nRefs = 2;
|
||||||
|
nDataLength = 0;
|
||||||
|
nAllocLength = 0;
|
||||||
|
achNil[0] = 0;
|
||||||
|
achNil[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetManager(_In_ IAtlStringMgr* pMgr) throw()
|
||||||
|
{
|
||||||
|
ATLASSERT(pStringMgr == NULL);
|
||||||
|
pStringMgr = pMgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
wchar_t achNil[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename BaseType = char >
|
||||||
|
class ChTraitsBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef char XCHAR;
|
||||||
|
typedef LPSTR PXSTR;
|
||||||
|
typedef LPCSTR PCXSTR;
|
||||||
|
typedef wchar_t YCHAR;
|
||||||
|
typedef LPWSTR PYSTR;
|
||||||
|
typedef LPCWSTR PCYSTR;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class ChTraitsBase< wchar_t >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef wchar_t XCHAR;
|
||||||
|
typedef LPWSTR PXSTR;
|
||||||
|
typedef LPCWSTR PCXSTR;
|
||||||
|
typedef char YCHAR;
|
||||||
|
typedef LPSTR PYSTR;
|
||||||
|
typedef LPCSTR PCYSTR;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template< typename BaseType, bool t_bMFCDLL = false>
|
||||||
|
class CSimpleStringT
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LPWSTR m_pszData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename ChTraitsBase<BaseType>::XCHAR XCHAR;
|
||||||
|
typedef typename ChTraitsBase<BaseType>::PXSTR PXSTR;
|
||||||
|
typedef typename ChTraitsBase<BaseType>::PCXSTR PCXSTR;
|
||||||
|
typedef typename ChTraitsBase<BaseType>::YCHAR YCHAR;
|
||||||
|
typedef typename ChTraitsBase<BaseType>::PYSTR PYSTR;
|
||||||
|
typedef typename ChTraitsBase<BaseType>::PCYSTR PCYSTR;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CSimpleStringT(_Inout_ IAtlStringMgr* pStringMgr)
|
||||||
|
{
|
||||||
|
CStringData* pData = pStringMgr->GetNilString();
|
||||||
|
Attach(pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSimpleStringT(_In_ const CSimpleStringT& strSrc)
|
||||||
|
{
|
||||||
|
CStringData* pSrcData = strSrc.GetData();
|
||||||
|
CStringData* pNewData = CloneData(pSrcData);
|
||||||
|
Attach(pNewData);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSimpleStringT(_In_ const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc)
|
||||||
|
{
|
||||||
|
CStringData* pSrcData = strSrc.GetData();
|
||||||
|
CStringData* pNewData = CloneData(pSrcData);
|
||||||
|
Attach(pNewData);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSimpleStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
|
||||||
|
{
|
||||||
|
SetString(pszSrc);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
operator PCXSTR() const throw()
|
||||||
|
{
|
||||||
|
return m_pszData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Empty() throw()
|
||||||
|
{
|
||||||
|
CStringData* pOldData = GetData();
|
||||||
|
IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
|
||||||
|
if (pOldData->nDataLength == 0) return;
|
||||||
|
|
||||||
|
if (pOldData->IsLocked())
|
||||||
{
|
{
|
||||||
ATLASSERT(nRefs > 0);
|
SetLength(0);
|
||||||
_InterlockedIncrement(&nRefs);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
void Release() throw()
|
|
||||||
{
|
{
|
||||||
ATLASSERT(nRefs != 0);
|
pOldData->Release();
|
||||||
|
CStringData* pNewData = pStringMgr->GetNilString();
|
||||||
|
Attach(pNewData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_InterlockedDecrement(&nRefs) <= 0)
|
void SetString(_In_opt_z_ PCXSTR pszSrc)
|
||||||
|
{
|
||||||
|
SetString(pszSrc, StringLength(pszSrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetString(_In_reads_opt_(nLength) PCXSTR pszSrc,
|
||||||
|
_In_ int nLength)
|
||||||
|
{
|
||||||
|
if (nLength == 0)
|
||||||
|
{
|
||||||
|
Empty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT nOldLength = GetLength();
|
||||||
|
UINT_PTR nOffset = pszSrc - GetString();
|
||||||
|
|
||||||
|
PXSTR pszBuffer = GetBuffer(nLength);
|
||||||
|
if (nOffset <= nOldLength)
|
||||||
{
|
{
|
||||||
pStringMgr->Free(this);
|
CopyCharsOverlapped(pszBuffer, GetAllocLength(),
|
||||||
|
pszBuffer + nOffset, nLength);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength);
|
||||||
|
}
|
||||||
|
ReleaseBufferSetLength(nLength);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
template< typename BaseType = char >
|
static int __cdecl StringLength(_In_opt_z_ const wchar_t* psz) throw()
|
||||||
class ChTraitsBase
|
|
||||||
{
|
{
|
||||||
public:
|
if (psz == NULL) return 0;
|
||||||
typedef char XCHAR;
|
return (int)wcslen(psz);
|
||||||
typedef LPSTR PXSTR;
|
}
|
||||||
typedef LPCSTR PCXSTR;
|
|
||||||
typedef wchar_t YCHAR;
|
|
||||||
typedef LPWSTR PYSTR;
|
|
||||||
typedef LPCWSTR PCYSTR;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
PXSTR GetBuffer()
|
||||||
class ChTraitsBase< wchar_t >
|
|
||||||
{
|
{
|
||||||
public:
|
CStringData* pData = GetData();
|
||||||
typedef wchar_t XCHAR;
|
if (pData->IsShared())
|
||||||
typedef LPWSTR PXSTR;
|
{
|
||||||
typedef LPCWSTR PCXSTR;
|
// We should fork here
|
||||||
typedef char YCHAR;
|
Fork(pData->nDataLength);
|
||||||
typedef LPSTR PYSTR;
|
}
|
||||||
typedef LPCSTR PCYSTR;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return m_pszData;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetAllocLength() const throw()
|
||||||
template< typename BaseType, bool t_bMFCDLL = false>
|
|
||||||
class CSimpleStringT
|
|
||||||
{
|
{
|
||||||
public:
|
return GetData()->nAllocLength;
|
||||||
typedef typename ChTraitsBase<BaseType>::XCHAR XCHAR;
|
}
|
||||||
typedef typename ChTraitsBase<BaseType>::PXSTR PXSTR;
|
|
||||||
typedef typename ChTraitsBase<BaseType>::PCXSTR PCXSTR;
|
|
||||||
typedef typename ChTraitsBase<BaseType>::YCHAR YCHAR;
|
|
||||||
typedef typename ChTraitsBase<BaseType>::PYSTR PYSTR;
|
|
||||||
typedef typename ChTraitsBase<BaseType>::PCYSTR PCYSTR;
|
|
||||||
|
|
||||||
public:
|
int GetLength() const throw()
|
||||||
explicit CSimpleStringT(_Inout_ IAtlStringMgr* pStringMgr)
|
{
|
||||||
|
return GetData()->nDataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCXSTR GetString() const throw()
|
||||||
|
{
|
||||||
|
return m_pszData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseBufferSetLength(_In_ int nNewLength)
|
||||||
|
{
|
||||||
|
ATLASSERT(nNewLength >= 0);
|
||||||
|
SetLength(nNewLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const throw()
|
||||||
|
{
|
||||||
|
return (GetLength() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Ret_notnull_ _Post_writable_size_(nMinBufferLength + 1) PXSTR GetBuffer(_In_ int nMinBufferLength)
|
||||||
|
{
|
||||||
|
return PrepareWrite(nMinBufferLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
CStringData* GetData() const throw()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<CStringData*>(m_pszData) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cdecl CopyChars(
|
||||||
|
_Out_writes_to_(nDestLen, nChars) XCHAR* pchDest,
|
||||||
|
_In_ size_t nDestLen,
|
||||||
|
_In_reads_opt_(nChars) const XCHAR* pchSrc,
|
||||||
|
_In_ int nChars) throw()
|
||||||
|
{
|
||||||
|
memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cdecl CopyCharsOverlapped(
|
||||||
|
_Out_writes_to_(nDestLen, nDestLen) XCHAR* pchDest,
|
||||||
|
_In_ size_t nDestLen,
|
||||||
|
_In_reads_(nChars) const XCHAR* pchSrc,
|
||||||
|
_In_ int nChars) throw()
|
||||||
|
{
|
||||||
|
memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Attach(_Inout_ CStringData* pData) throw()
|
||||||
|
{
|
||||||
|
m_pszData = static_cast<PXSTR>(pData->data());
|
||||||
|
}
|
||||||
|
__declspec(noinline) void Fork(_In_ int nLength)
|
||||||
|
{
|
||||||
|
CStringData* pOldData = GetData();
|
||||||
|
int nOldLength = pOldData->nDataLength;
|
||||||
|
CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate(nLength, sizeof(XCHAR));
|
||||||
|
if (pNewData == NULL)
|
||||||
{
|
{
|
||||||
ATLENSURE(pStringMgr != NULL);
|
throw; // ThrowMemoryException();
|
||||||
CStringData* pData = pStringMgr->GetNilString();
|
}
|
||||||
Attach(pData);
|
int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength) + 1;
|
||||||
|
CopyChars(PXSTR(pNewData->data()), nCharsToCopy,
|
||||||
|
PCXSTR(pOldData->data()), nCharsToCopy);
|
||||||
|
pNewData->nDataLength = nOldLength;
|
||||||
|
pOldData->Release();
|
||||||
|
Attach(pNewData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PXSTR PrepareWrite(_In_ int nLength)
|
||||||
|
{
|
||||||
|
CStringData* pOldData = GetData();
|
||||||
|
int nShared = 1 - pOldData->nRefs;
|
||||||
|
int nTooShort = pOldData->nAllocLength - nLength;
|
||||||
|
if ((nShared | nTooShort) < 0)
|
||||||
|
{
|
||||||
|
PrepareWrite2(nLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSimpleStringT(_In_ const CSimpleStringT& strSrc)
|
return m_pszData;
|
||||||
|
}
|
||||||
|
void PrepareWrite2(_In_ int nLength)
|
||||||
|
{
|
||||||
|
CStringData* pOldData = GetData();
|
||||||
|
if (pOldData->nDataLength > nLength)
|
||||||
{
|
{
|
||||||
CStringData* pSrcData = strSrc.GetData();
|
nLength = pOldData->nDataLength;
|
||||||
CStringData* pNewData = CloneData(pSrcData);
|
|
||||||
Attach(pNewData);
|
|
||||||
}
|
}
|
||||||
|
if (pOldData->IsShared())
|
||||||
CSimpleStringT(_In_ const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc)
|
|
||||||
{
|
{
|
||||||
CStringData* pSrcData = strSrc.GetData();
|
Fork(nLength);
|
||||||
CStringData* pNewData = CloneData(pSrcData);
|
ATLASSERT(FALSE);
|
||||||
Attach(pNewData);
|
|
||||||
}
|
}
|
||||||
|
else if (pOldData->nAllocLength < nLength)
|
||||||
|
|
||||||
operator PCXSTR() const throw()
|
|
||||||
{
|
{
|
||||||
return m_pszData;
|
int nNewLength = pOldData->nAllocLength;
|
||||||
|
if (nNewLength > 1024 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
nNewLength += 1024 * 1024;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nNewLength = nNewLength + nNewLength / 2;
|
||||||
|
}
|
||||||
|
if (nNewLength < nLength)
|
||||||
|
{
|
||||||
|
nNewLength = nLength;
|
||||||
|
}
|
||||||
|
Reallocate(nNewLength);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
void Reallocate(_In_ int nLength)
|
||||||
|
{
|
||||||
|
CStringData* pOldData = GetData();
|
||||||
|
ATLASSERT(pOldData->nAllocLength < nLength);
|
||||||
|
IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
|
||||||
|
if (pOldData->nAllocLength >= nLength || nLength <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CStringData* pNewData = pStringMgr->Reallocate(pOldData, nLength, sizeof(XCHAR));
|
||||||
|
if (pNewData == NULL) throw;
|
||||||
|
|
||||||
|
Attach(pNewData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLength(_In_ int nLength)
|
||||||
|
{
|
||||||
|
ATLASSERT(nLength >= 0);
|
||||||
|
ATLASSERT(nLength <= GetData()->nAllocLength);
|
||||||
|
|
||||||
|
if (nLength < 0 || nLength > GetData()->nAllocLength)
|
||||||
|
throw;
|
||||||
|
|
||||||
|
GetData()->nDataLength = nLength;
|
||||||
|
m_pszData[nLength] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -2,42 +2,128 @@
|
||||||
#define __ATLSTR_H__
|
#define __ATLSTR_H__
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#error ATL requires C++ compilation (use a .cpp suffix)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <atlbase.h>
|
#include <atlbase.h>
|
||||||
#include <cstringt.h>
|
#include <cstringt.h>
|
||||||
|
|
||||||
namespace ATL
|
namespace ATL
|
||||||
{
|
{
|
||||||
template< typename _BaseType = char, class StringIterator = ChTraitsOS<_BaseType>>
|
|
||||||
class StrTraitATL :
|
class CAtlStringMgr : public IAtlStringMgr
|
||||||
public StringIterator
|
{
|
||||||
|
protected:
|
||||||
|
IAtlMemMgr* m_MemMgr;
|
||||||
|
CNilStringData m_NilStrData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAtlStringMgr(_In_opt_ IAtlMemMgr* MemMgr = NULL):
|
||||||
|
m_MemMgr(MemMgr)
|
||||||
{
|
{
|
||||||
public:
|
m_NilStrData.SetManager(this);
|
||||||
static HINSTANCE FindStringResourceInstance(_In_ UINT nID) throw()
|
}
|
||||||
{
|
|
||||||
return(AtlFindStringResourceInstance(nID));
|
|
||||||
}
|
|
||||||
|
|
||||||
static IAtlStringMgr* GetDefaultManager() throw()
|
virtual ~CAtlStringMgr(void)
|
||||||
{
|
|
||||||
return CAtlStringMgr::GetInstance();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template< typename _CharType = wchar_t>
|
|
||||||
class ChTraitsOS :
|
|
||||||
public ChTraitsBase<_CharType>
|
|
||||||
{
|
{
|
||||||
protected:
|
}
|
||||||
|
|
||||||
public:
|
static IAtlStringMgr* GetInstance(void)
|
||||||
|
{
|
||||||
|
static CWin32Heap Win32Heap(::GetProcessHeap());
|
||||||
|
static CAtlStringMgr StringMgr(&Win32Heap);
|
||||||
|
return &StringMgr;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + NumChars * CharSize) CStringData* Allocate(
|
||||||
|
_In_ int NumChars,
|
||||||
|
_In_ int CharSize)
|
||||||
|
{
|
||||||
|
size_t SizeBytes;
|
||||||
|
CStringData* StrData;
|
||||||
|
|
||||||
|
SizeBytes = sizeof(CStringData) + ((NumChars + 1) * CharSize);
|
||||||
|
|
||||||
|
StrData = static_cast<CStringData*>(m_MemMgr->Allocate(SizeBytes));
|
||||||
|
if (StrData == NULL) return NULL;
|
||||||
|
|
||||||
|
StrData->pStringMgr = this;
|
||||||
|
StrData->nRefs = 1;
|
||||||
|
StrData->nAllocLength = NumChars;
|
||||||
|
StrData->nDataLength = 0;
|
||||||
|
|
||||||
|
return StrData;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Free(_In_ CStringData* StrData)
|
||||||
|
{
|
||||||
|
ATLASSERT(StrData->pStringMgr == this);
|
||||||
|
m_MemMgr->Free(StrData);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nChars*nCharSize) CStringData* Reallocate(
|
||||||
|
_Inout_ _Post_readable_byte_size_(sizeof(CStringData)) CStringData* StrData,
|
||||||
|
_In_ int nChars,
|
||||||
|
_In_ int nCharSize) throw()
|
||||||
|
{
|
||||||
|
ATLASSERT(StrData->pStringMgr == this);
|
||||||
|
|
||||||
|
CStringData* pNewData;
|
||||||
|
ULONG SizeBytes;
|
||||||
|
ULONG nDataBytes;
|
||||||
|
|
||||||
|
nChars++;
|
||||||
|
nDataBytes = nChars * nCharSize;
|
||||||
|
SizeBytes = sizeof(CStringData) + nDataBytes;
|
||||||
|
|
||||||
|
pNewData = static_cast< CStringData* >(m_MemMgr->Reallocate(StrData, SizeBytes));
|
||||||
|
if (pNewData == NULL) return NULL;
|
||||||
|
|
||||||
|
pNewData->nAllocLength = nChars - 1;
|
||||||
|
return pNewData;
|
||||||
|
}
|
||||||
|
virtual CStringData* GetNilString() throw()
|
||||||
|
{
|
||||||
|
m_NilStrData.AddRef();
|
||||||
|
return &m_NilStrData;
|
||||||
|
}
|
||||||
|
virtual IAtlStringMgr* Clone() throw()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool StaticInitialize()
|
||||||
|
{
|
||||||
|
GetInstance();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename _BaseType = char, class StringIterator = ChTraitsOS<_BaseType>>
|
||||||
|
class StrTraitATL :
|
||||||
|
public StringIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HINSTANCE FindStringResourceInstance(_In_ UINT nID) throw()
|
||||||
|
{
|
||||||
|
return AtlFindStringResourceInstance(nID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IAtlStringMgr* GetDefaultManager() throw()
|
||||||
|
{
|
||||||
|
return CAtlStringMgr::GetInstance();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template< typename _CharType = wchar_t>
|
||||||
|
class ChTraitsOS :
|
||||||
|
public ChTraitsBase<_CharType>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef _ATL_CSTRING_NO_CRT
|
#ifndef _ATL_CSTRING_NO_CRT
|
||||||
typedef CStringT<wchar_t, StrTraitATL<wchar_t, ChTraitsCRT<wchar_t>>> CAtlStringW;
|
typedef CStringT<wchar_t, StrTraitATL<wchar_t, ChTraitsCRT<wchar_t>>> CAtlStringW;
|
||||||
|
|
|
@ -2,75 +2,122 @@
|
||||||
#define __CSTRINGT_H__
|
#define __CSTRINGT_H__
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atlsimpstr.h>
|
#include <atlsimpstr.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <atlmem.h>
|
||||||
|
|
||||||
namespace ATL
|
namespace ATL
|
||||||
{
|
{
|
||||||
|
|
||||||
template< typename _CharType = wchar_t>
|
inline UINT WINAPI _AtlGetConversionACP() throw()
|
||||||
class ChTraitsCRT :
|
{
|
||||||
public ChTraitsBase<_CharType>
|
#ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
|
||||||
|
return CP_ACP;
|
||||||
|
#else
|
||||||
|
return CP_THREAD_ACP;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename _CharType = wchar_t>
|
||||||
|
class ChTraitsCRT : public ChTraitsBase<_CharType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
|
||||||
{
|
{
|
||||||
public:
|
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace _CSTRING_IMPL_
|
|
||||||
{
|
|
||||||
template <typename _CharType, class StringTraits>
|
|
||||||
struct _MFCDLLTraitsCheck
|
|
||||||
{
|
|
||||||
const static bool c_bIsMFCDLLTraits = false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename BaseType, class StringTraits>
|
static int __cdecl GetBaseTypeLength(
|
||||||
class CStringT :
|
_In_reads_(nLength) LPCWSTR pszSource,
|
||||||
public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
|
_In_ int nLength) throw()
|
||||||
{
|
{
|
||||||
public:
|
return ::WideCharToMultiByte(CP_THREAD_ACP, 0, pszSource, nLength, NULL, 0, NULL, NULL);
|
||||||
typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
|
}
|
||||||
typedef StringTraits StrTraits;
|
|
||||||
typedef typename CThisSimpleString::XCHAR XCHAR;
|
|
||||||
typedef typename CThisSimpleString::PXSTR PXSTR;
|
|
||||||
typedef typename CThisSimpleString::PCXSTR PCXSTR;
|
|
||||||
typedef typename CThisSimpleString::YCHAR YCHAR;
|
|
||||||
typedef typename CThisSimpleString::PYSTR PYSTR;
|
|
||||||
typedef typename CThisSimpleString::PCYSTR PCYSTR;
|
|
||||||
|
|
||||||
public:
|
static void __cdecl ConvertToBaseType(
|
||||||
CStringT() throw() :
|
_Out_writes_(nDestLength) LPWSTR pszDest,
|
||||||
CThisSimpleString(StringTraits::GetDefaultManager())
|
_In_ int nDestLength,
|
||||||
{
|
_In_ LPCWSTR pszSrc,
|
||||||
}
|
_In_ int nSrcLength = -1)
|
||||||
explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
|
{
|
||||||
CThisSimpleString(pStringMgr)
|
if (nSrcLength == -1)
|
||||||
{
|
nSrcLength = 1 + GetBaseTypeLength(pszSrc);
|
||||||
}
|
|
||||||
|
|
||||||
CStringT(_In_ const VARIANT& varSrc);
|
wmemcpy(pszDest, pszSrc, nSrcLength);
|
||||||
CStringT(
|
}
|
||||||
_In_ const VARIANT& varSrc,
|
};
|
||||||
_In_ IAtlStringMgr* pStringMgr);
|
|
||||||
|
|
||||||
static void __cdecl Construct(_In_ CStringT* pString)
|
|
||||||
{
|
|
||||||
new(pString)CStringT;
|
|
||||||
}
|
|
||||||
|
|
||||||
CStringT(_In_ const CStringT& strSrc) :
|
|
||||||
CThisSimpleString(strSrc)
|
namespace _CSTRING_IMPL_
|
||||||
{
|
{
|
||||||
}
|
template <typename _CharType, class StringTraits>
|
||||||
|
struct _MFCDLLTraitsCheck
|
||||||
|
{
|
||||||
|
const static bool c_bIsMFCDLLTraits = false;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename BaseType, class StringTraits>
|
||||||
|
class CStringT :
|
||||||
|
public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
|
||||||
|
typedef StringTraits StrTraits;
|
||||||
|
typedef typename CThisSimpleString::XCHAR XCHAR;
|
||||||
|
typedef typename CThisSimpleString::PXSTR PXSTR;
|
||||||
|
typedef typename CThisSimpleString::PCXSTR PCXSTR;
|
||||||
|
typedef typename CThisSimpleString::YCHAR YCHAR;
|
||||||
|
typedef typename CThisSimpleString::PYSTR PYSTR;
|
||||||
|
typedef typename CThisSimpleString::PCYSTR PCYSTR;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CStringT() throw() :
|
||||||
|
CThisSimpleString(StringTraits::GetDefaultManager())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
|
||||||
|
CThisSimpleString(pStringMgr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cdecl Construct(_In_ CStringT* pString)
|
||||||
|
{
|
||||||
|
new pString (CStringT);
|
||||||
|
}
|
||||||
|
|
||||||
|
CStringT(_In_ const CStringT& strSrc) :
|
||||||
|
CThisSimpleString(strSrc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
|
||||||
|
{
|
||||||
|
CThisSimpleString::operator=(pszSrc);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
|
||||||
|
_In_ UINT nID)
|
||||||
|
{
|
||||||
|
const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
|
||||||
|
if (pImage == NULL) return FALSE;
|
||||||
|
|
||||||
|
int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
|
||||||
|
PXSTR pszBuffer = GetBuffer(nLength);
|
||||||
|
StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
|
||||||
|
ReleaseBufferSetLength(nLength);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} //namespace ATL
|
} //namespace ATL
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue