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_PARAM_PARSER_H 17 #define CAMERA_NAPI_PARAM_PARSER_H 18 19 #include <cmath> 20 #include <cstddef> 21 #include <cstdint> 22 #include <memory> 23 #include <set> 24 #include <stdint.h> 25 #include <string> 26 #include <unordered_map> 27 #include <unordered_set> 28 #include <utility> 29 #include <variant> 30 31 #include "camera_error_code.h" 32 #include "camera_napi_const.h" 33 #include "camera_napi_object.h" 34 #include "js_native_api.h" 35 #include "js_native_api_types.h" 36 #include "napi/native_api.h" 37 38 namespace OHOS { 39 namespace CameraStandard { 40 enum CameraNapiAsyncFunctionType : int32_t { ASYNC_FUN_TYPE_NONE, ASYNC_FUN_TYPE_CALLBACK, ASYNC_FUN_TYPE_PROMISE }; 41 struct CameraNapiAsyncFunction { 42 public: CameraNapiAsyncFunctionCameraNapiAsyncFunction43 CameraNapiAsyncFunction(napi_env env, const char* resourceName, napi_ref& callbackRef, napi_deferred& deferred) 44 { 45 env_ = env; 46 status_ = napi_create_string_utf8(env, resourceName, NAPI_AUTO_LENGTH, &(resourceName_)); 47 if (status_ != napi_ok) { 48 return; 49 } 50 callbackRefPtr_ = &callbackRef; 51 deferred_ = &deferred; 52 } 53 GetResourceNameCameraNapiAsyncFunction54 inline napi_value GetResourceName() 55 { 56 return resourceName_; 57 } 58 IsStatusOkCameraNapiAsyncFunction59 inline bool IsStatusOk() 60 { 61 return status_ == napi_ok; 62 } 63 GetPromiseCameraNapiAsyncFunction64 inline napi_value GetPromise() 65 { 66 if (status_ != napi_ok) { 67 return nullptr; 68 } 69 return promise_; 70 } 71 GetAsyncFunctionTypeCameraNapiAsyncFunction72 inline CameraNapiAsyncFunctionType GetAsyncFunctionType() 73 { 74 return asyncFunctionType_; 75 } 76 AssertStatusCameraNapiAsyncFunction77 inline bool AssertStatus(CameraErrorCode errorCode, const char* message) 78 { 79 if (status_ != napi_ok) { 80 napi_throw_error(env_, std::to_string(errorCode).c_str(), message); 81 } 82 return status_ == napi_ok; 83 } 84 ResetCameraNapiAsyncFunction85 void Reset() 86 { 87 if (callbackRefPtr_ != nullptr && *callbackRefPtr_ != nullptr) { 88 napi_delete_reference(env_, *callbackRefPtr_); 89 *callbackRefPtr_ = nullptr; 90 } 91 if (deferred_ != nullptr && *deferred_ != nullptr) { 92 napi_value rejection = nullptr; 93 napi_get_undefined(env_, &rejection); 94 napi_reject_deferred(env_, *deferred_, rejection); 95 *deferred_ = nullptr; 96 } 97 } 98 99 private: CreatePromiseCameraNapiAsyncFunction100 napi_status CreatePromise() 101 { 102 if (status_ != napi_ok) { 103 return status_; 104 } 105 status_ = napi_create_promise(env_, deferred_, &promise_); 106 if (status_ == napi_ok) { 107 asyncFunctionType_ = ASYNC_FUN_TYPE_PROMISE; 108 } 109 return status_; 110 } 111 CreateCallbackCameraNapiAsyncFunction112 inline napi_status CreateCallback(napi_value callback) 113 { 114 if (status_ != napi_ok) { 115 return status_; 116 } 117 status_ = napi_create_reference(env_, callback, 1, callbackRefPtr_); 118 if (status_ == napi_ok) { 119 asyncFunctionType_ = ASYNC_FUN_TYPE_CALLBACK; 120 } 121 return status_; 122 } 123 124 napi_env env_ = nullptr; 125 napi_status status_ = napi_invalid_arg; 126 napi_value resourceName_ = nullptr; 127 napi_ref* callbackRefPtr_ = nullptr; 128 napi_deferred* deferred_ = nullptr; 129 napi_value promise_ = nullptr; 130 CameraNapiAsyncFunctionType asyncFunctionType_ = ASYNC_FUN_TYPE_NONE; 131 132 friend class CameraNapiParamParser; 133 }; 134 135 class CameraNapiParamParser { 136 public: 137 template<typename T> CameraNapiParamParser(napi_env env,napi_callback_info info,T * & nativeObjPointer)138 explicit CameraNapiParamParser(napi_env env, napi_callback_info info, T*& nativeObjPointer) 139 : CameraNapiParamParser(env, info, 0, nativeObjPointer, nullptr) 140 {} 141 142 template<typename T> CameraNapiParamParser(napi_env env,napi_callback_info info,T * & nativeObjPointer,std::shared_ptr<CameraNapiAsyncFunction> asyncFunction)143 explicit CameraNapiParamParser(napi_env env, napi_callback_info info, T*& nativeObjPointer, 144 std::shared_ptr<CameraNapiAsyncFunction> asyncFunction) 145 : CameraNapiParamParser(env, info, 0, nativeObjPointer, asyncFunction) 146 {} 147 148 template<typename T, typename... Args> CameraNapiParamParser(napi_env env,napi_callback_info info,T * & nativeObjPointer,Args &...args)149 explicit CameraNapiParamParser(napi_env env, napi_callback_info info, T*& nativeObjPointer, Args&... args) 150 : CameraNapiParamParser(env, info, sizeof...(args), nativeObjPointer, nullptr) 151 { 152 if (napiError != napi_ok) { 153 return; 154 } 155 if (paramSize_ > 0) { 156 Next(args...); 157 } 158 } 159 160 template<typename T, typename... Args> CameraNapiParamParser(napi_env env,napi_callback_info info,T * & nativeObjPointer,std::shared_ptr<CameraNapiAsyncFunction> asyncFunction,Args &...args)161 explicit CameraNapiParamParser(napi_env env, napi_callback_info info, T*& nativeObjPointer, 162 std::shared_ptr<CameraNapiAsyncFunction> asyncFunction, Args&... args) 163 : CameraNapiParamParser(env, info, sizeof...(args), nativeObjPointer, asyncFunction) 164 { 165 if (napiError != napi_ok) { 166 return; 167 } 168 if (paramSize_ > 0) { 169 Next(args...); 170 } 171 } 172 173 template<typename... Args> CameraNapiParamParser(napi_env env,std::vector<napi_value> paramValue,Args &...args)174 explicit CameraNapiParamParser(napi_env env, std::vector<napi_value> paramValue, Args&... args) 175 : env_(env), paramSize_(sizeof...(args)), paramValue_(paramValue) 176 { 177 if (paramSize_ != paramValue_.size()) { 178 napiError = napi_status::napi_invalid_arg; 179 return; 180 } 181 napiError = napi_ok; 182 if (paramSize_ > 0) { 183 Next(args...); 184 } 185 } 186 AssertStatus(CameraErrorCode errorCode,const char * message)187 inline bool AssertStatus(CameraErrorCode errorCode, const char* message) 188 { 189 if (napiError != napi_ok) { 190 napi_throw_error(env_, std::to_string(errorCode).c_str(), message); 191 } 192 return napiError == napi_ok; 193 } 194 IsStatusOk()195 inline bool IsStatusOk() 196 { 197 return napiError == napi_ok; 198 } 199 GetThisVar()200 inline napi_value GetThisVar() 201 { 202 return thisVar_; 203 } 204 205 private: 206 template<typename T> CameraNapiParamParser(napi_env env,napi_callback_info info,size_t napiParamSize,T * & nativeObjPointer,std::shared_ptr<CameraNapiAsyncFunction> asyncFunction)207 explicit CameraNapiParamParser(napi_env env, napi_callback_info info, size_t napiParamSize, T*& nativeObjPointer, 208 std::shared_ptr<CameraNapiAsyncFunction> asyncFunction) 209 : env_(env), asyncFunction_(asyncFunction) 210 { 211 size_t paramSizeIncludeAsyncFun = napiParamSize + (asyncFunction_ == nullptr ? 0 : 1); 212 paramSize_ = paramSizeIncludeAsyncFun; 213 paramValue_.resize(paramSize_, nullptr); 214 napiError = napi_get_cb_info(env_, info, ¶mSize_, paramValue_.data(), &thisVar_, nullptr); 215 if (napiError != napi_ok) { 216 return; 217 } 218 if (asyncFunction_ != nullptr) { 219 asyncFunction->Reset(); 220 // Check callback function 221 if (paramSize_ > 0 && paramSize_ == paramSizeIncludeAsyncFun) { 222 napi_valuetype napiType = napi_undefined; 223 napi_typeof(env, paramValue_[paramSize_ - 1], &napiType); 224 if (napiType == napi_function) { 225 napiError = asyncFunction_->CreateCallback(paramValue_[paramSize_ - 1]); 226 } else { 227 napiError = napi_status::napi_invalid_arg; 228 } 229 } else if (paramSizeIncludeAsyncFun > 0 && paramSize_ == paramSizeIncludeAsyncFun - 1) { 230 napiError = asyncFunction_->CreatePromise(); 231 } else { 232 napiError = napi_status::napi_invalid_arg; 233 } 234 if (napiError != napi_ok) { 235 return; 236 } 237 } else if (paramSize_ != napiParamSize) { 238 napiError = napi_status::napi_invalid_arg; 239 return; 240 } 241 UnwrapThisVarToAddr(thisVar_, nativeObjPointer); 242 } 243 244 template<typename T> UnwrapThisVarToAddr(napi_value thisVar,T * & dataPointAddr)245 void UnwrapThisVarToAddr(napi_value thisVar, T*& dataPointAddr) 246 { 247 if (napiError != napi_ok) { 248 return; 249 } 250 if (thisVar == nullptr) { 251 napiError = napi_invalid_arg; 252 return; 253 } 254 napiError = napi_unwrap(env_, thisVar, reinterpret_cast<void**>(&dataPointAddr)); 255 if (napiError == napi_ok && dataPointAddr == nullptr) { 256 napiError = napi_invalid_arg; 257 } 258 } 259 Next(CameraNapiObject & cameraNapiOjbect)260 CameraNapiParamParser& Next(CameraNapiObject& cameraNapiOjbect) 261 { 262 if (napiError != napi_status::napi_ok) { 263 return *this; 264 } 265 if (paraIndex_ >= paramSize_) { 266 napiError = napi_status::napi_invalid_arg; 267 return *this; 268 } 269 napiError = cameraNapiOjbect.ParseNapiObjectToMap(env_, paramValue_[paraIndex_]); 270 paraIndex_++; 271 return *this; 272 } 273 274 template<typename T> Next(T * & outData)275 CameraNapiParamParser& Next(T*& outData) 276 { 277 if (napiError != napi_status::napi_ok) { 278 return *this; 279 } 280 if (paraIndex_ >= paramSize_) { 281 napiError = napi_status::napi_invalid_arg; 282 return *this; 283 } 284 napi_valuetype valueNapiType = napi_undefined; 285 napi_typeof(env_, paramValue_[paraIndex_], &valueNapiType); 286 if (valueNapiType == napi_object) { 287 napiError = napi_unwrap(env_, paramValue_[paraIndex_], reinterpret_cast<void**>(&outData)); 288 if (napiError == napi_ok && outData == nullptr) { 289 napiError = napi_invalid_arg; 290 } 291 } else { 292 napiError = napi_status::napi_invalid_arg; 293 } 294 paraIndex_++; 295 return *this; 296 } 297 298 template<typename T, typename = std::enable_if_t<std::is_same_v<T, bool> || std::is_same_v<T, int32_t> || 299 std::is_same_v<T, int64_t> || std::is_same_v<T, uint32_t> || 300 std::is_same_v<T, double> || std::is_same_v<T, std::string>>> Next(T & outData)301 CameraNapiParamParser& Next(T& outData) 302 { 303 if (napiError != napi_status::napi_ok) { 304 return *this; 305 } 306 if (paraIndex_ >= paramSize_) { 307 napiError = napi_status::napi_invalid_arg; 308 return *this; 309 } 310 napi_valuetype valueNapiType = napi_undefined; 311 napi_typeof(env_, paramValue_[paraIndex_], &valueNapiType); 312 if (std::is_same_v<T, bool> && valueNapiType == napi_boolean) { 313 napiError = napi_get_value_bool(env_, paramValue_[paraIndex_], (bool*)(&outData)); 314 } else if (std::is_same_v<T, int32_t> && valueNapiType == napi_number) { 315 napiError = napi_get_value_int32(env_, paramValue_[paraIndex_], (int32_t*)(&outData)); 316 } else if (std::is_same_v<T, int64_t> && valueNapiType == napi_number) { 317 napiError = napi_get_value_int64(env_, paramValue_[paraIndex_], (int64_t*)(&outData)); 318 } else if (std::is_same_v<T, uint32_t> && valueNapiType == napi_number) { 319 napiError = napi_get_value_uint32(env_, paramValue_[paraIndex_], (uint32_t*)(&outData)); 320 } else if (std::is_same_v<T, double> && valueNapiType == napi_number) { 321 napiError = napi_get_value_double(env_, paramValue_[paraIndex_], (double*)(&outData)); 322 } else if (std::is_same_v<T, std::string> && valueNapiType == napi_string) { 323 size_t stringSize = 0; 324 napiError = napi_get_value_string_utf8(env_, paramValue_[paraIndex_], nullptr, 0, &stringSize); 325 if (napiError != napi_ok) { 326 paraIndex_++; 327 return *this; 328 } 329 std::string* stringPtr = (std::string*)(&outData); 330 stringPtr->resize(stringSize); 331 napiError = napi_get_value_string_utf8( 332 env_, paramValue_[paraIndex_], stringPtr->data(), stringSize + 1, &stringSize); 333 if (napiError != napi_ok) { 334 paraIndex_++; 335 return *this; 336 } 337 } else { 338 napiError = napi_status::napi_invalid_arg; 339 } 340 paraIndex_++; 341 return *this; 342 } 343 344 template<typename T, typename... Args> Next(T & outData,Args &...args)345 CameraNapiParamParser& Next(T& outData, Args&... args) 346 { 347 Next(outData); 348 if (sizeof...(args) > 0) { 349 Next(args...); 350 } 351 return *this; 352 } 353 354 napi_env env_ = nullptr; 355 napi_value thisVar_ = nullptr; 356 size_t paramSize_ = 0; 357 358 size_t paraIndex_ = 0; 359 std::vector<napi_value> paramValue_ {}; 360 std::shared_ptr<CameraNapiAsyncFunction> asyncFunction_ = nullptr; 361 napi_status napiError = napi_status::napi_invalid_arg; 362 }; 363 } // namespace CameraStandard 364 } // namespace OHOS 365 #endif