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#include "map_data_sequenceable.h"
17#include "hdi_log.h"
18#include <message_parcel.h>
19namespace OHOS {
20namespace HDI {
21namespace Camera {
22namespace V1_0 {
23constexpr int32_t BUFFER_DATA_MAGIC = 0x4567;
24constexpr int32_t BUFFER_MAX_USER_DATA_COUNT = 1000;
25
26enum ErrorCode : int32_t {
27    ERROR_OK = 0,
28    ERROR_INTERNAL = -1,
29    ERROR_NO_ENTRY = -2,
30    ERROR_TYPE_ERROR = -3,
31    ERROR_OUT_OF_RANGE = -4,
32};
33
34#define SET_DATA_FROM_POINTER(data, pointer) do { \
35    if ((pointer) != nullptr) { \
36        (data) = *(pointer); \
37    } \
38} while (0)
39
40sptr<MapDataSequenceable> MapDataSequenceable::Unmarshalling(Parcel &parcel)
41{
42    int32_t magic;
43    if (parcel.ReadInt32(magic) == false || magic != BUFFER_DATA_MAGIC) {
44        HDI_CAMERA_LOGW("read failed, magic is error");
45        return nullptr;
46    }
47
48    int32_t size = parcel.ReadInt32();
49    if (size > BUFFER_MAX_USER_DATA_COUNT) {
50        HDI_CAMERA_LOGE("Too much data obtained from Parcel");
51        return nullptr;
52    }
53    sptr<MapDataSequenceable> sequenceData(new MapDataSequenceable());
54
55    int32_t ret = ERROR_OK;
56    for (int32_t i = 0; i < size; i++) {
57        auto key = parcel.ReadString();
58        auto type = static_cast<MapDataType>(parcel.ReadInt32());
59        switch (type) {
60            case MapDataType::I32: {
61                ret = sequenceData->Set(key, type, parcel.ReadInt32());
62                break;
63            }
64            case MapDataType::I64: {
65                ret = sequenceData->Set(key, type, parcel.ReadInt64());
66                break;
67            }
68            case MapDataType::F64: {
69                ret = sequenceData->Set(key, type, parcel.ReadDouble());
70                break;
71            }
72            case MapDataType::STRING: {
73                ret = sequenceData->Set(key, type, parcel.ReadString());
74                break;
75            }
76            default: break;
77        }
78
79        if (ret != ERROR_OK) {
80            HDI_CAMERA_LOGE("Set extra data failed, return %{public}d", ret);
81            return nullptr;
82        }
83    }
84    return sequenceData;
85}
86
87bool MapDataSequenceable::Marshalling(Parcel &parcel) const
88{
89    OHOS::MessageParcel &dataParcel = static_cast<OHOS::MessageParcel &>(parcel);
90    std::lock_guard<std::mutex> lockGuard(mtx_);
91    dataParcel.WriteInt32(BUFFER_DATA_MAGIC);
92    dataParcel.WriteInt32(datas_.size());
93    for (const auto &[key, data] : datas_) {
94        dataParcel.WriteString(key);
95        dataParcel.WriteInt32(static_cast<int32_t>(data.type));
96        switch (data.type) {
97            case MapDataType::I32: {
98                int32_t i32 = -1;
99                auto pVal = std::any_cast<int32_t>(&data.val);
100                SET_DATA_FROM_POINTER(i32, pVal);
101                dataParcel.WriteInt32(i32);
102                break;
103            }
104            case MapDataType::I64: {
105                int64_t i64 = -1;
106                auto pVal = std::any_cast<int64_t>(&data.val);
107                SET_DATA_FROM_POINTER(i64, pVal);
108                dataParcel.WriteInt64(i64);
109                break;
110            }
111            case MapDataType::F64: {
112                double f64 = -1;
113                auto pVal = std::any_cast<double>(&data.val);
114                SET_DATA_FROM_POINTER(f64, pVal);
115                dataParcel.WriteDouble(f64);
116                break;
117            }
118            case MapDataType::STRING: {
119                std::string string = "-1";
120                auto pVal = std::any_cast<std::string>(&data.val);
121                SET_DATA_FROM_POINTER(string, pVal);
122                dataParcel.WriteString(string);
123                break;
124            }
125            default:
126                break;
127        }
128    }
129    return true;
130}
131
132int32_t MapDataSequenceable::Get(const std::string &key, int32_t &value) const
133{
134    return Get<int32_t>(key, MapDataType::I32, value);
135}
136
137int32_t MapDataSequenceable::Get(const std::string &key, int64_t &value) const
138{
139    return Get<int64_t>(key, MapDataType::I64, value);
140}
141
142int32_t MapDataSequenceable::Get(const std::string &key, double &value) const
143{
144    return Get<double>(key, MapDataType::F64, value);
145}
146
147int32_t MapDataSequenceable::Get(const std::string &key, std::string &value) const
148{
149    return Get<std::string>(key, MapDataType::STRING, value);
150}
151
152int32_t MapDataSequenceable::Set(const std::string &key, int32_t value)
153{
154    return Set(key, MapDataType::I32, value);
155}
156
157int32_t MapDataSequenceable::Set(const std::string &key, int64_t value)
158{
159    return Set(key, MapDataType::I64, value);
160}
161
162int32_t MapDataSequenceable::Set(const std::string &key, double value)
163{
164    return Set(key, MapDataType::F64, value);
165}
166
167int32_t MapDataSequenceable::Set(const std::string &key, const std::string& value)
168{
169    return Set(key, MapDataType::STRING, value);
170}
171
172template<class T>
173int32_t MapDataSequenceable::Get(const std::string &key, MapDataType type, T &value) const
174{
175    std::lock_guard<std::mutex> lockGuard(mtx_);
176    auto it = datas_.find(key);
177    if (it == datas_.end()) {
178        return ERROR_NO_ENTRY;
179    }
180    if (it->second.type != type) {
181        return ERROR_TYPE_ERROR;
182    }
183    auto pVal = std::any_cast<T>(&it->second.val);
184    if (pVal == nullptr) {
185        return ERROR_TYPE_ERROR;
186    }
187    value = *pVal;
188    return ERROR_OK;
189}
190
191int32_t MapDataSequenceable::Set(const std::string &key, MapDataType type, const std::any& val)
192{
193    std::lock_guard<std::mutex> lockGuard(mtx_);
194    auto it = datas_.find(key);
195    if (it == datas_.end() && datas_.size() > BUFFER_MAX_USER_DATA_COUNT) {
196        HDI_CAMERA_LOGW("SurfaceBuffer has too many extra data, cannot save one more!!!");
197        return ERROR_OUT_OF_RANGE;
198    }
199    datas_[key].type = type;
200    datas_[key].val = val;
201    return ERROR_OK;
202}
203
204}
205}
206}
207}