Use insert() instead of std::copy()
[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   std::unique_ptr<gchar, decltype(g_free)*> json_auto(json, g_free);
122   json_ = json;
123   return json_;
124 }
125
126 void Json::OnJsonObjectMember(JsonObject* object, const char* key,
127   JsonNode* node, gpointer user_data) {
128   auto* b = static_cast<Bundle*>(user_data);
129   KeyInfo* key_info;
130   JsonNodeType node_type = JSON_NODE_TYPE(node);
131   if (node_type == JSON_NODE_ARRAY) {
132     JsonArray* json_arr = json_node_get_array(node);
133     if (json_arr == nullptr)
134       return;
135
136     std::vector<std::vector<unsigned char>> values;
137     guint len = json_array_get_length(json_arr);
138     for (guint i = 0; i < len; ++i) {
139       auto* val = json_array_get_string_element(json_arr, i);
140       if (val == nullptr)
141         val = "";
142
143       auto* p = reinterpret_cast<unsigned char*>(const_cast<char*>(val));
144       std::vector<unsigned char> value(p, p + (strlen(val) + 1));
145       values.push_back(std::move(value));
146     }
147
148     try {
149       key_info = new KeyInfo(Bundle::Type::StringArray, key, std::move(values));
150     } catch (const Exception& e) {
151       _E("Error(%d)", e.GetErrorCode());
152       return;
153     } catch (const std::bad_alloc& ba) {
154       _E("bad alloc exception");
155       return;
156     }
157   } else {
158     auto* val = json_node_get_string(node);
159     if (val == nullptr)
160       val = "";
161
162     auto* p = reinterpret_cast<unsigned char*>(const_cast<char*>(val));
163     std::vector<unsigned char> value(p, p + (strlen(val) + 1));
164
165     try {
166       key_info = new KeyInfo(Bundle::Type::String, key, std::move(value));
167     } catch (const Exception& e) {
168       _E("Error(%d)", e.GetErrorCode());
169       return;
170     } catch (const std::bad_alloc& ba) {
171       _E("bad alloc exception");
172       return;
173     }
174   }
175
176   try {
177     b->Add(std::shared_ptr<KeyInfo>(key_info));
178   } catch (const Exception& e) {
179     _W("Add() is failed. error(%d)", e.GetErrorCode());
180     return;
181   }
182 }
183
184 }  // namespace internal
185 }  // namespace tizen_base