soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
sstringw.cpp
1#include "string/sstringw.h"
2#include <soui_mem_wrapper.h>
3#include <stdio.h>
4
5#define smin_tsr(a,b) (((a) < (b)) ? (a) : (b))
6
7SNSBEGIN
8
9int wchar_traits::LoadString(HINSTANCE hInst, UINT uID, wchar_t* lpBuffer, int nBufferMax)
10{
11#ifdef _WIN32
12 return ::LoadStringW(hInst, uID, lpBuffer, nBufferMax);
13#else
14 return 0;
15#endif
16}
17
18int wchar_traits::Format(wchar_t** ppszDst, const wchar_t* pszFormat, va_list & args)
19{
20#ifdef _WIN32
21 int len = _vscwprintf(pszFormat, args); // _vscprintf doesn't count terminating '\0'
22 if (len <= 0) {
23 return 0;
24 }
25 *ppszDst = (wchar_t*)soui_mem_wrapper::SouiMalloc((len + 1) * sizeof(wchar_t));
26 vswprintf_s(*ppszDst, len + 1, pszFormat, args);
27 return len;
28#else
29 wchar_t* fmt = wcsdup(pszFormat);
30 wchar_t* p = wcsstr(fmt, L"%s");
31 while (p) {
32 p[1] = L'S';
33 p = wcsstr(p + 2, L"%s");
34 }
35 wchar_t stkBuf[512];
36 int len = vswprintf_s(stkBuf, 512, fmt, args);
37 if (len >= 0) {
38 *ppszDst = (wchar_t*)soui_mem_wrapper::SouiMalloc((len + 1) * sizeof(wchar_t));
39 memcpy(*ppszDst, stkBuf, (len) * sizeof(wchar_t));
40 (*ppszDst)[len] = 0;
41 free(fmt);
42 }
43 else {
44 int bufLen = 1024;
45 wchar_t* buf = (wchar_t*)malloc(sizeof(wchar_t) * bufLen);
46 for (;;) {
47 len = vswprintf_s(buf, bufLen, fmt, args);
48 if (len != -1)
49 break;
50 bufLen *= 2;
51 if (bufLen > (1 << 16))
52 break;
53 free(buf);
54 buf = (wchar_t*)malloc(sizeof(wchar_t) * bufLen);
55 }
56 free(fmt);
57 if (len == -1) {
58 free(buf);
59 return 0;
60 }
61 *ppszDst = (wchar_t*)soui_mem_wrapper::SouiMalloc((len + 1) * sizeof(wchar_t));
62 memcpy(*ppszDst, buf, len * sizeof(wchar_t));
63 (*ppszDst)[len] = 0;
64 free(buf);
65 }
66 return len;
67#endif//_WIN32
68}
69
70wchar_t* wchar_traits::CharNext(wchar_t* psz)
71{
72 return psz + 1;
73}
74
75wchar_t wchar_traits::CharUpper(wchar_t ch)
76{
77 return (wchar_t)towupper(ch);
78}
79
80wchar_t wchar_traits::CharLower(wchar_t ch)
81{
82 return (wchar_t)towlower(ch);
83}
84
85int wchar_traits::IsSpace(wchar_t ch)
86{
87 return iswspace(ch);
88}
89
90wchar_t* wchar_traits::StrLower(wchar_t* psz)
91{
92 return _wcslwr(psz);
93}
94
95wchar_t* wchar_traits::StrUpper(wchar_t* psz)
96{
97 return _wcsupr(psz);
98}
99
100const wchar_t* wchar_traits::StrStr(const wchar_t* psz, const wchar_t* psz2)
101{
102 return wcsstr(psz, psz2);
103}
104
105const wchar_t* wchar_traits::StrRChr(const wchar_t* psz, wchar_t ch)
106{
107 return wcsrchr(psz, ch);
108}
109
110const wchar_t* wchar_traits::StrChr(const wchar_t* psz, wchar_t ch)
111{
112 return wcschr(psz, ch);
113}
114
115int wchar_traits::CompareNoCase(const wchar_t* psz1, const wchar_t* psz2)
116{
117 return _wcsicmp(psz1, psz2);
118}
119
120int wchar_traits::Compare(const wchar_t* psz1, const wchar_t* psz2)
121{
122 return wcscmp(psz1, psz2);
123}
124
125size_t wchar_traits::StrLen(const wchar_t* psz)
126{
127 return psz ? wcslen(psz) : 0;
128}
129
130//////////////////////////////////////////////////////////////////////////
131
132
133void SStringW::ReleaseData(TStringData* pData)
134{
135 if (pData != TStringData::InitDataNil())
136 {
137 SASSERT(pData->nRefs != 0);
138 pData->Release();
139 }
140}
141
142TStringData* SStringW::AllocData(int nLength, TStringData* pOldData /*= NULL*/)
143{
144 SASSERT(nLength >= 0);
145 SASSERT(nLength <= 0x7fffffff); // max size (enough room for 1 extra)
146
147 if (nLength == 0)
148 return TStringData::InitDataNil();
149
150 int nSize = sizeof(TStringData) + (nLength + 1) * sizeof(wchar_t);
151 TStringData* pData;
152 if (pOldData == NULL)
153 pData = (TStringData*)soui_mem_wrapper::SouiMalloc(nSize);
154 else
155 pData = (TStringData*)soui_mem_wrapper::SouiRealloc(pOldData, nSize);
156 if (pData == NULL)
157 return NULL;
158
159 pData->nRefs = 1;
160 pData->nDataLength = nLength;
161 pData->nAllocLength = nLength;
162
163 wchar_t* pchData = (wchar_t*)pData->data();
164 pchData[nLength] = '\0';
165
166 return pData;
167}
168
170{
171 TStringData* pData = GetData();
172 if (pData != TStringData::InitDataNil())
173 {
174 SASSERT(pData->nRefs != 0);
175 pData->Release();
176 Init();
177 }
178}
179
180bool SStringW::ReallocBuffer(int nNewLength)
181{
182#define TSTRING_REALLOC
183#ifdef TSTRING_REALLOC
184 TStringData* pData = GetData();
185 if (!pData->IsShared() && pData != TStringData::InitDataNil())
186 {
187 pData = AllocData(nNewLength, pData);
188 if (pData != NULL)
189 {
190 m_pszData = (wchar_t*)pData->data();
191 return true;
192 }
193
194 Init();
195 return false;
196 }
197#endif
198 TStringData* pOldData = GetData();
199 wchar_t* psz = m_pszData;
200 if (AllocBuffer(nNewLength))
201 {
202 int nLength = smin_tsr(pOldData->nDataLength, nNewLength) + 1;
203 memcpy(m_pszData, psz, nLength * sizeof(wchar_t));
204 ReleaseData(pOldData);
205 return true;
206 }
207 return false;
208}
209
210bool SStringW::AllocBuffer(int nLength)
211{
212 TStringData* pData = AllocData(nLength);
213 if (pData != NULL)
214 {
215 m_pszData = (wchar_t*)pData->data();
216 return true;
217 }
218 return false;
219}
220
222{
223 bool bRet = true;
224 TStringData* pData = GetData();
225 if (pData->IsShared() || nLen > pData->nAllocLength)
226 {
227 _ReleaseData();
228 bRet = AllocBuffer(nLen);
229 }
230 SASSERT(GetData()->nRefs <= 1);
231 return bRet;
232}
233
235{
236 TStringData* pData = GetData();
237 if (pData->IsShared())
238 {
239 _ReleaseData();
240 if (AllocBuffer(pData->nDataLength))
241 memcpy(m_pszData, pData->data(), (pData->nDataLength + 1) * sizeof(wchar_t));
242 }
243 SASSERT(GetData()->nRefs <= 1);
244}
245
246void SStringW::ConcatInPlace(int nSrcLen, const wchar_t* pszSrcData)
247{
248 // -- the main routine for += operators
249
250 // concatenating an empty string is a no-op!
251 if (nSrcLen == 0)
252 return;
253
254 // if the buffer is too small, or we have a width mis-match, just
255 // allocate a new buffer (slow but sure)
256 TStringData* pData = GetData();
257 if (pData->IsShared() || pData->nDataLength + nSrcLen > pData->nAllocLength)
258 {
259 // we have to grow the buffer
260 int nOldDataLength = pData->nDataLength;
261 int nNewLength = nOldDataLength + nSrcLen;
262 if (ReallocBuffer(nNewLength))
263 memcpy(m_pszData + nOldDataLength, pszSrcData, nSrcLen * sizeof(wchar_t));
264 }
265 else
266 {
267 // fast concatenation when buffer big enough
268 memcpy(m_pszData + pData->nDataLength, pszSrcData, nSrcLen * sizeof(wchar_t));
269 pData->nDataLength += nSrcLen;
270 SASSERT(pData->nDataLength <= pData->nAllocLength);
271 m_pszData[pData->nDataLength] = '\0';
272 }
273}
274
275bool SStringW::ConcatCopy(int nSrc1Len, const wchar_t* pszSrc1Data, int nSrc2Len, const wchar_t* pszSrc2Data)
276{
277 // -- master concatenation routine
278 // Concatenate two sources
279 // -- assume that 'this' is a new TStringT object
280
281 bool bRet = true;
282 int nNewLength = nSrc1Len + nSrc2Len;
283 if (nNewLength != 0)
284 {
285 bRet = ReallocBuffer(nNewLength);
286 if (bRet)
287 {
288 memcpy(m_pszData, pszSrc1Data, nSrc1Len * sizeof(wchar_t));
289 memcpy(m_pszData + nSrc1Len, pszSrc2Data, nSrc2Len * sizeof(wchar_t));
290 }
291 }
292 return bRet;
293}
294
295void SStringW::AssignCopy(int nSrcLen, const wchar_t* pszSrcData)
296{
297 if (AllocBeforeWrite(nSrcLen))
298 {
299 memcpy(m_pszData, pszSrcData, nSrcLen * sizeof(wchar_t));
300 GetData()->nDataLength = nSrcLen;
301 m_pszData[nSrcLen] = '\0';
302 }
303}
304
305void SStringW::AllocCopy(SStringW& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
306{
307 // will clone the data attached to this string
308 // allocating 'nExtraLen' characters
309 // Places results in uninitialized string 'dest'
310 // Will copy the part or all of original data to start of new string
311
312 int nNewLen = nCopyLen + nExtraLen;
313 if (nNewLen == 0)
314 {
315 dest.Init();
316 }
317 else
318 {
319 if (dest.ReallocBuffer(nNewLen))
320 memcpy(dest.m_pszData, m_pszData + nCopyIndex, nCopyLen * sizeof(wchar_t));
321 }
322}
323
324void SStringW::_AppendFormat(const wchar_t* pszFormat, va_list & args)
325{
326 if (pszFormat == NULL || *pszFormat == '\0')
327 return;
328
329 wchar_t* pszBuffer = NULL;
330 int nLength = wchar_traits::Format(&pszBuffer, pszFormat, args);
331 if (nLength > 0 && pszBuffer != NULL)
332 {
333 *this += SStringW(pszBuffer, nLength);
334 soui_mem_wrapper::SouiFree(pszBuffer);
335 }
336}
337
338BOOL SStringW::_Format(const wchar_t* pszFormat, va_list & args)
339{
340 if (pszFormat == NULL || *pszFormat == '\0')
341 {
342 Empty();
343 return FALSE;
344 }
345
346 wchar_t* pszBuffer = NULL;
347 int nLength = wchar_traits::Format(&pszBuffer, pszFormat, args);
348 if (nLength > 0 && pszBuffer != NULL)
349 {
350 *this = SStringW(pszBuffer, nLength);
351 soui_mem_wrapper::SouiFree(pszBuffer);
352 return TRUE;
353 }
354 else
355 {
356 Empty();
357 return FALSE;
358 }
359}
360
362{
363 m_pszData = (wchar_t*)TStringData::InitPszNil();
364}
365
366TStringData* SStringW::GetData() const
367{
368 SASSERT(m_pszData != NULL);
369 return ((TStringData*)m_pszData) - 1;
370}
371
372int SStringW::SafeStrlen(const wchar_t* psz)
373{
374 return (psz == NULL) ? 0 : (int)wchar_traits::StrLen(psz);
375}
376
378{
379 return GetData()->nAllocLength;
380}
381
382
384{
385 TStringData* pData = GetData();
386 SASSERT(pData->nDataLength <= pData->nAllocLength);
387 if (pData->nDataLength < pData->nAllocLength)
388 {
389 if (ReallocBuffer(pData->nDataLength))
390 SASSERT(m_pszData[GetData()->nDataLength] == '\0');
391 }
392 SASSERT(GetData() != NULL);
393}
394
395void SStringW::Preallocate(int nLength)
396{
397 int nOldLength = GetLength();
398 GetBuffer(nLength);
399 ReleaseBuffer(nOldLength);
400}
401
402void SStringW::SetLength(int nLength)
403{
404 SASSERT(nLength >= 0);
405 SASSERT(nLength <= GetData()->nAllocLength);
406
407 if (nLength >= 0 && nLength < GetData()->nAllocLength)
408 {
409 GetData()->nDataLength = nLength;
410 m_pszData[nLength] = 0;
411 }
412}
413
414wchar_t* SStringW::GetBufferSetLength(int nNewLength)
415{
416 SASSERT(nNewLength >= 0);
417
418 if (GetBuffer(nNewLength) == NULL)
419 return NULL;
420
421 GetData()->nDataLength = nNewLength;
422 m_pszData[nNewLength] = '\0';
423 return m_pszData;
424}
425
426void SStringW::ReleaseBuffer(int nNewLength /*= -1*/)
427{
428 CopyBeforeWrite(); // just in case GetBuffer was not called
429
430 if (nNewLength == -1)
431 nNewLength = SafeStrlen(m_pszData); // zero terminated
432
433 TStringData* pData = GetData();
434 SASSERT(nNewLength <= pData->nAllocLength);
435 pData->nDataLength = nNewLength;
436 m_pszData[nNewLength] = '\0';
437}
438
439wchar_t* SStringW::GetBuffer(int nMinBufLength)
440{
441 TStringData* pData = GetData();
442 if(nMinBufLength<0)
443 nMinBufLength = pData->nAllocLength;
444 if (pData->IsShared() || nMinBufLength > pData->nAllocLength)
445 {
446 // we have to grow the buffer
447 int nOldLen = pData->nDataLength;
448 if (nMinBufLength < nOldLen)
449 nMinBufLength = nOldLen;
450 if (!ReallocBuffer(nMinBufLength))
451 return NULL;
452 }
453 SASSERT(GetData()->nRefs <= 1);
454
455 // return a pointer to the character storage for this string
456 SASSERT(m_pszData != NULL);
457 return m_pszData;
458}
459
460SStringW __cdecl SStringW::AppendFormat(const wchar_t* pszFormat, ...)
461{
462 va_list argList;
463 va_start(argList, pszFormat);
464 _AppendFormat(pszFormat, argList);
465 va_end(argList);
466 return *this;
467}
468
469void __cdecl SStringW::AppendFormat(HINSTANCE hInst,UINT nFormatID, ...)
470{
471 SStringW strFormat;
472 if (!strFormat.LoadString(nFormatID, hInst))
473 return;
474
475 va_list argList;
476 va_start(argList, nFormatID);
477 _AppendFormat(strFormat, argList);
478 va_end(argList);
479}
480
481SStringW __cdecl SStringW::Format(const wchar_t* pszFormat, ...)
482{
483 va_list argList;
484 va_start(argList, pszFormat);
485 _Format(pszFormat, argList);
486 va_end(argList);
487 return *this;
488}
489
490BOOL __cdecl SStringW::Format(HINSTANCE hInst,UINT nFormatID, ...)
491{
492 SStringW strFormat;
493 if (!strFormat.LoadString(nFormatID, hInst))
494 {
495 Empty();
496 return FALSE;
497 }
498
499 va_list argList;
500 va_start(argList, nFormatID);
501 BOOL bRet = _Format(strFormat, argList);
502 va_end(argList);
503 return bRet;
504}
505
506BOOL SStringW::LoadString(UINT nID,HINSTANCE hInst)
507{
508 SASSERT(hInst);
509 wchar_t buf[1024 + 1];
510 int nChar = wchar_traits::LoadString(hInst, nID, buf, 1024);
511 if (nChar == 0) return FALSE;
512 AssignCopy(nChar, buf);
513 return TRUE;
514}
515
516int SStringW::Find(const wchar_t* pszSub, int nStart /*= 0*/) const
517{
518 int nLength = GetData()->nDataLength;
519 if (nStart > nLength)
520 return -1;
521
522 // find first matching substring
523 const wchar_t* psz = wchar_traits::StrStr(m_pszData + nStart, pszSub);
524
525 // return -1 for not found, distance from beginning otherwise
526 return (psz == NULL) ? -1 : (int)(psz - m_pszData);
527}
528
529int SStringW::FindChar(wchar_t ch, int nStart /*= 0*/) const
530{
531 int nLength = GetData()->nDataLength;
532 if (nStart >= nLength)
533 return -1;
534
535 // find first single character
536 const wchar_t* psz = wchar_traits::StrChr(m_pszData + nStart, ch);
537
538 // return -1 if not found and index otherwise
539 return (psz == NULL) ? -1 : (int)(psz - m_pszData);
540}
541
542int SStringW::ReverseFind(wchar_t ch) const
543{
544 // find last single character
545 const wchar_t* psz = wchar_traits::StrRChr(m_pszData, ch);
546
547 // return -1 if not found, distance from beginning otherwise
548 return (psz == NULL) ? -1 : (int)(psz - m_pszData);
549}
550
551int SStringW::Remove(wchar_t chRemove)
552{
554
555 wchar_t* pstrSource = m_pszData;
556 wchar_t* pstrDest = m_pszData;
557 wchar_t* pstrEnd = m_pszData + GetData()->nDataLength;
558
559 while (pstrSource < pstrEnd)
560 {
561 if (*pstrSource != chRemove)
562 {
563 *pstrDest = *pstrSource;
564 pstrDest = wchar_traits::CharNext(pstrDest);
565 }
566 pstrSource = wchar_traits::CharNext(pstrSource);
567 }
568 *pstrDest = '\0';
569 int nCount = (int)(pstrSource - pstrDest);
570 GetData()->nDataLength -= nCount;
571
572 return nCount;
573}
574
575int SStringW::Replace(const wchar_t* pszOld, const wchar_t* pszNew)
576{
577 // can't have empty or NULL pszOld
578 int nSourceLen = SafeStrlen(pszOld);
579 if (nSourceLen == 0)
580 return 0;
581 int nReplacementLen = SafeStrlen(pszNew);
582
583 // loop once to figure out the size of the result string
584 int nCount = 0;
585 wchar_t* pszStart = m_pszData;
586 wchar_t* pszEnd = m_pszData + GetData()->nDataLength;
587 wchar_t* pszTarget;
588 while (pszStart < pszEnd)
589 {
590 while ((pszTarget = (wchar_t*)wchar_traits::StrStr(pszStart, pszOld)) != NULL)
591 {
592 nCount++;
593 pszStart = pszTarget + nSourceLen;
594 }
595 pszStart += wchar_traits::StrLen(pszStart) + 1;
596 }
597
598 // if any changes were made, make them
599 if (nCount > 0)
600 {
602
603 // if the buffer is too small, just
604 // allocate a new buffer (slow but sure)
605 TStringData* pOldData = GetData();
606 int nOldLength = pOldData->nDataLength;
607 int nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount;
608 if (pOldData->nAllocLength < nNewLength || pOldData->IsShared())
609 if (!ReallocBuffer(nNewLength))
610 return -1;
611
612 // else, we just do it in-place
613 pszStart = m_pszData;
614 pszEnd = m_pszData + GetData()->nDataLength;
615
616 // loop again to actually do the work
617 while (pszStart < pszEnd)
618 {
619 while ((pszTarget = (wchar_t*)wchar_traits::StrStr(pszStart, pszOld)) != NULL)
620 {
621 int nBalance = nOldLength - ((int)(pszTarget - m_pszData) + nSourceLen);
622 memmove(pszTarget + nReplacementLen, pszTarget + nSourceLen, nBalance * sizeof(wchar_t));
623 memcpy(pszTarget, pszNew, nReplacementLen * sizeof(wchar_t));
624 pszStart = pszTarget + nReplacementLen;
625 pszStart[nBalance] = '\0';
626 nOldLength += (nReplacementLen - nSourceLen);
627 }
628 pszStart += wchar_traits::StrLen(pszStart) + 1;
629 }
630 SASSERT(m_pszData[nNewLength] == '\0');
631 GetData()->nDataLength = nNewLength;
632 }
633 return nCount;
634}
635
636int SStringW::ReplaceChar(wchar_t chOld, wchar_t chNew)
637{
638 int nCount = 0;
639
640 // short-circuit the nop case
641 if (chOld != chNew)
642 {
644
645 // otherwise modify each character that matches in the string
646 wchar_t* psz = m_pszData;
647 wchar_t* pszEnd = psz + GetData()->nDataLength;
648 while (psz < pszEnd)
649 {
650 // replace instances of the specified character only
651 if (*psz == chOld)
652 {
653 *psz = chNew;
654 nCount++;
655 }
656 psz = wchar_traits::CharNext(psz);
657 }
658 }
659 return nCount;
660}
661
662int SStringW::Delete(int nIndex, int nCount /*= 1*/)
663{
664 if (nIndex < 0)
665 nIndex = 0;
666 int nLength = GetData()->nDataLength;
667 if (nCount > 0 && nIndex < nLength)
668 {
669 if((nIndex + nCount) > nLength)
670 nCount = nLength - nIndex;
671
673
674 int nBytesToCopy = nLength - (nIndex + nCount) + 1;
675 memmove(m_pszData + nIndex, m_pszData + nIndex + nCount, nBytesToCopy * sizeof(wchar_t));
676 nLength -= nCount;
677 GetData()->nDataLength = nLength;
678 }
679
680 return nLength;
681}
682
683int SStringW::Insert(int nIndex, const wchar_t* psz)
684{
685 if (nIndex < 0)
686 nIndex = 0;
687
688 int nInsertLength = SafeStrlen(psz);
689 int nNewLength = GetData()->nDataLength;
690 if (nInsertLength > 0)
691 {
693
694 if (nIndex > nNewLength)
695 nIndex = nNewLength;
696 nNewLength += nInsertLength;
697
698 TStringData* pData = GetData();
699 if (pData->nAllocLength < nNewLength)
700 if (!ReallocBuffer(nNewLength))
701 return -1;
702
703 // move existing bytes down
704 memmove(m_pszData + nIndex + nInsertLength, m_pszData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(wchar_t));
705 memcpy(m_pszData + nIndex, psz, nInsertLength * sizeof(wchar_t));
706 GetData()->nDataLength = nNewLength;
707 }
708 return nNewLength;
709}
710
711int SStringW::InsertChar(int nIndex, wchar_t ch)
712{
714
715 if (nIndex < 0)
716 nIndex = 0;
717
718 TStringData* pData = GetData();
719 int nNewLength = pData->nDataLength;
720 if (nIndex > nNewLength)
721 nIndex = nNewLength;
722 nNewLength++;
723
724 if (pData->nAllocLength < nNewLength)
725 if (!ReallocBuffer(nNewLength))
726 return -1;
727
728 // move existing bytes down
729 memmove(m_pszData + nIndex + 1, m_pszData + nIndex, (nNewLength - nIndex) * sizeof(wchar_t));
730 m_pszData[nIndex] = ch;
731 GetData()->nDataLength = nNewLength;
732
733 return nNewLength;
734}
735
736bool SStringW::EndsWith(const SStringW& suffix, bool IgnoreCase /*= false*/) const
737{
738 if (GetLength() >= suffix.GetLength())
739 {
740 SStringW _src = Right(suffix.GetLength());
741 if (IgnoreCase)
742 return 0 == _src.CompareNoCase(suffix);
743 else
744 return 0 == _src.Compare(suffix);
745 }
746 return false;
747}
748
749bool SStringW::StartsWith(const SStringW& prefix, bool IgnoreCase /*= false*/) const
750{
751 if (GetLength() >= prefix.GetLength())
752 {
753 SStringW _src = Left(prefix.GetLength());
754 if (IgnoreCase)
755 return 0 == _src.CompareNoCase(prefix);
756 else
757 return 0 == _src.Compare(prefix);
758 }
759 return false;
760}
761
763{
764 if (IsEmpty()) return;
765
766 const wchar_t * pbuf = m_pszData;
767 const wchar_t * p = pbuf;
768 //look for start
769 while (*p)
770 {
771 if (!IsBlankChar(*p)) break;
772 p++;
773 }
774 const wchar_t * p1 = p; //get start
775 //look for end
776 const wchar_t * p2 = pbuf + GetLength() - 1;
777 while (p2 >= p1)
778 {
779 if (!IsBlankChar(*p2)) break;
780 p2--;
781 }
782 if (p2 < p1)
783 Empty();
784 else
785 (*this) = SStringW(p1, (int)(p2 - p1 + 1));
786}
787
788bool SStringW::IsBlankChar(const wchar_t &c)
789{
790 const wchar_t szBlank[] = { 0x0a,0x0d,0x20,0x09 };
791 for (int i = 0; i < ARRAYSIZE(szBlank); i++)
792 {
793 if (c == szBlank[i]) return true;
794 }
795 return false;
796}
797
798void SStringW::Trim(wchar_t ch /*= VK_SPACE*/)
799{
800 TrimRight(ch);
801 TrimLeft(ch);
802}
803
804void SStringW::TrimLeft(wchar_t chTarget /*= VK_SPACE*/)
805{
807
808 // find first non-matching character
809 wchar_t* psz = m_pszData;
810
811 while (chTarget == *psz)
812 psz = wchar_traits::CharNext(psz);
813
814 if (psz != m_pszData)
815 {
816 // fix up data and length
817 TStringData* pData = GetData();
818 int nDataLength = pData->nDataLength - (int)(psz - m_pszData);
819 memmove(m_pszData, psz, (nDataLength + 1) * sizeof(wchar_t));
820 pData->nDataLength = nDataLength;
821 }
822}
823
824void SStringW::TrimRight(wchar_t chTarget /*= VK_SPACE*/)
825{
827
828 // find beginning of trailing matches
829 // by starting at beginning (DBCS aware)
830 wchar_t* psz = m_pszData;
831 wchar_t* pszLast = NULL;
832
833 while (*psz != '\0')
834 {
835 if (*psz == chTarget)
836 {
837 if (pszLast == NULL)
838 pszLast = psz;
839 }
840 else
841 pszLast = NULL;
842 psz = wchar_traits::CharNext(psz);
843 }
844
845 if (pszLast != NULL)
846 {
847 // truncate at left-most matching character
848 *pszLast = '\0';
849 GetData()->nDataLength = (int)(pszLast - m_pszData);
850 }
851}
852
854{
856
857 if (m_pszData != NULL)
859}
860
862{
864
865 if (m_pszData != NULL)
867}
868
870 ToLower();
871 return *this;
872}
873
875 ToUpper();
876 return *this;
877}
878
879SStringW SStringW::Left(int nCount) const
880{
881 TStringData* pData = GetData();
882 if (nCount < 0)
883 nCount = 0;
884 else if (nCount > pData->nDataLength)
885 nCount = pData->nDataLength;
886
887 SStringW dest;
888 AllocCopy(dest, nCount, 0, 0);
889 return dest;
890}
891
892SStringW SStringW::Right(int nCount) const
893{
894 TStringData* pData = GetData();
895 if (nCount < 0)
896 nCount = 0;
897 else if (nCount > pData->nDataLength)
898 nCount = pData->nDataLength;
899
900 SStringW dest;
901 AllocCopy(dest, nCount, pData->nDataLength - nCount, 0);
902 return dest;
903}
904
905SStringW SStringW::Mid(int nFirst, int nCount) const
906{
907 // out-of-bounds requests return sensible things
908 if (nFirst < 0)
909 nFirst = 0;
910 if (nCount < 0)
911 nCount = 0;
912
913 TStringData* pData = GetData();
914 if (nFirst + nCount > pData->nDataLength)
915 nCount = pData->nDataLength - nFirst;
916 if (nFirst > pData->nDataLength)
917 nCount = 0;
918
919 SStringW dest;
920 AllocCopy(dest, nCount, nFirst, 0);
921 return dest;
922}
923
924SStringW SStringW::Mid(int nFirst) const
925{
926 return Mid(nFirst, GetData()->nDataLength - nFirst);
927}
928
929int SStringW::CompareNoCase(const wchar_t* psz) const
930{
932}
933
934int SStringW::Compare(const wchar_t* psz) const
935{
936 return wchar_traits::Compare(m_pszData, psz);
937}
938
940{
941 SStringW strCopy(src);
942 ConcatInPlace(strCopy.GetData()->nDataLength, strCopy.m_pszData);
943 return *this;
944}
945
946void SStringW::AppendStr(const wchar_t * psz, int nLen)
947{
948 if(nLen < 0) nLen = (int)wchar_traits::StrLen(psz);
949 ConcatInPlace(nLen, psz);
950}
951
952void SStringW::AppendChar(wchar_t ch)
953{
954 ConcatInPlace(1, &ch);
955}
956
958{
959 return Append(src);
960}
961
963{
964 return Append(ch);
965}
966
967const SStringW& SStringW::operator+=(const wchar_t* psz)
968{
969 return Append(psz);
970}
971
973{
974 AssignCopy(1, &ch);
975 return *this;
976}
977
978SStringW& SStringW::operator=(const wchar_t* psz)
979{
980 SStringW strCopy(psz);
981 AssignCopy(strCopy.GetData()->nDataLength, strCopy.m_pszData);
982 return *this;
983}
984
986{
987 if (m_pszData != stringSrc.m_pszData)
988 {
989 TStringData* pData = GetData();
990 if ((pData->IsLocked() && pData != TStringData::InitDataNil()) || stringSrc.GetData()->IsLocked())
991 {
992 // actual copy necessary since one of the strings is locked
993 AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pszData);
994 }
995 else
996 {
997 // can just copy references around
998 _ReleaseData();
999 SASSERT(stringSrc.GetData() != TStringData::InitDataNil());
1000 m_pszData = stringSrc.m_pszData;
1001 GetData()->AddRef();
1002 }
1003 }
1004 return *this;
1005}
1006
1007const wchar_t * SStringW::c_str() const
1008{
1009 return m_pszData;
1010}
1011
1012SStringW::operator const wchar_t*() const // as a C string
1013{
1014 return m_pszData;
1015}
1016
1017void SStringW::SetAt(int nIndex, wchar_t ch)
1018{
1019 SASSERT(nIndex >= 0);
1020 SASSERT(nIndex < GetData()->nDataLength);
1021
1023 m_pszData[nIndex] = ch;
1024}
1025
1026wchar_t SStringW::operator[](int nIndex) const
1027{
1028 // same as GetAt
1029 SASSERT(nIndex >= 0);
1030 SASSERT(nIndex < GetData()->nDataLength);
1031 return m_pszData[nIndex];
1032}
1033
1034wchar_t SStringW::GetAt(int nIndex) const
1035{
1036 SASSERT(nIndex >= 0);
1037 SASSERT(nIndex < GetData()->nDataLength);
1038 return m_pszData[nIndex];
1039}
1040
1041void SStringW::Empty() // free up the data
1042{
1043 TStringData* pData = GetData();
1044 if (pData->nDataLength == 0)
1045 return;
1046
1047 if (pData->nRefs >= 0)
1048 _ReleaseData();
1049 else
1050 {
1051 wchar_t sz[1] = { 0 };
1052 *this = sz;
1053 }
1054
1055 SASSERT(GetData()->nDataLength == 0);
1056 SASSERT(GetData()->IsLocked() || GetData()->nAllocLength == 0);
1057}
1058
1060{
1061 return GetData()->nDataLength == 0;
1062}
1063
1065{
1066 return GetData()->nDataLength;
1067}
1068
1069void SStringW::Copy(const IStringW *pSrc)
1070{
1071 if (m_pszData != pSrc->c_str())
1072 {
1073 const TStringData * pDataSrc = (const TStringData *)pSrc->GetPrivData();
1074 TStringData* pData = GetData();
1075 if ((pData->IsLocked() && pData != TStringData::InitDataNil()) || pDataSrc->IsLocked())
1076 {
1077 // actual copy necessary since one of the strings is locked
1078 AssignCopy(pDataSrc->nDataLength, pSrc->c_str());
1079 }
1080 else
1081 {
1082 // can just copy references around
1083 _ReleaseData();
1084 SASSERT(pDataSrc != TStringData::InitDataNil());
1085 m_pszData = (wchar_t*)pSrc->c_str();
1086 GetData()->AddRef();
1087 }
1088 }
1089
1090 AssignCopy(pSrc->GetLength(),pSrc->c_str());
1091}
1092
1093void SStringW::Assign(LPCWSTR src)
1094{
1095 AssignCopy((int)wcslen(src),src);
1096}
1097
1098void SStringW::Assign2(LPCWSTR src,int nLen)
1099{
1100 AssignCopy(nLen,src);
1101}
1102
1104{
1105 return GetData();
1106}
1107
1108
1109
1111{
1112 // free any attached data
1113 TStringData* pData = GetData();
1114 if (pData != TStringData::InitDataNil())
1115 pData->Release();
1116}
1117
1118SStringW::SStringW(const wchar_t* psz)
1119{
1120 Init();
1121 int nLength = SafeStrlen(psz);
1122 if (nLength != 0)
1123 {
1124 if (AllocBuffer(nLength))
1125 memcpy(m_pszData, psz, nLength * sizeof(wchar_t));
1126 }
1127}
1128
1129SStringW::SStringW(const wchar_t* psz, int nLength)
1130{
1131 Init();
1132 if (nLength < 0) nLength = SafeStrlen(psz);
1133 if (nLength != 0)
1134 {
1135 if (AllocBuffer(nLength))
1136 memcpy(m_pszData, psz, nLength * sizeof(wchar_t));
1137 }
1138}
1139
1140SStringW::SStringW(wchar_t ch, int nLength /*= 1*/)
1141{
1142 Init();
1143 if (nLength >= 1)
1144 {
1145 if (AllocBuffer(nLength))
1146 {
1147 for (int i = 0; i < nLength; i++)
1148 m_pszData[i] = ch;
1149 }
1150 }
1151}
1152
1153
1154void SStringW::InitFromIString(const IStringW *src)
1155{
1156 TStringData *pData = (TStringData*)src->GetPrivData();
1157 SASSERT(pData->nRefs != 0);
1158 if (pData->nRefs >= 0)
1159 {
1160 SASSERT(pData != TStringData::InitDataNil());
1161 m_pszData = (wchar_t*)pData->data();
1162 GetData()->AddRef();
1163 }
1164 else
1165 {
1166 Init();
1167 m_pszData = (wchar_t*)pData->data();
1168 }
1169}
1170
1171SStringW::SStringW(const IStringW * stringSrc)
1172{
1173 InitFromIString(stringSrc);
1174}
1175
1177{
1178 InitFromIString(&stringSrc);
1179}
1180
1182{
1183 Init();
1184}
1185
1187{
1188 delete this;
1189}
1190
1191
1193{
1194 return (UINT)_wtoi(m_pszData);
1195}
1196
1198{
1199 return _wtol(m_pszData);
1200}
1201
1203{
1204 return _wtoi(m_pszData);
1205}
1207{
1208 return (float)_wtof(m_pszData);
1209}
1211{
1212 return _wtof(m_pszData);
1213}
1215{
1216 return _wtoi(m_pszData) != 0;
1217}
1218SNSEND
SStringW()
Default constructor.
void Empty()
Empties the string.
void Assign2(LPCWSTR src, int nLen)
Assigns a substring of a character array to the string.
bool AllocBuffer(int nLength)
Allocates memory for the string buffer.
Definition sstringw.cpp:210
int CompareNoCase(const wchar_t *psz) SCONST
Compares the string with another string, ignoring case.
Definition sstringw.cpp:929
void ReleaseBuffer(int nNewLength=-1)
Releases the buffer and sets the new length of the string.
Definition sstringw.cpp:426
static bool IsBlankChar(const wchar_t &c)
Checks if a character is a blank character.
Definition sstringw.cpp:788
bool ReallocBuffer(int nNewLength)
Reallocates memory for the string buffer.
Definition sstringw.cpp:180
void AssignCopy(int nSrcLen, const wchar_t *pszSrcData)
Assigns a substring of a character array to the string.
Definition sstringw.cpp:295
void SetLength(int nLength)
Sets the length of the string.
Definition sstringw.cpp:402
void TrimBlank()
Trims leading and trailing whitespace characters from the string.
Definition sstringw.cpp:762
LPVOID GetPrivData() SCONST
Retrieves private data associated with the string.
long ToLong() SCONST OVERRIDE
Converts the string to a long integer.
int Remove(wchar_t chRemove)
Removes all occurrences of a character from the string.
Definition sstringw.cpp:551
void AllocCopy(SStringW &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const
Allocates and copies a substring of the string.
Definition sstringw.cpp:305
void AppendChar(wchar_t ch) OVERRIDE
Appends a character to the string.
Definition sstringw.cpp:952
SStringW & operator=(const SStringW &stringSrc)
Overloaded assignment operator from another SStringW object.
Definition sstringw.cpp:985
void Preallocate(int nLength)
Preallocates memory for the string buffer.
Definition sstringw.cpp:395
int Replace(const wchar_t *pszOld, const wchar_t *pszNew)
Replaces all occurrences of a substring with another substring.
Definition sstringw.cpp:575
const wchar_t * c_str() SCONST
Retrieves a C-style string representation of the string.
int ReplaceChar(wchar_t chOld, wchar_t chNew)
Replaces all occurrences of a character with another character.
Definition sstringw.cpp:636
BOOL IsEmpty() SCONST
Checks if the string is empty.
void InitFromIString(const IStringW *stringSrc)
Initializes the string from an IStringW object.
int Compare(const wchar_t *psz) SCONST
Compares the string with another string.
Definition sstringw.cpp:934
void FreeExtra()
Frees any extra allocated memory in the string buffer.
Definition sstringw.cpp:383
wchar_t * GetBufferSetLength(int nNewLength)
Retrieves a modifiable buffer for the string and sets the new length.
Definition sstringw.cpp:414
void TrimLeft(wchar_t chTarget=VK_SPACE) OVERRIDE
Trims leading whitespace characters from the string.
Definition sstringw.cpp:804
void Copy(const IStringW *src)
Copies the contents of another string into this string.
bool AllocBeforeWrite(int nLen)
Allocates memory for the string before writing to it.
Definition sstringw.cpp:221
void Trim(wchar_t chTarget=VK_SPACE) OVERRIDE
Trims leading and trailing whitespace characters from the string.
Definition sstringw.cpp:798
void _ReleaseData()
Releases the data structure of the string.
Definition sstringw.cpp:169
int GetAllocLength() const
Retrieves the allocated length of the string buffer.
Definition sstringw.cpp:377
int FindChar(wchar_t ch, int nStart=0) SCONST
Finds the first occurrence of a character in the string.
Definition sstringw.cpp:529
double ToDouble() SCONST OVERRIDE
Converts the string to a double.
void ConcatInPlace(int nSrcLen, const wchar_t *pszSrcData)
Concatenates a substring to the string in place.
Definition sstringw.cpp:246
SStringW Mid(int nFirst) const
Extracts a substring from the string.
Definition sstringw.cpp:924
static int SafeStrlen(const wchar_t *psz)
Computes the length of a null-terminated string safely.
Definition sstringw.cpp:372
BOOL __cdecl Format(HINSTANCE hInst, UINT nFormatID,...)
Formats a string using a format string and variable arguments.
Definition sstringw.cpp:490
SStringW & MakeLower()
Converts the string to lowercase.
Definition sstringw.cpp:869
bool EndsWith(const SStringW &suffix, bool IgnoreCase=false) const
Checks if the string ends with a specified suffix.
Definition sstringw.cpp:736
bool ConcatCopy(int nSrc1Len, const wchar_t *pszSrc1Data, int nSrc2Len, const wchar_t *pszSrc2Data)
Concatenates two substrings and copies the result to the string.
Definition sstringw.cpp:275
void Init()
Initializes the string.
Definition sstringw.cpp:361
SStringW & Append(const SStringW &src)
Appends another SStringW object to the string.
Definition sstringw.cpp:939
int InsertChar(int nIndex, wchar_t ch)
Inserts a character at a specified index.
Definition sstringw.cpp:711
void SetAt(int nIndex, wchar_t ch)
Sets the character at a specified index.
void TrimRight(wchar_t chTarget=VK_SPACE) OVERRIDE
Trims trailing whitespace characters from the string.
Definition sstringw.cpp:824
BOOL _Format(const wchar_t *pszFormat, va_list &args)
Formats a string using a format string and variable arguments.
Definition sstringw.cpp:338
BOOL ToBool() SCONST OVERRIDE
Converts the string to a boolean.
int Insert(int nIndex, const wchar_t *psz)
Inserts a substring at a specified index.
Definition sstringw.cpp:683
TStringData * GetData() const
Retrieves the data structure of the string.
Definition sstringw.cpp:366
float ToFloat() SCONST OVERRIDE
Converts the string to a float.
void _AppendFormat(const wchar_t *pszFormat, va_list &args)
Appends formatted data to the string using a format string and variable arguments.
Definition sstringw.cpp:324
void Assign(LPCWSTR src)
Assigns a character array to the string.
SStringW Right(int nCount) const
Extracts the rightmost part of the string.
Definition sstringw.cpp:892
void Release() OVERRIDE
Releases the string and its resources.
SStringW & MakeUpper()
Converts the string to uppercase.
Definition sstringw.cpp:874
wchar_t * GetBuffer(int nMinBufLength=-1)
Retrieves a modifiable buffer for the string.
Definition sstringw.cpp:439
int Delete(int nIndex, int nCount=1)
Deletes a substring from the string.
Definition sstringw.cpp:662
int ToInt() SCONST OVERRIDE
Converts the string to an integer.
void CopyBeforeWrite()
Copies the string before writing to it.
Definition sstringw.cpp:234
const SStringW & operator+=(const wchar_t *psz)
Overloaded concatenation operator with a character array.
Definition sstringw.cpp:967
wchar_t * m_pszData
Pointer to the ref counted string data.
Definition sstringw.h:763
static void ReleaseData(TStringData *pData)
Releases a data structure.
Definition sstringw.cpp:133
UINT ToUint() SCONST OVERRIDE
Converts the string to an unsigned integer.
void __cdecl AppendFormat(HINSTANCE hInst, UINT nFormatID,...)
Appends formatted data to the string using a format string and variable arguments.
Definition sstringw.cpp:469
int GetLength() SCONST
Retrieves the length of the string.
int Find(const wchar_t *pszSub, int nStart=0) SCONST
Finds the first occurrence of a substring in the string.
Definition sstringw.cpp:516
wchar_t GetAt(int nIndex) SCONST
Retrieves the character at a specified index.
SStringW Left(int nCount) const
Extracts the leftmost part of the string.
Definition sstringw.cpp:879
int ReverseFind(wchar_t ch) SCONST
Finds the last occurrence of a character in the string.
Definition sstringw.cpp:542
void ToUpper() OVERRIDE
Converts the string to uppercase.
Definition sstringw.cpp:861
wchar_t operator[](int nIndex) const
Retrieves the character at a specified index.
void ToLower() OVERRIDE
Converts the string to lowercase.
Definition sstringw.cpp:853
void AppendStr(const wchar_t *pszStr, int nLen=-1) OVERRIDE
Appends a substring to the string.
Definition sstringw.cpp:946
bool StartsWith(const SStringW &prefix, bool IgnoreCase=false) const
Checks if the string starts with a specified prefix.
Definition sstringw.cpp:749
~SStringW()
Destructor.
static TStringData * AllocData(int nLength, TStringData *pOldData=NULL)
Allocates a new data structure for the string.
Definition sstringw.cpp:142
BOOL LoadString(UINT nID, HINSTANCE hInst)
Loads a string resource from a module.
Definition sstringw.cpp:506
static int Compare(const wchar_t *psz1, const wchar_t *psz2)
Compares two strings lexicographically.
Definition sstringw.cpp:120
static wchar_t * CharNext(wchar_t *psz)
Moves to the next character in a string.
Definition sstringw.cpp:70
static wchar_t CharLower(wchar_t ch)
Converts a character to lowercase.
Definition sstringw.cpp:80
static size_t StrLen(const wchar_t *psz)
Computes the length of a null-terminated string.
Definition sstringw.cpp:125
static int CompareNoCase(const wchar_t *psz1, const wchar_t *psz2)
Compares two strings lexicographically, ignoring case.
Definition sstringw.cpp:115
static int LoadString(HINSTANCE hInst, UINT uID, wchar_t *lpBuffer, int nBufferMax)
Loads a string resource from a module.
Definition sstringw.cpp:9
static wchar_t * StrLower(wchar_t *psz)
Converts a string to lowercase.
Definition sstringw.cpp:90
static const wchar_t * StrRChr(const wchar_t *psz, wchar_t ch)
Finds the last occurrence of a character in a string.
Definition sstringw.cpp:105
static wchar_t * StrUpper(wchar_t *psz)
Converts a string to uppercase.
Definition sstringw.cpp:95
static const wchar_t * StrChr(const wchar_t *psz, wchar_t ch)
Finds the first occurrence of a character in a string.
Definition sstringw.cpp:110
static int Format(wchar_t **ppszDst, const wchar_t *pszFormat, va_list &args)
Formats a string using a format string and variable arguments.
Definition sstringw.cpp:18
static wchar_t CharUpper(wchar_t ch)
Converts a character to uppercase.
Definition sstringw.cpp:75
static int IsSpace(wchar_t ch)
Checks if a character is a whitespace character.
Definition sstringw.cpp:85
static const wchar_t * StrStr(const wchar_t *psz, const wchar_t *psz2)
Finds the first occurrence of a substring in a string.
Definition sstringw.cpp:100