/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef UDMF_TLV_UTIL_H #define UDMF_TLV_UTIL_H #include #include #include "unified_types.h" #include "unified_data.h" #include "unified_key.h" #include "tlv_object.h" #include "unified_record.h" namespace OHOS { namespace TLVUtil { using namespace OHOS::UDMF; template bool API_EXPORT ReadTlv(T &output, TLVObject &data, TAG tag); template size_t API_EXPORT CountBufferSize(const T &input, TLVObject &data); template bool API_EXPORT Writing(const T &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(T &output, TLVObject &data, const TLVHead &head); template size_t API_EXPORT CountBufferSize(const std::variant<_Types...> &input, TLVObject &data); template bool API_EXPORT Writing(const std::variant<_Types...> &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head); template size_t API_EXPORT CountBufferSize(const std::shared_ptr &input, TLVObject &data); template bool API_EXPORT Writing(const std::shared_ptr &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head); template size_t API_EXPORT CountBufferSize(const std::vector &input, TLVObject &data); template bool API_EXPORT Writing(const std::vector &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::vector &output, TLVObject &data, const TLVHead &head); template size_t API_EXPORT CountBufferSize(const std::map &input, TLVObject &data); template bool API_EXPORT Writing(const std::map &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::map &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::nullptr_t &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::nullptr_t &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::nullptr_t &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::monostate &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::monostate &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::monostate &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::string &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::string &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::string &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::vector &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::vector &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::vector &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const UDType &input, TLVObject &data); template <> bool API_EXPORT Writing(const UDType &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(UDType &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const DataStatus &input, TLVObject &data); template <> bool API_EXPORT Writing(const DataStatus &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(DataStatus &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const Object &input, TLVObject &data); template <> bool API_EXPORT Writing(const Object &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(Object &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const UnifiedKey &input, TLVObject &data); template <> bool API_EXPORT Writing(const UnifiedKey &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(UnifiedKey &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const UnifiedData &input, TLVObject &data); template <> bool API_EXPORT Writing(const UnifiedData &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(UnifiedData &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const UnifiedRecord &input, TLVObject &data); template <> bool API_EXPORT Writing(const UnifiedRecord &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(UnifiedRecord &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const Runtime &input, TLVObject &data); template <> bool API_EXPORT Writing(const Runtime &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(Runtime &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const Privilege &input, TLVObject &data); template <> bool API_EXPORT Writing(const Privilege &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(Privilege &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::shared_ptr &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head); template <> size_t API_EXPORT CountBufferSize(const std::shared_ptr &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::shared_ptr &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head); template bool ReadTlv(T &output, TLVObject &data, TAG tag) { while (data.GetCursor() < data.GetTotal()) { TLVHead head{}; if (!data.ReadHead(head)) { return false; } if (head.tag != static_cast(tag)) { data.Skip(head); continue; } if (!Reading(output, data, head)) { return false; } } return true; } template void InitWhenFirst(T input, TLVObject &data) { if (data.GetCursor() == data.GetTotal()) { CountBufferSize(input, data); data.UpdateSize(); } } template size_t CountBufferSize(const T &input, TLVObject &data) { return data.CountBasic(input); } template bool Writing(const T &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); return data.WriteBasic(tag, input); } template bool Reading(T &output, TLVObject &data, const TLVHead &head) { return data.ReadBasic(output, head); } template size_t CountBufferSize(const std::shared_ptr &input, TLVObject &data) { if (input == nullptr) { return data.CountHead(); } return CountBufferSize(*input, data); } template bool Writing(const std::shared_ptr &input, TLVObject &data, TAG tag) { if (input == nullptr) { return false; } InitWhenFirst(input, data); return Writing(*input, data, tag); } template bool Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head) { if (output == nullptr) { output = std::make_shared(); } return Reading(*output, data, head); } template size_t CountBufferSize(const std::vector &input, TLVObject &data) { auto size = data.CountHead() + data.CountBasic(input.size()); for (auto item : input) { size += CountBufferSize(item, data); } return size; } template bool Writing(const std::vector &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); if (!data.WriteBasic(TAG::TAG_VECTOR_SIZE, input.size())) { return false; } if (!input.empty()) { for (auto item : input) { if (!Writing(item, data, TAG::TAG_VECTOR_ITEM)) { return false; } } } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template bool Reading(std::vector &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead itemHead{}; if (!data.ReadHead(itemHead)) { return false; } if (itemHead.tag == static_cast(TAG::TAG_VECTOR_ITEM)) { T item{}; if (!Reading(item, data, itemHead)) { return false; } output.push_back(std::move(item)); continue; } if (!data.Skip(itemHead)) { return false; } } return true; } template size_t CountBufferSize(const std::map &input, TLVObject &data) { auto size = data.CountHead(); for (auto item : input) { size += data.CountHead() + CountBufferSize(item.first, data) + CountBufferSize(item.second, data); } return size; } template bool Writing(const std::map &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); if (!input.empty()) { for (auto item : input) { auto pairCursor = data.GetCursor(); data.OffsetHead(); if (!TLVUtil::Writing(item.first, data, TAG::TAG_MAP_KEY)) { return false; } if (!TLVUtil::Writing(item.second, data, TAG::TAG_MAP_VALUE)) { return false; } if (!data.WriteBackHead(static_cast(TAG::TAG_MAP_PAIR), pairCursor, data.GetCursor() - pairCursor - sizeof(TLVHead))) { return false; } } } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template bool Reading(std::map &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headPair{}; if (!data.ReadHead(headPair)) { return false; } if (headPair.tag != static_cast(TAG::TAG_MAP_PAIR)) { return false; } TLVHead headKey{}; if (!data.ReadHead(headKey) || headKey.tag != static_cast(TAG::TAG_MAP_KEY)) { return false; } T itemKey{}; if (!Reading(itemKey, data, headKey)) { return false; } TLVHead headValue{}; if (!data.ReadHead(headValue) || headValue.tag != static_cast(TAG::TAG_MAP_VALUE)) { return false; } R itemValue{}; if (!Reading(itemValue, data, headValue)) { return false; } output.emplace(std::move(itemKey), std::move(itemValue)); } return true; } template size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input) { return 0; } template size_t CountVariant(TLVObject &data, uint32_t step, const _InTp &input) { if (step == input.index()) { return CountBufferSize(std::get<_First>(input), data); } return CountVariant<_InTp, _Rest...>(data, step + 1, input); } template size_t CountBufferSize(const std::variant<_Types...> &input, TLVObject &data) { if (input.index() > size_t(std::numeric_limits::max())) { return 0; } uint32_t index = static_cast(input.index()); return data.CountHead() + data.CountBasic(index) + CountVariant(data, 0, input); } template bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag) { return true; } template bool WriteVariant(TLVObject &data, uint32_t step, const _InTp &input, TAG tag) { if (step == input.index()) { auto val = std::get<_First>(input); return Writing(val, data, tag); } return WriteVariant<_InTp, _Rest...>(data, step + 1, input, tag); } template bool Writing(const std::variant<_Types...> &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); uint32_t index = input.index(); if (!data.WriteBasic(TAG::TAG_VARIANT_INDEX, index)) { return false; } if (!WriteVariant(data, 0, input, TAG::TAG_VARIANT_ITEM)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head) { return true; } template bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, TLVHead head) { if (step == index) { _First output{}; auto success = Reading(output, data, head); value = output; return success; } return ReadVariant<_OutTp, _Rest...>(data, step + 1, index, value, head); } template bool Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head) { uint32_t index = 0; auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; if (!data.ReadHead(headItem)) { return false; } if (headItem.tag == static_cast(TAG::TAG_VARIANT_INDEX)) { if (!Reading(index, data, headItem)) { return false; } } else { return ReadVariant(data, 0, index, output, headItem); } } return true; } } // namespace TLVUtil } // namespace OHOS #endif // UDMF_TLV_UTIL_H