4cc9808f4c28b2c636fba6130df19cbc3cc30fd9
[platform/core/base/bundle.git] / src / bundle_cpp.cc
1 /*
2  * Copyright (c) 2019 - 2020 Samsung Electronics Co., Ltd.
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 <memory>
18
19 #include "bundle_cpp.h"
20 #include "bundle_cpp_implementation.h"
21 #include "bundle_internal.h"
22 #include "log-private.h"
23
24 namespace tizen_base {
25 Bundle::Impl::Impl(Bundle* parent, bool copy, bool own)
26   : copy_(copy), own_(own), parent_(parent) {
27 }
28
29 Bundle::Impl::Impl(Bundle* parent) : parent_(parent) {
30 }
31
32 Bundle::Impl::~Impl() = default;
33
34 Bundle::Bundle()
35   : impl_(new Impl(this)) {
36   impl_->handle_ = bundle_create();
37   if (impl_->handle_ == nullptr)
38     throw std::bad_alloc();
39 }
40
41 Bundle::Bundle(BundleRaw raw, bool base64)
42   : impl_(new Impl(this)) {
43   if (base64)
44     impl_->handle_ = bundle_decode(raw.first.get(), raw.second);
45   else
46     impl_->handle_ = bundle_decode_raw(raw.first.get(), raw.second);
47   if (impl_->handle_ == nullptr)
48     throw std::bad_alloc();
49 }
50
51 Bundle::Bundle(const std::string& raw)
52   : impl_(new Impl(this)) {
53   impl_->handle_ = bundle_decode(reinterpret_cast<const bundle_raw*>(
54       raw.c_str()), raw.length());
55   if (impl_->handle_ == nullptr)
56     throw std::bad_alloc();
57 }
58
59 Bundle::Bundle(bundle* b, bool copy, bool own)
60   : impl_(new Impl(this, copy, own)) {
61   if (b == nullptr)
62     throw std::invalid_argument("b cannot be null");
63
64   if (!impl_->copy_) {
65     impl_->handle_ = b;
66   } else {
67     impl_->handle_ = bundle_dup(b);
68     if (impl_->handle_ == nullptr)
69       throw std::bad_alloc();
70   }
71 }
72
73 Bundle::~Bundle() {
74   if (impl_ && impl_->handle_ && (impl_->own_ || impl_->copy_))
75     bundle_free(impl_->handle_);
76 }
77
78 Bundle::Bundle(const Bundle& b)
79   : impl_(new Impl(this)) {
80   impl_->handle_ = bundle_dup(b.impl_->handle_);
81   if (impl_->handle_ == nullptr)
82     throw std::bad_alloc();
83 }
84
85 Bundle::KeyInfo::KeyInfo(const bundle_keyval_t* handle, std::string name,
86                          bool own)
87   : impl_(new Impl(this, handle, std::move(name), own)) {
88 }
89
90 Bundle::KeyInfo::~KeyInfo() {
91   if (impl_ && impl_->handle_ && impl_->own_)
92     bundle_keyval_free(const_cast<bundle_keyval_t*>(impl_->handle_));
93 }
94
95 Bundle::KeyInfo::Impl::~Impl() = default;
96
97 Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent,
98                             const bundle_keyval_t* handle,
99                             std::string name,
100                             bool own)
101   : handle_(handle), name_(name), parent_(parent), own_(own) {
102 }
103
104 Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent) : parent_(parent) {
105 }
106
107 Bundle::KeyInfo::KeyInfo(const KeyInfo& k)
108     : impl_(new Impl(this)) {
109   impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
110   impl_->name_ = k.impl_->name_;
111   if (impl_->handle_ == nullptr)
112     throw std::bad_alloc();
113 }
114
115 Bundle::KeyInfo& Bundle::KeyInfo::operator = (const Bundle::KeyInfo& k) {
116   if (this != &k) {
117     if (impl_->handle_ && impl_->own_)
118       bundle_keyval_free(const_cast<bundle_keyval_t*>(impl_->handle_));
119
120     impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
121     impl_->name_ = k.impl_->name_;
122     if (impl_->handle_ == nullptr)
123       throw std::bad_alloc();
124
125     impl_->own_ = true;
126   }
127   return *this;
128 }
129
130 Bundle::KeyInfo::KeyInfo(Bundle::KeyInfo&& k) noexcept {
131   impl_ = std::move(k.impl_);
132   impl_->parent_ = this;
133 }
134
135 Bundle::KeyInfo& Bundle::KeyInfo::operator = (Bundle::KeyInfo&& k) noexcept {
136   if (this != &k) {
137     if (impl_->handle_ && impl_->own_)
138       bundle_keyval_free(const_cast<bundle_keyval_t*>(impl_->handle_));
139
140     impl_->handle_ = k.impl_->handle_;
141     impl_->name_ = k.impl_->name_;
142     impl_->own_ = k.impl_->own_;
143     k.impl_->handle_ = nullptr;
144     k.impl_->name_ = "";
145     k.impl_->own_ = false;
146   }
147   return *this;
148 }
149
150 bundle_type Bundle::KeyInfo::GetType() const {
151   return static_cast<bundle_type>(
152       bundle_keyval_get_type(const_cast<bundle_keyval_t*>(impl_->handle_)));
153 }
154
155 bool Bundle::KeyInfo::IsArray() const {
156   return bundle_keyval_type_is_array(const_cast<bundle_keyval_t*>(
157       impl_->handle_));
158 }
159
160 const std::string& Bundle::KeyInfo::GetName() const {
161   return impl_->name_;
162 }
163
164 Bundle& Bundle::operator = (const Bundle& b) {
165   if (this != &b) {
166     if (impl_->handle_ && (impl_->own_ || impl_->copy_))
167       bundle_free(impl_->handle_);
168
169     impl_->handle_ = bundle_dup(b.impl_->handle_);
170     if (impl_->handle_ == nullptr)
171       throw std::bad_alloc();
172
173     impl_->own_ = true;
174     impl_->copy_ = true;
175   }
176   return *this;
177 }
178
179 Bundle::Bundle(Bundle&& b) noexcept {
180   impl_ = std::move(b.impl_);
181   impl_->parent_ = this;
182 }
183
184 Bundle& Bundle::operator = (Bundle&& b) noexcept {
185   if (this != &b) {
186     if (impl_->handle_ && (impl_->own_ || impl_->copy_))
187       bundle_free(impl_->handle_);
188
189     impl_->handle_ = b.impl_->handle_;
190     b.impl_->handle_ = nullptr;
191     impl_->own_ = b.impl_->own_;
192     b.impl_->own_ = false;
193     impl_->copy_ = b.impl_->copy_;
194     b.impl_->copy_ = false;
195   }
196   return *this;
197 }
198
199 bool Bundle::IsEmpty() const noexcept {
200   return (bundle_get_count(impl_->handle_) == 0) ? true : false;
201 }
202
203 std::vector<Bundle::KeyInfo> Bundle::GetKeys() {
204   std::vector<Bundle::KeyInfo> v;
205
206   bundle_foreach(impl_->handle_, [](const char *key, const int type,
207       const bundle_keyval_t *kv, void *user_data) {
208         auto* v = static_cast<std::vector<KeyInfo>*>(user_data);
209         v->emplace_back(kv, key, false);
210       }, &v);
211
212   return v;
213 }
214
215 int Bundle::Add(const std::string& key, const std::string& val) {
216   int ret = bundle_add_str(impl_->handle_, key.c_str(), val.c_str());
217   if (ret != BUNDLE_ERROR_NONE)
218     LOGE("Add fail key(%s), val(%s), ret(%d)", key.c_str(), val.c_str(), ret);
219   return ret;
220 }
221
222 int Bundle::Add(const std::string& key, const std::vector<std::string>& val) {
223   std::vector<const char*> v;
224   for (auto& i : val) {
225     v.push_back(i.c_str());
226   }
227
228   int ret = bundle_add_str_array(
229     impl_->handle_, key.c_str(), v.data(), v.size());
230   if (ret != BUNDLE_ERROR_NONE)
231     LOGE("Add fail key(%s), ret(%d)", key.c_str(), ret);
232
233   return ret;
234 }
235
236 int Bundle::Add(const std::string& key, const std::vector<unsigned char>& val) {
237   int ret = bundle_add_byte(impl_->handle_, key.c_str(), val.data(), val.size());
238   if (ret != BUNDLE_ERROR_NONE)
239     LOGE("Add fail key(%s), ret(%d)", key.c_str(), ret);
240   return ret;
241 }
242
243 int Bundle::Delete(const std::string& key) {
244   int ret = bundle_del(impl_->handle_, key.c_str());
245   if (ret != BUNDLE_ERROR_NONE)
246     LOGE("Delete fail key(%s), ret(%d)", key.c_str(), ret);
247   return ret;
248 }
249
250 std::string Bundle::GetString(const std::string& key) const {
251   char* str = nullptr;
252   bundle_get_str(impl_->handle_, key.c_str(), &str);
253
254   if (!str)
255     return "";
256
257   return std::string(str);
258 }
259
260 std::vector<std::string> Bundle::GetStringArray(const std::string& key) const {
261   std::vector<std::string> v;
262
263   const char** str_array = nullptr;
264   int len = 0;
265
266   str_array = bundle_get_str_array(impl_->handle_, key.c_str(), &len);
267
268   for (int i = 0; i < len; i++) {
269     v.emplace_back(str_array[i]);
270   }
271
272   return v;
273 }
274
275 std::vector<unsigned char> Bundle::GetByte(const std::string& key) const {
276   size_t size;
277   unsigned char* bytes = nullptr;
278   int ret = bundle_get_byte(impl_->handle_, key.c_str(),
279       reinterpret_cast<void**>(&bytes), &size);
280   if (ret != BUNDLE_ERROR_NONE) {
281     LOGE("bundle_get_byte() is failed");
282     return {};
283   }
284
285   return std::vector<unsigned char>(bytes, bytes + size);
286 }
287
288 Bundle::BundleRaw Bundle::ToRaw(bool base64) {
289   bundle_raw* raw = nullptr;
290   int len = 0;
291   int ret;
292   if (base64)
293     ret = bundle_encode(impl_->handle_, &raw, &len);
294   else
295     ret = bundle_encode_raw(impl_->handle_, &raw, &len);
296   if (raw == nullptr) {
297     LOGE("Fail to encode data (%d)", ret);
298     throw std::bad_alloc();
299   }
300
301   return BundleRaw(
302       std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free), len);
303 }
304
305 int Bundle::GetCount() const {
306   return bundle_get_count(impl_->handle_);
307 }
308
309 bundle_type Bundle::GetType(const std::string& key) const {
310   return static_cast<bundle_type>(bundle_get_type(impl_->handle_, key.c_str()));
311 }
312
313 bundle* Bundle::GetHandle() const {
314   return impl_->handle_;
315 }
316
317 bundle* Bundle::Detach() {
318   auto* h = impl_->handle_;
319   impl_->handle_ = nullptr;
320   return h;
321 }
322
323 }  // namespace tizen_base