From b5f5d6f4dfecc42e8d35046ffd9ebb99d02c698f Mon Sep 17 00:00:00 2001 From: "dahyeong.kim" Date: Tue, 28 May 2013 19:53:21 +0900 Subject: [PATCH] Change the way to Convert UTF8 to wchar_t, and vice versa Change-Id: I4704dc32a28ae50d0a56753b015e050fe5242785 Signed-off-by: dahyeong.kim --- src/base/FBaseString.cpp | 46 ++++++++--------- src/base/FBase_StringConverter.cpp | 21 ++------ src/base/inc/FBaseUtil_IcuConverter.h | 28 +++++----- src/base/utility/FBaseUtil_IcuConverter.cpp | 80 +++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 55 deletions(-) diff --git a/src/base/FBaseString.cpp b/src/base/FBaseString.cpp index e5ff018..6f62102 100644 --- a/src/base/FBaseString.cpp +++ b/src/base/FBaseString.cpp @@ -38,6 +38,7 @@ #include #include #include "FBase_String.h" +#include "FBaseUtil_IcuConverter.h" namespace Tizen { namespace Base @@ -98,7 +99,7 @@ String::String(const wchar_t* pValue) , __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."); @@ -112,7 +113,7 @@ String::String(const wchar_t* 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,25 +128,24 @@ 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'; } } @@ -375,7 +375,7 @@ String::Append(const wchar_t* p) { wchar_t* pValue = __pValue; SysTryReturnResult(NID_BASE, AllocateCapacity(length) != false, E_OUT_OF_MEMORY, "Memory allocation failed."); - std::unique_ptr 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); @@ -454,7 +454,7 @@ String::EnsureCapacity(int minCapacity) bool String::Equals(const Object& obj) const { - const String* pOther = dynamic_cast (&obj); + const String* pOther = dynamic_cast< const String* >(&obj); if (pOther == null) { @@ -518,7 +518,7 @@ String::Format(int length, const wchar_t* pFormat, ...) Clear(); - std::unique_ptr 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'; @@ -1020,7 +1020,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 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,7 +1043,7 @@ String::SetCapacity(int capacity) } else { - std::unique_ptr 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"); _String::AtomicDec(__pRefCount); __pRefCount = pRefCntTemp.release(); @@ -1131,7 +1131,7 @@ String::SubString(int startIndex, int length, String& out) const if (length > 0) { - std::unique_ptr 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'; @@ -1512,7 +1512,7 @@ String::ExpandCapacity(int minCapacity) } else { - std::unique_ptr 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)); _String::AtomicDec(__pRefCount); @@ -1529,7 +1529,7 @@ String::ExpandCapacity(int minCapacity) result String::InitializeToDefault(int capacity) { - std::unique_ptr 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."); @@ -1541,7 +1541,7 @@ result String::CopyOnWrite(int capacity) { wchar_t* pValue = __pValue; - std::unique_ptr 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."); diff --git a/src/base/FBase_StringConverter.cpp b/src/base/FBase_StringConverter.cpp index a586c7c..fc121c1 100644 --- a/src/base/FBase_StringConverter.cpp +++ b/src/base/FBase_StringConverter.cpp @@ -19,13 +19,11 @@ * @brief This is the implementation for _StringConverter class. */ -#include #include #include -#include "FBase_StringConverter.h" #include - - +#include "FBase_StringConverter.h" +#include "FBaseUtil_IcuConverter.h" namespace Tizen { namespace Base { @@ -39,20 +37,7 @@ _StringConverter::CopyToCharArrayN(const String& str) char* _StringConverter::CopyToCharArrayN(const wchar_t* pValue) { - char* pRet = null; - - int len = wcstombs(0, pValue, 0); - SysTryReturn(NID_BASE, len != -1, null, E_INVALID_ARG, "[%s] Invalid argument is used. Invalid string.", - GetErrorMessage(E_INVALID_ARG)); - - pRet = new (std::nothrow) char[len + 1]; - SysTryReturn(NID_BASE, pRet != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", - GetErrorMessage(E_OUT_OF_MEMORY)); - - len = wcstombs(pRet, pValue, len); - pRet[len] = 0; - - return pRet; + return Tizen::Base::Utility::WcharToUtf8N(pValue); } }} //Tizen::Base diff --git a/src/base/inc/FBaseUtil_IcuConverter.h b/src/base/inc/FBaseUtil_IcuConverter.h index 230a61c..9fcce25 100644 --- a/src/base/inc/FBaseUtil_IcuConverter.h +++ b/src/base/inc/FBaseUtil_IcuConverter.h @@ -33,22 +33,22 @@ namespace Tizen { namespace Base { namespace Utility class _ICUConverter { - public: - _ICUConverter(); - ~_ICUConverter(); - - private: - result GetResultFromIcuErrorCode(UErrorCode& err); - public: - bool OpenConverter(const Tizen::Base::String& encodingScheme); - wchar_t* ConvertToUcharN(const char* src, int srcLength); - char* ConvertFromUcharN(const wchar_t* pSrc, int srcLength, int& retLength); - void CloseConverter(void); - - private: - UConverter* __pConverter; +public: + _ICUConverter(); + ~_ICUConverter(); + bool OpenConverter(const Tizen::Base::String& encodingScheme); + wchar_t* ConvertToUcharN(const char* src, int srcLength); + char* ConvertFromUcharN(const wchar_t* pSrc, int srcLength, int& retLength); + void CloseConverter(void); + +private: + result GetResultFromIcuErrorCode(UErrorCode& err); + UConverter* __pConverter; }; // _ICUConverter +char* WcharToUtf8N(const wchar_t* pValue); +wchar_t* Utf8ToWcharN(const char* pValue); + }}} // Tizen::Base::Utility #endif // _FBASE_UTIL_ICU_CONVERTER_H_ diff --git a/src/base/utility/FBaseUtil_IcuConverter.cpp b/src/base/utility/FBaseUtil_IcuConverter.cpp index 0ed4f72..e808ffb 100644 --- a/src/base/utility/FBaseUtil_IcuConverter.cpp +++ b/src/base/utility/FBaseUtil_IcuConverter.cpp @@ -200,4 +200,84 @@ _ICUConverter::GetResultFromIcuErrorCode(UErrorCode& err) } return E_SUCCESS; } + +struct UConverterDeleter +{ + void operator ()(UConverter* pConverter) + { + if (pConverter) + { + ucnv_close(pConverter); + } + } +}; + +char* +WcharToUtf8N(const wchar_t* pValue) +{ + SysTryReturn(NID_BASE_UTIL, pValue != null, null, E_INVALID_ARG, "[%s] Invalid argument is used. The pValue is null.", GetErrorMessage(E_INVALID_ARG)); + + int len = wcslen(pValue); + if (len == 0) + { + char* pRet = new (std::nothrow) char[1]; + SysTryReturn(NID_BASE_UTIL, pRet != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + pRet[0] = '\0'; + return pRet; + } + + UErrorCode err = U_ZERO_ERROR; + std::unique_ptr< UConverter, UConverterDeleter > pConverter(ucnv_open("UTF-8", &err)); + SysTryReturn(NID_BASE_UTIL, pConverter, null, E_OUT_OF_MEMORY, "[%s] ucnv_open() failed. pConverter is null.", GetErrorMessage(E_OUT_OF_MEMORY)); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] ucnv_open() failed. The err must be U_ZERO_ERROR.", GetErrorMessage(E_INVALID_ARG)); + + ucnv_setFromUCallBack(pConverter.get(), UCNV_FROM_U_CALLBACK_STOP, null, null, null, &err); + + int icuStrCapacity = len * 2 + 1; + std::unique_ptr< UChar[] > pIcuStr(new (std::nothrow) UChar[icuStrCapacity]); + SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + int outLen = 0; + UChar* pResultStr = u_strFromWCS(pIcuStr.get(), icuStrCapacity, &outLen, pValue, len, &err); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] u_strFromWCS() failed. pValue is %ls.", GetErrorMessage(E_INVALID_ARG), pValue); + + int destCapacity = outLen * 2 + 1; + std::unique_ptr< char[] > pDst(new (std::nothrow) char[destCapacity]); + SysTryReturn(NID_BASE_UTIL, pDst != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + ucnv_fromUChars(pConverter.get(), pDst.get(), destCapacity, pResultStr, outLen, &err); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] ucnv_fromUChars() failed. pValue is %ls.", GetErrorMessage(E_INVALID_ARG), pValue); + + return pDst.release(); +} + +wchar_t* +Utf8ToWcharN(const char* pValue) +{ + SysTryReturn(NID_BASE_UTIL, pValue != null, null, E_INVALID_ARG, "[%s] Invalid argument is used. The pValue is null.", GetErrorMessage(E_INVALID_ARG)); + + UErrorCode err = U_ZERO_ERROR; + std::unique_ptr< UConverter, UConverterDeleter > pConverter(ucnv_open("UTF-8", &err)); + SysTryReturn(NID_BASE_UTIL, pConverter, null, E_OUT_OF_MEMORY, "[%s] ucnv_open() failed. pConverter is null.", GetErrorMessage(E_OUT_OF_MEMORY)); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] ucnv_open() failed. The err must be U_ZERO_ERROR.", GetErrorMessage(E_INVALID_ARG)); + + ucnv_setFromUCallBack(pConverter.get(), UCNV_FROM_U_CALLBACK_STOP, null, null, null, &err); + + int len = strlen(pValue); + int icuStrCapacity = len + 1; + std::unique_ptr< UChar[] > pIcuStr(new (std::nothrow) UChar[icuStrCapacity]); + SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + signed int retLength = ucnv_toUChars(pConverter.get(), pIcuStr.get(), icuStrCapacity, pValue, len, &err); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] ucnv_toUChars() failed. pValue is %s.", GetErrorMessage(E_INVALID_ARG), pValue); + + int destCapacity = retLength + String::DEFAULT_CAPACITY + 1; + std::unique_ptr< wchar_t[] > pDst(new (std::nothrow) wchar_t[destCapacity]); + SysTryReturn(NID_BASE_UTIL, pDst != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + u_strToWCS(pDst.get(), destCapacity, &retLength, pIcuStr.get(), retLength, &err); + SysTryReturn(NID_BASE_UTIL, U_SUCCESS(err), null, E_INVALID_ARG, "[%s] u_strToWCS() failed. pValue is %s.", GetErrorMessage(E_INVALID_ARG), pValue); + + return pDst.release(); +} } } } // Tizen::Base::Utility -- 2.7.4