Tizen 2.1 base
[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         r = GetLastResult();
101         SysTryReturn(NID_WEB_JSON, pText.get(), r, r, "[%s] Propagating.", GetErrorMessage(r));
102
103         int charCount = strlen(pText.get());
104         charCount = (charCount <= bufferLength) ? charCount : bufferLength;
105         SysLog(NID_WEB_JSON, "[%d] characters written to given buffer", charCount);
106         memcpy(pBuffer, pText.get(), charCount);
107
108         return r;
109 }
110
111
112 result
113 _JsonWriterImpl::Compose(const IJsonValue* pValue, ByteBuffer& buffer)
114 {
115         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_DATA, "Invalid Input parameter.");
116
117         String output;
118         result r = ConvertIJsonToString(const_cast<IJsonValue*>(pValue), output);
119         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
120
121         unique_ptr<ByteBuffer> pByteBuf(StringUtil::StringToUtf8N(output));
122         r = GetLastResult();
123         SysTryReturn(NID_WEB_JSON, pByteBuf.get(), r, r, "[%s] Propagating.", GetErrorMessage(r));
124
125         if (buffer.GetPointer())
126         {
127                 int givenCapacity = buffer.GetCapacity();
128                 int requiredCapacity = pByteBuf->GetCapacity();
129
130                 if (givenCapacity < requiredCapacity)
131                 {
132                         r = buffer.ExpandCapacity(requiredCapacity);
133                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
134                 }
135
136                 buffer.Clear();
137                 r = buffer.CopyFrom(*pByteBuf);
138                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
139         }
140         else
141         {
142                 r = buffer.Construct(*pByteBuf);
143                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
144         }
145
146         return r;
147 }
148
149
150 result
151 _JsonWriterImpl::ConvertIJsonToString(IJsonValue* pValue, String& outString)
152 {
153         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_ARG, "input JsonValue pointer is null");
154
155         result r = E_SUCCESS;
156
157         switch (pValue->GetType())
158         {
159         case JSON_TYPE_OBJECT:
160                 {
161                         outString.Append(OBJECT_BEGIN);
162
163                         const String* pKey = null;
164                         IJsonValue* pObjectValue = null;
165                         JsonObject* pObject = static_cast<JsonObject*>(pValue);
166
167                         unique_ptr<JsonMapEnumerator> pMapEnum(pObject->GetMapEnumeratorN());
168                         r = GetLastResult();
169                         SysTryReturn(NID_WEB_JSON, pMapEnum.get(), r, r, "[%s] Propagating.", GetErrorMessage(r));
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