2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FBaseString.cpp
20 * @brief This is the implementation for String class.
29 #include <FBaseString.h>
30 #include <FBaseInt8.h>
31 #include <FBaseShort.h>
32 #include <FBaseInteger.h>
33 #include <FBaseLong.h>
34 #include <FBaseLongLong.h>
35 #include <FBaseFloat.h>
36 #include <FBaseDouble.h>
37 #include <FBaseCharacter.h>
38 #include <FBaseResult.h>
39 #include <FBaseSysLog.h>
40 #include <unique_ptr.h>
43 namespace Tizen { namespace Base
46 const float String::GROWTH_FACTOR = 1.5;
56 result r = InitializeToDefault(DEFAULT_CAPACITY);
57 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
60 String::String(int capacity)
70 capacity = DEFAULT_CAPACITY;
73 result r = InitializeToDefault(capacity);
74 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
77 String::String(const wchar_t ch)
85 result r = InitializeToDefault(DEFAULT_CAPACITY);
86 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
93 String::String(const wchar_t* pValue)
101 int length = (pValue != null) ? wcslen(pValue) : 0;
103 SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
104 "String has wrong length. The length has to be more bigger than 0.");
108 result r = InitializeToDefault(DEFAULT_CAPACITY);
109 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
113 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
114 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
116 wcsncpy(__pValue, pValue, length);
117 __pValue[length] = '\0';
122 String::String(const char* pValue)
128 , __pStringImpl(null)
130 int len = (pValue != null) ? mbstowcs(null, pValue, 0) : 0;
134 result r = InitializeToDefault(DEFAULT_CAPACITY);
135 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
139 result r = InitializeToDefault(len + DEFAULT_CAPACITY);
140 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
142 len = mbstowcs(__pValue, pValue, len);
145 SysLog(NID_BASE, "Invalid encoding range[%s].", pValue);
147 __pValue[len] = '\0';
152 String::String(const String& value)
153 : __capacity(value.__capacity)
154 , __length(value.__length)
155 , __hash(value.__hash)
157 , __pValue(value.__pValue)
158 , __pStringImpl(null)
160 SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
162 ++(*value.__pRefCount);
163 __pRefCount = value.__pRefCount;
166 String::~String(void)
168 if (*__pRefCount == 1)
181 String::operator [](int index) const
183 static wchar_t ch = -1;
184 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
185 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
186 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
187 return __pValue[index];
191 String::operator [](int index)
193 static wchar_t ch = -1;
194 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
195 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
196 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
198 if (*__pRefCount > 1)
200 result r = CopyOnWrite(__capacity);
201 SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
205 return __pValue[index];
209 String::operator =(const wchar_t* pRhs)
223 String::operator =(const String& rhs)
237 String::operator +=(const wchar_t* pRhs)
250 String::operator +=(const String& rhs)
257 Append(rhs.__pValue);
263 operator +(const String& lhs, const String& rhs)
267 str.Append(rhs.__pValue);
273 String::operator ==(const String& rhs) const
275 if (__length != rhs.__length)
280 return(CompareTo(rhs) == 0);
284 String::operator !=(const String& rhs) const
286 return(!(*this).operator ==(rhs));
290 String::IsEmpty(void) const
292 return(__length == 0);
296 String::Append(wchar_t ch)
298 result r = Append(Character::ToString(ch));
299 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
305 String::Append(char ch)
307 result r = Append((wchar_t) ch);
308 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
314 String::Append(int i)
316 result r = Append(Integer::ToString(i));
317 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
323 String::Append(short s)
325 result r = Append(Short::ToString(s));
326 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
332 String::Append(long l)
334 result r = Append(Long::ToString(l));
335 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
341 String::Append(long long ll)
343 result r = Append(LongLong::ToString(ll));
344 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
350 String::Append(float f)
352 result r = Append(Float::ToString(f));
353 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
359 String::Append(double d)
361 result r = Append(Double::ToString(d));
362 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
368 String::Append(const wchar_t* p)
370 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
372 int length = (wcslen(p) + __length);
374 if (*__pRefCount > 1)
376 wchar_t* pValue = __pValue;
377 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
378 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
379 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
381 wcsncpy(__pValue, pValue, __length);
383 __pRefCount = pRefCntTemp.release();
386 result r = EnsureCapacity(length);
387 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
389 wcsncpy((__pValue + __length), p, wcslen(p));
391 __pValue[length] = '\0';
399 String::Append(const String& str)
406 result r = Append(str.__pValue);
407 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
420 String::Compare(const String& str0, const String& str1)
422 if (str0.__pValue == str1.__pValue)
427 return(wcscmp(str0.__pValue, str1.__pValue));
431 String::CompareTo(const String& str) const
433 if (__pValue == str.__pValue)
438 return(wcscmp(__pValue, str.__pValue));
442 String::EnsureCapacity(int minCapacity)
444 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
447 if (minCapacity > __capacity)
449 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
455 String::Equals(const Object& obj) const
457 const String* pOther = dynamic_cast <const String*>(&obj);
464 return(*this == *pOther);
468 String::Equals(const String& str, bool caseSensitive) const
472 return(*this == str);
476 if (__length != str.__length)
481 if (__pValue == str.__pValue)
486 if (wcscasecmp(__pValue, str.__pValue) == 0)
496 String::Format(int length, const wchar_t* pFormat, ...)
499 result r = E_SUCCESS;
501 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
502 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
505 String tempStr(pFormat);
506 if (tempStr.IsEmpty() || length == 0)
512 // Check "%n" and "%hn"
513 r = tempStr.IndexOf(L"%n", 0, index);
514 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
516 r = tempStr.IndexOf(L"%hn", 0, index);
517 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
521 std::unique_ptr<wchar_t []> pStr(new (std::nothrow) wchar_t[length + 1]);
522 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
526 va_start(args, pFormat);
528 vswprintf(pStr.get(), length, tempStr.__pValue, args);
534 int len = wcslen(this->__pValue);
537 this->__pValue[len] = '\0';
538 this->__length = len;
542 this->__pValue[length - 1] = '\0';
543 this->__length = length - 1;
551 String::GetHashCode(void) const
557 wchar_t* pStr = __pValue;
558 for (int i = 0; i < __length; ++i)
560 hash = (hash << 5) - hash + (int) *pStr++;
573 String::GetCharAt(int indexAt, wchar_t& ret) const
575 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
576 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
577 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
578 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
580 ret = __pValue[indexAt];
586 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
588 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
589 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
590 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
591 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
593 wchar_t* pBeg = __pValue + startIndex;
594 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
600 return E_OBJ_NOT_FOUND;
603 indexOf = int(pFound - __pValue);
609 String::IndexOf(const String& str, int startIndex, int& indexOf) const
611 SysTryReturnResult(NID_BASE, (startIndex < __length), E_OUT_OF_RANGE,
612 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
613 SysTryReturnResult(NID_BASE, (startIndex >= 0), E_OUT_OF_RANGE,
614 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
618 indexOf = startIndex;
622 if (__length < str.__length)
625 return E_OBJ_NOT_FOUND;
630 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
635 return E_OBJ_NOT_FOUND;
638 indexOf = int(p - __pValue);
644 String::Insert(wchar_t ch, int indexAt)
646 SysTryReturnResult(NID_BASE,
647 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
648 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
651 if (*__pRefCount > 1)
653 result r = CopyOnWrite(__capacity);
654 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
657 int length = (__length + 1);
659 result r = EnsureCapacity(length);
660 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
662 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
664 __pValue[indexAt] = ch;
672 String::Insert(char ch, int indexAt)
674 wchar_t wideChar = (wchar_t) ch;
676 result r = Insert(wideChar, indexAt);
677 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
683 String::Insert(short s, int indexAt)
685 result r = Insert(Short::ToString(s), indexAt);
686 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
692 String::Insert(int i, int indexAt)
694 result r = Insert(Integer::ToString(i), indexAt);
695 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
701 String::Insert(long l, int indexAt)
703 result r = Insert(Long::ToString(l), indexAt);
704 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
710 String::Insert(long long ll, int indexAt)
712 result r = Insert(LongLong::ToString(ll), indexAt);
713 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
719 String::Insert(float f, int indexAt)
721 result r = Insert(Float::ToString(f), indexAt);
722 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
728 String::Insert(double d, int indexAt)
730 result r = Insert(Double::ToString(d), indexAt);
731 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
736 String::Insert(const wchar_t* p, int indexAt)
738 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
739 SysTryReturnResult(NID_BASE,
740 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
741 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
744 int length = wcslen(p);
750 if (*__pRefCount > 1)
752 result r = CopyOnWrite(__capacity);
753 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
756 result r = EnsureCapacity(__length + length);
757 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
759 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
760 wmemcpy((__pValue + indexAt), p, length);
768 String::Insert(const String& str, int indexAt)
770 result r = Insert(str.__pValue, indexAt);
771 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
777 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
779 SysTryReturnResult(NID_BASE,
780 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
781 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
782 startIndex, __length);
784 wchar_t* pBeg = __pValue + startIndex;
785 wchar_t* pEnd = __pValue;
790 indexOf = int(pBeg - __pValue);
799 return E_OBJ_NOT_FOUND;
803 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
805 SysTryReturnResult(NID_BASE,
806 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
807 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
808 startIndex, __length);
812 indexOf = startIndex;
816 if (__length < str.__length)
820 return E_OBJ_NOT_FOUND;
823 const wchar_t* pStr = str.__pValue;
825 int length = str.__length;
826 if (length > startIndex)
830 return E_OBJ_NOT_FOUND;
834 wchar_t* pBeg = __pValue + startIndex;
835 wchar_t* pEnd = __pValue;
839 if (wcsncmp(pBeg, pStr, length) == 0)
841 indexOf = (pBeg - __pValue);
848 return E_OBJ_NOT_FOUND;
852 String::Remove(int startIndex, int count)
854 SysTryReturnResult(NID_BASE,
855 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
856 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
857 startIndex, __length);
858 int moveIndex = startIndex + count;
859 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
860 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
861 startIndex, count, __length);
863 if (*__pRefCount > 1)
865 result r = CopyOnWrite(__capacity);
866 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
869 wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
871 __pValue[__length] = '\0';
878 String::Replace(wchar_t original, wchar_t replace)
880 if (*__pRefCount > 1)
882 result r = CopyOnWrite(__capacity);
883 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
886 for (int length = __length; length >= 0; --length)
888 if (__pValue[length] == original)
890 __pValue[length] = replace;
897 String::Replace(const String& org, const String& rep)
899 result r = Replace(org, rep, 0);
900 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
906 String::Replace(const String& org, const String& rep, int startIndex)
908 const int orgLen = org.__length;
909 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
911 SysTryReturnResult(NID_BASE,
912 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
913 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
914 startIndex, __length);
921 if ((orgLen == __length) && (*this == org))
923 const int newLength = rep.__length;
924 if (EnsureCapacity(newLength) != E_SUCCESS)
926 SetCapacity(newLength);
929 wcsncpy(__pValue, rep.__pValue, rep.__length);
931 __length = rep.__length;
932 __pValue[__length] = '\0';
938 int repLen = rep.__length;
940 wchar_t* pOrg = org.__pValue;
941 wchar_t* pRep = rep.__pValue;
945 wchar_t* pBeg = (__pValue + startIndex);
946 wchar_t* pEnd = pBeg + __length;
949 wchar_t* pTarget = null;
950 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
953 pBeg = pTarget + orgLen;
955 pBeg += wcslen(pBeg) + 1;
961 if (*__pRefCount > 1)
963 result r = CopyOnWrite(__capacity);
964 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
967 const int newLength = (count * (repLen - orgLen)) + __length;
968 result r = EnsureCapacity(newLength);
969 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
971 wchar_t* pBeg = (__pValue + startIndex);
972 wchar_t* pEnd = pBeg + __length;
975 wchar_t* pTarget = null;
976 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
978 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
979 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
980 wmemcpy(pTarget, pRep, repLen);
981 pBeg = pTarget + repLen;
982 pTarget[repLen + balance] = 0;
983 __length += (repLen - orgLen);
985 pBeg += (wcslen(pBeg) + 1);
988 __length = newLength;
996 String::Reverse(void)
998 if (*__pRefCount > 0)
1000 result r = CopyOnWrite(__capacity);
1001 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1004 wchar_t* pBeg = __pValue;
1005 wchar_t* pEnd = __pValue + __length - 1;
1008 for (; pBeg < pEnd; ++pBeg, --pEnd)
1018 String::SetCapacity(int capacity)
1020 SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1021 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1023 std::unique_ptr<wchar_t []> pValue(new (std::nothrow) wchar_t[capacity + 1]);
1024 SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1026 if (__pValue != null)
1028 if (__length < capacity)
1030 wmemcpy(pValue.get(), __pValue, (__length + 1));
1034 wmemcpy(pValue.get(), __pValue, capacity);
1035 pValue[capacity] = '\0';
1036 __length = capacity;
1040 if (*__pRefCount == 1)
1046 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1047 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1049 __pRefCount = pRefCntTemp.release();
1053 __pValue = pValue.release();
1054 __capacity = capacity;
1060 String::SetCharAt(wchar_t ch, int indexAt)
1062 SysTryReturn(NID_BASE,indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1063 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1064 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1066 if (*__pRefCount > 1)
1068 result r = CopyOnWrite(__capacity);
1069 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1072 __pValue[indexAt] = ch;
1079 String::SetLength(int newLength)
1081 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1084 if (*__pRefCount > 1)
1086 result r = CopyOnWrite(__capacity);
1087 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1090 static const wchar_t SPACE = 0x0020;
1092 result r = EnsureCapacity(newLength);
1093 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1095 if (newLength > __length)
1097 wmemset(__pValue + __length, SPACE, newLength - __length);
1100 __pValue[newLength] = '\0';
1101 __length = newLength;
1108 String::SubString(int startIndex, String& out) const
1110 SysTryReturnResult(NID_BASE,
1111 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1112 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1113 startIndex, __length);
1115 out = __pValue + startIndex;
1121 String::SubString(int startIndex, int length, String& out) const
1123 SysTryReturnResult(NID_BASE,
1124 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1125 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1126 startIndex, __length);
1127 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1128 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1129 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1130 startIndex, length, __length);
1134 std::unique_ptr<wchar_t []> pTemp(new (std::nothrow) wchar_t[length + 1]);
1135 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1136 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1137 pTemp[length] = '\0';
1141 else if (length == 0)
1150 String::StartsWith(const String& str, int startIndex) const
1152 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1153 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1154 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1155 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1156 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1157 GetErrorMessage(E_INVALID_ARG), str.__length);
1159 if (str.__length > __length)
1164 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1173 String::EndsWith(const String& str) const
1180 int strLen = str.__length;
1181 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1182 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1184 int curLen = __length;
1185 if (strLen > curLen || curLen == 0)
1189 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1198 String::ToLower(String& out) const
1200 String str(__length + 1);
1202 wchar_t* pDst = str.__pValue;
1203 wchar_t* pSrc = __pValue;
1205 for (; *pSrc != 0; ++pSrc, ++pDst)
1207 *pDst = Character::ToLower(*pSrc);
1212 str.__length = __length;
1219 String::ToLowerCase(String& out) const
1221 String str(__length + 1);
1223 wchar_t* pDst = str.__pValue;
1224 wchar_t* pSrc = __pValue;
1226 for (; *pSrc != 0; ++pSrc, ++pDst)
1228 *pDst = Character::ToLowerCase(*pSrc);
1233 str.__length = __length;
1240 String::ToUpper(String& out) const
1242 String str(__length + 1);
1244 wchar_t* pDst = str.__pValue;
1245 wchar_t* pSrc = __pValue;
1247 for (; *pSrc != 0; ++pSrc, ++pDst)
1249 *pDst = Character::ToUpper(*pSrc);
1254 str.__length = __length;
1261 String::ToUpperCase(String& out) const
1263 String str(__length + 1);
1265 wchar_t* pDst = str.__pValue;
1266 wchar_t* pSrc = __pValue;
1267 for (; *pSrc != 0; ++pSrc, ++pDst)
1269 *pDst = Character::ToUpperCase(*pSrc);
1274 str.__length = __length;
1281 String::ToLower(void)
1283 if (*__pRefCount > 1)
1285 result r = CopyOnWrite(__capacity);
1286 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1289 String str(__length + 1);
1291 wchar_t* pDst = str.__pValue;
1292 wchar_t* pSrc = __pValue;
1294 for (; *pSrc != 0; ++pSrc, ++pDst)
1296 *pDst = Character::ToLower(*pSrc);
1299 wcsncpy(__pValue, str.__pValue, __length);
1300 __pValue[__length] = '\0';
1305 String::ToLowerCase(void)
1307 if (*__pRefCount > 0)
1309 result r = CopyOnWrite(__capacity);
1310 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1313 String str(__length + 1);
1315 wchar_t* pDst = str.__pValue;
1316 wchar_t* pSrc = __pValue;
1318 for (; *pSrc != 0; ++pSrc, ++pDst)
1320 *pDst = Character::ToLowerCase(*pSrc);
1323 wcsncpy(__pValue, str.__pValue, __length);
1324 __pValue[__length] = '\0';
1329 String::ToUpper(void)
1331 if (*__pRefCount > 1)
1333 result r = CopyOnWrite(__capacity);
1334 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1337 String str(__length + 1);
1339 wchar_t* pDst = str.__pValue;
1340 wchar_t* pSrc = __pValue;
1342 for (; *pSrc != 0; ++pSrc, ++pDst)
1344 *pDst = Character::ToUpper(*pSrc);
1347 wcsncpy(__pValue, str.__pValue, __length);
1348 __pValue[__length] = '\0';
1353 String::ToUpperCase(void)
1355 if (*__pRefCount > 1)
1357 result r = CopyOnWrite(__capacity);
1358 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1361 String str(__length + 1);
1363 wchar_t* pDst = str.__pValue;
1364 wchar_t* pSrc = __pValue;
1366 for (; *pSrc != 0; ++pSrc, ++pDst)
1368 *pDst = Character::ToUpperCase(*pSrc);
1371 wcsncpy(__pValue, str.__pValue, __length);
1372 __pValue[__length] = '\0';
1385 int lastIndex = __length;
1387 const wchar_t* pStr = __pValue;
1389 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1394 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1400 if (lastIndex < __length)
1402 Remove(lastIndex, __length - lastIndex);
1408 Remove(0, startIndex);
1413 String::GetCapacity(void) const
1415 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1419 String::GetLength(void) const
1425 String::GetPointer(void) const
1432 String::Contains(const String& str) const
1434 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1435 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1436 GetErrorMessage(E_INVALID_ARG), str.__length);
1442 else if ((__length == str.__length) && (*this == str))
1447 wchar_t* pStart = __pValue;
1448 wchar_t* pEnd = pStart + __length;
1449 while (pStart < pEnd)
1451 while (wcsstr(pStart, str.__pValue) != null)
1462 String::AllocateCapacity(int capacity)
1464 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1465 if (__pValue == null)
1467 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1472 __pValue[capacity] = '\0';
1473 __capacity = capacity;
1479 String::ExpandCapacity(int minCapacity)
1481 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1483 if (minCapacity > capacity)
1485 capacity = minCapacity;
1488 std::unique_ptr<wchar_t []> pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1489 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1490 GetErrorMessage(E_OUT_OF_MEMORY));
1492 if (__pValue != null)
1494 wmemcpy(pNewValue.get(), __pValue, __length);
1495 pNewValue[__length] = '\0';
1497 if (*__pRefCount == 1)
1503 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1504 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1505 GetErrorMessage(E_OUT_OF_MEMORY));
1507 __pRefCount = pRefCntTemp.release();
1510 __pValue = pNewValue.release();
1511 __pValue[capacity] = '\0';
1512 __capacity = capacity;
1518 String::InitializeToDefault(int capacity)
1520 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1521 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1522 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1524 __pRefCount = pRefCntTemp.release();
1529 String::CopyOnWrite(int capacity)
1531 wchar_t* pValue = __pValue;
1532 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1533 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1534 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1536 wcsncpy(__pValue, pValue, __length);
1537 __pValue[__length] = '\0';
1539 __pRefCount = pRefCntTemp.release();
1544 String::Swap(String& str)
1546 std::swap(__capacity, str.__capacity);
1547 std::swap(__length, str.__length);
1548 std::swap(__hash, str.__hash);
1549 std::swap(__pRefCount, str.__pRefCount);
1550 std::swap(__pValue, str.__pValue);
1551 std::swap(__pStringImpl, str.__pStringImpl);