f9b26c49360458948313863cd9acfd328b580c47
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/framedyn/chstring.cpp
5 * PURPOSE: CHString class implementation
6 * PROGRAMMERS: Pierre Schweitzer (pierre@reactos.org)
8 * NOTE: This implementation is BROKEN on PURPOSE
9 * The CHString is a mix between std::string and
10 * UNICODE_STRING. It appears that basically it takes only
11 * the worse from both approaches.
12 * I've copied the behavior and implementation of Windows 2k3 even if
13 * it implies unsafe, wrong or unefficient methods.
14 * Note that the string at m_pchData might not be null terminated!
15 * Also, important note, two (or even more) CHString instances might
16 * have the same m_pchData object! Never forget that while modifying
17 * a string. You might be modifying the string for everyone.
18 * This is why a protected method is being used in the code: CopyBeforeWrite
19 * It copies source first, to ensure we only modify current string
20 * Side note, all the sizes are actually a number of chars. Only the size
21 * for implementation is the number of bytes
22 * Now, you know why this class is deprecated and shouldn't be used
25 /* INCLUDES ******************************************************************/
31 /* PRIVATE FUNCTIONS *********************************************************/
33 // This is the empty string that defaults strings without text
34 // This is unsafe. This string show be LPCWSTR
35 // However we have to assign it to LPWSTR var. So, let's ignore about const,
36 // as MS does. Normally we check in our code that we don't overwrite this string.
37 LPWSTR afxPchNil
= (LPWSTR
)L
"\0";
38 // This is the data that are matching the null string upper
39 CHStringData afxNullData
= {0, 0, 0};
40 // Exception we may throw in case of allocation failure
41 CHeap_Exception
HeapException(CHeap_Exception::E_ALLOCATION_ERROR
);
43 // Our own delete operator
44 // It is here basically because MS guys don't known about set_new_handler()
46 void operator delete(void* ptr
)
48 // In Windows 2k3, they check for ptr being null.
49 // ISO, POSIX and even MSDN explains that it is allowed
50 // to call free with NULL pointer...
57 // Implement our own new operator so that we can throw our own exception in case
58 // of allocation failure.
59 // It could have been done using set_new_handler(), but well. MS guys didn't do it
60 // that way. So, let's mimic.
61 void* operator new(size_t uSize
)
65 Buffer
= malloc(uSize
);
74 // This is a char to wchar string conversion helper
75 int mbstowcsz(LPWSTR lpDest
, LPCSTR lpSrc
, int nLen
)
79 // If we have nothing to convert or if output doesn't exist, return
80 if (nLen
== 0 || lpDest
== 0)
85 // Then, simply convert
86 Conv
= MultiByteToWideChar(CP_ACP
, 0, lpSrc
, -1, lpDest
, nLen
);
87 // In case of conversion success, null terminate the string
96 /* PUBLIC FUNCTIONS **********************************************************/
103 // Set to empty string
104 m_pchData
= afxPchNil
;
110 CHString::CHString(WCHAR ch
, int nRepeat
) throw (CHeap_Exception
)
112 // Allow null initialize, in case something goes wrong
113 m_pchData
= afxPchNil
;
115 // If we have a char to insert
118 // Allocate a buffer big enough
119 AllocBuffer(nRepeat
);
120 // And if possible, repeat char
123 for (int i
= 0; i
< nRepeat
; ++i
)
134 CHString::CHString(LPCWSTR lpsz
) throw (CHeap_Exception
)
137 // Allow null initialize, in case something goes wrong
138 m_pchData
= afxPchNil
;
140 // If we have an input string
144 Len
= SafeStrlen(lpsz
);
145 // Then, allocate a big enough buffer and copy string
146 // Note that here, we don't null terminate the string...
150 wcsncpy(m_pchData
, lpsz
, Len
);
158 CHString::CHString(LPCWSTR lpch
, int nLength
) throw (CHeap_Exception
)
160 // Allow null initialize, in case something goes wrong
161 m_pchData
= afxPchNil
;
163 // In case we have a string with a len
164 if (lpch
!= 0 && nLength
!= 0)
166 // Just copy the string
167 AllocBuffer(nLength
);
168 wcsncpy(m_pchData
, lpch
, nLength
);
175 CHString::CHString(LPCSTR lpsz
) throw (CHeap_Exception
)
178 // Allow null initialize, in case something goes wrong
179 m_pchData
= afxPchNil
;
181 // If we have input string
188 // Allocate and convert the string
190 mbstowcsz(m_pchData
, lpsz
, Len
+ 1);
191 // Releasing buffer here is to allow to
192 // update the buffer size. We notify we're
193 // done with changing the string: recompute its
203 CHString::CHString(const unsigned char* lpsz
)
207 // And call operator= with const char*, easier
208 *this = (LPCSTR
)lpsz
;
214 CHString::CHString(const CHString
& stringSrc
)
216 // If we have currently no referenced string
217 if (stringSrc
.GetData()->nRefs
< 0)
219 // Ensure we have the null string
220 m_pchData
= afxPchNil
;
221 // And then call, the copy operator with input string
222 *this = stringSrc
.m_pchData
;
226 // Otherwise, just copy the input string
227 m_pchData
= stringSrc
.m_pchData
;
228 // And increment the number of references
229 InterlockedIncrement(&GetData()->nRefs
);
230 // The whole point here is: Am I forget to release the old
231 // data?! MS doesn't release it, but I guess we should...
238 CHString::~CHString()
240 // If we have a string
241 if (GetData() != &afxNullData
)
243 // Check whether it's still in use after we release it
244 if (InterlockedDecrement(&GetData()->nRefs
) == 0)
255 void CHString::AllocBeforeWrite(int nLen
) throw (CHeap_Exception
)
257 // In case we have several strings pointing to our memory zone
258 // Or we need bigger buffer than actual
259 if (GetData()->nRefs
> 1 || nLen
> GetData()->nAllocLength
)
262 // And allocate a new one which is big enough
271 void CHString::AllocBuffer(int nSize
) throw (CHeap_Exception
)
273 // Here we have to allocate a buffer for the string
274 // It actually consists in: CHStringData structure
275 // with a buffer big enough at its end to store the
279 // Null size is easy allocation
282 m_pchData
= afxPchNil
;
286 // We cannot allow negative sizes
289 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
295 RaiseException(STATUS_INTEGER_OVERFLOW
, EXCEPTION_NONCONTINUABLE
, 0, 0);
298 // Just allocate big enough buffer, using our own operator new
299 Data
= (CHStringData
*)operator new(nSize
* sizeof(WCHAR
) + sizeof(CHStringData
));
300 // In case Data is null, throw an exception
301 // Yes, this is stupid! Our operator new is already supposed to through an exception...
309 Data
->nDataLength
= nSize
;
310 Data
->nAllocLength
= nSize
;
313 // We only return the string
314 // We can find back data with some mathematics
315 m_pchData
= Data
->data();
321 void CHString::AllocCopy(CHString
& dest
, int nCopyLen
, int nCopyIndex
, int nExtraLen
) const throw (CHeap_Exception
)
323 // Once again, we cannot deal with negative lens
326 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
331 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
336 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
339 // In case what we have to copy is null-sized, just set empty string
340 if (nCopyLen
+ nExtraLen
== 0)
342 dest
.m_pchData
= afxPchNil
;
346 // Otherwise, allocate a buffer in new string which is big enough
347 // You can note that we absolutely don't check about any existing
348 // (referenced) buffer in dest. Actually, dest is to be EMPTY string.
349 // The whole point of this function is to initialize a virgin string by
350 // copying data from another. This is needed by Left/Mid/Right
351 dest
.AllocBuffer(nCopyLen
+ nExtraLen
);
352 // And copy our stuff in
353 wcsncpy(dest
.m_pchData
, m_pchData
+ nCopyIndex
, nCopyLen
);
359 BSTR
CHString::AllocSysString() const throw (CHeap_Exception
)
363 // Just allocate the string
364 SysString
= SysAllocStringLen(m_pchData
, GetData()->nDataLength
);
376 void CHString::AssignCopy(int nSrcLen
, LPCWSTR lpszSrcData
) throw (CHeap_Exception
)
378 // Don't allow negative len
381 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
384 // We will have to modify a string that might be shared, so duplicate it
385 // Ensuring it's big enough to contain our new stuff
386 AllocBeforeWrite(nSrcLen
);
393 // Just copy, write down new size, and ensure it's null terminated
394 wcsncpy(m_pchData
, lpszSrcData
, nSrcLen
);
395 GetData()->nDataLength
= nSrcLen
;
396 m_pchData
[nSrcLen
] = 0;
402 int CHString::Collate(LPCWSTR lpsz
) const
404 // Just call the deprecated function here - no matter we are null terminated
405 // Did you read my statement about how safe is this implementation?
406 return wcscoll(m_pchData
, lpsz
);
412 int CHString::Compare(LPCWSTR lpsz
) const
414 // Just call the deprecated function here - no matter we are null terminated
415 // Did you read my statement about how safe is this implementation?
416 return wcscmp(m_pchData
, lpsz
);
422 int CHString::CompareNoCase(LPCWSTR lpsz
) const
424 // Just call the deprecated function here - no matter we are null terminated
425 // Did you read my statement about how safe is this implementation?
426 return wcsicmp(m_pchData
, lpsz
);
432 void CHString::ConcatInPlace(int nSrcLen
, LPCWSTR lpszSrcData
)
434 // With null length, there's not that much to concat...
440 // Still no negative length
443 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
446 // Ensure we wouldn't overflow with the concat
447 if (GetData()->nDataLength
+ nSrcLen
> INT_MAX
)
449 RaiseException(STATUS_INTEGER_OVERFLOW
, EXCEPTION_NONCONTINUABLE
, 0, 0);
452 // In case we have to modify a shared string OR if it can't fit into current buffer...
453 if (GetData()->nRefs
> 1 || GetData()->nDataLength
+ nSrcLen
> GetData()->nAllocLength
)
455 // Allocate a new buffer! (without forgetting to release old one)
456 CHStringData
* OldData
= GetData();
458 // You remember about "InPlace" in the function's name?
460 ConcatCopy(GetData()->nDataLength
, m_pchData
, nSrcLen
, lpszSrcData
);
465 // Ensure we don't overflow
466 if (nSrcLen
> INT_MAX
)
468 RaiseException(STATUS_INTEGER_OVERFLOW
, EXCEPTION_NONCONTINUABLE
, 0, 0);
471 // Then, just copy and null terminate
472 wcsncpy(m_pchData
+ GetData()->nDataLength
, lpszSrcData
, nSrcLen
);
473 GetData()->nDataLength
+= nSrcLen
;
474 m_pchData
[GetData()->nDataLength
] = 0;
481 void CHString::ConcatCopy(int nSrc1Len
, LPCWSTR lpszSrc1Data
, int nSrc2Len
, LPCWSTR lpszSrc2Data
) throw (CHeap_Exception
)
485 if (nSrc1Len
< 0 || nSrc2Len
< 0)
487 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, 0);
490 // If both len are null, do nothing
491 TotalLen
= nSrc1Len
+ nSrc2Len
;
497 // Otherwise, allocate a new buffer to hold everything (caller will release previous buffer)
498 AllocBuffer(TotalLen
);
500 wcsncpy(m_pchData
, lpszSrc1Data
, nSrc1Len
);
501 wcsncpy(m_pchData
+ nSrc1Len
, lpszSrc2Data
, nSrc2Len
);
507 void CHString::CopyBeforeWrite() throw (CHeap_Exception
)
511 // First, we need to get reference count
512 // And we also need to save Data for later copy
515 if (Data
->nRefs
<= 1)
517 // If its not used, don't waste time to realloc, it will do the job
521 // Release current data - we are sure it won't be freed upon that point
522 // Thanks to the reference count check previously done
524 // Alloc new buffer and copy old data in it
525 AllocBuffer(Data
->nDataLength
);
526 wcsncpy(m_pchData
, Data
->data(), Data
->nDataLength
);
532 void CHString::Empty()
535 if (GetData()->nDataLength
== 0)
540 // Empty it easily given it's reference count
541 if (GetData()->nRefs
< 0)
547 // Otherwise, just release it
548 // It will set back this instance to afxPchNil
549 // while decreasing reference count
557 int CHString::Find(WCHAR ch
) const
561 // Let's use appropriate helper
562 Found
= wcschr(m_pchData
, ch
);
563 // We have to return a position, so compute it
566 return (Found
- m_pchData
);
569 // Otherwise, return no position
576 int CHString::Find(LPCWSTR lpszSub
) const
580 // Let's use appropriate helper
581 Found
= wcsstr(m_pchData
, lpszSub
);
582 // We have to return a position, so compute it
585 return (Found
- m_pchData
);
588 // Otherwise, return no position
595 int CHString::FindOneOf(LPCWSTR lpszCharSet
) const
599 // Let's use appropriate helper
600 Found
= wcspbrk(m_pchData
, lpszCharSet
);
601 // We have to return a position, so compute it
604 return (Found
- m_pchData
);
607 // Otherwise, return no position
614 void CHString::Format(UINT nFormatID
, ...) throw (CHeap_Exception
)
616 // Deprecated and not implemented any longer - well, this is its implementation
623 void CHString::Format(LPCWSTR lpszFormat
, ...) throw (CHeap_Exception
)
625 // Forward to FormatV
628 va_start(ArgsList
, lpszFormat
);
629 FormatV(lpszFormat
, ArgsList
);
636 void CHString::FormatMessageW(UINT nFormatID
, ...) throw (CHeap_Exception
)
638 // Deprecated and not implemented any longer - well, this is its implementation
645 void CHString::FormatMessageW(LPCWSTR lpszFormat
, ...) throw (CHeap_Exception
)
653 void CHString::FormatV(LPCWSTR lpszFormat
, va_list argList
)
661 void CHString::FreeExtra() throw (CHeap_Exception
)
663 CHStringData
* OldData
;
665 // No extra? Do nothing
666 if (GetData()->nDataLength
== GetData()->nAllocLength
)
673 // Allocate a new one, at the right size (with no place for \0 :-))
674 AllocBuffer(GetData()->nDataLength
);
675 // Copy old and release it
676 wcsncpy(m_pchData
, OldData
->data(), OldData
->nDataLength
);
683 int CHString::GetAllocLength() const
685 return GetData()->nAllocLength
;
691 WCHAR
CHString::GetAt(int nIndex
) const
693 // It's up to you to check the index!
694 return m_pchData
[nIndex
];
700 LPWSTR
CHString::GetBuffer(int nMinBufLength
) throw (CHeap_Exception
)
702 LPWSTR OldBuffer
= m_pchData
;
704 // We'll have to allocate a new buffer if it's not big enough
705 // or if it's shared by several strings
706 if (GetData()->nRefs
> 1 || GetData()->nAllocLength
< nMinBufLength
)
708 CHStringData
* OldData
= GetData();
709 int OldLen
= GetData()->nDataLength
;
711 // Ensure we can hold enough
712 if (OldLen
> nMinBufLength
)
714 nMinBufLength
= OldLen
;
717 // Allocate new buffer
718 AllocBuffer(nMinBufLength
);
720 wcsncpy(m_pchData
, OldBuffer
, OldLen
);
721 GetData()->nDataLength
= OldLen
;
727 // Weirdly, here Windows always returns the old buffer
728 // Which basically exposes a wrong buffer
735 LPWSTR
CHString::GetBufferSetLength(int nNewLength
) throw (CHeap_Exception
)
737 // Get a buffer big enough
738 // We don't care about the return, it will be set in the string
739 (void)GetBuffer(nNewLength
);
740 // Set length, null-terminate and return
741 GetData()->nDataLength
= nNewLength
;
742 m_pchData
[nNewLength
] = 0;
749 CHStringData
* CHString::GetData() const
751 // In case of empty string, return empty data
752 if (m_pchData
== afxPchNil
)
757 // Otherwise, do maths
758 return (CHStringData
*)((ULONG_PTR
)m_pchData
- sizeof(CHStringData
));
764 int CHString::GetLength() const
766 return GetData()->nDataLength
;
772 void CHString::Init()
774 m_pchData
= afxPchNil
;
780 BOOL
CHString::IsEmpty() const
782 return (GetData()->nDataLength
== 0);
788 CHString
CHString::Left(int nCount
) const throw (CHeap_Exception
)
792 // Validate input (we can't get more than what we have ;-))
795 if (nCount
> GetData()->nDataLength
)
797 nCount
= GetData()->nDataLength
;
801 AllocCopy(NewString
, nCount
, 0, 0);
809 int CHString::LoadStringW(UINT nID
) throw (CHeap_Exception
)
811 // Deprecated and not implemented any longer - well, this is its implementation
818 int CHString::LoadStringW(UINT nID
, LPWSTR lpszBuf
, UINT nMaxBuf
) throw (CHeap_Exception
)
820 // Deprecated and not implemented any longer - well, this is its implementation
827 LPWSTR
CHString::LockBuffer()
831 // The purpose here is basically to set the nRefs to max int
832 LockedBuffer
= GetBuffer(0);
833 GetData()->nRefs
= INT_MAX
;
841 void CHString::MakeLower() throw (CHeap_Exception
)
843 // We'll modify string, duplicate it first if needed
846 // Let's use appropriate helper
853 void CHString::MakeReverse() throw (CHeap_Exception
)
855 // We'll modify string, duplicate it first if needed
858 // Let's use appropriate helper
865 void CHString::MakeUpper() throw (CHeap_Exception
)
867 // We'll modify string, duplicate it first if needed
870 // Let's use appropriate helper
877 CHString
CHString::Mid(int nFirst
) const throw (CHeap_Exception
)
879 // Take string from nFirst up to the end
880 return Mid(nFirst
, GetData()->nDataLength
- nFirst
);
886 CHString
CHString::Mid(int nFirst
, int nCount
) const throw (CHeap_Exception
)
890 // Validate sizes first
901 // Ensure we don't go beyond the string
902 if (nFirst
+ nCount
> GetData()->nDataLength
)
904 nCount
= GetData()->nDataLength
- nFirst
;
907 // Also ensure we don't read beyond
908 // Yes, this should have been done before previous check
909 // MS does it that way
910 if (nFirst
> GetData()->nDataLength
)
915 AllocCopy(NewString
, nCount
, nFirst
, 0);
923 void CHString::Release()
925 // If null string, nothing to do
926 if (GetData() == &afxNullData
)
931 // Otherwise, decrement ref count and release if required
932 if (InterlockedDecrement(&GetData()->nRefs
) == 0)
937 // In all cases, caller doesn't want string anymore
938 // So, switch back to empty string
939 m_pchData
= afxPchNil
;
945 void CHString::Release(CHStringData
* pData
)
947 // If empty string, ignore
948 if (pData
== &afxNullData
)
953 // Otherwise, simply and free if needed
954 if (InterlockedDecrement(&pData
->nRefs
) == 0)
963 void CHString::ReleaseBuffer(int nNewLength
) throw (CHeap_Exception
)
967 // We'll modify buffer, so duplicate
970 // If no len provided, get one
971 if (nNewLength
== -1)
973 nNewLength
= wcslen(m_pchData
);
976 // Set appropriate size and null-terminate
978 Data
->nDataLength
= nNewLength
;
979 Data
->data()[nNewLength
] = 0;
985 int CHString::ReverseFind(WCHAR ch
) const
989 // Let's use appropriate helper
990 Last
= wcsrchr(m_pchData
, ch
);
991 // We have to return a position, so compute it
994 return (Last
- m_pchData
);
997 // Otherwise, return no position
1004 CHString
CHString::Right(int nCount
) const throw (CHeap_Exception
)
1008 // Validate input (we can't get more than what we have ;-))
1011 if (nCount
> GetData()->nDataLength
)
1013 nCount
= GetData()->nDataLength
;
1017 AllocCopy(NewString
, nCount
, GetData()->nDataLength
- nCount
, 0);
1025 int CHString::SafeStrlen(LPCWSTR lpsz
)
1027 // Check we have a string and then get its length
1033 // Of course, it's not safe at all in case string is not null-terminated.
1034 // Things that may happen given strings are not to be null-terminated
1036 return (int)wcslen(lpsz
);
1042 void CHString::SetAt(int nIndex
, WCHAR ch
) throw (CHeap_Exception
)
1046 m_pchData
[nIndex
] = ch
;
1052 CHString
CHString::SpanExcluding(LPCWSTR lpszCharSet
) const throw (CHeap_Exception
)
1056 // Get position and then, extract
1057 Count
= wcscspn(m_pchData
, lpszCharSet
);
1064 CHString
CHString::SpanIncluding(LPCWSTR lpszCharSet
) const throw (CHeap_Exception
)
1068 // Get position and then, extract
1069 Count
= wcsspn(m_pchData
, lpszCharSet
);
1076 void CHString::TrimLeft() throw (CHeap_Exception
)
1082 // We'll modify, so copy first
1085 // Start at the begin of the string
1086 CurrentChar
= m_pchData
;
1087 while (*CurrentChar
!= 0)
1089 // Browse string till we find something which is not a space
1090 if (!iswspace(*CurrentChar
))
1098 // Then, calculate new begin (easy) and new length
1100 NewBegin
= (CurrentChar
- m_pchData
);
1101 NewLength
= GetData()->nDataLength
- NewBegin
;
1102 memmove(m_pchData
, CurrentChar
, NewLength
* sizeof(WCHAR
));
1103 GetData()->nDataLength
= NewLength
;
1109 void CHString::TrimRight() throw (CHeap_Exception
)
1114 // We'll modify, so copy first
1117 // Start at the begin of the string -- WHAT?!
1118 // Yes, this algorithm is the same that MS is
1119 // using for its TrimRight.
1120 // It is highly unefficient. It would have been
1121 // easier to start at nDataLength and to get back to
1122 // the begin. Note that it would have been safer as
1123 // well, in case the caller is using non-null-terminated
1124 // strings. But, well...
1125 CurrentChar
= m_pchData
;
1127 while (*CurrentChar
!= 0)
1129 // If not a space, reset what we can trim
1130 if (!iswspace(*CurrentChar
))
1134 // If it is one, and the first of the spaces serie
1135 // Keep its position
1136 else if (CanBeEaten
== 0)
1138 CanBeEaten
= CurrentChar
;
1144 // If nothing to trim, quit
1145 if (CanBeEaten
== 0)
1150 // Otherwise, shorten the string
1151 GetData()->nDataLength
= (CanBeEaten
- m_pchData
);
1157 void CHString::UnlockBuffer()
1159 // Unlock means just put ref back to 1
1160 // It was previously set to MAX_INT
1161 if (GetData() != &afxNullData
)
1163 GetData()->nRefs
= 1;
1170 const CHString
& CHString::operator=(char ch
) throw (CHeap_Exception
)
1179 const CHString
& CHString::operator=(WCHAR ch
) throw (CHeap_Exception
)
1188 const CHString
& CHString::operator=(CHString
*p
) throw (CHeap_Exception
)
1197 const CHString
& CHString::operator=(LPCSTR lpsz
) throw (CHeap_Exception
)
1201 // If we have string, get its len
1211 // Do this call, even with null len, just to get empty string
1212 AllocBeforeWrite(Len
);
1220 mbstowcsz(m_pchData
, lpsz
, Len
+ 1);
1221 // Get new size and so on
1230 const CHString
& CHString::operator=(LPCWSTR lpsz
) throw (CHeap_Exception
)
1234 Len
= SafeStrlen(lpsz
);
1235 AssignCopy(Len
, lpsz
);
1243 const CHString
& CHString::operator=(const CHString
& stringSrc
) throw (CHeap_Exception
)
1245 // Don't copy string on itself
1246 if (&stringSrc
== this)
1251 // In case we don't have a referenced string here,
1252 // or if the other is not referenced, just copy here
1253 if ((GetData()->nRefs
< 0 && GetData() != &afxNullData
) ||
1254 stringSrc
.GetData()->nRefs
< 0)
1256 AssignCopy(stringSrc
.GetData()->nDataLength
, stringSrc
.m_pchData
);
1260 // Otherwise, release current buffer
1262 // And set buffer as stringSrc buffer
1263 // And increase its reference count
1264 m_pchData
= stringSrc
.m_pchData
;
1265 InterlockedIncrement(&GetData()->nRefs
);
1273 const CHString
& CHString::operator=(const unsigned char* lpsz
) throw (CHeap_Exception
)
1275 *this = (LPCSTR
)lpsz
;
1282 const CHString
& CHString::operator+=(char ch
) throw (CHeap_Exception
)
1291 const CHString
& CHString::operator+=(WCHAR ch
) throw (CHeap_Exception
)
1293 ConcatInPlace(1, &ch
);
1300 const CHString
& CHString::operator+=(LPCWSTR lpsz
) throw (CHeap_Exception
)
1304 Len
= SafeStrlen(lpsz
);
1305 ConcatInPlace(Len
, lpsz
);
1313 const CHString
& CHString::operator+=(const CHString
& string
) throw (CHeap_Exception
)
1315 ConcatInPlace(string
.GetData()->nDataLength
, string
.m_pchData
);
1323 WCHAR
CHString::operator[](int nIndex
) const
1325 return m_pchData
[nIndex
];
1331 CHString::operator LPWSTR()
1339 CHString WINAPI
operator+(WCHAR ch
, const CHString
& string
) throw (CHeap_Exception
)
1343 // Basically concat in a new string
1344 NewString
.ConcatCopy(1, &ch
, string
.GetData()->nDataLength
, string
.m_pchData
);
1352 CHString WINAPI
operator+(const CHString
& string
, WCHAR ch
) throw (CHeap_Exception
)
1356 // Basically concat in a new string
1357 NewString
.ConcatCopy(string
.GetData()->nDataLength
, string
.m_pchData
, 1, &ch
);
1365 CHString WINAPI
operator+(const CHString
& string
, LPCWSTR lpsz
) throw (CHeap_Exception
)
1370 // Get string length
1371 Len
= CHString::SafeStrlen(lpsz
);
1372 // And concat in new string
1373 NewString
.ConcatCopy(string
.GetData()->nDataLength
, string
.m_pchData
, Len
, lpsz
);
1381 CHString WINAPI
operator+(LPCWSTR lpsz
, const CHString
& string
) throw (CHeap_Exception
)
1386 // Get string length
1387 Len
= CHString::SafeStrlen(lpsz
);
1388 // And concat in new string
1389 NewString
.ConcatCopy(Len
, lpsz
, string
.GetData()->nDataLength
, string
.m_pchData
);
1397 CHString WINAPI
operator+(const CHString
& string1
, const CHString
& string2
) throw (CHeap_Exception
)
1401 // Basically concat in a new string
1402 NewString
.ConcatCopy(string1
.GetData()->nDataLength
, string1
.m_pchData
,
1403 string2
.GetData()->nDataLength
, string2
.m_pchData
);