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