ReactOS 0.4.15-dev-7918-g2a2556c
chstring.cpp
Go to the documentation of this file.
1/*
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)
7 *
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
23 */
24
25/* INCLUDES ******************************************************************/
26
27#define CHSTRING_BUILD
28
29#include <chstring.h>
30#define NDEBUG
31#include <debug.h>
32
33/* PRIVATE FUNCTIONS *********************************************************/
34
35// This is the empty string that defaults strings without text
36// This is unsafe. This string show be LPCWSTR
37// However we have to assign it to LPWSTR var. So, let's ignore about const,
38// as MS does. Normally we check in our code that we don't overwrite this string.
40// This is the data that are matching the null string upper
42// Exception we may throw in case of allocation failure
44
45// Our own delete operator
46// It is here basically because MS guys don't known about set_new_handler()
47// See operator new
48void operator delete(void* ptr)
49{
50 // In Windows 2k3, they check for ptr being null.
51 // ISO, POSIX and even MSDN explains that it is allowed
52 // to call free with NULL pointer...
53 if (ptr)
54 {
55 free(ptr);
56 }
57}
58
59// Implement our own new operator so that we can throw our own exception in case
60// of allocation failure.
61// It could have been done using set_new_handler(), but well. MS guys didn't do it
62// that way. So, let's mimic.
63void* operator new(size_t uSize)
64{
65 void* Buffer;
66
67 Buffer = malloc(uSize);
68 if (!Buffer)
69 {
70 throw HeapException;
71 }
72
73 return Buffer;
74}
75
76// This is a char to wchar string conversion helper
77int mbstowcsz(LPWSTR lpDest, LPCSTR lpSrc, int nLen)
78{
79 int Conv;
80
81 // If we have nothing to convert or if output doesn't exist, return
82 if (nLen == 0 || lpDest == 0)
83 {
84 return 0;
85 }
86
87 // Then, simply convert
88 Conv = MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, lpDest, nLen);
89 // In case of conversion success, null terminate the string
90 if (Conv != 0)
91 {
92 lpDest[nLen] = 0;
93 }
94
95 return Conv;
96}
97
98/* PUBLIC FUNCTIONS **********************************************************/
99
100/*
101 * @implemented
102 */
104{
105 // Set to empty string
107}
108
109/*
110 * @implemented
111 */
113{
114 // Allow null initialize, in case something goes wrong
116
117 // If we have a char to insert
118 if (nRepeat >= 1)
119 {
120 // Allocate a buffer big enough
121 AllocBuffer(nRepeat);
122 // And if possible, repeat char
123 if (m_pchData)
124 {
125 for (int i = 0; i < nRepeat; ++i)
126 {
127 m_pchData[i] = ch;
128 }
129 }
130 }
131}
132
133/*
134 * @implemented
135 */
137{
138 // Allow null initialize, in case something goes wrong
140
141 // If we have an input string
142 if (lpsz != 0)
143 {
144 // Get its length
145 int Len = SafeStrlen(lpsz);
146 // Then, allocate a big enough buffer and copy string
147 // Note that here, we don't null terminate the string...
148 if (Len)
149 {
151 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData),
152 reinterpret_cast<LPCWSTR>(lpsz),
153 Len);
154 }
155 }
156}
157
158/*
159 * @implemented
160 */
162{
163 // Allow null initialize, in case something goes wrong
165
166 // In case we have a string with a len
167 if (lpch != 0 && nLength != 0)
168 {
169 // Just copy the string
171 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData),
172 reinterpret_cast<LPCWSTR>(lpch),
173 nLength);
174 }
175}
176
177/*
178 * @implemented
179 */
181{
182 // Allow null initialize, in case something goes wrong
184
185 // If we have input string
186 if (lpsz != 0)
187 {
188 // Get its length
189 int Len = (int)strlen(lpsz);
190 if (Len)
191 {
192 // Allocate and convert the string
194 mbstowcsz(reinterpret_cast<LPWSTR>(m_pchData), lpsz, Len + 1);
195 // Releasing buffer here is to allow to
196 // update the buffer size. We notify we're
197 // done with changing the string: recompute its
198 // length, please
200 }
201 }
202}
203
204/*
205 * @implemented
206 */
207CHString::CHString(const unsigned char* lpsz)
208{
209 // Null init
210 Init();
211 // And call operator= with const char*, easier
212 *this = (LPCSTR)lpsz;
213}
214
215/*
216 * @implemented
217 */
219{
220 // If we have currently no referenced string
221 if (stringSrc.GetData()->nRefs < 0)
222 {
223 // Ensure we have the null string
225 // And then call, the copy operator with input string
226 *this = stringSrc.m_pchData;
227 }
228 else
229 {
230 // Otherwise, just copy the input string
231 m_pchData = stringSrc.m_pchData;
232 // And increment the number of references
233 InterlockedIncrement(&GetData()->nRefs);
234 // The whole point here is: Am I forget to release the old
235 // data?! MS doesn't release it, but I guess we should...
236 }
237}
238
239/*
240 * @implemented
241 */
243{
244 // If we have a string
245 if (GetData() != &afxNullData)
246 {
247 // Check whether it's still in use after we release it
248 if (InterlockedDecrement(&GetData()->nRefs) == 0)
249 {
250 // If so, delete it
251 delete GetData();
252 }
253 }
254}
255
256/*
257 * @implemented
258 */
260{
261 // In case we have several strings pointing to our memory zone
262 // Or we need bigger buffer than actual
263 if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
264 {
265 // Just drop current
266 // And allocate a new one which is big enough
267 Release();
268 AllocBuffer(nLen);
269 }
270}
271
272/*
273 * @implemented
274 */
276{
277 // Here we have to allocate a buffer for the string
278 // It actually consists in: CHStringData structure
279 // with a buffer big enough at its end to store the
280 // string.
282
283 // Null size is easy allocation
284 if (nSize == 0)
285 {
287 return;
288 }
289
290 // We cannot allow negative sizes
291 if (nSize < 0)
292 {
294 }
295
296 // Nor too big
297 if (nSize > (INT_MAX - (int)sizeof(CHStringData)) / (int)sizeof(WCHAR))
298 {
300 }
301
302 // Just allocate big enough buffer, using our own operator new
303 Data = (CHStringData *)operator new(nSize * sizeof(WCHAR) + sizeof(CHStringData));
304 // In case Data is null, throw an exception
305 // Yes, this is stupid! Our operator new is already supposed to through an exception...
306 // Thanks MS
307 if (!Data)
308 {
309 throw HeapException;
310 }
311
312 Data->nRefs = 1;
313 Data->nDataLength = nSize;
314 Data->nAllocLength = nSize;
315 Data->data()[0] = 0;
316
317 // We only return the string
318 // We can find back data with some mathematics
319 m_pchData = Data->data();
320}
321
322/*
323 * @implemented
324 */
325void CHString::AllocCopy(CHString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
326{
327 // Once again, we cannot deal with negative lens
328 if (nCopyLen < 0)
329 {
331 }
332
333 if (nCopyIndex < 0)
334 {
336 }
337
338 if (nExtraLen < 0)
339 {
341 }
342
343 // In case what we have to copy is null-sized, just set empty string
344 if (nCopyLen + nExtraLen == 0)
345 {
346 dest.m_pchData = afxPchNil;
347 return;
348 }
349
350 // Otherwise, allocate a buffer in new string which is big enough
351 // You can note that we absolutely don't check about any existing
352 // (referenced) buffer in dest. Actually, dest is to be EMPTY string.
353 // The whole point of this function is to initialize a virgin string by
354 // copying data from another. This is needed by Left/Mid/Right
355 dest.AllocBuffer(nCopyLen + nExtraLen);
356 // And copy our stuff in
357 wcsncpy(reinterpret_cast<LPWSTR>(dest.m_pchData),
358 reinterpret_cast<LPWSTR>(m_pchData + nCopyIndex),
359 nCopyLen);
360}
361
362/*
363 * @implemented
364 */
366{
367 BSTR SysString;
368
369 // Just allocate the string
370 SysString = SysAllocStringLen(reinterpret_cast<LPWSTR>(m_pchData), GetData()->nDataLength);
371 if (!SysString)
372 {
373 throw HeapException;
374 }
375
376 return reinterpret_cast<CHSTRING_LPWSTR>(SysString);
377}
378
379/*
380 * @implemented
381 */
382void CHString::AssignCopy(int nSrcLen, CHSTRING_LPCWSTR lpszSrcData)
383{
384 // Don't allow negative len
385 if (nSrcLen < 0)
386 {
388 }
389
390 // We will have to modify a string that might be shared, so duplicate it
391 // Ensuring it's big enough to contain our new stuff
392 AllocBeforeWrite(nSrcLen);
393 if (nSrcLen == 0)
394 {
395 Release();
396 return;
397 }
398
399 // Just copy, write down new size, and ensure it's null terminated
400 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData),
401 reinterpret_cast<LPCWSTR>(lpszSrcData), nSrcLen);
402 GetData()->nDataLength = nSrcLen;
403 m_pchData[nSrcLen] = 0;
404}
405
406/*
407 * @implemented
408 */
410{
411 // Just call the deprecated function here - no matter we are null terminated
412 // Did you read my statement about how safe is this implementation?
413 return wcscoll(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpsz));
414}
415
416/*
417 * @implemented
418 */
420{
421 // Just call the deprecated function here - no matter we are null terminated
422 // Did you read my statement about how safe is this implementation?
423 return wcscmp(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpsz));
424}
425
426/*
427 * @implemented
428 */
430{
431 // Just call the deprecated function here - no matter we are null terminated
432 // Did you read my statement about how safe is this implementation?
433 return wcsicmp(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpsz));
434}
435
436/*
437 * @implemented
438 */
439void CHString::ConcatInPlace(int nSrcLen, CHSTRING_LPCWSTR lpszSrcData)
440{
441 // With null length, there's not that much to concat...
442 if (nSrcLen == 0)
443 {
444 return;
445 }
446
447 // Still no negative length
448 if (nSrcLen < 0)
449 {
451 }
452
453 // Ensure we wouldn't overflow with the concat
454 if (GetData()->nDataLength > INT_MAX - nSrcLen)
455 {
457 }
458
459 // In case we have to modify a shared string OR if it can't fit into current buffer...
460 if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
461 {
462 // Allocate a new buffer! (without forgetting to release old one)
463 CHStringData* OldData = GetData();
464
465 // You remember about "InPlace" in the function's name?
466 // The cake is a lie
467 ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
468 Release(OldData);
469 }
470 else
471 {
472 // Ensure we don't overflow
473 if (nSrcLen > INT_MAX - GetData()->nDataLength)
474 {
476 }
477
478 // Then, just copy and null terminate
479 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData + GetData()->nDataLength),
480 reinterpret_cast<LPCWSTR>(lpszSrcData),
481 nSrcLen);
482 GetData()->nDataLength += nSrcLen;
484 }
485}
486
487/*
488 * @implemented
489 */
491 int nSrc1Len, CHSTRING_LPCWSTR lpszSrc1Data,
492 int nSrc2Len, CHSTRING_LPCWSTR lpszSrc2Data)
493{
494 int TotalLen;
495
496 if (nSrc1Len < 0 || nSrc2Len < 0)
497 {
499 }
500
501 // If both len are null, do nothing
502 TotalLen = nSrc1Len + nSrc2Len;
503 if (TotalLen == 0)
504 {
505 return;
506 }
507
508 // Otherwise, allocate a new buffer to hold everything (caller will release previous buffer)
509 AllocBuffer(TotalLen);
510 // And concat stuff
511 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData),
512 reinterpret_cast<LPCWSTR>(lpszSrc1Data),
513 nSrc1Len);
514 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData + nSrc1Len),
515 reinterpret_cast<LPCWSTR>(lpszSrc2Data),
516 nSrc2Len);
517}
518
519/*
520 * @implemented
521 */
523{
525
526 // First, we need to get reference count
527 // And we also need to save Data for later copy
528 Data = GetData();
529
530 if (Data->nRefs <= 1)
531 {
532 // If its not used, don't waste time to realloc, it will do the job
533 return;
534 }
535
536 // Release current data - we are sure it won't be freed upon that point
537 // Thanks to the reference count check previously done
538 Release();
539 // Alloc new buffer and copy old data in it
540 AllocBuffer(Data->nDataLength);
541 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData),
542 reinterpret_cast<LPCWSTR>(Data->data()),
543 Data->nDataLength);
544}
545
546/*
547 * @implemented
548 */
550{
551 // Already empty
552 if (GetData()->nDataLength == 0)
553 {
554 return;
555 }
556
557 // Empty it easily given it's reference count
558 if (GetData()->nRefs < 0)
559 {
560 *this = afxPchNil;
561 }
562 else
563 {
564 // Otherwise, just release it
565 // It will set back this instance to afxPchNil
566 // while decreasing reference count
567 Release();
568 }
569}
570
571/*
572 * @implemented
573 */
575{
577
578 // Let's use appropriate helper
579 Found = reinterpret_cast<CHSTRING_LPCWSTR>(wcschr(reinterpret_cast<LPCWSTR>(m_pchData), ch));
580 // We have to return a position, so compute it
581 if (Found)
582 {
583 return (Found - m_pchData);
584 }
585
586 // Otherwise, return no position
587 return -1;
588}
589
590/*
591 * @implemented
592 */
594{
596
597 // Let's use appropriate helper
598 Found = reinterpret_cast<CHSTRING_LPCWSTR>(wcsstr(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpszSub)));
599 // We have to return a position, so compute it
600 if (Found)
601 {
602 return (Found - m_pchData);
603 }
604
605 // Otherwise, return no position
606 return -1;
607}
608
609/*
610 * @implemented
611 */
613{
615
616 // Let's use appropriate helper
617 Found = reinterpret_cast<CHSTRING_LPCWSTR>(wcspbrk(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpszCharSet)));
618 // We have to return a position, so compute it
619 if (Found)
620 {
621 return (Found - m_pchData);
622 }
623
624 // Otherwise, return no position
625 return -1;
626}
627
628/*
629 * @implemented
630 */
631void CHString::Format(UINT nFormatID, ...)
632{
633 // Deprecated and not implemented any longer - well, this is its implementation
634 return;
635}
636
637/*
638 * @implemented
639 */
641{
642 // Forward to FormatV
643 va_list ArgsList;
644
645 va_start(ArgsList, lpszFormat);
646 FormatV(lpszFormat, ArgsList);
647 va_end(ArgsList);
648}
649
650/*
651 * @implemented
652 */
653void CHString::FormatMessageW(UINT nFormatID, ...)
654{
655 // Deprecated and not implemented any longer - well, this is its implementation
656 return;
657}
658
659/*
660 * @unimplemented
661 */
663{
665}
666
667/*
668 * @unimplemented
669 */
671{
673}
674
675/*
676 * @implemented
677 */
679{
680 CHStringData* OldData;
681
682 // No extra? Do nothing
683 if (GetData()->nDataLength == GetData()->nAllocLength)
684 {
685 return;
686 }
687
688 // Get old buffer
689 OldData = GetData();
690 // Allocate a new one, at the right size (with no place for \0 :-))
691 AllocBuffer(GetData()->nDataLength);
692 // Copy old and release it
693 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(OldData->data()), OldData->nDataLength);
694 Release(OldData);
695}
696
697/*
698 * @implemented
699 */
701{
702 return GetData()->nAllocLength;
703}
704
705/*
706 * @implemented
707 */
709{
710 // It's up to you to check the index!
711 return m_pchData[nIndex];
712}
713
714/*
715 * @implemented
716 */
718{
719 CHSTRING_LPWSTR OldBuffer = m_pchData;
720
721 // We'll have to allocate a new buffer if it's not big enough
722 // or if it's shared by several strings
723 if (GetData()->nRefs > 1 || GetData()->nAllocLength < nMinBufLength)
724 {
725 CHStringData* OldData = GetData();
726 int OldLen = GetData()->nDataLength;
727
728 // Ensure we can hold enough
729 if (OldLen > nMinBufLength)
730 {
731 nMinBufLength = OldLen;
732 }
733
734 // Allocate new buffer
735 AllocBuffer(nMinBufLength);
736 // Copy contents
737 wcsncpy(reinterpret_cast<LPWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(OldBuffer), OldLen);
738 GetData()->nDataLength = OldLen;
739
740 // Release old
741 Release(OldData);
742 }
743
744 // Weirdly, here Windows always returns the old buffer
745 // Which basically exposes a wrong buffer
746 return OldBuffer;
747}
748
749/*
750 * @implemented
751 */
753{
754 // Get a buffer big enough
755 // We don't care about the return, it will be set in the string
756 (void)GetBuffer(nNewLength);
757 // Set length, null-terminate and return
758 GetData()->nDataLength = nNewLength;
759 m_pchData[nNewLength] = 0;
760 return m_pchData;
761}
762
763/*
764 * @implemented
765 */
767{
768 // In case of empty string, return empty data
769 if (m_pchData == afxPchNil)
770 {
771 return &afxNullData;
772 }
773
774 // Otherwise, do maths
775 return (CHStringData*)((ULONG_PTR)m_pchData - sizeof(CHStringData));
776}
777
778/*
779 * @implemented
780 */
782{
783 return GetData()->nDataLength;
784}
785
786/*
787 * @implemented
788 */
790{
792}
793
794/*
795 * @implemented
796 */
798{
799 return (GetData()->nDataLength == 0);
800}
801
802/*
803 * @implemented
804 */
805CHString CHString::Left(int nCount) const
806{
807 CHString NewString;
808
809 // Validate input (we can't get more than what we have ;-))
810 if (nCount)
811 {
812 if (nCount > GetData()->nDataLength)
813 {
814 nCount = GetData()->nDataLength;
815 }
816 }
817
818 AllocCopy(NewString, nCount, 0, 0);
819
820 return NewString;
821}
822
823/*
824 * @implemented
825 */
827{
828 // Deprecated and not implemented any longer - well, this is its implementation
829 return 0;
830}
831
832/*
833 * @implemented
834 */
836{
837 // Deprecated and not implemented any longer - well, this is its implementation
838 return 0;
839}
840
841/*
842 * @implemented
843 */
845{
846 CHSTRING_LPWSTR LockedBuffer;
847
848 // The purpose here is basically to set the nRefs to max int
849 LockedBuffer = GetBuffer(0);
850 GetData()->nRefs = INT_MAX;
851
852 return LockedBuffer;
853}
854
855/*
856 * @implemented
857 */
859{
860 // We'll modify string, duplicate it first if needed
862
863 // Let's use appropriate helper
864 _wcslwr(reinterpret_cast<LPWSTR>(m_pchData));
865}
866
867/*
868 * @implemented
869 */
871{
872 // We'll modify string, duplicate it first if needed
874
875 // Let's use appropriate helper
876 _wcsrev(reinterpret_cast<LPWSTR>(m_pchData));
877}
878
879/*
880 * @implemented
881 */
883{
884 // We'll modify string, duplicate it first if needed
886
887 // Let's use appropriate helper
888 _wcsupr(reinterpret_cast<LPWSTR>(m_pchData));
889}
890
891/*
892 * @implemented
893 */
894CHString CHString::Mid(int nFirst) const
895{
896 // Take string from nFirst up to the end
897 return Mid(nFirst, GetData()->nDataLength - nFirst);
898}
899
900/*
901 * @implemented
902 */
903CHString CHString::Mid(int nFirst, int nCount) const
904{
905 CHString NewString;
906
907 // Validate sizes first
908 if (nFirst < 0)
909 {
910 nFirst = 0;
911 }
912
913 if (nCount < 0)
914 {
915 nCount = 0;
916 }
917
918 // Ensure we don't go beyond the string
919 if (nFirst + nCount > GetData()->nDataLength)
920 {
921 nCount = GetData()->nDataLength - nFirst;
922 }
923
924 // Also ensure we don't read beyond
925 // Yes, this should have been done before previous check
926 // MS does it that way
927 if (nFirst > GetData()->nDataLength)
928 {
929 nCount = 0;
930 }
931
932 AllocCopy(NewString, nCount, nFirst, 0);
933
934 return NewString;
935}
936
937/*
938 * @implemented
939 */
941{
942 // If null string, nothing to do
943 if (GetData() == &afxNullData)
944 {
945 return;
946 }
947
948 // Otherwise, decrement ref count and release if required
949 if (InterlockedDecrement(&GetData()->nRefs) == 0)
950 {
951 delete GetData();
952 }
953
954 // In all cases, caller doesn't want string anymore
955 // So, switch back to empty string
957}
958
959/*
960 * @implemented
961 */
963{
964 // If empty string, ignore
965 if (pData == &afxNullData)
966 {
967 return;
968 }
969
970 // Otherwise, simply and free if needed
971 if (InterlockedDecrement(&pData->nRefs) == 0)
972 {
973 delete pData;
974 }
975}
976
977/*
978 * @implemented
979 */
980void CHString::ReleaseBuffer(int nNewLength)
981{
983
984 // We'll modify buffer, so duplicate
986
987 // If no len provided, get one
988 if (nNewLength == -1)
989 {
990 nNewLength = (int)wcslen(reinterpret_cast<LPCWSTR>(m_pchData));
991 }
992
993 // Set appropriate size and null-terminate
994 Data = GetData();
995 Data->nDataLength = nNewLength;
996 Data->data()[nNewLength] = 0;
997}
998
999/*
1000 * @implemented
1001 */
1003{
1004 CHSTRING_WCHAR *Last;
1005
1006 // Let's use appropriate helper
1007 Last = reinterpret_cast<CHSTRING_WCHAR*>(wcsrchr(reinterpret_cast<LPCWSTR>(m_pchData), ch));
1008 // We have to return a position, so compute it
1009 if (Last)
1010 {
1011 return (Last - m_pchData);
1012 }
1013
1014 // Otherwise, return no position
1015 return -1;
1016}
1017
1018/*
1019 * @implemented
1020 */
1021CHString CHString::Right(int nCount) const
1022{
1023 CHString NewString;
1024
1025 // Validate input (we can't get more than what we have ;-))
1026 if (nCount >= 0)
1027 {
1028 if (nCount > GetData()->nDataLength)
1029 {
1030 nCount = GetData()->nDataLength;
1031 }
1032 }
1033
1034 AllocCopy(NewString, nCount, GetData()->nDataLength - nCount, 0);
1035
1036 return NewString;
1037}
1038
1039/*
1040 * @implemented
1041 */
1043{
1044 // Check we have a string and then get its length
1045 if (lpsz == 0)
1046 {
1047 return 0;
1048 }
1049
1050 // Of course, it's not safe at all in case string is not null-terminated.
1051 // Things that may happen given strings are not to be null-terminated
1052 // in this class...
1053 return (int)wcslen(reinterpret_cast<LPCWSTR>(lpsz));
1054}
1055
1056/*
1057 * @implemented
1058 */
1060{
1062
1063 m_pchData[nIndex] = ch;
1064}
1065
1066/*
1067 * @implemented
1068 */
1070{
1071 int Count;
1072
1073 // Get position and then, extract
1074 Count = (int)wcscspn(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpszCharSet));
1075 return Left(Count);
1076}
1077
1078/*
1079 * @implemented
1080 */
1082{
1083 int Count;
1084
1085 // Get position and then, extract
1086 Count = (int)wcsspn(reinterpret_cast<LPCWSTR>(m_pchData), reinterpret_cast<LPCWSTR>(lpszCharSet));
1087 return Left(Count);
1088}
1089
1090/*
1091 * @implemented
1092 */
1094{
1095 int NewBegin;
1096 int NewLength;
1097 CHSTRING_WCHAR *CurrentChar;
1098
1099 // We'll modify, so copy first
1101
1102 // Start at the begin of the string
1103 CurrentChar = m_pchData;
1104 while (*CurrentChar != 0)
1105 {
1106 // Browse string till we find something which is not a space
1107 if (!iswspace(*CurrentChar))
1108 {
1109 break;
1110 }
1111
1112 CurrentChar++;
1113 }
1114
1115 // Then, calculate new begin (easy) and new length
1116 // And move memory
1117 NewBegin = (CurrentChar - m_pchData);
1118 NewLength = GetData()->nDataLength - NewBegin;
1119 memmove(m_pchData, CurrentChar, NewLength * sizeof(CHSTRING_WCHAR));
1121}
1122
1123/*
1124 * @implemented
1125 */
1127{
1128 CHSTRING_WCHAR *CurrentChar;
1129 CHSTRING_WCHAR *CanBeEaten;
1130
1131 // We'll modify, so copy first
1133
1134 // Start at the begin of the string -- WHAT?!
1135 // Yes, this algorithm is the same that MS is
1136 // using for its TrimRight.
1137 // It is highly unefficient. It would have been
1138 // easier to start at nDataLength and to get back to
1139 // the begin. Note that it would have been safer as
1140 // well, in case the caller is using non-null-terminated
1141 // strings. But, well...
1142 CurrentChar = m_pchData;
1143 CanBeEaten = 0;
1144 while (*CurrentChar != 0)
1145 {
1146 // If not a space, reset what we can trim
1147 if (!iswspace(*CurrentChar))
1148 {
1149 CanBeEaten = 0;
1150 }
1151 // If it is one, and the first of the spaces serie
1152 // Keep its position
1153 else if (CanBeEaten == 0)
1154 {
1155 CanBeEaten = CurrentChar;
1156 }
1157
1158 CurrentChar++;
1159 }
1160
1161 // If nothing to trim, quit
1162 if (CanBeEaten == 0)
1163 {
1164 return;
1165 }
1166
1167 // Otherwise, shorten the string
1168 GetData()->nDataLength = (CanBeEaten - m_pchData);
1169}
1170
1171/*
1172 * @implemented
1173 */
1175{
1176 // Unlock means just put ref back to 1
1177 // It was previously set to MAX_INT
1178 if (GetData() != &afxNullData)
1179 {
1180 GetData()->nRefs = 1;
1181 }
1182}
1183
1184/*
1185 * @implemented
1186 */
1188{
1189 *this = (CHSTRING_WCHAR)ch;
1190 return *this;
1191}
1192
1193/*
1194 * @implemented
1195 */
1197{
1198 AssignCopy(1, &ch);
1199 return *this;
1200}
1201
1202/*
1203 * @implemented
1204 */
1206{
1207 *this = *p;
1208 return *this;
1209}
1210
1211/*
1212 * @implemented
1213 */
1215{
1216 int Len;
1217
1218 // If we have string, get its len
1219 if (lpsz != 0)
1220 {
1221 Len = (int)strlen(lpsz);
1222 }
1223 else
1224 {
1225 Len = 0;
1226 }
1227
1228 // Do this call, even with null len, just to get empty string
1230 if (Len == 0)
1231 {
1232 Release();
1233 return *this;
1234 }
1235
1236 // Convert and copy
1237 mbstowcsz(reinterpret_cast<LPWSTR>(m_pchData), lpsz, Len + 1);
1238 // Get new size and so on
1239 ReleaseBuffer();
1240
1241 return *this;
1242}
1243
1244/*
1245 * @implemented
1246 */
1248{
1249 int Len;
1250
1251 Len = SafeStrlen(lpsz);
1252 AssignCopy(Len, lpsz);
1253
1254 return *this;
1255}
1256
1257/*
1258 * @implemented
1259 */
1260const CHString& CHString::operator=(const CHString& stringSrc)
1261{
1262 // Don't copy string on itself
1263 if (&stringSrc == this)
1264 {
1265 return *this;
1266 }
1267
1268 // In case we don't have a referenced string here,
1269 // or if the other is not referenced, just copy here
1270 if ((GetData()->nRefs < 0 && GetData() != &afxNullData) ||
1271 stringSrc.GetData()->nRefs < 0)
1272 {
1273 AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
1274 return *this;
1275 }
1276
1277 // Otherwise, release current buffer
1278 Release();
1279 // And set buffer as stringSrc buffer
1280 // And increase its reference count
1281 m_pchData = stringSrc.m_pchData;
1282 InterlockedIncrement(&GetData()->nRefs);
1283
1284 return *this;
1285}
1286
1287/*
1288 * @implemented
1289 */
1290const CHString& CHString::operator=(const unsigned char* lpsz)
1291{
1292 *this = (LPCSTR)lpsz;
1293 return *this;
1294}
1295
1296/*
1297 * @implemented
1298 */
1300{
1301 *this += (CHSTRING_WCHAR)ch;
1302 return *this;
1303}
1304
1305/*
1306 * @implemented
1307 */
1309{
1310 ConcatInPlace(1, &ch);
1311 return *this;
1312}
1313
1314/*
1315 * @implemented
1316 */
1318{
1319 int Len;
1320
1321 Len = SafeStrlen(lpsz);
1322 ConcatInPlace(Len, lpsz);
1323
1324 return *this;
1325}
1326
1327/*
1328 * @implemented
1329 */
1331{
1332 ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
1333
1334 return *this;
1335}
1336
1337/*
1338 * @implemented
1339 */
1341{
1342 return m_pchData[nIndex];
1343}
1344
1345/*
1346 * @implemented
1347 */
1348CHString::operator CHSTRING_LPCWSTR() const
1349{
1350 return m_pchData;
1351}
1352
1353/*
1354 * @implemented
1355 */
1357{
1358 CHString NewString;
1359
1360 // Basically concat in a new string
1361 NewString.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
1362
1363 return NewString;
1364}
1365
1366/*
1367 * @implemented
1368 */
1370{
1371 CHString NewString;
1372
1373 // Basically concat in a new string
1374 NewString.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch);
1375
1376 return NewString;
1377}
1378
1379/*
1380 * @implemented
1381 */
1383{
1384 int Len;
1385 CHString NewString;
1386
1387 // Get string length
1388 Len = CHString::SafeStrlen(lpsz);
1389 // And concat in new string
1390 NewString.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, Len, lpsz);
1391
1392 return NewString;
1393}
1394
1395/*
1396 * @implemented
1397 */
1399{
1400 int Len;
1401 CHString NewString;
1402
1403 // Get string length
1404 Len = CHString::SafeStrlen(lpsz);
1405 // And concat in new string
1406 NewString.ConcatCopy(Len, lpsz, string.GetData()->nDataLength, string.m_pchData);
1407
1408 return NewString;
1409}
1410
1411/*
1412 * @implemented
1413 */
1415{
1416 CHString NewString;
1417
1418 // Basically concat in a new string
1419 NewString.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
1420 string2.GetData()->nDataLength, string2.m_pchData);
1421
1422 return NewString;
1423}
static USHORT USHORT * NewLength
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define UNIMPLEMENTED
Definition: debug.h:115
return Found
Definition: dirsup.c:1270
CHStringData afxNullData
Definition: chstring.cpp:41
int mbstowcsz(LPWSTR lpDest, LPCSTR lpSrc, int nLen)
Definition: chstring.cpp:77
CHSTRING_WCHAR afxPchNil[1]
Definition: chstring.cpp:39
CHString WINAPI operator+(CHSTRING_WCHAR ch, const CHString &string)
Definition: chstring.cpp:1356
CHeap_Exception HeapException(CHeap_Exception::E_ALLOCATION_ERROR)
const CHSTRING_WCHAR * CHSTRING_LPCWSTR
Definition: chstring.h:14
CHSTRING_WCHAR * CHSTRING_LPWSTR
Definition: chstring.h:15
unsigned short CHSTRING_WCHAR
Definition: chstring.h:13
Definition: bufpool.h:45
CHStringData * GetData() const
Definition: chstring.cpp:766
void ConcatInPlace(int nSrcLen, CHSTRING_LPCWSTR lpszSrcData)
Definition: chstring.cpp:439
CHString Left(int nCount) const
Definition: chstring.cpp:805
void TrimLeft()
Definition: chstring.cpp:1093
void SetAt(int nIndex, CHSTRING_WCHAR ch)
Definition: chstring.cpp:1059
const CHString & operator+=(char ch)
Definition: chstring.cpp:1299
int GetLength() const
Definition: chstring.cpp:781
void CopyBeforeWrite()
Definition: chstring.cpp:522
int Compare(CHSTRING_LPCWSTR lpsz) const
Definition: chstring.cpp:419
void Init()
Definition: chstring.cpp:789
void UnlockBuffer()
Definition: chstring.cpp:1174
void AssignCopy(int nSrcLen, CHSTRING_LPCWSTR lpszSrcData)
Definition: chstring.cpp:382
const CHString & operator=(char ch)
Definition: chstring.cpp:1187
CHString SpanExcluding(CHSTRING_LPCWSTR lpszCharSet) const
Definition: chstring.cpp:1069
void MakeUpper()
Definition: chstring.cpp:882
void ReleaseBuffer(int nNewLength=-1)
Definition: chstring.cpp:980
CHSTRING_LPWSTR GetBuffer(int nMinBufLength)
Definition: chstring.cpp:717
void MakeLower()
Definition: chstring.cpp:858
CHString Right(int nCount) const
Definition: chstring.cpp:1021
void FormatMessageW(UINT nFormatID,...)
Definition: chstring.cpp:653
void MakeReverse()
Definition: chstring.cpp:870
CHSTRING_WCHAR operator[](int nIndex) const
Definition: chstring.cpp:1340
int Collate(CHSTRING_LPCWSTR lpsz) const
Definition: chstring.cpp:409
CHString Mid(int nFirst) const
Definition: chstring.cpp:894
int LoadStringW(UINT nID)
Definition: chstring.cpp:826
void TrimRight()
Definition: chstring.cpp:1126
void ConcatCopy(int nSrc1Len, CHSTRING_LPCWSTR lpszSrc1Data, int nSrc2Len, CHSTRING_LPCWSTR lpszSrc2Data)
Definition: chstring.cpp:490
CHString SpanIncluding(CHSTRING_LPCWSTR lpszCharSet) const
Definition: chstring.cpp:1081
void AllocCopy(CHString &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
Definition: chstring.cpp:325
int CompareNoCase(CHSTRING_LPCWSTR lpsz) const
Definition: chstring.cpp:429
CHSTRING_LPWSTR LockBuffer()
Definition: chstring.cpp:844
int Find(CHSTRING_WCHAR ch) const
Definition: chstring.cpp:574
CHSTRING_LPWSTR GetBufferSetLength(int nNewLength)
Definition: chstring.cpp:752
void Release()
Definition: chstring.cpp:940
CHSTRING_LPWSTR m_pchData
Definition: chstring.h:147
void Empty()
Definition: chstring.cpp:549
CHSTRING_LPWSTR AllocSysString() const
Definition: chstring.cpp:365
int ReverseFind(CHSTRING_WCHAR ch) const
Definition: chstring.cpp:1002
void AllocBuffer(int nLen)
Definition: chstring.cpp:275
void FormatV(CHSTRING_LPCWSTR lpszFormat, va_list argList)
Definition: chstring.cpp:670
int GetAllocLength() const
Definition: chstring.cpp:700
int FindOneOf(CHSTRING_LPCWSTR lpszCharSet) const
Definition: chstring.cpp:612
void FreeExtra()
Definition: chstring.cpp:678
void AllocBeforeWrite(int nLen)
Definition: chstring.cpp:259
CHSTRING_WCHAR GetAt(int nIndex) const
Definition: chstring.cpp:708
static int WINAPI SafeStrlen(CHSTRING_LPCWSTR lpsz)
Definition: chstring.cpp:1042
void Format(UINT nFormatID,...)
Definition: chstring.cpp:631
BOOL IsEmpty() const
Definition: chstring.cpp:797
@ E_ALLOCATION_ERROR
Definition: provexce.h:11
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define Len
Definition: deflate.h:82
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
OLECHAR * BSTR
Definition: compat.h:2293
#define MultiByteToWideChar
Definition: compat.h:110
#define wcsicmp
Definition: compat.h:15
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define ULONG_PTR
Definition: config.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
static BYTE * GetData(BYTE *pData, ULONG *pLength)
Definition: assembly.c:114
return pMemory GetBuffer()
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define iswspace(_c)
Definition: ctype.h:669
#define INT_MAX
Definition: limits.h:40
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
static CHAR string1[MAX_PATH]
Definition: asmname.c:32
static CHAR string2[MAX_PATH]
Definition: automation.c:449
static char * dest
Definition: rtl.c:135
unsigned int UINT
Definition: ndis.h:50
int Count
Definition: noreturn.cpp:7
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:339
_CRTIMP wchar_t *__cdecl _wcsrev(_Inout_z_ wchar_t *_Str)
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcspbrk(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP size_t __cdecl wcsspn(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
_Check_return_ _CRTIMP size_t __cdecl wcscspn(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_CRTIMP wchar_t *__cdecl _wcslwr(_Inout_z_ wchar_t *_String)
_Check_return_ _CRTIMP int __cdecl wcscoll(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
long nRefs
Definition: chstring.h:21
CHSTRING_WCHAR * data()
Definition: chstring.h:25
int nDataLength
Definition: chstring.h:22
int nAllocLength
Definition: chstring.h:23
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2084
_In_ DWORD nLength
Definition: wincon.h:473
#define WINAPI
Definition: msvc.h:6
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185