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>
42 namespace Tizen { namespace Base
45 const float String::GROWTH_FACTOR = 1.5;
55 result r = InitializeToDefault(DEFAULT_CAPACITY);
56 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
59 String::String(int capacity)
69 capacity = DEFAULT_CAPACITY;
72 result r = InitializeToDefault(capacity);
73 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
76 String::String(wchar_t ch)
84 result r = InitializeToDefault(DEFAULT_CAPACITY);
85 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
92 String::String(const wchar_t* pValue)
100 int length = (pValue != null) ? wcslen(pValue) : 0;
102 SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
103 "String has wrong length. The length has to be more bigger than 0.");
107 result r = InitializeToDefault(DEFAULT_CAPACITY);
108 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
112 result r = InitializeToDefault(length + DEFAULT_CAPACITY);
113 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
115 wcsncpy(__pValue, pValue, length);
116 __pValue[length] = '\0';
121 String::String(const char* pValue)
127 , __pStringImpl(null)
129 int len = (pValue != null) ? mbstowcs(null, pValue, 0) : 0;
133 result r = InitializeToDefault(DEFAULT_CAPACITY);
134 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
138 result r = InitializeToDefault(len + DEFAULT_CAPACITY);
139 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
141 len = mbstowcs(__pValue, pValue, len);
144 SysLog(NID_BASE, "Invalid encoding range[%s].", pValue);
146 __pValue[len] = '\0';
151 String::String(const String& value)
152 : __capacity(value.__capacity)
153 , __length(value.__length)
154 , __hash(value.__hash)
156 , __pValue(value.__pValue)
157 , __pStringImpl(null)
159 SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
161 ++(*value.__pRefCount);
162 __pRefCount = value.__pRefCount;
165 String::~String(void)
167 if (*__pRefCount == 1)
180 String::operator [](int index) const
182 static wchar_t ch = -1;
183 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
184 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
185 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
186 return __pValue[index];
190 String::operator [](int index)
192 static wchar_t ch = -1;
193 SysTryReturn(NID_BASE, (index < __length && index >= 0), ch, E_OUT_OF_RANGE,
194 "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
195 GetErrorMessage(E_OUT_OF_RANGE), index, __length);
197 if (*__pRefCount > 1)
199 result r = CopyOnWrite(__capacity);
200 SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
204 return __pValue[index];
208 String::operator =(const wchar_t* pRhs)
222 String::operator =(const String& rhs)
236 String::operator +=(const wchar_t* pRhs)
249 String::operator +=(const String& rhs)
256 Append(rhs.__pValue);
262 operator +(const String& lhs, const String& rhs)
266 str.Append(rhs.__pValue);
272 String::operator ==(const String& rhs) const
274 if (__length != rhs.__length)
279 return(CompareTo(rhs) == 0);
283 String::operator !=(const String& rhs) const
285 return(!(*this).operator ==(rhs));
289 String::IsEmpty(void) const
291 return(__length == 0);
295 String::Append(wchar_t ch)
297 result r = Append(Character::ToString(ch));
298 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
304 String::Append(char ch)
306 result r = Append((wchar_t) ch);
307 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
313 String::Append(int i)
315 result r = Append(Integer::ToString(i));
316 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
322 String::Append(short s)
324 result r = Append(Short::ToString(s));
325 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
331 String::Append(long l)
333 result r = Append(Long::ToString(l));
334 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
340 String::Append(long long ll)
342 result r = Append(LongLong::ToString(ll));
343 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
349 String::Append(float f)
351 result r = Append(Float::ToString(f));
352 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
358 String::Append(double d)
360 result r = Append(Double::ToString(d));
361 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
367 String::Append(const wchar_t* p)
369 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
371 int length = (wcslen(p) + __length);
373 if (*__pRefCount > 1)
375 wchar_t* pValue = __pValue;
376 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
377 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
378 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
380 wcsncpy(__pValue, pValue, __length);
382 __pRefCount = pRefCntTemp.release();
385 result r = EnsureCapacity(length);
386 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
388 wcsncpy((__pValue + __length), p, wcslen(p));
390 __pValue[length] = '\0';
398 String::Append(const String& str)
405 result r = Append(str.__pValue);
406 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
419 String::Compare(const String& str0, const String& str1)
421 if (str0.__pValue == str1.__pValue)
426 return(wcscmp(str0.__pValue, str1.__pValue));
430 String::CompareTo(const String& str) const
432 if (__pValue == str.__pValue)
437 return(wcscmp(__pValue, str.__pValue));
441 String::EnsureCapacity(int minCapacity)
443 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
446 if (minCapacity > __capacity)
448 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
454 String::Equals(const Object& obj) const
456 const String* pOther = dynamic_cast <const String*>(&obj);
463 return(*this == *pOther);
467 String::Equals(const String& str, bool caseSensitive) const
471 return(*this == str);
475 if (__length != str.__length)
480 if (__pValue == str.__pValue)
485 if (wcscasecmp(__pValue, str.__pValue) == 0)
495 String::Format(int length, const wchar_t* pFormat, ...)
498 result r = E_SUCCESS;
500 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
501 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
504 String tempStr(pFormat);
505 if (tempStr.IsEmpty() || length == 0)
511 // Check "%n" and "%hn"
512 r = tempStr.IndexOf(L"%n", 0, index);
513 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
515 r = tempStr.IndexOf(L"%hn", 0, index);
516 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
520 std::unique_ptr<wchar_t []> pStr(new (std::nothrow) wchar_t[length + 1]);
521 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
525 va_start(args, pFormat);
527 vswprintf(pStr.get(), length, tempStr.__pValue, args);
533 int len = wcslen(this->__pValue);
536 this->__pValue[len] = '\0';
537 this->__length = len;
541 this->__pValue[length - 1] = '\0';
542 this->__length = length - 1;
550 String::GetHashCode(void) const
556 wchar_t* pStr = __pValue;
557 for (int i = 0; i < __length; ++i)
559 hash = (hash << 5) - hash + (int) *pStr++;
572 String::GetCharAt(int indexAt, wchar_t& ret) const
574 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
575 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
576 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
577 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
579 ret = __pValue[indexAt];
585 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
587 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
588 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
589 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
590 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
592 wchar_t* pBeg = __pValue + startIndex;
593 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
599 return E_OBJ_NOT_FOUND;
602 indexOf = int(pFound - __pValue);
608 String::IndexOf(const String& str, int startIndex, int& indexOf) const
610 SysTryReturnResult(NID_BASE, (startIndex < __length), E_OUT_OF_RANGE,
611 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
612 SysTryReturnResult(NID_BASE, (startIndex >= 0), E_OUT_OF_RANGE,
613 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
617 indexOf = startIndex;
621 if (__length < str.__length)
624 return E_OBJ_NOT_FOUND;
629 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
634 return E_OBJ_NOT_FOUND;
637 indexOf = int(p - __pValue);
643 String::Insert(wchar_t ch, int indexAt)
645 SysTryReturnResult(NID_BASE,
646 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
647 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
650 if (*__pRefCount > 1)
652 result r = CopyOnWrite(__capacity);
653 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
656 int length = (__length + 1);
658 result r = EnsureCapacity(length);
659 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
661 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
663 __pValue[indexAt] = ch;
671 String::Insert(char ch, int indexAt)
673 wchar_t wideChar = (wchar_t) ch;
675 result r = Insert(wideChar, indexAt);
676 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
682 String::Insert(short s, int indexAt)
684 result r = Insert(Short::ToString(s), indexAt);
685 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
691 String::Insert(int i, int indexAt)
693 result r = Insert(Integer::ToString(i), indexAt);
694 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
700 String::Insert(long l, int indexAt)
702 result r = Insert(Long::ToString(l), indexAt);
703 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
709 String::Insert(long long ll, int indexAt)
711 result r = Insert(LongLong::ToString(ll), indexAt);
712 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
718 String::Insert(float f, int indexAt)
720 result r = Insert(Float::ToString(f), indexAt);
721 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
727 String::Insert(double d, int indexAt)
729 result r = Insert(Double::ToString(d), indexAt);
730 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
735 String::Insert(const wchar_t* p, int indexAt)
737 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
738 SysTryReturnResult(NID_BASE,
739 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
740 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
743 int length = wcslen(p);
749 if (*__pRefCount > 1)
751 result r = CopyOnWrite(__capacity);
752 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
755 result r = EnsureCapacity(__length + length);
756 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
758 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
759 wmemcpy((__pValue + indexAt), p, length);
767 String::Insert(const String& str, int indexAt)
769 result r = Insert(str.__pValue, indexAt);
770 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
776 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
778 SysTryReturnResult(NID_BASE,
779 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
780 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
781 startIndex, __length);
783 wchar_t* pBeg = __pValue + startIndex;
784 wchar_t* pEnd = __pValue;
789 indexOf = int(pBeg - __pValue);
798 return E_OBJ_NOT_FOUND;
802 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
804 SysTryReturnResult(NID_BASE,
805 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
806 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
807 startIndex, __length);
811 indexOf = startIndex;
815 if (__length < str.__length)
819 return E_OBJ_NOT_FOUND;
822 const wchar_t* pStr = str.__pValue;
824 int length = str.__length;
825 if (length > startIndex)
829 return E_OBJ_NOT_FOUND;
833 wchar_t* pBeg = __pValue + startIndex;
834 wchar_t* pEnd = __pValue;
838 if (wcsncmp(pBeg, pStr, length) == 0)
840 indexOf = (pBeg - __pValue);
847 return E_OBJ_NOT_FOUND;
851 String::Remove(int startIndex, int count)
853 SysTryReturnResult(NID_BASE,
854 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
855 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
856 startIndex, __length);
857 int moveIndex = startIndex + count;
858 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
859 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
860 startIndex, count, __length);
862 if (*__pRefCount > 1)
864 result r = CopyOnWrite(__capacity);
865 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
868 wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
870 __pValue[__length] = '\0';
877 String::Replace(wchar_t original, wchar_t replace)
879 if (*__pRefCount > 1)
881 result r = CopyOnWrite(__capacity);
882 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
885 for (int length = __length; length >= 0; --length)
887 if (__pValue[length] == original)
889 __pValue[length] = replace;
896 String::Replace(const String& org, const String& rep)
898 result r = Replace(org, rep, 0);
899 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
905 String::Replace(const String& org, const String& rep, int startIndex)
907 const int orgLen = org.__length;
908 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
910 SysTryReturnResult(NID_BASE,
911 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
912 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
913 startIndex, __length);
920 if ((orgLen == __length) && (*this == org))
922 const int newLength = rep.__length;
923 if (EnsureCapacity(newLength) != E_SUCCESS)
925 SetCapacity(newLength);
928 wcsncpy(__pValue, rep.__pValue, rep.__length);
930 __length = rep.__length;
931 __pValue[__length] = '\0';
937 int repLen = rep.__length;
939 wchar_t* pOrg = org.__pValue;
940 wchar_t* pRep = rep.__pValue;
944 wchar_t* pBeg = (__pValue + startIndex);
945 wchar_t* pEnd = pBeg + __length;
948 wchar_t* pTarget = null;
949 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
952 pBeg = pTarget + orgLen;
954 pBeg += wcslen(pBeg) + 1;
960 if (*__pRefCount > 1)
962 result r = CopyOnWrite(__capacity);
963 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
966 const int newLength = (count * (repLen - orgLen)) + __length;
967 result r = EnsureCapacity(newLength);
968 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
970 wchar_t* pBeg = (__pValue + startIndex);
971 wchar_t* pEnd = pBeg + __length;
974 wchar_t* pTarget = null;
975 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
977 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
978 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
979 wmemcpy(pTarget, pRep, repLen);
980 pBeg = pTarget + repLen;
981 pTarget[repLen + balance] = 0;
982 __length += (repLen - orgLen);
984 pBeg += (wcslen(pBeg) + 1);
987 __length = newLength;
995 String::Reverse(void)
997 if (*__pRefCount > 1)
999 result r = CopyOnWrite(__capacity);
1000 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");
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 if (*__pRefCount > 1)
1067 result r = CopyOnWrite(__capacity);
1068 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1071 __pValue[indexAt] = ch;
1078 String::SetLength(int newLength)
1080 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1083 if (*__pRefCount > 1)
1085 result r = CopyOnWrite(__capacity);
1086 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1089 static const wchar_t SPACE = 0x0020;
1091 result r = EnsureCapacity(newLength);
1092 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1094 if (newLength > __length)
1096 wmemset(__pValue + __length, SPACE, newLength - __length);
1099 __pValue[newLength] = '\0';
1100 __length = newLength;
1107 String::SubString(int startIndex, String& out) const
1109 SysTryReturnResult(NID_BASE,
1110 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1111 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1112 startIndex, __length);
1114 out = __pValue + startIndex;
1120 String::SubString(int startIndex, int length, String& out) const
1122 SysTryReturnResult(NID_BASE,
1123 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1124 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1125 startIndex, __length);
1126 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1127 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1128 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1129 startIndex, length, __length);
1133 std::unique_ptr<wchar_t []> pTemp(new (std::nothrow) wchar_t[length + 1]);
1134 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1135 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1136 pTemp[length] = '\0';
1140 else if (length == 0)
1149 String::StartsWith(const String& str, int startIndex) const
1151 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1152 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1153 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1154 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1155 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1156 GetErrorMessage(E_INVALID_ARG), str.__length);
1158 if (str.__length > __length)
1163 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1172 String::EndsWith(const String& str) const
1179 int strLen = str.__length;
1180 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1181 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1183 int curLen = __length;
1184 if (strLen > curLen || curLen == 0)
1188 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1197 String::ToLower(String& out) const
1199 String str(__length + 1);
1201 wchar_t* pDst = str.__pValue;
1202 wchar_t* pSrc = __pValue;
1204 for (; *pSrc != 0; ++pSrc, ++pDst)
1206 *pDst = Character::ToLower(*pSrc);
1211 str.__length = __length;
1218 String::ToLowerCase(String& out) const
1220 String str(__length + 1);
1222 wchar_t* pDst = str.__pValue;
1223 wchar_t* pSrc = __pValue;
1225 for (; *pSrc != 0; ++pSrc, ++pDst)
1227 *pDst = Character::ToLowerCase(*pSrc);
1232 str.__length = __length;
1239 String::ToUpper(String& out) const
1241 String str(__length + 1);
1243 wchar_t* pDst = str.__pValue;
1244 wchar_t* pSrc = __pValue;
1246 for (; *pSrc != 0; ++pSrc, ++pDst)
1248 *pDst = Character::ToUpper(*pSrc);
1253 str.__length = __length;
1260 String::ToUpperCase(String& out) const
1262 String str(__length + 1);
1264 wchar_t* pDst = str.__pValue;
1265 wchar_t* pSrc = __pValue;
1266 for (; *pSrc != 0; ++pSrc, ++pDst)
1268 *pDst = Character::ToUpperCase(*pSrc);
1273 str.__length = __length;
1280 String::ToLower(void)
1282 if (*__pRefCount > 1)
1284 result r = CopyOnWrite(__capacity);
1285 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1288 String str(__length + 1);
1290 wchar_t* pDst = str.__pValue;
1291 wchar_t* pSrc = __pValue;
1293 for (; *pSrc != 0; ++pSrc, ++pDst)
1295 *pDst = Character::ToLower(*pSrc);
1298 wcsncpy(__pValue, str.__pValue, __length);
1299 __pValue[__length] = '\0';
1304 String::ToLowerCase(void)
1306 if (*__pRefCount > 1)
1308 result r = CopyOnWrite(__capacity);
1309 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1312 String str(__length + 1);
1314 wchar_t* pDst = str.__pValue;
1315 wchar_t* pSrc = __pValue;
1317 for (; *pSrc != 0; ++pSrc, ++pDst)
1319 *pDst = Character::ToLowerCase(*pSrc);
1322 wcsncpy(__pValue, str.__pValue, __length);
1323 __pValue[__length] = '\0';
1328 String::ToUpper(void)
1330 if (*__pRefCount > 1)
1332 result r = CopyOnWrite(__capacity);
1333 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1336 String str(__length + 1);
1338 wchar_t* pDst = str.__pValue;
1339 wchar_t* pSrc = __pValue;
1341 for (; *pSrc != 0; ++pSrc, ++pDst)
1343 *pDst = Character::ToUpper(*pSrc);
1346 wcsncpy(__pValue, str.__pValue, __length);
1347 __pValue[__length] = '\0';
1352 String::ToUpperCase(void)
1354 if (*__pRefCount > 1)
1356 result r = CopyOnWrite(__capacity);
1357 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1360 String str(__length + 1);
1362 wchar_t* pDst = str.__pValue;
1363 wchar_t* pSrc = __pValue;
1365 for (; *pSrc != 0; ++pSrc, ++pDst)
1367 *pDst = Character::ToUpperCase(*pSrc);
1370 wcsncpy(__pValue, str.__pValue, __length);
1371 __pValue[__length] = '\0';
1384 int lastIndex = __length;
1386 const wchar_t* pStr = __pValue;
1388 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1393 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1398 bool trimRight = lastIndex < __length;
1399 bool trimLeft = startIndex > 0;
1401 if (!trimRight && !trimLeft) // nothing to trim
1406 if (*__pRefCount > 1)
1408 result r = CopyOnWrite(__capacity);
1409 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1414 Remove(lastIndex, __length - lastIndex);
1419 Remove(0, startIndex);
1424 String::GetCapacity(void) const
1426 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1430 String::GetLength(void) const
1436 String::GetPointer(void) const
1443 String::Contains(const String& str) const
1445 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1446 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1447 GetErrorMessage(E_INVALID_ARG), str.__length);
1453 else if ((__length == str.__length) && (*this == str))
1458 wchar_t* pStart = __pValue;
1459 wchar_t* pEnd = pStart + __length;
1460 while (pStart < pEnd)
1462 while (wcsstr(pStart, str.__pValue) != null)
1473 String::AllocateCapacity(int capacity)
1475 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1476 if (__pValue == null)
1478 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1483 __pValue[capacity] = '\0';
1484 __capacity = capacity;
1490 String::ExpandCapacity(int minCapacity)
1492 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1494 if (minCapacity > capacity)
1496 capacity = minCapacity;
1499 std::unique_ptr<wchar_t []> pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1500 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1501 GetErrorMessage(E_OUT_OF_MEMORY));
1503 if (__pValue != null)
1505 wmemcpy(pNewValue.get(), __pValue, __length);
1506 pNewValue[__length] = '\0';
1508 if (*__pRefCount == 1)
1514 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1515 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1516 GetErrorMessage(E_OUT_OF_MEMORY));
1518 __pRefCount = pRefCntTemp.release();
1521 __pValue = pNewValue.release();
1522 __pValue[capacity] = '\0';
1523 __capacity = capacity;
1529 String::InitializeToDefault(int capacity)
1531 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1532 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1533 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1535 __pRefCount = pRefCntTemp.release();
1540 String::CopyOnWrite(int capacity)
1542 wchar_t* pValue = __pValue;
1543 std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
1544 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1545 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1547 wcsncpy(__pValue, pValue, __length);
1548 __pValue[__length] = '\0';
1550 __pRefCount = pRefCntTemp.release();
1555 String::Swap(String& str)
1557 std::swap(__capacity, str.__capacity);
1558 std::swap(__length, str.__length);
1559 std::swap(__hash, str.__hash);
1560 std::swap(__pRefCount, str.__pRefCount);
1561 std::swap(__pValue, str.__pValue);
1562 std::swap(__pStringImpl, str.__pStringImpl);