• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 #ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H
17 #define DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H
18 #include <cstdint>
19 #include <map>
20 #include <memory>
21 #include <string>
22 #include <vector>
23 
24 #include "api/visibility.h"
25 #include "endian_converter.h"
26 #include "parcel.h"
27 #include "securec.h"
28 
29 namespace OHOS::MiscServices {
30 #pragma pack(1)
31 struct TLVHead {
32     uint16_t tag;
33     uint32_t len;
34     std::uint8_t value[0];
35 };
36 #pragma pack()
37 struct RawMem {
38     uintptr_t buffer;
39     size_t bufferLen;
40     // notice:Keep the parcel reference to prevent the memory in the parcel from being destructed
41     std::shared_ptr<OHOS::Parcel> parcel;
42 };
43 
44 /*
45  * Common tag definitions.
46  * Product should use after TAG_BUFF
47  **/
48 enum COMMON_TAG : uint16_t {
49     TAG_VECTOR_ITEM = 0x0000,
50     TAG_MAP_KEY,
51     TAG_MAP_VALUE,
52 
53     TAG_BUFF = 0x0100,
54 };
55 struct API_EXPORT TLVObject {
56 public:
TLVObjectTLVObject57     TLVObject() : total_(0), cursor_(0)
58     {
59     }
60     virtual bool Encode(std::vector<std::uint8_t> &buffer) = 0;
61     virtual bool Decode(const std::vector<std::uint8_t> &buffer) = 0;
62     virtual size_t Count() = 0;
63 
InitTLVObject64     inline void Init(std::vector<std::uint8_t> &buffer)
65     {
66         buffer.resize(Count());
67         total_ = buffer.size();
68         cursor_ = 0;
69     }
70 
CountTLVObject71     static inline size_t Count(bool value)
72     {
73         return sizeof(value) + sizeof(TLVHead);
74     }
CountTLVObject75     static inline size_t Count(int8_t value)
76     {
77         return sizeof(value) + sizeof(TLVHead);
78     }
CountTLVObject79     static inline size_t Count(int16_t value)
80     {
81         return sizeof(value) + sizeof(TLVHead);
82     }
CountTLVObject83     static inline size_t Count(int32_t value)
84     {
85         return sizeof(value) + sizeof(TLVHead);
86     }
CountTLVObject87     static inline size_t Count(int64_t value)
88     {
89         return sizeof(value) + sizeof(TLVHead);
90     }
CountTLVObject91     static inline size_t Count(uint32_t value)
92     {
93         return sizeof(value) + sizeof(TLVHead);
94     }
CountTLVObject95     static inline size_t Count(const std::string &value)
96     {
97         return value.size() + sizeof(TLVHead);
98     }
CountTLVObject99     static inline size_t Count(const RawMem &value)
100     {
101         return value.bufferLen + sizeof(TLVHead);
102     }
CountTLVObject103     static inline size_t Count(TLVObject &value)
104     {
105         return value.Count() + sizeof(TLVHead);
106     }
107     template<typename T>
CountTLVObject108     inline size_t Count(std::shared_ptr<T> &value)
109     {
110         if (value == nullptr) {
111             return 0;
112         }
113         return Count(*value);
114     }
115     template<typename T>
CountTLVObject116     inline size_t Count(std::vector<T> &value)
117     {
118         size_t expectSize = sizeof(TLVHead);
119         for (auto &item : value) {
120             expectSize += Count(item);
121         }
122         return expectSize;
123     }
CountTLVObject124     static inline size_t Count(std::vector<uint8_t> &value)
125     {
126         size_t expectSize = sizeof(TLVHead);
127         expectSize += value.size();
128         return expectSize;
129     }
CountTLVObject130     static inline size_t Count(std::map<std::string, std::vector<uint8_t>> &value)
131     {
132         size_t expectSize = sizeof(TLVHead);
133         for (auto &item : value) {
134             expectSize += Count(item.first);
135             expectSize += Count(item.second);
136         }
137         return expectSize;
138     }
139 
140     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, bool value);
141     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int8_t value);
142     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int16_t value);
143     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int32_t value);
144     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int64_t value);
145     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, uint32_t value);
146     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const std::string &value);
147     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const RawMem &value);
148     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, TLVObject &value);
149     template<typename T>
WriteTLVObject150     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<T> &value)
151     {
152         if (!HasExpectBuffer(buffer, sizeof(TLVHead))) {
153             return false;
154         }
155         auto tagCursor = cursor_;
156         cursor_ += sizeof(TLVHead);
157         auto valueCursor = cursor_;
158         bool ret = WriteValue(buffer, value);
159         WriteHead(buffer, type, tagCursor, cursor_ - valueCursor);
160         return ret;
161     }
162     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<uint8_t> &value);
163     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::map<std::string, std::vector<uint8_t>> &value);
164     template<typename T>
WriteTLVObject165     bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::shared_ptr<T> &value)
166     {
167         if (value == nullptr) {
168             return true;
169         }
170         return Write(buffer, type, *value);
171     }
172     bool ReadHead(const std::vector<std::uint8_t> &buffer, TLVHead &head);
173     bool ReadValue(const std::vector<std::uint8_t> &buffer, bool &value, const TLVHead &head);
174     bool ReadValue(const std::vector<std::uint8_t> &buffer, int8_t &value, const TLVHead &head);
175     bool ReadValue(const std::vector<std::uint8_t> &buffer, int16_t &value, const TLVHead &head);
176     bool ReadValue(const std::vector<std::uint8_t> &buffer, int32_t &value, const TLVHead &head);
177     bool ReadValue(const std::vector<std::uint8_t> &buffer, int64_t &value, const TLVHead &head);
178     bool ReadValue(const std::vector<std::uint8_t> &buffer, uint32_t &value, const TLVHead &head);
179     bool ReadValue(const std::vector<std::uint8_t> &buffer, std::string &value, const TLVHead &head);
180     bool ReadValue(const std::vector<std::uint8_t> &buffer, RawMem &rawMem, const TLVHead &head);
181     bool ReadValue(const std::vector<std::uint8_t> &buffer, TLVObject &value, const TLVHead &head);
182     template<typename T>
ReadValueTLVObject183     bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<T> &value, const TLVHead &head)
184     {
185         auto vectorEnd = cursor_ + head.len;
186         for (; cursor_ < vectorEnd;) {
187             // V: item value
188             TLVHead valueHead{};
189             bool ret = ReadHead(buffer, valueHead);
190             T item{};
191             ret = ret && ReadValue(buffer, item, valueHead);
192             if (!ret) {
193                 return false;
194             }
195             value.push_back(item);
196         }
197         return true;
198     }
199     bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<uint8_t> &value, const TLVHead &head);
200     bool ReadValue(const std::vector<std::uint8_t> &buffer, std::map<std::string, std::vector<uint8_t>> &value,
201         const TLVHead &head);
202 
203     template<typename T>
ReadValueTLVObject204     bool ReadValue(const std::vector<std::uint8_t> &buffer, std::shared_ptr<T> &value, const TLVHead &head)
205     {
206         value = std::make_shared<T>();
207         if (value == nullptr) {
208             return false;
209         }
210         return ReadValue(buffer, *value, head);
211     }
212 
213 protected:
214     virtual ~TLVObject() = default;
SkipTLVObject215     inline bool Skip(size_t len, size_t total)
216     {
217         if (total < len || total - len < cursor_) {
218             return false;
219         }
220         cursor_ += len;
221         return true;
222     }
IsEnoughTLVObject223     inline bool IsEnough() const
224     {
225         return cursor_ < total_;
226     }
227 
228     size_t total_ = 0;
229 
230 private:
231     bool Encode(std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total);
232     bool Decode(const std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total);
WriteHeadTLVObject233     static inline void WriteHead(std::vector<std::uint8_t> &buffer, uint16_t type, size_t tagCursor, uint32_t len)
234     {
235         auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + tagCursor);
236         tlvHead->tag = HostToNet(type);
237         tlvHead->len = HostToNet(len);
238     }
239     template<typename T>
WriteBasicTLVObject240     bool WriteBasic(std::vector<std::uint8_t> &buffer, uint16_t type, T value)
241     {
242         if (!HasExpectBuffer(buffer, sizeof(TLVHead) + sizeof(value))) {
243             return false;
244         }
245         auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + cursor_);
246         tlvHead->tag = HostToNet(type);
247         tlvHead->len = HostToNet((uint32_t)sizeof(value));
248         auto valueBuff = HostToNet(value);
249         auto ret = memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value));
250         if (ret != EOK) {
251             return false;
252         }
253         cursor_ += sizeof(TLVHead) + sizeof(value);
254         return true;
255     }
256 
257     template<typename T>
WriteValueTLVObject258     bool WriteValue(std::vector<std::uint8_t> &buffer, std::vector<T> &value)
259     {
260         // items iterator
261         bool ret = true;
262         for (T &item : value) {
263             // V:item value
264             ret = ret && Write(buffer, TAG_VECTOR_ITEM, item);
265         }
266         return ret;
267     }
268 
269     template<typename T>
ReadBasicValueTLVObject270     bool ReadBasicValue(const std::vector<std::uint8_t> &buffer, T &value, const TLVHead &head)
271     {
272         if (head.len != sizeof(T) || head.len == 0) {
273             return false;
274         }
275         if (!HasExpectBuffer(buffer, head.len)) {
276             return false;
277         }
278         auto ret = memcpy_s(&value, sizeof(T), buffer.data() + cursor_, sizeof(T));
279         if (ret != EOK) {
280             return false;
281         }
282         value = NetToHost(value);
283         cursor_ += sizeof(T);
284         return true;
285     }
286 
HasExpectBufferTLVObject287     inline bool HasExpectBuffer(const std::vector<std::uint8_t> &buffer, uint32_t expectLen) const
288     {
289         return buffer.size() >= cursor_ && buffer.size() - cursor_ >= expectLen;
290     }
291 
292     size_t cursor_ = 0;
293 };
294 } // namespace OHOS::MiscServices
295 #endif // DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H
296