• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramSize_, 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