sync with tizen_2.0
[platform/framework/native/appfw.git] / src / text / FText_DecoderImpl.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_DecoderImpl.cpp
20  * @brief               This is the implementation file for _DecoderImpl class.
21  */
22
23 #include <unique_ptr.h>
24 #include "FText_EncodingCore.h"
25 #include <FBaseSysLog.h>
26 #include "FText_DecoderImpl.h"
27
28 using namespace Tizen::Base;
29 using namespace Tizen::Base::Collection;
30 using namespace Tizen::Base::Utility;
31
32 namespace Tizen { namespace Text
33 {
34
35 _DecoderImpl::_DecoderImpl(void)
36         : __pDecoder(null)
37         , __encodingType("")
38 {
39 }
40
41 _DecoderImpl::~_DecoderImpl(void)
42 {
43 }
44
45 _DecoderImpl*
46 _DecoderImpl::GetDecoderN(const String& encodingType)
47 {
48         SysTryReturn(NID_TEXT, (encodingType == L"UTF-8"), null, E_INVALID_ARG,
49                         "[%s] Invalid argument is used.encdoingType(%ls) is not UTF-8.Failed to open decoder.", GetErrorMessage(E_INVALID_ARG), encodingType.GetPointer());
50
51         std::unique_ptr<_DecoderImpl> pDecoderImpl(new (std::nothrow) _DecoderImpl);
52         SysTryReturn(NID_TEXT, pDecoderImpl, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
53
54         pDecoderImpl->__pDecoder.reset(_EncodingCore::GetEncodingCoreN(encodingType, L"WCHAR_T"));
55
56         result r = GetLastResult();
57         SysTryReturn(NID_TEXT, (pDecoderImpl->__pDecoder != null), null, r,
58                            "[%s] Failed to open decoder.", GetErrorMessage(r));
59
60         pDecoderImpl->__encodingType = encodingType;
61         pDecoderImpl->_pDecoderImpl = pDecoderImpl.get();
62
63         SetLastResult(E_SUCCESS);
64         return pDecoderImpl.release();
65 }
66
67 result
68 _DecoderImpl::Decode(const byte* pSrc, int srcLength, WcharBuffer*& pWcharBuffer, int index, bool flush) const
69 {
70         SysAssertf(__pDecoder != null, "Not yet constructed! Construct() should be called before use.");
71
72         SysTryReturnResult(NID_TEXT, (pSrc != null), E_INVALID_ARG, "[%s] Invalid argument is used. pSrc can not be null.", GetErrorMessage(E_INVALID_ARG));
73         SysTryReturnResult(NID_TEXT, (srcLength >= 0), E_INVALID_ARG,
74                                 "[%s] Invalid argument is used. srcLength(%d) cannot be negative.", GetErrorMessage(E_INVALID_ARG), srcLength);
75         SysTryReturnResult(NID_TEXT, (index >= 0), E_INVALID_ARG,
76                                 "[%s] Invalid argument is used. index(%d) cannot be negative.", GetErrorMessage(E_INVALID_ARG), index);
77
78         result r = E_SUCCESS;
79         int currPosition = 0;
80         int retLength = 0;
81         bool isMemAllocReq = false;
82
83         std::unique_ptr<wchar_t[]> pDst(__pDecoder->DecodeExN(pSrc, srcLength, retLength, flush));
84         r = GetLastResult();
85         SysTryReturnResult(NID_TEXT, (pDst != null), r, "[%s] Decoding failed", GetErrorMessage(r));
86
87         WcharBuffer* pOutBuffer = pWcharBuffer;
88         if (retLength > 0)
89         {
90                 if (pOutBuffer == null)
91                 {
92                         isMemAllocReq = true;
93                         pOutBuffer = new (std::nothrow) WcharBuffer;
94                         SysTryCatch(NID_TEXT, (pOutBuffer != null), ,
95                                            E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Byte Buffer allocation failed");
96
97                         r = pOutBuffer->Construct(retLength);
98                         SysTryCatch(NID_TEXT, (!IsFailed(r)), , r, "[%s] Unable to Construct Byte buffer", GetErrorMessage(r));
99
100                         pWcharBuffer = pOutBuffer;
101
102                 }
103                 else
104                 {
105                         currPosition = pOutBuffer->GetPosition();
106
107                         r = pOutBuffer->SetPosition(index);
108                         SysTryCatch(NID_TEXT, (!IsFailed(r)), , r, "[%s] Unable to set Byte buffer position", GetErrorMessage(r));
109                 }
110
111                 r = pOutBuffer->SetArray(pDst.get(), 0, retLength);
112                 SysTryCatch(NID_TEXT, (!IsFailed(r)), , r, "[%s] Unable to fill Byte buffer", GetErrorMessage(r));
113
114                 r = pOutBuffer->SetPosition(currPosition);
115                 SysTryCatch(NID_TEXT, (!IsFailed(r)), , r, "[%s] Unable to set Byte buffer position", GetErrorMessage(r));
116
117                 return r;
118         }
119
120 CATCH:
121         if (isMemAllocReq)
122         {
123                 delete pWcharBuffer;
124                 pWcharBuffer = null;
125         }
126         return r;
127 }
128
129 result
130 _DecoderImpl::GetCharCount(const ByteBuffer& bytes, int byteIndex, int byteCount, int& charCount, bool flush) const
131 {
132         SysAssertf(__pDecoder != null, "Not yet constructed! Construct() should be called before use.");
133
134         charCount = 0;
135         int inBufSize = bytes.GetLimit();
136         result r = CheckBufferInput(inBufSize, byteIndex, byteCount);
137         SysTryReturn(NID_TEXT, (!IsFailed(r)), r, r, "[%s] Input validation failed", GetErrorMessage(r));
138
139         byte lastByte = 0;
140         r = bytes.GetByte(byteIndex + byteCount - 1, lastByte);
141         if (!IsFailed(r))
142         {
143                 if (lastByte == '\0')
144                 {
145                         byteCount--;
146                 }
147         }
148
149         r = __pDecoder->GetCharCount((bytes.GetPointer() + byteIndex), byteCount, charCount);
150
151         if (charCount < 0)
152         {
153                 charCount = 0;
154         }
155
156         return r;
157 }
158
159 WcharBuffer*
160 _DecoderImpl::GetCharsN(const ByteBuffer& bytes, bool flush) const
161 {
162         SysAssertf(__pDecoder != null, "Not yet constructed! Construct() should be called before use.");
163
164         WcharBuffer* pBuffer = null;
165         int srcLength = 0;
166         result r = GetBufferSize(bytes, srcLength);
167         SysTryReturn(NID_TEXT, (!IsFailed(r)), null, r, "[%s] Input validation failed", GetErrorMessage(r));
168
169         r = Decode(bytes.GetPointer(), srcLength, pBuffer, 0, flush);
170
171         SetLastResult(r);
172         return pBuffer;
173 }
174
175 WcharBuffer*
176 _DecoderImpl::GetCharsN(const ByteBuffer& bytes, int byteIndex, int byteCount, bool flush) const
177 {
178         SysAssertf(__pDecoder != null, "Not yet constructed! Construct() should be called before use.");
179
180         WcharBuffer* pBuffer = null;
181         int srcLength = bytes.GetLimit();
182         result r = CheckBufferInput(srcLength, byteIndex, byteCount);
183         SysTryReturn(NID_TEXT, (!IsFailed(r)), null, r, "[%s] Input validation failed", GetErrorMessage(r));
184
185         r = Decode(bytes.GetPointer() + byteIndex, byteCount, pBuffer, 0, flush);
186
187         SetLastResult(r);
188         return pBuffer;
189 }
190
191 result
192 _DecoderImpl::GetBufferSize(const ByteBuffer& bytes, int& byteBufSize) const
193 {
194         // It is assumed that user has set limit properly
195         byteBufSize = bytes.GetLimit();
196
197         // Adjusting byteBufSize if bytes has null char at the end
198         byte lastByte = 0;
199         result r = bytes.GetByte(byteBufSize - 1, lastByte);
200         SysTryReturnResult(NID_TEXT, (!IsFailed(r)), E_INVALID_ARG, "[%s] Last byte check failed", GetErrorMessage(r));
201
202         if ((lastByte == '\0')and(byteBufSize > 1))
203         {
204                 byteBufSize -= 1;
205         }
206         SysTryReturnResult(NID_TEXT, (byteBufSize > 0), E_INVALID_ARG,
207                         "[%s] Invalid argument is used. byteBufSize [%d] is invalid.", GetErrorMessage(E_INVALID_ARG), byteBufSize);
208
209         return E_SUCCESS;
210 }
211
212 result
213 _DecoderImpl::CheckBufferInput(int inBufSize, int inIndex, int inCount) const
214 {
215         SysTryReturnResult(NID_TEXT, (inIndex >= 0), E_INVALID_ARG,
216                                 "[%s] Invalid argument is used. inIndex(%d) cannot be negative.", GetErrorMessage(E_INVALID_ARG), inIndex);
217         SysTryReturnResult(NID_TEXT, (inCount >= 0), E_INVALID_ARG,
218                                 "[%s] Invalid argument is used. inCount(%d) cannot be negative.", GetErrorMessage(E_INVALID_ARG), inCount);
219         SysTryReturnResult(NID_TEXT, (inBufSize > 0), E_INVALID_ARG,
220                                 "[%s] Invalid argument is used. inBufSize(%d) cannot be negative.", GetErrorMessage(E_INVALID_ARG), inBufSize);
221
222         SysTryReturnResult(NID_TEXT, (inBufSize > inIndex), E_OUT_OF_RANGE,
223                                 "[%s] inIndex(%d) is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE), inIndex);
224         SysTryReturnResult(NID_TEXT, (inBufSize >= inCount), E_OUT_OF_RANGE,
225                                 "[%s] inCount(%d) is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE), inCount);
226         SysTryReturnResult(NID_TEXT, (inBufSize >= (inIndex + inCount)), E_UNDERFLOW,
227                         "[%s] sum of the length of the inIndex(%d) and inCount(%d) is greater than inBufSize(%d).",
228                         GetErrorMessage(E_UNDERFLOW), inIndex, inCount, inBufSize);
229         return E_SUCCESS;
230 }
231
232 } } // Tizen::Text