705fa9b268320d0e8557329d80400dee8e3da32b
[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 "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"
24
25 namespace tizen_base {
26
27 Parcel::Impl::Impl(Parcel* parent, bool big_endian)
28     : parent_(parent), big_endian_(big_endian) {
29 }
30
31 Parcel::Impl::~Impl() {}
32
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);
36 }
37
38 int Parcel::Impl::Read(void* buf, uint32_t size) {
39   if (data_.size() == 0)
40     return TIZEN_ERROR_NO_DATA;
41
42   if (reader_ + size > data_.size())
43     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
44
45   auto* p = reinterpret_cast<uint8_t*>(buf);
46   std::copy(&data_[reader_], &data_[reader_] + size, p);
47   reader_ += size;
48   set_last_result(TIZEN_ERROR_NONE);
49   return TIZEN_ERROR_NONE;
50 }
51
52 const std::vector<uint8_t>& Parcel::Impl::GetRaw() {
53   return data_;
54 }
55
56 void Parcel::Impl::ResetReader() {
57   reader_ = 0;
58 }
59
60 void Parcel::Impl::Clear() {
61   data_.clear();
62   reader_ = 0;
63 }
64
65 void Parcel::Impl::Reset(const void* buf, uint32_t size) {
66   Clear();
67   Write(buf, size);
68 }
69
70 bool Parcel::Impl::IsEmpty() {
71   return data_.size() == 0;
72 }
73
74 void Parcel::Impl::WriteSize(uint32_t size) {
75   if (IsBigEndian())
76     size = GUINT32_TO_BE(size);
77
78   Write<uint32_t>(size);
79 }
80
81 template <typename T>
82 void Parcel::Impl::Write(T d) {
83   auto* p = reinterpret_cast<uint8_t*>(&d);
84   data_.insert(data_.end(), p, p + sizeof(T));
85 }
86
87 int Parcel::Impl::ReadSize(uint32_t* size) {
88   if (data_.size() == 0)
89     return TIZEN_ERROR_NO_DATA;
90
91   if (reader_ + sizeof(uint32_t) > data_.size())
92     return TIZEN_ERROR_ILLEGAL_BYTE_SEQ;
93
94   auto* p = reinterpret_cast<uint8_t*>(size);
95   std::copy(&data_[reader_], &data_[reader_] + sizeof(uint32_t), p);
96   reader_ += sizeof(uint32_t);
97
98   if (IsBigEndian())
99     *size = GUINT32_FROM_BE(*size);
100
101   return TIZEN_ERROR_NONE;
102 }
103
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;
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 void Parcel::Impl::SetByteOrder(bool big_endian) {
117   big_endian_ = big_endian;
118 }
119
120 bool Parcel::Impl::IsBigEndian() {
121   return big_endian_;
122 }
123
124 Parcel::Parcel(bool big_endian) : impl_(new Impl(this, big_endian)) {
125 }
126
127 Parcel::Parcel(const void* buf, uint32_t size, bool big_endian)
128     : impl_(new Impl(this, big_endian)) {
129   impl_->Write(buf, size);
130 }
131
132 Parcel::~Parcel() {};
133
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_;
139 }
140
141 Parcel& Parcel::operator = (const Parcel& p) {
142   if (this != &p) {
143     impl_->big_endian_ = p.impl_->big_endian_;
144     impl_->data_ = p.impl_->data_;
145     impl_->reader_ = p.impl_->reader_;
146   }
147   return *this;
148 }
149
150 Parcel::Parcel(Parcel&& p) noexcept
151     : impl_(new Impl(this)) {
152   impl_ = std::move(p.impl_);
153   impl_->parent_ = this;
154 }
155
156 Parcel& Parcel::operator = (Parcel&& p) noexcept {
157   if (this != &p) {
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;
162   }
163   return *this;
164 }
165
166 bool Parcel::IsEmpty() const noexcept {
167   return impl_->IsEmpty();
168 }
169
170 void Parcel::Write(const void* buf, uint32_t size) {
171   impl_->Write(buf, size);
172 }
173
174 int Parcel::Read(void* buf, uint32_t size) {
175   return impl_->Read(buf, size);
176 }
177
178 void Parcel::WriteBool(bool val) {
179   impl_->Write<bool>(val);
180 }
181
182 void Parcel::WriteByte(char val) {
183   impl_->Write<char>(val);
184 }
185
186 void Parcel::WriteUInt16(uint16_t val) {
187   if (impl_->IsBigEndian())
188     val = GUINT16_TO_BE(val);
189
190   impl_->Write<uint16_t>(val);
191 }
192
193 void Parcel::WriteUInt32(uint32_t val) {
194   if (impl_->IsBigEndian())
195     val = GUINT32_TO_BE(val);
196
197   impl_->Write<uint32_t>(val);
198 }
199
200 void Parcel::WriteUInt64(uint64_t val) {
201   if (impl_->IsBigEndian())
202     val = GUINT64_TO_BE(val);
203
204   impl_->Write<uint64_t>(val);
205 }
206
207 void Parcel::WriteInt16(int16_t val) {
208   if (impl_->IsBigEndian())
209     val = GINT16_TO_BE(val);
210
211   impl_->Write<int16_t>(val);
212 }
213
214 void Parcel::WriteInt32(int32_t val) {
215   if (impl_->IsBigEndian())
216     val = GINT32_TO_BE(val);
217
218   impl_->Write<int32_t>(val);
219 }
220
221 void Parcel::WriteInt64(int64_t val) {
222   if (impl_->IsBigEndian())
223     val = GINT64_TO_BE(val);
224
225   impl_->Write<int64_t>(val);
226 }
227
228 void Parcel::WriteFloat(float val) {
229   if (impl_->IsBigEndian())
230     val = static_cast<float>(GINT32_TO_BE(val));
231
232   impl_->Write<float>(val);
233 }
234
235 void Parcel::WriteDouble(double val) {
236   if (impl_->IsBigEndian())
237     val = static_cast<double>(GINT64_TO_BE(val));
238
239   impl_->Write<double>(val);
240 }
241
242 void Parcel::WriteString(const std::string& str) {
243   impl_->WriteSize(str.length() + 1);
244   impl_->Write(str.c_str(), str.length() + 1);
245 }
246
247 void Parcel::WriteCString(const char* str) {
248   impl_->WriteSize(strlen(str) + 1);
249   impl_->Write(str, strlen(str) + 1);
250 }
251
252 int Parcel::ReadBool(bool* val) {
253   return impl_->Read<bool>(val);
254 }
255
256 int Parcel::ReadByte(char* val) {
257   return impl_->Read<char>(val);
258 }
259
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);
264
265   return ret;
266 }
267
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);
272
273   return ret;
274 }
275
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);
280
281   return ret;
282 }
283
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);
288
289   return ret;
290 }
291
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);
296
297   return ret;
298 }
299
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);
304
305   return ret;
306 }
307
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));
312
313   return ret;
314 }
315
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));
320
321   return ret;
322 }
323
324 std::string Parcel::ReadString() {
325   uint32_t len = 0;
326   int ret = impl_->ReadSize(&len);
327   if (ret != TIZEN_ERROR_NONE) {
328     set_last_result(ret);
329     return {};
330   }
331
332   char* str = new (std::nothrow) char[len];
333   if (str == nullptr) {
334     set_last_result(TIZEN_ERROR_OUT_OF_MEMORY);
335     return {};
336   }
337
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);
342     return {};
343   }
344
345   set_last_result(TIZEN_ERROR_NONE);
346   return std::string(str);
347 }
348
349 int Parcel::ReadCString(char** str) {
350   uint32_t len = 0;
351   int ret = impl_->ReadSize(&len);
352   if (ret != TIZEN_ERROR_NONE)
353     return ret;
354
355   char* val = static_cast<char*>(calloc(len, sizeof(char)));
356   if (val == nullptr)
357     return TIZEN_ERROR_OUT_OF_MEMORY;
358
359   ret = impl_->Read(val, len);
360   if (ret != TIZEN_ERROR_NONE) {
361     free(val);
362     return ret;
363   }
364
365   *str = val;
366   return TIZEN_ERROR_NONE;
367 }
368
369 const std::vector<uint8_t>& Parcel::GetRaw() {
370   return impl_->GetRaw();
371 }
372
373 void Parcel::ResetReader() {
374   impl_->ResetReader();
375 }
376
377 void Parcel::Clear() {
378   impl_->Clear();
379 }
380
381 void Parcel::Reset(const void* buf, uint32_t size) {
382   impl_->Reset(buf, size);
383 }
384
385 void Parcel::WriteParcelable(const Parcelable& parcelable) {
386   parcelable.WriteToParcel(this);
387 }
388
389 int Parcel::ReadParcelable(Parcelable* parcelable) {
390   parcelable->ReadFromParcel(this);
391   return TIZEN_ERROR_NONE;
392 }
393
394 void Parcel::SetByteOrder(bool big_endian) {
395   impl_->SetByteOrder(big_endian);
396 }
397
398 }  // namespace tizen_base