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