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
19 #include <cstdio>
20 #include "securec.h"
21 #include "error_code.h"
22 #include "unified_meta.h"
23 #include "unified_types.h"
24 #include "endian_converter.h"
25
26 namespace OHOS {
27 namespace UDMF {
28 enum class TAG {
29 TAG_INT32 = 0x0000,
30 TAG_INT64,
31 TAG_UINT32,
32 TAG_UINT64,
33 TAG_BOOL,
34 TAG_DOUBLE,
35 TAG_STRING,
36 TAG_VECTOR,
37 TAG_MAP,
38 TAG_BUTT,
39 };
40
41 #pragma pack(1)
42 struct TLVHead {
43 uint16_t tag;
44 uint32_t len;
45 std::uint8_t value[0];
46 };
47 #pragma pack()
48
49 class TLVObject {
50 public:
51 TLVObject() = default;
52 ~TLVObject() = default;
53 explicit TLVObject(std::vector<std::uint8_t> &buffer);
54 void SetFile(std::FILE *file);
55 void UpdateSize();
56 std::vector<std::uint8_t> GetBuffer();
57 void Count(const uint32_t value);
58 void Count(const uint64_t value);
59 void Count(const int32_t value);
60 void Count(const int64_t value);
61 void Count(const float value);
62 void Count(const double value);
63 void Count(const std::string &value);
64 void Count(const std::vector<uint8_t> &value);
65 void Count(const UDVariant &value);
66 void Count(const UDDetails &value);
67 void Count(const UnifiedKey &value);
68 void Count(const Privilege &value);
69 template<typename T> bool WriteBasic(TAG type, const T &value);
70 template<typename T> bool ReadBasic(T &value);
71 bool WriteString(const std::string &value);
72 bool ReadString(std::string &value);
73 bool WriteVector(const std::vector<uint8_t> &value);
74 bool ReadVector(std::vector<uint8_t> &value);
75 bool WriteVariant(const UDVariant &value);
76 bool ReadVariant(UDVariant &value);
77 bool WriteMap(const UDDetails &value);
78 bool ReadMap(UDDetails &value);
79
80 private:
81 bool WriteVariantInner(TAG &tag, const UDVariant &value);
82 bool ReadVariantInner(uint16_t tag, UDVariant &value);
83 bool ReadHead(TLVHead &head);
84 void WriteHead(uint16_t type, size_t tagCursor, uint32_t len);
85 bool HasExpectBuffer(const uint32_t expectLen) const;
86 void PrepareHeader(size_t size, size_t &tagCursor, size_t &valueCursor);
87 void PrepareBuffer(size_t size);
88 bool SaveBufferToFile();
89 bool LoadBufferFormFile(size_t size);
90
91 private:
92 std::size_t total_ = 0;
93 std::size_t cursor_ = 0;
94 std::vector<std::uint8_t> *buffer_;
95 std::FILE *file_ = nullptr;
96 };
97
98 template<typename T>
WriteBasic(TAG type,const T & value)99 bool TLVObject::WriteBasic(TAG type, const T &value)
100 {
101 PrepareBuffer(sizeof(TLVHead) + sizeof(value));
102 if (!HasExpectBuffer(sizeof(TLVHead) + sizeof(value))) {
103 return false;
104 }
105 auto *tlvHead = reinterpret_cast<TLVHead*>(buffer_->data() + cursor_);
106 tlvHead->tag = HostToNet(static_cast<uint16_t>(type));
107 tlvHead->len = HostToNet((uint32_t)sizeof(value));
108 auto valueBuff = HostToNet(value);
109 size_t maxSize = sizeof(value) + 1;
110 auto ret = memcpy_s(tlvHead->value, maxSize, &valueBuff, sizeof(value));
111 if (ret != EOK) {
112 return false;
113 }
114 if (!SaveBufferToFile()) {
115 return false;
116 }
117 cursor_ += sizeof(TLVHead) + sizeof(value);
118 return true;
119 }
120
121 template<typename T>
ReadBasic(T & value)122 bool TLVObject::ReadBasic(T &value)
123 {
124 TLVHead head {};
125 if (!ReadHead(head)) {
126 return false;
127 }
128 if (head.len == 0 || head.len != sizeof(T)) {
129 return false;
130 }
131 if (!HasExpectBuffer(head.len)) {
132 return false;
133 }
134 if (!LoadBufferFormFile(head.len)) {
135 return false;
136 }
137 auto ret = memcpy_s(&value, sizeof(T), buffer_->data() + cursor_, sizeof(T));
138 if (ret != EOK) {
139 return false;
140 }
141 value = NetToHost(value);
142 cursor_ += sizeof(T);
143 if (file_ != nullptr) {
144 cursor_ += sizeof(TLVHead);
145 }
146 return true;
147 }
148
149 } // namespace UDMF
150 } // namespace OHOS
151 #endif // UDMF_TLV_OBJECT_H