/* * 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. */ #define LOG_TAG "TlvUtil" #include "tlv_util.h" #include "udmf_utils.h" #include "logger.h" #include "tlv_object.h" namespace OHOS { namespace TLVUtil { template <> size_t CountBufferSize(const std::nullptr_t &input, TLVObject &data) { return data.CountHead(); } template <> bool Writing(const std::nullptr_t &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); return data.WriteHead(static_cast(tag), 0); } template <> bool Reading(std::nullptr_t &output, TLVObject &data, const TLVHead &head) { return data.Read(output, head); } template <> size_t CountBufferSize(const std::monostate &input, TLVObject &data) { return data.Count(input); } template <> bool Writing(const std::monostate &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); return data.Write(tag, input); } template <> bool Reading(std::monostate &output, TLVObject &data, const TLVHead &head) { return data.Read(output, head); } template <> size_t CountBufferSize(const std::string &input, TLVObject &data) { return data.Count(input); } template <> bool Writing(const std::string &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); return data.Write(tag, input); } template <> bool Reading(std::string &output, TLVObject &data, const TLVHead &head) { return data.Read(output, head); } template <> size_t CountBufferSize(const std::vector &input, TLVObject &data) { return data.Count(input); } template <> bool Writing(const std::vector &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); return data.Write(tag, input); } template <> bool Reading(std::vector &output, TLVObject &data, const TLVHead &head) { return data.Read(output, head); } template <> size_t CountBufferSize(const UDType &input, TLVObject &data) { int32_t type = input; return data.CountBasic(type); } template <> bool Writing(const UDType &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); int32_t type = input; return data.WriteBasic(tag, type); } template <> bool Reading(UDType &output, TLVObject &data, const TLVHead &head) { int32_t type; if (!Reading(type, data, head)) { return false; } if (type < UDType::ENTITY || type >= UDType::UD_BUTT) { return false; } output = static_cast(type); return true; } template <> size_t CountBufferSize(const DataStatus &input, TLVObject &data) { int32_t status = input; return data.CountBasic(status); } template <> bool Writing(const DataStatus &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); int32_t status = input; return data.WriteBasic(tag, status); } template <> bool Reading(DataStatus &output, TLVObject &data, const TLVHead &head) { int32_t status; if (!data.ReadBasic(status, head)) { return false; } if (status < DataStatus::WORKING || status >= DataStatus::FADE) { return false; } output = static_cast(status); return true; } template <> size_t CountBufferSize(const Object &input, TLVObject &data) { return data.CountHead() + CountBufferSize(input.value_, data); } template <> bool Writing(const Object &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); if (!Writing(input.value_, data, TAG::TAG_OBJECT_VALUE)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Object &output, TLVObject &data, const TLVHead &head) { TLVHead headValue{}; if (!data.ReadHead(headValue)) { return false; } if (headValue.tag != static_cast(TAG::TAG_OBJECT_VALUE)) { return false; } if (!Reading(output.value_, data, headValue)) { return false; } return true; } template <> size_t CountBufferSize(const UnifiedKey &input, TLVObject &data) { return data.CountHead() + data.Count(input.key) + data.Count(input.intention) + data.Count(input.bundleName) + data.Count(input.groupId); } template <> bool Writing(const UnifiedKey &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); if (!data.Write(TAG::TAG_KEY, input.key)) { return false; } if (!data.Write(TAG::TAG_INTENTION, input.intention)) { return false; } if (!data.Write(TAG::TAG_BUNDLE_NAME, input.bundleName)) { return false; } if (!data.Write(TAG::TAG_GROUP_ID, input.groupId)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(UnifiedKey &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; if (!data.ReadHead(headItem)) { return false; } switch (headItem.tag) { case static_cast(TAG::TAG_KEY): if (!data.Read(output.key, headItem)) { return false; } break; case static_cast(TAG::TAG_INTENTION): if (!data.Read(output.intention, headItem)) { return false; } break; case static_cast(TAG::TAG_BUNDLE_NAME): if (!data.Read(output.bundleName, headItem)) { return false; } break; case static_cast(TAG::TAG_GROUP_ID): if (!data.Read(output.groupId, headItem)) { return false; } break; default: data.Skip(headItem); } } return true; } template <> size_t CountBufferSize(const UnifiedData &input, TLVObject &data) { std::string version = UTILS::GetCurrentSdkVersion(); return data.CountHead() + data.Count(version) + TLVUtil::CountBufferSize(input.GetRecords(), data); } template <> bool Writing(const UnifiedData &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); std::string version = UTILS::GetCurrentSdkVersion(); if (!data.Write(TAG::TAG_VERSION, version)) { return false; } if (!TLVUtil::Writing(input.GetRecords(), data, TAG::TAG_UNIFIED_RECORD)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(UnifiedData &output, TLVObject &data, const TLVHead &head) { 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_VERSION)) { data.Skip(headItem); continue; } if (headItem.tag == static_cast(TAG::TAG_UNIFIED_RECORD)) { auto records = output.GetRecords(); if (!Reading(records, data, headItem)) { return false; } output.SetRecords(records); continue; } data.Skip(headItem); } return true; } template <> size_t CountBufferSize(const UnifiedRecord &input, TLVObject &data) { std::string version = UTILS::GetCurrentSdkVersion(); return data.CountHead() + data.Count(version) + data.CountBasic(static_cast(input.GetType())) + data.Count(input.GetUid()) + CountBufferSize(input.GetOriginValue(), data); } template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); std::string version = UTILS::GetCurrentSdkVersion(); if (!data.Write(TAG::TAG_VERSION, version)) { return false; } if (!data.WriteBasic(TAG::TAG_UD_TYPE, static_cast(input.GetType()))) { return false; } if (!data.Write(TAG::TAG_UID, input.GetUid())) { return false; } if (!TLVUtil::Writing(input.GetOriginValue(), data, TAG::TAG_RECORD_VALUE)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; UDType dataType; std::string uid; ValueType value; while (data.GetCursor() < endCursor) { TLVHead headItem{}; if (!data.ReadHead(headItem)) { return false; } switch (headItem.tag) { case static_cast(TAG::TAG_VERSION): data.Skip(headItem); break; case static_cast(TAG::TAG_UD_TYPE): if (!TLVUtil::Reading(dataType, data, headItem)) { return false; } output.SetType(dataType); break; case static_cast(TAG::TAG_UID): if (!data.Read(uid, headItem)) { return false; } output.SetUid(uid); break; case static_cast(TAG::TAG_RECORD_VALUE): if (!TLVUtil::Reading(value, data, headItem)) { return false; } output.SetValue(value); break; default: data.Skip(headItem); } } return true; } template <> size_t CountBufferSize(const Runtime &input, TLVObject &data) { std::string version = UTILS::GetCurrentSdkVersion(); return data.CountHead() + data.CountBasic(input.isPrivate) + data.CountBasic(input.dataVersion) + data.CountBasic(input.recordTotalNum) + data.CountBasic(input.tokenId) + data.CountBasic(static_cast(input.createTime)) + data.CountBasic(static_cast(input.lastModifiedTime)) + data.CountBasic(static_cast(input.dataStatus)) + data.Count(input.sourcePackage) + data.Count(input.createPackage) + data.Count(input.deviceId) + TLVUtil::CountBufferSize(input.key, data) + data.Count(version) + TLVUtil::CountBufferSize(input.privileges, data); } template <> bool Writing(const Runtime &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); std::string version = UTILS::GetCurrentSdkVersion(); if (!TLVUtil::Writing(version, data, TAG::TAG_VERSION)) { return false; } if (!TLVUtil::Writing(input.key, data, TAG::TAG_KEY)) { return false; } if (!data.WriteBasic(TAG::TAG_IS_PRIVATE, input.isPrivate)) { return false; } if (!TLVUtil::Writing(input.privileges, data, TAG::TAG_PRIVILEGE)) { return false; } if (!data.WriteBasic(TAG::TAG_CREATE_TIME, static_cast(input.createTime))) { return false; } if (!data.Write(TAG::TAG_SOURCE_PACKAGE, input.sourcePackage)) { return false; } if (!data.WriteBasic(TAG::TAG_DATA_STATUS, static_cast(input.dataStatus))) { return false; } if (!data.WriteBasic(TAG::TAG_DATA_VERSION, input.dataVersion)) { return false; } if (!data.WriteBasic(TAG::TAG_LAST_MODIFIED_TIME, static_cast(input.lastModifiedTime))) { return false; } if (!data.Write(TAG::TAG_CREATE_PACKAGE, input.createPackage)) { return false; } if (!data.Write(TAG::TAG_DEVICE_ID, input.deviceId)) { return false; } if (!data.WriteBasic(TAG::TAG_RECORD_TOTAL_NUM, input.recordTotalNum)) { return false; } if (!data.WriteBasic(TAG::TAG_TOKEN_ID, input.tokenId)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; if (!data.ReadHead(headItem)) { return false; } bool result = true; int64_t createTime = 0; int64_t lastModifiedTime = 0; switch (headItem.tag) { case static_cast(TAG::TAG_KEY): result = TLVUtil::Reading(output.key, data, headItem); break; case static_cast(TAG::TAG_IS_PRIVATE): result = data.ReadBasic(output.isPrivate, headItem); break; case static_cast(TAG::TAG_PRIVILEGE): result = TLVUtil::Reading(output.privileges, data, headItem); break; case static_cast(TAG::TAG_CREATE_TIME): result = data.ReadBasic(createTime, headItem); output.createTime = static_cast(createTime); break; case static_cast(TAG::TAG_SOURCE_PACKAGE): result = data.Read(output.sourcePackage, headItem); break; case static_cast(TAG::TAG_DATA_STATUS): result = TLVUtil::Reading(output.dataStatus, data, headItem); break; case static_cast(TAG::TAG_DATA_VERSION): result = data.ReadBasic(output.dataVersion, headItem); break; case static_cast(TAG::TAG_LAST_MODIFIED_TIME): result = data.ReadBasic(lastModifiedTime, headItem); output.lastModifiedTime = static_cast(lastModifiedTime); break; case static_cast(TAG::TAG_CREATE_PACKAGE): result = data.Read(output.createPackage, headItem); break; case static_cast(TAG::TAG_DEVICE_ID): result = data.Read(output.deviceId, headItem); break; case static_cast(TAG::TAG_RECORD_TOTAL_NUM): result = data.ReadBasic(output.recordTotalNum, headItem); break; case static_cast(TAG::TAG_TOKEN_ID): result = data.ReadBasic(output.tokenId, headItem); break; default: result = data.Skip(headItem); } if (!result) { return false; } } return true; } template <> size_t CountBufferSize(const Privilege &input, TLVObject &data) { return data.CountHead() + data.CountBasic(input.tokenId) + data.Count(input.readPermission) + data.Count(input.writePermission); } template <> bool Writing(const Privilege &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); auto tagCursor = data.GetCursor(); data.OffsetHead(); if (!data.WriteBasic(TAG::TAG_TOKEN_ID, input.tokenId)) { return false; } if (!data.Write(TAG::TAG_READPERMISSION, input.readPermission)) { return false; } if (!data.Write(TAG::TAG_WRITEPERMISSION, input.writePermission)) { return false; } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Privilege &output, TLVObject &data, const TLVHead &head) { auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; if (!data.ReadHead(headItem)) { return false; } switch (headItem.tag) { case static_cast(TAG::TAG_TOKEN_ID): if (!data.ReadBasic(output.tokenId, headItem)) { return false; } break; case static_cast(TAG::TAG_READPERMISSION): if (!data.Read(output.readPermission, headItem)) { return false; } break; case static_cast(TAG::TAG_WRITEPERMISSION): if (!data.Read(output.writePermission, headItem)) { return false; } break; default: data.Skip(headItem); } } return true; } template <> size_t CountBufferSize(const std::shared_ptr &input, TLVObject &data) { std::vector val; if (!input->EncodeTlv(val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when CountBufferSize"); return 0; } return CountBufferSize(val, data); } template <> bool Writing(const std::shared_ptr &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); std::vector val; if (!input->EncodeTlv(val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when Writing"); return false; } return data.Write(tag, val); } template <> bool Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head) { std::vector val; if (!data.Read(val, head)) { LOG_ERROR(UDMF_FRAMEWORK, "Reading u8 vector error."); return false; } output = std::shared_ptr(OHOS::Media::PixelMap::DecodeTlv(val)); if (output == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "DecodeTlv pixelMap error when Reading."); return false; } return true; } template <> size_t CountBufferSize(const std::shared_ptr &input, TLVObject &data) { Parcel parcel; if (!input->Marshalling(parcel)) { LOG_ERROR(UDMF_FRAMEWORK, "Marshalling want error when Count"); return 0; } auto size = parcel.GetDataSize(); std::vector val(size); return CountBufferSize(val, data); } template <> bool Writing(const std::shared_ptr &input, TLVObject &data, TAG tag) { InitWhenFirst(input, data); Parcel parcel; if (!input->Marshalling(parcel)) { LOG_ERROR(UDMF_FRAMEWORK, "Marshalling want error in tlv write. tag=%{public}hu", tag); return false; } auto size = parcel.GetDataSize(); auto buffer = parcel.GetData(); std::vector val(size); if (size != 0) { auto err = memcpy_s(val.data(), size, reinterpret_cast(buffer), size); if (err != EOK) { LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write want. tag=%{public}hu", tag); return false; } } return data.Write(tag, val); } template <> bool Reading(std::shared_ptr &output, TLVObject &data, const TLVHead &head) { std::vector val; if (!data.Read(val, head)) { LOG_ERROR(UDMF_FRAMEWORK, "Reading u8 vector error."); return false; } std::shared_ptr parcel = std::make_shared(); auto buffer = malloc(val.size()); if (buffer == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "malloc error in tlv read. tag=%{public}hu", head.tag); return false; } auto err = memcpy_s(buffer, val.size(), val.data(), val.size()); if (err != EOK) { LOG_ERROR(UDMF_FRAMEWORK, "memcpy_s error in tlv read want. tag=%{public}hu", head.tag); return false; } if (!parcel->ParseFrom((uintptr_t)buffer, head.len)) { LOG_ERROR(UDMF_FRAMEWORK, "ParseFrom error in tlv read want. tag=%{public}hu", head.tag); return false; } auto want = AAFwk::Want::Unmarshalling(*parcel); if (want == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshalling want error in tlv read. tag=%{public}hu", head.tag); return false; } output = std::shared_ptr(want); return true; } } // namespace TLVUtil } // namespace OHOS