1/*
2 * Copyright (c) 2023-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#include "common/log.h"
17#include "meta/any.h"
18#include <map>
19
20namespace {
21constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Any" };
22}
23
24namespace {
25using namespace OHOS::Media;
26using BaseTypesMap = std::map<std::string, AnyValueType>;
27
28const BaseTypesMap &GetBaseTypesMap()
29{
30    static const BaseTypesMap baseTypeMap([]() {
31        BaseTypesMap typeMap;
32        Any defaultBool = (bool)true;
33        typeMap[std::string(defaultBool.TypeName())] = AnyValueType::BOOL;
34        Any defaultInt32 = (int32_t)0;
35        typeMap[std::string(defaultInt32.TypeName())] = AnyValueType::INT32_T;
36        Any defaultInt64 = (int64_t)0;
37        typeMap[std::string(defaultInt64.TypeName())] = AnyValueType::INT64_T;
38        Any defaultFoalt = (float)0.0;
39        typeMap[std::string(defaultFoalt.TypeName())] = AnyValueType::FLOAT;
40        Any defaultDouble = (double)0.0;
41        typeMap[std::string(defaultDouble.TypeName())] = AnyValueType::DOUBLE;
42        Any defaultString = std::string();
43        typeMap[std::string(defaultString.TypeName())] = AnyValueType::STRING;
44        Any defaultVecUint8 = std::vector<uint8_t>();
45        typeMap[std::string(defaultVecUint8.TypeName())] = AnyValueType::VECTOR_UINT8;
46        return typeMap;
47    }());
48    return baseTypeMap;
49}
50} // namespace
51
52namespace OHOS {
53namespace Media {
54bool Any::BaseTypesToParcel(const Any *operand, MessageParcel &parcel) noexcept
55{
56    auto iter = GetBaseTypesMap().find(std::string(operand->TypeName()));
57    if (iter == GetBaseTypesMap().end()) {
58        parcel.WriteInt32(static_cast<int32_t>(AnyValueType::INVALID_TYPE));
59        return false;
60    }
61    bool ret = parcel.WriteInt32(static_cast<int32_t>(iter->second));
62    switch (iter->second) {
63        case AnyValueType::BOOL:
64            ret = ret && parcel.WriteBool(*AnyCast<bool>(operand));
65            break;
66        case AnyValueType::INT32_T:
67            ret = ret && parcel.WriteInt32(*AnyCast<int32_t>(operand));
68            break;
69        case AnyValueType::INT64_T:
70            ret = ret && parcel.WriteInt64(*AnyCast<int64_t>(operand));
71            break;
72        case AnyValueType::FLOAT:
73            ret = ret && parcel.WriteFloat(*AnyCast<float>(operand));
74            break;
75        case AnyValueType::DOUBLE:
76            ret = ret && parcel.WriteDouble(*AnyCast<double>(operand));
77            break;
78        case AnyValueType::STRING:
79            ret = ret && parcel.WriteString(*AnyCast<std::string>(operand));
80            break;
81        case AnyValueType::VECTOR_UINT8:
82            ret = ret && parcel.WriteUInt8Vector(*AnyCast<std::vector<uint8_t>>(operand));
83            break;
84        default: {
85            parcel.WriteInt32(static_cast<int32_t>(AnyValueType::INVALID_TYPE));
86            return false;
87        }
88    }
89    return ret;
90}
91
92enum class StatusCodeFromParcel {
93    SUCCESS = 0,
94    ENUM_RETRY = 1,
95    NO_RETRY = 2,
96};
97
98// returnValue : 0 -- success; 1 -- retry for enum type; 2 -- failed no retry
99int Any::BaseTypesFromParcel(Any *operand, MessageParcel &parcel) noexcept
100{
101    AnyValueType type = static_cast<AnyValueType>(parcel.ReadInt32());
102    switch (type) {
103        case AnyValueType::BOOL: {
104            Any tmp(parcel.ReadBool());
105            operand->Swap(tmp);
106            break;
107        }
108        case AnyValueType::INT32_T: {
109            Any tmp(parcel.ReadInt32());
110            operand->Swap(tmp);
111            break;
112        }
113        case AnyValueType::INT64_T: {
114            Any tmp(parcel.ReadInt64());
115            operand->Swap(tmp);
116            break;
117        }
118        case AnyValueType::FLOAT: {
119            Any tmp(parcel.ReadFloat());
120            operand->Swap(tmp);
121            break;
122        }
123        case AnyValueType::DOUBLE: {
124            Any tmp(parcel.ReadDouble());
125            operand->Swap(tmp);
126            break;
127        }
128        case AnyValueType::STRING: {
129            Any tmp(parcel.ReadString());
130            operand->Swap(tmp);
131            break;
132        }
133        case AnyValueType::VECTOR_UINT8: {
134            std::vector<uint8_t> val;
135            (void)parcel.ReadUInt8Vector(&val);
136            Any tmp(val);
137            operand->Swap(tmp);
138            break;
139        }
140        case AnyValueType::INVALID_TYPE:
141            return static_cast<int>(StatusCodeFromParcel::ENUM_RETRY);
142        default:
143            return static_cast<int>(StatusCodeFromParcel::NO_RETRY);
144    }
145    return static_cast<int>(StatusCodeFromParcel::SUCCESS);
146}
147
148/**
149 * Get TypeName From function info.
150 * Extract the Type name out of Function Info
151 * @param functionInfo Function Info
152 * @return Name of Type T ,Such as <b>bool int float double std::vector<unsigned char></b> etc.
153 * @example In windows with MEDIA_NO_OHOS define,
154 * FunctionInfo will be like <br>
155 * static constexpr std::string_view OHOS::Media::Any::GetTypeName()
156 * [with T = <b>bool</b>; std::string_view = std::basic_string_view<char>] <br>
157 * with MEDIA_OHOS define, FunctionInfo will be like <br>
158 * static std::string_view OHOS::Media::Any::GetTypeName() [T = <b>std::vector<unsigned char></b>]  <br>
159 * For EnumType , FunctionInfo will be like <br>
160 * static std::string_view OHOS::Media::Any::GetTypeName() [T = <b>OHOS::Media::Plugins::VideoEncodeBitrateMode</b>]
161 */
162std::string_view Any::GetTypeNameFromFunctionInfo(const char* functionInfo) noexcept
163{
164    std::string_view stringInfo = functionInfo;
165    std::string_view retType = "Unknown";
166    size_t beginIndex = stringInfo.find_first_of('=');
167    if (beginIndex == std::string::npos) {
168        MEDIA_LOG_E("GetTypeNameFromFunctionInfo failed. Function: " PUBLIC_LOG_S, stringInfo.data());
169        return retType;
170    } else {
171        beginIndex += 2; // 2 表示右移两位
172    }
173#ifdef MEDIA_OHOS
174    size_t endIndex = stringInfo.find_last_of(']');
175#else
176    size_t endIndex = stringInfo.find_last_of(';');
177#endif
178    FALSE_RETURN_V_MSG_E(endIndex != std::string::npos,
179        retType, "GetTypeNameFromFunctionInfo find Type failed. Function: " PUBLIC_LOG_S, stringInfo.data());
180    std::string_view typeNameRet(functionInfo + beginIndex, endIndex - beginIndex);
181    return typeNameRet;
182}
183} // namespace Media
184} // namespace OHOS