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