[ATL][ATL_APITEST] Add CAtlList::InsertBefore/After + test
[reactos.git] / sdk / lib / atl / cstringt.h
1 #ifndef __CSTRINGT_H__
2 #define __CSTRINGT_H__
3
4 #pragma once
5 #include <atlsimpstr.h>
6 #include <stddef.h>
7 #include <stdio.h>
8 #include <wchar.h>
9 #include <atlmem.h>
10
11 namespace ATL
12 {
13
14 inline UINT WINAPI _AtlGetConversionACP() throw()
15 {
16 #ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
17 return CP_ACP;
18 #else
19 return CP_THREAD_ACP;
20 #endif
21 }
22
23
24 template<typename _CharType = wchar_t>
25 class ChTraitsCRT : public ChTraitsBase<_CharType>
26 {
27 public:
28
29 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
30 {
31 if (pszSource == NULL) return -1;
32 return static_cast<int>(wcslen(pszSource));
33 }
34
35 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw()
36 {
37 if (pszSource == NULL) return 0;
38 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0) - 1;
39 }
40
41 static int __cdecl GetBaseTypeLength(
42 _In_reads_(nLength) LPCWSTR pszSource,
43 _In_ int nLength) throw()
44 {
45 return nLength;
46 }
47
48 static int __cdecl GetBaseTypeLength(
49 _In_reads_(nLength) LPCSTR pszSource,
50 _In_ int nLength) throw()
51 {
52 return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0);
53 }
54
55 static void __cdecl ConvertToBaseType(
56 _Out_writes_(nDestLength) LPWSTR pszDest,
57 _In_ int nDestLength,
58 _In_ LPCWSTR pszSrc,
59 _In_ int nSrcLength = -1)
60 {
61 if (nSrcLength == -1)
62 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
63
64 wmemcpy(pszDest, pszSrc, nSrcLength);
65 }
66
67 static void __cdecl ConvertToBaseType(
68 _Out_writes_(nDestLength) LPWSTR pszDest,
69 _In_ int nDestLength,
70 _In_ LPCSTR pszSrc,
71 _In_ int nSrcLength = -1)
72 {
73 if (nSrcLength == -1)
74 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
75
76 ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength);
77 }
78
79 static void __cdecl MakeLower(
80 _Out_writes_(nSrcLength) LPWSTR pszSource,
81 _In_ int nSrcLength)
82 {
83 ::CharLowerBuffW(pszSource, nSrcLength);
84 }
85
86 static DWORD GetEnvironmentVariable(
87 _In_z_ LPCWSTR pszVar,
88 _Out_writes_opt_(nBufLength) LPWSTR pszBuf,
89 _In_opt_ int nBufLength)
90 {
91 return ::GetEnvironmentVariableW(pszVar, pszBuf, nBufLength);
92 }
93
94 static void __cdecl MakeUpper(
95 _Out_writes_(nSrcLength) LPWSTR pszSource,
96 _In_ int nSrcLength)
97 {
98 ::CharUpperBuffW(pszSource, nSrcLength);
99 }
100
101 static LPWSTR __cdecl FindString(
102 _In_z_ LPCWSTR pszSource,
103 _In_z_ LPCWSTR pszSub)
104 {
105 return ::wcsstr(pszSource, pszSub);
106 }
107
108 static LPWSTR __cdecl FindChar(
109 _In_z_ LPCWSTR pszSource,
110 _In_ WCHAR ch)
111 {
112 return ::wcschr(pszSource, ch);
113 }
114
115 static LPWSTR __cdecl FindCharReverse(
116 _In_z_ LPCWSTR pszSource,
117 _In_ WCHAR ch)
118 {
119 return ::wcsrchr(pszSource, ch);
120 }
121
122 static LPWSTR __cdecl FindOneOf(
123 _In_z_ LPCWSTR pszSource,
124 _In_z_ LPCWSTR pszCharSet)
125 {
126 return ::wcspbrk(pszSource, pszCharSet);
127 }
128
129 static int __cdecl Compare(
130 _In_z_ LPCWSTR psz1,
131 _In_z_ LPCWSTR psz2)
132 {
133 return ::wcscmp(psz1, psz2);
134 }
135
136 static int __cdecl CompareNoCase(
137 _In_z_ LPCWSTR psz1,
138 _In_z_ LPCWSTR psz2)
139 {
140 return ::_wcsicmp(psz1, psz2);
141 }
142
143 static int __cdecl FormatV(
144 _In_opt_z_ LPWSTR pszDest,
145 _In_z_ LPCWSTR pszFormat,
146 _In_ va_list args)
147 {
148 if (pszDest == NULL)
149 return ::_vscwprintf(pszFormat, args);
150 return ::vswprintf(pszDest, pszFormat, args);
151 }
152
153 static BSTR __cdecl AllocSysString(
154 _In_z_ LPCWSTR pszSource,
155 _In_ int nLength)
156 {
157 return ::SysAllocStringLen(pszSource, nLength);
158 }
159 };
160
161
162 // Template specialization
163
164 template<>
165 class ChTraitsCRT<char> : public ChTraitsBase<char>
166 {
167 public:
168
169 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
170 {
171 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
172 }
173
174 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw()
175 {
176 if (pszSource == NULL) return 0;
177 return static_cast<int>(strlen(pszSource));
178 }
179
180 static int __cdecl GetBaseTypeLength(
181 _In_reads_(nLength) LPCWSTR pszSource,
182 _In_ int nLength) throw()
183 {
184 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
185 }
186
187 static int __cdecl GetBaseTypeLength(
188 _In_reads_(nLength) LPCSTR pszSource,
189 _In_ int nLength) throw()
190 {
191 return nLength;
192 }
193
194 static void __cdecl ConvertToBaseType(
195 _Out_writes_(nDestLength) LPSTR pszDest,
196 _In_ int nDestLength,
197 _In_ LPCWSTR pszSrc,
198 _In_ int nSrcLength = -1)
199 {
200 if (nSrcLength == -1)
201 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
202
203 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
204 }
205
206 static void __cdecl ConvertToBaseType(
207 _Out_writes_(nDestLength) LPSTR pszDest,
208 _In_ int nDestLength,
209 _In_ LPCSTR pszSrc,
210 _In_ int nSrcLength = -1)
211 {
212 if (nSrcLength == -1)
213 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
214
215 memcpy(pszDest, pszSrc, nSrcLength);
216 }
217
218 static void __cdecl MakeLower(
219 _Out_writes_(nSrcLength) LPSTR pszSource,
220 _In_ int nSrcLength)
221 {
222 ::CharLowerBuffA(pszSource, nSrcLength);
223 }
224
225 static DWORD GetEnvironmentVariable(
226 _In_z_ LPCSTR pszVar,
227 _Out_writes_opt_(nBufLength) LPSTR pszBuf,
228 _In_opt_ int nBufLength)
229 {
230 return ::GetEnvironmentVariableA(pszVar, pszBuf, nBufLength);
231 }
232
233 static void __cdecl MakeUpper(
234 _Out_writes_(nSrcLength) LPSTR pszSource,
235 _In_ int nSrcLength)
236 {
237 ::CharUpperBuffA(pszSource, nSrcLength);
238 }
239
240 static LPSTR __cdecl FindString(
241 _In_z_ LPCSTR pszSource,
242 _In_z_ LPCSTR pszSub)
243 {
244 return ::strstr(pszSource, pszSub);
245 }
246
247 static LPSTR __cdecl FindChar(
248 _In_z_ LPCSTR pszSource,
249 _In_ CHAR ch)
250 {
251 return ::strchr(pszSource, ch);
252 }
253
254 static LPSTR __cdecl FindCharReverse(
255 _In_z_ LPCSTR pszSource,
256 _In_ CHAR ch)
257 {
258 return ::strrchr(pszSource, ch);
259 }
260
261 static LPSTR __cdecl FindOneOf(
262 _In_z_ LPCSTR pszSource,
263 _In_z_ LPCSTR pszCharSet)
264 {
265 return ::strpbrk(pszSource, pszCharSet);
266 }
267
268 static int __cdecl Compare(
269 _In_z_ LPCSTR psz1,
270 _In_z_ LPCSTR psz2)
271 {
272 return ::strcmp(psz1, psz2);
273 }
274
275 static int __cdecl CompareNoCase(
276 _In_z_ LPCSTR psz1,
277 _In_z_ LPCSTR psz2)
278 {
279 return ::_stricmp(psz1, psz2);
280 }
281
282 static int __cdecl FormatV(
283 _In_opt_z_ LPSTR pszDest,
284 _In_z_ LPCSTR pszFormat,
285 _In_ va_list args)
286 {
287 if (pszDest == NULL)
288 return ::_vscprintf(pszFormat, args);
289 return ::vsprintf(pszDest, pszFormat, args);
290 }
291
292 static BSTR __cdecl AllocSysString(
293 _In_z_ LPCSTR pszSource,
294 _In_ int nLength)
295 {
296 int nLen = ChTraitsCRT<wchar_t>::GetBaseTypeLength(pszSource, nLength);
297 BSTR bstr = ::SysAllocStringLen(NULL, nLen);
298 if (bstr)
299 {
300 ChTraitsCRT<wchar_t>::ConvertToBaseType(bstr, nLen, pszSource, nLength);
301 }
302 return bstr;
303 }
304
305 };
306
307
308 namespace _CSTRING_IMPL_
309 {
310 template <typename _CharType, class StringTraits>
311 struct _MFCDLLTraitsCheck
312 {
313 const static bool c_bIsMFCDLLTraits = false;
314 };
315 }
316
317
318 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
319
320 template <typename BaseType, class StringTraits>
321 class CStringT :
322 public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
323 {
324 public:
325 typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
326 typedef StringTraits StrTraits;
327 typedef typename CThisSimpleString::XCHAR XCHAR;
328 typedef typename CThisSimpleString::PXSTR PXSTR;
329 typedef typename CThisSimpleString::PCXSTR PCXSTR;
330 typedef typename CThisSimpleString::YCHAR YCHAR;
331 typedef typename CThisSimpleString::PYSTR PYSTR;
332 typedef typename CThisSimpleString::PCYSTR PCYSTR;
333
334 public:
335 CStringT() throw() :
336 CThisSimpleString(StringTraits::GetDefaultManager())
337 {
338 }
339
340 explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
341 CThisSimpleString(pStringMgr)
342 {
343 }
344
345 static void __cdecl Construct(_In_ CStringT* pString)
346 {
347 new(pString) CStringT;
348 }
349
350 CStringT(_In_ const CStringT& strSrc) :
351 CThisSimpleString(strSrc)
352 {
353 }
354
355 CStringT(_In_ const CThisSimpleString& strSrc) :
356 CThisSimpleString(strSrc)
357 {
358 }
359
360 template<class StringTraits_>
361 CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) :
362 CThisSimpleString(StringTraits::GetDefaultManager())
363 {
364 *this = static_cast<const YCHAR*>(strSrc);
365 }
366
367 protected:
368 /* helper function */
369 template <typename T_CHAR>
370 void LoadFromPtr_(_In_opt_z_ const T_CHAR* pszSrc)
371 {
372 if (pszSrc == NULL)
373 return;
374 if (IS_INTRESOURCE(pszSrc))
375 LoadString(LOWORD(pszSrc));
376 else
377 *this = pszSrc;
378 }
379
380 public:
381 CStringT(_In_opt_z_ const XCHAR* pszSrc) :
382 CThisSimpleString(StringTraits::GetDefaultManager())
383 {
384 LoadFromPtr_(pszSrc);
385 }
386
387 CStringT(_In_opt_z_ const XCHAR* pszSrc,
388 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr)
389 {
390 LoadFromPtr_(pszSrc);
391 }
392
393 CStringT(_In_opt_z_ const YCHAR* pszSrc) :
394 CThisSimpleString(StringTraits::GetDefaultManager())
395 {
396 LoadFromPtr_(pszSrc);
397 }
398
399 CStringT(_In_opt_z_ const YCHAR* pszSrc,
400 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr)
401 {
402 LoadFromPtr_(pszSrc);
403 }
404
405 CStringT(_In_reads_z_(nLength) const XCHAR* pch,
406 _In_ int nLength) :
407 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
408 {
409 }
410
411 CStringT(_In_reads_z_(nLength) const YCHAR* pch,
412 _In_ int nLength) :
413 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
414 {
415 }
416
417 CStringT& operator=(_In_ const CStringT& strSrc)
418 {
419 CThisSimpleString::operator=(strSrc);
420 return *this;
421 }
422
423 CStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
424 {
425 CThisSimpleString::operator=(pszSrc);
426 return *this;
427 }
428
429 CStringT& operator=(_In_opt_z_ PCYSTR pszSrc)
430 {
431 int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
432 if (length > 0)
433 {
434 PXSTR result = CThisSimpleString::GetBuffer(length);
435 StringTraits::ConvertToBaseType(result, length, pszSrc);
436 CThisSimpleString::ReleaseBufferSetLength(length);
437 }
438 else
439 {
440 CThisSimpleString::Empty();
441 }
442 return *this;
443 }
444
445 CStringT& operator=(_In_ const CThisSimpleString &strSrc)
446 {
447 CThisSimpleString::operator=(strSrc);
448 return *this;
449 }
450
451 friend bool operator==(const CStringT& str1, const CStringT& str2) throw()
452 {
453 return str1.Compare(str2) == 0;
454 }
455
456 friend bool operator==(const CStringT& str1, PCXSTR psz2) throw()
457 {
458 return str1.Compare(psz2) == 0;
459 }
460
461 friend bool operator==(const CStringT& str1, PCYSTR psz2) throw()
462 {
463 CStringT tmp(psz2, str1.GetManager());
464 return tmp.Compare(str1) == 0;
465 }
466
467 friend bool operator==(const CStringT& str1, XCHAR ch2) throw()
468 {
469 return str1.GetLength() == 1 && str1[0] == ch2;
470 }
471
472 friend bool operator==(PCXSTR psz1, const CStringT& str2) throw()
473 {
474 return str2.Compare(psz1) == 0;
475 }
476
477 friend bool operator==(PCYSTR psz1, const CStringT& str2) throw()
478 {
479 CStringT tmp(psz1, str2.GetManager());
480 return tmp.Compare(str2) == 0;
481 }
482
483 friend bool operator==(XCHAR ch1, const CStringT& str2) throw()
484 {
485 return str2.GetLength() == 1 && str2[0] == ch1;
486 }
487
488 CStringT& operator+=(_In_ const CThisSimpleString& str)
489 {
490 CThisSimpleString::operator+=(str);
491 return *this;
492 }
493
494 CStringT& operator+=(_In_z_ PCXSTR pszSrc)
495 {
496 CThisSimpleString::operator+=(pszSrc);
497 return *this;
498 }
499
500 CStringT& operator+=(_In_ XCHAR ch)
501 {
502 CThisSimpleString::operator+=(ch);
503 return *this;
504 }
505
506 BOOL LoadString(_In_ UINT nID)
507 {
508 return LoadString(_AtlBaseModule.GetResourceInstance(), nID);
509 }
510
511 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
512 _In_ UINT nID)
513 {
514 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
515 if (pImage == NULL) return FALSE;
516
517 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
518 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
519 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
520 CThisSimpleString::ReleaseBufferSetLength(nLength);
521
522 return TRUE;
523 }
524
525 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar)
526 {
527 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
528
529 if (nLength > 0)
530 {
531 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
532 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
533 CThisSimpleString::ReleaseBuffer();
534 return TRUE;
535 }
536
537 CThisSimpleString::Empty();
538 return FALSE;
539 }
540
541 CStringT& MakeLower()
542 {
543 int nLength = CThisSimpleString::GetLength();
544 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
545
546 StringTraits::MakeLower(pszBuffer, nLength);
547 CThisSimpleString::ReleaseBufferSetLength(nLength);
548
549 return *this;
550 }
551
552 CStringT& MakeUpper()
553 {
554 int nLength = CThisSimpleString::GetLength();
555 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
556
557 StringTraits::MakeUpper(pszBuffer, nLength);
558 CThisSimpleString::ReleaseBufferSetLength(nLength);
559
560 return *this;
561 }
562
563 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw()
564 {
565 int nLength = CThisSimpleString::GetLength();
566
567 if (iStart >= nLength || iStart < 0)
568 return -1;
569
570 PCXSTR pszString = CThisSimpleString::GetString();
571 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub);
572
573 return pszResult ? ((int)(pszResult - pszString)) : -1;
574 }
575
576 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw()
577 {
578 int nLength = CThisSimpleString::GetLength();
579
580 if (iStart >= nLength || iStart < 0)
581 return -1;
582
583 PCXSTR pszString = CThisSimpleString::GetString();
584 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch);
585
586 return pszResult ? ((int)(pszResult - pszString)) : -1;
587 }
588
589 int FindOneOf(_In_ PCXSTR pszCharSet) const throw()
590 {
591 PCXSTR pszString = CThisSimpleString::GetString();
592 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet);
593
594 return pszResult ? ((int)(pszResult - pszString)) : -1;
595 }
596
597 int ReverseFind(_In_ XCHAR ch) const throw()
598 {
599 PCXSTR pszString = CThisSimpleString::GetString();
600 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch);
601
602 return pszResult ? ((int)(pszResult - pszString)) : -1;
603 }
604
605 int Compare(_In_z_ PCXSTR psz) const
606 {
607 return StringTraits::Compare(CThisSimpleString::GetString(), psz);
608 }
609
610 int CompareNoCase(_In_z_ PCXSTR psz) const
611 {
612 return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz);
613 }
614
615 CStringT Mid(int iFirst, int nCount) const
616 {
617 int nLength = CThisSimpleString::GetLength();
618
619 if (iFirst < 0)
620 iFirst = 0;
621 if (nCount < 0)
622 nCount = 0;
623 if (iFirst > nLength)
624 iFirst = nLength;
625 if (iFirst + nCount > nLength)
626 nCount = nLength - iFirst;
627
628 return CStringT(CThisSimpleString::GetString() + iFirst, nCount);
629 }
630
631 CStringT Mid(int iFirst) const
632 {
633 int nLength = CThisSimpleString::GetLength();
634
635 if (iFirst < 0)
636 iFirst = 0;
637 if (iFirst > nLength)
638 iFirst = nLength;
639
640 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst);
641 }
642
643 CStringT Left(int nCount) const
644 {
645 int nLength = CThisSimpleString::GetLength();
646
647 if (nCount < 0)
648 nCount = 0;
649 if (nCount > nLength)
650 nCount = nLength;
651
652 return CStringT(CThisSimpleString::GetString(), nCount);
653 }
654
655 CStringT Right(int nCount) const
656 {
657 int nLength = CThisSimpleString::GetLength();
658
659 if (nCount < 0)
660 nCount = 0;
661 if (nCount > nLength)
662 nCount = nLength;
663
664 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount);
665 }
666
667
668 void __cdecl Format(UINT nFormatID, ...)
669 {
670 va_list args;
671 va_start(args, nFormatID);
672 CStringT formatString;
673 if (formatString.LoadString(nFormatID))
674 FormatV(formatString, args);
675 va_end(args);
676 }
677
678 void __cdecl Format(PCXSTR pszFormat, ...)
679 {
680 va_list args;
681 va_start(args, pszFormat);
682 FormatV(pszFormat, args);
683 va_end(args);
684 }
685
686 void FormatV(PCXSTR pszFormat, va_list args)
687 {
688 int nLength = StringTraits::FormatV(NULL, pszFormat, args);
689
690 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
691 StringTraits::FormatV(pszBuffer, pszFormat, args);
692 CThisSimpleString::ReleaseBufferSetLength(nLength);
693 }
694
695
696 int Replace(PCXSTR pszOld, PCXSTR pszNew)
697 {
698 PCXSTR pszString = CThisSimpleString::GetString();
699
700 const int nLength = CThisSimpleString::GetLength();
701 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld);
702 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew);
703 const int nDiff = nNewLen - nOldLen;
704 int nResultLength = nLength;
705
706 PCXSTR pszFound;
707 while ((pszFound = StringTraits::FindString(pszString, pszOld)))
708 {
709 nResultLength += nDiff;
710 pszString = pszFound + nOldLen;
711 }
712
713 if (pszString == CThisSimpleString::GetString())
714 return 0;
715
716 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength);
717 PXSTR pszNext;
718 int nCount = 0, nRemaining = nLength;
719 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld)))
720 {
721 nRemaining -= (pszNext - pszResult);
722 nRemaining -= nOldLen;
723 if (nRemaining > 0)
724 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1);
725 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen);
726 pszResult = pszNext + nNewLen;
727 nCount++;
728 }
729
730 CThisSimpleString::ReleaseBufferSetLength(nResultLength);
731
732 return nCount;
733 }
734
735 int Replace(XCHAR chOld, XCHAR chNew)
736 {
737 PCXSTR pszString = CThisSimpleString::GetString();
738 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld);
739 if (!pszFirst)
740 return 0;
741
742 int nLength = CThisSimpleString::GetLength();
743 int nCount = 0;
744
745 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
746 pszFirst = pszBuffer + (pszFirst - pszString);
747 do {
748 *pszFirst = chNew;
749 ++nCount;
750 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld)));
751
752 CThisSimpleString::ReleaseBufferSetLength(nLength);
753 return nCount;
754 }
755
756
757 static PCXSTR DefaultTrimChars()
758 {
759 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 };
760 return str;
761 }
762
763
764 CStringT& TrimLeft()
765 {
766 return TrimLeft(DefaultTrimChars());
767 }
768
769 CStringT& TrimLeft(XCHAR chTarget)
770 {
771 XCHAR str[2] = { chTarget, 0 };
772 return TrimLeft(str);
773 }
774
775 CStringT& TrimLeft(PCXSTR pszTargets)
776 {
777 int nLength = CThisSimpleString::GetLength();
778 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
779 int nCount = 0;
780
781 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount]))
782 nCount++;
783
784 if (nCount > 0)
785 {
786 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount);
787 nLength -= nCount;
788 }
789 CThisSimpleString::ReleaseBufferSetLength(nLength);
790
791 return *this;
792 }
793
794
795 CStringT& TrimRight()
796 {
797 return TrimRight(DefaultTrimChars());
798 }
799
800 CStringT& TrimRight(XCHAR chTarget)
801 {
802 XCHAR str[2] = { chTarget, 0 };
803 return TrimRight(str);
804 }
805
806 CStringT& TrimRight(PCXSTR pszTargets)
807 {
808 int nLength = CThisSimpleString::GetLength();
809 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
810
811 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1]))
812 nLength--;
813
814 CThisSimpleString::ReleaseBufferSetLength(nLength);
815
816 return *this;
817 }
818
819
820 CStringT& Trim()
821 {
822 return Trim(DefaultTrimChars());
823 }
824
825 CStringT& Trim(XCHAR chTarget)
826 {
827 XCHAR str[2] = { chTarget, 0 };
828 return Trim(str);
829 }
830
831 CStringT& Trim(PCXSTR pszTargets)
832 {
833 return TrimRight(pszTargets).TrimLeft(pszTargets);
834 }
835
836
837 BSTR AllocSysString() const
838 {
839 return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength());
840 }
841
842
843 };
844
845 } //namespace ATL
846
847 #endif