1 /*
2 * Copyright (c) 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 UDMF_TLV_OBJECT_H
17 #define UDMF_TLV_OBJECT_H
18 #include <cstddef>
19 #include <type_traits>
20 #include "securec.h"
21 #include "unified_meta.h"
22 #include "endian_converter.h"
23 #include "tlv_tag.h"
24
25 namespace OHOS {
26 namespace UDMF {
27 #pragma pack(1)
28 struct TLVHead {
29 uint16_t tag;
30 uint32_t len;
31 std::uint8_t value[0];
32 };
33 #pragma pack()
34
35 class API_EXPORT TLVObject {
36 public:
37 TLVObject() = default;
38 ~TLVObject() = default;
39 explicit TLVObject(std::vector<std::uint8_t> &buffer);
40 void SetFile(std::FILE *file);
41 void UpdateSize();
42 std::vector<std::uint8_t> GetBuffer();
43 size_t GetTotal();
44 size_t GetCursor();
45 size_t OffsetHead();
46 void ResetCursor();
47
48 size_t Count(const std::string &value);
49 size_t Count(const std::vector<uint8_t> &value);
50 size_t Count(const OHOS::AAFwk::Want &value);
51 size_t Count(const std::monostate &value);
52 size_t Count(const void *value);
53
54 bool Write(TAG tag, const std::string &value);
55 bool Write(TAG tag, const std::vector<uint8_t> &value);
56 bool Write(TAG tag, const OHOS::AAFwk::Want &value);
57 bool Write(TAG tag, const std::monostate &value);
58 bool Write(TAG tag, const void *value);
59
60 bool Read(std::string &value, const TLVHead &head);
61 bool Read(std::vector<uint8_t> &value, const TLVHead &head);
62 bool Read(OHOS::AAFwk::Want &value, const TLVHead &head);
63 bool Read(std::monostate &value, const TLVHead &head);
64 bool Read(void *value, const TLVHead &head);
65
66 template <typename T> size_t CountBasic(const T &value);
67 template <typename T> bool WriteBasic(TAG type, const T &value);
68 template <typename T> bool ReadBasic(T &value, const TLVHead &head);
69
70 size_t CountHead();
71 bool WriteHead(uint16_t tag, uint32_t len);
72 bool WriteBackHead(uint16_t tag, size_t tagCursor, uint32_t len);
73 bool ReadHead(TLVHead &head);
74
75 bool Skip(TLVHead &head);
76 bool HasExpectBuffer(const uint32_t expectLen) const;
77 bool SaveBufferToFile();
78 bool SaveBufferToFileFront(size_t tagCursor, uint32_t len);
79 bool LoadBufferFormFile(size_t size);
80
81
82 private:
83 void PrepareBufferForFile(size_t size);
84 std::uint8_t *GetStartCursor();
85
86 std::size_t total_ = 0;
87 std::size_t cursor_ = 0;
88 std::vector<std::uint8_t> *buffer_;
89 std::FILE *file_ = nullptr;
90 };
91
CountBasic(const T & value)92 template <typename T> size_t TLVObject::CountBasic(const T &value)
93 {
94 static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
95 auto size = sizeof(value) + sizeof(TLVHead);
96 total_ += size;
97 return size;
98 }
99
WriteBasic(TAG type,const T & value)100 template <typename T> bool TLVObject::WriteBasic(TAG type, const T &value)
101 {
102 static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
103 if (!HasExpectBuffer(sizeof(TLVHead) + sizeof(value))) {
104 return false;
105 }
106 auto tlvHead = reinterpret_cast<TLVHead *>(GetStartCursor());
107 tlvHead->tag = HostToNet(static_cast<uint16_t>(type));
108 tlvHead->len = HostToNet((uint32_t)sizeof(value));
109 auto valueBuff = HostToNet(value);
110 if (memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value)) != EOK) {
111 return false;
112 }
113 cursor_ += sizeof(TLVHead) + sizeof(value);
114 return SaveBufferToFile();
115 }
116
ReadBasic(T & value,const TLVHead & head)117 template <typename T> bool TLVObject::ReadBasic(T &value, const TLVHead &head)
118 {
119 static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
120 if (head.len == 0 || head.len != sizeof(T)) {
121 return false;
122 }
123 if (!HasExpectBuffer(head.len)) {
124 return false;
125 }
126 if (!LoadBufferFormFile(head.len)) {
127 return false;
128 }
129 auto startCursor = GetStartCursor();
130 auto ret = memcpy_s(&value, sizeof(T), startCursor, sizeof(T));
131 if (ret != EOK) {
132 return false;
133 }
134 value = NetToHost(value);
135 cursor_ += sizeof(T);
136 return true;
137 }
138 } // namespace UDMF
139 } // namespace OHOS
140 #endif // UDMF_TLV_OBJECT_H
141