Fix wrong implementation about encoding & decoding bundle raw
[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   : impl_(new Impl(this, handle, std::move(name))) {
87 }
88
89 Bundle::KeyInfo::~KeyInfo() {
90 }
91
92 Bundle::KeyInfo::Impl::~Impl() = default;
93 Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent,
94                             const bundle_keyval_t* handle,
95                             std::string name)
96   : handle_(handle), name_(name), parent_(parent) {
97 }
98
99 Bundle::KeyInfo::Impl::Impl(Bundle::KeyInfo* parent) : parent_(parent) {
100 }
101
102 Bundle::KeyInfo::KeyInfo(const KeyInfo& k)
103     : impl_(new Impl(this)) {
104   impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
105   impl_->name_ = k.impl_->name_;
106   if (impl_->handle_ == nullptr)
107     throw std::bad_alloc();
108 }
109
110 Bundle::KeyInfo& Bundle::KeyInfo::operator = (const Bundle::KeyInfo& k) {
111   if (this != &k) {
112     impl_->handle_ = bundle_keyval_dup(k.impl_->handle_);
113     impl_->name_ = k.impl_->name_;
114     if (impl_->handle_ == nullptr)
115       throw std::bad_alloc();
116   }
117   return *this;
118 }
119
120 Bundle::KeyInfo::KeyInfo(Bundle::KeyInfo&& k) noexcept {
121   impl_ = std::unique_ptr<Impl>(new Impl(this));
122   impl_->handle_ = k.impl_->handle_;
123   impl_->name_ = k.impl_->name_;
124   k.impl_->handle_ = nullptr;
125   k.impl_->name_ = "";
126 }
127
128 Bundle::KeyInfo& Bundle::KeyInfo::operator = (Bundle::KeyInfo&& k) noexcept {
129   if (this != &k) {
130     impl_->handle_ = k.impl_->handle_;
131     impl_->name_ = k.impl_->name_;
132     k.impl_->handle_ = nullptr;
133     k.impl_->name_ = "";
134   }
135   return *this;
136 }
137
138 bundle_type Bundle::KeyInfo::GetType() const {
139   return static_cast<bundle_type>(
140       bundle_keyval_get_type(const_cast<bundle_keyval_t*>(impl_->handle_)));
141 }
142
143 bool Bundle::KeyInfo::IsArray() const {
144   return bundle_keyval_type_is_array(const_cast<bundle_keyval_t*>(
145       impl_->handle_));
146 }
147
148 const std::string& Bundle::KeyInfo::GetName() const {
149   return impl_->name_;
150 }
151
152 Bundle& Bundle::operator = (const Bundle& b) {
153   if (this != &b) {
154     impl_->handle_ = bundle_dup(b.impl_->handle_);
155     if (impl_->handle_ == nullptr)
156       throw std::bad_alloc();
157   }
158   return *this;
159 }
160
161 Bundle::Bundle(Bundle&& b) noexcept {
162   impl_ = std::move(b.impl_);
163   impl_->parent_ = this;
164 }
165
166 Bundle& Bundle::operator = (Bundle&& b) noexcept {
167   if (this != &b) {
168     impl_->handle_ = b.impl_->handle_;
169     b.impl_->handle_ = nullptr;
170   }
171   return *this;
172 }
173
174 bool Bundle::IsEmpty() const noexcept {
175   return (bundle_get_count(impl_->handle_) == 0) ? true : false;
176 }
177
178 std::vector<Bundle::KeyInfo> Bundle::GetKeys() {
179   std::vector<Bundle::KeyInfo> v;
180
181   bundle_foreach(impl_->handle_, [](const char *key, const int type,
182       const bundle_keyval_t *kv, void *user_data) {
183         auto* v = static_cast<std::vector<KeyInfo>*>(user_data);
184         v->emplace_back(kv, key);
185       }, &v);
186
187   return v;
188 }
189
190 int Bundle::Add(const std::string& key, const std::string& val) {
191   int ret = bundle_add_str(impl_->handle_, key.c_str(), val.c_str());
192   if (ret != BUNDLE_ERROR_NONE)
193     LOGE("Add fail key(%s), val(%s), ret(%d)", key.c_str(), val.c_str(), ret);
194   return ret;
195 }
196
197 int Bundle::Add(const std::string& key, const std::vector<std::string>& val) {
198   std::vector<const char*> v;
199   for (auto& i : val) {
200     v.push_back(i.c_str());
201   }
202
203   int ret = bundle_add_str_array(
204     impl_->handle_, key.c_str(), v.data(), v.size());
205   if (ret != BUNDLE_ERROR_NONE)
206     LOGE("Add fail key(%s), ret(%d)", key.c_str(), ret);
207
208   return ret;
209 }
210
211 int Bundle::Add(const std::string& key, const std::vector<unsigned char>& val) {
212   int ret = bundle_add_byte(impl_->handle_, key.c_str(), val.data(), val.size());
213   if (ret != BUNDLE_ERROR_NONE)
214     LOGE("Add fail key(%s), ret(%d)", key.c_str(), ret);
215   return ret;
216 }
217
218 int Bundle::Delete(const std::string& key) {
219   int ret = bundle_del(impl_->handle_, key.c_str());
220   if (ret != BUNDLE_ERROR_NONE)
221     LOGE("Add fail key(%s), ret(%d)", key.c_str(), ret);
222   return ret;
223 }
224
225 std::string Bundle::GetString(const std::string& key) const {
226   char* str = nullptr;
227   bundle_get_str(impl_->handle_, key.c_str(), &str);
228
229   if (!str)
230     return "";
231
232   return std::string(str);
233 }
234
235 std::vector<std::string> Bundle::GetStringArray(const std::string& key) const {
236   std::vector<std::string> v;
237
238   const char** str_array = nullptr;
239   int len = 0;
240
241   str_array = bundle_get_str_array(impl_->handle_, key.c_str(), &len);
242
243   for (int i = 0; i < len; i++) {
244     v.emplace_back(str_array[i]);
245   }
246
247   return v;
248 }
249
250 std::vector<unsigned char> Bundle::GetByte(const std::string& key) const {
251   size_t size;
252   unsigned char* bytes = nullptr;
253   int ret = bundle_get_byte(impl_->handle_, key.c_str(),
254       reinterpret_cast<void**>(&bytes), &size);
255   if (ret != BUNDLE_ERROR_NONE) {
256     LOGE("bundle_get_byte() is failed");
257     return {};
258   }
259
260   return std::vector<unsigned char>(bytes, bytes + size);
261 }
262
263 Bundle::BundleRaw Bundle::ToRaw(bool base64) {
264   bundle_raw* raw = nullptr;
265   int len = 0;
266   int ret;
267   if (base64)
268     ret = bundle_encode(impl_->handle_, &raw, &len);
269   else
270     ret = bundle_encode_raw(impl_->handle_, &raw, &len);
271   if (raw == nullptr) {
272     LOGE("Fail to encode data (%d)", ret);
273     throw std::bad_alloc();
274   }
275
276   return BundleRaw(
277       std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free), len);
278 }
279
280 int Bundle::GetCount() const {
281   return bundle_get_count(impl_->handle_);
282 }
283
284 bundle_type Bundle::GetType(const std::string& key) const {
285   return static_cast<bundle_type>(bundle_get_type(impl_->handle_, key.c_str()));
286 }
287
288 bundle* Bundle::GetHandle() const {
289   return impl_->handle_;
290 }
291
292 bundle* Bundle::Detach() {
293   auto* h = impl_->handle_;
294   impl_->handle_ = nullptr;
295   return h;
296 }
297
298 }  // namespace tizen_base