[2.2] Add Unshareable marker in String
authordahyeong.kim <dahyeong.kim@samsung.com>
Sun, 9 Jun 2013 08:13:05 +0000 (17:13 +0900)
committerdahyeong.kim <dahyeong.kim@samsung.com>
Thu, 13 Jun 2013 13:27:04 +0000 (22:27 +0900)
Change-Id: I373957875fbaefd940f0f6f1f789a0c74da5e56a
Signed-off-by: dahyeong.kim <dahyeong.kim@samsung.com>
inc/FBaseString.h
src/base/FBaseString.cpp

index f9b6fe0..185a3e3 100644 (file)
@@ -1081,11 +1081,12 @@ private:
        result InitializeToDefault(int capacity);
 
        //
-       // Copies __pValue and subtract and initialize __pRefCount
+       // When the reference count is bigger than 1 and it is not UNSHAREABLE, copies__pValue and subtracts and initializes __pRefCount.
+       // If the isUnshareable is true, this method sets the reference count to UNSHAREABLE.
        //
-       // @since 2.0
+       // @since 2.2
        //
-       result CopyOnWrite(int capacity);
+       result AboutToModify(int capacity, bool isUnshareable = false);
 
        //
        // Swaps member-wisely
@@ -1101,6 +1102,7 @@ private:
        mutable wchar_t* __pValue;
 
        static const float GROWTH_FACTOR;
+       static const int UNSHAREABLE;
 
        class _StringImpl * __pStringImpl;
        friend class _StringImpl;
index 6f62102..56f37c5 100644 (file)
@@ -45,6 +45,7 @@ namespace Tizen { namespace Base
 {
 
 const float String::GROWTH_FACTOR = 1.5;
+const int String::UNSHAREABLE = Integer::VALUE_MAX;
 
 String::String(void)
        : __capacity(0)
@@ -150,22 +151,43 @@ String::String(const char* pValue)
 }
 
 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.");
 
-       _String::AtomicInc(value.__pRefCount);
-       __pRefCount = value.__pRefCount;
+       if (*(value.__pRefCount) != UNSHAREABLE)
+       {
+               _String::AtomicInc(value.__pRefCount);
+               __pRefCount = value.__pRefCount;
+               __pValue = value.__pValue;
+               __capacity = value.__capacity;
+               __length = value.__length;
+               __hash = value.__hash;
+       }
+       else
+       {
+               int length = wcslen(value.__pValue);
+
+               SysTryReturnVoidResult(NID_BASE, length >= 0, E_OUT_OF_RANGE,
+                       "String has wrong length. The length has to be more bigger than 0.");
+
+               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;
@@ -195,11 +217,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];
@@ -371,7 +390,7 @@ 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.");
@@ -648,15 +667,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 +763,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 +873,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 +887,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)
        {
@@ -958,14 +965,11 @@ String::Replace(const String& org, const String& rep, int startIndex)
 
        if (count > 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);
+               r = EnsureCapacity(newLength);
                SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
 
                wchar_t* pBeg = (__pValue + startIndex);
@@ -995,11 +999,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;
@@ -1063,11 +1064,8 @@ String::SetCharAt(wchar_t ch, int indexAt)
                "[%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 +1079,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)
@@ -1280,11 +1275,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 +1296,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 +1317,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 +1338,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);
 
@@ -1404,11 +1387,8 @@ String::Trim(void)
                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)
        {
@@ -1538,17 +1518,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';
+
+               _String::AtomicDec(__pRefCount);
+               __pRefCount = pRefCntTemp.release();
+       }
+
+       if (isUnshareable)
+       {
+               *__pRefCount = UNSHAREABLE;
+       }
 
-       wcsncpy(__pValue, pValue, __length);
-       __pValue[__length] = '\0';
-       _String::AtomicDec(__pRefCount);
-       __pRefCount = pRefCntTemp.release();
        return E_SUCCESS;
 }