a8918b09617fd2c172def75e59efce5d79a3910e
[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 BOOL LoadString(_In_ UINT nID)
457 {
458 return LoadString(_AtlBaseModule.GetResourceInstance(), nID);
459 }
460
461 _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
462 _In_ UINT nID)
463 {
464 const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
465 if (pImage == NULL) return FALSE;
466
467 int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
468 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
469 StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
470 CThisSimpleString::ReleaseBufferSetLength(nLength);
471
472 return TRUE;
473 }
474
475 BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar)
476 {
477 int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
478
479 if (nLength > 0)
480 {
481 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
482 StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
483 CThisSimpleString::ReleaseBuffer();
484 return TRUE;
485 }
486
487 CThisSimpleString::Empty();
488 return FALSE;
489 }
490
491 CStringT& MakeLower()
492 {
493 int nLength = CThisSimpleString::GetLength();
494 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
495
496 StringTraits::MakeLower(pszBuffer, nLength);
497 CThisSimpleString::ReleaseBufferSetLength(nLength);
498
499 return *this;
500 }
501
502 CStringT& MakeUpper()
503 {
504 int nLength = CThisSimpleString::GetLength();
505 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
506
507 StringTraits::MakeUpper(pszBuffer, nLength);
508 CThisSimpleString::ReleaseBufferSetLength(nLength);
509
510 return *this;
511 }
512
513 int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw()
514 {
515 int nLength = CThisSimpleString::GetLength();
516
517 if (iStart >= nLength || iStart < 0)
518 return -1;
519
520 PCXSTR pszString = CThisSimpleString::GetString();
521 PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub);
522
523 return pszResult ? ((int)(pszResult - pszString)) : -1;
524 }
525
526 int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw()
527 {
528 int nLength = CThisSimpleString::GetLength();
529
530 if (iStart >= nLength || iStart < 0)
531 return -1;
532
533 PCXSTR pszString = CThisSimpleString::GetString();
534 PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch);
535
536 return pszResult ? ((int)(pszResult - pszString)) : -1;
537 }
538
539 int FindOneOf(_In_ PCXSTR pszCharSet) const throw()
540 {
541 PCXSTR pszString = CThisSimpleString::GetString();
542 PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet);
543
544 return pszResult ? ((int)(pszResult - pszString)) : -1;
545 }
546
547 int ReverseFind(_In_ XCHAR ch) const throw()
548 {
549 PCXSTR pszString = CThisSimpleString::GetString();
550 PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch);
551
552 return pszResult ? ((int)(pszResult - pszString)) : -1;
553 }
554
555 int Compare(_In_z_ PCXSTR psz) const
556 {
557 return StringTraits::Compare(CThisSimpleString::GetString(), psz);
558 }
559
560
561 CStringT Mid(int iFirst, int nCount) const
562 {
563 int nLength = CThisSimpleString::GetLength();
564
565 if (iFirst < 0)
566 iFirst = 0;
567 if (nCount < 0)
568 nCount = 0;
569 if (iFirst > nLength)
570 iFirst = nLength;
571 if (iFirst + nCount > nLength)
572 nCount = nLength - iFirst;
573
574 return CStringT(CThisSimpleString::GetString() + iFirst, nCount);
575 }
576
577 CStringT Mid(int iFirst) const
578 {
579 int nLength = CThisSimpleString::GetLength();
580
581 if (iFirst < 0)
582 iFirst = 0;
583 if (iFirst > nLength)
584 iFirst = nLength;
585
586 return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst);
587 }
588
589 CStringT Left(int nCount) const
590 {
591 int nLength = CThisSimpleString::GetLength();
592
593 if (nCount < 0)
594 nCount = 0;
595 if (nCount > nLength)
596 nCount = nLength;
597
598 return CStringT(CThisSimpleString::GetString(), nCount);
599 }
600
601 CStringT Right(int nCount) const
602 {
603 int nLength = CThisSimpleString::GetLength();
604
605 if (nCount < 0)
606 nCount = 0;
607 if (nCount > nLength)
608 nCount = nLength;
609
610 return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount);
611 }
612
613
614 void __cdecl Format(UINT nFormatID, ...)
615 {
616 va_list args;
617 va_start(args, nFormatID);
618 CStringT formatString;
619 if (formatString.LoadString(nFormatID))
620 FormatV(formatString, args);
621 va_end(args);
622 }
623
624 void __cdecl Format(PCXSTR pszFormat, ...)
625 {
626 va_list args;
627 va_start(args, pszFormat);
628 FormatV(pszFormat, args);
629 va_end(args);
630 }
631
632 void FormatV(PCXSTR pszFormat, va_list args)
633 {
634 int nLength = StringTraits::FormatV(NULL, pszFormat, args);
635
636 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
637 StringTraits::FormatV(pszBuffer, pszFormat, args);
638 CThisSimpleString::ReleaseBufferSetLength(nLength);
639 }
640
641
642 int Replace(PCXSTR pszOld, PCXSTR pszNew)
643 {
644 PCXSTR pszString = CThisSimpleString::GetString();
645
646 const int nLength = CThisSimpleString::GetLength();
647 const int nOldLen = StringTraits::GetBaseTypeLength(pszOld);
648 const int nNewLen = StringTraits::GetBaseTypeLength(pszNew);
649 const int nDiff = nNewLen - nOldLen;
650 int nResultLength = nLength;
651
652 PCXSTR pszFound;
653 while ((pszFound = StringTraits::FindString(pszString, pszOld)))
654 {
655 nResultLength += nDiff;
656 pszString = pszFound + nOldLen;
657 }
658
659 if (pszString == CThisSimpleString::GetString())
660 return 0;
661
662 PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength);
663 PXSTR pszNext;
664 int nCount = 0, nRemaining = nLength;
665 while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld)))
666 {
667 nRemaining -= (pszNext - pszResult);
668 nRemaining -= nOldLen;
669 if (nRemaining > 0)
670 CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1);
671 CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen);
672 pszResult = pszNext + nNewLen;
673 nCount++;
674 }
675
676 CThisSimpleString::ReleaseBufferSetLength(nResultLength);
677
678 return nCount;
679 }
680
681 int Replace(XCHAR chOld, XCHAR chNew)
682 {
683 PCXSTR pszString = CThisSimpleString::GetString();
684 PXSTR pszFirst = StringTraits::FindChar(pszString, chOld);
685 if (!pszFirst)
686 return 0;
687
688 int nLength = CThisSimpleString::GetLength();
689 int nCount = 0;
690
691 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
692 pszFirst = pszBuffer + (pszFirst - pszString);
693 do {
694 *pszFirst = chNew;
695 ++nCount;
696 } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld)));
697
698 CThisSimpleString::ReleaseBufferSetLength(nLength);
699 return nCount;
700 }
701
702
703 static PCXSTR DefaultTrimChars()
704 {
705 static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 };
706 return str;
707 }
708
709
710 CStringT& TrimLeft()
711 {
712 return TrimLeft(DefaultTrimChars());
713 }
714
715 CStringT& TrimLeft(XCHAR chTarget)
716 {
717 XCHAR str[2] = { chTarget, 0 };
718 return TrimLeft(str);
719 }
720
721 CStringT& TrimLeft(PCXSTR pszTargets)
722 {
723 int nLength = CThisSimpleString::GetLength();
724 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
725 int nCount = 0;
726
727 while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount]))
728 nCount++;
729
730 if (nCount > 0)
731 {
732 CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount);
733 nLength -= nCount;
734 }
735 CThisSimpleString::ReleaseBufferSetLength(nLength);
736
737 return *this;
738 }
739
740
741 CStringT& TrimRight()
742 {
743 return TrimRight(DefaultTrimChars());
744 }
745
746 CStringT& TrimRight(XCHAR chTarget)
747 {
748 XCHAR str[2] = { chTarget, 0 };
749 return TrimRight(str);
750 }
751
752 CStringT& TrimRight(PCXSTR pszTargets)
753 {
754 int nLength = CThisSimpleString::GetLength();
755 PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength);
756
757 while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1]))
758 nLength--;
759
760 CThisSimpleString::ReleaseBufferSetLength(nLength);
761
762 return *this;
763 }
764
765
766 CStringT& Trim()
767 {
768 return Trim(DefaultTrimChars());
769 }
770
771 CStringT& Trim(XCHAR chTarget)
772 {
773 XCHAR str[2] = { chTarget, 0 };
774 return Trim(str);
775 }
776
777 CStringT& Trim(PCXSTR pszTargets)
778 {
779 return TrimRight(pszTargets).TrimLeft(pszTargets);
780 }
781
782
783 };
784
785 } //namespace ATL
786
787 #endif