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