//
-// Open Service Platform
// Copyright (c) 2012 Samsung Electronics Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the License);
* @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 "FBase_String.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)
, __pValue(null)
, __pStringImpl(null)
{
- int length = (pValue != null) ? wcslen(pValue) : 0;
+ 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.");
{
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;
, __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.");
- ++(*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;
}
else
{
- (*__pRefCount)--;
+ _String::AtomicDec(__pRefCount);
__pRefCount = null;
}
}
"[%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];
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)--;
+ _String::AtomicDec(__pRefCount);
__pRefCount = pRefCntTemp.release();
}
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)
{
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';
"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));
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));
"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;
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)
{
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);
void
String::Reverse(void)
{
- if (*__pRefCount > 0)
- {
- 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;
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)
}
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)--;
+ _String::AtomicDec(__pRefCount);
__pRefCount = pRefCntTemp.release();
}
}
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;
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)
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';
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);
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);
void
String::ToLowerCase(void)
{
- if (*__pRefCount > 0)
- {
- 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);
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);
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);
--lastIndex;
}
- // trim right
- if (lastIndex < __length)
+ bool trimRight = lastIndex < __length;
+ bool trimLeft = startIndex > 0;
+
+ if (!trimRight && !trimLeft) // nothing to trim
+ {
+ return;
+ }
+
+ result r = AboutToModify(__capacity);
+ SysTryReturnVoidResult(NID_BASE, r == E_SUCCESS, E_OUT_OF_MEMORY, "Memory allocation failed");
+
+ if (trimRight)
{
Remove(lastIndex, __length - lastIndex);
}
- // trim left
- if (startIndex > 0)
+ if (trimLeft)
{
Remove(0, startIndex);
}
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));
}
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)--;
+ _String::AtomicDec(__pRefCount);
__pRefCount = pRefCntTemp.release();
}
}
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.");
}
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';
- --(*__pRefCount);
- __pRefCount = pRefCntTemp.release();
return E_SUCCESS;
}