Refactor Bundle
[platform/core/base/bundle.git] / src / json-internal.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
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 #include "exception-internal.h"
18 #include "json-internal.h"
19
20 namespace tizen_base {
21 namespace internal {
22
23 Json::Json(std::string json) : json_(std::move(json)) {
24 }
25
26 Json::Json(Bundle* b) : b_(b) {
27 }
28
29 Json::~Json() = default;
30
31 Bundle* Json::ToBundle() {
32   if (json_.empty())
33     return nullptr;
34
35   JsonParser* parser = json_parser_new();
36   if (parser == nullptr)
37     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
38
39   std::unique_ptr<JsonParser, decltype(g_object_unref)*> parser_ptr(parser,
40       g_object_unref);
41
42   GError* error = nullptr;
43   json_parser_load_from_data(parser, json_.c_str(), json_.length(), &error);
44   if (error) {
45     g_error_free(error);
46     THROW(BUNDLE_ERROR_INVALID_PARAMETER);
47   }
48
49   JsonNode* root = json_parser_get_root(parser);
50   if (root == nullptr)
51     THROW(BUNDLE_ERROR_INVALID_PARAMETER);
52
53   JsonObject* root_obj = json_node_get_object(root);
54   if (root_obj == nullptr)
55     THROW(BUNDLE_ERROR_INVALID_PARAMETER);
56
57   Bundle* b = new (std::nothrow) Bundle();
58   if (b == nullptr)
59     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
60
61   json_object_foreach_member(root_obj, OnJsonObjectMember, b);
62
63   return b;
64 }
65
66 std::string Json::ToString() {
67   if (b_ == nullptr)
68     THROW(BUNDLE_ERROR_INVALID_PARAMETER);
69
70   JsonObject* object = json_object_new();
71   if (object == nullptr)
72     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
73
74   std::unique_ptr<JsonObject, decltype(json_object_unref)*> object_ptr(object,
75       json_object_unref);
76
77   for (const auto& kv : b_->GetMap()) {
78     auto& key_info = kv.second;
79     if (key_info->GetType() == Bundle::Type::StringArray) {
80       JsonArray* json_arr = json_array_new();
81       if (json_arr == nullptr)
82         THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
83
84       for (const auto& v : key_info->GetValues()) {
85         json_array_add_string_element(json_arr,
86             const_cast<const char*>(reinterpret_cast<char*>(v.get())));
87       }
88
89       json_object_set_array_member(object, key_info->GetKey().c_str(),
90           json_arr);
91     } else {
92       json_object_set_string_member(object, key_info->GetKey().c_str(),
93           const_cast<const char*>(
94             reinterpret_cast<char*>(
95               key_info->GetValues()[0].get())));
96     }
97   }
98
99   JsonNode* node = json_node_new(JSON_NODE_OBJECT);
100   if (node == nullptr)
101     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
102
103   std::unique_ptr<JsonNode, decltype(json_node_free)*> node_ptr(node,
104       json_node_free);
105
106   json_node_set_object(node, object);
107
108   JsonGenerator* generator = json_generator_new();
109   if (generator == nullptr)
110     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
111
112   std::unique_ptr<JsonGenerator, decltype(g_object_unref)*> generator_ptr(
113       generator, g_object_unref);
114
115   json_generator_set_root(generator, node);
116   gsize length = 0;
117   gchar* json = json_generator_to_data(generator, &length);
118   if (json == nullptr)
119     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
120
121   json_ = json;
122   return json_;
123 }
124
125 void Json::OnJsonObjectMember(JsonObject* object, const char* key,
126   JsonNode* node, gpointer user_data) {
127   auto* b = static_cast<Bundle*>(user_data);
128   std::shared_ptr<KeyInfo> key_info;
129   JsonNodeType node_type = JSON_NODE_TYPE(node);
130   if (node_type == JSON_NODE_ARRAY) {
131     JsonArray* json_arr = json_node_get_array(node);
132     if (json_arr == nullptr)
133       return;
134
135     std::vector<std::vector<unsigned char>> values;
136     guint len = json_array_get_length(json_arr);
137     for (guint i = 0; i < len; ++i) {
138       auto* val = json_array_get_string_element(json_arr, i);
139       auto* p = reinterpret_cast<unsigned char*>(const_cast<char*>(val));
140       std::vector<unsigned char> value;
141       std::copy(p, p + (strlen(val) + 1), std::back_inserter(value));
142       values.push_back(value);
143     }
144     key_info.reset(
145         new (std::nothrow) KeyInfo(Bundle::Type::StringArray, key, values));
146   } else {
147     auto* val = json_node_get_string(node);
148     if (val == nullptr)
149       return;
150     auto* p = reinterpret_cast<unsigned char*>(const_cast<char*>(val));
151     std::vector<unsigned char> value;
152     std::copy(p, p + (strlen(val) + 1), std::back_inserter(value));
153     key_info.reset(
154         new (std::nothrow) KeyInfo(Bundle::Type::String, key, value));
155   }
156
157   if (key_info.get() == nullptr) {
158     _E("Out of memory");
159     return;
160   }
161
162   try {
163     b->Add(key_info);
164   } catch (Exception& e) {
165     _W("Add() is failed. error(%d)", e.GetErrorCode());
166     return;
167   }
168 }
169
170 }  // namespace internal
171 }  // namespace tizen_base