[ATL] Add CComBSTR.Attach
[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 FormatV(
137 _In_opt_z_ LPWSTR pszDest,
138 _In_z_ LPCWSTR pszFormat,
139 _In_ va_list args)
140 {
141 if (pszDest == NULL)
142 return ::_vscwprintf(pszFormat, args);
143 return ::vswprintf(pszDest, pszFormat, args);
144 }
145
146 };
147
148
149 // Template specialization
150
151 template<>
152 class ChTraitsCRT<char> : public ChTraitsBase<char>
153 {
154 public:
155
156 static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
157 {
158 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
159 }
160
161 static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw()
162 {
163 if (pszSource == NULL) return 0;
164 return static_cast<int>(strlen(pszSource));
165 }
166
167 static int __cdecl GetBaseTypeLength(
168 _In_reads_(nLength) LPCWSTR pszSource,
169 _In_ int nLength) throw()
170 {
171 return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL);
172 }
173
174 static int __cdecl GetBaseTypeLength(
175 _In_reads_(nLength) LPCSTR pszSource,
176 _In_ int nLength) throw()
177 {
178 return nLength;
179 }
180
181 static void __cdecl ConvertToBaseType(
182 _Out_writes_(nDestLength) LPSTR pszDest,
183 _In_ int nDestLength,
184 _In_ LPCWSTR pszSrc,
185 _In_ int nSrcLength = -1)
186 {
187 if (nSrcLength == -1)
188 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
189
190 ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL);
191 }
192
193 static void __cdecl ConvertToBaseType(
194 _Out_writes_(nDestLength) LPSTR pszDest,
195 _In_ int nDestLength,
196 _In_ LPCSTR pszSrc,
197 _In_ int nSrcLength = -1)
198 {
199 if (nSrcLength == -1)
200 nSrcLength = 1 + GetBaseTypeLength(pszSrc);
201
202 memcpy(pszDest, pszSrc, nSrcLength);
203 }
204
205 static void __cdecl MakeLower(
206 _Out_writes_(nSrcLength) LPSTR pszSource,
207 _In_ int nSrcLength)
208 {
209 ::CharLowerBuffA(pszSource, nSrcLength);
210 }
211
212 static DWORD GetEnvironmentVariable(
213 _In_z_ LPCSTR pszVar,
214 _Out_writes_opt_(nBufLength) LPSTR pszBuf,
215 _In_opt_ int nBufLength)
216 {
217 return ::GetEnvironmentVariableA(pszVar, pszBuf, nBufLength);
218 }
219
220 static void __cdecl MakeUpper(
221 _Out_writes_(nSrcLength) LPSTR pszSource,
222 _In_ int nSrcLength)
223 {
224 ::CharUpperBuffA(pszSource, nSrcLength);
225 }
226
227 static LPSTR __cdecl FindString(
228 _In_z_ LPCSTR pszSource,
229 _In_z_ LPCSTR pszSub)
230 {
231 return ::strstr(pszSource, pszSub);
232 }
233
234 static LPSTR __cdecl FindChar(
235 _In_z_ LPCSTR pszSource,
236 _In_ CHAR ch)
237 {
238 return ::strchr(pszSource, ch);
239 }
240
241 static LPSTR __cdecl FindCharReverse(
242 _In_z_ LPCSTR pszSource,
243 _In_ CHAR ch)
244 {
245 return ::strrchr(pszSource, ch);
246 }
247
248 static LPSTR __cdecl FindOneOf(
249 _In_z_ LPCSTR pszSource,
250 _In_z_ LPCSTR pszCharSet)
251 {
252 return ::strpbrk(pszSource, pszCharSet);
253 }
254
255 static int __cdecl Compare(
256 _In_z_ LPCSTR psz1,
257 _In_z_ LPCSTR psz2)
258 {
259 return ::strcmp(psz1, psz2);
260 }
261
262 static int __cdecl FormatV(
263 _In_opt_z_ LPSTR pszDest,
264 _In_z_ LPCSTR pszFormat,
265 _In_ va_list args)
266 {
267 if (pszDest == NULL)
268 return ::_vscprintf(pszFormat, args);
269 return ::vsprintf(pszDest, pszFormat, args);
270 }
271
272 };
273
274
275 namespace _CSTRING_IMPL_
276 {
277 template <typename _CharType, class StringTraits>
278 struct _MFCDLLTraitsCheck
279 {
280 const static bool c_bIsMFCDLLTraits = false;
281 };
282 }
283
284
285 // TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined.
286
287 template <typename BaseType, class StringTraits>
288 class CStringT :
289 public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
290 {
291 public:
292 typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
293 typedef StringTraits StrTraits;
294 typedef typename CThisSimpleString::XCHAR XCHAR;
295 typedef typename CThisSimpleString::PXSTR PXSTR;
296 typedef typename CThisSimpleString::PCXSTR PCXSTR;
297 typedef typename CThisSimpleString::YCHAR YCHAR;
298 typedef typename CThisSimpleString::PYSTR PYSTR;
299 typedef typename CThisSimpleString::PCYSTR PCYSTR;
300
301 public:
302 CStringT() throw() :
303 CThisSimpleString(StringTraits::GetDefaultManager())
304 {
305 }
306
307 explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
308 CThisSimpleString(pStringMgr)
309 {
310 }
311
312 static void __cdecl Construct(_In_ CStringT* pString)
313 {
314 new(pString) CStringT;
315 }
316
317 CStringT(_In_ const CStringT& strSrc) :
318 CThisSimpleString(strSrc)
319 {
320 }
321
322 CStringT(_In_ const CThisSimpleString& strSrc) :
323 CThisSimpleString(strSrc)
324 {
325 }
326
327 template<class StringTraits_>
328 CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) :
329 CThisSimpleString(StringTraits::GetDefaultManager())
330 {
331 *this = static_cast<const YCHAR*>(strSrc);
332 }
333
334 protected:
335 /* helper function */
336 template <typename T_CHAR>
337 void LoadFromPtr_(_In_opt_z_ const T_CHAR* pszSrc)
338 {
339 if (pszSrc == NULL)
340 return;
341 if (IS_INTRESOURCE(pszSrc))
342 LoadString(LOWORD(pszSrc));
343 else
344 *this = pszSrc;
345 }
346
347 public:
348 CStringT(_In_opt_z_ const XCHAR* pszSrc) :
349 CThisSimpleString(StringTraits::GetDefaultManager())
350 {
351 LoadFromPtr_(pszSrc);
352 }
353
354 CStringT(_In_opt_z_ const XCHAR* pszSrc,
355 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr)
356 {
357 LoadFromPtr_(pszSrc);
358 }
359
360 CStringT(_In_opt_z_ const YCHAR* pszSrc) :
361 CThisSimpleString(StringTraits::GetDefaultManager())
362 {
363 LoadFromPtr_(pszSrc);
364 }
365
366 CStringT(_In_opt_z_ const YCHAR* pszSrc,
367 _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr)
368 {
369 LoadFromPtr_(pszSrc);
370 }
371
372 CStringT(_In_reads_z_(nLength) const XCHAR* pch,
373 _In_ int nLength) :
374 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
375 {
376 }
377
378 CStringT(_In_reads_z_(nLength) const YCHAR* pch,
379 _In_ int nLength) :
380 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
381 {
382 }
383
384 CStringT& operator=(_In_ const CStringT& strSrc)
385 {
386 CThisSimpleString::operator=(strSrc);
387 return *this;
388 }
389
390 CStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
391 {
392 CThisSimpleString::operator=(pszSrc);
393 return *this;
394 }
395
396 CStringT& operator=(_In_opt_z_ PCYSTR pszSrc)
397 {
398 int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
399 if (length > 0)
400 {
401 PXSTR result = CThisSimpleString::GetBuffer(length);
402 StringTraits::ConvertToBaseType(result, length, pszSrc);
403 CThisSimpleString::ReleaseBufferSetLength(length);
404 }
405 else
406 {
407 CThisSimpleString::Empty();
408 }
409 return *this;
410 }
411
412 CStringT& operator=(_In_ const CThisSimpleString &strSrc)
413 {
414 CThisSimpleString::operator=(strSrc);
415 return *this;
416 }
417
418 friend bool operator==(const CStringT& str1, const CStringT& str2) throw()
419 {
420 return str1.Compare(str2) == 0;
421 }
422
423 friend bool operator==(const CStringT& str1, PCXSTR psz2) throw()
424 {
425 return str1.Compare(psz2) == 0;
426 }
427
428 friend bool operator==(const CStringT& str1, PCYSTR psz2) throw()
429 {
430 CStringT tmp(psz2, str1.GetManager());
431 return tmp.Compare(str1) == 0;
432 }
433
434 friend bool operator==(const CStringT& str1, XCHAR ch2) throw()
435 {
436 return str1.GetLength() == 1 && str1[0] == ch2;
437 }
438
439 friend bool operator==(PCXSTR psz1, const CStringT& str2) throw()
440 {
441 return str2.Compare(psz1) == 0;
442 }
443
444 friend bool operator==(PCYSTR psz1, const CStringT& str2) throw()
445 {
446 CStringT tmp(psz1, str2.GetManager());
447 return tmp.Compare(str2) == 0;
448 }
449
450 friend bool operator==(XCHAR ch1, const CStringT& str2) throw()
451 {
452 return str2.GetLength() == 1 && str2[0] == ch1;
453 }
454
455 CStringT& operator+=(_In_ const CThisSimpleString& str)
456 {
457 CThisSimpleString::operator+=(str);
458 return *this;
459 }
460
461 CStringT& operator+=(_In_z_ PCXSTR pszSrc)
462 {
463 CThisSimpleString::operator+=(pszSrc);
464 return *this;
465 }
466
467 CStringT& operator+=(_In_ XCHAR ch)
468 {
469 CThisSimpleString::operator+=(ch);
470 return *this;
471 }
472
473 BOOL LoadString(_In_ UINT nID)
474 {
475 return LoadString(_AtlBaseModule.GetResourceInstance(), nID);
476 }
477
478 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
479 _In_ UINT nID)
480 {
481 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
482 if (pImage == NULL) return FALSE;
483
484 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
485 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
486 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
487 CThisSimpleString::ReleaseBufferSetLength(nLength);
488
489 return TRUE;
490 }
491
492 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar)
493 {
494 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
495
496 if (nLength > 0)
497 {
498 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
499 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
500 CThisSimpleString::ReleaseBuffer();
501 return TRUE;
502 }
503
504 CThisSimpleString::Empty();
505 return FALSE;
506 }
507
508 CStringT& MakeLower()
509 {
510 int nLength = CThisSimpleString::GetLength();
511 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
512
513 StringTraits::MakeLower(pszBuffer, nLength);
514 CThisSimpleString::ReleaseBufferSetLength(nLength);
515
516 return *this;
517 }
518
519 CStringT& MakeUpper()
520 {
521 int nLength = CThisSimpleString::GetLength();
522 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
523
524 StringTraits::MakeUpper(pszBuffer, nLength);
525 CThisSimpleString::ReleaseBufferSetLength(nLength);
526
527 return *this;
528 }
529
530 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw()
531 {
532 int nLength = CThisSimpleString::GetLength();
533
534 if (iStart >= nLength || iStart < 0)
535 return -1;
536
537 PCXSTR pszString = CThisSimpleString::GetString();
538 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub);
539
540 return pszResult ? ((int)(pszResult - pszString)) : -1;
541 }
542
543 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw()
544 {
545 int nLength = CThisSimpleString::GetLength();
546
547 if (iStart >= nLength || iStart < 0)
548 return -1;
549
550 PCXSTR pszString = CThisSimpleString::GetString();
551 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch);
552
553 return pszResult ? ((int)(pszResult - pszString)) : -1;
554 }
555
556 int FindOneOf(_In_ PCXSTR pszCharSet) const throw()
557 {
558 PCXSTR pszString = CThisSimpleString::GetString();
559 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet);
560
561 return pszResult ? ((int)(pszResult - pszString)) : -1;
562 }
563
564 int ReverseFind(_In_ XCHAR ch) const throw()
565 {
566 PCXSTR pszString = CThisSimpleString::GetString();
567 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch);
568
569 return pszResult ? ((int)(pszResult - pszString)) : -1;
570 }
571
572 int Compare(_In_z_ PCXSTR psz) const
573 {
574 return StringTraits::Compare(CThisSimpleString::GetString(), psz);
575 }
576
577
578 CStringT Mid(int iFirst, int nCount) const
579 {
580 int nLength = CThisSimpleString::GetLength();
581
582 if (iFirst < 0)
583 iFirst = 0;
584 if (nCount < 0)
585 nCount = 0;
586 if (iFirst > nLength)
587 iFirst = nLength;
588 if (iFirst + nCount > nLength)
589 nCount = nLength - iFirst;
590
591 return CStringT(CThisSimpleString::GetString() + iFirst, nCount);
592 }
593
594 CStringT Mid(int iFirst) const
595 {
596 int nLength = CThisSimpleString::GetLength();
597
598 if (iFirst < 0)
599 iFirst = 0;
600 if (iFirst > nLength)
601 iFirst = nLength;
602
603 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst);
604 }
605
606 CStringT Left(int nCount) const
607 {
608 int nLength = CThisSimpleString::GetLength();
609
610 if (nCount < 0)
611 nCount = 0;
612 if (nCount > nLength)
613 nCount = nLength;
614
615 return CStringT(CThisSimpleString::GetString(), nCount);
616 }
617
618 CStringT Right(int nCount) const
619 {
620 int nLength = CThisSimpleString::GetLength();
621
622 if (nCount < 0)
623 nCount = 0;
624 if (nCount > nLength)
625 nCount = nLength;
626
627 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount);
628 }
629
630
631 void __cdecl Format(UINT nFormatID, ...)
632 {
633 va_list args;
634 va_start(args, nFormatID);
635 CStringT formatString;
636 if (formatString.LoadString(nFormatID))
637 FormatV(formatString, args);
638 va_end(args);
639 }
640
641 void __cdecl Format(PCXSTR pszFormat, ...)
642 {
643 va_list args;
644 va_start(args, pszFormat);
645 FormatV(pszFormat, args);
646 va_end(args);
647 }
648
649 void FormatV(PCXSTR pszFormat, va_list args)
650 {
651 int nLength = StringTraits::FormatV(NULL, pszFormat, args);
652
653 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
654 StringTraits::FormatV(pszBuffer, pszFormat, args);
655 CThisSimpleString::ReleaseBufferSetLength(nLength);
656 }
657
658
659 int Replace(PCXSTR pszOld, PCXSTR pszNew)
660 {
661 PCXSTR pszString = CThisSimpleString::GetString();
662
663 const int nLength = CThisSimpleString::GetLength();
664 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld);
665 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew);
666 const int nDiff = nNewLen - nOldLen;
667 int nResultLength = nLength;
668
669 PCXSTR pszFound;
670 while ((pszFound = StringTraits::FindString(pszString, pszOld)))
671 {
672 nResultLength += nDiff;
673 pszString = pszFound + nOldLen;
674 }
675
676 if (pszString == CThisSimpleString::GetString())
677 return 0;
678
679 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength);
680 PXSTR pszNext;
681 int nCount = 0, nRemaining = nLength;
682 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld)))
683 {
684 nRemaining -= (pszNext - pszResult);
685 nRemaining -= nOldLen;
686 if (nRemaining > 0)
687 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1);
688 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen);
689 pszResult = pszNext + nNewLen;
690 nCount++;
691 }
692
693 CThisSimpleString::ReleaseBufferSetLength(nResultLength);
694
695 return nCount;
696 }
697
698 int Replace(XCHAR chOld, XCHAR chNew)
699 {
700 PCXSTR pszString = CThisSimpleString::GetString();
701 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld);
702 if (!pszFirst)
703 return 0;
704
705 int nLength = CThisSimpleString::GetLength();
706 int nCount = 0;
707
708 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
709 pszFirst = pszBuffer + (pszFirst - pszString);
710 do {
711 *pszFirst = chNew;
712 ++nCount;
713 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld)));
714
715 CThisSimpleString::ReleaseBufferSetLength(nLength);
716 return nCount;
717 }
718
719
720 static PCXSTR DefaultTrimChars()
721 {
722 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 };
723 return str;
724 }
725
726
727 CStringT& TrimLeft()
728 {
729 return TrimLeft(DefaultTrimChars());
730 }
731
732 CStringT& TrimLeft(XCHAR chTarget)
733 {
734 XCHAR str[2] = { chTarget, 0 };
735 return TrimLeft(str);
736 }
737
738 CStringT& TrimLeft(PCXSTR pszTargets)
739 {
740 int nLength = CThisSimpleString::GetLength();
741 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
742 int nCount = 0;
743
744 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount]))
745 nCount++;
746
747 if (nCount > 0)
748 {
749 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount);
750 nLength -= nCount;
751 }
752 CThisSimpleString::ReleaseBufferSetLength(nLength);
753
754 return *this;
755 }
756
757
758 CStringT& TrimRight()
759 {
760 return TrimRight(DefaultTrimChars());
761 }
762
763 CStringT& TrimRight(XCHAR chTarget)
764 {
765 XCHAR str[2] = { chTarget, 0 };
766 return TrimRight(str);
767 }
768
769 CStringT& TrimRight(PCXSTR pszTargets)
770 {
771 int nLength = CThisSimpleString::GetLength();
772 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
773
774 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1]))
775 nLength--;
776
777 CThisSimpleString::ReleaseBufferSetLength(nLength);
778
779 return *this;
780 }
781
782
783 CStringT& Trim()
784 {
785 return Trim(DefaultTrimChars());
786 }
787
788 CStringT& Trim(XCHAR chTarget)
789 {
790 XCHAR str[2] = { chTarget, 0 };
791 return Trim(str);
792 }
793
794 CStringT& Trim(PCXSTR pszTargets)
795 {
796 return TrimRight(pszTargets).TrimLeft(pszTargets);
797 }
798
799
800 };
801
802 } //namespace ATL
803
804 #endif