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