merge with master
[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
138                 r = buffer.CopyFrom(*pByteBuf);
139                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
140
141                 buffer.Flip();
142         }
143         else
144         {
145                 r = buffer.Construct(*pByteBuf);
146                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
147         }
148
149         return r;
150 }
151
152
153 result
154 _JsonWriterImpl::ConvertIJsonToString(IJsonValue* pValue, String& outString)
155 {
156         SysTryReturnResult(NID_WEB_JSON, pValue, E_INVALID_ARG, "input JsonValue pointer is null");
157
158         result r = E_SUCCESS;
159
160         switch (pValue->GetType())
161         {
162         case JSON_TYPE_OBJECT:
163                 {
164                         outString.Append(OBJECT_BEGIN);
165
166                         const String* pKey = null;
167                         IJsonValue* pObjectValue = null;
168                         JsonObject* pObject = static_cast<JsonObject*>(pValue);
169
170                         unique_ptr<JsonMapEnumerator> pMapEnum(pObject->GetMapEnumeratorN());
171                         r = GetLastResult();
172                         SysTryReturn(NID_WEB_JSON, pMapEnum.get(), r, r, "[%s] Propagating.", GetErrorMessage(r));
173
174                         int itemCount = pObject->GetCount();
175
176                         while (pMapEnum->MoveNext() == E_SUCCESS)
177                         {
178                                 r = pMapEnum->GetKey(pKey);
179                                 SysTryReturn(NID_WEB_JSON, pKey, r, r, "[%s]Propagating.", GetErrorMessage(r));
180
181                                 String escString;
182                                 r = ToEscString(*pKey, escString);
183                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
184
185                                 outString.Append(QUOTE);
186                                 outString.Append(escString);
187                                 outString.Append(QUOTE);
188
189                                 r = pMapEnum->GetValue(pObjectValue);
190                                 SysTryReturn(NID_WEB_JSON, pObjectValue, r, r, "[%s] Propagating.", GetErrorMessage(r));
191
192                                 outString.Append(COLON);
193                                 r = ConvertIJsonToString(pObjectValue, outString);
194                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
195
196                                 if (--itemCount)
197                                 {
198                                         outString.Append(COMMA);
199                                 }
200                         }
201                         outString.Append(OBJECT_END);
202                 }
203                 break;
204
205         case JSON_TYPE_ARRAY:
206                 {
207                         outString.Append(ARRAY_BEGIN);
208
209                         IJsonValue* pArrayValue = null;
210                         JsonArray* pArray = static_cast<JsonArray*>(pValue);
211                         int itemCount = pArray->GetCount() - 1;
212
213                         for (int index = 0; index <= itemCount; index++)
214                         {
215                                 r = pArray->GetAt(index, pArrayValue);
216                                 SysTryReturn(NID_WEB_JSON, pArrayValue, r, r, "[%s] Propagating.", GetErrorMessage(r));
217
218                                 r = ConvertIJsonToString(pArrayValue, outString);
219                                 SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
220
221                                 if (index != itemCount)
222                                 {
223                                         outString.Append(COMMA);
224                                 }
225                         }
226
227                         outString.Append(ARRAY_END);
228                 }
229                 break;
230
231         case JSON_TYPE_STRING:
232                 {
233                         String escString;
234                         r = ToEscString(*(static_cast<JsonString*>(pValue)), escString);
235                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
236
237                         outString.Append(QUOTE);
238                         outString.Append(escString);
239                         outString.Append(QUOTE);
240                 }
241                 break;
242
243         case JSON_TYPE_NUMBER:
244                 {
245                         String out;
246                         double val1 = static_cast<JsonNumber*>(pValue)->ToDouble();
247                         double val2 = Math::Floor(val1);
248
249                         r = (Double::Compare(val1, val2) == 0) ? out.Format(15, L"%g", val1) : out.Format(15, L"%f", val1);
250                         SysTryReturn(NID_WEB_JSON, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
251
252                         outString.Append(out);
253                 }
254                 break;
255
256         case JSON_TYPE_BOOL:
257                 outString.Append((static_cast<JsonBool*>(pValue))->ToString());
258                 break;
259
260         case JSON_TYPE_NULL:
261                 outString.Append((static_cast<JsonNull*>(pValue))->ToString());
262                 break;
263
264         default:
265                 SysLogException(NID_WEB_JSON, E_INVALID_DATA, "[E_INVALID_DATA] reached default of ConvertIJsonToString");
266                 return E_INVALID_DATA;
267         }
268
269         return r;
270 }
271
272
273 result
274 _JsonWriterImpl::ToEscString(const String& unEscStr, String& escString)
275 {
276         const wchar_t* pUnEscBuf = unEscStr.GetPointer();
277         SysTryReturn(NID_WEB_JSON, pUnEscBuf, GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
278
279         int length = unEscStr.GetLength();
280
281         for (int i = 0; i < length; i++)
282         {
283                 switch (pUnEscBuf[i])
284                 {
285                 case '\\':
286                         escString.Append(L"\\\\");
287                         break;
288                 case '\"':
289                         escString.Append(L"\\\"");
290                         break;
291                 case '/':
292                         escString.Append(L"\\/");
293                         break;
294                 case '\b':
295                         escString.Append(L"\\b");
296                         break;
297                 case '\f':
298                         escString.Append(L"\\f");
299                         break;
300                 case '\n':
301                         escString.Append(L"\\n");
302                         break;
303                 case '\r':
304                         escString.Append(L"\\r");
305                         break;
306                 case '\t':
307                         escString.Append(L"\\t");
308                         break;
309                 default:
310                         if (pUnEscBuf[i] < 0x80)
311                         {
312                                 escString.Append(pUnEscBuf[i]);
313                         }
314                         else
315                         {
316                                 String uni;
317                                 uni.Format(7, L"\\u%04x", pUnEscBuf[i]);
318                                 escString.Append(uni);
319                         }
320                         break;
321                 }
322         }
323
324         return E_SUCCESS;
325 }
326
327
328 }}} // Tizen::Web::Json