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