Files
phs_v1.0.1.0/commonlibrary/c_utils/docs/zh-cn/c-utils-guide-parcel.md
2024-09-27 19:16:49 +08:00

283 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 使用Parcel作为数据容器
## 概述
Parcel对象是一个数据容器其提供一个内存空间以供数据写入。Parcel对象不仅支持诸如`int`,`float`,`double`等基本类型的写入,同时也支持扁平化地写入一个继承了`Parcelable`类的子类对象。可用于IPC中以实现数据通信功能。
## 涉及功能
### OHOS::Parcel
数据/消息的容器类。
#### 具体描述
```cpp
class OHOS::Parcel;
```
包含用于写入以及读出多种类型的数据包括基本类型、Parcelable对象等。
`#include <parcel.h>`
#### Public Functions
| 返回类型 | 名称 |
| -------------- | -------------- |
| | **Parcel**() |
| | **Parcel**(Allocator* allocator)<br>构造Parcel对象并指定内存分配器Allcator。 |
| virtual | **~Parcel**() |
| bool | **CheckOffsets**()<br>检查从当前光标读取对象的操作是否可行。 |
| void | **FlushBuffer**()<br>释放parcel中的数据区域并重置该parcel状态。 |
| uintptr_t | **GetData**() const<br>获取指向当前parcel中数据起始位置的指针。 |
| size_t | **GetDataCapacity**() const<br>获取当前parcel的总体容量(字节)即parcel中数据区域的当前总大小。 |
| size_t | **GetDataSize**() const<br>获取当前parcel中已存在数据的总大小。 |
| size_t | **GetMaxCapacity**() const |
| binder_size_t | **GetObjectOffsets**() const<br>获取写入至当前parcel的每一个oject的具体位置。 |
| size_t | **GetOffsetsSize**() const<br>获取当前存储的所有object的位置的总大小。 |
| size_t | **GetReadableBytes**() const<br>获取剩余可从当前parcel读出的总字节数。 |
| size_t | **GetReadPosition**()<br>获取当前读光标位置。 |
| size_t | **GetWritableBytes**() const<br>获取剩余可向当前parcel写入的总字节数。 |
| size_t | **GetWritePosition**()<br>获取当前写光标位置。 |
| void | **InjectOffsets**(binder_size_t offsets, size_t offsetSize)<br>记录一个数组,该数组内包含多个对象的位置偏移量。 |
| bool | **ParseFrom**(uintptr_t data, size_t size)<br>使用当前parcel读入输入数据。 |
| bool | **ReadBool**() |
| bool | **ReadBool**(bool& value) |
| bool | **ReadBoolUnaligned**() |
| bool | **ReadBoolVector**(std::vector< bool >* val) |
| const uint8_t* | **ReadBuffer**(size_t length)<br>从当前parcel中读出一块数据(一块缓存区的数据)。 |
| const char* | **ReadCString**()<br>从当前parcel中读出C-风格的字符串。 |
| double | **ReadDouble**() |
| bool | **ReadDouble**(double& value) |
| bool | **ReadDoubleVector**(std::vector< double >* val) |
| float | **ReadFloat**() |
| bool | **ReadFloat**(float& value) |
| bool | **ReadFloatVector**(std::vector< float >* val) |
| int16_t | **ReadInt16**() |
| bool | **ReadInt16**(int16_t& value) |
| bool | **ReadInt16Unaligned**(int16_t& value) |
| bool | **ReadInt16Vector**(std::vector< int16_t >* val) |
| int32_t | **ReadInt32**() |
| bool | **ReadInt32**(int32_t& value) |
| bool | **ReadInt32Vector**(std::vector< int32_t >* val) |
| int64_t | **ReadInt64**() |
| bool | **ReadInt64**(int64_t& value) |
| bool | **ReadInt64Vector**(std::vector< int64_t >* val) |
| int8_t | **ReadInt8**() |
| bool | **ReadInt8**(int8_t& value) |
| bool | **ReadInt8Unaligned**(int8_t& value) |
| bool | **ReadInt8Vector**(std::vector< int8_t >* val) |
| template <typename T \> <br>sptr< T > | **ReadObject**()<br>从当前parcel读出某一具体对象。 |
| template <typename T \> <br>T* | **ReadParcelable**()<br>从当前parcel读出一个Parcelable(及其子类)对象。 |
| uintptr_t | **ReadPointer**() |
| const std::string | **ReadString**()<br>从当前parcel中读出一个C++字符串(`std::string`)对象。 |
| bool | **ReadString**(std::string& value)<br>从当前parcel读出C++`std::string`字符串对象,并存入输入对象中。 |
| const std::u16string | **ReadString16**()<br>从当前parcel中读出一个UTF-16编码的C++字符串(`std::u16string`)对象。 |
| bool | **ReadString16**(std::u16string& value)<br>从当前parcel读出一个UTF-16编码的C++`std::u16string`字符串对象,并存入输入对象中。 |
| bool | **ReadString16Vector**(std::vector< std::u16string >* val) |
| const std::u16string | **ReadString16WithLength**(int32_t& len)<br>从当前parcel中读出UTF-16编码的C++字符串(`std::u16string`)对象以及其对应长度。 |
| const std::string | **ReadString8WithLength**(int32_t& len)<br>从当前parcel中读出C++字符串(`std::string`)对象以及其对应长度。 |
| bool | **ReadStringVector**(std::vector< std::string >* val) |
| template <typename T \> <br>sptr< T > | **ReadStrongParcelable**()<br>从当前parcel读出一个Parcelable对象并使用智能指针管理该对象。 |
| uint16_t | **ReadUint16**() |
| bool | **ReadUint16**(uint16_t& value) |
| bool | **ReadUint16Unaligned**(uint16_t& value) |
| bool | **ReadUInt16Vector**(std::vector< uint16_t >* val) |
| uint32_t | **ReadUint32**() |
| bool | **ReadUint32**(uint32_t& value) |
| bool | **ReadUInt32Vector**(std::vector< uint32_t >* val) |
| uint64_t | **ReadUint64**() |
| bool | **ReadUint64**(uint64_t& value) |
| bool | **ReadUInt64Vector**(std::vector< uint64_t >* val) |
| uint8_t | **ReadUint8**() |
| bool | **ReadUint8**(uint8_t& value) |
| bool | **ReadUint8Unaligned**(uint8_t& value) |
| bool | **ReadUInt8Vector**(std::vector< uint8_t >* val) |
| const uint8_t* | **ReadUnpadBuffer**(size_t length)<br>从当前parcel中读出一块数据(一块缓存区的数据)。 |
| template <typename T \> <br>bool | **ReadVector**(std::vector< T >* val, bool(Parcel::*)(T&) Read)<br>从当前parcel读出一个`std::vector`对象。 |
| bool | **RewindRead**(size_t newPosition)<br>将读光标置于指定位置。 |
| bool | **RewindWrite**(size_t offsets)<br>将写光标置于指定位置。 |
| bool | **SetAllocator**(Allocator* allocator)<br>设置当前parcel的内存分配器Allocator对象。 |
| bool | **SetDataCapacity**(size_t newCapacity)<br>设置当前parcel的以字节数为单位的容量大小即parcel内数据区域的大小。 |
| bool | **SetDataSize**(size_t dataSize)<br>设置当前parcel的已存在数据大小(字节)。 |
| bool | **SetMaxCapacity**(size_t maxCapacity)<br>设置当前parcel的以字节为单位的最大容量。 |
| void | **SkipBytes**(size_t bytes)<br>在读操作中,跳过接下来由`bytes`指定的几个字节。 |
| bool | **WriteBool**(bool value) |
| bool | **WriteBoolUnaligned**(bool value) |
| bool | **WriteBoolVector**(const std::vector< bool >& val) |
| bool | **WriteBuffer**(const void* data, size_t size) |
| bool | **WriteBufferAddTerminator**(const void* data, size_t size, size_t typeSize) |
| bool | **WriteCString**(const char* value)<br>向当前parcel写入一个C风格的字符串。 |
| bool | **WriteDouble**(double value) |
| bool | **WriteDoubleVector**(const std::vector< double >& val) |
| bool | **WriteFloat**(float value) |
| bool | **WriteFloatVector**(const std::vector< float >& val) |
| bool | **WriteInt16**(int16_t value) |
| bool | **WriteInt16Unaligned**(int16_t value) |
| bool | **WriteInt16Vector**(const std::vector< int16_t >& val) |
| bool | **WriteInt32**(int32_t value) |
| bool | **WriteInt32Vector**(const std::vector< int32_t >& val) |
| bool | **WriteInt64**(int64_t value) |
| bool | **WriteInt64Vector**(const std::vector< int64_t >& val) |
| bool | **WriteInt8**(int8_t value) |
| bool | **WriteInt8Unaligned**(int8_t value) |
| bool | **WriteInt8Vector**(const std::vector< int8_t >& val) |
| template <typename T \> <br>bool | **WriteObject**(const sptr< T >& object)<br>向当前parcel写入某一具体对象。 |
| bool | **WriteParcelable**(const Parcelable* object)<br>向当前parcel写入Parcelable对象。 |
| bool | **WritePointer**(uintptr_t value) |
| bool | **WriteRemoteObject**(const Parcelable* object)<br>向当前parcel中写入remote对象。 |
| bool | **WriteString**(const std::string& value)<br>向当前parcel写入一个C++的std::string字符串。 |
| bool | **WriteString16**(const std::u16string& value)<br>向当前parcel写入一个C++的std::string字符串。 |
| bool | **WriteString16Vector**(const std::vector< std::u16string >& val) |
| bool | **WriteString16WithLength**(const char16_t* value, size_t len)<br>向当前parcel写入一个UTF-16编码的字符串。 |
| bool | **WriteString8WithLength**(const char* value, size_t len)<br>向当前parcel写入一个UTF-8编码的字符串。 |
| bool | **WriteStringVector**(const std::vector< std::string >& val) |
| bool | **WriteStrongParcelable**(const sptr< Parcelable >& object)<br>将Parcelable对象的`HOLD_OBJECT`行为开启后写入当前parcel。 |
| bool | **WriteUint16**(uint16_t value) |
| bool | **WriteUint16Unaligned**(uint16_t value) |
| bool | **WriteUInt16Vector**(const std::vector< uint16_t >& val) |
| bool | **WriteUint32**(uint32_t value) |
| bool | **WriteUInt32Vector**(const std::vector< uint32_t >& val) |
| bool | **WriteUint64**(uint64_t value) |
| bool | **WriteUInt64Vector**(const std::vector< uint64_t >& val) |
| bool | **WriteUint8**(uint8_t value) |
| bool | **WriteUint8Unaligned**(uint8_t value) |
| bool | **WriteUInt8Vector**(const std::vector< uint8_t >& val) |
| bool | **WriteUnpadBuffer**(const void* data, size_t size) |
| template <typename T1 ,typename T2 \> <br>bool | **WriteVector**(const std::vector< T1 >& val, bool(Parcel::*)(T2) Write)<br>向当前parcel写入一个`std::vector`对象。 |
#### Protected Functions
| 返回类型 | 名称 |
| -------------- | -------------- |
| bool | **EnsureObjectsCapacity**()<br>确保当前写入对象数量小于对象容量。 |
| bool | **WriteObjectOffset**(binder_size_t offset)<br>记录待写入对象的具体位置,该位置表示为相对于数据区域起始处的偏移量。 |
### OHOS::Parcelable
定义了实例可被写入至某一Parcel的类接口。
#### 具体描述
```cpp
class OHOS::Parcelable;
```
**提示**: 如果当前对象为remote其地址将被用于在内核中进行数据传输。
`#include <parcel.h>`
继承自 OHOS::RefBase
#### Public Types
| | 名称 |
| -------------- | -------------- |
| enum| **BehaviorFlag** { IPC = 0x01, RPC = 0x02, HOLD_OBJECT = 0x10}<br>用于描述Parcelable对象具体行为的枚举类。 |
#### Public Functions
| 返回类型 | 名称 |
| -------------- | -------------- |
| | **Parcelable**() |
| | **Parcelable**(bool asRemote)<br>构造一个Parcelable对象。 |
| virtual | **~Parcelable**() = default |
| void | **ClearBehavior**(BehaviorFlag b) const<br>清除指定行为标志位。 |
| virtual bool | **Marshalling**(Parcel& parcel) const =0<br>向指定Parcel对象中写入当前Parcelable对象。 |
| void | **SetBehavior**(BehaviorFlag b) const<br>设置指定行为标志位。 |
| bool | **TestBehavior**(BehaviorFlag b) const<br>检查指定行为是否已开启。 |
#### Public Attributes
| | 名称 |
| -------------- | -------------- |
| bool | **asRemote_** <br>指明对象是否为remote的标志位。 |
| uint8_t | **behavior_** <br>指定已开启行为的具体值。 |
## 使用示例
1. 使用方法(伪代码)
```c++
// 写入端以某种顺序写入数据
struct TestData {
bool booltest;
int8_t int8test;
int16_t int16test;
int32_t int32test;
uint8_t uint8test;
uint16_t uint16test;
uint32_t uint32test;
};
...
Parcel parcel(nullptr);
struct TestData data = { true, -0x34, 0x5634, -0x12345678, 0x34, 0x5634, 0x12345678 };
bool result = false;
result = parcel.WriteBool(data.booltest);
if (!result) {
// 写失败处理
}
result = parcel.WriteInt8(data.int8test);
if (!result) {
// 写失败处理
}
result = parcel.WriteInt16(data.int16test);
if (!result) {
// 写失败处理
}
result = parcel.WriteInt32(data.int32test);
if (!result) {
// 写失败处理
}
result = parcel.WriteUint8(data.uint8test);
if (!result) {
// 写失败处理
}
result = parcel.WriteUint16(data.uint16test);
if (!result) {
// 写失败处理
}
result = parcel.WriteUint32(data.uint32test);
if (!result) {
// 写失败处理
}
```
```c++
// 接收端根据写入端写入顺序读取数据
bool readbool = parcel.ReadBool();
int8_t readint8 = parcel.ReadInt8();
int16_t readint16 = parcel.ReadInt16();
int32_t readint32 = parcel.ReadInt32();
uint8_t readuint8 = parcel.ReadUint8();
uint16_t readuint16 = parcel.ReadUint16();
uint32_t readuint32 = parcel.ReadUint32();
```
2. 测试用例编译运行方法
- 测试用例代码参见 base/test/unittest/common/utils_parcel_test.cpp
- 使用开发者自测试框架,使用方法参见:[开发自测试执行框架-测试用例执行](https://gitee.com/openharmony/testfwk_developer_test#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E6%89%A7%E8%A1%8C)
- 使用以下具体命令以运行`parcel.h`对应测试用例
```bash
run -t UT -tp utils -ts UtilsParcelTest
```