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_UTIL_H
17 #define UDMF_TLV_UTIL_H
18 
19 
20 #include <utility>
21 #include <vector>
22 #include "unified_types.h"
23 #include "unified_data.h"
24 #include "unified_key.h"
25 #include "tlv_object.h"
26 #include "unified_record.h"
27 
28 
29 namespace OHOS {
30 namespace TLVUtil {
31 using namespace OHOS::UDMF;
32 
33 template <typename T> bool API_EXPORT ReadTlv(T &output, TLVObject &data, TAG tag);
34 
35 template <typename T> size_t API_EXPORT CountBufferSize(const T &input, TLVObject &data);
36 template <typename T> bool API_EXPORT Writing(const T &input, TLVObject &data, TAG tag);
37 template <typename T> bool API_EXPORT Reading(T &output, TLVObject &data, const TLVHead &head);
38 
39 template <typename... _Types> size_t API_EXPORT CountBufferSize(const std::variant<_Types...> &input, TLVObject &data);
40 template <typename... _Types> bool API_EXPORT Writing(const std::variant<_Types...> &input, TLVObject &data, TAG tag);
41 template <typename... _Types>
42 bool API_EXPORT Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head);
43 
44 template <typename T> size_t API_EXPORT CountBufferSize(const std::shared_ptr<T> &input, TLVObject &data);
45 template <typename T> bool API_EXPORT Writing(const std::shared_ptr<T> &input, TLVObject &data, TAG tag);
46 template <typename T> bool API_EXPORT Reading(std::shared_ptr<T> &output, TLVObject &data, const TLVHead &head);
47 
48 template <typename T> size_t API_EXPORT CountBufferSize(const std::vector<T> &input, TLVObject &data);
49 template <typename T> bool API_EXPORT Writing(const std::vector<T> &input, TLVObject &data, TAG tag);
50 template <typename T> bool API_EXPORT Reading(std::vector<T> &output, TLVObject &data, const TLVHead &head);
51 
52 template <typename T, typename R> size_t API_EXPORT CountBufferSize(const std::map<T, R> &input, TLVObject &data);
53 template <typename T, typename R> bool API_EXPORT Writing(const std::map<T, R> &input, TLVObject &data, TAG tag);
54 template <typename T, typename R> bool API_EXPORT Reading(std::map<T, R> &output, TLVObject &data, const TLVHead &head);
55 
56 template <> size_t API_EXPORT CountBufferSize(const std::nullptr_t &input, TLVObject &data);
57 template <> bool API_EXPORT Writing(const std::nullptr_t &input, TLVObject &data, TAG tag);
58 template <> bool API_EXPORT Reading(std::nullptr_t &output, TLVObject &data, const TLVHead &head);
59 
60 template <> size_t API_EXPORT CountBufferSize(const std::monostate &input, TLVObject &data);
61 template <> bool API_EXPORT Writing(const std::monostate &input, TLVObject &data, TAG tag);
62 template <> bool API_EXPORT Reading(std::monostate &output, TLVObject &data, const TLVHead &head);
63 
64 template <> size_t API_EXPORT CountBufferSize(const std::string &input, TLVObject &data);
65 template <> bool API_EXPORT Writing(const std::string &input, TLVObject &data, TAG tag);
66 template <> bool API_EXPORT Reading(std::string &output, TLVObject &data, const TLVHead &head);
67 
68 template <> size_t API_EXPORT CountBufferSize(const std::vector<uint8_t> &input, TLVObject &data);
69 template <> bool API_EXPORT Writing(const std::vector<uint8_t> &input, TLVObject &data, TAG tag);
70 template <> bool API_EXPORT Reading(std::vector<uint8_t> &output, TLVObject &data, const TLVHead &head);
71 
72 template <> size_t API_EXPORT CountBufferSize(const UDType &input, TLVObject &data);
73 template <> bool API_EXPORT Writing(const UDType &input, TLVObject &data, TAG tag);
74 template <> bool API_EXPORT Reading(UDType &output, TLVObject &data, const TLVHead &head);
75 
76 template <> size_t API_EXPORT CountBufferSize(const DataStatus &input, TLVObject &data);
77 template <> bool API_EXPORT Writing(const DataStatus &input, TLVObject &data, TAG tag);
78 template <> bool API_EXPORT Reading(DataStatus &output, TLVObject &data, const TLVHead &head);
79 
80 template <> size_t API_EXPORT CountBufferSize(const Object &input, TLVObject &data);
81 template <> bool API_EXPORT Writing(const Object &input, TLVObject &data, TAG tag);
82 template <> bool API_EXPORT Reading(Object &output, TLVObject &data, const TLVHead &head);
83 
84 template <> size_t API_EXPORT CountBufferSize(const UnifiedKey &input, TLVObject &data);
85 template <> bool API_EXPORT Writing(const UnifiedKey &input, TLVObject &data, TAG tag);
86 template <> bool API_EXPORT Reading(UnifiedKey &output, TLVObject &data, const TLVHead &head);
87 
88 template <> size_t API_EXPORT CountBufferSize(const UnifiedData &input, TLVObject &data);
89 template <> bool API_EXPORT Writing(const UnifiedData &input, TLVObject &data, TAG tag);
90 template <> bool API_EXPORT Reading(UnifiedData &output, TLVObject &data, const TLVHead &head);
91 
92 template <> size_t API_EXPORT CountBufferSize(const UnifiedRecord &input, TLVObject &data);
93 template <> bool API_EXPORT Writing(const UnifiedRecord &input, TLVObject &data, TAG tag);
94 template <> bool API_EXPORT Reading(UnifiedRecord &output, TLVObject &data, const TLVHead &head);
95 
96 template <> size_t API_EXPORT CountBufferSize(const Runtime &input, TLVObject &data);
97 template <> bool API_EXPORT Writing(const Runtime &input, TLVObject &data, TAG tag);
98 template <> bool API_EXPORT Reading(Runtime &output, TLVObject &data, const TLVHead &head);
99 
100 template <> size_t API_EXPORT CountBufferSize(const Privilege &input, TLVObject &data);
101 template <> bool API_EXPORT Writing(const Privilege &input, TLVObject &data, TAG tag);
102 template <> bool API_EXPORT Reading(Privilege &output, TLVObject &data, const TLVHead &head);
103 
104 template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr<OHOS::Media::PixelMap> &input, TLVObject &data);
105 template <> bool API_EXPORT Writing(const std::shared_ptr<OHOS::Media::PixelMap> &input, TLVObject &data, TAG tag);
106 template <>
107 bool API_EXPORT Reading(std::shared_ptr<OHOS::Media::PixelMap> &output, TLVObject &data, const TLVHead &head);
108 
109 template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr<OHOS::AAFwk::Want> &input, TLVObject &data);
110 template <> bool API_EXPORT Writing(const std::shared_ptr<OHOS::AAFwk::Want> &input, TLVObject &data, TAG tag);
111 template <> bool API_EXPORT Reading(std::shared_ptr<OHOS::AAFwk::Want> &output, TLVObject &data, const TLVHead &head);
112 
ReadTlv(T & output,TLVObject & data,TAG tag)113 template <typename T> bool ReadTlv(T &output, TLVObject &data, TAG tag)
114 {
115     while (data.GetCursor() < data.GetTotal()) {
116         TLVHead head{};
117         if (!data.ReadHead(head)) {
118             return false;
119         }
120         if (head.tag != static_cast<uint16_t>(tag)) {
121             data.Skip(head);
122             continue;
123         }
124         if (!Reading(output, data, head)) {
125             return false;
126         }
127     }
128     return true;
129 }
130 
InitWhenFirst(T input,TLVObject & data)131 template <typename T> void InitWhenFirst(T input, TLVObject &data)
132 {
133     if (data.GetCursor() == data.GetTotal()) {
134         CountBufferSize(input, data);
135         data.UpdateSize();
136     }
137 }
138 
CountBufferSize(const T & input,TLVObject & data)139 template <typename T> size_t CountBufferSize(const T &input, TLVObject &data)
140 {
141     return data.CountBasic(input);
142 }
143 
Writing(const T & input,TLVObject & data,TAG tag)144 template <typename T> bool Writing(const T &input, TLVObject &data, TAG tag)
145 {
146     InitWhenFirst(input, data);
147     return data.WriteBasic(tag, input);
148 }
149 
Reading(T & output,TLVObject & data,const TLVHead & head)150 template <typename T> bool Reading(T &output, TLVObject &data, const TLVHead &head)
151 {
152     return data.ReadBasic(output, head);
153 }
154 
CountBufferSize(const std::shared_ptr<T> & input,TLVObject & data)155 template <typename T> size_t CountBufferSize(const std::shared_ptr<T> &input, TLVObject &data)
156 {
157     if (input == nullptr) {
158         return data.CountHead();
159     }
160     return CountBufferSize(*input, data);
161 }
162 
Writing(const std::shared_ptr<T> & input,TLVObject & data,TAG tag)163 template <typename T> bool Writing(const std::shared_ptr<T> &input, TLVObject &data, TAG tag)
164 {
165     if (input == nullptr) {
166         return false;
167     }
168     InitWhenFirst(input, data);
169     return Writing(*input, data, tag);
170 }
171 
Reading(std::shared_ptr<T> & output,TLVObject & data,const TLVHead & head)172 template <typename T> bool Reading(std::shared_ptr<T> &output, TLVObject &data, const TLVHead &head)
173 {
174     if (output == nullptr) {
175         output = std::make_shared<T>();
176     }
177     return Reading(*output, data, head);
178 }
179 
CountBufferSize(const std::vector<T> & input,TLVObject & data)180 template <typename T> size_t CountBufferSize(const std::vector<T> &input, TLVObject &data)
181 {
182     auto size = data.CountHead() + data.CountBasic(input.size());
183     for (auto item : input) {
184         size += CountBufferSize(item, data);
185     }
186     return size;
187 }
188 
Writing(const std::vector<T> & input,TLVObject & data,TAG tag)189 template <typename T> bool Writing(const std::vector<T> &input, TLVObject &data, TAG tag)
190 {
191     InitWhenFirst(input, data);
192     auto tagCursor = data.GetCursor();
193     data.OffsetHead();
194     if (!data.WriteBasic(TAG::TAG_VECTOR_SIZE, input.size())) {
195         return false;
196     }
197     if (!input.empty()) {
198         for (auto item : input) {
199             if (!Writing(item, data, TAG::TAG_VECTOR_ITEM)) {
200                 return false;
201             }
202         }
203     }
204     return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
205 }
206 
Reading(std::vector<T> & output,TLVObject & data,const TLVHead & head)207 template <typename T> bool Reading(std::vector<T> &output, TLVObject &data, const TLVHead &head)
208 {
209     auto endCursor = data.GetCursor() + head.len;
210     while (data.GetCursor() < endCursor) {
211         TLVHead itemHead{};
212         if (!data.ReadHead(itemHead)) {
213             return false;
214         }
215         if (itemHead.tag == static_cast<uint16_t>(TAG::TAG_VECTOR_ITEM)) {
216             T item{};
217             if (!Reading(item, data, itemHead)) {
218                 return false;
219             }
220             output.push_back(std::move(item));
221             continue;
222         }
223         if (!data.Skip(itemHead)) {
224             return false;
225         }
226     }
227     return true;
228 }
229 
CountBufferSize(const std::map<T,R> & input,TLVObject & data)230 template <typename T, typename R> size_t CountBufferSize(const std::map<T, R> &input, TLVObject &data)
231 {
232     auto size = data.CountHead();
233     for (auto item : input) {
234         size += data.CountHead() + CountBufferSize(item.first, data) + CountBufferSize(item.second, data);
235     }
236     return size;
237 }
238 
Writing(const std::map<T,R> & input,TLVObject & data,TAG tag)239 template <typename T, typename R> bool Writing(const std::map<T, R> &input, TLVObject &data, TAG tag)
240 {
241     InitWhenFirst(input, data);
242     auto tagCursor = data.GetCursor();
243     data.OffsetHead();
244     if (!input.empty()) {
245         for (auto item : input) {
246             auto pairCursor = data.GetCursor();
247             data.OffsetHead();
248             if (!TLVUtil::Writing(item.first, data, TAG::TAG_MAP_KEY)) {
249                 return false;
250             }
251             if (!TLVUtil::Writing(item.second, data, TAG::TAG_MAP_VALUE)) {
252                 return false;
253             }
254             if (!data.WriteBackHead(static_cast<uint16_t>(TAG::TAG_MAP_PAIR), pairCursor,
255                 data.GetCursor() - pairCursor - sizeof(TLVHead))) {
256                 return false;
257             }
258         }
259     }
260     return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
261 }
262 
Reading(std::map<T,R> & output,TLVObject & data,const TLVHead & head)263 template <typename T, typename R> bool Reading(std::map<T, R> &output, TLVObject &data, const TLVHead &head)
264 {
265     auto endCursor = data.GetCursor() + head.len;
266     while (data.GetCursor() < endCursor) {
267         TLVHead headPair{};
268         if (!data.ReadHead(headPair)) {
269             return false;
270         }
271         if (headPair.tag != static_cast<uint16_t>(TAG::TAG_MAP_PAIR)) {
272             return false;
273         }
274         TLVHead headKey{};
275         if (!data.ReadHead(headKey) || headKey.tag != static_cast<uint16_t>(TAG::TAG_MAP_KEY)) {
276             return false;
277         }
278         T itemKey{};
279         if (!Reading(itemKey, data, headKey)) {
280             return false;
281         }
282         TLVHead headValue{};
283         if (!data.ReadHead(headValue) || headValue.tag != static_cast<uint16_t>(TAG::TAG_MAP_VALUE)) {
284             return false;
285         }
286         R itemValue{};
287         if (!Reading(itemValue, data, headValue)) {
288             return false;
289         }
290         output.emplace(std::move(itemKey), std::move(itemValue));
291     }
292     return true;
293 }
294 
CountVariant(TLVObject & data,uint32_t step,const _InTp & input)295 template <typename _InTp> size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input)
296 {
297     return 0;
298 }
299 
300 template <typename _InTp, typename _First, typename... _Rest>
CountVariant(TLVObject & data,uint32_t step,const _InTp & input)301 size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input)
302 {
303     if (step == input.index()) {
304         return CountBufferSize(std::get<_First>(input), data);
305     }
306     return CountVariant<_InTp, _Rest...>(data, step + 1, input);
307 }
308 
CountBufferSize(const std::variant<_Types...> & input,TLVObject & data)309 template <typename... _Types> size_t CountBufferSize(const std::variant<_Types...> &input, TLVObject &data)
310 {
311     if (input.index() > size_t(std::numeric_limits<uint32_t>::max())) {
312         return 0;
313     }
314     uint32_t index = static_cast<uint32_t>(input.index());
315     return data.CountHead() + data.CountBasic(index) + CountVariant<decltype(input), _Types...>(data, 0, input);
316 }
317 
WriteVariant(TLVObject & data,uint32_t step,const _InTp & input,TAG tag)318 template <typename _InTp> bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag)
319 {
320     return true;
321 }
322 
323 template <typename _InTp, typename _First, typename... _Rest>
WriteVariant(TLVObject & data,uint32_t step,const _InTp & input,TAG tag)324 bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag)
325 {
326     if (step == input.index()) {
327         auto val = std::get<_First>(input);
328         return Writing(val, data, tag);
329     }
330     return WriteVariant<_InTp, _Rest...>(data, step + 1, input, tag);
331 }
332 
Writing(const std::variant<_Types...> & input,TLVObject & data,TAG tag)333 template <typename... _Types> bool Writing(const std::variant<_Types...> &input, TLVObject &data, TAG tag)
334 {
335     InitWhenFirst(input, data);
336     auto tagCursor = data.GetCursor();
337     data.OffsetHead();
338     uint32_t index = input.index();
339     if (!data.WriteBasic(TAG::TAG_VARIANT_INDEX, index)) {
340         return false;
341     }
342     if (!WriteVariant<decltype(input), _Types...>(data, 0, input, TAG::TAG_VARIANT_ITEM)) {
343         return false;
344     }
345     return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
346 }
347 
ReadVariant(TLVObject & data,uint32_t step,uint32_t index,_OutTp & value,TLVHead head)348 template <typename _OutTp> bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head)
349 {
350     return true;
351 }
352 
353 template <typename _OutTp, typename _First, typename... _Rest>
ReadVariant(TLVObject & data,uint32_t step,uint32_t index,_OutTp & value,TLVHead head)354 bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head)
355 {
356     if (step == index) {
357         _First output{};
358         auto success = Reading(output, data, head);
359         value = output;
360         return success;
361     }
362     return ReadVariant<_OutTp, _Rest...>(data, step + 1, index, value, head);
363 }
364 
Reading(std::variant<_Types...> & output,TLVObject & data,const TLVHead & head)365 template <typename... _Types> bool Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head)
366 {
367     uint32_t index = 0;
368     auto endCursor = data.GetCursor() + head.len;
369     while (data.GetCursor() < endCursor) {
370         TLVHead headItem{};
371         if (!data.ReadHead(headItem)) {
372             return false;
373         }
374         if (headItem.tag == static_cast<uint16_t>(TAG::TAG_VARIANT_INDEX)) {
375             if (!Reading(index, data, headItem)) {
376                 return false;
377             }
378         } else {
379             return ReadVariant<decltype(output), _Types...>(data, 0, index, output, headItem);
380         }
381     }
382     return true;
383 }
384 } // namespace TLVUtil
385 } // namespace OHOS
386 #endif // UDMF_TLV_UTIL_H
387