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