From 2e11f1737254d219e18a8894e8a5f369278c2ba5 Mon Sep 17 00:00:00 2001 From: "dahyeong.kim" Date: Sun, 9 Jun 2013 17:13:05 +0900 Subject: [PATCH] [2.2] Add Unshareable marker in String Change-Id: I373957875fbaefd940f0f6f1f789a0c74da5e56a Signed-off-by: dahyeong.kim --- inc/FBaseString.h | 8 ++- src/base/FBaseString.cpp | 172 ++++++++++++++++++++++------------------------- 2 files changed, 86 insertions(+), 94 deletions(-) diff --git a/inc/FBaseString.h b/inc/FBaseString.h index f9b6fe0..185a3e3 100644 --- a/inc/FBaseString.h +++ b/inc/FBaseString.h @@ -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; diff --git a/src/base/FBaseString.cpp b/src/base/FBaseString.cpp index 6f62102..56f37c5 100644 --- a/src/base/FBaseString.cpp +++ b/src/base/FBaseString.cpp @@ -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; } -- 2.7.4