1 /* 2 * Copyright (c) 2022 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 } CountTLVObject107 template<typename T> inline size_t Count(std::shared_ptr<T> &value) 108 { 109 if (value == nullptr) { 110 return 0; 111 } 112 return Count(*value); 113 } CountTLVObject114 template<typename T> inline size_t Count(std::vector<T> &value) 115 { 116 size_t expectSize = sizeof(TLVHead); 117 for (auto &item : value) { 118 expectSize += Count(item); 119 } 120 return expectSize; 121 } CountTLVObject122 static inline size_t Count(std::vector<uint8_t> &value) 123 { 124 size_t expectSize = sizeof(TLVHead); 125 expectSize += value.size(); 126 return expectSize; 127 } CountTLVObject128 static inline size_t Count(std::map<std::string, std::vector<uint8_t>> &value) 129 { 130 size_t expectSize = sizeof(TLVHead); 131 for (auto &item : value) { 132 expectSize += Count(item.first); 133 expectSize += Count(item.second); 134 } 135 return expectSize; 136 } 137 138 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, bool value); 139 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int8_t value); 140 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int16_t value); 141 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int32_t value); 142 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int64_t value); 143 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, uint32_t value); 144 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const std::string &value); 145 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const RawMem &value); 146 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, TLVObject &value); WriteTLVObject147 template<typename T> bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<T> &value) 148 { 149 if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { 150 return false; 151 } 152 auto tagCursor = cursor_; 153 cursor_ += sizeof(TLVHead); 154 auto valueCursor = cursor_; 155 bool ret = WriteValue(buffer, value); 156 WriteHead(buffer, type, tagCursor, cursor_ - valueCursor); 157 return ret; 158 } 159 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<uint8_t> &value); 160 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::map<std::string, std::vector<uint8_t>> &value); WriteTLVObject161 template<typename T> bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::shared_ptr<T> &value) 162 { 163 if (value == nullptr) { 164 return true; 165 } 166 return Write(buffer, type, *value); 167 } 168 bool ReadHead(const std::vector<std::uint8_t> &buffer, TLVHead &head); 169 bool ReadValue(const std::vector<std::uint8_t> &buffer, bool &value, const TLVHead &head); 170 bool ReadValue(const std::vector<std::uint8_t> &buffer, int8_t &value, const TLVHead &head); 171 bool ReadValue(const std::vector<std::uint8_t> &buffer, int16_t &value, const TLVHead &head); 172 bool ReadValue(const std::vector<std::uint8_t> &buffer, int32_t &value, const TLVHead &head); 173 bool ReadValue(const std::vector<std::uint8_t> &buffer, int64_t &value, const TLVHead &head); 174 bool ReadValue(const std::vector<std::uint8_t> &buffer, uint32_t &value, const TLVHead &head); 175 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::string &value, const TLVHead &head); 176 bool ReadValue(const std::vector<std::uint8_t> &buffer, RawMem &rawMem, const TLVHead &head); 177 bool ReadValue(const std::vector<std::uint8_t> &buffer, TLVObject &value, const TLVHead &head); 178 template<typename T> ReadValueTLVObject179 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<T> &value, const TLVHead &head) 180 { 181 auto vectorEnd = cursor_ + head.len; 182 for (; cursor_ < vectorEnd;) { 183 // V: item value 184 TLVHead valueHead{}; 185 bool ret = ReadHead(buffer, valueHead); 186 T item{}; 187 ret = ret && ReadValue(buffer, item, valueHead); 188 if (!ret) { 189 return false; 190 } 191 value.push_back(item); 192 } 193 return true; 194 } 195 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<uint8_t> &value, const TLVHead &head); 196 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::map<std::string, std::vector<uint8_t>> &value, 197 const TLVHead &head); 198 199 template<typename T> ReadValueTLVObject200 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::shared_ptr<T> &value, const TLVHead &head) 201 { 202 value = std::make_shared<T>(); 203 if (value == nullptr) { 204 return false; 205 } 206 return ReadValue(buffer, *value, head); 207 } 208 209 protected: 210 virtual ~TLVObject() = default; SkipTLVObject211 inline bool Skip(size_t len, size_t total) 212 { 213 if (total < len || total - len < cursor_) { 214 return false; 215 } 216 cursor_ += len; 217 return true; 218 } IsEnoughTLVObject219 inline bool IsEnough() const 220 { 221 return cursor_ < total_; 222 } 223 224 size_t total_ = 0; 225 226 private: 227 bool Encode(std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total); 228 bool Decode(const std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total); WriteHeadTLVObject229 static inline void WriteHead(std::vector<std::uint8_t> &buffer, uint16_t type, size_t tagCursor, uint32_t len) 230 { 231 auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + tagCursor); 232 tlvHead->tag = HostToNet(type); 233 tlvHead->len = HostToNet(len); 234 } WriteBasicTLVObject235 template<typename T> bool WriteBasic(std::vector<std::uint8_t> &buffer, uint16_t type, T value) 236 { 237 if (!HasExpectBuffer(buffer, sizeof(TLVHead) + sizeof(value))) { 238 return false; 239 } 240 auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + cursor_); 241 tlvHead->tag = HostToNet(type); 242 tlvHead->len = HostToNet((uint32_t)sizeof(value)); 243 auto valueBuff = HostToNet(value); 244 auto ret = memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value)); 245 if (ret != EOK) { 246 return false; 247 } 248 cursor_ += sizeof(TLVHead) + sizeof(value); 249 return true; 250 } 251 WriteValueTLVObject252 template<typename T> bool WriteValue(std::vector<std::uint8_t> &buffer, std::vector<T> &value) 253 { 254 // items iterator 255 bool ret = true; 256 for (T &item : value) { 257 // V:item value 258 ret = ret && Write(buffer, TAG_VECTOR_ITEM, item); 259 } 260 return ret; 261 } 262 ReadBasicValueTLVObject263 template<typename T> bool ReadBasicValue(const std::vector<std::uint8_t> &buffer, T &value, const TLVHead &head) 264 { 265 if (head.len == 0) { 266 return false; 267 } 268 if (!HasExpectBuffer(buffer, head.len)) { 269 return false; 270 } 271 auto ret = memcpy_s(&value, sizeof(T), buffer.data() + cursor_, sizeof(T)); 272 if (ret != EOK) { 273 return false; 274 } 275 value = NetToHost(value); 276 cursor_ += sizeof(T); 277 return true; 278 } 279 HasExpectBufferTLVObject280 inline bool HasExpectBuffer(const std::vector<std::uint8_t> &buffer, uint32_t expectLen) const 281 { 282 return buffer.size() >= cursor_ && buffer.size() - cursor_ >= expectLen; 283 } 284 285 size_t cursor_ = 0; 286 }; 287 } // namespace OHOS::MiscServices 288 #endif // DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H 289