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 UriInfo &input, TLVObject &data);
105 template <> bool API_EXPORT Writing(const UriInfo &input, TLVObject &data, TAG tag);
106 template <> bool API_EXPORT Reading(UriInfo &output, TLVObject &data, const TLVHead &head);
107
108 template <> bool API_EXPORT Reading(ShareOptions &output, TLVObject &data, const TLVHead &head);
109
110 template <> size_t API_EXPORT CountBufferSize(const UnifiedDataProperties &input, TLVObject &data);
111 template <> bool API_EXPORT Writing(const UnifiedDataProperties &input, TLVObject &data, TAG tag);
112 template <> bool API_EXPORT Reading(UnifiedDataProperties &output, TLVObject &data, const TLVHead &head);
113
114 template <> size_t API_EXPORT CountBufferSize(const OHOS::AAFwk::WantParams &input, TLVObject &data);
115 template <> bool API_EXPORT Writing(const OHOS::AAFwk::WantParams &input, TLVObject &data, TAG tag);
116 template <> bool API_EXPORT Reading(OHOS::AAFwk::WantParams &output, TLVObject &data, const TLVHead &head);
117
118 template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr<OHOS::Media::PixelMap> &input, TLVObject &data);
119 template <> bool API_EXPORT Writing(const std::shared_ptr<OHOS::Media::PixelMap> &input, TLVObject &data, TAG tag);
120 template <>
121 bool API_EXPORT Reading(std::shared_ptr<OHOS::Media::PixelMap> &output, TLVObject &data, const TLVHead &head);
122
123 template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr<std::map<std::string, ValueType>> &input,
124 TLVObject &data);
125 template <> bool API_EXPORT Writing(const std::shared_ptr<std::map<std::string, ValueType>> &input,
126 TLVObject &data, TAG tag);
127 template <>
128 bool API_EXPORT Reading(std::shared_ptr<std::map<std::string, ValueType>> &output,
129 TLVObject &data, const TLVHead &head);
130
131 template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr<OHOS::AAFwk::Want> &input, TLVObject &data);
132 template <> bool API_EXPORT Writing(const std::shared_ptr<OHOS::AAFwk::Want> &input, TLVObject &data, TAG tag);
133 template <> bool API_EXPORT Reading(std::shared_ptr<OHOS::AAFwk::Want> &output, TLVObject &data, const TLVHead &head);
134
135 template <> size_t API_EXPORT CountBufferSize(const Summary &input, TLVObject &data);
136 template <> bool API_EXPORT Writing(const Summary &input, TLVObject &data, TAG tag);
137 template <> bool API_EXPORT Reading(Summary &output, TLVObject &data, const TLVHead &head);
138
ReadTlv(T & output,TLVObject & data,TAG tag)139 template <typename T> bool ReadTlv(T &output, TLVObject &data, TAG tag)
140 {
141 while (data.GetCursor() < data.GetTotal()) {
142 TLVHead head{};
143 if (!data.ReadHead(head)) {
144 return false;
145 }
146 if (head.tag != static_cast<uint16_t>(tag)) {
147 data.Skip(head);
148 continue;
149 }
150 if (!Reading(output, data, head)) {
151 return false;
152 }
153 }
154 return true;
155 }
156
InitWhenFirst(T & input,TLVObject & data)157 template <typename T> void InitWhenFirst(T &input, TLVObject &data)
158 {
159 if (data.GetCursor() == data.GetTotal()) {
160 CountBufferSize(input, data);
161 data.UpdateSize();
162 }
163 }
164
CountBufferSize(const T & input,TLVObject & data)165 template <typename T> size_t CountBufferSize(const T &input, TLVObject &data)
166 {
167 return data.CountBasic(input);
168 }
169
Writing(const T & input,TLVObject & data,TAG tag)170 template <typename T> bool Writing(const T &input, TLVObject &data, TAG tag)
171 {
172 InitWhenFirst(input, data);
173 return data.WriteBasic(tag, input);
174 }
175
Reading(T & output,TLVObject & data,const TLVHead & head)176 template <typename T> bool Reading(T &output, TLVObject &data, const TLVHead &head)
177 {
178 return data.ReadBasic(output, head);
179 }
180
CountBufferSize(const std::shared_ptr<T> & input,TLVObject & data)181 template <typename T> size_t CountBufferSize(const std::shared_ptr<T> &input, TLVObject &data)
182 {
183 if (input == nullptr) {
184 return data.CountHead();
185 }
186 return CountBufferSize(*input, data);
187 }
188
Writing(const std::shared_ptr<T> & input,TLVObject & data,TAG tag)189 template <typename T> bool Writing(const std::shared_ptr<T> &input, TLVObject &data, TAG tag)
190 {
191 if (input == nullptr) {
192 return false;
193 }
194 InitWhenFirst(input, data);
195 return Writing(*input, data, tag);
196 }
197
Reading(std::shared_ptr<T> & output,TLVObject & data,const TLVHead & head)198 template <typename T> bool Reading(std::shared_ptr<T> &output, TLVObject &data, const TLVHead &head)
199 {
200 if (output == nullptr) {
201 output = std::make_shared<T>();
202 }
203 return Reading(*output, data, head);
204 }
205
CountBufferSize(const std::vector<T> & input,TLVObject & data)206 template <typename T> size_t CountBufferSize(const std::vector<T> &input, TLVObject &data)
207 {
208 auto size = data.CountHead() + data.CountBasic(input.size());
209 for (auto item : input) {
210 size += CountBufferSize(item, data);
211 }
212 return size;
213 }
214
Writing(const std::vector<T> & input,TLVObject & data,TAG tag)215 template <typename T> bool Writing(const std::vector<T> &input, TLVObject &data, TAG tag)
216 {
217 InitWhenFirst(input, data);
218 auto tagCursor = data.GetCursor();
219 data.OffsetHead();
220 if (!data.WriteBasic(TAG::TAG_VECTOR_SIZE, input.size())) {
221 return false;
222 }
223 if (!input.empty()) {
224 for (auto item : input) {
225 if (!Writing(item, data, TAG::TAG_VECTOR_ITEM)) {
226 return false;
227 }
228 }
229 }
230 return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
231 }
232
Reading(std::vector<T> & output,TLVObject & data,const TLVHead & head)233 template <typename T> bool Reading(std::vector<T> &output, TLVObject &data, const TLVHead &head)
234 {
235 auto endCursor = data.GetCursor() + head.len;
236 while (data.GetCursor() < endCursor) {
237 TLVHead itemHead{};
238 if (!data.ReadHead(itemHead)) {
239 return false;
240 }
241 if (itemHead.tag == static_cast<uint16_t>(TAG::TAG_VECTOR_ITEM)) {
242 T item{};
243 if (!Reading(item, data, itemHead)) {
244 return false;
245 }
246 output.push_back(std::move(item));
247 continue;
248 }
249 if (!data.Skip(itemHead)) {
250 return false;
251 }
252 }
253 return true;
254 }
255
CountBufferSize(const std::map<T,R> & input,TLVObject & data)256 template <typename T, typename R> size_t CountBufferSize(const std::map<T, R> &input, TLVObject &data)
257 {
258 auto size = data.CountHead();
259 for (auto item : input) {
260 size += data.CountHead() + CountBufferSize(item.first, data) + CountBufferSize(item.second, data);
261 }
262 return size;
263 }
264
Writing(const std::map<T,R> & input,TLVObject & data,TAG tag)265 template <typename T, typename R> bool Writing(const std::map<T, R> &input, TLVObject &data, TAG tag)
266 {
267 InitWhenFirst(input, data);
268 auto tagCursor = data.GetCursor();
269 data.OffsetHead();
270 if (!input.empty()) {
271 for (auto item : input) {
272 auto pairCursor = data.GetCursor();
273 data.OffsetHead();
274 if (!TLVUtil::Writing(item.first, data, TAG::TAG_MAP_KEY)) {
275 return false;
276 }
277 if (!TLVUtil::Writing(item.second, data, TAG::TAG_MAP_VALUE)) {
278 return false;
279 }
280 if (!data.WriteBackHead(static_cast<uint16_t>(TAG::TAG_MAP_PAIR), pairCursor,
281 data.GetCursor() - pairCursor - sizeof(TLVHead))) {
282 return false;
283 }
284 }
285 }
286 return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
287 }
288
Reading(std::map<T,R> & output,TLVObject & data,const TLVHead & head)289 template <typename T, typename R> bool Reading(std::map<T, R> &output, TLVObject &data, const TLVHead &head)
290 {
291 auto endCursor = data.GetCursor() + head.len;
292 while (data.GetCursor() < endCursor) {
293 TLVHead headPair{};
294 if (!data.ReadHead(headPair)) {
295 return false;
296 }
297 if (headPair.tag != static_cast<uint16_t>(TAG::TAG_MAP_PAIR)) {
298 return false;
299 }
300 TLVHead headKey{};
301 if (!data.ReadHead(headKey) || headKey.tag != static_cast<uint16_t>(TAG::TAG_MAP_KEY)) {
302 return false;
303 }
304 T itemKey{};
305 if (!Reading(itemKey, data, headKey)) {
306 return false;
307 }
308 TLVHead headValue{};
309 if (!data.ReadHead(headValue) || headValue.tag != static_cast<uint16_t>(TAG::TAG_MAP_VALUE)) {
310 return false;
311 }
312 R itemValue{};
313 if (!Reading(itemValue, data, headValue)) {
314 return false;
315 }
316 output.emplace(std::move(itemKey), std::move(itemValue));
317 }
318 return true;
319 }
320
CountVariant(TLVObject & data,uint32_t step,const _InTp & input)321 template <typename _InTp> size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input)
322 {
323 return 0;
324 }
325
326 template <typename _InTp, typename _First, typename... _Rest>
CountVariant(TLVObject & data,uint32_t step,const _InTp & input)327 size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input)
328 {
329 if (step == input.index()) {
330 return CountBufferSize(std::get<_First>(input), data);
331 }
332 return CountVariant<_InTp, _Rest...>(data, step + 1, input);
333 }
334
CountBufferSize(const std::variant<_Types...> & input,TLVObject & data)335 template <typename... _Types> size_t CountBufferSize(const std::variant<_Types...> &input, TLVObject &data)
336 {
337 if (input.index() > size_t(std::numeric_limits<uint32_t>::max())) {
338 return 0;
339 }
340 uint32_t index = static_cast<uint32_t>(input.index());
341 return data.CountHead() + data.CountBasic(index) + CountVariant<decltype(input), _Types...>(data, 0, input);
342 }
343
WriteVariant(TLVObject & data,uint32_t step,const _InTp & input,TAG tag)344 template <typename _InTp> bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag)
345 {
346 return true;
347 }
348
349 template <typename _InTp, typename _First, typename... _Rest>
WriteVariant(TLVObject & data,uint32_t step,const _InTp & input,TAG tag)350 bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag)
351 {
352 if (step == input.index()) {
353 auto val = std::get<_First>(input);
354 return Writing(val, data, tag);
355 }
356 return WriteVariant<_InTp, _Rest...>(data, step + 1, input, tag);
357 }
358
Writing(const std::variant<_Types...> & input,TLVObject & data,TAG tag)359 template <typename... _Types> bool Writing(const std::variant<_Types...> &input, TLVObject &data, TAG tag)
360 {
361 InitWhenFirst(input, data);
362 auto tagCursor = data.GetCursor();
363 data.OffsetHead();
364 uint32_t index = input.index();
365 if (!data.WriteBasic(TAG::TAG_VARIANT_INDEX, index)) {
366 return false;
367 }
368 if (!WriteVariant<decltype(input), _Types...>(data, 0, input, TAG::TAG_VARIANT_ITEM)) {
369 return false;
370 }
371 return data.WriteBackHead(static_cast<uint16_t>(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead));
372 }
373
ReadVariant(TLVObject & data,uint32_t step,uint32_t index,_OutTp & value,TLVHead head)374 template <typename _OutTp> bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head)
375 {
376 return true;
377 }
378
379 template <typename _OutTp, typename _First, typename... _Rest>
ReadVariant(TLVObject & data,uint32_t step,uint32_t index,_OutTp & value,TLVHead head)380 bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head)
381 {
382 if (step == index) {
383 _First output{};
384 auto success = Reading(output, data, head);
385 value = output;
386 return success;
387 }
388 return ReadVariant<_OutTp, _Rest...>(data, step + 1, index, value, head);
389 }
390
Reading(std::variant<_Types...> & output,TLVObject & data,const TLVHead & head)391 template <typename... _Types> bool Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head)
392 {
393 uint32_t index = 0;
394 auto endCursor = data.GetCursor() + head.len;
395 while (data.GetCursor() < endCursor) {
396 TLVHead headItem{};
397 if (!data.ReadHead(headItem)) {
398 return false;
399 }
400 if (headItem.tag == static_cast<uint16_t>(TAG::TAG_VARIANT_INDEX)) {
401 if (!Reading(index, data, headItem)) {
402 return false;
403 }
404 } else {
405 return ReadVariant<decltype(output), _Types...>(data, 0, index, output, headItem);
406 }
407 }
408 return true;
409 }
410 } // namespace TLVUtil
411 } // namespace OHOS
412 #endif // UDMF_TLV_UTIL_H
413