Refactor bundle implementation
[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 <glib.h>
18
19 #include <exception>
20 #include <mutex>
21
22 #include "parcel/common.hh"
23 #include "parcel/log_private.hh"
24 #include "parcel/parcel.hh"
25 #include "parcel/parcel_implementation.hh"
26 #include "parcel/parcelable.hh"
27
28 namespace tizen_base {
29 namespace {
30
31 constexpr const size_t kDataCapacity = 8;
32
33 }  // namespace
34
35 Parcel::Impl::Impl(Parcel* parent, size_t data_capacity, uint8_t* data)
36     : parent_(parent), data_capacity_(data_capacity), data_(data) {
37   if (data_ != nullptr)
38     data_size_ = data_capacity_;
39   else
40     data_ = static_cast<uint8_t*>(malloc(data_capacity_));
41 }
42
43 Parcel::Impl::~Impl() {
44   free(data_);
45 }
46
47 void Parcel::Impl::Write(const void* buf, uint32_t size) {
48   if (data_size_ + size > data_capacity_) {
49     size_t new_size = (data_capacity_ + size) * 3 / 2;
50     uint8_t* data = static_cast<uint8_t*>(realloc(data_, new_size));
51     if (data == nullptr)
52       throw std::bad_alloc();
53
54     data_ = data;
55     data_capacity_ = new_size;
56   }
57
58   memcpy(data_ + data_size_, buf, size);
59   data_size_ += size;
60 }
61
62 int Parcel::Impl::Read(void* buf, uint32_t size) {
63   if (data_size_ == 0)
64     return TIZEN_ERROR_NO_DATA;
65
66   if (reader_ + size > data_size_)
67     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
68
69   memcpy(buf, data_ + reader_, size);
70   reader_ += size;
71   set_last_result(TIZEN_ERROR_NONE);
72   return TIZEN_ERROR_NONE;
73 }
74
75 void Parcel::Impl::ResetReader() {
76   reader_ = 0;
77 }
78
79 void Parcel::Impl::Clear() {
80   data_size_ = 0;
81   reader_ = 0;
82 }
83
84 void Parcel::Impl::Reset(const void* buf, uint32_t size) {
85   Clear();
86   Write(buf, size);
87 }
88
89 bool Parcel::Impl::IsEmpty() {
90   return data_size_ == 0;
91 }
92
93 void Parcel::Impl::WriteSize(uint32_t size) {
94   if (IsBigEndian())
95     size = GUINT32_TO_BE(size);
96
97   Write<uint32_t>(size);
98 }
99
100 template <typename T>
101 void Parcel::Impl::Write(T d) {
102   if (data_size_ + sizeof(T) > data_capacity_) {
103     size_t new_size = (data_capacity_ + sizeof(T)) * 3 / 2;
104     uint8_t* data = static_cast<uint8_t*>(realloc(data_, new_size));
105     if (data == nullptr)
106       throw std::bad_alloc();
107
108     data_ = data;
109     data_capacity_ = new_size;
110   }
111
112   auto* p = reinterpret_cast<uint8_t*>(&d);
113   memcpy(data_ + data_size_, p, sizeof(T));
114   data_size_ += sizeof(T);
115 }
116
117 int Parcel::Impl::ReadSize(uint32_t* size) {
118   if (data_size_ == 0)
119     return TIZEN_ERROR_NO_DATA;
120
121   int ret = Read<uint32_t>(size);
122   if (ret != TIZEN_ERROR_NONE)
123     return ret;
124
125   if (IsBigEndian())
126     *size = GUINT32_FROM_BE(*size);
127
128   return TIZEN_ERROR_NONE;
129 }
130
131 template <typename T>
132 int Parcel::Impl::Read(T* d) {
133   uint32_t size = static_cast<uint32_t>(sizeof(T));
134   if (reader_ + size > data_size_)
135     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
136
137   auto* p = reinterpret_cast<uint8_t*>(d);
138   memcpy(p, data_ + reader_, size);
139   reader_ += size;
140   return TIZEN_ERROR_NONE;
141 }
142
143 void Parcel::Impl::SetByteOrder(bool big_endian) {
144   big_endian_ = big_endian;
145 }
146
147 bool Parcel::Impl::IsBigEndian() const {
148   return big_endian_;
149 }
150
151 uint8_t* Parcel::Impl::GetData() const {
152   return data_;
153 }
154
155 size_t Parcel::Impl::GetDataSize() const {
156   return data_size_;
157 }
158
159 size_t Parcel::Impl::GetDataCapacity() const {
160   return data_capacity_;
161 }
162
163 void Parcel::Impl::SetDataCapacity(size_t size) {
164   uint8_t* data = static_cast<uint8_t*>(realloc(data_, size));
165   if (data == nullptr)
166     throw std::bad_alloc();
167
168   data_ = data;
169   data_capacity_ = size;
170 }
171
172 uint8_t* Parcel::Impl::Detach(size_t* size) {
173   uint8_t* data = data_;
174   *size = data_size_;
175   data_ = nullptr;
176   data_capacity_ = 0;
177   data_size_ = 0;
178   reader_= 0;
179   return data;
180 }
181
182 uint32_t Parcel::Impl::GetReader() const {
183   return reader_;
184 }
185
186 std::vector<uint8_t> Parcel::Impl::ToRaw() {
187   return std::vector<uint8_t>(data_, data_ + data_size_);
188 }
189
190 Parcel::Parcel()
191     : impl_(new Impl(this, kDataCapacity, nullptr)) {
192   if (impl_->data_ == nullptr)
193     throw std::bad_alloc();
194 }
195
196 Parcel::Parcel(const void* buf, uint32_t size, bool copy)
197     : impl_(new Impl(this, size,
198           copy ? nullptr : static_cast<uint8_t*>(const_cast<void*>(buf)))) {
199   if (impl_->data_ == nullptr)
200     throw std::bad_alloc();
201
202   if (copy)
203     impl_->Write(buf, size);
204 }
205
206 Parcel::~Parcel() {};
207
208 Parcel::Parcel(const Parcel& p)
209   : impl_(new Impl(this, kDataCapacity)) {
210   impl_->big_endian_ = p.impl_->big_endian_;
211   impl_->data_capacity_ = p.impl_->data_capacity_;
212   impl_->data_size_ = p.impl_->data_size_;
213
214   uint8_t* data = static_cast<uint8_t*>(
215       realloc(impl_->data_, impl_->data_capacity_));
216   if (data == nullptr)
217     throw std::bad_alloc();
218
219   impl_->data_ = data;
220   memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
221
222   impl_->reader_ = p.impl_->reader_;
223 }
224
225 Parcel& Parcel::operator = (const Parcel& p) {
226   if (this != &p) {
227     impl_->big_endian_ = p.impl_->big_endian_;
228     impl_->data_capacity_ = p.impl_->data_capacity_;
229     impl_->data_size_ = p.impl_->data_size_;
230
231     uint8_t* data = static_cast<uint8_t*>(
232         realloc(impl_->data_, impl_->data_capacity_));
233     if (data == nullptr)
234       throw std::bad_alloc();
235
236     impl_->data_ = data;
237     memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
238
239     impl_->reader_ = p.impl_->reader_;
240   }
241   return *this;
242 }
243
244 Parcel::Parcel(Parcel&& p) noexcept
245     : impl_(new Impl(this, kDataCapacity)) {
246   impl_->big_endian_ = p.impl_->big_endian_;
247
248   impl_->data_size_ = p.impl_->data_size_;
249   p.impl_->data_size_ = 0;
250
251   uint8_t* data = impl_->data_;
252   size_t data_capacity = impl_->data_capacity_;
253
254   impl_->data_ = p.impl_->data_;
255   impl_->data_capacity_ = p.impl_->data_capacity_;
256
257   p.impl_->data_ = data;
258   p.impl_->data_capacity_ = data_capacity;
259
260   impl_->reader_ = p.impl_->reader_;
261   p.impl_->reader_ = 0;
262 }
263
264 Parcel& Parcel::operator = (Parcel&& p) noexcept {
265   if (this != &p) {
266     impl_->big_endian_ = p.impl_->big_endian_;
267
268     impl_->data_size_ = p.impl_->data_size_;
269     p.impl_->data_size_ = 0;
270
271     uint8_t* data = impl_->data_;
272     size_t data_capacity = impl_->data_capacity_;
273
274     impl_->data_ = p.impl_->data_;
275     impl_->data_capacity_ = p.impl_->data_capacity_;
276
277     p.impl_->data_ = data;
278     p.impl_->data_capacity_ = data_capacity;
279
280     impl_->reader_ = p.impl_->reader_;
281     p.impl_->reader_ = 0;
282   }
283   return *this;
284 }
285
286 bool Parcel::IsEmpty() const noexcept {
287   return impl_->IsEmpty();
288 }
289
290 void Parcel::Write(const void* buf, uint32_t size) {
291   impl_->Write(buf, size);
292 }
293
294 int Parcel::Read(void* buf, uint32_t size) {
295   return impl_->Read(buf, size);
296 }
297
298 void Parcel::WriteBool(bool val) {
299   impl_->Write<bool>(val);
300 }
301
302 void Parcel::WriteByte(char val) {
303   impl_->Write<char>(val);
304 }
305
306 void Parcel::WriteUInt16(uint16_t val) {
307   if (impl_->IsBigEndian())
308     val = GUINT16_TO_BE(val);
309
310   impl_->Write<uint16_t>(val);
311 }
312
313 void Parcel::WriteUInt32(uint32_t val) {
314   if (impl_->IsBigEndian())
315     val = GUINT32_TO_BE(val);
316
317   impl_->Write<uint32_t>(val);
318 }
319
320 void Parcel::WriteUInt64(uint64_t val) {
321   if (impl_->IsBigEndian())
322     val = GUINT64_TO_BE(val);
323
324   impl_->Write<uint64_t>(val);
325 }
326
327 void Parcel::WriteInt16(int16_t val) {
328   if (impl_->IsBigEndian())
329     val = GINT16_TO_BE(val);
330
331   impl_->Write<int16_t>(val);
332 }
333
334 void Parcel::WriteInt32(int32_t val) {
335   if (impl_->IsBigEndian())
336     val = GINT32_TO_BE(val);
337
338   impl_->Write<int32_t>(val);
339 }
340
341 void Parcel::WriteInt64(int64_t val) {
342   if (impl_->IsBigEndian())
343     val = GINT64_TO_BE(val);
344
345   impl_->Write<int64_t>(val);
346 }
347
348 void Parcel::WriteFloat(float val) {
349   if (impl_->IsBigEndian())
350     val = static_cast<float>(GINT32_TO_BE(val));
351
352   impl_->Write<float>(val);
353 }
354
355 void Parcel::WriteDouble(double val) {
356   if (impl_->IsBigEndian())
357     val = static_cast<double>(GINT64_TO_BE(val));
358
359   impl_->Write<double>(val);
360 }
361
362 void Parcel::WriteString(const std::string& str) {
363   impl_->WriteSize(str.length() + 1);
364   impl_->Write(str.c_str(), str.length() + 1);
365 }
366
367 void Parcel::WriteCString(const char* str) {
368   impl_->WriteSize(strlen(str) + 1);
369   impl_->Write(str, strlen(str) + 1);
370 }
371
372 int Parcel::ReadBool(bool* val) {
373   return impl_->Read<bool>(val);
374 }
375
376 int Parcel::ReadByte(char* val) {
377   return impl_->Read<char>(val);
378 }
379
380 int Parcel::ReadUInt16(uint16_t* val) {
381   int ret = impl_->Read<uint16_t>(val);
382   if (impl_->IsBigEndian())
383     *val = GUINT16_FROM_BE(*val);
384
385   return ret;
386 }
387
388 int Parcel::ReadUInt32(uint32_t* val) {
389   int ret = impl_->Read<uint32_t>(val);
390   if (impl_->IsBigEndian())
391     *val = GUINT32_FROM_BE(*val);
392
393   return ret;
394 }
395
396 int Parcel::ReadUInt64(uint64_t* val) {
397   int ret = impl_->Read<uint64_t>(val);
398   if (impl_->IsBigEndian())
399     *val = GUINT64_FROM_BE(*val);
400
401   return ret;
402 }
403
404 int Parcel::ReadInt16(int16_t* val) {
405   int ret = impl_->Read<int16_t>(val);
406   if (impl_->IsBigEndian())
407     *val = GINT16_FROM_BE(*val);
408
409   return ret;
410 }
411
412 int Parcel::ReadInt32(int32_t* val) {
413   int ret = impl_->Read<int32_t>(val);
414   if (impl_->IsBigEndian())
415     *val = GINT32_FROM_BE(*val);
416
417   return ret;
418 }
419
420 int Parcel::ReadInt64(int64_t* val) {
421   int ret = impl_->Read<int64_t>(val);
422   if (impl_->IsBigEndian())
423     *val = GINT64_FROM_BE(*val);
424
425   return ret;
426 }
427
428 int Parcel::ReadFloat(float* val) {
429   int ret = impl_->Read<float>(val);
430   if (impl_->IsBigEndian())
431     *val = static_cast<float>(GINT32_FROM_BE(*val));
432
433   return ret;
434 }
435
436 int Parcel::ReadDouble(double* val) {
437   int ret = impl_->Read<double>(val);
438   if (impl_->IsBigEndian())
439     *val = static_cast<double>(GINT64_FROM_BE(*val));
440
441   return ret;
442 }
443
444 std::string Parcel::ReadString() {
445   uint32_t len = 0;
446   int ret = impl_->ReadSize(&len);
447   if (ret != TIZEN_ERROR_NONE) {
448     set_last_result(ret);
449     return {};
450   }
451
452   char* str = new (std::nothrow) char[len];
453   if (str == nullptr) {
454     set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
455     return {};
456   }
457
458   auto ptr = std::unique_ptr<char[]>(str);
459   ret = impl_->Read(str, len);
460   if (ret != TIZEN_ERROR_NONE) {
461     set_last_result(ret);
462     return {};
463   }
464
465   set_last_result(TIZEN_ERROR_NONE);
466   return std::string(str);
467 }
468
469 int Parcel::ReadCString(char** str) {
470   uint32_t len = 0;
471   int ret = impl_->ReadSize(&len);
472   if (ret != TIZEN_ERROR_NONE)
473     return ret;
474
475   char* val = static_cast<char*>(calloc(len, sizeof(char)));
476   if (val == nullptr)
477     return TIZEN_ERROR_OUT_OF_MEMORY;
478
479   ret = impl_->Read(val, len);
480   if (ret != TIZEN_ERROR_NONE) {
481     free(val);
482     return ret;
483   }
484
485   *str = val;
486   return TIZEN_ERROR_NONE;
487 }
488
489 void Parcel::ResetReader() {
490   impl_->ResetReader();
491 }
492
493 void Parcel::Clear() {
494   impl_->Clear();
495 }
496
497 void Parcel::Reset(const void* buf, uint32_t size) {
498   impl_->Reset(buf, size);
499 }
500
501 void Parcel::WriteParcelable(const Parcelable& parcelable) {
502   parcelable.WriteToParcel(this);
503 }
504
505 int Parcel::ReadParcelable(Parcelable* parcelable) {
506   parcelable->ReadFromParcel(this);
507   return TIZEN_ERROR_NONE;
508 }
509
510 void Parcel::SetByteOrder(bool big_endian) {
511   impl_->SetByteOrder(big_endian);
512 }
513
514 uint8_t* Parcel::GetData() const {
515   return impl_->GetData();
516 }
517
518 size_t Parcel::GetDataSize() const {
519   return impl_->GetDataSize();
520 }
521
522 size_t Parcel::GetDataCapacity() const {
523   return impl_->GetDataCapacity();
524 }
525
526 void Parcel::SetDataCapacity(size_t size) {
527   impl_->SetDataCapacity(size);
528 }
529
530 uint8_t* Parcel::Detach(size_t* size) {
531   return impl_->Detach(size);
532 }
533
534 uint32_t Parcel::GetReader() const {
535   return impl_->GetReader();
536 }
537
538 std::vector<uint8_t> Parcel::ToRaw() {
539   return impl_->ToRaw();
540 }
541
542 }  // namespace tizen_base