2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
28 namespace tizen_base {
31 constexpr const size_t kDataCapacity = 8;
35 Parcel::Impl::Impl(Parcel* parent, size_t data_capacity, uint8_t* data)
36 : parent_(parent), data_capacity_(data_capacity), data_(data) {
38 data_size_ = data_capacity_;
40 data_ = static_cast<uint8_t*>(malloc(data_capacity_));
43 Parcel::Impl::~Impl() {
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));
52 throw std::bad_alloc();
55 data_capacity_ = new_size;
58 memcpy(data_ + data_size_, buf, size);
62 int Parcel::Impl::Read(void* buf, uint32_t size) {
64 return TIZEN_ERROR_NO_DATA;
66 if (reader_ + size > data_size_)
67 return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
69 memcpy(buf, data_ + reader_, size);
71 set_last_result(TIZEN_ERROR_NONE);
72 return TIZEN_ERROR_NONE;
75 void Parcel::Impl::ResetReader() {
79 void Parcel::Impl::Clear() {
84 void Parcel::Impl::Reset(const void* buf, uint32_t size) {
89 bool Parcel::Impl::IsEmpty() {
90 return data_size_ == 0;
93 void Parcel::Impl::WriteSize(uint32_t size) {
95 size = GUINT32_TO_BE(size);
97 Write<uint32_t>(size);
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));
106 throw std::bad_alloc();
109 data_capacity_ = new_size;
112 auto* p = reinterpret_cast<uint8_t*>(&d);
113 memcpy(data_ + data_size_, p, sizeof(T));
114 data_size_ += sizeof(T);
117 int Parcel::Impl::ReadSize(uint32_t* size) {
119 return TIZEN_ERROR_NO_DATA;
121 int ret = Read<uint32_t>(size);
122 if (ret != TIZEN_ERROR_NONE)
126 *size = GUINT32_FROM_BE(*size);
128 return TIZEN_ERROR_NONE;
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;
137 auto* p = reinterpret_cast<uint8_t*>(d);
138 memcpy(p, data_ + reader_, size);
140 return TIZEN_ERROR_NONE;
143 void Parcel::Impl::SetByteOrder(bool big_endian) {
144 big_endian_ = big_endian;
147 bool Parcel::Impl::IsBigEndian() const {
151 uint8_t* Parcel::Impl::GetData() const {
155 size_t Parcel::Impl::GetDataSize() const {
159 size_t Parcel::Impl::GetDataCapacity() const {
160 return data_capacity_;
163 void Parcel::Impl::SetDataCapacity(size_t size) {
164 uint8_t* data = static_cast<uint8_t*>(realloc(data_, size));
166 throw std::bad_alloc();
169 data_capacity_ = size;
172 uint8_t* Parcel::Impl::Detach(size_t* size) {
173 uint8_t* data = data_;
182 uint32_t Parcel::Impl::GetReader() const {
186 std::vector<uint8_t> Parcel::Impl::ToRaw() {
187 return std::vector<uint8_t>(data_, data_ + data_size_);
191 : impl_(new Impl(this, kDataCapacity, nullptr)) {
192 if (impl_->data_ == nullptr)
193 throw std::bad_alloc();
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();
203 impl_->Write(buf, size);
206 Parcel::~Parcel() {};
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_;
214 uint8_t* data = static_cast<uint8_t*>(
215 realloc(impl_->data_, impl_->data_capacity_));
217 throw std::bad_alloc();
220 memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
222 impl_->reader_ = p.impl_->reader_;
225 Parcel& Parcel::operator = (const Parcel& 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_;
231 uint8_t* data = static_cast<uint8_t*>(
232 realloc(impl_->data_, impl_->data_capacity_));
234 throw std::bad_alloc();
237 memcpy(impl_->data_, p.impl_->data_, impl_->data_size_);
239 impl_->reader_ = p.impl_->reader_;
244 Parcel::Parcel(Parcel&& p) noexcept
245 : impl_(new Impl(this, kDataCapacity)) {
246 impl_->big_endian_ = p.impl_->big_endian_;
248 impl_->data_size_ = p.impl_->data_size_;
249 p.impl_->data_size_ = 0;
251 uint8_t* data = impl_->data_;
252 size_t data_capacity = impl_->data_capacity_;
254 impl_->data_ = p.impl_->data_;
255 impl_->data_capacity_ = p.impl_->data_capacity_;
257 p.impl_->data_ = data;
258 p.impl_->data_capacity_ = data_capacity;
260 impl_->reader_ = p.impl_->reader_;
261 p.impl_->reader_ = 0;
264 Parcel& Parcel::operator = (Parcel&& p) noexcept {
266 impl_->big_endian_ = p.impl_->big_endian_;
268 impl_->data_size_ = p.impl_->data_size_;
269 p.impl_->data_size_ = 0;
271 uint8_t* data = impl_->data_;
272 size_t data_capacity = impl_->data_capacity_;
274 impl_->data_ = p.impl_->data_;
275 impl_->data_capacity_ = p.impl_->data_capacity_;
277 p.impl_->data_ = data;
278 p.impl_->data_capacity_ = data_capacity;
280 impl_->reader_ = p.impl_->reader_;
281 p.impl_->reader_ = 0;
286 bool Parcel::IsEmpty() const noexcept {
287 return impl_->IsEmpty();
290 void Parcel::Write(const void* buf, uint32_t size) {
291 impl_->Write(buf, size);
294 int Parcel::Read(void* buf, uint32_t size) {
295 return impl_->Read(buf, size);
298 void Parcel::WriteBool(bool val) {
299 impl_->Write<bool>(val);
302 void Parcel::WriteByte(char val) {
303 impl_->Write<char>(val);
306 void Parcel::WriteUInt16(uint16_t val) {
307 if (impl_->IsBigEndian())
308 val = GUINT16_TO_BE(val);
310 impl_->Write<uint16_t>(val);
313 void Parcel::WriteUInt32(uint32_t val) {
314 if (impl_->IsBigEndian())
315 val = GUINT32_TO_BE(val);
317 impl_->Write<uint32_t>(val);
320 void Parcel::WriteUInt64(uint64_t val) {
321 if (impl_->IsBigEndian())
322 val = GUINT64_TO_BE(val);
324 impl_->Write<uint64_t>(val);
327 void Parcel::WriteInt16(int16_t val) {
328 if (impl_->IsBigEndian())
329 val = GINT16_TO_BE(val);
331 impl_->Write<int16_t>(val);
334 void Parcel::WriteInt32(int32_t val) {
335 if (impl_->IsBigEndian())
336 val = GINT32_TO_BE(val);
338 impl_->Write<int32_t>(val);
341 void Parcel::WriteInt64(int64_t val) {
342 if (impl_->IsBigEndian())
343 val = GINT64_TO_BE(val);
345 impl_->Write<int64_t>(val);
348 void Parcel::WriteFloat(float val) {
349 if (impl_->IsBigEndian())
350 val = static_cast<float>(GINT32_TO_BE(val));
352 impl_->Write<float>(val);
355 void Parcel::WriteDouble(double val) {
356 if (impl_->IsBigEndian())
357 val = static_cast<double>(GINT64_TO_BE(val));
359 impl_->Write<double>(val);
362 void Parcel::WriteString(const std::string& str) {
363 impl_->WriteSize(str.length() + 1);
364 impl_->Write(str.c_str(), str.length() + 1);
367 void Parcel::WriteCString(const char* str) {
368 impl_->WriteSize(strlen(str) + 1);
369 impl_->Write(str, strlen(str) + 1);
372 int Parcel::ReadBool(bool* val) {
373 return impl_->Read<bool>(val);
376 int Parcel::ReadByte(char* val) {
377 return impl_->Read<char>(val);
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);
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);
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);
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);
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);
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);
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));
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));
444 std::string Parcel::ReadString() {
446 int ret = impl_->ReadSize(&len);
447 if (ret != TIZEN_ERROR_NONE) {
448 set_last_result(ret);
452 char* str = new (std::nothrow) char[len];
453 if (str == nullptr) {
454 set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
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);
465 set_last_result(TIZEN_ERROR_NONE);
466 return std::string(str);
469 int Parcel::ReadCString(char** str) {
471 int ret = impl_->ReadSize(&len);
472 if (ret != TIZEN_ERROR_NONE)
475 char* val = static_cast<char*>(calloc(len, sizeof(char)));
477 return TIZEN_ERROR_OUT_OF_MEMORY;
479 ret = impl_->Read(val, len);
480 if (ret != TIZEN_ERROR_NONE) {
486 return TIZEN_ERROR_NONE;
489 void Parcel::ResetReader() {
490 impl_->ResetReader();
493 void Parcel::Clear() {
497 void Parcel::Reset(const void* buf, uint32_t size) {
498 impl_->Reset(buf, size);
501 void Parcel::WriteParcelable(const Parcelable& parcelable) {
502 parcelable.WriteToParcel(this);
505 int Parcel::ReadParcelable(Parcelable* parcelable) {
506 parcelable->ReadFromParcel(this);
507 return TIZEN_ERROR_NONE;
510 void Parcel::SetByteOrder(bool big_endian) {
511 impl_->SetByteOrder(big_endian);
514 uint8_t* Parcel::GetData() const {
515 return impl_->GetData();
518 size_t Parcel::GetDataSize() const {
519 return impl_->GetDataSize();
522 size_t Parcel::GetDataCapacity() const {
523 return impl_->GetDataCapacity();
526 void Parcel::SetDataCapacity(size_t size) {
527 impl_->SetDataCapacity(size);
530 uint8_t* Parcel::Detach(size_t* size) {
531 return impl_->Detach(size);
534 uint32_t Parcel::GetReader() const {
535 return impl_->GetReader();
538 std::vector<uint8_t> Parcel::ToRaw() {
539 return impl_->ToRaw();
542 } // namespace tizen_base