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