2e7460b799473283007109f3de33bde3e829f186
[reactos.git] / reactos / 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 template<class StringTraits_>
323 CStringT(_In_ const CStringT<YCHAR, StringTraits_> & strSrc) :
324 CThisSimpleString(StringTraits::GetDefaultManager())
325 {
326 *this = static_cast<const YCHAR*>(strSrc);
327 }
328
329 CStringT(_In_opt_z_ const XCHAR* pszSrc) :
330 CThisSimpleString( StringTraits::GetDefaultManager() )
331 {
332 // FIXME: Check whether pszSrc is not a resource string ID!
333 *this = pszSrc;
334 }
335
336 CStringT(
337 _In_opt_z_ const XCHAR* pszSrc,
338 _In_ IAtlStringMgr* pStringMgr) :
339 CThisSimpleString( pStringMgr )
340 {
341 // FIXME: Check whether pszSrc is not a resource string ID!
342 *this = pszSrc;
343 }
344
345 CStringT(_In_opt_z_ const YCHAR* pszSrc) :
346 CThisSimpleString( StringTraits::GetDefaultManager() )
347 {
348 // FIXME: Check whether pszSrc is not a resource string ID!
349 *this = pszSrc;
350 }
351
352 CStringT(
353 _In_opt_z_ const YCHAR* pszSrc,
354 _In_ IAtlStringMgr* pStringMgr) :
355 CThisSimpleString( pStringMgr )
356 {
357 // FIXME: Check whether pszSrc is not a resource string ID!
358 *this = pszSrc;
359 }
360
361 CStringT(
362 _In_reads_z_(nLength) const XCHAR* pch,
363 _In_ int nLength) :
364 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
365 {
366 }
367
368 CStringT(
369 _In_reads_z_(nLength) const YCHAR* pch,
370 _In_ int nLength) :
371 CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager())
372 {
373 }
374
375 CStringT& operator=(_In_ const CStringT& strSrc)
376 {
377 CThisSimpleString::operator=(strSrc);
378 return *this;
379 }
380
381 CStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
382 {
383 CThisSimpleString::operator=(pszSrc);
384 return *this;
385 }
386
387 CStringT& operator=(_In_opt_z_ PCYSTR pszSrc)
388 {
389 int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
390 if (length > 0)
391 {
392 PXSTR result = CThisSimpleString::GetBuffer(length);
393 StringTraits::ConvertToBaseType(result, length, pszSrc);
394 CThisSimpleString::ReleaseBufferSetLength(length);
395 }
396 else
397 {
398 CThisSimpleString::Empty();
399 }
400 return *this;
401 }
402
403 friend bool operator==(const CStringT& str1, const CStringT& str2) throw()
404 {
405 return str1.Compare(str2) == 0;
406 }
407
408 friend bool operator==(const CStringT& str1, PCXSTR psz2) throw()
409 {
410 return str1.Compare(psz2) == 0;
411 }
412
413 friend bool operator==(const CStringT& str1, PCYSTR psz2) throw()
414 {
415 CStringT tmp(psz2, str1.GetManager());
416 return tmp == str1;
417 }
418
419 friend bool operator==(const CStringT& str1, XCHAR ch2) throw()
420 {
421 return str1.GetLength() == 1 && str1[0] == ch2;
422 }
423
424 friend bool operator==(PCXSTR psz1, const CStringT& str2) throw()
425 {
426 return str2.Compare(psz1) == 0;
427 }
428
429 friend bool operator==(PCYSTR psz1, const CStringT& str2) throw()
430 {
431 CStringT tmp(psz1, str2.GetManager());
432 return tmp.Compare(str2) == 0;
433 }
434
435 friend bool operator==(XCHAR ch1, const CStringT& str2) throw()
436 {
437 return str2.GetLength() == 1 && str2[0] == ch1;
438 }
439
440 CStringT& operator+=(_In_ const CThisSimpleString& str)
441 {
442 CThisSimpleString::operator+=(str);
443 return *this;
444 }
445
446 CStringT& operator+=(_In_z_ PCXSTR pszSrc)
447 {
448 CThisSimpleString::operator+=(pszSrc);
449 return *this;
450 }
451
452 BOOL LoadString(_In_ UINT nID)
453 {
454 return LoadString(_AtlBaseModule.GetResourceInstance(), nID);
455 }
456
457 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
458 _In_ UINT nID)
459 {
460 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
461 if (pImage == NULL) return FALSE;
462
463 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
464 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
465 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
466 CThisSimpleString::ReleaseBufferSetLength(nLength);
467
468 return TRUE;
469 }
470
471 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar)
472 {
473 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
474
475 if (nLength > 0)
476 {
477 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
478 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
479 CThisSimpleString::ReleaseBuffer();
480 return TRUE;
481 }
482
483 CThisSimpleString::Empty();
484 return FALSE;
485 }
486
487 CStringT& MakeLower()
488 {
489 int nLength = CThisSimpleString::GetLength();
490 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
491
492 StringTraits::MakeLower(pszBuffer, nLength);
493 CThisSimpleString::ReleaseBufferSetLength(nLength);
494
495 return *this;
496 }
497
498 CStringT& MakeUpper()
499 {
500 int nLength = CThisSimpleString::GetLength();
501 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
502
503 StringTraits::MakeUpper(pszBuffer, nLength);
504 CThisSimpleString::ReleaseBufferSetLength(nLength);
505
506 return *this;
507 }
508
509 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw()
510 {
511 int nLength = CThisSimpleString::GetLength();
512
513 if (iStart >= nLength || iStart < 0)
514 return -1;
515
516 PCXSTR pszString = CThisSimpleString::GetString();
517 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub);
518
519 return pszResult ? ((int)(pszResult - pszString)) : -1;
520 }
521
522 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw()
523 {
524 int nLength = CThisSimpleString::GetLength();
525
526 if (iStart >= nLength || iStart < 0)
527 return -1;
528
529 PCXSTR pszString = CThisSimpleString::GetString();
530 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch);
531
532 return pszResult ? ((int)(pszResult - pszString)) : -1;
533 }
534
535 int FindOneOf(_In_ PCXSTR pszCharSet) const throw()
536 {
537 PCXSTR pszString = CThisSimpleString::GetString();
538 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet);
539
540 return pszResult ? ((int)(pszResult - pszString)) : -1;
541 }
542
543 int ReverseFind(_In_ XCHAR ch) const throw()
544 {
545 PCXSTR pszString = CThisSimpleString::GetString();
546 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch);
547
548 return pszResult ? ((int)(pszResult - pszString)) : -1;
549 }
550
551 int Compare(_In_z_ PCXSTR psz) const
552 {
553 return StringTraits::Compare(CThisSimpleString::GetString(), psz);
554 }
555
556
557 CStringT Mid(int iFirst, int nCount) const
558 {
559 int nLength = CThisSimpleString::GetLength();
560
561 if (iFirst < 0)
562 iFirst = 0;
563 if (nCount < 0)
564 nCount = 0;
565 if (iFirst > nLength)
566 iFirst = nLength;
567 if (iFirst + nCount > nLength)
568 nCount = nLength - iFirst;
569
570 return CStringT(CThisSimpleString::GetString() + iFirst, nCount);
571 }
572
573 CStringT Mid(int iFirst) const
574 {
575 int nLength = CThisSimpleString::GetLength();
576
577 if (iFirst < 0)
578 iFirst = 0;
579 if (iFirst > nLength)
580 iFirst = nLength;
581
582 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst);
583 }
584
585 CStringT Left(int nCount) const
586 {
587 int nLength = CThisSimpleString::GetLength();
588
589 if (nCount < 0)
590 nCount = 0;
591 if (nCount > nLength)
592 nCount = nLength;
593
594 return CStringT(CThisSimpleString::GetString(), nCount);
595 }
596
597 CStringT Right(int nCount) const
598 {
599 int nLength = CThisSimpleString::GetLength();
600
601 if (nCount < 0)
602 nCount = 0;
603 if (nCount > nLength)
604 nCount = nLength;
605
606 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount);
607 }
608
609
610 void __cdecl Format(UINT nFormatID, ...)
611 {
612 va_list args;
613 va_start(args, nFormatID);
614 CStringT formatString;
615 if (formatString.LoadString(nFormatID))
616 FormatV(formatString, args);
617 va_end(args);
618 }
619
620 void __cdecl Format(PCXSTR pszFormat, ...)
621 {
622 va_list args;
623 va_start(args, pszFormat);
624 FormatV(pszFormat, args);
625 va_end(args);
626 }
627
628 void FormatV(PCXSTR pszFormat, va_list args)
629 {
630 int nLength = StringTraits::FormatV(NULL, pszFormat, args);
631
632 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
633 StringTraits::FormatV(pszBuffer, pszFormat, args);
634 CThisSimpleString::ReleaseBufferSetLength(nLength);
635 }
636
637
638 int Replace(PCXSTR pszOld, PCXSTR pszNew)
639 {
640 PCXSTR pszString = CThisSimpleString::GetString();
641
642 const int nLength = CThisSimpleString::GetLength();
643 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld);
644 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew);
645 const int nDiff = nNewLen - nOldLen;
646 int nResultLength = nLength;
647
648 PCXSTR pszFound;
649 while ((pszFound = StringTraits::FindString(pszString, pszOld)))
650 {
651 nResultLength += nDiff;
652 pszString = pszFound + nOldLen;
653 }
654
655 if (pszString == CThisSimpleString::GetString())
656 return 0;
657
658 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength);
659 PXSTR pszNext;
660 int nCount = 0, nRemaining = nLength;
661 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld)))
662 {
663 nRemaining -= (pszNext - pszResult);
664 nRemaining -= nOldLen;
665 if (nRemaining > 0)
666 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1);
667 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen);
668 pszResult = pszNext + nNewLen;
669 nCount++;
670 }
671
672 CThisSimpleString::ReleaseBufferSetLength(nResultLength);
673
674 return nCount;
675 }
676
677 int Replace(XCHAR chOld, XCHAR chNew)
678 {
679 PCXSTR pszString = CThisSimpleString::GetString();
680 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld);
681 if (!pszFirst)
682 return 0;
683
684 int nLength = CThisSimpleString::GetLength();
685 int nCount = 0;
686
687 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
688 pszFirst = pszBuffer + (pszFirst - pszString);
689 do {
690 *pszFirst = chNew;
691 ++nCount;
692 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld)));
693
694 CThisSimpleString::ReleaseBufferSetLength(nLength);
695 return nCount;
696 }
697
698
699 static PCXSTR DefaultTrimChars()
700 {
701 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 };
702 return str;
703 }
704
705
706 CStringT& TrimLeft()
707 {
708 return TrimLeft(DefaultTrimChars());
709 }
710
711 CStringT& TrimLeft(XCHAR chTarget)
712 {
713 XCHAR str[2] = { chTarget, 0 };
714 return TrimLeft(str);
715 }
716
717 CStringT& TrimLeft(PCXSTR pszTargets)
718 {
719 int nLength = CThisSimpleString::GetLength();
720 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
721 int nCount = 0;
722
723 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount]))
724 nCount++;
725
726 if (nCount > 0)
727 {
728 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount);
729 nLength -= nCount;
730 }
731 CThisSimpleString::ReleaseBufferSetLength(nLength);
732
733 return *this;
734 }
735
736
737 CStringT& TrimRight()
738 {
739 return TrimRight(DefaultTrimChars());
740 }
741
742 CStringT& TrimRight(XCHAR chTarget)
743 {
744 XCHAR str[2] = { chTarget, 0 };
745 return TrimRight(str);
746 }
747
748 CStringT& TrimRight(PCXSTR pszTargets)
749 {
750 int nLength = CThisSimpleString::GetLength();
751 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
752
753 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1]))
754 nLength--;
755
756 CThisSimpleString::ReleaseBufferSetLength(nLength);
757
758 return *this;
759 }
760
761
762 CStringT& Trim()
763 {
764 return Trim(DefaultTrimChars());
765 }
766
767 CStringT& Trim(XCHAR chTarget)
768 {
769 XCHAR str[2] = { chTarget, 0 };
770 return Trim(str);
771 }
772
773 CStringT& Trim(PCXSTR pszTargets)
774 {
775 return TrimRight(pszTargets).TrimLeft(pszTargets);
776 }
777
778
779 };
780
781 } //namespace ATL
782
783 #endif