ea4434c9db27777339142c761a2af6bf966e8bf4
1 #ifndef __ATLSIMPSTR_H__
2 #define __ATLSIMPSTR_H__
13 // Pure virtual interface
18 virtual ~IAtlStringMgr() {}
20 virtual _Ret_maybenull_
_Post_writable_byte_size_(sizeof(CStringData
) + nAllocLength
*nCharSize
)
21 CStringData
* Allocate(
22 _In_
int nAllocLength
,
27 _Inout_ CStringData
* pData
30 virtual _Ret_maybenull_
_Post_writable_byte_size_(sizeof(CStringData
) + nAllocLength
*nCharSize
)
31 CStringData
* Reallocate(
32 _Inout_ CStringData
* pData
,
33 _In_
int nAllocLength
,
37 virtual CStringData
* GetNilString(void) = 0;
38 virtual IAtlStringMgr
* Clone(void) = 0;
44 IAtlStringMgr
* pStringMgr
;
57 _InterlockedIncrement(&nRefs
);
60 void Release() throw()
62 ATLASSERT(nRefs
!= 0);
64 if (_InterlockedDecrement(&nRefs
) <= 0)
66 pStringMgr
->Free(this);
70 bool IsLocked() const throw()
75 bool IsShared() const throw()
81 class CNilStringData
:
85 CNilStringData() throw()
95 void SetManager(_In_ IAtlStringMgr
* pMgr
) throw()
97 ATLASSERT(pStringMgr
== NULL
);
106 template< typename BaseType
= char >
112 typedef LPCSTR PCXSTR
;
113 typedef wchar_t YCHAR
;
114 typedef LPWSTR PYSTR
;
115 typedef LPCWSTR PCYSTR
;
119 class ChTraitsBase
<wchar_t>
122 typedef wchar_t XCHAR
;
123 typedef LPWSTR PXSTR
;
124 typedef LPCWSTR PCXSTR
;
127 typedef LPCSTR PCYSTR
;
130 template< typename BaseType
, bool t_bMFCDLL
= false>
134 typedef typename ChTraitsBase
<BaseType
>::XCHAR XCHAR
;
135 typedef typename ChTraitsBase
<BaseType
>::PXSTR PXSTR
;
136 typedef typename ChTraitsBase
<BaseType
>::PCXSTR PCXSTR
;
137 typedef typename ChTraitsBase
<BaseType
>::YCHAR YCHAR
;
138 typedef typename ChTraitsBase
<BaseType
>::PYSTR PYSTR
;
139 typedef typename ChTraitsBase
<BaseType
>::PCYSTR PCYSTR
;
145 explicit CSimpleStringT(_Inout_ IAtlStringMgr
* pStringMgr
)
147 CStringData
* pData
= pStringMgr
->GetNilString();
151 CSimpleStringT(_In_
const CSimpleStringT
& strSrc
)
153 CStringData
* pSrcData
= strSrc
.GetData();
154 CStringData
* pNewData
= CloneData(pSrcData
);
159 _In_z_ PCXSTR pszSrc
,
160 _Inout_ IAtlStringMgr
* pStringMgr
)
162 int nLength
= StringLength(pszSrc
);
163 CStringData
* pData
= pStringMgr
->Allocate(nLength
, sizeof(XCHAR
));
166 throw; // ThrowMemoryException();
170 CopyChars(m_pszData
, nLength
, pszSrc
, nLength
);
174 _In_count_(nLength
) const XCHAR
* pchSrc
,
176 _Inout_ IAtlStringMgr
* pStringMgr
)
178 if (pchSrc
== NULL
&& nLength
!= 0)
181 CStringData
* pData
= pStringMgr
->Allocate(nLength
, sizeof(XCHAR
));
184 throw; // ThrowMemoryException();
188 CopyChars(m_pszData
, nLength
, pchSrc
, nLength
);
191 ~CSimpleStringT() throw()
193 CStringData
* pData
= GetData();
197 CSimpleStringT
& operator=(_In_opt_z_ PCXSTR pszSrc
)
203 CSimpleStringT
& operator=(_In_
const CSimpleStringT
& strSrc
)
205 CStringData
* pData
= GetData();
206 CStringData
* pNewData
= strSrc
.GetData();
208 if (pNewData
!= pData
)
210 if (!pData
->IsLocked() && (pNewData
->pStringMgr
== pData
->pStringMgr
))
212 pNewData
= CloneData(pNewData
);
218 SetString(strSrc
.GetString(), strSrc
.GetLength());
225 CSimpleStringT
& operator+=(_In_
const CSimpleStringT
& strSrc
)
231 CSimpleStringT
& operator+=(_In_z_ PCXSTR pszSrc
)
237 operator PCXSTR() const throw()
244 CStringData
* pOldData
= GetData();
245 IAtlStringMgr
* pStringMgr
= pOldData
->pStringMgr
;
246 if (pOldData
->nDataLength
== 0) return;
248 if (pOldData
->IsLocked())
255 CStringData
* pNewData
= pStringMgr
->GetNilString();
261 _In_count_(nLength
) PCXSTR pszSrc
,
264 UINT_PTR nOffset
= pszSrc
- GetString();
266 int nOldLength
= GetLength();
270 ATLASSERT(nLength
>= 0);
272 #if 0 // FIXME: See comment for StringLengthN below.
273 nLength
= StringLengthN(pszSrc
, nLength
);
274 if (!(INT_MAX
- nLength
>= nOldLength
))
278 int nNewLength
= nOldLength
+ nLength
;
279 PXSTR pszBuffer
= GetBuffer(nNewLength
);
280 if (nOffset
<= (UINT_PTR
)nOldLength
)
282 pszSrc
= pszBuffer
+ nOffset
;
284 CopyChars(pszBuffer
+ nOldLength
, nLength
, pszSrc
, nLength
);
285 ReleaseBufferSetLength(nNewLength
);
288 void Append(_In_z_ PCXSTR pszSrc
)
290 Append(pszSrc
, StringLength(pszSrc
));
293 void Append(_In_
const CSimpleStringT
& strSrc
)
295 Append(strSrc
.GetString(), strSrc
.GetLength());
298 void SetString(_In_opt_z_ PCXSTR pszSrc
)
300 SetString(pszSrc
, StringLength(pszSrc
));
303 void SetString(_In_reads_opt_(nLength
) PCXSTR pszSrc
,
312 UINT nOldLength
= GetLength();
313 UINT_PTR nOffset
= pszSrc
- GetString();
315 PXSTR pszBuffer
= GetBuffer(nLength
);
316 if (nOffset
<= nOldLength
)
318 CopyCharsOverlapped(pszBuffer
, GetAllocLength(),
319 pszBuffer
+ nOffset
, nLength
);
323 CopyChars(pszBuffer
, GetAllocLength(), pszSrc
, nLength
);
325 ReleaseBufferSetLength(nLength
);
331 CStringData
* pData
= GetData();
332 if (pData
->IsShared())
334 // We should fork here
335 Fork(pData
->nDataLength
);
341 _Ret_notnull_
_Post_writable_size_(nMinBufferLength
+ 1) PXSTR
GetBuffer(_In_
int nMinBufferLength
)
343 return PrepareWrite(nMinBufferLength
);
346 int GetAllocLength() const throw()
348 return GetData()->nAllocLength
;
351 int GetLength() const throw()
353 return GetData()->nDataLength
;
356 PCXSTR
GetString() const throw()
361 void ReleaseBufferSetLength(_In_
int nNewLength
)
363 ATLASSERT(nNewLength
>= 0);
364 SetLength(nNewLength
);
367 bool IsEmpty() const throw()
369 return (GetLength() == 0);
372 CStringData
* GetData() const throw()
374 return (reinterpret_cast<CStringData
*>(m_pszData
) - 1);
377 IAtlStringMgr
* GetManager() const throw()
379 IAtlStringMgr
* pStringMgr
= GetData()->pStringMgr
;
380 return (pStringMgr
? pStringMgr
->Clone() : NULL
);
384 friend CSimpleStringT
operator+(
385 _In_
const CSimpleStringT
& str1
,
386 _In_
const CSimpleStringT
& str2
)
388 CSimpleStringT
s(str1
.GetManager());
389 Concatenate(s
, str1
, str1
.GetLength(), str2
, str2
.GetLength());
393 friend CSimpleStringT
operator+(
394 _In_
const CSimpleStringT
& str1
,
397 CSimpleStringT
s(str1
.GetManager());
398 Concatenate(s
, str1
, str1
.GetLength(), psz2
, StringLength(psz2
));
402 friend CSimpleStringT
operator+(
404 _In_
const CSimpleStringT
& str2
)
406 CSimpleStringT
s(str2
.GetManager());
407 Concatenate(s
, psz1
, StringLength(psz1
), str2
, str2
.GetLength());
411 static void __cdecl
CopyChars(
412 _Out_writes_to_(nDestLen
, nChars
) XCHAR
* pchDest
,
413 _In_
size_t nDestLen
,
414 _In_reads_opt_(nChars
) const XCHAR
* pchSrc
,
415 _In_
int nChars
) throw()
417 memcpy(pchDest
, pchSrc
, nChars
* sizeof(XCHAR
));
420 static void __cdecl
CopyCharsOverlapped(
421 _Out_writes_to_(nDestLen
, nDestLen
) XCHAR
* pchDest
,
422 _In_
size_t nDestLen
,
423 _In_reads_(nChars
) const XCHAR
* pchSrc
,
424 _In_
int nChars
) throw()
426 memmove(pchDest
, pchSrc
, nChars
* sizeof(XCHAR
));
429 static int __cdecl
StringLength(_In_opt_z_
const char* psz
) throw()
431 if (psz
== NULL
) return 0;
432 return (int)strlen(psz
);
435 static int __cdecl
StringLength(_In_opt_z_
const wchar_t* psz
) throw()
437 if (psz
== NULL
) return 0;
438 return (int)wcslen(psz
);
441 #if 0 // For whatever reason we do not link with strnlen / wcsnlen. Please investigate!
442 // strnlen / wcsnlen are available in MSVCRT starting Vista+.
443 static int __cdecl
StringLengthN(
444 _In_opt_z_count_(sizeInXChar
) const char* psz
,
445 _In_
size_t sizeInXChar
) throw()
447 if (psz
== NULL
) return 0;
448 return (int)strnlen(psz
, sizeInXChar
);
451 static int __cdecl
StringLengthN(
452 _In_opt_z_count_(sizeInXChar
) const wchar_t* psz
,
453 _In_
size_t sizeInXChar
) throw()
455 if (psz
== NULL
) return 0;
456 return (int)wcsnlen(psz
, sizeInXChar
);
461 static void __cdecl
Concatenate(
462 _Inout_ CSimpleStringT
& strResult
,
463 _In_count_(nLength1
) PCXSTR psz1
,
465 _In_count_(nLength2
) PCXSTR psz2
,
468 int nNewLength
= nLength1
+ nLength2
;
469 PXSTR pszBuffer
= strResult
.GetBuffer(nNewLength
);
470 CopyChars(pszBuffer
, nLength1
, psz1
, nLength1
);
471 CopyChars(pszBuffer
+ nLength1
, nLength2
, psz2
, nLength2
);
472 strResult
.ReleaseBufferSetLength(nNewLength
);
476 void Attach(_Inout_ CStringData
* pData
) throw()
478 m_pszData
= static_cast<PXSTR
>(pData
->data());
481 __declspec(noinline
) void Fork(_In_
int nLength
)
483 CStringData
* pOldData
= GetData();
484 int nOldLength
= pOldData
->nDataLength
;
485 CStringData
* pNewData
= pOldData
->pStringMgr
->Clone()->Allocate(nLength
, sizeof(XCHAR
));
486 if (pNewData
== NULL
)
488 throw; // ThrowMemoryException();
490 int nCharsToCopy
= ((nOldLength
< nLength
) ? nOldLength
: nLength
) + 1;
491 CopyChars(PXSTR(pNewData
->data()), nCharsToCopy
,
492 PCXSTR(pOldData
->data()), nCharsToCopy
);
493 pNewData
->nDataLength
= nOldLength
;
498 PXSTR
PrepareWrite(_In_
int nLength
)
500 CStringData
* pOldData
= GetData();
501 int nShared
= 1 - pOldData
->nRefs
;
502 int nTooShort
= pOldData
->nAllocLength
- nLength
;
503 if ((nShared
| nTooShort
) < 0)
505 PrepareWrite2(nLength
);
510 void PrepareWrite2(_In_
int nLength
)
512 CStringData
* pOldData
= GetData();
513 if (pOldData
->nDataLength
> nLength
)
515 nLength
= pOldData
->nDataLength
;
517 if (pOldData
->IsShared())
522 else if (pOldData
->nAllocLength
< nLength
)
524 int nNewLength
= pOldData
->nAllocLength
;
525 if (nNewLength
> 1024 * 1024 * 1024)
527 nNewLength
+= 1024 * 1024;
531 nNewLength
= nNewLength
+ nNewLength
/ 2;
533 if (nNewLength
< nLength
)
535 nNewLength
= nLength
;
537 Reallocate(nNewLength
);
541 void Reallocate(_In_
int nLength
)
543 CStringData
* pOldData
= GetData();
544 ATLASSERT(pOldData
->nAllocLength
< nLength
);
545 IAtlStringMgr
* pStringMgr
= pOldData
->pStringMgr
;
546 if (pOldData
->nAllocLength
>= nLength
|| nLength
<= 0)
550 CStringData
* pNewData
= pStringMgr
->Reallocate(pOldData
, nLength
, sizeof(XCHAR
));
551 if (pNewData
== NULL
)
553 throw; // ThrowMemoryException();
559 void SetLength(_In_
int nLength
)
561 ATLASSERT(nLength
>= 0);
562 ATLASSERT(nLength
<= GetData()->nAllocLength
);
564 if (nLength
< 0 || nLength
> GetData()->nAllocLength
)
567 GetData()->nDataLength
= nLength
;
568 m_pszData
[nLength
] = 0;
571 static CStringData
* __cdecl
CloneData(_Inout_ CStringData
* pData
)
573 CStringData
* pNewData
= NULL
;
575 IAtlStringMgr
* pNewStringMgr
= pData
->pStringMgr
->Clone();
576 if (!pData
->IsLocked() && (pNewStringMgr
== pData
->pStringMgr
))
583 pNewData
= pNewStringMgr
->Allocate(pData
->nDataLength
, sizeof(XCHAR
));
584 if (pNewData
== NULL
)
586 throw; // ThrowMemoryException();
589 pNewData
->nDataLength
= pData
->nDataLength
;
590 CopyChars(PXSTR(pNewData
->data()), pData
->nDataLength
+ 1,
591 PCXSTR(pData
->data()), pData
->nDataLength
+ 1);