Merge "Update code of system and text for reporting Klocwork." into tizen_2.2
[platform/framework/native/appfw.git] / src / text / FText_GsmEncodingCore.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_GsmEncodingCore.cpp
19  * @brief               This is the implementation file for _GsmEncodingCore class.
20  */
21
22 // Includes
23 #include <unique_ptr.h>
24 #include <FBaseSysLog.h>
25 #include "FText_GsmEncodingCore.h"
26
27
28 using namespace Tizen::Base;
29
30 namespace Tizen { namespace Text
31 {
32
33
34 typedef struct
35 {
36         byte gsm;
37         wchar_t unicode;
38 } GsmUniTable;
39
40
41 #define GSM_TABLE_UNI_LENGTH 0x80
42 static const wchar_t GSM_UNICODE_TABLE[] =
43 {
44         0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
45         0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
46         0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
47         0x03A3, 0x0398, 0x039E, 0xFFFD, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
48         0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
49         0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
50         0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
51         0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
52         0x00A1, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
53         0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
54         0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
55         0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6, 0x00D1, 0x00DC, 0x00A7,
56         0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
57         0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
58         0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
59         0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0
60 };
61
62
63 #define EXT_GSM_TABLE_1B_LENGTH 10
64 static const GsmUniTable GSM_UNICODE_TABLE_EXTENSION[] =
65 {
66         {0x0A, 0x000C}, {0x14, 0x005E}, {0x28, 0x007B}, {0x29, 0x007D}, {0x2F, 0x005C},
67         {0x3C, 0x005B}, {0x3D, 0x007E}, {0x3E, 0x005D}, {0x40, 0x007C}, {0x65, 0x20AC}
68 };
69
70 _GsmEncodingCore::_GsmEncodingCore(void)
71 {
72 }
73
74
75 _GsmEncodingCore::~_GsmEncodingCore(void)
76 {
77 }
78
79 _EncodingCore*
80 _GsmEncodingCore::GetEncodingCoreImplN(const Tizen::Base::String& encodingFrom, const Tizen::Base::String& encodingTo)
81 {
82         SysTryReturn(NID_TEXT, encodingFrom == L"GSM", null, E_UNSUPPORTED_TYPE, "[E_UNSUPPORTED_TYPE] It is not the GSM encoding type.");
83         _GsmEncodingCore* pEncoderDecoder = new (std::nothrow) _GsmEncodingCore;
84         SysTryReturn(NID_TEXT, pEncoderDecoder, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
85         return pEncoderDecoder;
86 }
87
88
89 String
90 _GsmEncodingCore::GetName(void)
91 {
92         return String(L"GSM");
93 }
94
95 result
96 _GsmEncodingCore::GetByteCount(const wchar_t* pSrc, int srcLength, int& retLength)
97 {
98         retLength = -1;
99         if (pSrc != null)
100         {
101                 int gsmSize = 0;
102                 int index = 0;
103                 wchar_t* pUnicodeStr = (wchar_t*) pSrc;
104                 while (srcLength > 0)
105                 {
106                         bool foundInExtTable = false;
107                         SysTryReturnResult(NID_TEXT, (*pUnicodeStr != 0xFFFD), E_INVALID_ENCODING_RANGE,
108                                 "[%s] Encoding failed. pSrc(%ls) contains code(%x) pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE), pSrc, *pUnicodeStr);
109                         SysTryReturnResult(NID_TEXT, (*pUnicodeStr <= 0x20AC), E_INVALID_ENCODING_RANGE,
110                                 "[%s] Encoding failed. pSrc(%ls) contains code(%x) pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE), pSrc, *pUnicodeStr);
111
112                         if (*pUnicodeStr == '\0')
113                         {
114                                 gsmSize++;
115                                 break;
116                         }
117
118                         for (index = 0; index < EXT_GSM_TABLE_1B_LENGTH; index++)
119                         {
120                                 if (*pUnicodeStr == GSM_UNICODE_TABLE_EXTENSION[index].unicode)
121                                 {
122                                         gsmSize++;
123                                         foundInExtTable = true;
124                                         break;
125                                 }
126                         }
127                         if (!foundInExtTable)
128                         {
129                                 bool foundInUniTable = false;
130
131                                 // 0x0020 - 0x005F, 0x0061 - 0x007E
132                                 if (*pUnicodeStr < 0x0020 || *pUnicodeStr > 0x007E || *pUnicodeStr == 0x0060)
133                                 {
134                                         for (index = 0; index < GSM_TABLE_UNI_LENGTH; index++)
135                                         {
136                                                 if (*pUnicodeStr == GSM_UNICODE_TABLE[index])
137                                                 {
138                                                         foundInUniTable = true;
139                                                         break;
140                                                 }
141                                         }
142
143                                         SysTryReturnResult(NID_TEXT, foundInUniTable, E_INVALID_ENCODING_RANGE,
144                                         "[%s] Encoding failed. String contains code pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE));
145                                 }
146                         }
147
148                         gsmSize++;
149                         pUnicodeStr++;
150                         srcLength--;
151                 }
152                 retLength = gsmSize;
153                 return E_SUCCESS;
154         }
155
156         return E_INVALID_ARG;
157 }
158
159 result
160 _GsmEncodingCore::GetCharCount(const byte* pSrc, int srcLength, int& retLength)
161 {
162         retLength = -1;
163         if (pSrc != null)
164         {
165                 int uniSize = 0;
166                 int index = 0;
167                 byte* pGsmByte = (byte*) pSrc;
168                 while (srcLength > 1)
169                 {
170                         SysTryReturnResult(NID_TEXT, not (*pGsmByte & 0x80), E_INVALID_ENCODING_RANGE,
171                                         "[%s] Encoding failed. String contains code pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE));
172                         if (*pGsmByte == 0x1B)
173                         {
174                                 bool foundInExtTable = false;
175
176                                 pGsmByte++;
177                                 srcLength--;
178                                 for (index = 0; index < EXT_GSM_TABLE_1B_LENGTH; index++)
179                                 {
180                                         if (*pGsmByte == GSM_UNICODE_TABLE_EXTENSION[index].gsm)
181                                         {
182                                                 foundInExtTable = true;
183                                                 break;
184                                         }
185                                 }
186                                 SysTryReturnResult(NID_TEXT, foundInExtTable, E_INVALID_ENCODING_RANGE,
187                                         "[%s] Encoding failed. String contains code pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE));
188                         }
189                         uniSize++;
190                         pGsmByte++;
191                         srcLength--;
192                 }
193
194                 if (srcLength)
195                 {
196                         SysTryReturnResult(NID_TEXT, not ((*pGsmByte & 0x80) || (*pGsmByte == 0x1B)), E_INVALID_ENCODING_RANGE,
197                                         "[%s] Encoding failed. String contains code pointing outside of bounds by GSM encdoing.", GetErrorMessage(E_INVALID_ENCODING_RANGE));
198                         uniSize++;
199                 }
200
201                 retLength = uniSize;
202                 return E_SUCCESS;
203         }
204
205         return E_INVALID_ARG;
206 }
207
208 byte*
209 _GsmEncodingCore::EncodeN(const wchar_t* pSrc, int srcLength, int& retLength)
210 {
211         result r = GetByteCount(pSrc, srcLength, retLength);
212         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Encoding failed", GetErrorMessage(r));
213
214         std::unique_ptr<byte[]> pDst(new (std::nothrow) byte[retLength + 1]);
215         SysTryReturn(NID_TEXT, pDst, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
216
217         wchar_t* pUnicodeStr = (wchar_t*) pSrc;
218         byte* pCurrPos = pDst.get();
219         int index = 0;
220         while (srcLength > 0)
221         {
222                 bool foundInUniTable = false;
223                 if (*pUnicodeStr < GSM_TABLE_UNI_LENGTH)
224                 {
225                         if (*pUnicodeStr == GSM_UNICODE_TABLE[*pUnicodeStr])
226                         {
227                                 *pCurrPos = (byte) (*pUnicodeStr);
228                                 foundInUniTable = true;
229                         }
230                 }
231                 if (!foundInUniTable)
232                 {
233                         for (index = 0; index < GSM_TABLE_UNI_LENGTH; index++)
234                         {
235                                 if (*pUnicodeStr == GSM_UNICODE_TABLE[index])
236                                 {
237                                         *pCurrPos = (byte) index;
238                                         foundInUniTable = true;
239                                         break;
240                                 }
241                         }
242                         if (!foundInUniTable)
243                         {
244                                 for (index = 0; index < EXT_GSM_TABLE_1B_LENGTH; index++)
245                                 {
246                                         if (*pUnicodeStr == GSM_UNICODE_TABLE_EXTENSION[index].unicode)
247                                         {
248                                                 *pCurrPos = 0x1B;
249                                                 *(++pCurrPos) = GSM_UNICODE_TABLE_EXTENSION[index].gsm;
250                                                 break;
251                                         }
252                                 }
253                         }
254                 }
255
256                 pCurrPos++;
257                 pUnicodeStr++;
258                 srcLength--;
259         }
260
261         SetLastResult(E_SUCCESS);
262         return pDst.release();
263 }
264
265 wchar_t*
266 _GsmEncodingCore::DecodeN(const byte* pSrc, int srcLength, int& retLength)
267 {
268         // 0 in GSM is mapped to 0x40 ['@'] in UNICODE, following code is to handle terminating null.
269         if (srcLength > 1 && pSrc[srcLength - 1] == '\0')
270         {
271                 --srcLength;
272         }
273
274         result r = GetCharCount(pSrc, srcLength, retLength);
275         SysTryReturn(NID_TEXT, !IsFailed(r), null, r, "[%s] Encoding failed", GetErrorMessage(r));
276
277         std::unique_ptr<wchar_t[]> pDst( new (std::nothrow) wchar_t[retLength + 1]);
278         SysTryReturn(NID_TEXT, pDst, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
279
280         byte* pGsmByte = (byte*) pSrc;
281         wchar_t* pCurrPos = pDst.get();
282         int index = 0;
283         while (srcLength > 0 && pGsmByte != null)
284         {
285                 *pCurrPos = GSM_UNICODE_TABLE[*pGsmByte];
286                 if (*pGsmByte == 0x001B)
287                 {
288                         pGsmByte++;
289                         srcLength--;
290
291                         for (index = 0; index < EXT_GSM_TABLE_1B_LENGTH; index++)
292                         {
293                                 if (*pGsmByte == GSM_UNICODE_TABLE_EXTENSION[index].gsm)
294                                 {
295                                         *pCurrPos = GSM_UNICODE_TABLE_EXTENSION[index].unicode;
296                                         break;
297                                 }
298                         }
299                 }
300                 pCurrPos++;
301                 pGsmByte++;
302                 srcLength--;
303         }
304
305         *(pDst.get() + (retLength)) = '\0';
306         SetLastResult(E_SUCCESS);
307         return pDst.release();
308 }
309
310 int
311 _GsmEncodingCore::GetMaxByteCount(int charCount) const
312 {
313         return charCount * 2;
314 }
315
316 int
317 _GsmEncodingCore::GetMaxCharCount(int byteCount) const
318 {
319         return byteCount;
320 }
321
322 } } // Tizen::Text