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