Merge "Update code of system and text for reporting Klocwork." into tizen_2.2
[platform/framework/native/appfw.git] / src / text / FText_IcuEncodingCore.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                FText_IcuEncodingCore.cpp
19  * @brief               This is the implementation file for _IcuEncodingCore class.
20  */
21
22 // Includes
23 #include<unique_ptr.h>
24 #include <unicode/ustring.h>
25 #include <cstdlib>
26 #include <FBaseSysLog.h>
27 #include "FText_IcuEncodingCore.h"
28
29 using namespace Tizen::Base;
30 using namespace Tizen::Base::Collection;
31 using namespace Tizen::Base::Utility;
32
33 namespace Tizen { namespace Text
34 {
35
36 _IcuEncodingCore::_IcuEncodingCore(void)
37         : __pEncoder(null)
38 {
39 }
40
41 _IcuEncodingCore::~_IcuEncodingCore(void)
42 {
43         if (__pEncoder)
44         {
45                 ucnv_close(__pEncoder);
46                 __pEncoder = null;
47         }
48 }
49
50 result
51 _IcuEncodingCore::__Encode(const wchar_t* pSrc, int srcLength, byte* pDst, int dstLength, int& retLength)
52 {
53         SysTryReturnResult(NID_TEXT, pSrc, E_INVALID_ARG,
54                         "[%s] Invalid argument is used. Input buffer pSrc is null.", GetErrorMessage(E_INVALID_ARG));
55         SysTryReturnResult(NID_TEXT, srcLength >= 0, E_INVALID_ARG,
56                         "[%s] Invalid argument is used. srcLength(%d) can not be negative.", GetErrorMessage(E_INVALID_ARG), srcLength);
57
58         UErrorCode err = U_ZERO_ERROR;
59         int outLen = 0;
60         int icuStrLen = srcLength * 2;
61
62         result r = E_OUT_OF_MEMORY;
63         IcuUChar* pIcuStr = new (std::nothrow) IcuUChar[icuStrLen];
64         if (pIcuStr)
65         {
66                 IcuUChar* pIcuStr1 = u_strFromWCS(pIcuStr, icuStrLen, &outLen, pSrc, srcLength, &err);
67                 if (U_SUCCESS(err))
68                 {
69                         if (pDst)
70                         {
71                                 retLength = ucnv_fromUChars(__pEncoder, (char*) pDst, dstLength, pIcuStr1, outLen, &err);
72                         }
73                         else
74                         {
75                                 retLength = ucnv_fromUChars(__pEncoder, null, 0, pIcuStr1, outLen, &err);
76                                 if (err == U_BUFFER_OVERFLOW_ERROR)
77                                 {
78                                         err = U_ZERO_ERROR;
79                                 }
80                                 else
81                                 {
82                                         retLength = -1;
83                                 }
84                         }
85                 }
86
87                 r = GetResultFromIcuErrorCode(err);
88         }
89
90         delete[] pIcuStr;
91         return r;
92 }
93
94 result
95 _IcuEncodingCore::__Decode(const byte* pSrc, int srcLength, wchar_t* pDst, int dstLength, int& retLength)
96 {
97         SysTryReturnResult(NID_TEXT, pSrc, E_INVALID_ARG,
98                         "[%s] Invalid argument is used. Input buffer pSrc is null.", GetErrorMessage(E_INVALID_ARG));
99         SysTryReturnResult(NID_TEXT, srcLength >= 0, E_INVALID_ARG,
100                         "[%s] Invalid argument is used. srcLength(%d) can not be negative.", GetErrorMessage(E_INVALID_ARG), srcLength);
101
102         bool isCallForCharCount = (pDst == null);
103         if (isCallForCharCount)
104         {
105                 dstLength = srcLength * 2;
106                 pDst = new (std::nothrow) wchar_t[dstLength];
107                 SysTryReturnResult(NID_TEXT, pDst, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
108         }
109
110         UErrorCode err = U_ZERO_ERROR;
111         int icuStrLen = dstLength * 2;
112         IcuUChar* pIcuStr = new (std::nothrow) IcuUChar[icuStrLen];
113         if (pIcuStr)
114         {
115                 retLength = ucnv_toUChars(__pEncoder, pIcuStr, icuStrLen, (const char*) pSrc, srcLength, &err);
116                 if (U_SUCCESS(err))
117                 {
118                         pDst = u_strToWCS(pDst, dstLength, &retLength, pIcuStr, retLength, &err);
119                 }
120         }
121         delete[] pIcuStr;
122
123         if (isCallForCharCount)
124         {
125                 if (U_FAILURE(err))
126                 {
127                         retLength = -1;
128                 }
129
130                 delete[] pDst;
131                 pDst = null;
132         }
133
134         return GetResultFromIcuErrorCode(err);
135 }
136
137 byte*
138 _IcuEncodingCore::EncodeExN(const wchar_t* pSrc, int srcLength, int& retLength, bool flush)
139 {
140         SysTryReturn(NID_TEXT, pSrc, null, E_INVALID_ARG,
141                         "[%s] Invalid argument is used. Input buffer pSrc is null.", GetErrorMessage(E_INVALID_ARG));
142         SysTryReturn(NID_TEXT, srcLength >= 0, null, E_INVALID_ARG,
143                         "[%s] Invalid argument is used. srcLength(%d) can not be negative.", GetErrorMessage(E_INVALID_ARG), srcLength);
144
145         result r = E_SUCCESS;
146         UErrorCode err = U_ZERO_ERROR;
147         byte* pDst = null;
148
149         int outLen = 0;
150         int icuStrLen = srcLength * 2;
151         IcuUChar* pIcuStr = new (std::nothrow) IcuUChar[icuStrLen];
152         SysTryCatch(NID_TEXT, pIcuStr, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
153
154         pIcuStr = u_strFromWCS(pIcuStr, icuStrLen, &outLen, pSrc, srcLength, &err);
155         r = GetResultFromIcuErrorCode(err);
156         if (U_SUCCESS(err))
157         {
158                 int maxDestLen = UCNV_GET_MAX_BYTES_FOR_STRING(outLen, ucnv_getMaxCharSize(__pEncoder));
159                 pDst = new (std::nothrow) byte[maxDestLen];
160                 if (pDst)
161                 {
162                         char* pDstArray = (char*) pDst;
163                         const char* pDstLimit = pDstArray + maxDestLen;
164                         const IcuUChar* pSrcArray = pIcuStr;
165                         const IcuUChar* pSrcLimit = pIcuStr + outLen;
166
167                         err = U_ZERO_ERROR;
168                         ucnv_fromUnicode(__pEncoder, &pDstArray, pDstLimit, &pSrcArray, pSrcLimit, null, flush, &err);
169                         r = GetResultFromIcuErrorCode(err);
170                         if (U_SUCCESS(err))
171                         {
172                                 retLength = (byte*) pDstArray - pDst;
173
174                                 delete[] pIcuStr;
175                                 SetLastResult(E_SUCCESS);
176                                 return pDst;
177                         }
178                 }
179         }
180
181 CATCH:
182         delete[] pIcuStr;
183         delete[] pDst;
184         retLength = -1;
185         SetLastResult(r);
186         return null;
187 }
188
189 wchar_t*
190 _IcuEncodingCore::DecodeExN(const byte* pSrc, int srcLength, int& retLength, bool flush)
191 {
192         SysTryReturn(NID_TEXT, pSrc, null, E_INVALID_ARG,
193                         "[%s] Invalid argument is used. Input buffer pSrc is null.", GetErrorMessage(E_INVALID_ARG));
194         SysTryReturn(NID_TEXT, srcLength >= 0, null, E_INVALID_ARG,
195                         "[%s] Invalid argument is used. srcLength(%d) can not be negative.", GetErrorMessage(E_INVALID_ARG), srcLength);
196
197         UErrorCode err = U_ZERO_ERROR;
198         int icuStrLen = srcLength * 2;
199         IcuUChar* pIcuStr = new (std::nothrow) IcuUChar[icuStrLen];
200         SysTryReturn(NID_TEXT, pIcuStr, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
201
202         IcuUChar* pDstArray = pIcuStr;
203         const IcuUChar* pDstLimit = pIcuStr + icuStrLen;
204         const char* pSrcArray = (const char*) pSrc;
205         const char* pSrcLimit = pSrcArray + srcLength;
206
207         result r = E_SUCCESS;
208         wchar_t* pDst = null;
209         err = U_ZERO_ERROR;
210
211         ucnv_toUnicode(__pEncoder, &pDstArray, pDstLimit, &pSrcArray, pSrcLimit, null, flush, &err);
212         r = GetResultFromIcuErrorCode(err);
213
214         if (U_SUCCESS(err))
215         {
216                 int dstLength = pDstArray - pIcuStr;
217                 pDst = new (std::nothrow) wchar_t[dstLength + 1];
218                 SysTryCatch(NID_TEXT, pDst, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
219                 pDst[dstLength] = '\0';
220
221                 pDst = u_strToWCS(pDst, dstLength, &retLength, pIcuStr, dstLength, &err);
222                 r = GetResultFromIcuErrorCode(err);
223                 SysTryCatch(NID_TEXT, !IsFailed(r), , r, "Decoding failed");
224
225                 delete[] pIcuStr;
226                 SetLastResult(E_SUCCESS);
227                 return pDst;
228         }
229
230 CATCH:
231         delete[] pIcuStr;
232         delete[] pDst;
233         retLength = -1;
234         SetLastResult(r);
235         return null;
236 }
237
238 _EncodingCore*
239 _IcuEncodingCore::GetEncodingCoreImplN(const Tizen::Base::String& encodingFrom, const Tizen::Base::String& encodingTo)
240 {
241         result r = E_SUCCESS;
242         UErrorCode err = U_ZERO_ERROR;
243         std::unique_ptr<_IcuEncodingCore> pEncodingCore(null);
244
245         int lenEncoding = encodingFrom.GetLength();
246         std::unique_ptr<char[]> pEncoding(new (std::nothrow) char[lenEncoding + 2]);
247         SysTryReturn(NID_TEXT, (pEncoding != null), null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
248
249         size_t retLength = wcstombs(pEncoding.get(), encodingFrom.GetPointer(), lenEncoding);
250         SysTryReturn(NID_TEXT, (retLength > 0), null, E_SYSTEM, "[%s] Unable to convert encoding string to multi byte char array", GetErrorMessage(E_SYSTEM));
251
252         *(pEncoding.get() + retLength) = '\0';
253
254         pEncodingCore.reset(new (std::nothrow) _IcuEncodingCore);
255         SysTryReturn(NID_TEXT, (pEncodingCore != null), null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
256
257         pEncodingCore->__pEncoder = ucnv_open(pEncoding.get(), &err);
258         if (U_FAILURE(err))
259         {
260                 String subsEncoding(encodingFrom);
261                 subsEncoding.ToUpper();
262                 if (subsEncoding.StartsWith("UCS", 0))
263                 {
264                         r = subsEncoding.Replace("UCS", "UTF");
265                         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Unable to open ICU converter", GetErrorMessage(r));
266
267                         r = subsEncoding.Replace("4", "32");
268                         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Unable to open ICU converter", GetErrorMessage(r));
269
270                         size_t retLength = wcstombs(pEncoding.get(), subsEncoding.GetPointer(), subsEncoding.GetLength());
271                         SysTryReturn(NID_TEXT, (retLength > 0), null, E_SYSTEM, "[%s] Unable to convert encoding string to multi byte char array", GetErrorMessage(E_SYSTEM));
272
273                         pEncoding[retLength] = '\0';
274                         err = U_ZERO_ERROR;
275                         pEncodingCore->__pEncoder = ucnv_open(pEncoding.get(), &err);
276                 }
277
278         }
279         r = pEncodingCore->GetResultFromIcuErrorCode(err);
280         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Unable to open ICU converter", GetErrorMessage(r));
281
282         ucnv_setFromUCallBack(pEncodingCore->__pEncoder, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &err);
283         ucnv_setToUCallBack(pEncodingCore->__pEncoder, UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &err);
284
285         pEncodingCore->_encodingFrom = encodingFrom;
286         pEncodingCore->_encodingTo = L"WCHAR_T";
287
288         SetLastResult(E_SUCCESS);
289         return pEncodingCore.release();
290 }
291
292 String
293 _IcuEncodingCore::GetName(void)
294 {
295         UErrorCode err = U_ZERO_ERROR;
296         const char* pName = ucnv_getName(__pEncoder, &err);
297         if (U_SUCCESS(err))
298         {
299                 return String(pName);
300         }
301
302         return String();
303 }
304
305 result
306 _IcuEncodingCore::GetByteCount(const wchar_t* pSrc, int srcLength, int& retLength)
307 {
308         return __Encode(pSrc, srcLength, null, 0, retLength);
309 }
310
311 result
312 _IcuEncodingCore::GetCharCount(const byte* pSrc, int srcLength, int& retLength)
313 {
314         return __Decode(pSrc, srcLength, null, 0, retLength);
315 }
316
317 byte*
318 _IcuEncodingCore::EncodeN(const wchar_t* pSrc, int srcLength, int& retLength)
319 {
320         int maxDestLen = UCNV_GET_MAX_BYTES_FOR_STRING(srcLength * 2, ucnv_getMaxCharSize(__pEncoder));
321         std::unique_ptr<byte[]> pByte(new (std::nothrow) byte[maxDestLen]);
322         SysTryReturn(NID_TEXT, pByte, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
323
324         result r = __Encode(pSrc, srcLength, pByte.get(), maxDestLen, retLength);
325         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Encode operation failed", GetErrorMessage(r));
326
327         SetLastResult(E_SUCCESS);
328         return pByte.release();
329 }
330
331 wchar_t*
332 _IcuEncodingCore::DecodeN(const byte* pSrc, int srcLength, int& retLength)
333 {
334         int maxDestLen = srcLength * 2;
335         std::unique_ptr<wchar_t[]> pWchar(new (std::nothrow) wchar_t[maxDestLen]);
336         SysTryReturn(NID_TEXT, pWchar, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
337
338         result r = __Decode(pSrc, srcLength, pWchar.get(), maxDestLen, retLength);
339         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Encode operation failed", GetErrorMessage(r));
340
341         SetLastResult(E_SUCCESS);
342         return pWchar.release();
343 }
344
345 int
346 _IcuEncodingCore::GetMaxByteCount(int charCount) const
347 {
348         return charCount * (ucnv_getMaxCharSize(__pEncoder));
349 }
350
351 int
352 _IcuEncodingCore::GetMaxCharCount(int byteCount) const
353 {
354         return byteCount / (ucnv_getMinCharSize(__pEncoder));
355 }
356
357
358 result
359 _IcuEncodingCore::GetResultFromIcuErrorCode(UErrorCode& err)
360 {
361         result r = E_SUCCESS;
362         if (!U_SUCCESS(err))
363         {
364                 switch (err)
365                 {
366                 case U_MEMORY_ALLOCATION_ERROR:
367                 {
368                         r = E_OUT_OF_MEMORY;
369                         break;
370                 }
371
372                 case U_INDEX_OUTOFBOUNDS_ERROR:
373                 {
374                         r = E_INVALID_ARG;
375                         break;
376                 }
377
378                 case U_TRUNCATED_CHAR_FOUND:
379                 // fall through to U_INVALID_CHAR_FOUND
380                 case U_INVALID_CHAR_FOUND:
381                 // fall through to U_ILLEGAL_CHAR_FOUND
382                 case U_ILLEGAL_CHAR_FOUND:
383                 {
384                         r = E_INVALID_ENCODING_RANGE;
385                         break;
386                 }
387
388                 case U_INVALID_TABLE_FORMAT:
389                 {
390                         r = E_SYSTEM;
391                         break;
392                 }
393
394                 case U_BUFFER_OVERFLOW_ERROR:
395                 {
396                         r = E_OVERFLOW;
397                         break;
398                 }
399
400                 case U_STRING_NOT_TERMINATED_WARNING:
401                 {
402                         r = E_INVALID_ARG;
403                         break;
404                 }
405
406                 case U_ILLEGAL_ARGUMENT_ERROR:
407                 {
408                         r = E_INVALID_ARG;
409                         break;
410                 }
411
412                 case U_FILE_ACCESS_ERROR:
413                 // fall through to U_AMBIGUOUS_ALIAS_WARNING
414                 case U_AMBIGUOUS_ALIAS_WARNING:
415                 {
416                         r = E_UNSUPPORTED_TYPE;
417                         break;
418                 }
419
420                 default:
421                 {
422                         r = E_SYSTEM;
423                         break;
424                 }
425                 }
426         }
427         return r;
428 }
429
430 IcuUChar*
431 _IcuEncodingCore::GetIcuUcharN(const Tizen::Base::String& ospString, result& r)
432 {
433         UErrorCode err = U_ZERO_ERROR;
434         int outLen = 0;
435         int srcLength = ospString.GetLength();
436         std::unique_ptr<IcuUChar> pIcuStr(new (std::nothrow) IcuUChar(srcLength + 2));
437         SysTryReturn(NID_TEXT, pIcuStr != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
438
439         pIcuStr.reset(u_strFromWCS(
440                 pIcuStr.get(),
441                 srcLength + 2,
442                 &outLen,
443                 ospString.GetPointer(),
444                 srcLength,
445                 &err
446                 ));
447
448         r = GetResultFromIcuErrorCode(err);
449         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Error in converting osp string to ICU UChar", GetErrorMessage(r));
450
451         return pIcuStr.release();
452 }
453
454
455 } } // Tizen::Text