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