Add Parcel Library
[platform/core/base/bundle.git] / parcel / parcel.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 "include/bundle_cpp.h"
18 #include "parcel/common.hh"
19 #include "parcel/log_private.hh"
20 #include "parcel/parcel.hh"
21 #include "parcel/parcel_implementation.hh"
22 #include "parcel/parcelable.hh"
23
24 namespace tizen_base {
25
26 Parcel::Impl::Impl(Parcel* parent) : parent_(parent) {
27 }
28
29 Parcel::Impl::~Impl() = default;
30
31 void Parcel::Impl::Write(const void* buf, uint32_t size) {
32   auto* p = reinterpret_cast<const uint8_t*>(buf);
33   std::copy(p, p + size, std::back_inserter(data_));
34 }
35
36 int Parcel::Impl::Read(void* buf, uint32_t size) {
37   if (data_.size() == 0)
38     return TIZEN_ERROR_NO_DATA;
39
40   if (reader_ + size > data_.size())
41     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
42
43   auto* p = reinterpret_cast<uint8_t*>(buf);
44   std::copy(&data_[reader_], &data_[reader_] + size, p);
45   reader_ += size;
46   set_last_result(TIZEN_ERROR_NONE);
47   return TIZEN_ERROR_NONE;
48 }
49
50 const std::vector<uint8_t>& Parcel::Impl::GetRaw() {
51   return data_;
52 }
53
54 void Parcel::Impl::ResetReader() {
55   reader_ = 0;
56 }
57
58 void Parcel::Impl::Clear() {
59   data_.clear();
60   reader_ = 0;
61 }
62
63 void Parcel::Impl::Reset(const void* buf, uint32_t size) {
64   Clear();
65   Write(buf, size);
66 }
67
68 bool Parcel::Impl::IsEmpty() {
69   return data_.size() == 0;
70 }
71
72 void Parcel::Impl::WriteSize(uint32_t size) {
73   auto* p = reinterpret_cast<uint8_t*>(&size);
74   std::copy(p, p + sizeof(size), std::back_inserter(data_));
75 }
76
77 template <typename T>
78 void Parcel::Impl::Write(T d) {
79   WriteSize(sizeof(T));
80   auto* p = reinterpret_cast<uint8_t*>(&d);
81   std::copy(p, p + sizeof(T), std::back_inserter(data_));
82 }
83
84 int Parcel::Impl::ReadSize(uint32_t* size) {
85   if (data_.size() == 0)
86     return TIZEN_ERROR_NO_DATA;
87
88   if (reader_ + sizeof(uint32_t) > data_.size())
89     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
90
91   auto* p = reinterpret_cast<uint8_t*>(size);
92   std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p);
93   reader_ += sizeof(uint32_t);
94   return TIZEN_ERROR_NONE;
95 }
96
97 template <typename T>
98 int Parcel::Impl::Read(T* d) {
99   uint32_t size = 0;
100   int ret = ReadSize(&size);
101   if (ret != TIZEN_ERROR_NONE)
102     return ret;
103
104   if (size == 0 || size != sizeof(T))
105     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
106
107   if (reader_ + size > data_.size())
108     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
109
110   auto* p = reinterpret_cast<uint8_t*>(d);
111   std::copy(&data_[reader_], &data_[reader_] + size, p);
112   reader_ += size;
113   return TIZEN_ERROR_NONE;
114 }
115
116 Parcel::Parcel() : impl_(new Impl(this)) {
117 }
118
119 Parcel::Parcel(const void* buf, uint32_t size) : impl_(new Impl(this)) {
120   impl_->Write(buf, size);
121 }
122
123 Parcel::~Parcel() = default;
124
125 Parcel::Parcel(const Parcel& p)
126   : impl_(new Impl(this)) {
127   std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
128       std::back_inserter(impl_->data_));
129   impl_->reader_ = p.impl_->reader_;
130 }
131
132 Parcel& Parcel::operator = (const Parcel& p) {
133   if (this != &p) {
134     std::copy(p.impl_->data_.begin(), p.impl_->data_.end(),
135         std::back_inserter(impl_->data_));
136     impl_->reader_ = p.impl_->reader_;
137   }
138   return *this;
139 }
140
141 Parcel::Parcel(Parcel&& p) noexcept {
142   impl_ = std::move(p.impl_);
143   impl_->parent_ = this;
144 }
145
146 Parcel& Parcel::operator = (Parcel&& p) noexcept {
147   if (this != &p) {
148     impl_->data_ = std::move(p.impl_->data_);
149     impl_->reader_ = p.impl_->reader_;
150     p.impl_->reader_ = 0;
151   }
152   return *this;
153 }
154
155 bool Parcel::IsEmpty() const noexcept {
156   return impl_->IsEmpty();
157 }
158
159 void Parcel::Write(const void* buf, uint32_t size) {
160   impl_->Write(buf, size);
161 }
162
163 int Parcel::Read(void* buf, uint32_t size) {
164   return impl_->Read(buf, size);
165 }
166
167 void Parcel::WriteBool(bool val) {
168   impl_->Write<bool>(val);
169 }
170
171 void Parcel::WriteByte(char val) {
172   impl_->Write<char>(val);
173 }
174
175 void Parcel::WriteUInt16(uint16_t val) {
176   impl_->Write<uint16_t>(val);
177 }
178
179 void Parcel::WriteUInt32(uint32_t val) {
180   impl_->Write<uint32_t>(val);
181 }
182
183 void Parcel::WriteUInt64(uint64_t val) {
184   impl_->Write<uint64_t>(val);
185 }
186
187 void Parcel::WriteInt16(int16_t val) {
188   impl_->Write<int16_t>(val);
189 }
190
191 void Parcel::WriteInt32(int32_t val) {
192   impl_->Write<int32_t>(val);
193 }
194
195 void Parcel::WriteInt64(int64_t val) {
196   impl_->Write<int64_t>(val);
197 }
198
199 void Parcel::WriteFloat(float val) {
200   impl_->Write<float>(val);
201 }
202
203 void Parcel::WriteDouble(double val) {
204   impl_->Write<double>(val);
205 }
206
207 void Parcel::WriteString(const std::string& str) {
208   impl_->WriteSize(str.length() + 1);
209   impl_->Write(str.c_str(), str.length() + 1);
210 }
211
212 void Parcel::WriteCString(const char* str) {
213   impl_->WriteSize(strlen(str) + 1);
214   impl_->Write(str, strlen(str) + 1);
215 }
216
217 void Parcel::WriteCBundle(bundle* b) {
218   bundle_raw* raw = nullptr;
219   int len = 0;
220   bundle_encode(b, &raw, &len);
221   auto ptr = std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free);
222
223   auto* p = reinterpret_cast<void*>(raw);
224   impl_->WriteSize(len + 1);
225   impl_->Write(p, len + 1);
226 }
227
228 void Parcel::WriteBundle(const Bundle& b) {
229   auto raw = const_cast<Bundle&>(b).ToRaw();
230   auto* p = reinterpret_cast<void*>(raw.first.get());
231   impl_->WriteSize(raw.second + 1);
232   impl_->Write(p, raw.second + 1);
233 }
234
235 int Parcel::ReadBool(bool* val) {
236   return impl_->Read<bool>(val);
237 }
238
239 int Parcel::ReadByte(char* val) {
240   return impl_->Read<char>(val);
241 }
242
243 int Parcel::ReadUInt16(uint16_t* val) {
244   return impl_->Read<uint16_t>(val);
245 }
246
247 int Parcel::ReadUInt32(uint32_t* val) {
248   return impl_->Read<uint32_t>(val);
249 }
250
251 int Parcel::ReadUInt64(uint64_t* val) {
252   return impl_->Read<uint64_t>(val);
253 }
254
255 int Parcel::ReadInt16(int16_t* val) {
256   return impl_->Read<int16_t>(val);
257 }
258
259 int Parcel::ReadInt32(int32_t* val) {
260   return impl_->Read<int32_t>(val);
261 }
262
263 int Parcel::ReadInt64(int64_t* val) {
264   return impl_->Read<int64_t>(val);
265 }
266
267 int Parcel::ReadFloat(float* val) {
268   return impl_->Read<float>(val);
269 }
270
271 int Parcel::ReadDouble(double* val) {
272   return impl_->Read<double>(val);
273 }
274
275 std::string Parcel::ReadString() {
276   uint32_t len = 0;
277   int ret = impl_->ReadSize(&len);
278   if (ret != TIZEN_ERROR_NONE) {
279     set_last_result(ret);
280     return {};
281   }
282
283   char* str = new (std::nothrow) char [len];
284   if (str == nullptr) {
285     set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
286     return {};
287   }
288
289   auto ptr = std::unique_ptr<char[]>(str);
290   ret = impl_->Read(str, len);
291   if (ret != TIZEN_ERROR_NONE) {
292     set_last_result(ret);
293     return {};
294   }
295
296   set_last_result(TIZEN_ERROR_NONE);
297   return std::string(str);
298 }
299
300 int Parcel::ReadCString(char** str) {
301   uint32_t len = 0;
302   int ret = impl_->ReadSize(&len);
303   if (ret != TIZEN_ERROR_NONE)
304     return ret;
305
306   char* val = static_cast<char*>(calloc(len, sizeof(char)));
307   if (val == nullptr)
308     return TIZEN_ERROR_OUT_OF_MEMORY;
309
310   ret = impl_->Read(val, len);
311   if (ret != TIZEN_ERROR_NONE) {
312     free(val);
313     return ret;
314   }
315
316   *str = val;
317   return TIZEN_ERROR_NONE;
318 }
319
320 int Parcel::ReadCBundle(bundle** b) {
321   uint32_t len = 0;
322   int ret = impl_->ReadSize(&len);
323   if (ret != TIZEN_ERROR_NONE)
324     return ret;
325
326   uint8_t* raw = new (std::nothrow) uint8_t [len];
327   if (raw == nullptr)
328     return TIZEN_ERROR_OUT_OF_MEMORY;
329
330   auto ptr = std::unique_ptr<uint8_t[]>(raw);
331   ret = impl_->Read(raw, len);
332   if (ret != TIZEN_ERROR_NONE)
333     return ret;
334
335   *b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), len);
336   if (*b == nullptr)
337     return get_last_result();
338
339   return TIZEN_ERROR_NONE;
340 }
341
342 Bundle Parcel::ReadBundle() {
343   uint32_t len = 0;
344   int ret = impl_->ReadSize(&len);
345   if (ret != TIZEN_ERROR_NONE) {
346     set_last_result(ret);
347     return {};
348   }
349
350   uint8_t* raw = new (std::nothrow) uint8_t [len];
351   if (raw == nullptr) {
352     set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
353     return {};
354   }
355
356   auto ptr = std::unique_ptr<uint8_t[]>(raw);
357   ret = impl_->Read(raw, len);
358   if (ret != TIZEN_ERROR_NONE) {
359     set_last_result(ret);
360     return {};
361   }
362
363   bundle* b = bundle_decode(reinterpret_cast<bundle_raw*>(raw), len);
364   if (b == nullptr)
365     return {};
366
367   set_last_result(TIZEN_ERROR_NONE);
368   return Bundle(b, false, true);
369 }
370
371 const std::vector<uint8_t>& Parcel::GetRaw() {
372   return impl_->GetRaw();
373 }
374
375 void Parcel::ResetReader() {
376   impl_->ResetReader();
377 }
378
379 void Parcel::Clear() {
380   impl_->Clear();
381 }
382
383 void Parcel::Reset(const void* buf, uint32_t size) {
384   impl_->Reset(buf, size);
385 }
386
387 void Parcel::WriteParcelable(const Parcelable& parcelable) {
388   impl_->Write<int32_t>(1);
389   parcelable.WriteToParcel(this);
390 }
391
392 int Parcel::ReadParcelable(Parcelable* parcelable) {
393   int32_t has_parcelable = 0;
394   int ret = impl_->Read<int32_t>(&has_parcelable);
395   if (ret != TIZEN_ERROR_NONE)
396     return ret;
397
398   if (has_parcelable != 1)
399     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
400
401   parcelable->ReadFromParcel(this);
402   return TIZEN_ERROR_NONE;
403 }
404
405 }  // naemspace tizen_base