Change the way to Convert UTF8 to wchar_t, and vice versa
authordahyeong.kim <dahyeong.kim@samsung.com>
Tue, 28 May 2013 10:53:21 +0000 (19:53 +0900)
committerdahyeong.kim <dahyeong.kim@samsung.com>
Thu, 30 May 2013 12:06:47 +0000 (21:06 +0900)
Change-Id: I4704dc32a28ae50d0a56753b015e050fe5242785
Signed-off-by: dahyeong.kim <dahyeong.kim@samsung.com>
src/base/FBaseString.cpp
src/base/FBase_StringConverter.cpp
src/base/inc/FBaseUtil_IcuConverter.h
src/base/utility/FBaseUtil_IcuConverter.cpp

index e5ff018..6f62102 100644 (file)
@@ -38,6 +38,7 @@
 #include <FBaseSysLog.h>
 #include <unique_ptr.h>
 #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<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);
@@ -454,7 +454,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 +518,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';
 
@@ -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<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,7 +1043,7 @@ 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");
                        _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<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';
@@ -1512,7 +1512,7 @@ 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));
                        _String::AtomicDec(__pRefCount);
@@ -1529,7 +1529,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.");
 
@@ -1541,7 +1541,7 @@ result
 String::CopyOnWrite(int capacity)
 {
        wchar_t* pValue = __pValue;
-       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.");
 
index a586c7c..fc121c1 100644 (file)
 * @brief               This is the implementation for _StringConverter class.
 */
 
-#include <stdlib.h>
 #include <new>
 #include <FBaseResult.h>
-#include "FBase_StringConverter.h"
 #include <FBaseSysLog.h>
-
-
+#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
index 230a61c..9fcce25 100644 (file)
@@ -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_
index 0ed4f72..e808ffb 100644 (file)
@@ -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