1 /* 2 * Copyright (c) 2024-2024 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 CAMERA_NAPI_OBJECT_H 17 #define CAMERA_NAPI_OBJECT_H 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <list> 22 #include <string> 23 #include <unordered_map> 24 #include <unordered_set> 25 #include <variant> 26 #include <vector> 27 28 #include "js_native_api.h" 29 #include "js_native_api_types.h" 30 #include "napi/native_api.h" 31 32 namespace OHOS { 33 namespace CameraStandard { 34 struct CameraNapiObject { 35 public: 36 typedef std::variant<bool*, int32_t*, uint32_t*, int64_t*, float*, double*, std::string*, CameraNapiObject*, 37 napi_value, std::vector<int32_t>*, std::list<CameraNapiObject>*> 38 NapiVariantBindAddr; 39 40 typedef std::unordered_map<std::string, NapiVariantBindAddr> CameraNapiObjFieldMap; 41 CameraNapiObjectCameraNapiObject42 CameraNapiObject(CameraNapiObjFieldMap fieldMap) : fieldMap_(fieldMap) {} 43 ParseNapiObjectToMapCameraNapiObject44 napi_status ParseNapiObjectToMap(napi_env env, napi_value napiObject) 45 { 46 napi_valuetype type = napi_undefined; 47 napi_typeof(env, napiObject, &type); 48 if (type != napi_object) { 49 return napi_invalid_arg; 50 } 51 for (auto& it : fieldMap_) { 52 NapiVariantBindAddr& bindAddr = it.second; 53 napi_value napiObjValue = nullptr; 54 napi_status res = napi_get_named_property(env, napiObject, it.first.c_str(), &napiObjValue); 55 if (res != napi_ok) { 56 return res; 57 } 58 napi_valuetype valueType = napi_undefined; 59 napi_typeof(env, napiObjValue, &valueType); 60 if (valueType == napi_undefined && optionalKeys_.find(it.first) != optionalKeys_.end()) { 61 continue; 62 } 63 if (std::holds_alternative<bool*>(bindAddr)) { 64 res = GetVariantBoolFromNapiValue(env, napiObjValue, bindAddr); 65 } else if (std::holds_alternative<int32_t*>(bindAddr)) { 66 res = GetVariantInt32FromNapiValue(env, napiObjValue, bindAddr); 67 } else if (std::holds_alternative<uint32_t*>(bindAddr)) { 68 res = GetVariantUint32FromNapiValue(env, napiObjValue, bindAddr); 69 } else if (std::holds_alternative<int64_t*>(bindAddr)) { 70 res = GetVariantInt64FromNapiValue(env, napiObjValue, bindAddr); 71 } else if (std::holds_alternative<float*>(bindAddr)) { 72 res = GetVariantFloatFromNapiValue(env, napiObjValue, bindAddr); 73 } else if (std::holds_alternative<double*>(bindAddr)) { 74 res = GetVariantDoubleFromNapiValue(env, napiObjValue, bindAddr); 75 } else if (std::holds_alternative<std::string*>(bindAddr)) { 76 res = GetVariantStringFromNapiValue(env, napiObjValue, bindAddr); 77 } else if (std::holds_alternative<CameraNapiObject*>(bindAddr)) { 78 res = GetVariantCameraNapiObjectFromNapiValue(env, napiObjValue, bindAddr); 79 } else { 80 res = napi_invalid_arg; 81 } 82 if (res != napi_ok) { 83 return res; 84 } 85 settedKeys_.emplace(it.first); 86 } 87 return napi_ok; 88 }; 89 SetOptionalKeysCameraNapiObject90 void SetOptionalKeys(std::unordered_set<std::string>& keys) 91 { 92 optionalKeys_ = keys; 93 } 94 IsKeySettedCameraNapiObject95 bool IsKeySetted(const std::string& key) 96 { 97 return settedKeys_.find(key) != settedKeys_.end(); 98 } 99 CreateNapiObjFromMapCameraNapiObject100 napi_value CreateNapiObjFromMap(napi_env env) 101 { 102 napi_value result = nullptr; 103 if (fieldMap_.empty()) { 104 napi_get_undefined(env, &result); 105 return result; 106 } 107 napi_create_object(env, &result); 108 for (auto& it : fieldMap_) { 109 NapiVariantBindAddr& bindAddr = it.second; 110 napi_value fieldValue = std::visit(CreateNapiObjVisitor(env), bindAddr); 111 napi_set_named_property(env, result, it.first.c_str(), fieldValue); 112 } 113 return result; 114 } 115 116 private: 117 class CreateNapiObjVisitor { 118 public: CreateNapiObjVisitorCameraNapiObject119 explicit CreateNapiObjVisitor(napi_env& env) : env_(env) {} operatorCameraNapiObject120 napi_value operator()(bool*& variantAddr) 121 { 122 napi_value result = nullptr; 123 napi_status status = napi_get_boolean(env_, *variantAddr, &result); 124 return status == napi_ok ? result : nullptr; 125 } operatorCameraNapiObject126 napi_value operator()(int32_t*& variantAddr) 127 { 128 napi_value result = nullptr; 129 napi_status status = napi_create_int32(env_, *variantAddr, &result); 130 return status == napi_ok ? result : nullptr; 131 } operatorCameraNapiObject132 napi_value operator()(uint32_t*& variantAddr) 133 { 134 napi_value result = nullptr; 135 napi_status status = napi_create_uint32(env_, *variantAddr, &result); 136 return status == napi_ok ? result : nullptr; 137 } operatorCameraNapiObject138 napi_value operator()(int64_t*& variantAddr) 139 { 140 napi_value result = nullptr; 141 napi_status status = napi_create_int64(env_, *variantAddr, &result); 142 return status == napi_ok ? result : nullptr; 143 } operatorCameraNapiObject144 napi_value operator()(float*& variantAddr) 145 { 146 napi_value result = nullptr; 147 napi_status status = napi_create_double(env_, *variantAddr, &result); 148 return status == napi_ok ? result : nullptr; 149 } operatorCameraNapiObject150 napi_value operator()(double*& variantAddr) 151 { 152 napi_value result = nullptr; 153 napi_status status = napi_create_double(env_, *variantAddr, &result); 154 return status == napi_ok ? result : nullptr; 155 } operatorCameraNapiObject156 napi_value operator()(std::string*& variantAddr) 157 { 158 napi_value result = nullptr; 159 napi_status status = napi_create_string_utf8(env_, variantAddr->c_str(), variantAddr->size(), &result); 160 return status == napi_ok ? result : nullptr; 161 } operatorCameraNapiObject162 napi_value operator()(CameraNapiObject*& variantAddr) 163 { 164 return variantAddr->CreateNapiObjFromMap(env_); 165 } operatorCameraNapiObject166 napi_value operator()(napi_value& variantAddr) 167 { 168 return variantAddr; 169 } operatorCameraNapiObject170 napi_value operator()(std::vector<int32_t>*& variantAddr) 171 { 172 napi_value result = nullptr; 173 napi_status status = napi_create_array(env_, &result); 174 if (status != napi_ok) { 175 return nullptr; 176 } 177 auto& nativeArray = *variantAddr; 178 for (size_t i = 0; i < nativeArray.size(); i++) { 179 napi_value item = nullptr; 180 napi_create_int32(env_, nativeArray[i], &item); 181 if (napi_set_element(env_, result, i, item) != napi_ok) { 182 return nullptr; 183 } 184 } 185 return result; 186 } operatorCameraNapiObject187 napi_value operator()(std::list<CameraNapiObject>*& variantAddr) 188 { 189 napi_value result = nullptr; 190 napi_status status = napi_create_array(env_, &result); 191 if (status != napi_ok) { 192 return nullptr; 193 } 194 auto& nativeArray = *variantAddr; 195 size_t index = 0; 196 for (auto& obj : nativeArray) { 197 if (napi_set_element(env_, result, index, obj.CreateNapiObjFromMap(env_)) != napi_ok) { 198 return nullptr; 199 } 200 index++; 201 } 202 return result; 203 } 204 205 private: 206 napi_env& env_; 207 }; 208 GetVariantBoolFromNapiValueCameraNapiObject209 napi_status GetVariantBoolFromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 210 { 211 if (!ValidNapiType(env, napiValue, napi_boolean)) { 212 return napi_invalid_arg; 213 } 214 auto variantAddrPointer = std::get_if<bool*>(&variantAddr); 215 if (variantAddrPointer == nullptr) { 216 return napi_invalid_arg; 217 } 218 return napi_get_value_bool(env, napiValue, *variantAddrPointer); 219 }; 220 GetVariantInt32FromNapiValueCameraNapiObject221 napi_status GetVariantInt32FromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 222 { 223 if (!ValidNapiType(env, napiValue, napi_number)) { 224 return napi_invalid_arg; 225 } 226 auto variantAddrPointer = std::get_if<int32_t*>(&variantAddr); 227 if (variantAddrPointer == nullptr) { 228 return napi_invalid_arg; 229 } 230 return napi_get_value_int32(env, napiValue, *variantAddrPointer); 231 }; 232 GetVariantUint32FromNapiValueCameraNapiObject233 napi_status GetVariantUint32FromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 234 { 235 if (!ValidNapiType(env, napiValue, napi_number)) { 236 return napi_invalid_arg; 237 } 238 auto variantAddrPointer = std::get_if<uint32_t*>(&variantAddr); 239 if (variantAddrPointer == nullptr) { 240 return napi_invalid_arg; 241 } 242 return napi_get_value_uint32(env, napiValue, *variantAddrPointer); 243 }; 244 GetVariantInt64FromNapiValueCameraNapiObject245 napi_status GetVariantInt64FromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 246 { 247 if (!ValidNapiType(env, napiValue, napi_number)) { 248 return napi_invalid_arg; 249 } 250 auto variantAddrPointer = std::get_if<int64_t*>(&variantAddr); 251 if (variantAddrPointer == nullptr) { 252 return napi_invalid_arg; 253 } 254 return napi_get_value_int64(env, napiValue, *variantAddrPointer); 255 }; 256 GetVariantFloatFromNapiValueCameraNapiObject257 napi_status GetVariantFloatFromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 258 { 259 if (!ValidNapiType(env, napiValue, napi_number)) { 260 return napi_invalid_arg; 261 } 262 auto variantAddrPointer = std::get_if<float*>(&variantAddr); 263 if (variantAddrPointer == nullptr) { 264 return napi_invalid_arg; 265 } 266 double tmpData = 0; 267 napi_status res = napi_get_value_double(env, napiValue, &tmpData); 268 **variantAddrPointer = tmpData; 269 return res; 270 }; 271 GetVariantDoubleFromNapiValueCameraNapiObject272 napi_status GetVariantDoubleFromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 273 { 274 if (!ValidNapiType(env, napiValue, napi_number)) { 275 return napi_invalid_arg; 276 } 277 auto variantAddrPointer = std::get_if<double*>(&variantAddr); 278 if (variantAddrPointer == nullptr) { 279 return napi_invalid_arg; 280 } 281 return napi_get_value_double(env, napiValue, *variantAddrPointer); 282 }; 283 GetVariantStringFromNapiValueCameraNapiObject284 napi_status GetVariantStringFromNapiValue(napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 285 { 286 if (!ValidNapiType(env, napiValue, napi_string)) { 287 return napi_invalid_arg; 288 } 289 290 auto variantAddrPointer = std::get_if<std::string*>(&variantAddr); 291 if (variantAddrPointer == nullptr) { 292 return napi_invalid_arg; 293 } 294 295 size_t stringSize = 0; 296 napi_status res = napi_get_value_string_utf8(env, napiValue, nullptr, 0, &stringSize); 297 if (res != napi_ok) { 298 return res; 299 } 300 auto& stringValue = **variantAddrPointer; 301 stringValue.resize(stringSize); 302 res = napi_get_value_string_utf8(env, napiValue, stringValue.data(), stringSize + 1, &stringSize); 303 return res; 304 }; 305 GetVariantCameraNapiObjectFromNapiValueCameraNapiObject306 napi_status GetVariantCameraNapiObjectFromNapiValue( 307 napi_env env, napi_value napiValue, NapiVariantBindAddr& variantAddr) 308 { 309 if (!ValidNapiType(env, napiValue, napi_object)) { 310 return napi_invalid_arg; 311 } 312 auto variantAddrPointer = std::get_if<CameraNapiObject*>(&variantAddr); 313 if (variantAddrPointer == nullptr) { 314 return napi_invalid_arg; 315 } 316 return (*variantAddrPointer)->ParseNapiObjectToMap(env, napiValue); 317 } 318 ValidNapiTypeCameraNapiObject319 bool ValidNapiType(napi_env env, napi_value napiObjValue, napi_valuetype valueType) 320 { 321 napi_valuetype objValueType = napi_undefined; 322 napi_status res = napi_typeof(env, napiObjValue, &objValueType); 323 if (res != napi_ok) { 324 return false; 325 } 326 return objValueType == valueType; 327 } 328 329 CameraNapiObjFieldMap fieldMap_; 330 std::unordered_set<std::string> optionalKeys_; 331 std::unordered_set<std::string> settedKeys_; 332 }; 333 } // namespace CameraStandard 334 } // namespace OHOS 335 #endif /* CAMERA_NAPI_OBJECT_H */ 336