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