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 "FBaseUtil_AtomicOperations.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)
103 result r = InitializeToDefault(DEFAULT_CAPACITY);
104 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
108 int length = wcslen(pValue);
109 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
110 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
112 wcsncpy(__pValue, pValue, length);
113 __pValue[length] = '\0';
118 String::String(const char* pValue)
124 , __pStringImpl(null)
126 if (pValue == null || strlen(pValue) == 0)
128 result r = InitializeToDefault(DEFAULT_CAPACITY);
129 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
133 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
134 SysTryReturnVoidResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
136 std::unique_ptr< wchar_t[] > pStr(Tizen::Base::Utility::Utf8ToWcharN(pValue));
137 SysTryReturnVoidResult(NID_BASE, pStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
139 __pRefCount = pRefCntTemp.release();
140 __pValue = pStr.release();
141 __length = wcslen(__pValue);
142 __capacity = __length + DEFAULT_CAPACITY;
143 __pValue[__length] = '\0';
147 String::String(const String& value)
153 , __pStringImpl(null)
155 if (*(value.__pRefCount) != UNSHAREABLE)
157 Utility::_AtomicOperations::AtomicInc(value.__pRefCount);
158 __pRefCount = value.__pRefCount;
159 __pValue = value.__pValue;
160 __capacity = value.__capacity;
161 __length = value.__length;
162 __hash = value.__hash;
166 int length = wcslen(value.__pValue);
168 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
169 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
171 wcsncpy(__pValue, value.__pValue, length);
172 __pValue[length] = '\0';
177 String::~String(void)
179 if (*__pRefCount == 1 || *__pRefCount == UNSHAREABLE)
186 Utility::_AtomicOperations::AtomicDec(__pRefCount);
192 String::operator [](int index) const
194 static wchar_t ch = -1;
195 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
196 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
197 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
198 return __pValue[index];
202 String::operator [](int index)
204 static wchar_t ch = -1;
205 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
206 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
207 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
209 result r = AboutToModify(__capacity, true);
210 SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
213 return __pValue[index];
217 String::operator =(const wchar_t* pRhs)
231 String::operator =(const String& rhs)
245 String::operator +=(const wchar_t* pRhs)
258 String::operator +=(const String& rhs)
265 Append(rhs.__pValue);
271 operator +(const String& lhs, const String& rhs)
275 str.Append(rhs.__pValue);
281 String::operator ==(const String& rhs) const
283 if (__length != rhs.__length)
287 return(CompareTo(rhs) == 0);
291 String::operator !=(const String& rhs) const
293 return(!(*this).operator ==(rhs));
297 String::IsEmpty(void) const
299 return(__length == 0);
303 String::Append(wchar_t ch)
305 result r = Append(Character::ToString(ch));
306 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
312 String::Append(char ch)
314 result r = Append((wchar_t) ch);
315 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
321 String::Append(int i)
323 result r = Append(Integer::ToString(i));
324 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
330 String::Append(short s)
332 result r = Append(Short::ToString(s));
333 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
339 String::Append(long l)
341 result r = Append(Long::ToString(l));
342 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
348 String::Append(long long ll)
350 result r = Append(LongLong::ToString(ll));
351 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
357 String::Append(float f)
359 result r = Append(Float::ToString(f));
360 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
366 String::Append(double d)
368 result r = Append(Double::ToString(d));
369 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
375 String::Append(const wchar_t* p)
377 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
379 int length = (wcslen(p) + __length);
381 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
383 wchar_t* pValue = __pValue;
384 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
385 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
386 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
388 wcsncpy(__pValue, pValue, __length);
389 Utility::_AtomicOperations::AtomicDec(__pRefCount);
390 __pRefCount = pRefCntTemp.release();
393 result r = EnsureCapacity(length);
394 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
396 wcsncpy((__pValue + __length), p, wcslen(p));
398 __pValue[length] = '\0';
406 String::Append(const String& str)
413 result r = Append(str.__pValue);
414 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
427 String::Compare(const String& str0, const String& str1)
429 if (str0.__pValue == str1.__pValue)
434 return(wcscmp(str0.__pValue, str1.__pValue));
438 String::CompareTo(const String& str) const
440 if (__pValue == str.__pValue)
445 return(wcscmp(__pValue, str.__pValue));
449 String::EnsureCapacity(int minCapacity)
451 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
454 if (minCapacity > __capacity)
456 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
462 String::Equals(const Object& obj) const
464 const String* pOther = dynamic_cast< const String* >(&obj);
471 return(*this == *pOther);
475 String::Equals(const String& str, bool caseSensitive) const
479 return(*this == str);
483 if (__length != str.__length)
488 if (__pValue == str.__pValue)
493 if (wcscasecmp(__pValue, str.__pValue) == 0)
503 String::Format(int length, const wchar_t* pFormat, ...)
506 result r = E_SUCCESS;
508 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
509 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
512 String tempStr(pFormat);
513 if (tempStr.IsEmpty() || length == 0)
519 // Check "%n" and "%hn"
520 r = tempStr.IndexOf(L"%n", 0, index);
521 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
523 r = tempStr.IndexOf(L"%hn", 0, index);
524 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
528 std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
529 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
533 va_start(args, pFormat);
535 vswprintf(pStr.get(), length, tempStr.__pValue, args);
541 int len = wcslen(this->__pValue);
544 this->__pValue[len] = '\0';
545 this->__length = len;
549 this->__pValue[length - 1] = '\0';
550 this->__length = length - 1;
558 String::GetHashCode(void) const
567 const int DEFAULT_HASH_VALUE = 352654597;
568 const int HASH_MULTIPLIER = 1566083941;
570 int num = DEFAULT_HASH_VALUE;
571 int num2 = DEFAULT_HASH_VALUE;
572 wchar_t* pStr = __pValue;
573 for (int i = __length; i >= 2 ; i -= 4)
575 num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
576 num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ pStr[1];
579 num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
580 __hash = num + (num2 * HASH_MULTIPLIER);
586 String::GetCharAt(int indexAt, wchar_t& ret) const
588 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
589 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
590 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
591 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
593 ret = __pValue[indexAt];
599 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
601 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
602 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
603 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
604 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
606 wchar_t* pBeg = __pValue + startIndex;
607 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
613 return E_OBJ_NOT_FOUND;
616 indexOf = int(pFound - __pValue);
622 String::IndexOf(const String& str, int startIndex, int& indexOf) const
624 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
625 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
626 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
627 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
631 indexOf = startIndex;
635 if (__length < str.__length)
638 return E_OBJ_NOT_FOUND;
643 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
648 return E_OBJ_NOT_FOUND;
651 indexOf = int(p - __pValue);
657 String::Insert(wchar_t ch, int indexAt)
659 SysTryReturnResult(NID_BASE,
660 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
661 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
664 result r = AboutToModify(__capacity);
665 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
667 int length = (__length + 1);
669 r = EnsureCapacity(length);
670 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
672 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
674 __pValue[indexAt] = ch;
682 String::Insert(char ch, int indexAt)
684 wchar_t wideChar = (wchar_t) ch;
686 result r = Insert(wideChar, indexAt);
687 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
693 String::Insert(short s, int indexAt)
695 result r = Insert(Short::ToString(s), indexAt);
696 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
702 String::Insert(int i, int indexAt)
704 result r = Insert(Integer::ToString(i), indexAt);
705 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
711 String::Insert(long l, int indexAt)
713 result r = Insert(Long::ToString(l), indexAt);
714 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
720 String::Insert(long long ll, int indexAt)
722 result r = Insert(LongLong::ToString(ll), indexAt);
723 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
729 String::Insert(float f, int indexAt)
731 result r = Insert(Float::ToString(f), indexAt);
732 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
738 String::Insert(double d, int indexAt)
740 result r = Insert(Double::ToString(d), indexAt);
741 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
746 String::Insert(const wchar_t* p, int indexAt)
748 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
749 SysTryReturnResult(NID_BASE,
750 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
751 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
754 int length = wcslen(p);
760 result r = AboutToModify(__capacity);
761 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
763 r = EnsureCapacity(__length + length);
764 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
766 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
767 wmemcpy((__pValue + indexAt), p, length);
775 String::Insert(const String& str, int indexAt)
777 result r = Insert(str.__pValue, indexAt);
778 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
784 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
786 SysTryReturnResult(NID_BASE,
787 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
788 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
789 startIndex, __length);
791 wchar_t* pBeg = __pValue + startIndex;
792 wchar_t* pEnd = __pValue;
797 indexOf = int(pBeg - __pValue);
806 return E_OBJ_NOT_FOUND;
810 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
812 SysTryReturnResult(NID_BASE,
813 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
814 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
815 startIndex, __length);
819 indexOf = startIndex;
823 if (__length < str.__length)
827 return E_OBJ_NOT_FOUND;
830 const wchar_t* pStr = str.__pValue;
832 int length = str.__length;
833 if (length > startIndex)
837 return E_OBJ_NOT_FOUND;
841 wchar_t* pBeg = __pValue + startIndex;
842 wchar_t* pEnd = __pValue;
846 if (wcsncmp(pBeg, pStr, length) == 0)
848 indexOf = (pBeg - __pValue);
855 return E_OBJ_NOT_FOUND;
859 String::Remove(int startIndex, int count)
861 SysTryReturnResult(NID_BASE,
862 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
863 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
864 startIndex, __length);
865 int moveIndex = startIndex + count;
866 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
867 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
868 startIndex, count, __length);
870 result r = AboutToModify(__capacity);
871 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
873 wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
875 __pValue[__length] = '\0';
882 String::Replace(wchar_t original, wchar_t replace)
884 result r = AboutToModify(__capacity);
885 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
887 for (int length = __length; length >= 0; --length)
889 if (__pValue[length] == original)
891 __pValue[length] = replace;
898 String::Replace(const String& org, const String& rep)
900 result r = Replace(org, rep, 0);
901 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
907 String::Replace(const String& org, const String& rep, int startIndex)
909 const int orgLen = org.__length;
910 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
912 SysTryReturnResult(NID_BASE,
913 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
914 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
915 startIndex, __length);
922 if ((orgLen == __length) && (*this == org))
924 const int newLength = rep.__length;
925 if (EnsureCapacity(newLength) != E_SUCCESS)
927 SetCapacity(newLength);
930 wcsncpy(__pValue, rep.__pValue, rep.__length);
932 __length = rep.__length;
933 __pValue[__length] = '\0';
939 int repLen = rep.__length;
941 wchar_t* pOrg = org.__pValue;
942 wchar_t* pRep = rep.__pValue;
946 wchar_t* pBeg = (__pValue + startIndex);
947 wchar_t* pEnd = pBeg + __length;
950 wchar_t* pTarget = null;
951 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
954 pBeg = pTarget + orgLen;
956 pBeg += wcslen(pBeg) + 1;
962 result r = AboutToModify(__capacity);
963 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
965 const int newLength = (count * (repLen - orgLen)) + __length;
966 r = EnsureCapacity(newLength);
967 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
969 wchar_t* pBeg = (__pValue + startIndex);
970 wchar_t* pEnd = pBeg + __length;
973 wchar_t* pTarget = null;
974 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
976 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
977 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
978 wmemcpy(pTarget, pRep, repLen);
979 pBeg = pTarget + repLen;
980 pTarget[repLen + balance] = 0;
981 __length += (repLen - orgLen);
983 pBeg += (wcslen(pBeg) + 1);
986 __length = newLength;
994 String::Reverse(void)
996 result r = AboutToModify(__capacity);
997 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
999 wchar_t* pBeg = __pValue;
1000 wchar_t* pEnd = __pValue + __length - 1;
1003 for (; pBeg < pEnd; ++pBeg, --pEnd)
1013 String::SetCapacity(int capacity)
1015 SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1016 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1018 std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
1019 SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1021 if (__pValue != null)
1023 if (__length < capacity)
1025 wmemcpy(pValue.get(), __pValue, (__length + 1));
1029 wmemcpy(pValue.get(), __pValue, capacity);
1030 pValue[capacity] = '\0';
1031 __length = capacity;
1035 if (*__pRefCount == 1)
1041 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1042 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1043 Utility::_AtomicOperations::AtomicDec(__pRefCount);
1044 __pRefCount = pRefCntTemp.release();
1048 __pValue = pValue.release();
1049 __capacity = capacity;
1055 String::SetCharAt(wchar_t ch, int indexAt)
1057 SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1058 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1059 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1061 result r = AboutToModify(__capacity);
1062 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1064 __pValue[indexAt] = ch;
1071 String::SetLength(int newLength)
1073 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1076 result r = AboutToModify(__capacity);
1077 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1079 static const wchar_t SPACE = 0x0020;
1081 r = EnsureCapacity(newLength);
1082 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1084 if (newLength > __length)
1086 wmemset(__pValue + __length, SPACE, newLength - __length);
1089 __pValue[newLength] = '\0';
1090 __length = newLength;
1097 String::SubString(int startIndex, String& out) const
1099 SysTryReturnResult(NID_BASE,
1100 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1101 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1102 startIndex, __length);
1104 out = __pValue + startIndex;
1110 String::SubString(int startIndex, int length, String& out) const
1112 SysTryReturnResult(NID_BASE,
1113 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1114 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1115 startIndex, __length);
1116 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1117 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1118 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1119 startIndex, length, __length);
1123 std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
1124 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1125 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1126 pTemp[length] = '\0';
1130 else if (length == 0)
1139 String::StartsWith(const String& str, int startIndex) const
1141 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1142 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1143 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1144 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1145 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1146 GetErrorMessage(E_INVALID_ARG), str.__length);
1148 if (str.__length > __length)
1153 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1162 String::EndsWith(const String& str) const
1169 int strLen = str.__length;
1170 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1171 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1173 int curLen = __length;
1174 if (strLen > curLen || curLen == 0)
1178 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1187 String::ToLower(String& out) const
1189 String str(__length + 1);
1191 wchar_t* pDst = str.__pValue;
1192 wchar_t* pSrc = __pValue;
1194 for (; *pSrc != 0; ++pSrc, ++pDst)
1196 *pDst = Character::ToLower(*pSrc);
1201 str.__length = __length;
1208 String::ToLowerCase(String& out) const
1210 String str(__length + 1);
1212 wchar_t* pDst = str.__pValue;
1213 wchar_t* pSrc = __pValue;
1215 for (; *pSrc != 0; ++pSrc, ++pDst)
1217 *pDst = Character::ToLowerCase(*pSrc);
1222 str.__length = __length;
1229 String::ToUpper(String& out) const
1231 String str(__length + 1);
1233 wchar_t* pDst = str.__pValue;
1234 wchar_t* pSrc = __pValue;
1236 for (; *pSrc != 0; ++pSrc, ++pDst)
1238 *pDst = Character::ToUpper(*pSrc);
1243 str.__length = __length;
1250 String::ToUpperCase(String& out) const
1252 String str(__length + 1);
1254 wchar_t* pDst = str.__pValue;
1255 wchar_t* pSrc = __pValue;
1256 for (; *pSrc != 0; ++pSrc, ++pDst)
1258 *pDst = Character::ToUpperCase(*pSrc);
1263 str.__length = __length;
1270 String::ToLower(void)
1272 result r = AboutToModify(__capacity);
1273 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1275 String str(__length + 1);
1277 wchar_t* pDst = str.__pValue;
1278 wchar_t* pSrc = __pValue;
1280 for (; *pSrc != 0; ++pSrc, ++pDst)
1282 *pDst = Character::ToLower(*pSrc);
1285 wcsncpy(__pValue, str.__pValue, __length);
1286 __pValue[__length] = '\0';
1291 String::ToLowerCase(void)
1293 result r = AboutToModify(__capacity);
1294 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1296 String str(__length + 1);
1298 wchar_t* pDst = str.__pValue;
1299 wchar_t* pSrc = __pValue;
1301 for (; *pSrc != 0; ++pSrc, ++pDst)
1303 *pDst = Character::ToLowerCase(*pSrc);
1306 wcsncpy(__pValue, str.__pValue, __length);
1307 __pValue[__length] = '\0';
1312 String::ToUpper(void)
1314 result r = AboutToModify(__capacity);
1315 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1317 String str(__length + 1);
1319 wchar_t* pDst = str.__pValue;
1320 wchar_t* pSrc = __pValue;
1322 for (; *pSrc != 0; ++pSrc, ++pDst)
1324 *pDst = Character::ToUpper(*pSrc);
1327 wcsncpy(__pValue, str.__pValue, __length);
1328 __pValue[__length] = '\0';
1333 String::ToUpperCase(void)
1335 result r = AboutToModify(__capacity);
1336 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1338 String str(__length + 1);
1340 wchar_t* pDst = str.__pValue;
1341 wchar_t* pSrc = __pValue;
1343 for (; *pSrc != 0; ++pSrc, ++pDst)
1345 *pDst = Character::ToUpperCase(*pSrc);
1348 wcsncpy(__pValue, str.__pValue, __length);
1349 __pValue[__length] = '\0';
1362 int lastIndex = __length;
1364 const wchar_t* pStr = __pValue;
1366 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1371 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1376 bool trimRight = lastIndex < __length;
1377 bool trimLeft = startIndex > 0;
1379 if (!trimRight && !trimLeft) // nothing to trim
1384 result r = AboutToModify(__capacity);
1385 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1389 Remove(lastIndex, __length - lastIndex);
1394 Remove(0, startIndex);
1399 String::GetCapacity(void) const
1401 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1405 String::GetLength(void) const
1411 String::GetPointer(void) const
1418 String::Contains(const String& str) const
1420 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1421 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1422 GetErrorMessage(E_INVALID_ARG), str.__length);
1428 else if ((__length == str.__length) && (*this == str))
1433 return (wcsstr(__pValue, str.__pValue) != null);
1437 String::AllocateCapacity(int capacity)
1439 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1440 if (__pValue == null)
1442 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1447 __pValue[capacity] = '\0';
1448 __capacity = capacity;
1454 String::ExpandCapacity(int minCapacity)
1456 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1458 if (minCapacity > capacity)
1460 capacity = minCapacity;
1463 std::unique_ptr< wchar_t[] > pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1464 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1465 GetErrorMessage(E_OUT_OF_MEMORY));
1467 if (__pValue != null)
1469 wmemcpy(pNewValue.get(), __pValue, __length);
1470 pNewValue[__length] = '\0';
1472 if (*__pRefCount == 1)
1478 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1479 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1480 GetErrorMessage(E_OUT_OF_MEMORY));
1481 Utility::_AtomicOperations::AtomicDec(__pRefCount);
1482 __pRefCount = pRefCntTemp.release();
1485 __pValue = pNewValue.release();
1486 __pValue[capacity] = '\0';
1487 __capacity = capacity;
1493 String::InitializeToDefault(int capacity)
1495 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1496 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1497 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1499 __pRefCount = pRefCntTemp.release();
1504 String::AboutToModify(int capacity, bool isUnshareable)
1506 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
1508 wchar_t* pValue = __pValue;
1509 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1510 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1511 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
1513 wcsncpy(__pValue, pValue, __length);
1514 __pValue[__length] = '\0';
1516 Utility::_AtomicOperations::AtomicDec(__pRefCount);
1517 __pRefCount = pRefCntTemp.release();
1522 *__pRefCount = UNSHAREABLE;
1529 String::Swap(String& str)
1531 std::swap(__capacity, str.__capacity);
1532 std::swap(__length, str.__length);
1533 std::swap(__hash, str.__hash);
1534 std::swap(__pRefCount, str.__pRefCount);
1535 std::swap(__pValue, str.__pValue);
1536 std::swap(__pStringImpl, str.__pStringImpl);