integrate code from master to tizen_2.1
[platform/framework/native/json.git] / src / FWebJson_JsonWriterImpl.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                FWebJson_JsonWriterImpl.cpp
20  * @brief               The file contains the definition of _JsonWriterImpl class.
21  *
22  * This file contains the definition of _JsonWriterImpl class.
23  */
24 #include <new>
25 #include <unique_ptr.h>
26 #include <FBaseByteBuffer.h>
27 #include <FBaseColIEnumeratorT.h>
28 #include <FBaseColIMapEnumeratorT.h>
29 #include <FBaseSysLog.h>
30 #include <FBaseString.h>
31 #include <FBaseUtilMath.h>
32 #include <FBaseUtilStringUtil.h>
33 #include <FIoFile.h>
34 #include <FWebJsonIJsonValue.h>
35 #include <FWebJsonJsonArray.h>
36 #include <FWebJsonJsonBool.h>
37 #include <FWebJsonJsonNull.h>
38 #include <FWebJsonJsonNumber.h>
39 #include <FWebJsonJsonObject.h>
40 #include <FWebJsonJsonString.h>
41 #include <FBase_StringConverter.h>
42 #include "FWebJson_JsonWriterImpl.h"
43 #include "FWebJson_JsonUtils.h"
44
45
46 using namespace std;
47 using namespace Tizen::Base;
48 using namespace Tizen::Base::Collection;
49 using namespace Tizen::Base::Utility;
50 using namespace Tizen::Io;
51
52
53 namespace Tizen { namespace Web { namespace Json
54 {
55
56
57 static const char COMMA = ',';
58 static const char QUOTE = '\"';
59 static const char COLON = ':';
60 static const char OBJECT_BEGIN = '{';
61 static const char OBJECT_END = '}';
62 static const char ARRAY_BEGIN = '[';
63 static const char ARRAY_END = ']';
64
65
66 result
67 _JsonWriterImpl::Compose(const IJsonValue* pValue, String& filePath)
68 {
69         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_DATA, "There is no data in IJsonValue.");
70
71         result r = E_SUCCESS;
72         File file;
73         String output;
74
75         r = ConvertIJsonToString(const_cast<IJsonValue*>(pValue), output);
76         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
77
78         SysLog(NID_WEB_JSON, "file path: [%ls]", filePath.GetPointer());
79         r = file.Construct(filePath, "w+");
80         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
81
82         r = file.Write(output);
83         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
84
85         return r;
86 }
87
88
89 result
90 _JsonWriterImpl::Compose(const IJsonValue* pValue, void* pBuffer, int bufferLength)
91 {
92         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_DATA, "Invalid Input parameter.");
93         SysTryReturnResult(NID_WEB_JSON, pBuffer && bufferLength >= 0, E_INVALID_ARG, "Invalid buffer parameter.");
94
95         String output;
96         result r = ConvertIJsonToString(const_cast<IJsonValue*>(pValue), output);
97         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
98
99         unique_ptr<char[]> pText(_StringConverter::CopyToCharArrayN(output));
100         SysTryReturn(NID_WEB_JSON, pText.get(), GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
101
102         int charCount = strlen(pText.get());
103         charCount = (charCount <= bufferLength) ? charCount : bufferLength;
104         SysLog(NID_WEB_JSON, "[%d] characters written to given buffer", charCount);
105         memcpy(pBuffer, pText.get(), charCount);
106
107         return r;
108 }
109
110
111 result
112 _JsonWriterImpl::Compose(const IJsonValue* pValue, ByteBuffer& buffer)
113 {
114         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_DATA, "Invalid Input parameter.");
115
116         String output;
117         result r = ConvertIJsonToString(const_cast<IJsonValue*>(pValue), output);
118         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
119
120         unique_ptr<ByteBuffer> pByteBuf(StringUtil::StringToUtf8N(output));
121         SysTryReturn(NID_WEB_JSON, pByteBuf.get(), GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
122
123         if (buffer.GetPointer())
124         {
125                 int givenCapacity = buffer.GetCapacity();
126                 int requiredCapacity = pByteBuf->GetCapacity();
127
128                 if (givenCapacity < requiredCapacity)
129                 {
130                         r = buffer.ExpandCapacity(requiredCapacity);
131                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
132                 }
133
134                 buffer.Clear();
135
136                 r = buffer.CopyFrom(*pByteBuf);
137                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
138
139                 buffer.Flip();
140         }
141         else
142         {
143                 r = buffer.Construct(*pByteBuf);
144                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
145         }
146
147         return r;
148 }
149
150
151 result
152 _JsonWriterImpl::ConvertIJsonToString(IJsonValue* pValue, String& outString)
153 {
154         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_ARG, "input JsonValue pointer is null");
155
156         result r = E_SUCCESS;
157
158         switch (pValue->GetType())
159         {
160         case JSON_TYPE_OBJECT:
161                 {
162                         outString.Append(OBJECT_BEGIN);
163
164                         const String* pKey = null;
165                         IJsonValue* pObjectValue = null;
166                         JsonObject* pObject = static_cast<JsonObject*>(pValue);
167
168                         unique_ptr<JsonMapEnumerator> pMapEnum(pObject->GetMapEnumeratorN());
169                         SysTryReturn(NID_WEB_JSON, pMapEnum.get(), GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
170
171                         int itemCount = pObject->GetCount();
172
173                         while (pMapEnum->MoveNext() == E_SUCCESS)
174                         {
175                                 r = pMapEnum->GetKey(pKey);
176                                 SysTryReturn(NID_WEB_JSON, pKey, r, r, "[%s]Propagating.", GetErrorMessage(r));
177
178                                 String escString;
179                                 r = ToEscString(*pKey, escString);
180                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
181
182                                 outString.Append(QUOTE);
183                                 outString.Append(escString);
184                                 outString.Append(QUOTE);
185
186                                 r = pMapEnum->GetValue(pObjectValue);
187                                 SysTryReturn(NID_WEB_JSON, pObjectValue, r, r, "[%s] Propagating.", GetErrorMessage(r));
188
189                                 outString.Append(COLON);
190                                 r = ConvertIJsonToString(pObjectValue, outString);
191                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
192
193                                 if (--itemCount)
194                                 {
195                                         outString.Append(COMMA);
196                                 }
197                         }
198                         outString.Append(OBJECT_END);
199                 }
200                 break;
201
202         case JSON_TYPE_ARRAY:
203                 {
204                         outString.Append(ARRAY_BEGIN);
205
206                         IJsonValue* pArrayValue = null;
207                         JsonArray* pArray = static_cast<JsonArray*>(pValue);
208                         int itemCount = pArray->GetCount() - 1;
209
210                         for (int index = 0; index <= itemCount; index++)
211                         {
212                                 r = pArray->GetAt(index, pArrayValue);
213                                 SysTryReturn(NID_WEB_JSON, pArrayValue, r, r, "[%s] Propagating.", GetErrorMessage(r));
214
215                                 r = ConvertIJsonToString(pArrayValue, outString);
216                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
217
218                                 if (index != itemCount)
219                                 {
220                                         outString.Append(COMMA);
221                                 }
222                         }
223
224                         outString.Append(ARRAY_END);
225                 }
226                 break;
227
228         case JSON_TYPE_STRING:
229                 {
230                         String escString;
231                         r = ToEscString(*(static_cast<JsonString*>(pValue)), escString);
232                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
233
234                         outString.Append(QUOTE);
235                         outString.Append(escString);
236                         outString.Append(QUOTE);
237                 }
238                 break;
239
240         case JSON_TYPE_NUMBER:
241                 {
242                         String out;
243                         double val1 = static_cast<JsonNumber*>(pValue)->ToDouble();
244                         double val2 = Math::Floor(val1);
245
246                         r = (Double::Compare(val1, val2) == 0) ? out.Format(15, L"%g", val1) : out.Format(15, L"%f", val1);
247                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
248
249                         outString.Append(out);
250                 }
251                 break;
252
253         case JSON_TYPE_BOOL:
254                 outString.Append((static_cast<JsonBool*>(pValue))->ToString());
255                 break;
256
257         case JSON_TYPE_NULL:
258                 outString.Append((static_cast<JsonNull*>(pValue))->ToString());
259                 break;
260
261         default:
262                 SysLogException(NID_WEB_JSON, E_INVALID_DATA, "[E_INVALID_DATA] reached default of ConvertIJsonToString");
263                 return E_INVALID_DATA;
264         }
265
266         return r;
267 }
268
269
270 result
271 _JsonWriterImpl::ToEscString(const String& unEscStr, String& escString)
272 {
273         const wchar_t* pUnEscBuf = unEscStr.GetPointer();
274         SysTryReturn(NID_WEB_JSON, pUnEscBuf, GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
275
276         int length = unEscStr.GetLength();
277
278         for (int i = 0; i < length; i++)
279         {
280                 switch (pUnEscBuf[i])
281                 {
282                 case '\\':
283                         escString.Append(L"\\\\");
284                         break;
285                 case '\"':
286                         escString.Append(L"\\\"");
287                         break;
288                 case '/':
289                         escString.Append(L"\\/");
290                         break;
291                 case '\b':
292                         escString.Append(L"\\b");
293                         break;
294                 case '\f':
295                         escString.Append(L"\\f");
296                         break;
297                 case '\n':
298                         escString.Append(L"\\n");
299                         break;
300                 case '\r':
301                         escString.Append(L"\\r");
302                         break;
303                 case '\t':
304                         escString.Append(L"\\t");
305                         break;
306                 default:
307                         if (pUnEscBuf[i] < 0x80)
308                         {
309                                 escString.Append(pUnEscBuf[i]);
310                         }
311                         else
312                         {
313                                 String uni;
314                                 uni.Format(7, L"\\u%04x", pUnEscBuf[i]);
315                                 escString.Append(uni);
316                         }
317                         break;
318                 }
319         }
320
321         return E_SUCCESS;
322 }
323
324
325 }}} // Tizen::Web::Json