Manage when the string length is zero
[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                 SetLastResult(E_SUCCESS);
217                 return pRet;
218         }
219
220         UErrorCode err = U_ZERO_ERROR;
221         UConverter* pConverter = ucnv_open("UTF-8", &err);
222
223         result r = _ICUConverter::GetResultFromIcuErrorCode(err);
224         SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, null, r, "[%s] The err must be U_ZERO_ERROR.", GetErrorMessage(r));
225
226         ucnv_setFromUCallBack(pConverter, UCNV_FROM_U_CALLBACK_STOP, null, null, null, &err);
227
228         int icuStrLen = len * 2;
229         UChar* pIcuStr = new (std::nothrow) UChar[icuStrLen];
230         SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
231         
232         int outLen = 0;
233         UChar* pResultStr = u_strFromWCS(pIcuStr, icuStrLen, &outLen, pValue, len, &err);
234
235         char* pOutBuf = null;
236         if (U_SUCCESS(err))
237         {
238                 char* pTmpOut = null;
239                 int outBytesLeftOut = len * 4;
240                 pOutBuf = new (std::nothrow) char[outBytesLeftOut + 1];
241                 SysTryCatch(NID_BASE_UTIL, pOutBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
242
243                 pTmpOut = pOutBuf;
244                 memset(pOutBuf, 0, outBytesLeftOut + 1);
245                 int retLength = ucnv_fromUChars(pConverter, pTmpOut, outBytesLeftOut, pResultStr, outLen, &err);
246                 
247                 r = _ICUConverter::GetResultFromIcuErrorCode(err);
248                 if (IsFailed(r))
249                 {
250                         delete[] pOutBuf;
251                         pOutBuf = null;
252                 }
253         }
254
255 CATCH:
256         if (pConverter)
257         {
258                 ucnv_close(pConverter);
259                 pConverter = null;
260         }
261         delete[] pIcuStr;
262         pIcuStr = null;
263         SetLastResult(r);
264         return pOutBuf;
265 }
266
267 wchar_t*
268 ConvertMbsToWcsN(const char* pValue)
269 {
270         int len = strlen(pValue);
271         SysTryReturn(NID_BASE_UTIL, len != 0, null, E_INVALID_ARG, "[%s] Invalid argument is used. The pValue is an empty string.", GetErrorMessage(E_INVALID_ARG));
272
273         UErrorCode err = U_ZERO_ERROR;
274         UConverter* pConverter = ucnv_open("UTF-8", &err);
275
276         result r = _ICUConverter::GetResultFromIcuErrorCode(err);
277         SysTryReturn(NID_BASE_UTIL, r == E_SUCCESS, null, r, "[%s] The err must be U_ZERO_ERROR.", GetErrorMessage(r));
278
279         ucnv_setFromUCallBack(pConverter, UCNV_FROM_U_CALLBACK_STOP, null, null, null, &err);
280
281         int icuStrLen = len + 1;
282         UChar* pIcuStr = new (std::nothrow) UChar[icuStrLen];
283         SysTryReturn(NID_BASE_UTIL, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
284         memset(pIcuStr, 0, sizeof(UChar) * (icuStrLen));
285
286         const char* pTmpIn = pValue;
287         signed int retLength = ucnv_toUChars(pConverter, pIcuStr, icuStrLen, pTmpIn, len, &err);
288
289         wchar_t* pDst = null;
290         wchar_t* pResultStr = null;
291         if (U_SUCCESS(err))
292         {
293                 pDst = new (std::nothrow) wchar_t[retLength + 1];
294                 SysTryCatch(NID_BASE_UTIL, pDst != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
295                 memset(pDst, 0, sizeof(wchar_t) * (retLength + 1));
296                 pResultStr = u_strToWCS(pDst, retLength, &retLength, pIcuStr, retLength, &err);
297                 
298                 r = _ICUConverter::GetResultFromIcuErrorCode(err);
299                 if (IsFailed(r))
300                 {
301                         delete[] pDst;
302                         pDst = null;
303                 }
304         }
305
306 CATCH:
307         if (pConverter)
308         {
309                 ucnv_close(pConverter);
310                 pConverter = null;
311         }
312         SetLastResult(r);
313         delete[] pIcuStr;
314         pIcuStr = null;
315         return pResultStr;
316 }
317
318 } } } // Tizen::Base::Utility