1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 /**
17 * @file parcel.h
18 *
19 * @brief Provide classes for data container implemented in c_utils.
20 *
21 * Including class Parcel, Parcelable and related memory Allocator.
22 */
23
24 #ifndef OHOS_UTILS_PARCEL_H
25 #define OHOS_UTILS_PARCEL_H
26
27 #include <string>
28 #include <vector>
29 #include "gmock/gmock.h"
30 #include "nocopyable.h"
31 #include "refbase.h"
32 #include "flat_obj.h"
33
34 namespace OHOS {
35 const uint32_t NUM_TEST = 4;
36 class Parcel;
37
38 /**
39 * @brief Interface for class whose Instance can be written into a Parcel.
40 *
41 * @note If this object is remote, its position intends to
42 * use in kernel data transaction.
43 */
44 class Parcelable : public virtual RefBase {
45 public:
46 virtual ~Parcelable() = default;
47
48 Parcelable();
49 /**
50 * @brief Construct a new Parcelable object.
51 *
52 * @param asRemote Specifies whether this object is remote.
53 */
54 explicit Parcelable(bool asRemote);
55
56 /**
57 * @brief Write a parcelable object to the given parcel.
58 *
59 * @param parcel Target parcel to write to.
60 * @return Return true being written on success or false if any error occur.
61 * @note If this object is remote, its position will be saved in the parcel.
62 * @note A static Unmarshalling function must also be implemented, so that
63 * you can get data from the given parcel into this parcelable object.
64 * See `static TestParcelable *Unmarshalling(Parcel &parcel)` as an example.
65 */
66 virtual bool Marshalling(Parcel &parcel) const = 0;
67
68 /**
69 * @brief Enum flag to describe behaviors of the Parcelable object.
70 *
71 * @var IPC Indicate the object can be used in IPC.
72 * @var RPC Indicate the object can be used in RPC.
73 * @var HOLD_OBJECT Indicate the object will ensure
74 * alive during data transaction.
75 *
76 */
77 enum BehaviorFlag { IPC = 0x01, RPC = 0x02, HOLD_OBJECT = 0x10 };
78
79 /**
80 * @brief Enable specified behavior.
81 *
82 * @param b Specific flag value.
83 * @see BehaviorFlag.
84 */
SetBehavior(BehaviorFlag b)85 inline void SetBehavior(BehaviorFlag b) const
86 {
87 behavior_ |= static_cast<uint8_t>(b);
88 }
89
90 /**
91 * @brief Disable specified behavior.
92 *
93 * @param b Specific flag value. See BehaviorFlag.
94 */
ClearBehavior(BehaviorFlag b)95 inline void ClearBehavior(BehaviorFlag b) const
96 {
97 behavior_ &= static_cast<uint8_t>(~b);
98 }
99
100 /**
101 * @brief Check whether specified behavior is enabled.
102 *
103 * @param b Specific flag value.
104 * @see BehaviorFlag.
105 */
TestBehavior(BehaviorFlag b)106 inline bool TestBehavior(BehaviorFlag b) const
107 {
108 return behavior_ & (static_cast<uint8_t>(b));
109 }
110
111 public:
112 bool asRemote_; // if the object is remote
113 mutable uint8_t behavior_; // value of flag of behaviors
114 };
115
116 /**
117 * @brief Interface for memory allocator of the data in Parcel.
118 */
119 class Allocator {
120 public:
121 virtual ~Allocator() = default;
122
123 virtual void *Realloc(void *data, size_t newSize) = 0;
124
125 virtual void *Alloc(size_t size) = 0;
126
127 virtual void Dealloc(void *data) = 0;
128 };
129
130 /**
131 * @brief Default implement of Allocator.
132 *
133 * @note Allocator defined by user for a parcel need be specified manually.
134 */
135 class DefaultAllocator : public Allocator {
136 public:
137 /**
138 * @brief Use `malloc()` to allocate memory for a parcel.
139 *
140 * @param size Size of desired memory region.
141 * @return Void-type pointer to the memory region.
142 */
143 void *Alloc(size_t size) override;
144
145 /**
146 * @brief Use `free()` to deallocate memory for a parcel.
147 *
148 * @param data Void-type pointer to the memory region.
149 */
150 void Dealloc(void *data) override;
151 private:
152 /**
153 * @brief Use `realloc()` to reallocate memory for a parcel.
154 *
155 * @param data Void-type pointer to the existed memory region.
156 * @param newSize New desired size of memory region.
157 * @return Void-type pointer to the new memory region.
158 */
159 void *Realloc(void *data, size_t newSize) override;
160 };
161
162 /**
163 * @brief A data/message container.
164 *
165 * Contains interfaces for writing and reading data of various types,
166 * including primitives, Parcelable objects etc.
167 *
168 * @note Usually used in IPC, RPC.
169 */
170 class Parcel {
171 public:
Parcel()172 Parcel() {}
173
174 /**
175 * @brief Construct a new Parcel object with specified Allocator.
176 *
177 * @param allocator Specified Allocator.
178 */
Parcel(Allocator * allocator)179 explicit Parcel(Allocator *allocator)
180 {
181 (void)allocator;
182 }
183
184 ~Parcel();
185 size_t GetDataSize() const;
186 uintptr_t GetData() const;
187 binder_size_t GetObjectOffsets() const;
188 size_t GetOffsetsSize() const;
189 size_t GetWritableBytes() const;
190 size_t GetReadableBytes() const;
191 size_t GetDataCapacity() const;
192 size_t GetMaxCapacity() const;
193 bool SetDataCapacity(size_t newCapacity);
194 bool SetDataSize(size_t dataSize);
195 bool SetMaxCapacity(size_t maxCapacity);
196 bool WriteBool(bool value);
197 bool WriteInt8(int8_t value);
198 bool WriteInt16(int16_t value);
199 bool WriteInt32(int32_t value);
200 bool WriteInt64(int64_t value);
201 bool WriteUint8(uint8_t value);
202 bool WriteUint16(uint16_t value);
203 bool WriteUint32(uint32_t value);
204 bool WriteUint64(uint64_t value);
205 bool WriteFloat(float value);
206 bool WriteDouble(double value);
207 bool WritePointer(uintptr_t value);
208 bool WriteBuffer(const void *data, size_t size);
209 bool WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize);
210 bool WriteUnpadBuffer(const void *data, size_t size);
211 bool WriteCString(const char *value);
212 bool WriteString(const std::string &value);
213 bool WriteString16(const std::u16string &value);
214 bool WriteString16WithLength(const char16_t *value, size_t len);
215 bool WriteString8WithLength(const char *value, size_t len);
216 bool WriteParcelable(const Parcelable *object);
217 bool WriteStrongParcelable(const sptr<Parcelable> &object);
218 bool WriteRemoteObject(const Parcelable *object);
219 template<typename T>
220 bool WriteObject(const sptr<T> &object);
221 bool ParseFrom(uintptr_t data, size_t size);
222 bool ReadBool();
223 int8_t ReadInt8();
224 int16_t ReadInt16();
225 int32_t ReadInt32();
226 int64_t ReadInt64();
ReadUint8()227 uint8_t ReadUint8()
228 {
229 if (writable_ == true) {
230 return 0;
231 }
232 return NUM_TEST;
233 }
234 uint16_t ReadUint16();
235 uint32_t ReadUint32();
236 uint64_t ReadUint64();
237 float ReadFloat();
238 double ReadDouble();
239 uintptr_t ReadPointer();
240 bool ReadBool(bool &value);
241 bool ReadInt8(int8_t &value);
242 bool ReadInt16(int16_t &value);
243 bool ReadInt32(int32_t &value);
244 bool ReadInt64(int64_t &value);
245 bool ReadUint8(uint8_t &value);
246 bool ReadUint16(uint16_t &value);
247 bool ReadUint32(uint32_t &value);
248 bool ReadUint64(uint64_t &value);
249 bool ReadFloat(float &value);
250 bool ReadDouble(double &value);
251 const uint8_t *ReadBuffer(size_t length);
252 const uint8_t *ReadUnpadBuffer(size_t length);
253 void SkipBytes(size_t bytes);
254 const char *ReadCString();
255 const std::string ReadString();
256 bool ReadString(std::string &value);
257 const std::u16string ReadString16();
258 bool ReadString16(std::u16string &value);
259 const std::u16string ReadString16WithLength(int32_t &len);
260 const std::string ReadString8WithLength(int32_t &len);
261 bool RewindRead(size_t newPosition);
262 bool RewindWrite(size_t offsets);
263 size_t GetReadPosition();
264 size_t GetWritePosition();
265 template <typename T>
266 T *ReadParcelable();
267
268 template <typename T>
269 sptr<T> ReadStrongParcelable();
270
271 bool CheckOffsets();
272
273 template<typename T>
274 sptr<T> ReadObject();
275
276 bool SetAllocator(Allocator *allocator);
277
278 void InjectOffsets(binder_size_t offsets, size_t offsetSize);
279 void FlushBuffer();
280 template <typename T1, typename T2>
281 bool WriteVector(const std::vector<T1> &val, bool (Parcel::*write)(T2));
282 bool WriteBoolVector(const std::vector<bool> &val);
283 bool WriteInt8Vector(const std::vector<int8_t> &val);
284 bool WriteInt16Vector(const std::vector<int16_t> &val);
285 bool WriteInt32Vector(const std::vector<int32_t> &val);
286 bool WriteInt64Vector(const std::vector<int64_t> &val);
287 bool WriteUInt8Vector(const std::vector<uint8_t> &val);
288 bool WriteUInt16Vector(const std::vector<uint16_t> &val);
289 bool WriteUInt32Vector(const std::vector<uint32_t> &val);
290 bool WriteUInt64Vector(const std::vector<uint64_t> &val);
291 bool WriteFloatVector(const std::vector<float> &val);
292 bool WriteDoubleVector(const std::vector<double> &val);
293 bool WriteStringVector(const std::vector<std::string> &val);
294 bool WriteString16Vector(const std::vector<std::u16string> &val);
295 template <typename T>
296 bool ReadVector(std::vector<T> *val, bool (Parcel::*read)(T &));
297 bool ReadBoolVector(std::vector<bool> *val);
298 bool ReadInt8Vector(std::vector<int8_t> *val);
299 bool ReadInt16Vector(std::vector<int16_t> *val);
300 bool ReadInt32Vector(std::vector<int32_t> *val);
301 bool ReadInt64Vector(std::vector<int64_t> *val);
302 bool ReadUInt8Vector(std::vector<uint8_t> *val);
303 bool ReadUInt16Vector(std::vector<uint16_t> *val);
304 bool ReadUInt32Vector(std::vector<uint32_t> *val);
305 bool ReadUInt64Vector(std::vector<uint64_t> *val);
306 bool ReadFloatVector(std::vector<float> *val);
307 bool ReadDoubleVector(std::vector<double> *val);
308 bool ReadStringVector(std::vector<std::string> *val);
309 bool ReadString16Vector(std::vector<std::u16string> *val);
310 bool WriteBoolUnaligned(bool value);
311 bool WriteInt8Unaligned(int8_t value);
312 bool WriteInt16Unaligned(int16_t value);
313 bool WriteUint8Unaligned(uint8_t value);
314 bool WriteUint16Unaligned(uint16_t value);
315 bool ReadBoolUnaligned();
316 bool ReadInt8Unaligned(int8_t &value);
317 bool ReadInt16Unaligned(int16_t &value);
318 bool ReadUint8Unaligned(uint8_t &value);
319 bool ReadUint16Unaligned(uint16_t &value);
320
321 protected:
322 bool WriteObjectOffset(binder_size_t offset);
323 bool EnsureObjectsCapacity();
324 private:
325 DISALLOW_COPY_AND_MOVE(Parcel);
326 template <typename T>
327 bool Write(T value);
328
329 template <typename T>
330 bool Read(T &value);
331
332 template <typename T>
333 T Read();
334
335 template <typename T>
336 bool ReadPadded(T &value);
337
GetPadSize(size_t size)338 inline size_t GetPadSize(size_t size)
339 {
340 const size_t sizeOffset = 3;
341 return (((size + sizeOffset) & (~sizeOffset)) - size);
342 }
343
344 size_t CalcNewCapacity(size_t minCapacity);
345
346 bool WriteDataBytes(const void *data, size_t size);
347
348 void WritePadBytes(size_t padded);
349
350 bool EnsureWritableCapacity(size_t desireCapacity);
351
352 bool WriteParcelableOffset(size_t offset);
353
354 private:
355 uint8_t *data_;
356 size_t readCursor_;
357 size_t writeCursor_;
358 size_t dataSize_;
359 size_t dataCapacity_;
360 size_t maxDataCapacity_;
361 binder_size_t *objectOffsets_;
362 size_t objectCursor_;
363 size_t objectsCapacity_;
364 Allocator *allocator_;
365 std::vector<sptr<Parcelable>> objectHolder_;
366 bool writable_ = true;
367 };
368
369 template <typename T>
WriteObject(const sptr<T> & object)370 bool Parcel::WriteObject(const sptr<T> &object)
371 {
372 if (object == nullptr) {
373 return T::Marshalling(*this, object);
374 }
375 return WriteRemoteObject(object.GetRefPtr());
376 }
377
378 template <typename T>
ReadObject()379 sptr<T> Parcel::ReadObject()
380 {
381 if (!this->CheckOffsets()) {
382 return nullptr;
383 }
384 sptr<T> res(T::Unmarshalling(*this));
385 return res;
386 }
387
388 // Read data from the given parcel into this parcelable object.
389 template <typename T>
ReadParcelable()390 T *Parcel::ReadParcelable()
391 {
392 int32_t size = this->ReadInt32();
393 if (size == 0) {
394 return nullptr;
395 }
396 return T::Unmarshalling(*this);
397 }
398
399 // Read data from the given parcel into this parcelable object, return sptr.
400 template <typename T>
ReadStrongParcelable()401 sptr<T> Parcel::ReadStrongParcelable()
402 {
403 int32_t size = this->ReadInt32();
404 if (size == 0) {
405 return nullptr;
406 }
407 sptr<T> res(T::Unmarshalling(*this));
408 return res;
409 }
410
411 } // namespace OHOS
412 #endif
413