Change the way to convert wchar_t* to char* in CopyToCharArrayN()
[platform/framework/native/appfw.git] / src / base / utility / FBaseUtil_IcuConverter.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @File        :       FBaseUtil_ICUConverter.cpp
20  * @brief       :   Implementation for _ICUConverter Class
21  */
22 // Includes
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <wchar.h>
26 #include <string.h>
27 #include <new>
28 #include <unique_ptr.h>
29 #include <unicode/ustring.h>
30 #include <FBaseResult.h>
31 #include "FBase_StringConverter.h"
32 #include "FBase_NativeError.h"
33 #include <FBaseSysLog.h>
34 #include "FBaseUtil_IcuConverter.h"
35
36
37 namespace Tizen { namespace Base { namespace Utility
38 {
39 _ICUConverter::_ICUConverter(void)
40               :__pConverter(null)
41 {
42
43 }
44 _ICUConverter::~_ICUConverter(void)
45 {
46         if (__pConverter)
47         {
48                 ucnv_close(__pConverter);
49                 __pConverter = null;
50         }
51 }
52
53 bool
54 _ICUConverter::OpenConverter(const Tizen::Base::String& encodingScheme)
55 {
56         std::unique_ptr< char[] > pConverterName(_StringConverter::CopyToCharArrayN(encodingScheme));
57         SysTryReturn(NID_BASE_UTIL, pConverterName != null, false, E_INVALID_ARG, "[%s] Invalid coding scheme.", GetErrorMessage(E_INVALID_ARG));
58         UErrorCode err = U_ZERO_ERROR;
59
60         if (!encodingScheme.CompareTo("UCS-2"))
61         {
62                 __pConverter = ucnv_open("UTF-16LE", &err);
63         }
64         else
65         {
66                 __pConverter = ucnv_open(pConverterName.get(), &err);
67         }
68
69         result r = GetResultFromIcuErrorCode(err);
70         SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, false, r, "[%s] The err must be U_ZERO_ERROR.", GetErrorMessage(r));
71
72         SetLastResult(E_SUCCESS);
73         return true;
74 }
75
76 void
77 _ICUConverter::CloseConverter(void)
78 {
79         if (__pConverter)
80         {
81                 ucnv_close(__pConverter);
82                 __pConverter = null;
83         }
84 }
85
86 char*
87 _ICUConverter::ConvertFromUcharN(const wchar_t* pSrc, int srcLength, int& retLength)
88 {
89         UErrorCode errorCode = U_ZERO_ERROR;
90         result r = E_SUCCESS;
91         char* pOutBuf = null;
92         ucnv_setFromUCallBack(__pConverter, UCNV_FROM_U_CALLBACK_STOP, null, null, null, &errorCode);
93
94         int outLen = 0;
95         int icuStrLen = srcLength * 2;
96         UChar* pIcuStr = new (std::nothrow) UChar[icuStrLen];
97         SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
98         UChar* pResultStr = u_strFromWCS(pIcuStr, icuStrLen, &outLen, pSrc, srcLength, &errorCode);
99         if (U_SUCCESS(errorCode))
100         {
101                 char* pTmpOut = null;
102                 int outBytesLeftOut = srcLength * 4;
103                 pOutBuf = new (std::nothrow) char[outBytesLeftOut + 1];
104                 SysTryCatch(NID_BASE_UTIL, pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
105
106                 pTmpOut = pOutBuf;
107                 memset(pOutBuf, 0, (outBytesLeftOut + 1));
108                 retLength = ucnv_fromUChars(__pConverter, pTmpOut, outBytesLeftOut, pResultStr, outLen, &errorCode);
109                 r = GetResultFromIcuErrorCode(errorCode);
110                 if (IsFailed(r))
111                 {
112                         delete[] pOutBuf;
113                         pOutBuf = null;
114                 }
115         }
116
117 CATCH:
118         delete[] pIcuStr;
119         pIcuStr = null;
120         SetLastResult(r);
121         return pOutBuf;
122 }
123
124 wchar_t*
125 _ICUConverter::ConvertToUcharN(const char* src, int srcLength)
126 {
127         UErrorCode errorCode = U_ZERO_ERROR;
128         ucnv_setToUCallBack(__pConverter, UCNV_TO_U_CALLBACK_STOP, null, null, null, &errorCode);
129         wchar_t* pDst = null;
130         wchar_t* pResultStr = null;
131         const char* pTmpIn = src;
132         int icuStrLen = (srcLength + 1);
133         UChar* pIcuStr = new (std::nothrow) UChar[icuStrLen];
134         SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
135         memset(pIcuStr, 0, sizeof(UChar) * (icuStrLen));
136
137         signed int retLength = ucnv_toUChars(__pConverter, pIcuStr, icuStrLen, pTmpIn, srcLength, &errorCode);
138         result r = GetResultFromIcuErrorCode(errorCode);
139         if (U_SUCCESS(errorCode))
140         {
141                 pDst = new (std::nothrow) wchar_t[retLength + 1];
142                 SysTryCatch(NID_BASE_UTIL, pDst != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
143                 memset(pDst, 0, sizeof(wchar_t) * (retLength + 1));
144                 pResultStr = u_strToWCS(pDst, retLength, &retLength, pIcuStr, retLength, &errorCode);
145                 r = GetResultFromIcuErrorCode(errorCode);
146                 if (IsFailed(r))
147                 {
148                         delete[] pDst;
149                         pDst = null;
150                 }
151         }
152
153 CATCH:
154         SetLastResult(r);
155         delete[] pIcuStr;
156         pIcuStr = null;
157         return pResultStr;
158 }
159
160 result
161 _ICUConverter::GetResultFromIcuErrorCode(UErrorCode& err)
162 {
163         if (U_FAILURE(err))
164         {
165                 switch (err)
166                 {
167                         case U_ZERO_ERROR:
168                                 return E_SUCCESS;
169                         case U_MEMORY_ALLOCATION_ERROR:
170                                 return E_OUT_OF_MEMORY;
171
172                         case U_INDEX_OUTOFBOUNDS_ERROR:
173                                 return E_INVALID_ARG;
174
175                         case U_TRUNCATED_CHAR_FOUND:
176                         // fall through to U_INVALID_CHAR_FOUND
177                         case U_INVALID_CHAR_FOUND:
178                         // fall through to U_ILLEGAL_CHAR_FOUND
179                         case U_ILLEGAL_CHAR_FOUND:
180                                 return E_INVALID_ENCODING_RANGE;
181
182                         case U_INVALID_TABLE_FORMAT:
183                                 return E_SYSTEM;
184
185                         case U_BUFFER_OVERFLOW_ERROR:
186                                 return E_OVERFLOW;
187
188                         case U_STRING_NOT_TERMINATED_WARNING:
189                                 return E_INVALID_ARG;
190
191                         case U_ILLEGAL_ARGUMENT_ERROR:
192                                 return E_INVALID_ARG;
193
194                         case U_FILE_ACCESS_ERROR:
195                         case U_AMBIGUOUS_ALIAS_WARNING:
196                                 return E_UNSUPPORTED_TYPE;
197
198                         default:
199                                 return E_SYSTEM;
200                 }
201         }
202         return E_SUCCESS;
203 }
204
205 char*
206 ConvertWcsToMbsN(const wchar_t* pValue)
207 {
208         SysTryReturn(NID_BASE_UTIL, pValue != null, null, E_INVALID_ARG, "[%s] Invalid argument is used. The pValue is null.", GetErrorMessage(E_INVALID_ARG));
209
210         int len = wcslen(pValue);
211         if (len == 0)
212         {
213                 char* pRet = new (std::nothrow) char[1];
214                 SysTryReturn(NID_BASE_UTIL, pRet != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
215                 pRet[0] = '\0';
216                 return pRet;
217         }
218
219         UErrorCode err = U_ZERO_ERROR;
220         UConverter* pConverter = ucnv_open("UTF-8", &err);
221
222         SysTryReturn(NID_BASE_UTIL, err == U_ZERO_ERROR, null, E_INVALID_ARG, "[%s] ucnv_open() failed. The err must be U_ZERO_ERROR.", GetErrorMessage(E_INVALID_ARG));
223
224         ucnv_setFromUCallBack(pConverter, UCNV_FROM_U_CALLBACK_STOP, null, null, null, &err);
225
226         int icuStrLen = len * 2;
227         UChar* pIcuStr = new (std::nothrow) UChar[icuStrLen];
228         SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
229
230         int outLen = 0;
231         UChar* pResultStr = u_strFromWCS(pIcuStr, icuStrLen, &outLen, pValue, len, &err);
232
233         char* pOutBuf = null;
234         if (U_SUCCESS(err))
235         {
236                 char* pTmpOut = null;
237                 int outBytesLeftOut = len * 4;
238                 pOutBuf = new (std::nothrow) char[outBytesLeftOut + 1];
239                 SysTryCatch(NID_BASE_UTIL, pOutBuf != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
240
241                 pTmpOut = pOutBuf;
242                 memset(pOutBuf, 0, outBytesLeftOut + 1);
243                 int retLength = ucnv_fromUChars(pConverter, pTmpOut, outBytesLeftOut, pResultStr, outLen, &err);
244
245                 if (U_FAILURE(err))
246                 {
247                         SysLogException(NID_BASE_UTIL, E_INVALID_ARG, "[%s] ucnv_fromUChars() failed. pTmpOut is %s.", GetErrorMessage(E_INVALID_ARG), pTmpOut);
248                         delete[] pOutBuf;
249                         pOutBuf = null;
250                 }
251         }
252         else
253         {
254                 SysLogException(NID_BASE_UTIL, E_INVALID_ARG, "[%s] u_strFromWCS() failed. pValue is %ls.", GetErrorMessage(E_INVALID_ARG), pValue);
255         }
256
257 CATCH:
258         if (pConverter)
259         {
260                 ucnv_close(pConverter);
261                 pConverter = null;
262         }
263         delete[] pIcuStr;
264         pIcuStr = null;
265         return pOutBuf;
266 }
267 } } } // Tizen::Base::Utilityy