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