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.
19 #include "parcel/common.hh"
20 #include "parcel/log_private.hh"
21 #include "parcel/parcel.hh"
22 #include "parcel/parcel_implementation.hh"
23 #include "parcel/parcelable.hh"
25 namespace tizen_base {
27 Parcel::Impl::Impl(Parcel* parent, bool big_endian)
28 : parent_(parent), big_endian_(big_endian) {
31 Parcel::Impl::~Impl() {}
33 void Parcel::Impl::Write(const void* buf, uint32_t size) {
34 auto* p = reinterpret_cast<const uint8_t*>(buf);
35 data_.insert(data_.end(), p, p + size);
38 int Parcel::Impl::Read(void* buf, uint32_t size) {
39 if (data_.size() == 0)
40 return TIZEN_ERROR_NO_DATA;
42 if (reader_ + size > data_.size())
43 return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
45 auto* p = reinterpret_cast<uint8_t*>(buf);
46 std::copy(&data_[reader_], &data_[reader_] + size, p);
48 set_last_result(TIZEN_ERROR_NONE);
49 return TIZEN_ERROR_NONE;
52 const std::vector<uint8_t>& Parcel::Impl::GetRaw() {
56 void Parcel::Impl::ResetReader() {
60 void Parcel::Impl::Clear() {
65 void Parcel::Impl::Reset(const void* buf, uint32_t size) {
70 bool Parcel::Impl::IsEmpty() {
71 return data_.size() == 0;
74 void Parcel::Impl::WriteSize(uint32_t size) {
76 size = GUINT32_TO_BE(size);
78 Write<uint32_t>(size);
82 void Parcel::Impl::Write(T d) {
83 auto* p = reinterpret_cast<uint8_t*>(&d);
84 data_.insert(data_.end(), p, p + sizeof(T));
87 int Parcel::Impl::ReadSize(uint32_t* size) {
88 if (data_.size() == 0)
89 return TIZEN_ERROR_NO_DATA;
91 if (reader_ + sizeof(uint32_t) > data_.size())
92 return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
94 auto* p = reinterpret_cast<uint8_t*>(size);
95 std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p);
96 reader_ += sizeof(uint32_t);
99 *size = GUINT32_FROM_BE(*size);
101 return TIZEN_ERROR_NONE;
104 template <typename T>
105 int Parcel::Impl::Read(T* d) {
106 uint32_t size = sizeof(T);
107 if (reader_ + size > data_.size())
108 return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
110 auto* p = reinterpret_cast<uint8_t*>(d);
111 std::copy(&data_[reader_], &data_[reader_] + size, p);
113 return TIZEN_ERROR_NONE;
116 void Parcel::Impl::SetByteOrder(bool big_endian) {
117 big_endian_ = big_endian;
120 bool Parcel::Impl::IsBigEndian() {
124 Parcel::Parcel(bool big_endian) : impl_(new Impl(this, big_endian)) {
127 Parcel::Parcel(const void* buf, uint32_t size, bool big_endian)
128 : impl_(new Impl(this, big_endian)) {
129 impl_->Write(buf, size);
132 Parcel::~Parcel() {};
134 Parcel::Parcel(const Parcel& p)
135 : impl_(new Impl(this)) {
136 impl_->big_endian_ = p.impl_->big_endian_;
137 impl_->data_ = p.impl_->data_;
138 impl_->reader_ = p.impl_->reader_;
141 Parcel& Parcel::operator = (const Parcel& p) {
143 impl_->big_endian_ = p.impl_->big_endian_;
144 impl_->data_ = p.impl_->data_;
145 impl_->reader_ = p.impl_->reader_;
150 Parcel::Parcel(Parcel&& p) noexcept
151 : impl_(new Impl(this)) {
152 impl_ = std::move(p.impl_);
153 impl_->parent_ = this;
156 Parcel& Parcel::operator = (Parcel&& p) noexcept {
158 impl_->big_endian_ = p.impl_->big_endian_;
159 impl_->data_ = std::move(p.impl_->data_);
160 impl_->reader_ = p.impl_->reader_;
161 p.impl_->reader_ = 0;
166 bool Parcel::IsEmpty() const noexcept {
167 return impl_->IsEmpty();
170 void Parcel::Write(const void* buf, uint32_t size) {
171 impl_->Write(buf, size);
174 int Parcel::Read(void* buf, uint32_t size) {
175 return impl_->Read(buf, size);
178 void Parcel::WriteBool(bool val) {
179 impl_->Write<bool>(val);
182 void Parcel::WriteByte(char val) {
183 impl_->Write<char>(val);
186 void Parcel::WriteUInt16(uint16_t val) {
187 if (impl_->IsBigEndian())
188 val = GUINT16_TO_BE(val);
190 impl_->Write<uint16_t>(val);
193 void Parcel::WriteUInt32(uint32_t val) {
194 if (impl_->IsBigEndian())
195 val = GUINT32_TO_BE(val);
197 impl_->Write<uint32_t>(val);
200 void Parcel::WriteUInt64(uint64_t val) {
201 if (impl_->IsBigEndian())
202 val = GUINT64_TO_BE(val);
204 impl_->Write<uint64_t>(val);
207 void Parcel::WriteInt16(int16_t val) {
208 if (impl_->IsBigEndian())
209 val = GINT16_TO_BE(val);
211 impl_->Write<int16_t>(val);
214 void Parcel::WriteInt32(int32_t val) {
215 if (impl_->IsBigEndian())
216 val = GINT32_TO_BE(val);
218 impl_->Write<int32_t>(val);
221 void Parcel::WriteInt64(int64_t val) {
222 if (impl_->IsBigEndian())
223 val = GINT64_TO_BE(val);
225 impl_->Write<int64_t>(val);
228 void Parcel::WriteFloat(float val) {
229 if (impl_->IsBigEndian())
230 val = static_cast<float>(GINT32_TO_BE(val));
232 impl_->Write<float>(val);
235 void Parcel::WriteDouble(double val) {
236 if (impl_->IsBigEndian())
237 val = static_cast<double>(GINT64_TO_BE(val));
239 impl_->Write<double>(val);
242 void Parcel::WriteString(const std::string& str) {
243 impl_->WriteSize(str.length() + 1);
244 impl_->Write(str.c_str(), str.length() + 1);
247 void Parcel::WriteCString(const char* str) {
248 impl_->WriteSize(strlen(str) + 1);
249 impl_->Write(str, strlen(str) + 1);
252 int Parcel::ReadBool(bool* val) {
253 return impl_->Read<bool>(val);
256 int Parcel::ReadByte(char* val) {
257 return impl_->Read<char>(val);
260 int Parcel::ReadUInt16(uint16_t* val) {
261 int ret = impl_->Read<uint16_t>(val);
262 if (impl_->IsBigEndian())
263 *val = GUINT16_FROM_BE(*val);
268 int Parcel::ReadUInt32(uint32_t* val) {
269 int ret = impl_->Read<uint32_t>(val);
270 if (impl_->IsBigEndian())
271 *val = GUINT32_FROM_BE(*val);
276 int Parcel::ReadUInt64(uint64_t* val) {
277 int ret = impl_->Read<uint64_t>(val);
278 if (impl_->IsBigEndian())
279 *val = GUINT64_FROM_BE(*val);
284 int Parcel::ReadInt16(int16_t* val) {
285 int ret = impl_->Read<int16_t>(val);
286 if (impl_->IsBigEndian())
287 *val = GINT16_FROM_BE(*val);
292 int Parcel::ReadInt32(int32_t* val) {
293 int ret = impl_->Read<int32_t>(val);
294 if (impl_->IsBigEndian())
295 *val = GINT32_FROM_BE(*val);
300 int Parcel::ReadInt64(int64_t* val) {
301 int ret = impl_->Read<int64_t>(val);
302 if (impl_->IsBigEndian())
303 *val = GINT64_FROM_BE(*val);
308 int Parcel::ReadFloat(float* val) {
309 int ret = impl_->Read<float>(val);
310 if (impl_->IsBigEndian())
311 *val = static_cast<float>(GINT32_FROM_BE(*val));
316 int Parcel::ReadDouble(double* val) {
317 int ret = impl_->Read<double>(val);
318 if (impl_->IsBigEndian())
319 *val = static_cast<double>(GINT64_FROM_BE(*val));
324 std::string Parcel::ReadString() {
326 int ret = impl_->ReadSize(&len);
327 if (ret != TIZEN_ERROR_NONE) {
328 set_last_result(ret);
332 char* str = new (std::nothrow) char[len];
333 if (str == nullptr) {
334 set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
338 auto ptr = std::unique_ptr<char[]>(str);
339 ret = impl_->Read(str, len);
340 if (ret != TIZEN_ERROR_NONE) {
341 set_last_result(ret);
345 set_last_result(TIZEN_ERROR_NONE);
346 return std::string(str);
349 int Parcel::ReadCString(char** str) {
351 int ret = impl_->ReadSize(&len);
352 if (ret != TIZEN_ERROR_NONE)
355 char* val = static_cast<char*>(calloc(len, sizeof(char)));
357 return TIZEN_ERROR_OUT_OF_MEMORY;
359 ret = impl_->Read(val, len);
360 if (ret != TIZEN_ERROR_NONE) {
366 return TIZEN_ERROR_NONE;
369 const std::vector<uint8_t>& Parcel::GetRaw() {
370 return impl_->GetRaw();
373 void Parcel::ResetReader() {
374 impl_->ResetReader();
377 void Parcel::Clear() {
381 void Parcel::Reset(const void* buf, uint32_t size) {
382 impl_->Reset(buf, size);
385 void Parcel::WriteParcelable(const Parcelable& parcelable) {
386 parcelable.WriteToParcel(this);
389 int Parcel::ReadParcelable(Parcelable* parcelable) {
390 parcelable->ReadFromParcel(this);
391 return TIZEN_ERROR_NONE;
394 void Parcel::SetByteOrder(bool big_endian) {
395 impl_->SetByteOrder(big_endian);
398 } // namespace tizen_base