2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FBaseString.cpp
19 * @brief This is the implementation for String class.
28 #include <FBaseString.h>
29 #include <FBaseInt8.h>
30 #include <FBaseShort.h>
31 #include <FBaseInteger.h>
32 #include <FBaseLong.h>
33 #include <FBaseLongLong.h>
34 #include <FBaseFloat.h>
35 #include <FBaseDouble.h>
36 #include <FBaseCharacter.h>
37 #include <FBaseResult.h>
38 #include <FBaseSysLog.h>
39 #include <unique_ptr.h>
40 #include "FBase_String.h"
41 #include "FBaseUtil_IcuConverter.h"
44 namespace Tizen { namespace Base
47 const float String::GROWTH_FACTOR = 1.5;
48 const int String::UNSHAREABLE = Integer::VALUE_MAX;
58 result r = InitializeToDefault(DEFAULT_CAPACITY);
59 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
62 String::String(int capacity)
72 capacity = DEFAULT_CAPACITY;
75 result r = InitializeToDefault(capacity);
76 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
79 String::String(wchar_t ch)
87 result r = InitializeToDefault(DEFAULT_CAPACITY);
88 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
95 String::String(const wchar_t* pValue)
101 , __pStringImpl(null)
103 int length = (pValue != null) ? wcslen(pValue) : 0;
105 SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
106 "String has wrong length. The length has to be more bigger than 0.");
110 result r = InitializeToDefault(DEFAULT_CAPACITY);
111 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
115 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
116 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
118 wcsncpy(__pValue, pValue, length);
119 __pValue[length] = '\0';
124 String::String(const char* pValue)
130 , __pStringImpl(null)
132 if (pValue == null || strlen(pValue) == 0)
134 result r = InitializeToDefault(DEFAULT_CAPACITY);
135 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
139 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
140 SysTryReturnVoidResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
142 std::unique_ptr< wchar_t[] > pStr(Tizen::Base::Utility::Utf8ToWcharN(pValue));
143 SysTryReturnVoidResult(NID_BASE, pStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
145 __pRefCount = pRefCntTemp.release();
146 __pValue = pStr.release();
147 __length = wcslen(__pValue);
148 __capacity = __length + DEFAULT_CAPACITY;
149 __pValue[__length] = '\0';
153 String::String(const String& value)
159 , __pStringImpl(null)
161 SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
163 if (*(value.__pRefCount) != UNSHAREABLE)
165 _String::AtomicInc(value.__pRefCount);
166 __pRefCount = value.__pRefCount;
167 __pValue = value.__pValue;
168 __capacity = value.__capacity;
169 __length = value.__length;
170 __hash = value.__hash;
174 int length = wcslen(value.__pValue);
176 SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
177 "String has wrong length. The length has to be more bigger than 0.");
179 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
180 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
182 wcsncpy(__pValue, value.__pValue, length);
183 __pValue[length] = '\0';
188 String::~String(void)
190 if (*__pRefCount == 1 || *__pRefCount == UNSHAREABLE)
197 _String::AtomicDec(__pRefCount);
203 String::operator [](int index) const
205 static wchar_t ch = -1;
206 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
207 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
208 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
209 return __pValue[index];
213 String::operator [](int index)
215 static wchar_t ch = -1;
216 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
217 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
218 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
220 result r = AboutToModify(__capacity, true);
221 SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
224 return __pValue[index];
228 String::operator =(const wchar_t* pRhs)
242 String::operator =(const String& rhs)
256 String::operator +=(const wchar_t* pRhs)
269 String::operator +=(const String& rhs)
276 Append(rhs.__pValue);
282 operator +(const String& lhs, const String& rhs)
286 str.Append(rhs.__pValue);
292 String::operator ==(const String& rhs) const
294 if (__length != rhs.__length)
299 return(CompareTo(rhs) == 0);
303 String::operator !=(const String& rhs) const
305 return(!(*this).operator ==(rhs));
309 String::IsEmpty(void) const
311 return(__length == 0);
315 String::Append(wchar_t ch)
317 result r = Append(Character::ToString(ch));
318 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
324 String::Append(char ch)
326 result r = Append((wchar_t) ch);
327 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
333 String::Append(int i)
335 result r = Append(Integer::ToString(i));
336 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
342 String::Append(short s)
344 result r = Append(Short::ToString(s));
345 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
351 String::Append(long l)
353 result r = Append(Long::ToString(l));
354 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
360 String::Append(long long ll)
362 result r = Append(LongLong::ToString(ll));
363 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
369 String::Append(float f)
371 result r = Append(Float::ToString(f));
372 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
378 String::Append(double d)
380 result r = Append(Double::ToString(d));
381 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
387 String::Append(const wchar_t* p)
389 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
391 int length = (wcslen(p) + __length);
393 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
395 wchar_t* pValue = __pValue;
396 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
397 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
398 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
400 wcsncpy(__pValue, pValue, __length);
401 _String::AtomicDec(__pRefCount);
402 __pRefCount = pRefCntTemp.release();
405 result r = EnsureCapacity(length);
406 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
408 wcsncpy((__pValue + __length), p, wcslen(p));
410 __pValue[length] = '\0';
418 String::Append(const String& str)
425 result r = Append(str.__pValue);
426 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
439 String::Compare(const String& str0, const String& str1)
441 if (str0.__pValue == str1.__pValue)
446 return(wcscmp(str0.__pValue, str1.__pValue));
450 String::CompareTo(const String& str) const
452 if (__pValue == str.__pValue)
457 return(wcscmp(__pValue, str.__pValue));
461 String::EnsureCapacity(int minCapacity)
463 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
466 if (minCapacity > __capacity)
468 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
474 String::Equals(const Object& obj) const
476 const String* pOther = dynamic_cast< const String* >(&obj);
483 return(*this == *pOther);
487 String::Equals(const String& str, bool caseSensitive) const
491 return(*this == str);
495 if (__length != str.__length)
500 if (__pValue == str.__pValue)
505 if (wcscasecmp(__pValue, str.__pValue) == 0)
515 String::Format(int length, const wchar_t* pFormat, ...)
518 result r = E_SUCCESS;
520 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
521 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
524 String tempStr(pFormat);
525 if (tempStr.IsEmpty() || length == 0)
531 // Check "%n" and "%hn"
532 r = tempStr.IndexOf(L"%n", 0, index);
533 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
535 r = tempStr.IndexOf(L"%hn", 0, index);
536 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
540 std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
541 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
545 va_start(args, pFormat);
547 vswprintf(pStr.get(), length, tempStr.__pValue, args);
553 int len = wcslen(this->__pValue);
556 this->__pValue[len] = '\0';
557 this->__length = len;
561 this->__pValue[length - 1] = '\0';
562 this->__length = length - 1;
570 String::GetHashCode(void) const
576 wchar_t* pStr = __pValue;
577 for (int i = 0; i < __length; ++i)
579 hash = (hash << 5) - hash + (int) *pStr++;
592 String::GetCharAt(int indexAt, wchar_t& ret) const
594 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
595 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
596 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
597 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
599 ret = __pValue[indexAt];
605 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
607 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
608 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
609 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
610 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
612 wchar_t* pBeg = __pValue + startIndex;
613 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
619 return E_OBJ_NOT_FOUND;
622 indexOf = int(pFound - __pValue);
628 String::IndexOf(const String& str, int startIndex, int& indexOf) const
630 SysTryReturnResult(NID_BASE, (startIndex < __length), E_OUT_OF_RANGE,
631 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
632 SysTryReturnResult(NID_BASE, (startIndex >= 0), E_OUT_OF_RANGE,
633 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
637 indexOf = startIndex;
641 if (__length < str.__length)
644 return E_OBJ_NOT_FOUND;
649 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
654 return E_OBJ_NOT_FOUND;
657 indexOf = int(p - __pValue);
663 String::Insert(wchar_t ch, int indexAt)
665 SysTryReturnResult(NID_BASE,
666 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
667 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
670 result r = AboutToModify(__capacity);
671 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
673 int length = (__length + 1);
675 r = EnsureCapacity(length);
676 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
678 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
680 __pValue[indexAt] = ch;
688 String::Insert(char ch, int indexAt)
690 wchar_t wideChar = (wchar_t) ch;
692 result r = Insert(wideChar, indexAt);
693 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
699 String::Insert(short s, int indexAt)
701 result r = Insert(Short::ToString(s), indexAt);
702 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
708 String::Insert(int i, int indexAt)
710 result r = Insert(Integer::ToString(i), indexAt);
711 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
717 String::Insert(long l, int indexAt)
719 result r = Insert(Long::ToString(l), indexAt);
720 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
726 String::Insert(long long ll, int indexAt)
728 result r = Insert(LongLong::ToString(ll), indexAt);
729 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
735 String::Insert(float f, int indexAt)
737 result r = Insert(Float::ToString(f), indexAt);
738 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
744 String::Insert(double d, int indexAt)
746 result r = Insert(Double::ToString(d), indexAt);
747 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
752 String::Insert(const wchar_t* p, int indexAt)
754 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
755 SysTryReturnResult(NID_BASE,
756 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
757 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
760 int length = wcslen(p);
766 result r = AboutToModify(__capacity);
767 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
769 r = EnsureCapacity(__length + length);
770 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
772 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
773 wmemcpy((__pValue + indexAt), p, length);
781 String::Insert(const String& str, int indexAt)
783 result r = Insert(str.__pValue, indexAt);
784 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
790 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
792 SysTryReturnResult(NID_BASE,
793 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
794 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
795 startIndex, __length);
797 wchar_t* pBeg = __pValue + startIndex;
798 wchar_t* pEnd = __pValue;
803 indexOf = int(pBeg - __pValue);
812 return E_OBJ_NOT_FOUND;
816 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
818 SysTryReturnResult(NID_BASE,
819 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
820 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
821 startIndex, __length);
825 indexOf = startIndex;
829 if (__length < str.__length)
833 return E_OBJ_NOT_FOUND;
836 const wchar_t* pStr = str.__pValue;
838 int length = str.__length;
839 if (length > startIndex)
843 return E_OBJ_NOT_FOUND;
847 wchar_t* pBeg = __pValue + startIndex;
848 wchar_t* pEnd = __pValue;
852 if (wcsncmp(pBeg, pStr, length) == 0)
854 indexOf = (pBeg - __pValue);
861 return E_OBJ_NOT_FOUND;
865 String::Remove(int startIndex, int count)
867 SysTryReturnResult(NID_BASE,
868 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
869 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
870 startIndex, __length);
871 int moveIndex = startIndex + count;
872 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
873 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
874 startIndex, count, __length);
876 result r = AboutToModify(__capacity);
877 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
879 wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
881 __pValue[__length] = '\0';
888 String::Replace(wchar_t original, wchar_t replace)
890 result r = AboutToModify(__capacity);
891 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
893 for (int length = __length; length >= 0; --length)
895 if (__pValue[length] == original)
897 __pValue[length] = replace;
904 String::Replace(const String& org, const String& rep)
906 result r = Replace(org, rep, 0);
907 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
913 String::Replace(const String& org, const String& rep, int startIndex)
915 const int orgLen = org.__length;
916 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
918 SysTryReturnResult(NID_BASE,
919 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
920 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
921 startIndex, __length);
928 if ((orgLen == __length) && (*this == org))
930 const int newLength = rep.__length;
931 if (EnsureCapacity(newLength) != E_SUCCESS)
933 SetCapacity(newLength);
936 wcsncpy(__pValue, rep.__pValue, rep.__length);
938 __length = rep.__length;
939 __pValue[__length] = '\0';
945 int repLen = rep.__length;
947 wchar_t* pOrg = org.__pValue;
948 wchar_t* pRep = rep.__pValue;
952 wchar_t* pBeg = (__pValue + startIndex);
953 wchar_t* pEnd = pBeg + __length;
956 wchar_t* pTarget = null;
957 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
960 pBeg = pTarget + orgLen;
962 pBeg += wcslen(pBeg) + 1;
968 result r = AboutToModify(__capacity);
969 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
971 const int newLength = (count * (repLen - orgLen)) + __length;
972 r = EnsureCapacity(newLength);
973 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
975 wchar_t* pBeg = (__pValue + startIndex);
976 wchar_t* pEnd = pBeg + __length;
979 wchar_t* pTarget = null;
980 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
982 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
983 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
984 wmemcpy(pTarget, pRep, repLen);
985 pBeg = pTarget + repLen;
986 pTarget[repLen + balance] = 0;
987 __length += (repLen - orgLen);
989 pBeg += (wcslen(pBeg) + 1);
992 __length = newLength;
1000 String::Reverse(void)
1002 result r = AboutToModify(__capacity);
1003 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1005 wchar_t* pBeg = __pValue;
1006 wchar_t* pEnd = __pValue + __length - 1;
1009 for (; pBeg < pEnd; ++pBeg, --pEnd)
1019 String::SetCapacity(int capacity)
1021 SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1022 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1024 std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
1025 SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1027 if (__pValue != null)
1029 if (__length < capacity)
1031 wmemcpy(pValue.get(), __pValue, (__length + 1));
1035 wmemcpy(pValue.get(), __pValue, capacity);
1036 pValue[capacity] = '\0';
1037 __length = capacity;
1041 if (*__pRefCount == 1)
1047 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1048 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1049 _String::AtomicDec(__pRefCount);
1050 __pRefCount = pRefCntTemp.release();
1054 __pValue = pValue.release();
1055 __capacity = capacity;
1061 String::SetCharAt(wchar_t ch, int indexAt)
1063 SysTryReturn(NID_BASE,indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1064 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1065 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1067 result r = AboutToModify(__capacity);
1068 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1070 __pValue[indexAt] = ch;
1077 String::SetLength(int newLength)
1079 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1082 result r = AboutToModify(__capacity);
1083 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1085 static const wchar_t SPACE = 0x0020;
1087 r = EnsureCapacity(newLength);
1088 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1090 if (newLength > __length)
1092 wmemset(__pValue + __length, SPACE, newLength - __length);
1095 __pValue[newLength] = '\0';
1096 __length = newLength;
1103 String::SubString(int startIndex, String& out) const
1105 SysTryReturnResult(NID_BASE,
1106 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1107 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1108 startIndex, __length);
1110 out = __pValue + startIndex;
1116 String::SubString(int startIndex, int length, String& out) const
1118 SysTryReturnResult(NID_BASE,
1119 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1120 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1121 startIndex, __length);
1122 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1123 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1124 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1125 startIndex, length, __length);
1129 std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
1130 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1131 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1132 pTemp[length] = '\0';
1136 else if (length == 0)
1145 String::StartsWith(const String& str, int startIndex) const
1147 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1148 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1149 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1150 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1151 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1152 GetErrorMessage(E_INVALID_ARG), str.__length);
1154 if (str.__length > __length)
1159 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1168 String::EndsWith(const String& str) const
1175 int strLen = str.__length;
1176 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1177 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1179 int curLen = __length;
1180 if (strLen > curLen || curLen == 0)
1184 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1193 String::ToLower(String& out) const
1195 String str(__length + 1);
1197 wchar_t* pDst = str.__pValue;
1198 wchar_t* pSrc = __pValue;
1200 for (; *pSrc != 0; ++pSrc, ++pDst)
1202 *pDst = Character::ToLower(*pSrc);
1207 str.__length = __length;
1214 String::ToLowerCase(String& out) const
1216 String str(__length + 1);
1218 wchar_t* pDst = str.__pValue;
1219 wchar_t* pSrc = __pValue;
1221 for (; *pSrc != 0; ++pSrc, ++pDst)
1223 *pDst = Character::ToLowerCase(*pSrc);
1228 str.__length = __length;
1235 String::ToUpper(String& out) const
1237 String str(__length + 1);
1239 wchar_t* pDst = str.__pValue;
1240 wchar_t* pSrc = __pValue;
1242 for (; *pSrc != 0; ++pSrc, ++pDst)
1244 *pDst = Character::ToUpper(*pSrc);
1249 str.__length = __length;
1256 String::ToUpperCase(String& out) const
1258 String str(__length + 1);
1260 wchar_t* pDst = str.__pValue;
1261 wchar_t* pSrc = __pValue;
1262 for (; *pSrc != 0; ++pSrc, ++pDst)
1264 *pDst = Character::ToUpperCase(*pSrc);
1269 str.__length = __length;
1276 String::ToLower(void)
1278 result r = AboutToModify(__capacity);
1279 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1281 String str(__length + 1);
1283 wchar_t* pDst = str.__pValue;
1284 wchar_t* pSrc = __pValue;
1286 for (; *pSrc != 0; ++pSrc, ++pDst)
1288 *pDst = Character::ToLower(*pSrc);
1291 wcsncpy(__pValue, str.__pValue, __length);
1292 __pValue[__length] = '\0';
1297 String::ToLowerCase(void)
1299 result r = AboutToModify(__capacity);
1300 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1302 String str(__length + 1);
1304 wchar_t* pDst = str.__pValue;
1305 wchar_t* pSrc = __pValue;
1307 for (; *pSrc != 0; ++pSrc, ++pDst)
1309 *pDst = Character::ToLowerCase(*pSrc);
1312 wcsncpy(__pValue, str.__pValue, __length);
1313 __pValue[__length] = '\0';
1318 String::ToUpper(void)
1320 result r = AboutToModify(__capacity);
1321 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1323 String str(__length + 1);
1325 wchar_t* pDst = str.__pValue;
1326 wchar_t* pSrc = __pValue;
1328 for (; *pSrc != 0; ++pSrc, ++pDst)
1330 *pDst = Character::ToUpper(*pSrc);
1333 wcsncpy(__pValue, str.__pValue, __length);
1334 __pValue[__length] = '\0';
1339 String::ToUpperCase(void)
1341 result r = AboutToModify(__capacity);
1342 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1344 String str(__length + 1);
1346 wchar_t* pDst = str.__pValue;
1347 wchar_t* pSrc = __pValue;
1349 for (; *pSrc != 0; ++pSrc, ++pDst)
1351 *pDst = Character::ToUpperCase(*pSrc);
1354 wcsncpy(__pValue, str.__pValue, __length);
1355 __pValue[__length] = '\0';
1368 int lastIndex = __length;
1370 const wchar_t* pStr = __pValue;
1372 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1377 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1382 bool trimRight = lastIndex < __length;
1383 bool trimLeft = startIndex > 0;
1385 if (!trimRight && !trimLeft) // nothing to trim
1390 result r = AboutToModify(__capacity);
1391 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1395 Remove(lastIndex, __length - lastIndex);
1400 Remove(0, startIndex);
1405 String::GetCapacity(void) const
1407 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1411 String::GetLength(void) const
1417 String::GetPointer(void) const
1424 String::Contains(const String& str) const
1426 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1427 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1428 GetErrorMessage(E_INVALID_ARG), str.__length);
1434 else if ((__length == str.__length) && (*this == str))
1439 wchar_t* pStart = __pValue;
1440 wchar_t* pEnd = pStart + __length;
1441 while (pStart < pEnd)
1443 while (wcsstr(pStart, str.__pValue) != null)
1454 String::AllocateCapacity(int capacity)
1456 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1457 if (__pValue == null)
1459 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1464 __pValue[capacity] = '\0';
1465 __capacity = capacity;
1471 String::ExpandCapacity(int minCapacity)
1473 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1475 if (minCapacity > capacity)
1477 capacity = minCapacity;
1480 std::unique_ptr<wchar_t []> pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1481 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1482 GetErrorMessage(E_OUT_OF_MEMORY));
1484 if (__pValue != null)
1486 wmemcpy(pNewValue.get(), __pValue, __length);
1487 pNewValue[__length] = '\0';
1489 if (*__pRefCount == 1)
1495 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1496 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1497 GetErrorMessage(E_OUT_OF_MEMORY));
1498 _String::AtomicDec(__pRefCount);
1499 __pRefCount = pRefCntTemp.release();
1502 __pValue = pNewValue.release();
1503 __pValue[capacity] = '\0';
1504 __capacity = capacity;
1510 String::InitializeToDefault(int capacity)
1512 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1513 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1514 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1516 __pRefCount = pRefCntTemp.release();
1521 String::AboutToModify(int capacity, bool isUnshareable)
1523 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
1525 wchar_t* pValue = __pValue;
1526 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1527 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1528 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
1530 wcsncpy(__pValue, pValue, __length);
1531 __pValue[__length] = '\0';
1533 _String::AtomicDec(__pRefCount);
1534 __pRefCount = pRefCntTemp.release();
1539 *__pRefCount = UNSHAREABLE;
1546 String::Swap(String& str)
1548 std::swap(__capacity, str.__capacity);
1549 std::swap(__length, str.__length);
1550 std::swap(__hash, str.__hash);
1551 std::swap(__pRefCount, str.__pRefCount);
1552 std::swap(__pValue, str.__pValue);
1553 std::swap(__pStringImpl, str.__pStringImpl);