Implementation of ImmutableString 34/12934/10
authorKeebong <keebong.bahn@samsung.com>
Fri, 8 Nov 2013 07:15:31 +0000 (16:15 +0900)
committerKeebong <keebong.bahn@samsung.com>
Thu, 5 Dec 2013 09:41:48 +0000 (18:41 +0900)
Change-Id: I6efdfba089a1d20196e5c637600eb3f72a2e724d
Signed-off-by: Keebong <keebong.bahn@samsung.com>
inc/FBaseImmutableString.h
src/base/CMakeLists.txt
src/base/FBaseImmutableString.cpp [new file with mode: 0644]
src/base/FBase_StringBuffer.cpp [new file with mode: 0644]
src/base/inc/FBase_StringBuffer.h [new file with mode: 0644]

index f2eaf4b..a66324b 100644 (file)
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//             http://www.apache.org/licenses/LICENSE-2.0
+//     http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
@@ -31,6 +31,9 @@
 
 namespace Tizen { namespace Base
 {
+
+class _StringBuffer;
+
 /**
  *     @class  ImmutableString
  *     @brief  This class represents a immutable sequence of Unicode characters.
@@ -75,7 +78,7 @@ public:
         * @since 3.0
         *
         * @param[in]   pStr    A pointer to an array of Unicode characters
-        * @remark              If whcar_t* type null pointer is entered on parameter, the empty string is set.
+        * @remarks             If whcar_t* type null pointer is entered on parameter, the empty string is set.
         */
        explicit ImmutableString(const wchar_t* pStr);
 
@@ -85,7 +88,7 @@ public:
         * @since 3.0
         *
         * @param[in]   pStr    A pointer to an array of UTF-8 characters
-        * @remark              If char* type null pointer is entered on parameter, the empty string is set.
+        * @remarks             If char* type null pointer is entered on parameter, the empty string is set.
         */
        explicit ImmutableString(const char* pStr);
 
@@ -161,8 +164,7 @@ public:
         * @return              @c true if this instance contains the specified substring, @n
         *                              else @c false
         * @param[in]   str     The string to match
-        * @exception   E_SUCCESS       The method is successful.
-        * @exception   E_INVALID_ARG   The specified @c str is an empty string.
+        * @remarks             This method returns @c true when an empty string is entered on parameter.
         */
        bool Contains(const ImmutableString& str) const;
 
@@ -176,6 +178,7 @@ public:
         * @param[in]   str     An instance to match
         * @exception   E_SUCCESS       The method is successful.
         * @exception   E_INVALID_ARG   The specified @c str is an empty string.
+        * @remarks             The specific error code can be accessed by using GetLastResult() method.
         */
        bool EndsWith(const ImmutableString& str) const;
 
@@ -219,9 +222,13 @@ public:
         * @exception   E_INVALID_ARG   Either of the following conditions has occurred:
         *                                                              - The specified @c length is negative.
         *                                                              - The specified @c pFormat is @c null.
+        *                                                              - The specified @c pFormat includes "%n" or "%hn" which may cause format string vulnerability.
         * @remarks
         *                      - If an "l" modifier is present in @c pFormat (for example, L"@%ls"), it is a pointer to an array of wide characters.
         *                      - A pointer to an array of UTF-8 characters is not allowed in the Format() method (for example, Format(20, L"@%s", pUTF8Str)).
+        *                      - This method is locale-dependent.
+        *                      - This method returns an empty string when an exception occurs.
+        *                      - The specific error code can be accessed by using the GetLastResult() method.
         * The following format specifiers are supported in this method:
         * @code
         * specifier    Output
@@ -263,7 +270,7 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c indexAt is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c indexAt is less than @c 0.
-        * @remark              This method does not guarantee a usable value of out-parameter when an error occurs.
+        * @remarks             This method does not guarantee a usable value of out-parameter when an error occurs.
         */
        result GetCharAt(int indexAt, wchar_t& ch) const;
 
@@ -311,7 +318,7 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
-        * @remark              This method does not guarantee a usable value of out-parameter when an error occurs.
+        * @remarks             Do not use the @c indexOf when the method returns an error.
         */
        result IndexOf(wchar_t ch, int startIndex, int& indexOf) const;
 
@@ -330,7 +337,7 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
-        * @remark              This method does not guarantee a usable value of out-parameter when an error occurs.
+        * @remarks             Do not use the @c indexOf when the method returns an error.
         */
        result IndexOf(const ImmutableString& str, int startIndex, int& indexOf) const;
 
@@ -344,9 +351,11 @@ public:
         * @param[in]   indexAt The position to insert @c str
         * @exception   E_SUCCESS       The method is successful.
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
-        *                                                              - The specified @c indexAt is either greater than or equal to the length of the current instance.
+        *                                                              - The specified @c indexAt is greater than the length of the current instance.
         *                                                              - The specified @c indexAt is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString Insert(const ImmutableString& str, int indexAt) const;
 
@@ -375,7 +384,7 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
-        * @remark              This method does not guarantee a usable value of out-parameter when an error occurs.
+        * @remarks             Do not use the @c indexOf when the method returns an error.
         * @code
         *
         *      int indexOf;
@@ -406,7 +415,7 @@ public:
         *
         * @remarks
         *                              - If the substring is empty, E_SUCCESS is returned and the value of @c indexOf is set to @c startIndex.
-        *                              - This method does not guarantee a usable value of out-parameter when an error occurs.
+        *                              - Do not use the @c indexOf when the method returns an error.
         * @code
         *
         *      int indexOf;
@@ -435,7 +444,9 @@ public:
         *                                                              - The specified @c startIndex is less than @c 0.
         *                                                              - The specified @c length is greater than the length of the substring starting from @c startIndex.
         *                                                              - The specified @c length is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString Remove(int startIndex, int length) const;
 
@@ -464,7 +475,9 @@ public:
         * @param[in]   replace An instance to replace all occurrences of @c original by
         * @exception   E_SUCCESS               The method is successful.
         * @exception   E_INVALID_ARG   The specified @c original is an empty string.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString Replace(const ImmutableString& original, const ImmutableString& replace) const;
 
@@ -484,7 +497,10 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        *                                                              - The length of the specified @c original is greater than the length of the substring starting from @c startIndex.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString Replace(const ImmutableString& original, const ImmutableString& replace, int startIndex) const;
 
@@ -511,7 +527,9 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c indexAt is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c indexAt is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString SetCharAt(wchar_t ch, int indexAt) const;
 
@@ -529,6 +547,9 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
+        * @remarks
+        *                              - The specific error code can be accessed by using GetLastResult() method.
+        *                              - This method returns @c true when an empty string is entered on parameter.
         */
        bool StartsWith(const ImmutableString& str, int startIndex) const;
 
@@ -557,7 +578,9 @@ public:
         * @exception   E_OUT_OF_RANGE  Either of the following conditions has occurred:
         *                                                              - The specified @c startIndex is either greater than or equal to the length of the current instance.
         *                                                              - The specified @c startIndex is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString SubString(int startIndex) const;
 
@@ -577,7 +600,9 @@ public:
         *                                                              - The specified @c startIndex is less than @c 0.
         *                                                              - The specified @c length is greater than the length of the substring starting from @c startIndex.
         *                                                              - The specified @c length is less than @c 0.
-        * @remark              This method returns an empty string when an exception occurs.
+        * @remarks
+        *                              - This method returns an empty string when an exception occurs.
+        *                              - The specific error code can be accessed by using GetLastResult() method.
         */
        ImmutableString SubString(int startIndex, int length) const;
 
@@ -630,14 +655,12 @@ private:
        //
        // Overloaded constructor
        //
-       explicit ImmutableString(int capacity);
+       ImmutableString(_StringBuffer* pBuf);
 
 private:
 
-       class _StringBuffer* __pImpl;
+       _StringBuffer* __pImpl;
        friend class _StringBuffer;
-
-       class _ImmutableStringImpl* __pImmutableStringImpl;
 };
 
 /**
index e5f3de2..2822816 100755 (executable)
@@ -22,6 +22,7 @@ SET (${this_target}_SOURCE_FILES
        FBaseErrors.cpp
        FBaseFloat.cpp
        FBaseFloatComparer.cpp
+       FBaseImmutableString.cpp
        FBaseInt8.cpp
        FBaseInt8Comparer.cpp
        FBaseInteger8.cpp
@@ -40,6 +41,7 @@ SET (${this_target}_SOURCE_FILES
        FBaseString.cpp
        FBaseStringComparer.cpp
        FBaseStringHashCodeProvider.cpp
+       FBase_StringBuffer.cpp
        FBase_StringConverter.cpp
        FBaseSys.cpp
        FBaseTimeSpan.cpp
diff --git a/src/base/FBaseImmutableString.cpp b/src/base/FBaseImmutableString.cpp
new file mode 100644 (file)
index 0000000..ff1736d
--- /dev/null
@@ -0,0 +1,554 @@
+//
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file       FBaseImmutableString.cpp
+ * @brief      This is the implementation for ImmutableString class.
+ */
+#include <wchar.h>
+#include <stdarg.h>
+#include <new>
+#include <FBaseImmutableString.h>
+#include <FBase_StringBuffer.h>
+#include <FBaseResult.h>
+#include <FBaseSysLog.h>
+#include <unique_ptr.h>
+#include "FBaseUtil_AtomicOperations.h"
+
+namespace Tizen { namespace Base
+{
+
+ImmutableString::ImmutableString(const wchar_t* pStr)
+       : __pImpl(new (std::nothrow) _StringBuffer(pStr))
+{
+       SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+}
+
+ImmutableString::ImmutableString(const char* pStr)
+       : __pImpl(new (std::nothrow) _StringBuffer(pStr))
+{
+       SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+}
+
+ImmutableString::ImmutableString(const String& value)
+       : __pImpl(new (std::nothrow) _StringBuffer(value))
+{
+       SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+}
+
+ImmutableString::ImmutableString(const ImmutableString& value)
+       : __pImpl(null)
+{
+       Utility::_AtomicOperations::AtomicInc(&(value.__pImpl->__refCount));
+       __pImpl = value.__pImpl;
+}
+
+ImmutableString::~ImmutableString(void)
+{
+       if (__pImpl->__refCount > 1)
+       {
+               Utility::_AtomicOperations::AtomicDec(&(__pImpl->__refCount));
+               __pImpl = null;
+       }
+       else
+       {
+               delete __pImpl;
+       }
+}
+
+wchar_t
+ImmutableString::operator [](int index) const
+{
+       return __pImpl->__pValue[index];
+}
+
+ImmutableString
+ImmutableString::Append(const ImmutableString& str) const
+{
+       ClearLastResult();
+       return ImmutableString(__pImpl->__pValue, str.GetPointer());
+}
+
+int
+ImmutableString::CompareTo(const ImmutableString& str) const
+{
+       if (__pImpl->__pValue == str.__pImpl->__pValue)
+       {
+               return 0;
+       }
+
+       return wcscmp(__pImpl->__pValue, str.__pImpl->__pValue);
+}
+
+bool
+ImmutableString::Contains(const ImmutableString& str) const
+{
+       return (wcsstr(__pImpl->__pValue, str.__pImpl->__pValue) != null);
+}
+
+bool
+ImmutableString::EndsWith(const ImmutableString& str) const
+{
+       int strLen = str.__pImpl->__length;
+       SysTryReturn(NID_BASE, strLen > 0, false, E_INVALID_ARG,
+               "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.", GetErrorMessage(E_INVALID_ARG), strLen);
+
+       SetLastResult(E_SUCCESS);
+
+       int curLen = __pImpl->__length;
+       if (strLen > curLen || curLen == 0)
+       {
+               return false;
+       }
+       else if (wcscmp(__pImpl->__pValue + (curLen - strLen), str.__pImpl->__pValue) == 0)
+       {
+               return true;
+       }
+
+       return false;
+}
+
+bool
+ImmutableString::Equals(const Object& obj) const
+{
+       const ImmutableString* pOther = dynamic_cast< const ImmutableString* >(&obj);
+
+       if (pOther == null)
+       {
+               return false;
+       }
+
+       if (__pImpl->__length != pOther->__pImpl->__length)
+       {
+               return false;
+       }
+
+       return (CompareTo(*pOther) == 0);
+}
+
+bool
+ImmutableString::EqualsCaseInsensitive(const ImmutableString& str) const
+{
+       if (__pImpl->__length != str.__pImpl->__length)
+       {
+               return false;
+       }
+
+       if (__pImpl->__pValue == str.__pImpl->__pValue)
+       {
+               return true;
+       }
+
+       if (wcscasecmp(__pImpl->__pValue, str.__pImpl->__pValue) == 0)
+       {
+               return true;
+       }
+
+       return false;
+}
+
+ImmutableString
+ImmutableString::Format(int length, const wchar_t* pFormat, ...)
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, pFormat != null, ImmutableString(L""), E_INVALID_ARG, "[%s] The pFormat is null.", GetErrorMessage(E_INVALID_ARG));
+       SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_INVALID_ARG,
+               "[%s] The length(%d) MUST be greater than or equal to 0.", GetErrorMessage(E_INVALID_ARG), length);
+
+       if ((*pFormat == L'\0') || (length == 0))
+       {
+               return ImmutableString(L"");
+       }
+
+       // Check "%n" and "%hn"
+       SysTryReturn(NID_BASE, wcsstr(pFormat, L"%n") == null, ImmutableString(L""), E_INVALID_ARG,
+               "[%s] (%ls) is not supported format.", GetErrorMessage(E_INVALID_ARG), pFormat);
+       SysTryReturn(NID_BASE, wcsstr(pFormat, L"%hn") == null, ImmutableString(L""), E_INVALID_ARG,
+               "[%s] (%ls) is not supported format.", GetErrorMessage(E_INVALID_ARG), pFormat);
+
+       va_list args;
+       va_start(args, pFormat);
+
+       _StringBuffer* pBuf = _StringBuffer::Format(length, pFormat, args);
+
+       va_end(args);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+result
+ImmutableString::GetCharAt(int indexAt, wchar_t& ret) const
+{
+       SysTryReturnResult(NID_BASE, indexAt < __pImpl->__length, E_OUT_OF_RANGE,
+               "The indexAt(%d) MUST be less than the length of this ImmutableString(%d).", indexAt, __pImpl->__length);
+       SysTryReturnResult(NID_BASE, indexAt >= 0, E_OUT_OF_RANGE,
+               "The indexAt(%d) MUST be greater than or equal to 0.", indexAt);
+
+       ret = __pImpl->__pValue[indexAt];
+       return E_SUCCESS;
+}
+
+int
+ImmutableString::GetHashCode(void) const
+{
+       if (__pImpl->__length == 0)
+       {
+               return 0;
+       }
+
+       if (__pImpl->__hash == 0)
+       {
+               __pImpl->__hash = __pImpl->GetHashCode(__pImpl->__pValue);
+       }
+       return __pImpl->__hash;
+}
+
+int
+ImmutableString::GetLength(void) const
+{
+       return __pImpl->__length;
+}
+
+const wchar_t*
+ImmutableString::GetPointer(void) const
+{
+       return __pImpl->__pValue;
+}
+
+result
+ImmutableString::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
+{
+       SysTryReturnResult(NID_BASE, startIndex < __pImpl->__length, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be less than the length of this ImmutableString(%d).", startIndex, __pImpl->__length);
+       SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
+
+       wchar_t* pBeg = __pImpl->__pValue + startIndex;
+       wchar_t* pFound = wcschr(pBeg, ch);
+
+
+       SysTryReturnResult(NID_BASE, pFound, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t character is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), ch);
+
+
+       indexOf = static_cast< int >(pFound - __pImpl->__pValue);
+       return E_SUCCESS;
+}
+
+result
+ImmutableString::IndexOf(const ImmutableString& str, int startIndex, int& indexOf) const
+{
+       SysTryReturnResult(NID_BASE, startIndex < __pImpl->__length, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be less than the length of this ImmutableString(%d).", startIndex, __pImpl->__length);
+       SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
+
+       if (str.IsEmpty())
+       {
+               indexOf = startIndex;
+               return E_SUCCESS;
+       }
+
+       SysTryReturnResult(NID_BASE, __pImpl->__length >= str.__pImpl->__length, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
+
+       wchar_t* pStr = wcsstr(__pImpl->__pValue + startIndex, str.__pImpl->__pValue);
+
+       SysTryReturnResult(NID_BASE, pStr, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
+
+       indexOf = static_cast< int >(pStr - __pImpl->__pValue);
+       return E_SUCCESS;
+}
+
+ImmutableString
+ImmutableString::Insert(const ImmutableString& str, int indexAt) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, (indexAt >= 0) && (indexAt <= __pImpl->__length), ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), indexAt, __pImpl->__length);
+
+       _StringBuffer* pBuf = __pImpl->Insert(str.__pImpl, indexAt);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+bool
+ImmutableString::IsEmpty(void) const
+{
+       return (__pImpl->__length == 0);
+}
+
+result
+ImmutableString::LastIndexOf(wchar_t ch, int startIndex, int& indexOf) const
+{
+       SysTryReturnResult(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               startIndex, __pImpl->__length);
+
+       wchar_t* pBeg = __pImpl->__pValue + startIndex;
+       wchar_t* pEnd = __pImpl->__pValue;
+       while (pEnd <= pBeg)
+       {
+               if (*pBeg == ch)
+               {
+                       indexOf = static_cast< int >(pBeg - __pImpl->__pValue);
+                       return E_SUCCESS;
+               }
+               --pBeg;
+       }
+
+       SysTryReturnResult(NID_BASE, false, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t character is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), ch);
+}
+
+result
+ImmutableString::LastIndexOf(const ImmutableString& str, int startIndex, int& indexOf) const
+{
+       SysTryReturnResult(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, E_OUT_OF_RANGE,
+               "The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               startIndex, __pImpl->__length);
+
+       if (str.IsEmpty())
+       {
+               indexOf = startIndex;
+               return E_SUCCESS;
+       }
+
+       SysTryReturnResult(NID_BASE, __pImpl->__length >= str.__pImpl->__length, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
+
+       const wchar_t* pStr = str.__pImpl->__pValue;
+
+       int length = str.__pImpl->__length;
+
+       SysTryReturnResult(NID_BASE, length <= startIndex, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
+
+       wchar_t* pBeg = __pImpl->__pValue + startIndex;
+       wchar_t* pEnd = __pImpl->__pValue;
+
+       while (pBeg >= pEnd)
+       {
+               if (wcsncmp(pBeg, pStr, length) == 0)
+               {
+                       indexOf = (pBeg - __pImpl->__pValue);
+
+                       return E_SUCCESS;
+               }
+               --pBeg;
+       }
+
+       SysTryReturnResult(NID_BASE, false, E_OBJ_NOT_FOUND, "[%s] The expected wchar_t string is not found.",
+               GetErrorMessage(E_OBJ_NOT_FOUND), str.GetPointer());
+}
+
+ImmutableString
+ImmutableString::Remove(int startIndex, int length) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, ((startIndex >= 0) && (startIndex < __pImpl->__length)), ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
+
+       SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The length(%d) MUST be geater than or equal to 0.", GetErrorMessage(E_OUT_OF_RANGE), length);
+
+       int moveIndex = startIndex + length;
+       SysTryReturn(NID_BASE, moveIndex <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) + length(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, length, __pImpl->__length);
+
+       _StringBuffer* pBuf = __pImpl->Remove(startIndex, length);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::Replace(wchar_t original, wchar_t replace) const
+{
+       ClearLastResult();
+       _StringBuffer* pBuf = __pImpl->Replace(original, replace);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::Replace(const ImmutableString& org, const ImmutableString& rep, int startIndex) const
+{
+       ClearLastResult();
+       const int orgLen = org.__pImpl->__length;
+       SysTryReturn(NID_BASE, orgLen > 0, ImmutableString(L""), E_INVALID_ARG, "[%s] The length of org(%d) MUST be greater than 0.",
+               GetErrorMessage(E_INVALID_ARG), orgLen);
+
+       SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
+
+       SysTryReturn(NID_BASE, orgLen + startIndex <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The length of org(%d) + startIndex(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), org.__pImpl->__length, startIndex, __pImpl->__length);
+
+       _StringBuffer* pBuf = __pImpl->Replace(org.__pImpl, rep.__pImpl, startIndex);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::Replace(const ImmutableString& org, const ImmutableString& rep) const
+{
+       return Replace(org, rep, 0);
+}
+
+ImmutableString
+ImmutableString::Reverse(void) const
+{
+       ClearLastResult();
+       _StringBuffer* pBuf = __pImpl->Reverse();
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::SetCharAt(wchar_t ch, int indexAt) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The indexAt(%d) MUST be greater than or equal to 0, and less then the length of this string(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), indexAt, __pImpl->__length);
+
+       _StringBuffer* pBuf = __pImpl->SetCharAt(ch, indexAt);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+bool
+ImmutableString::StartsWith(const ImmutableString& str, int startIndex) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, false, E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
+
+       if (str.__pImpl->__length > __pImpl->__length)
+       {
+               return false;
+       }
+
+       if ((wcsncmp(__pImpl->__pValue + startIndex, str.__pImpl->__pValue, str.__pImpl->__length) == 0))
+       {
+               return true;
+       }
+       return false;
+}
+
+bool
+ImmutableString::StartsWith(const ImmutableString& str) const
+{
+       return StartsWith(str, 0);
+}
+
+ImmutableString
+ImmutableString::SubString(int startIndex) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
+
+       return SubString(startIndex, __pImpl->__length - startIndex);
+}
+
+ImmutableString
+ImmutableString::SubString(int startIndex, int length) const
+{
+       ClearLastResult();
+       SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) MUST be greater than or equal to 0, and less than the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, __pImpl->__length);
+       SysTryReturn(NID_BASE, length >= 0, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The length(%d) MUST be greater than 0.", GetErrorMessage(E_OUT_OF_RANGE), length);
+       SysTryReturn(NID_BASE, startIndex + length <= __pImpl->__length, ImmutableString(L""), E_OUT_OF_RANGE,
+               "[%s] The startIndex(%d) + length(%d) MUST be less than or equal to the length of this ImmutableString(%d).",
+               GetErrorMessage(E_OUT_OF_RANGE), startIndex, length, __pImpl->__length);
+
+       _StringBuffer* pBuf = __pImpl->SubString(startIndex, length);
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::ToUpperCase(void) const
+{
+       ClearLastResult();
+       _StringBuffer* pBuf = __pImpl->ToUpperCase();
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::ToLowerCase(void) const
+{
+       ClearLastResult();
+       _StringBuffer* pBuf = __pImpl->ToLowerCase();
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString
+ImmutableString::Trim(void) const
+{
+       ClearLastResult();
+       _StringBuffer* pBuf = __pImpl->Trim();
+
+       SysTryReturn(NID_BASE, pBuf != null, ImmutableString(pBuf), E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       return ImmutableString(pBuf);
+}
+
+ImmutableString::ImmutableString(const wchar_t* pStr1, const wchar_t* pStr2)
+       : __pImpl(new (std::nothrow) _StringBuffer(pStr1, pStr2))
+{
+       SysTryReturnVoidResult(NID_BASE, __pImpl != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+}
+
+ImmutableString::ImmutableString(_StringBuffer* pBuf)
+       : __pImpl(pBuf)
+{
+}
+
+}} //Tizen::Base
diff --git a/src/base/FBase_StringBuffer.cpp b/src/base/FBase_StringBuffer.cpp
new file mode 100644 (file)
index 0000000..eb5efba
--- /dev/null
@@ -0,0 +1,427 @@
+//
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file               FBase_StringBuffer.cpp
+ * @brief      This is the implementation for _StringBuffer class.
+ */
+
+#include <wchar.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <new>
+#include <FBaseString.h>
+#include <FBaseCharacter.h>
+#include <FBaseImmutableString.h>
+#include <FBase_StringBuffer.h>
+#include <unique_ptr.h>
+#include <FBaseResult.h>
+#include <FBaseSysLog.h>
+#include "FBaseUtil_IcuConverter.h"
+
+namespace Tizen { namespace Base
+{
+
+_StringBuffer::_StringBuffer(const wchar_t* pStr)
+       : __pValue(null)
+       , __length(0)
+       , __hash(0)
+       , __refCount(1)
+{
+       if (pStr)
+       {
+               int length = wcslen(pStr);
+               __pValue = new (std::nothrow) wchar_t[length + 1];
+               SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+               wcsncpy(__pValue, pStr, length);
+               __pValue[length] = L'\0';
+               __length = length;
+       }
+       else
+       {
+               __pValue = new (std::nothrow) wchar_t[1];
+               SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+               __pValue[0] = L'\0';
+       }
+}
+
+_StringBuffer::_StringBuffer(const char* pStr)
+       : __pValue(null)
+       , __length(0)
+       , __hash(0)
+       , __refCount(1)
+{
+       if (pStr)
+       {
+               std::unique_ptr< wchar_t[] > pWcharStr(Tizen::Base::Utility::Utf8ToWcharN(pStr));
+               SysTryReturnVoidResult(NID_BASE, pWcharStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
+               __pValue = pWcharStr.release();
+               __length = wcslen(__pValue);
+               __pValue[__length] = L'\0';
+       }
+       else
+       {
+               __pValue = new (std::nothrow) wchar_t[1];
+               SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+               __pValue[0] = L'\0';
+       }
+}
+
+_StringBuffer::_StringBuffer(const String& value)
+       : __pValue(null)
+       , __length(0)
+       , __hash(0)
+       , __refCount(1)
+{
+       int length = value.GetLength();
+       __pValue = new (std::nothrow) wchar_t[length + 1];
+       SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+       wcsncpy(__pValue, value.GetPointer(), length);
+       __pValue[length] = L'\0';
+       __length = length;
+}
+
+_StringBuffer::_StringBuffer(const wchar_t* pStr1, const wchar_t* pStr2)
+       : __pValue(null)
+       , __length(0)
+       , __hash(0)
+       , __refCount(1)
+{
+       int length = wcslen(pStr1) + wcslen(pStr2);
+       __pValue = new (std::nothrow) wchar_t[length + 1];
+       SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wcscpy(__pValue, pStr1);
+       wcscat(__pValue, pStr2);
+       __pValue[length] = L'\0';
+       __length = length;
+}
+
+_StringBuffer::_StringBuffer(int capacity)
+       : __pValue(new (std::nothrow) wchar_t[capacity])
+       , __length(0)
+       , __hash(0)
+       , __refCount(1)
+{
+       SysTryReturnVoidResult(NID_BASE, __pValue != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+}
+
+_StringBuffer::~_StringBuffer()
+{
+       delete[] __pValue;
+}
+
+_StringBuffer*
+_StringBuffer::Format(int length, const wchar_t* pFormat, va_list& args)
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(length));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+       vswprintf(pTemp->__pValue, length, pFormat, args);
+
+       int len = wcslen(pTemp->__pValue);
+       if (length > len)
+       {
+               pTemp->__pValue[len] = L'\0';
+               pTemp->__length = len;
+       }
+       else
+       {
+               pTemp->__pValue[length - 1] = L'\0';
+               pTemp->__length = length - 1;
+       }
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Insert(const _StringBuffer* pStr, int indexAt) const
+{
+       int length = __length + pStr->__length;
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wchar_t* pBeg = __pValue;
+       wchar_t* pDes = pTemp->__pValue;
+
+       wmemcpy(pDes, pBeg, indexAt);
+       pDes += indexAt;
+       wmemcpy(pDes, pStr->__pValue, pStr->__length);
+       pDes += pStr->__length;
+       pBeg += indexAt;
+       wmemcpy(pDes, pBeg, wcslen(pBeg));
+       pTemp->__pValue[length] = L'\0';
+       pTemp->__length = length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Remove(int startIndex, int length) const
+{
+       int newLen = __length - length;
+
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(newLen + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wchar_t* pBeg = __pValue;
+       wchar_t* pDes = pTemp->__pValue;
+
+       wmemcpy(pDes, pBeg, startIndex);
+       pBeg += startIndex + length;
+       pDes += startIndex;
+       wmemcpy(pDes, pBeg, __length - startIndex - length);
+       pTemp->__pValue[newLen] = L'\0';
+       pTemp->__length = newLen;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Replace(wchar_t original, wchar_t replace) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       for (int index = 0; index < __length; ++index)
+       {
+               if (__pValue[index] == original)
+               {
+                       pTemp->__pValue[index] = replace;
+               }
+               else
+               {
+                       pTemp->__pValue[index] = __pValue[index];
+               }
+       }
+       pTemp->__pValue[__length] = L'\0';
+       pTemp->__length = __length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Replace(const _StringBuffer* pOriginal, const _StringBuffer* pReplace, int startIndex) const
+{
+       const int orgLen = pOriginal->__length;
+       wchar_t* pOrg = pOriginal->__pValue;
+
+       if ((orgLen == __length) && (wcscmp(__pValue, pOrg) == 0) && (startIndex == 0))
+       {
+               std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(pReplace->__pValue));
+               SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+               return pTemp.release();
+       }
+
+       int repLen = pReplace->__length;
+       wchar_t* pRep = pReplace->__pValue;
+       wchar_t* pBeg = __pValue + startIndex;
+       int count = 0;
+       wchar_t* pMatch = null;
+
+       while (pMatch = wcsstr(pBeg, pOrg))
+       {
+               pBeg = pMatch + orgLen;
+               ++count;
+       }
+
+       if (count == 0)
+       {
+               std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__pValue));
+               SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+               return pTemp.release();
+       }
+
+       int newLen = __length + (repLen - orgLen) * count;
+
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(newLen + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wchar_t* pDes = pTemp->__pValue;
+       wmemcpy(pDes, __pValue, startIndex);
+       pBeg = __pValue + startIndex;
+       pDes += startIndex;
+
+       while (count > 0)
+       {
+               pMatch = wcsstr(pBeg, pOrg);
+               int len_front = static_cast< int >(pMatch - pBeg);
+               if(len_front == 0)
+               {
+                       wmemcpy(pDes, pRep, repLen);
+                       pBeg += orgLen;
+                       pDes += repLen;
+               }
+               else
+               {
+                       wmemcpy(pDes, pBeg, len_front);
+                       pBeg += (len_front + orgLen);
+                       pDes += len_front;
+                       wmemcpy(pDes, pRep, repLen);
+                       pDes += repLen;
+               }
+               --count;
+       }
+       wmemcpy(pDes, pBeg, wcslen(pBeg));
+       pTemp->__pValue[newLen] = L'\0';
+       pTemp->__length = newLen;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Reverse(void) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       for (int i = 0; i < __length; ++i)
+       {
+               pTemp->__pValue[i] = __pValue[__length - 1 - i];
+       }
+
+       pTemp->__pValue[__length] = L'\0';
+       pTemp->__length = __length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::SetCharAt(wchar_t ch, int indexAt) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__pValue));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+       pTemp->__pValue[indexAt] = ch;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::SubString(int startIndex, int length) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wcsncpy(pTemp->__pValue, __pValue + startIndex, length);
+       pTemp->__pValue[length] = L'\0';
+       pTemp->__length = length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::ToUpperCase(void) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wchar_t* pBeg = __pValue;
+       wchar_t* pDes = pTemp->__pValue;
+       for (; *pBeg != 0; ++pBeg, ++pDes)
+       {
+               *pDes = Character::ToUpperCase(*pBeg);
+       }
+       *pDes = L'\0';
+       pTemp->__length = __length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::ToLowerCase(void) const
+{
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__length + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wchar_t* pBeg = __pValue;
+       wchar_t* pDes = pTemp->__pValue;
+       for (; *pBeg != 0; ++pBeg, ++pDes)
+       {
+               *pDes = Character::ToLowerCase(*pBeg);
+       }
+       *pDes = L'\0';
+       pTemp->__length = __length;
+
+       return pTemp.release();
+}
+
+_StringBuffer*
+_StringBuffer::Trim(void) const
+{
+       if (__length == 0)
+       {
+               std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(L""));
+               SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+               return pTemp.release();
+       }
+
+       int lastIndex = __length;
+       int startIndex = 0;
+       const wchar_t* pStr = __pValue;
+
+       while ((startIndex < lastIndex) && (*(pStr + startIndex) <= L' '))
+       {
+               ++startIndex;
+       }
+
+       while ((startIndex < lastIndex) && (*(pStr + lastIndex - 1) <= L' '))
+       {
+               --lastIndex;
+       }
+
+       bool trimRight = lastIndex < __length;
+       bool trimLeft = startIndex > 0;
+
+       if (!trimRight && !trimLeft)
+       {
+               std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(__pValue));
+               SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+               pTemp.release();
+       }
+
+       int newLen = __length - startIndex - (__length - lastIndex);
+       std::unique_ptr< _StringBuffer > pTemp(new (std::nothrow) _StringBuffer(newLen + 1));
+       SysTryReturn(NID_BASE, pTemp != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
+
+       wcsncpy(pTemp->__pValue, __pValue + startIndex, newLen);
+       pTemp->__pValue[newLen] = L'\0';
+       pTemp->__length = newLen;
+
+       return pTemp.release();
+}
+
+int
+_StringBuffer::GetHashCode(const wchar_t* pValue)
+{
+       static const int DEFAULT_HASH_VALUE = 352654597;
+       static const int HASH_MULTIPLIER = 1566083941;
+
+       int num = DEFAULT_HASH_VALUE;
+       int num2 = DEFAULT_HASH_VALUE;
+       for (int i = wcslen(pValue); i >= 2 ; i -= 4)
+       {
+               num = (((num << 5) + num) + (num >> 27)) ^ pValue[0];
+               num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ pValue[1];
+               pValue += 2;
+       }
+       num = (((num << 5) + num) + (num >> 27)) ^ pValue[0];
+       int hash = num + (num2 * HASH_MULTIPLIER);
+
+       return hash;
+}
+}} //Tizen::Base
diff --git a/src/base/inc/FBase_StringBuffer.h b/src/base/inc/FBase_StringBuffer.h
new file mode 100644 (file)
index 0000000..d9b13b5
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file       FBase_StringBuffer.h
+ * @brief      This is the header file for the %_StringBuffer class.
+ *
+ * This file contains the declarations of the %_StringBuffer class.
+ */
+
+#ifndef _FBASE_INTERNAL_STRING_BUFFER_H_
+#define _FBASE_INTERNAL_STRING_BUFFER_H_
+
+namespace Tizen {namespace Base
+{
+
+class String;
+class ImmutalbeString;
+
+class _StringBuffer
+{
+public:
+       _StringBuffer(const wchar_t* pStr);
+       _StringBuffer(const char* pStr);
+       _StringBuffer(const String& value);
+       _StringBuffer(const wchar_t* pStr1, const wchar_t* pStr2);
+       explicit _StringBuffer(int capacity);
+       ~_StringBuffer(void);
+
+       static _StringBuffer* Format(int length, const wchar_t* pFormat, __builtin_va_list& args);
+       _StringBuffer* Insert(const _StringBuffer* pStr, int indexAt) const;
+       _StringBuffer* Remove(int startIndex, int length) const;
+       _StringBuffer* Replace(wchar_t original, wchar_t replace) const;
+       _StringBuffer* Replace(const _StringBuffer* pOriginal, const _StringBuffer* pReplace, int startIndex) const;
+       _StringBuffer* Reverse(void) const;
+       _StringBuffer* SetCharAt(wchar_t ch, int indexAt) const;
+       _StringBuffer* SubString(int startIndex, int length) const;
+       _StringBuffer* ToUpperCase(void) const;
+       _StringBuffer* ToLowerCase(void) const;
+       _StringBuffer* Trim(void) const;
+       int GetHashCode(const wchar_t* pValue);
+
+       wchar_t* __pValue;
+       int __length;
+       int __hash;
+       volatile int __refCount;
+
+};
+}} // Tizen::Base
+#endif // _FBASE_INTERNAL_STRING_BUFFER_H_