Merge "[Native][25/11/2013][Add]Adding BigInteger class" into tizen
[platform/framework/native/appfw.git] / src / base / FBaseString.cpp
index ec9aae1..abb38f1 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -19,7 +18,6 @@
 * @file                FBaseString.cpp
 * @brief       This is the implementation for String class.
 */
-
 #include <wchar.h>
 #include <math.h>
 #include <stdlib.h>
 #include <FBaseResult.h>
 #include <FBaseSysLog.h>
 #include <unique_ptr.h>
-
+#include "FBaseUtil_AtomicOperations.h"
+#include "FBaseUtil_IcuConverter.h"
 
 namespace Tizen { namespace Base
 {
 
 const float String::GROWTH_FACTOR = 1.5;
+const int String::UNSHAREABLE = Integer::VALUE_MAX;
 
 String::String(void)
        : __capacity(0)
@@ -98,11 +98,6 @@ String::String(const wchar_t* pValue)
        , __pValue(null)
        , __pStringImpl(null)
 {
-       int length  = (pValue != null) ? wcslen(pValue) : 0;
-
-       SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
-               "String has wrong length. The length has to be more bigger than 0.");
-
        if (pValue == null)
        {
                result r = InitializeToDefault(DEFAULT_CAPACITY);
@@ -110,9 +105,10 @@ String::String(const wchar_t* pValue)
        }
        else
        {
+               int length = wcslen(pValue);
                result r = InitializeToDefault(length + DEFAULT_CAPACITY);
                SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-               
+
                wcsncpy(__pValue, pValue, length);
                __pValue[length] = '\0';
                __length = length;
@@ -127,52 +123,67 @@ String::String(const char* pValue)
        , __pValue(null)
        , __pStringImpl(null)
 {
-       int len = (pValue != null) ? mbstowcs(null, pValue, 0) : 0;
-
-       if (pValue == null)
+       if (pValue == null || strlen(pValue) == 0)
        {
                result r = InitializeToDefault(DEFAULT_CAPACITY);
                SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
        }
        else
        {
-               result r = InitializeToDefault(len + DEFAULT_CAPACITY);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
+               std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
+               SysTryReturnVoidResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
-               len = mbstowcs(__pValue, pValue, len);
-               if (len == -1)
-               {
-                       SysLog(NID_BASE, "Invalid encoding range[%s].", pValue);
-               }
-               __pValue[len] = '\0';
-               __length = len;
+               std::unique_ptr< wchar_t[] > pStr(Tizen::Base::Utility::Utf8ToWcharN(pValue));
+               SysTryReturnVoidResult(NID_BASE, pStr != null, GetLastResult(), "[%ls] Propagating.", GetErrorMessage(GetLastResult()));
+
+               __pRefCount = pRefCntTemp.release();
+               __pValue = pStr.release();
+               __length = wcslen(__pValue);
+               __capacity = __length + DEFAULT_CAPACITY;
+               __pValue[__length] = '\0';
        }
 }
 
 String::String(const String& value)
-       : __capacity(value.__capacity)
-       , __length(value.__length)
-       , __hash(value.__hash)
+       : __capacity(0)
+       , __length(0)
+       , __hash(0)
        , __pRefCount(null)
-       , __pValue(value.__pValue)
+       , __pValue(null)
        , __pStringImpl(null)
 {
-       SysTryReturnVoidResult(NID_BASE, value.__length >= 0, E_OUT_OF_RANGE, "The length has to be greater than 0.");
+       if (*(value.__pRefCount) != UNSHAREABLE)
+       {
+               Utility::_AtomicOperations::AtomicInc(value.__pRefCount);
+               __pRefCount = value.__pRefCount;
+               __pValue = value.__pValue;
+               __capacity = value.__capacity;
+               __length = value.__length;
+               __hash = value.__hash;
+       }
+       else
+       {
+               int length = wcslen(value.__pValue);
 
-       ++(*value.__pRefCount);
-       __pRefCount = value.__pRefCount;
+               result r = InitializeToDefault(length + DEFAULT_CAPACITY);
+               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
+
+               wcsncpy(__pValue, value.__pValue, length);
+               __pValue[length] = '\0';
+               __length = length;
+       }
 }
 
 String::~String(void)
 {
-       if (*__pRefCount == 1)
+       if (*__pRefCount == 1 || *__pRefCount == UNSHAREABLE)
        {
                delete[] __pValue;
                delete __pRefCount;
        }
        else
        {
-               (*__pRefCount)--;
+               Utility::_AtomicOperations::AtomicDec(__pRefCount);
                __pRefCount = null;
        }
 }
@@ -195,11 +206,8 @@ String::operator [](int index)
                "[%s] The index(%d) MUST be greater than or equal to 0, and less than the length of this string(%d).",
                GetErrorMessage(E_OUT_OF_RANGE), index, __length);
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity, true);
+       SysTryReturn(NID_BASE, r == E_SUCCESS, ch, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        __hash = 0;
        return __pValue[index];
@@ -276,7 +284,6 @@ String::operator ==(const String& rhs) const
        {
                return false;
        }
-
        return(CompareTo(rhs) == 0);
 }
 
@@ -371,15 +378,15 @@ String::Append(const wchar_t* p)
 
        int length = (wcslen(p) + __length);
 
-       if (*__pRefCount > 1)
+       if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
        {
                wchar_t* pValue = __pValue;
                SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
-               std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
+               std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
                SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
 
                wcsncpy(__pValue, pValue, __length);
-               (*__pRefCount)--;
+               Utility::_AtomicOperations::AtomicDec(__pRefCount);
                __pRefCount = pRefCntTemp.release();
        }
 
@@ -454,7 +461,7 @@ String::EnsureCapacity(int minCapacity)
 bool
 String::Equals(const Object& obj) const
 {
-       const String* pOther = dynamic_cast <const String*>(&obj);
+       const String* pOther = dynamic_cast< const String* >(&obj);
 
        if (pOther == null)
        {
@@ -518,7 +525,7 @@ String::Format(int length, const wchar_t* pFormat, ...)
 
        Clear();
 
-       std::unique_ptr<wchar_t []> pStr(new (std::nothrow) wchar_t[length + 1]);
+       std::unique_ptr< wchar_t[] > pStr(new (std::nothrow) wchar_t[length + 1]);
        SysTryReturnResult(NID_BASE, pStr != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
        pStr[length] = '\0';
 
@@ -550,23 +557,29 @@ String::Format(int length, const wchar_t* pFormat, ...)
 int
 String::GetHashCode(void) const
 {
-       int hash = 0;
+       if (__length == 0)
+       {
+               return 0;
+       }
 
        if (__hash == 0)
        {
+               const int DEFAULT_HASH_VALUE = 352654597;
+               const int HASH_MULTIPLIER = 1566083941;
+
+               int num = DEFAULT_HASH_VALUE;
+               int num2 = DEFAULT_HASH_VALUE;
                wchar_t* pStr = __pValue;
-               for (int i = 0; i < __length; ++i)
+               for (int i = __length; i >= 2 ; i -= 4)
                {
-                       hash = (hash << 5) - hash + (int) *pStr++;
+                   num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
+                   num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ pStr[1];
+                   pStr += 2;
                }
-               __hash = hash;
-       }
-       else
-       {
-               hash = __hash;
+               num = (((num << 5) + num) + (num >> 27)) ^ pStr[0];
+               __hash = num + (num2 * HASH_MULTIPLIER);
        }
-
-       return hash;
+       return __hash;
 }
 
 result
@@ -608,9 +621,9 @@ String::IndexOf(wchar_t ch, int startIndex, int& indexOf) const
 result
 String::IndexOf(const String& str, int startIndex, int& indexOf) const
 {
-       SysTryReturnResult(NID_BASE, (startIndex < __length), E_OUT_OF_RANGE,
+       SysTryReturnResult(NID_BASE, startIndex < __length, E_OUT_OF_RANGE,
                "The startIndex(%d) MUST be less than the length of this string(%d).", startIndex, __length);
-       SysTryReturnResult(NID_BASE, (startIndex >= 0), E_OUT_OF_RANGE,
+       SysTryReturnResult(NID_BASE, startIndex >= 0, E_OUT_OF_RANGE,
                "The startIndex(%d) MUST be greater than or equal to 0.", startIndex);
 
        if (str.IsEmpty())
@@ -648,15 +661,12 @@ String::Insert(wchar_t ch, int indexAt)
                "The indexAt(%d) MUST be greater than or equal to 0, and less than or equal to the length of this string(%d).",
                indexAt, __length);
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        int length = (__length + 1);
 
-       result r = EnsureCapacity(length);
+       r = EnsureCapacity(length);
        SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
 
        wmemmove((__pValue + indexAt + 1), (__pValue + indexAt), ((__length + 1) - indexAt));
@@ -747,13 +757,10 @@ String::Insert(const wchar_t* p, int indexAt)
                return E_SUCCESS;
        }
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
-       result r = EnsureCapacity(__length + length);
+       r = EnsureCapacity(__length + length);
        SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
 
        wmemmove((__pValue + indexAt + length), (__pValue + indexAt), ((__length + 1) - indexAt));
@@ -860,11 +867,8 @@ String::Remove(int startIndex, int count)
                "The startIndex(%d) + count(%d) MUST be less than or equal to the length of this string(%d).",
                startIndex, count, __length);
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        wmemmove(__pValue + startIndex, __pValue + moveIndex, (__length - moveIndex) + 1);
        __length -= count;
@@ -877,11 +881,8 @@ String::Remove(int startIndex, int count)
 void
 String::Replace(wchar_t original, wchar_t replace)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        for (int length = __length; length >= 0; --length)
        {
@@ -897,7 +898,7 @@ result
 String::Replace(const String& org, const String& rep)
 {
        result r = Replace(org, rep, 0);
-       SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "Propagating.");
 
        return r;
 }
@@ -905,8 +906,7 @@ String::Replace(const String& org, const String& rep)
 result
 String::Replace(const String& org, const String& rep, int startIndex)
 {
-       const int orgLen = org.__length;
-       SysTryReturnResult(NID_BASE, orgLen > 0, E_INVALID_ARG, "The length of org(%d) MUST be greater than 0.", orgLen);
+       SysTryReturnResult(NID_BASE, org.__length > 0, E_INVALID_ARG, "The length of org MUST be greater than 0.");
 
        SysTryReturnResult(NID_BASE,
                startIndex >= 0 && startIndex < __length, E_OUT_OF_RANGE,
@@ -918,71 +918,55 @@ String::Replace(const String& org, const String& rep, int startIndex)
                return E_SUCCESS;
        }
 
+       int orgLen = org.__length;
+       int repLen = rep.__length;
        if ((orgLen == __length) && (*this == org))
        {
-               const int newLength = rep.__length;
-               if (EnsureCapacity(newLength) != E_SUCCESS)
-               {
-                       SetCapacity(newLength);
-               }
+               result r = AboutToModify(__capacity);
+               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
-               wcsncpy(__pValue, rep.__pValue, rep.__length);
+               r = EnsureCapacity(repLen);
+               SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "Propagating.");
 
-               __length = rep.__length;
+               wcsncpy(__pValue, rep.__pValue, repLen);
+
+               __length = repLen;
                __pValue[__length] = '\0';
                __hash = 0;
 
                return E_SUCCESS;
        }
 
-       int repLen = rep.__length;
+       int matchedCount = 0;
 
-       wchar_t* pOrg = org.__pValue;
-       wchar_t* pRep = rep.__pValue;
+       wchar_t* pBeg = __pValue + startIndex;
+       wchar_t* pMatch = null;
 
-       int count = 0;
+       while ((pMatch = wcsstr(pBeg, org.__pValue)) != null)
        {
-               wchar_t* pBeg = (__pValue + startIndex);
-               wchar_t* pEnd = pBeg + __length;
-               while (pBeg < pEnd)
-               {
-                       wchar_t* pTarget = null;
-                       while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
-                       {
-                               ++count;
-                               pBeg = pTarget + orgLen;
-                       }
-                       pBeg += wcslen(pBeg) + 1;
-               }
+               ++matchedCount;
+               pBeg = pMatch + orgLen;
        }
 
-       if (count > 0)
+       if (matchedCount > 0)
        {
-               if (*__pRefCount > 1)
-               {
-                       result r = CopyOnWrite(__capacity);
-                       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-               }
+               result r = AboutToModify(__capacity);
+               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
-               const int newLength = (count * (repLen - orgLen)) + __length;
-               result r = EnsureCapacity(newLength);
-               SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
+               const int newLength = (matchedCount * (repLen - orgLen)) + __length;
+               r = EnsureCapacity(newLength);
+               SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "Propagating.");
 
-               wchar_t* pBeg = (__pValue + startIndex);
-               wchar_t* pEnd = pBeg + __length;
-               while (pBeg < pEnd)
+               pBeg = __pValue + startIndex;
+               while ((pMatch = wcsstr(pBeg, org.__pValue)) != null)
                {
-                       wchar_t* pTarget = null;
-                       while ((pTarget = (wchar_t*) wcsstr(pBeg, pOrg)) != null)
-                       {
-                               int balance = __length - int(pTarget - (__pValue + startIndex) + orgLen);
-                               wmemmove(pTarget + repLen, pTarget + orgLen, balance);
-                               wmemcpy(pTarget, pRep, repLen);
-                               pBeg = pTarget + repLen;
-                               pTarget[repLen + balance] = 0;
-                               __length += (repLen - orgLen);
-                       }
-                       pBeg += (wcslen(pBeg) + 1);
+                       int count = __length - (pMatch - __pValue) - orgLen;
+                       wmemmove(pMatch + repLen, pMatch + orgLen, count);
+                       wmemcpy(pMatch, rep.__pValue, repLen);
+
+                       pBeg = pMatch + repLen;
+                       pMatch[repLen + count] = '\0';
+                       __length += (repLen - orgLen);
                }
 
                __length = newLength;
@@ -995,11 +979,8 @@ String::Replace(const String& org, const String& rep, int startIndex)
 void
 String::Reverse(void)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        wchar_t* pBeg = __pValue;
        wchar_t* pEnd = __pValue + __length - 1;
@@ -1020,7 +1001,7 @@ String::SetCapacity(int capacity)
        SysTryReturnResult(NID_BASE, capacity >= 0, E_INVALID_ARG,
                "The capacity(%d) MUST be greater than or equal to 0.", capacity);
 
-       std::unique_ptr<wchar_t []> pValue(new (std::nothrow) wchar_t[capacity + 1]);
+       std::unique_ptr< wchar_t[] > pValue(new (std::nothrow) wchar_t[capacity + 1]);
        SysTryReturnResult(NID_BASE, pValue != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        if (__pValue != null)
@@ -1043,9 +1024,9 @@ String::SetCapacity(int capacity)
                }
                else
                {
-                       std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
+                       std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
                        SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed");
-                       (*__pRefCount)--;
+                       Utility::_AtomicOperations::AtomicDec(__pRefCount);
                        __pRefCount = pRefCntTemp.release();
                }
        }
@@ -1059,15 +1040,12 @@ String::SetCapacity(int capacity)
 result
 String::SetCharAt(wchar_t ch, int indexAt)
 {
-       SysTryReturn(NID_BASE,indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
+       SysTryReturn(NID_BASE, indexAt >= 0 && indexAt < __length, E_OUT_OF_RANGE, 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, __length);
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        __pValue[indexAt] = ch;
        __hash = 0;
@@ -1081,15 +1059,12 @@ String::SetLength(int newLength)
        SysTryReturnResult(NID_BASE, newLength >= 0, E_INVALID_ARG, "The newLength(%d) MUST be greater than or equal to 0.",
                newLength);
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        static const wchar_t SPACE = 0x0020;
 
-       result r = EnsureCapacity(newLength);
+       r = EnsureCapacity(newLength);
        SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
 
        if (newLength > __length)
@@ -1131,7 +1106,7 @@ String::SubString(int startIndex, int length, String& out) const
 
        if (length > 0)
        {
-               std::unique_ptr<wchar_t []> pTemp(new (std::nothrow) wchar_t[length + 1]);
+               std::unique_ptr< wchar_t[] > pTemp(new (std::nothrow) wchar_t[length + 1]);
                SysTryReturnResult(NID_BASE, pTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
                wcsncpy(pTemp.get(), __pValue + startIndex, length);
                pTemp[length] = '\0';
@@ -1152,7 +1127,7 @@ String::StartsWith(const String& str, int startIndex) const
        SysTryReturn(NID_BASE, startIndex >= 0 && startIndex < __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, __length);
-       SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG, 
+       SysTryReturn(NID_BASE, str.__length > 0, false, E_INVALID_ARG,
                "[%s] Invalid argument is used. The length of str(%d) MUST be greater than 0.",
                GetErrorMessage(E_INVALID_ARG), str.__length);
 
@@ -1280,11 +1255,8 @@ String::ToUpperCase(String& out) const
 void
 String::ToLower(void)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        String str(__length + 1);
 
@@ -1304,11 +1276,8 @@ String::ToLower(void)
 void
 String::ToLowerCase(void)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        String str(__length + 1);
 
@@ -1328,11 +1297,8 @@ String::ToLowerCase(void)
 void
 String::ToUpper(void)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        String str(__length + 1);
 
@@ -1352,11 +1318,8 @@ String::ToUpper(void)
 void
 String::ToUpperCase(void)
 {
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
        String str(__length + 1);
 
@@ -1399,16 +1362,13 @@ String::Trim(void)
        bool trimRight = lastIndex < __length;
        bool trimLeft = startIndex > 0;
 
-       if (!trimRight && !trimLeft)    // nothing to trim
+       if (!trimRight && !trimLeft)    // nothing to trim
        {
                return;
        }
 
-       if (*__pRefCount > 1)
-       {
-               result r = CopyOnWrite(__capacity);
-               SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
-       }
+       result r = AboutToModify(__capacity);
+       SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
 
        if (trimRight)
        {
@@ -1456,18 +1416,7 @@ String::Contains(const String& str) const
                return true;
        }
 
-       wchar_t* pStart = __pValue;
-       wchar_t* pEnd = pStart + __length;
-       while (pStart < pEnd)
-       {
-               while (wcsstr(pStart, str.__pValue) != null)
-               {
-                       return true;
-               }
-               ++pStart;
-       }
-
-       return false;
+       return (wcsstr(__pValue, str.__pValue) != null);
 }
 
 bool
@@ -1497,7 +1446,7 @@ String::ExpandCapacity(int minCapacity)
                capacity = minCapacity;
        }
 
-       std::unique_ptr<wchar_t []> pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
+       std::unique_ptr< wchar_t[] > pNewValue(new (std::nothrow) wchar_t[capacity + 1]); // + 1 for null character
        SysTryReturn(NID_BASE, pNewValue != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
                GetErrorMessage(E_OUT_OF_MEMORY));
 
@@ -1512,10 +1461,10 @@ String::ExpandCapacity(int minCapacity)
                }
                else
                {
-                       std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
+                       std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
                        SysTryReturn(NID_BASE, pRefCntTemp != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed",
                                GetErrorMessage(E_OUT_OF_MEMORY));
-                       (*__pRefCount)--;
+                       Utility::_AtomicOperations::AtomicDec(__pRefCount);
                        __pRefCount = pRefCntTemp.release();
                }
        }
@@ -1529,7 +1478,7 @@ String::ExpandCapacity(int minCapacity)
 result
 String::InitializeToDefault(int capacity)
 {
-       std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
+       std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
        SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
        SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
 
@@ -1538,17 +1487,27 @@ String::InitializeToDefault(int capacity)
 }
 
 result
-String::CopyOnWrite(int capacity)
+String::AboutToModify(int capacity, bool isUnshareable)
 {
-       wchar_t* pValue = __pValue;
-       std::unique_ptr<int> pRefCntTemp(new (std::nothrow) int(1));
-       SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
-       SysTryReturnResult(NID_BASE, AllocateCapacity(capacity) != false, E_OUT_OF_MEMORY, "Memory allocation failed.");
+       if (*__pRefCount > 1 && *__pRefCount != UNSHAREABLE)
+       {
+               wchar_t* pValue = __pValue;
+               std::unique_ptr< int > pRefCntTemp(new (std::nothrow) int(1));
+               SysTryReturnResult(NID_BASE, pRefCntTemp != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
+               SysTryReturnResult(NID_BASE, AllocateCapacity(capacity), E_OUT_OF_MEMORY, "Memory allocation failed.");
+
+               wcsncpy(__pValue, pValue, __length);
+               __pValue[__length] = '\0';
+
+               Utility::_AtomicOperations::AtomicDec(__pRefCount);
+               __pRefCount = pRefCntTemp.release();
+       }
+
+       if (isUnshareable)
+       {
+               *__pRefCount = UNSHAREABLE;
+       }
 
-       wcsncpy(__pValue, pValue, __length);
-       __pValue[__length] = '\0';
-       --(*__pRefCount);
-       __pRefCount = pRefCntTemp.release();
        return E_SUCCESS;
 }