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)
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 _String::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 _String::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)
288 return(CompareTo(rhs) == 0);
292 String::operator !=(const String& rhs) const
294 return(!(*this).operator ==(rhs));
298 String::IsEmpty(void) const
300 return(__length == 0);
304 String::Append(wchar_t ch)
306 result r = Append(Character::ToString(ch));
307 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
313 String::Append(char ch)
315 result r = Append((wchar_t) ch);
316 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
322 String::Append(int i)
324 result r = Append(Integer::ToString(i));
325 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
331 String::Append(short s)
333 result r = Append(Short::ToString(s));
334 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
340 String::Append(long l)
342 result r = Append(Long::ToString(l));
343 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
349 String::Append(long long ll)
351 result r = Append(LongLong::ToString(ll));
352 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
358 String::Append(float f)
360 result r = Append(Float::ToString(f));
361 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
367 String::Append(double d)
369 result r = Append(Double::ToString(d));
370 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
376 String::Append(const wchar_t* p)
378 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "p is null.");
380 int length = (wcslen(p) + __length);
382 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
384 wchar_t* pValue = __pValue;
385 SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
386 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
387 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
389 wcsncpy(__pValue, pValue, __length);
390 _String::AtomicDec(__pRefCount);
391 __pRefCount = pRefCntTemp.release();
394 result r = EnsureCapacity(length);
395 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
397 wcsncpy((__pValue + __length), p, wcslen(p));
399 __pValue[length] = '\0';
407 String::Append(const String& str)
414 result r = Append(str.__pValue);
415 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
428 String::Compare(const String& str0, const String& str1)
430 if (str0.__pValue == str1.__pValue)
435 return(wcscmp(str0.__pValue, str1.__pValue));
439 String::CompareTo(const String& str) const
441 if (__pValue == str.__pValue)
446 return(wcscmp(__pValue, str.__pValue));
450 String::EnsureCapacity(int minCapacity)
452 SysTryReturnResult(NID_BASE, minCapacity >= 0, E_INVALID_ARG, "The minCapacity(%d) MUST be greater than or equal to 0.",
455 if (minCapacity > __capacity)
457 SysTryReturnResult(NID_BASE, ExpandCapacity(minCapacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
463 String::Equals(const Object& obj) const
465 const String* pOther = dynamic_cast< const String* >(&obj);
472 return(*this == *pOther);
476 String::Equals(const String& str, bool caseSensitive) const
480 return(*this == str);
484 if (__length != str.__length)
489 if (__pValue == str.__pValue)
494 if (wcscasecmp(__pValue, str.__pValue) == 0)
504 String::Format(int length, const wchar_t* pFormat, ...)
507 result r = E_SUCCESS;
509 SysTryReturnResult(NID_BASE, pFormat != null, E_INVALID_ARG, "The pFormat is null.");
510 SysTryReturnResult(NID_BASE, length >= 0, E_INVALID_ARG, "The length(%d) MUST be greater than or equal to 0.",
513 String tempStr(pFormat);
514 if (tempStr.IsEmpty() || length == 0)
520 // Check "%n" and "%hn"
521 r = tempStr.IndexOf(L"%n", 0, index);
522 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
524 r = tempStr.IndexOf(L"%hn", 0, index);
525 SysTryReturnResult(NID_BASE, r == E_OBJ_NOT_FOUND, E_INVALID_ARG, "(%ls) is not supported format.", pFormat);
529 std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
530 SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
534 va_start(args, pFormat);
536 vswprintf(pStr.get(), length, tempStr.__pValue, args);
542 int len = wcslen(this->__pValue);
545 this->__pValue[len] = '\0';
546 this->__length = len;
550 this->__pValue[length - 1] = '\0';
551 this->__length = length - 1;
559 String::GetHashCode(void) const
565 wchar_t* pStr = __pValue;
566 for (int i = 0; i < __length; ++i)
568 hash = (hash << 5) - hash + (int) *pStr++;
581 String::GetCharAt(int indexAt, wchar_t& ret) const
583 SysTryReturnResult(NID_BASE, (indexAt < __length), E_OUT_OF_RANGE,
584 "The indexAt(%d) MUST be less than the length of this string(%d).", indexAt, __length);
585 SysTryReturnResult(NID_BASE, (indexAt >= 0), E_OUT_OF_RANGE,
586 "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
588 ret = __pValue[indexAt];
594 String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
596 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
597 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
598 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
599 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
601 wchar_t* pBeg = __pValue + startIndex;
602 wchar_t* pFound = (wchar_t*) wcschr((const wchar_t*) pBeg, (wchar_t) ch);
608 return E_OBJ_NOT_FOUND;
611 indexOf = int(pFound - __pValue);
617 String::IndexOf(const String& str, int startIndex, int& indexOf) const
619 SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
620 "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
621 SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
622 "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
626 indexOf = startIndex;
630 if (__length < str.__length)
633 return E_OBJ_NOT_FOUND;
638 p = (wchar_t*) wcsstr((__pValue + startIndex), str.__pValue);
643 return E_OBJ_NOT_FOUND;
646 indexOf = int(p - __pValue);
652 String::Insert(wchar_t ch, int indexAt)
654 SysTryReturnResult(NID_BASE,
655 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
656 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
659 result r = AboutToModify(__capacity);
660 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
662 int length = (__length + 1);
664 r = EnsureCapacity(length);
665 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
667 wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
669 __pValue[indexAt] = ch;
677 String::Insert(char ch, int indexAt)
679 wchar_t wideChar = (wchar_t) ch;
681 result r = Insert(wideChar, indexAt);
682 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
688 String::Insert(short s, int indexAt)
690 result r = Insert(Short::ToString(s), indexAt);
691 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
697 String::Insert(int i, int indexAt)
699 result r = Insert(Integer::ToString(i), indexAt);
700 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
706 String::Insert(long l, int indexAt)
708 result r = Insert(Long::ToString(l), indexAt);
709 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
715 String::Insert(long long ll, int indexAt)
717 result r = Insert(LongLong::ToString(ll), indexAt);
718 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
724 String::Insert(float f, int indexAt)
726 result r = Insert(Float::ToString(f), indexAt);
727 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
733 String::Insert(double d, int indexAt)
735 result r = Insert(Double::ToString(d), indexAt);
736 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
741 String::Insert(const wchar_t* p, int indexAt)
743 SysTryReturnResult(NID_BASE, p != null, E_INVALID_ARG, "The p is null.");
744 SysTryReturnResult(NID_BASE,
745 indexAt >= 0 && indexAt <= __length, E_OUT_OF_RANGE,
746 "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
749 int length = wcslen(p);
755 result r = AboutToModify(__capacity);
756 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
758 r = EnsureCapacity(__length + length);
759 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
761 wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
762 wmemcpy((__pValue + indexAt), p, length);
770 String::Insert(const String& str, int indexAt)
772 result r = Insert(str.__pValue, indexAt);
773 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
779 String::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
781 SysTryReturnResult(NID_BASE,
782 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
783 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
784 startIndex, __length);
786 wchar_t* pBeg = __pValue + startIndex;
787 wchar_t* pEnd = __pValue;
792 indexOf = int(pBeg - __pValue);
801 return E_OBJ_NOT_FOUND;
805 String::LastIndexOf(const String& str, int startIndex, int& indexOf) const
807 SysTryReturnResult(NID_BASE,
808 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
809 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
810 startIndex, __length);
814 indexOf = startIndex;
818 if (__length < str.__length)
822 return E_OBJ_NOT_FOUND;
825 const wchar_t* pStr = str.__pValue;
827 int length = str.__length;
828 if (length > startIndex)
832 return E_OBJ_NOT_FOUND;
836 wchar_t* pBeg = __pValue + startIndex;
837 wchar_t* pEnd = __pValue;
841 if (wcsncmp(pBeg, pStr, length) == 0)
843 indexOf = (pBeg - __pValue);
850 return E_OBJ_NOT_FOUND;
854 String::Remove(int startIndex, int count)
856 SysTryReturnResult(NID_BASE,
857 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
858 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
859 startIndex, __length);
860 int moveIndex = startIndex + count;
861 SysTryReturnResult(NID_BASE, moveIndex <= __length, E_OUT_OF_RANGE,
862 "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
863 startIndex, count, __length);
865 result r = AboutToModify(__capacity);
866 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 result r = AboutToModify(__capacity);
880 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
882 for (int length = __length; length >= 0; --length)
884 if (__pValue[length] == original)
886 __pValue[length] = replace;
893 String::Replace(const String& org, const String& rep)
895 result r = Replace(org, rep, 0);
896 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
902 String::Replace(const String& org, const String& rep, int startIndex)
904 const int orgLen = org.__length;
905 SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
907 SysTryReturnResult(NID_BASE,
908 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
909 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
910 startIndex, __length);
917 if ((orgLen == __length) && (*this == org))
919 const int newLength = rep.__length;
920 if (EnsureCapacity(newLength) != E_SUCCESS)
922 SetCapacity(newLength);
925 wcsncpy(__pValue, rep.__pValue, rep.__length);
927 __length = rep.__length;
928 __pValue[__length] = '\0';
934 int repLen = rep.__length;
936 wchar_t* pOrg = org.__pValue;
937 wchar_t* pRep = rep.__pValue;
941 wchar_t* pBeg = (__pValue + startIndex);
942 wchar_t* pEnd = pBeg + __length;
945 wchar_t* pTarget = null;
946 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
949 pBeg = pTarget + orgLen;
951 pBeg += wcslen(pBeg) + 1;
957 result r = AboutToModify(__capacity);
958 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
960 const int newLength = (count * (repLen - orgLen)) + __length;
961 r = EnsureCapacity(newLength);
962 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
964 wchar_t* pBeg = (__pValue + startIndex);
965 wchar_t* pEnd = pBeg + __length;
968 wchar_t* pTarget = null;
969 while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
971 int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
972 wmemmove(pTarget + repLen, pTarget + orgLen, balance);
973 wmemcpy(pTarget, pRep, repLen);
974 pBeg = pTarget + repLen;
975 pTarget[repLen + balance] = 0;
976 __length += (repLen - orgLen);
978 pBeg += (wcslen(pBeg) + 1);
981 __length = newLength;
989 String::Reverse(void)
991 result r = AboutToModify(__capacity);
992 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
994 wchar_t* pBeg = __pValue;
995 wchar_t* pEnd = __pValue + __length - 1;
998 for (; pBeg < pEnd; ++pBeg, --pEnd)
1008 String::SetCapacity(int capacity)
1010 SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
1011 "The capacity(%d) MUST be greater than or equal to 0.", capacity);
1013 std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
1014 SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1016 if (__pValue != null)
1018 if (__length < capacity)
1020 wmemcpy(pValue.get(), __pValue, (__length + 1));
1024 wmemcpy(pValue.get(), __pValue, capacity);
1025 pValue[capacity] = '\0';
1026 __length = capacity;
1030 if (*__pRefCount == 1)
1036 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1037 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
1038 _String::AtomicDec(__pRefCount);
1039 __pRefCount = pRefCntTemp.release();
1043 __pValue = pValue.release();
1044 __capacity = capacity;
1050 String::SetCharAt(wchar_t ch, int indexAt)
1052 SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1053 "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
1054 GetErrorMessage(E_OUT_OF_RANGE), indexAt, __length);
1056 result r = AboutToModify(__capacity);
1057 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1059 __pValue[indexAt] = ch;
1066 String::SetLength(int newLength)
1068 SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
1071 result r = AboutToModify(__capacity);
1072 SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1074 static const wchar_t SPACE = 0x0020;
1076 r = EnsureCapacity(newLength);
1077 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
1079 if (newLength > __length)
1081 wmemset(__pValue + __length, SPACE, newLength - __length);
1084 __pValue[newLength] = '\0';
1085 __length = newLength;
1092 String::SubString(int startIndex, String& out) const
1094 SysTryReturnResult(NID_BASE,
1095 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1096 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1097 startIndex, __length);
1099 out = __pValue + startIndex;
1105 String::SubString(int startIndex, int length, String& out) const
1107 SysTryReturnResult(NID_BASE,
1108 startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
1109 "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1110 startIndex, __length);
1111 SysTryReturnResult(NID_BASE, length >= 0, E_OUT_OF_RANGE, "The length(%d) MUST be greater than 0.", length);
1112 SysTryReturnResult(NID_BASE, startIndex + length <= __length, E_OUT_OF_RANGE,
1113 "The startIndex(%d) + length(%d) MUST be less than or equal to the length of this string(%d).",
1114 startIndex, length, __length);
1118 std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
1119 SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1120 wcsncpy(pTemp.get(), __pValue + startIndex, length);
1121 pTemp[length] = '\0';
1125 else if (length == 0)
1134 String::StartsWith(const String& str, int startIndex) const
1136 SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __length, false, E_OUT_OF_RANGE,
1137 "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
1138 GetErrorMessage(E_OUT_OF_RANGE), startIndex, __length);
1139 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1140 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1141 GetErrorMessage(E_INVALID_ARG), str.__length);
1143 if (str.__length > __length)
1148 if ((wcsncmp(__pValue + startIndex, str.__pValue, str.__length) == 0))
1157 String::EndsWith(const String& str) const
1164 int strLen = str.__length;
1165 SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
1166 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
1168 int curLen = __length;
1169 if (strLen > curLen || curLen == 0)
1173 else if (wcscmp(__pValue + (curLen - strLen), str.__pValue) == 0)
1182 String::ToLower(String& out) const
1184 String str(__length + 1);
1186 wchar_t* pDst = str.__pValue;
1187 wchar_t* pSrc = __pValue;
1189 for (; *pSrc != 0; ++pSrc, ++pDst)
1191 *pDst = Character::ToLower(*pSrc);
1196 str.__length = __length;
1203 String::ToLowerCase(String& out) const
1205 String str(__length + 1);
1207 wchar_t* pDst = str.__pValue;
1208 wchar_t* pSrc = __pValue;
1210 for (; *pSrc != 0; ++pSrc, ++pDst)
1212 *pDst = Character::ToLowerCase(*pSrc);
1217 str.__length = __length;
1224 String::ToUpper(String& out) const
1226 String str(__length + 1);
1228 wchar_t* pDst = str.__pValue;
1229 wchar_t* pSrc = __pValue;
1231 for (; *pSrc != 0; ++pSrc, ++pDst)
1233 *pDst = Character::ToUpper(*pSrc);
1238 str.__length = __length;
1245 String::ToUpperCase(String& out) const
1247 String str(__length + 1);
1249 wchar_t* pDst = str.__pValue;
1250 wchar_t* pSrc = __pValue;
1251 for (; *pSrc != 0; ++pSrc, ++pDst)
1253 *pDst = Character::ToUpperCase(*pSrc);
1258 str.__length = __length;
1265 String::ToLower(void)
1267 result r = AboutToModify(__capacity);
1268 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1270 String str(__length + 1);
1272 wchar_t* pDst = str.__pValue;
1273 wchar_t* pSrc = __pValue;
1275 for (; *pSrc != 0; ++pSrc, ++pDst)
1277 *pDst = Character::ToLower(*pSrc);
1280 wcsncpy(__pValue, str.__pValue, __length);
1281 __pValue[__length] = '\0';
1286 String::ToLowerCase(void)
1288 result r = AboutToModify(__capacity);
1289 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1291 String str(__length + 1);
1293 wchar_t* pDst = str.__pValue;
1294 wchar_t* pSrc = __pValue;
1296 for (; *pSrc != 0; ++pSrc, ++pDst)
1298 *pDst = Character::ToLowerCase(*pSrc);
1301 wcsncpy(__pValue, str.__pValue, __length);
1302 __pValue[__length] = '\0';
1307 String::ToUpper(void)
1309 result r = AboutToModify(__capacity);
1310 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::ToUpper(*pSrc);
1322 wcsncpy(__pValue, str.__pValue, __length);
1323 __pValue[__length] = '\0';
1328 String::ToUpperCase(void)
1330 result r = AboutToModify(__capacity);
1331 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
1333 String str(__length + 1);
1335 wchar_t* pDst = str.__pValue;
1336 wchar_t* pSrc = __pValue;
1338 for (; *pSrc != 0; ++pSrc, ++pDst)
1340 *pDst = Character::ToUpperCase(*pSrc);
1343 wcsncpy(__pValue, str.__pValue, __length);
1344 __pValue[__length] = '\0';
1357 int lastIndex = __length;
1359 const wchar_t* pStr = __pValue;
1361 while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
1366 while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
1371 bool trimRight = lastIndex < __length;
1372 bool trimLeft = startIndex > 0;
1374 if (!trimRight && !trimLeft) // nothing to trim
1379 result r = AboutToModify(__capacity);
1380 SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
1384 Remove(lastIndex, __length - lastIndex);
1389 Remove(0, startIndex);
1394 String::GetCapacity(void) const
1396 return __capacity; // REMARK: the actual allocated size of buffer is __capacity + 1
1400 String::GetLength(void) const
1406 String::GetPointer(void) const
1413 String::Contains(const String& str) const
1415 SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
1416 "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
1417 GetErrorMessage(E_INVALID_ARG), str.__length);
1423 else if ((__length == str.__length) && (*this == str))
1428 wchar_t* pStart = __pValue;
1429 wchar_t* pEnd = pStart + __length;
1430 while (pStart < pEnd)
1432 while (wcsstr(pStart, str.__pValue) != null)
1443 String::AllocateCapacity(int capacity)
1445 __pValue = new (std::nothrow) wchar_t[capacity + 1]; // + 1 for null character
1446 if (__pValue == null)
1448 SysLogException(NID_BASE, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1453 __pValue[capacity] = '\0';
1454 __capacity = capacity;
1460 String::ExpandCapacity(int minCapacity)
1462 int capacity = (__capacity ? (4 * (((int) (GROWTH_FACTOR * __capacity) - 1) / 4 + 1)) : 0); // nearest multiple of 4
1464 if (minCapacity > capacity)
1466 capacity = minCapacity;
1469 std::unique_ptr< wchar_t[] > pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
1470 SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
1471 GetErrorMessage(E_OUT_OF_MEMORY));
1473 if (__pValue != null)
1475 wmemcpy(pNewValue.get(), __pValue, __length);
1476 pNewValue[__length] = '\0';
1478 if (*__pRefCount == 1)
1484 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1485 SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
1486 GetErrorMessage(E_OUT_OF_MEMORY));
1487 _String::AtomicDec(__pRefCount);
1488 __pRefCount = pRefCntTemp.release();
1491 __pValue = pNewValue.release();
1492 __pValue[capacity] = '\0';
1493 __capacity = capacity;
1499 String::InitializeToDefault(int capacity)
1501 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1502 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1503 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
1505 __pRefCount = pRefCntTemp.release();
1510 String::AboutToModify(int capacity, bool isUnshareable)
1512 if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
1514 wchar_t* pValue = __pValue;
1515 std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
1516 SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
1517 SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
1519 wcsncpy(__pValue, pValue, __length);
1520 __pValue[__length] = '\0';
1522 _String::AtomicDec(__pRefCount);
1523 __pRefCount = pRefCntTemp.release();
1528 *__pRefCount = UNSHAREABLE;
1535 String::Swap(String& str)
1537 std::swap(__capacity, str.__capacity);
1538 std::swap(__length, str.__length);
1539 std::swap(__hash, str.__hash);
1540 std::swap(__pRefCount, str.__pRefCount);
1541 std::swap(__pValue, str.__pValue);
1542 std::swap(__pStringImpl, str.__pStringImpl);