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.
27 #include <FBaseString.h>
28 #include <FBaseInt8.h>
29 #include <FBaseShort.h>
30 #include <FBaseInteger.h>
31 #include <FBaseLong.h>
32 #include <FBaseLongLong.h>
33 #include <FBaseFloat.h>
34 #include <FBaseDouble.h>
35 #include <FBaseCharacter.h>
36 #include <FBaseResult.h>
37 #include <FBaseSysLog.h>
38 #include <unique_ptr.h>
39 #include "FBase_String.h"
40 #include "FBaseUtil_IcuConverter.h"
42 namespace Tizen { namespace Base
45 const float String::GROWTH_FACTOR = 1.5;
46 const int String::UNSHAREABLE = Integer::VALUE_MAX;
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(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 if (pValue == null || strlen(pValue) == 0)
132 result r = InitializeToDefault(DEFAULT_CAPACITY);
133 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
137 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
138 SysTryReturnVoidResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
140 std::unique_ptr< wchar_t[] > pStr(Tizen::Base::Utility::Utf8ToWcharN(pValue));
141 SysTryReturnVoidResult(NID_BASE, pStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
143 __pRefCount = pRefCntTemp.release();
144 __pValue = pStr.release();
145 __length = wcslen(__pValue);
146 __capacity = __length + DEFAULT_CAPACITY;
147 __pValue[__length] = '\0';
151 String::String(const String& value)
157 , __pStringImpl(null)
159 SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
161 if (*(value.__pRefCount) != UNSHAREABLE)
163 _String::AtomicInc(value.__pRefCount);
164 __pRefCount = value.__pRefCount;
165 __pValue = value.__pValue;
166 __capacity = value.__capacity;
167 __length = value.__length;
168 __hash = value.__hash;
172 int length = wcslen(value.__pValue);
174 SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
175 "String has wrong length. The length has to be more bigger than 0.");
177 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
178 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
180 wcsncpy(__pValue, value.__pValue, length);
181 __pValue[length] = '\0';
186 String::~String(void)
188 if (*__pRefCount == 1 || *__pRefCount == UNSHAREABLE)
195 _String::AtomicDec(__pRefCount);
201 String::operator [](int index) const
203 static wchar_t ch = -1;
204 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
205 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
206 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
207 return __pValue[index];
211 String::operator [](int index)
213 static wchar_t ch = -1;
214 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
215 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
216 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
218 result r = AboutToModify(__capacity, true);
219 SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
222 return __pValue[index];
226 String::operator =(const wchar_t* pRhs)
240 String::operator =(const String& rhs)
254 String::operator +=(const wchar_t* pRhs)
267 String::operator +=(const String& rhs)
274 Append(rhs.__pValue);
280 operator +(const String& lhs, const String& rhs)
284 str.Append(rhs.__pValue);
290 String::operator ==(const String& rhs) const
292 if (__length != rhs.__length)
297 return(CompareTo(rhs) == 0);
301 String::operator !=(const String& rhs) const
303 return(!(*this).operator ==(rhs));
307 String::IsEmpty(void) const
309 return(__length == 0);
313 String::Append(wchar_t ch)
315 result r = Append(Character::ToString(ch));
316 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
322 String::Append(char ch)
324 result r = Append((wchar_t) ch);
325 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
331 String::Append(int i)
333 result r = Append(Integer::ToString(i));
334 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
340 String::Append(short s)
342 result r = Append(Short::ToString(s));
343 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
349 String::Append(long l)
351 result r = Append(Long::ToString(l));
352 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
358 String::Append(long long ll)
360 result r = Append(LongLong::ToString(ll));
361 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
367 String::Append(float f)
369 result r = Append(Float::ToString(f));
370 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
376 String::Append(double d)
378 result r = Append(Double::ToString(d));
379 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
385 String::Append(const wchar_t* p)
387 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
389 int length = (wcslen(p) + __length);
391 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
393 wchar_t* pValue = __pValue;
394 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
395 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
396 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
398 wcsncpy(__pValue, pValue, __length);
399 _String::AtomicDec(__pRefCount);
400 __pRefCount = pRefCntTemp.release();
403 result r = EnsureCapacity(length);
404 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
406 wcsncpy((__pValue + __length), p, wcslen(p));
408 __pValue[length] = '\0';
416 String::Append(const String& str)
423 result r = Append(str.__pValue);
424 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
437 String::Compare(const String& str0, const String& str1)
439 if (str0.__pValue == str1.__pValue)
444 return(wcscmp(str0.__pValue, str1.__pValue));
448 String::CompareTo(const String& str) const
450 if (__pValue == str.__pValue)
455 return(wcscmp(__pValue, str.__pValue));
459 String::EnsureCapacity(int minCapacity)
461 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
464 if (minCapacity > __capacity)
466 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
472 String::Equals(const Object& obj) const
474 const String* pOther = dynamic_cast< const String* >(&obj);
481 return(*this == *pOther);
485 String::Equals(const String& str, bool caseSensitive) const
489 return(*this == str);
493 if (__length != str.__length)
498 if (__pValue == str.__pValue)
503 if (wcscasecmp(__pValue, str.__pValue) == 0)
513 String::Format(int length, const wchar_t* pFormat, ...)
516 result r = E_SUCCESS;
518 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
519 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
522 String tempStr(pFormat);
523 if (tempStr.IsEmpty() || length == 0)
529 // Check "%n" and "%hn"
530 r = tempStr.IndexOf(L"%n", 0, index);
531 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
533 r = tempStr.IndexOf(L"%hn", 0, index);
534 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
538 std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
539 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
543 va_start(args, pFormat);
545 vswprintf(pStr.get(), length, tempStr.__pValue, args);
551 int len = wcslen(this->__pValue);
554 this->__pValue[len] = '\0';
555 this->__length = len;
559 this->__pValue[length - 1] = '\0';
560 this->__length = length - 1;
568 String::GetHashCode(void) const
574 wchar_t* pStr = __pValue;
575 for (int i = 0; i < __length; ++i)
577 hash = (hash << 5) - hash + (int) *pStr++;
590 String::GetCharAt(int indexAt, wchar_t& ret) const
592 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
593 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
594 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
595 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
597 ret = __pValue[indexAt];
603 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
605 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
606 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
607 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
608 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
610 wchar_t* pBeg = __pValue + startIndex;
611 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
617 return E_OBJ_NOT_FOUND;
620 indexOf = int(pFound - __pValue);
626 String::IndexOf(const String& str, int startIndex, int& indexOf) const
628 SysTryReturnResult(NID_BASE, (startIndex < __length), E_OUT_OF_RANGE,
629 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
630 SysTryReturnResult(NID_BASE, (startIndex >= 0), E_OUT_OF_RANGE,
631 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
635 indexOf = startIndex;
639 if (__length < str.__length)
642 return E_OBJ_NOT_FOUND;
647 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
652 return E_OBJ_NOT_FOUND;
655 indexOf = int(p - __pValue);
661 String::Insert(wchar_t ch, int indexAt)
663 SysTryReturnResult(NID_BASE,
664 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
665 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
668 result r = AboutToModify(__capacity);
669 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
671 int length = (__length + 1);
673 r = EnsureCapacity(length);
674 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
676 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
678 __pValue[indexAt] = ch;
686 String::Insert(char ch, int indexAt)
688 wchar_t wideChar = (wchar_t) ch;
690 result r = Insert(wideChar, indexAt);
691 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
697 String::Insert(short s, int indexAt)
699 result r = Insert(Short::ToString(s), indexAt);
700 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
706 String::Insert(int i, int indexAt)
708 result r = Insert(Integer::ToString(i), indexAt);
709 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
715 String::Insert(long l, int indexAt)
717 result r = Insert(Long::ToString(l), indexAt);
718 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
724 String::Insert(long long ll, int indexAt)
726 result r = Insert(LongLong::ToString(ll), indexAt);
727 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
733 String::Insert(float f, int indexAt)
735 result r = Insert(Float::ToString(f), indexAt);
736 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
742 String::Insert(double d, int indexAt)
744 result r = Insert(Double::ToString(d), indexAt);
745 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
750 String::Insert(const wchar_t* p, int indexAt)
752 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
753 SysTryReturnResult(NID_BASE,
754 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
755 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
758 int length = wcslen(p);
764 result r = AboutToModify(__capacity);
765 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
767 r = EnsureCapacity(__length + length);
768 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
770 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
771 wmemcpy((__pValue + indexAt), p, length);
779 String::Insert(const String& str, int indexAt)
781 result r = Insert(str.__pValue, indexAt);
782 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
788 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
790 SysTryReturnResult(NID_BASE,
791 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
792 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
793 startIndex, __length);
795 wchar_t* pBeg = __pValue + startIndex;
796 wchar_t* pEnd = __pValue;
801 indexOf = int(pBeg - __pValue);
810 return E_OBJ_NOT_FOUND;
814 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
816 SysTryReturnResult(NID_BASE,
817 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
818 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
819 startIndex, __length);
823 indexOf = startIndex;
827 if (__length < str.__length)
831 return E_OBJ_NOT_FOUND;
834 const wchar_t* pStr = str.__pValue;
836 int length = str.__length;
837 if (length > startIndex)
841 return E_OBJ_NOT_FOUND;
845 wchar_t* pBeg = __pValue + startIndex;
846 wchar_t* pEnd = __pValue;
850 if (wcsncmp(pBeg, pStr, length) == 0)
852 indexOf = (pBeg - __pValue);
859 return E_OBJ_NOT_FOUND;
863 String::Remove(int startIndex, int count)
865 SysTryReturnResult(NID_BASE,
866 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
867 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
868 startIndex, __length);
869 int moveIndex = startIndex + count;
870 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
871 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
872 startIndex, count, __length);
874 result r = AboutToModify(__capacity);
875 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
877 wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
879 __pValue[__length] = '\0';
886 String::Replace(wchar_t original, wchar_t replace)
888 result r = AboutToModify(__capacity);
889 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
891 for (int length = __length; length >= 0; --length)
893 if (__pValue[length] == original)
895 __pValue[length] = replace;
902 String::Replace(const String& org, const String& rep)
904 result r = Replace(org, rep, 0);
905 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
911 String::Replace(const String& org, const String& rep, int startIndex)
913 const int orgLen = org.__length;
914 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
916 SysTryReturnResult(NID_BASE,
917 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
918 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
919 startIndex, __length);
926 if ((orgLen == __length) && (*this == org))
928 const int newLength = rep.__length;
929 if (EnsureCapacity(newLength) != E_SUCCESS)
931 SetCapacity(newLength);
934 wcsncpy(__pValue, rep.__pValue, rep.__length);
936 __length = rep.__length;
937 __pValue[__length] = '\0';
943 int repLen = rep.__length;
945 wchar_t* pOrg = org.__pValue;
946 wchar_t* pRep = rep.__pValue;
950 wchar_t* pBeg = (__pValue + startIndex);
951 wchar_t* pEnd = pBeg + __length;
954 wchar_t* pTarget = null;
955 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
958 pBeg = pTarget + orgLen;
960 pBeg += wcslen(pBeg) + 1;
966 result r = AboutToModify(__capacity);
967 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
969 const int newLength = (count * (repLen - orgLen)) + __length;
970 r = EnsureCapacity(newLength);
971 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
973 wchar_t* pBeg = (__pValue + startIndex);
974 wchar_t* pEnd = pBeg + __length;
977 wchar_t* pTarget = null;
978 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
980 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
981 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
982 wmemcpy(pTarget, pRep, repLen);
983 pBeg = pTarget + repLen;
984 pTarget[repLen + balance] = 0;
985 __length += (repLen - orgLen);
987 pBeg += (wcslen(pBeg) + 1);
990 __length = newLength;
998 String::Reverse(void)
1000 result r = AboutToModify(__capacity);
1001 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1003 wchar_t* pBeg = __pValue;
1004 wchar_t* pEnd = __pValue + __length - 1;
1007 for (; pBeg < pEnd; ++pBeg, --pEnd)
1017 String::SetCapacity(int capacity)
1019 SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1020 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1022 std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
1023 SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1025 if (__pValue != null)
1027 if (__length < capacity)
1029 wmemcpy(pValue.get(), __pValue, (__length + 1));
1033 wmemcpy(pValue.get(), __pValue, capacity);
1034 pValue[capacity] = '\0';
1035 __length = capacity;
1039 if (*__pRefCount == 1)
1045 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1046 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1047 _String::AtomicDec(__pRefCount);
1048 __pRefCount = pRefCntTemp.release();
1052 __pValue = pValue.release();
1053 __capacity = capacity;
1059 String::SetCharAt(wchar_t ch, int indexAt)
1061 SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1062 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1063 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1065 result r = AboutToModify(__capacity);
1066 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1068 __pValue[indexAt] = ch;
1075 String::SetLength(int newLength)
1077 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1080 result r = AboutToModify(__capacity);
1081 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1083 static const wchar_t SPACE = 0x0020;
1085 r = EnsureCapacity(newLength);
1086 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1088 if (newLength > __length)
1090 wmemset(__pValue + __length, SPACE, newLength - __length);
1093 __pValue[newLength] = '\0';
1094 __length = newLength;
1101 String::SubString(int startIndex, String& out) const
1103 SysTryReturnResult(NID_BASE,
1104 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1105 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1106 startIndex, __length);
1108 out = __pValue + startIndex;
1114 String::SubString(int startIndex, int length, String& out) const
1116 SysTryReturnResult(NID_BASE,
1117 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1118 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1119 startIndex, __length);
1120 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1121 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1122 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1123 startIndex, length, __length);
1127 std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
1128 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1129 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1130 pTemp[length] = '\0';
1134 else if (length == 0)
1143 String::StartsWith(const String& str, int startIndex) const
1145 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1146 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1147 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1148 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1149 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1150 GetErrorMessage(E_INVALID_ARG), str.__length);
1152 if (str.__length > __length)
1157 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1166 String::EndsWith(const String& str) const
1173 int strLen = str.__length;
1174 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1175 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1177 int curLen = __length;
1178 if (strLen > curLen || curLen == 0)
1182 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1191 String::ToLower(String& out) const
1193 String str(__length + 1);
1195 wchar_t* pDst = str.__pValue;
1196 wchar_t* pSrc = __pValue;
1198 for (; *pSrc != 0; ++pSrc, ++pDst)
1200 *pDst = Character::ToLower(*pSrc);
1205 str.__length = __length;
1212 String::ToLowerCase(String& out) const
1214 String str(__length + 1);
1216 wchar_t* pDst = str.__pValue;
1217 wchar_t* pSrc = __pValue;
1219 for (; *pSrc != 0; ++pSrc, ++pDst)
1221 *pDst = Character::ToLowerCase(*pSrc);
1226 str.__length = __length;
1233 String::ToUpper(String& out) const
1235 String str(__length + 1);
1237 wchar_t* pDst = str.__pValue;
1238 wchar_t* pSrc = __pValue;
1240 for (; *pSrc != 0; ++pSrc, ++pDst)
1242 *pDst = Character::ToUpper(*pSrc);
1247 str.__length = __length;
1254 String::ToUpperCase(String& out) const
1256 String str(__length + 1);
1258 wchar_t* pDst = str.__pValue;
1259 wchar_t* pSrc = __pValue;
1260 for (; *pSrc != 0; ++pSrc, ++pDst)
1262 *pDst = Character::ToUpperCase(*pSrc);
1267 str.__length = __length;
1274 String::ToLower(void)
1276 result r = AboutToModify(__capacity);
1277 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1279 String str(__length + 1);
1281 wchar_t* pDst = str.__pValue;
1282 wchar_t* pSrc = __pValue;
1284 for (; *pSrc != 0; ++pSrc, ++pDst)
1286 *pDst = Character::ToLower(*pSrc);
1289 wcsncpy(__pValue, str.__pValue, __length);
1290 __pValue[__length] = '\0';
1295 String::ToLowerCase(void)
1297 result r = AboutToModify(__capacity);
1298 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1300 String str(__length + 1);
1302 wchar_t* pDst = str.__pValue;
1303 wchar_t* pSrc = __pValue;
1305 for (; *pSrc != 0; ++pSrc, ++pDst)
1307 *pDst = Character::ToLowerCase(*pSrc);
1310 wcsncpy(__pValue, str.__pValue, __length);
1311 __pValue[__length] = '\0';
1316 String::ToUpper(void)
1318 result r = AboutToModify(__capacity);
1319 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1321 String str(__length + 1);
1323 wchar_t* pDst = str.__pValue;
1324 wchar_t* pSrc = __pValue;
1326 for (; *pSrc != 0; ++pSrc, ++pDst)
1328 *pDst = Character::ToUpper(*pSrc);
1331 wcsncpy(__pValue, str.__pValue, __length);
1332 __pValue[__length] = '\0';
1337 String::ToUpperCase(void)
1339 result r = AboutToModify(__capacity);
1340 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1342 String str(__length + 1);
1344 wchar_t* pDst = str.__pValue;
1345 wchar_t* pSrc = __pValue;
1347 for (; *pSrc != 0; ++pSrc, ++pDst)
1349 *pDst = Character::ToUpperCase(*pSrc);
1352 wcsncpy(__pValue, str.__pValue, __length);
1353 __pValue[__length] = '\0';
1366 int lastIndex = __length;
1368 const wchar_t* pStr = __pValue;
1370 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1375 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1380 bool trimRight = lastIndex < __length;
1381 bool trimLeft = startIndex > 0;
1383 if (!trimRight && !trimLeft) // nothing to trim
1388 result r = AboutToModify(__capacity);
1389 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1393 Remove(lastIndex, __length - lastIndex);
1398 Remove(0, startIndex);
1403 String::GetCapacity(void) const
1405 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1409 String::GetLength(void) const
1415 String::GetPointer(void) const
1422 String::Contains(const String& str) const
1424 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1425 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1426 GetErrorMessage(E_INVALID_ARG), str.__length);
1432 else if ((__length == str.__length) && (*this == str))
1437 wchar_t* pStart = __pValue;
1438 wchar_t* pEnd = pStart + __length;
1439 while (pStart < pEnd)
1441 while (wcsstr(pStart, str.__pValue) != null)
1452 String::AllocateCapacity(int capacity)
1454 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1455 if (__pValue == null)
1457 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1462 __pValue[capacity] = '\0';
1463 __capacity = capacity;
1469 String::ExpandCapacity(int minCapacity)
1471 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1473 if (minCapacity > capacity)
1475 capacity = minCapacity;
1478 std::unique_ptr< wchar_t[] > pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1479 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1480 GetErrorMessage(E_OUT_OF_MEMORY));
1482 if (__pValue != null)
1484 wmemcpy(pNewValue.get(), __pValue, __length);
1485 pNewValue[__length] = '\0';
1487 if (*__pRefCount == 1)
1493 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1494 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1495 GetErrorMessage(E_OUT_OF_MEMORY));
1496 _String::AtomicDec(__pRefCount);
1497 __pRefCount = pRefCntTemp.release();
1500 __pValue = pNewValue.release();
1501 __pValue[capacity] = '\0';
1502 __capacity = capacity;
1508 String::InitializeToDefault(int capacity)
1510 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1511 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1512 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1514 __pRefCount = pRefCntTemp.release();
1519 String::AboutToModify(int capacity, bool isUnshareable)
1521 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
1523 wchar_t* pValue = __pValue;
1524 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1525 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1526 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
1528 wcsncpy(__pValue, pValue, __length);
1529 __pValue[__length] = '\0';
1531 _String::AtomicDec(__pRefCount);
1532 __pRefCount = pRefCntTemp.release();
1537 *__pRefCount = UNSHAREABLE;
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);