• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 a
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 "aip_napi_utils.h"
17 
18 #include <dlfcn.h>
19 #include <memory>
20 #include <climits>
21 
22 #include "js_ability.h"
23 #include "aip_log.h"
24 
25 #undef LOG_TAG
26 #define LOG_TAG "AipNapiUtils"
27 
28 namespace OHOS {
29 namespace DataIntelligence {
30 namespace {
31 using namespace OHOS::AppDataMgrJsKit;
32 static constexpr uint32_t MAX_VALUE_LENGTH = 1024 * 1024 * 8; // the max length of all kand of out string value
33 static constexpr uint8_t CONFIG_LENGTH_1 = 2;
34 static constexpr uint8_t CONFIG_LENGTH_2 = 3;
35 static constexpr uint32_t MAX_STR_PARAM_LEN = 512;
36 constexpr const char *PATH_SPLIT = "/";
37 struct OperatorInfo {
38     const char *operatorStr;
39     int32_t operatorEnum;
40 };
41 } // namespace
42 
LoadAlgoLibrary(const std::string & libraryName,AipCoreManagerHandle & aipMgrHandler)43 bool AipNapiUtils::LoadAlgoLibrary(const std::string &libraryName, AipCoreManagerHandle &aipMgrHandler)
44 {
45     AIP_HILOGD("Enter");
46     if (aipMgrHandler.handle != nullptr) {
47         AIP_HILOGE("handle has exists");
48         return false;
49     }
50 
51     if (libraryName.empty()) {
52         AIP_HILOGE("algoPath is empty");
53         return false;
54     }
55     char libRealPath[PATH_MAX] = {};
56     if (realpath(libraryName.c_str(), libRealPath) == nullptr) {
57         AIP_HILOGE("get absolute algoPath error, %{public}d", errno);
58         return false;
59     }
60 
61     aipMgrHandler.handle = dlopen(libRealPath, RTLD_LAZY);
62     if (aipMgrHandler.handle == nullptr) {
63         AIP_HILOGE("cannot load lib error: %{public}s", dlerror());
64         return false;
65     }
66 
67     aipMgrHandler.create = reinterpret_cast<IAipCoreManager *(*)()>(dlsym(aipMgrHandler.handle, "Create"));
68     aipMgrHandler.destroy = reinterpret_cast<void (*)(const IAipCoreManager *)>(dlsym(aipMgrHandler.handle, "Destroy"));
69     if (aipMgrHandler.create == nullptr || aipMgrHandler.destroy == nullptr) {
70         dlclose(aipMgrHandler.handle);
71         aipMgrHandler.Clear();
72         AIP_HILOGE("Failed to create and destroy algo");
73         return false;
74     }
75 
76     aipMgrHandler.pAipManager = aipMgrHandler.create();
77     AIP_HILOGD("Exit");
78     return true;
79 }
80 
81 
UnLoadAlgoLibrary(AipCoreManagerHandle & aipMgrHandler)82 bool AipNapiUtils::UnLoadAlgoLibrary(AipCoreManagerHandle &aipMgrHandler)
83 {
84     AIP_HILOGD("Enter");
85     if (aipMgrHandler.handle == nullptr) {
86         AIP_HILOGE("handle is nullptr");
87         return false;
88     }
89 
90     if (aipMgrHandler.pAipManager != nullptr && aipMgrHandler.destroy != nullptr) {
91         aipMgrHandler.destroy(aipMgrHandler.pAipManager);
92         aipMgrHandler.pAipManager = nullptr;
93     }
94 
95     dlclose(aipMgrHandler.handle);
96     aipMgrHandler.Clear();
97     AIP_HILOGD("Exit");
98     return true;
99 }
100 
GetAlgoObj(AipCoreManagerHandle & aipMgrHandler)101 IAipCoreManager *AipNapiUtils::GetAlgoObj(AipCoreManagerHandle &aipMgrHandler)
102 {
103     AIP_HILOGD("Enter");
104     if (aipMgrHandler.handle == nullptr) {
105         AIP_HILOGE("handle is nullptr");
106         return nullptr;
107     }
108 
109     if (aipMgrHandler.pAipManager != nullptr) {
110         AIP_HILOGD("pAipManager already exists");
111         return aipMgrHandler.pAipManager;
112     }
113 
114     if (aipMgrHandler.create == nullptr) {
115         AIP_HILOGE("create is nullptr");
116         return nullptr;
117     }
118 
119     aipMgrHandler.pAipManager = aipMgrHandler.create();
120     AIP_HILOGD("Exit");
121     return aipMgrHandler.pAipManager;
122 }
123 
ValidateArgsType(napi_env env,napi_value * args,size_t argc,const std::vector<std::string> & expectedTypes)124 bool AipNapiUtils::ValidateArgsType(napi_env env, napi_value *args, size_t argc,
125     const std::vector<std::string> &expectedTypes)
126 {
127     AIP_HILOGD("Enter");
128     napi_status status = napi_ok;
129     napi_valuetype valueType = napi_undefined;
130 
131     if (argc != expectedTypes.size()) {
132         AIP_HILOGE("Wrong number of arguments");
133         return false;
134     }
135 
136     for (size_t i = 0; i < argc; ++i) {
137         status = napi_typeof(env, args[i], &valueType);
138         if (status != napi_ok) {
139             AIP_HILOGE("Error while checking arguments types");
140             return false;
141         }
142         std::string expectedType = expectedTypes[i];
143         if ((expectedType == "string" && valueType != napi_string) ||
144             (expectedType == "object" && valueType != napi_object) ||
145             (expectedType == "number" && valueType != napi_number) ||
146             (expectedType == "function" && valueType != napi_function)) {
147             AIP_HILOGE("Wrong argument type");
148             return false;
149         }
150     }
151     return true;
152 }
153 
TransJsToStr(napi_env env,napi_value value,std::string & str)154 bool AipNapiUtils::TransJsToStr(napi_env env, napi_value value, std::string &str)
155 {
156     size_t strlen = 0;
157     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &strlen);
158     if (status != napi_ok) {
159         AIP_HILOGE("Error string length invalid");
160         return false;
161     }
162     if (strlen < 0 || strlen > MAX_STR_PARAM_LEN) {
163         AIP_HILOGE("The string length invalid");
164         return false;
165     }
166     std::vector<char> buf(strlen + 1);
167     status = napi_get_value_string_utf8(env, value, buf.data(), strlen + 1, &strlen);
168     if (status != napi_ok) {
169         AIP_HILOGE("napi_get_value_string_utf8 failed");
170         return false;
171     }
172     str = buf.data();
173     return true;
174 }
175 
TransJsToStrUnlimited(napi_env env,napi_value value,std::string & str)176 bool AipNapiUtils::TransJsToStrUnlimited(napi_env env, napi_value value, std::string &str)
177 {
178     size_t strlen = 0;
179     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &strlen);
180     if (status != napi_ok) {
181         AIP_HILOGE("Error string length invalid");
182         return false;
183     }
184     if (strlen < 0) {
185         AIP_HILOGE("The string length invalid");
186         return false;
187     }
188     std::vector<char> buf(strlen + 1);
189     status = napi_get_value_string_utf8(env, value, buf.data(), strlen + 1, &strlen);
190     if (status != napi_ok) {
191         AIP_HILOGE("napi_get_value_string_utf8 failed");
192         return false;
193     }
194     str = buf.data();
195     return true;
196 }
197 
TransJsToInt32(napi_env env,napi_value value,int32_t & res)198 bool AipNapiUtils::TransJsToInt32(napi_env env, napi_value value, int32_t &res)
199 {
200     napi_status status = napi_get_value_int32(env, value, &res);
201     if (status != napi_ok) {
202         AIP_HILOGE("napi_get_value_int32 failed");
203         return false;
204     }
205     return true;
206 }
207 
TransJsToDouble(napi_env env,napi_value value,double & res)208 bool AipNapiUtils::TransJsToDouble(napi_env env, napi_value value, double &res)
209 {
210     napi_status status = napi_get_value_double(env, value, &res);
211     if (status != napi_ok) {
212         AIP_HILOGE("napi_get_value_double failed");
213         return false;
214     }
215     return true;
216 }
217 
TransJsToBool(napi_env env,napi_value value,bool & res)218 bool AipNapiUtils::TransJsToBool(napi_env env, napi_value value, bool &res)
219 {
220     napi_status status = napi_get_value_bool(env, value, &res);
221     if (status != napi_ok) {
222         return false;
223     }
224     return true;
225 }
226 
CreateStringData(napi_env env,napi_value aipServiceValue,napi_value result,const std::string name,std::string & content)227 void AipNapiUtils::CreateStringData(napi_env env, napi_value aipServiceValue, napi_value result, const std::string name,
228     std::string &content)
229 {
230     napi_status ret = napi_create_string_utf8(env, content.c_str(), NAPI_AUTO_LENGTH, &aipServiceValue);
231     if (ret != napi_ok) {
232         AIP_HILOGE("napi_create_string_utf8 failed");
233         return;
234     }
235 
236     ret = napi_set_named_property(env, result, name.c_str(), aipServiceValue);
237     if (ret != napi_ok) {
238         AIP_HILOGE("napi_set_named_property failed");
239     }
240 }
241 
CreateInt32Data(napi_env env,napi_value aipServiceValue,napi_value result,const std::string name,int32_t value)242 void AipNapiUtils::CreateInt32Data(napi_env env, napi_value aipServiceValue, napi_value result, const std::string name,
243     int32_t value)
244 {
245     napi_status ret = napi_create_int32(env, value, &aipServiceValue);
246     if (ret != napi_ok) {
247         AIP_HILOGE("napi_create_int32 failed");
248         return;
249     }
250 
251     ret = napi_set_named_property(env, result, name.c_str(), aipServiceValue);
252     if (ret != napi_ok) {
253         AIP_HILOGE("napi_set_named_property failed");
254     }
255 }
256 
CreateDoubleData(napi_env env,double value,napi_value * result)257 void AipNapiUtils::CreateDoubleData(napi_env env, double value, napi_value *result)
258 {
259     napi_status ret = napi_create_double(env, value, result);
260     if (ret != napi_ok) {
261         AIP_HILOGE("napi_create_int32 failed");
262         return;
263     }
264 }
265 
SetInt32Property(napi_env env,napi_value targetObj,int32_t value,const char * propName)266 void AipNapiUtils::SetInt32Property(napi_env env, napi_value targetObj, int32_t value, const char *propName)
267 {
268     napi_value prop = nullptr;
269     napi_status ret = napi_create_int32(env, value, &prop);
270     if (ret != napi_ok) {
271         AIP_HILOGE("napi_create_int32 failed");
272         return;
273     }
274     SetPropertyName(env, targetObj, propName, prop);
275 }
276 
SetStringProperty(napi_env env,napi_value targetObj,std::string value,const char * propName)277 void AipNapiUtils::SetStringProperty(napi_env env, napi_value targetObj, std::string value, const char *propName)
278 {
279     napi_value prop = nullptr;
280     napi_status ret = napi_create_string_utf8(env, value.c_str(), value.size(), &prop);
281     if (ret != napi_ok) {
282         AIP_HILOGE("napi_create_int32 failed");
283         return;
284     }
285     SetPropertyName(env, targetObj, propName, prop);
286 }
287 
SetPropertyName(napi_env env,napi_value targetObj,const char * propName,napi_value propValue)288 void AipNapiUtils::SetPropertyName(napi_env env, napi_value targetObj, const char *propName, napi_value propValue)
289 {
290     napi_status status = napi_set_named_property(env, targetObj, propName, propValue);
291     if (status != napi_ok) {
292         AIP_HILOGE("napi_set_named_property failed");
293         return;
294     }
295 }
296 
CheckModelConfig(napi_env env,napi_value value)297 bool AipNapiUtils::CheckModelConfig(napi_env env, napi_value value)
298 {
299     napi_valuetype valuetype;
300     napi_status status = napi_typeof(env, value, &valuetype);
301     if (status != napi_ok || valuetype != napi_object) {
302         AIP_HILOGE("ModelConfig is not object");
303         return false;
304     }
305 
306     napi_value KeysArray;
307     status = napi_get_property_names(env, value, &KeysArray);
308     if (status != napi_ok) {
309         AIP_HILOGE("Failed to get property names");
310         return false;
311     }
312 
313     uint32_t length;
314     status = napi_get_array_length(env, KeysArray, &length);
315     if (status != napi_ok) {
316         AIP_HILOGE("Failed to get array length");
317         return false;
318     }
319 
320     if (length != CONFIG_LENGTH_1 && length != CONFIG_LENGTH_2) {
321         AIP_HILOGE("The modelConfig length is failed");
322         return false;
323     }
324     return true;
325 }
326 
Convert2Value(napi_env env,napi_value in,bool & out)327 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, bool &out)
328 {
329     return napi_get_value_bool(env, in, &out);
330 }
331 
Convert2Value(napi_env env,napi_value in,int32_t & out)332 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, int32_t &out)
333 {
334     return napi_get_value_int32(env, in, &out);
335 }
336 
Convert2Value(napi_env env,napi_value in,uint32_t & out)337 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, uint32_t &out)
338 {
339     return napi_get_value_uint32(env, in, &out);
340 }
341 
Convert2Value(napi_env env,napi_value in,std::vector<uint8_t> & out)342 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, std::vector<uint8_t> &out)
343 {
344     bool isTypedArray = false;
345     napi_is_typedarray(env, in, &isTypedArray);
346     if (!isTypedArray) {
347         return napi_invalid_arg;
348     }
349 
350     napi_typedarray_type type;
351     napi_value input_buffer = nullptr;
352     size_t byte_offset = 0;
353     size_t length = 0;
354     void *tmp = nullptr;
355     auto status = napi_get_typedarray_info(env, in, &type, &length, &tmp, &input_buffer, &byte_offset);
356     if (status != napi_ok || type != napi_uint8_array) {
357         return napi_invalid_arg;
358     }
359 
360     out = (tmp != nullptr ? std::vector<uint8_t>(static_cast<uint8_t *>(tmp), static_cast<uint8_t *>(tmp) + length)
361         : std::vector<uint8_t>());
362     return status;
363 }
364 
Convert2Value(napi_env env,napi_value in,int64_t & out)365 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, int64_t &out)
366 {
367     return napi_get_value_int64(env, in, &out);
368 }
369 
Convert2Value(napi_env env,napi_value in,std::string & out)370 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, std::string &out)
371 {
372     napi_valuetype type = napi_undefined;
373     napi_status status = napi_typeof(env, in, &type);
374     LOG_ERROR_RETURN((status == napi_ok) && (type == napi_string), "The parameter type is not a string.",
375         napi_invalid_arg);
376     size_t buffSize = 0;
377     napi_get_value_string_utf8(env, in, nullptr, 0, &buffSize);
378     // cut down with 0 if more than MAX_VALUE_LENGTH
379     if (buffSize >= MAX_VALUE_LENGTH - 1) {
380         buffSize = MAX_VALUE_LENGTH - 1;
381     }
382     std::unique_ptr<char[]> buffer = std::make_unique<char[]>(buffSize + 1);
383     LOG_ERROR_RETURN(buffer, "Buffer data is nullptr.", napi_invalid_arg);
384     status = napi_get_value_string_utf8(env, in, buffer.get(), buffSize + 1, &buffSize);
385     LOG_ERROR_RETURN(status == napi_ok, "napi_get_value_string_utf8 failed", napi_invalid_arg);
386     out = std::string(buffer.get());
387     return status;
388 }
389 
Convert2Value(napi_env env,napi_value in,std::vector<float> & out)390 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, std::vector<float> &out)
391 {
392     bool isTypedArray = false;
393     napi_is_typedarray(env, in, &isTypedArray);
394     if (!isTypedArray) {
395         return napi_invalid_arg;
396     }
397 
398     napi_typedarray_type type;
399     napi_value input_buffer = nullptr;
400     size_t byte_offset = 0;
401     size_t length = 0;
402     void *tmp = nullptr;
403     auto status = napi_get_typedarray_info(env, in, &type, &length, &tmp, &input_buffer, &byte_offset);
404     if (status != napi_ok || type != napi_float32_array) {
405         return napi_invalid_arg;
406     }
407 
408     out = (tmp != nullptr
409                   ? std::vector<float>(static_cast<float *>(tmp), static_cast<float *>(tmp) + length / sizeof(float))
410                   : std::vector<float>());
411     return status;
412 }
413 
Convert2Value(napi_env env,napi_value in,float & out)414 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, float &out)
415 {
416     double tmp;
417     napi_status status = napi_get_value_double(env, in, &tmp);
418     out = tmp;
419     return status;
420 }
421 
Convert2Value(napi_env env,napi_value in,double & out)422 napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, double &out)
423 {
424     return napi_get_value_double(env, in, &out);
425 }
426 
IsNull(napi_env env,napi_value value)427 bool AipNapiUtils::IsNull(napi_env env, napi_value value)
428 {
429     napi_valuetype type = napi_undefined;
430     napi_status status = napi_typeof(env, value, &type);
431     return status == napi_ok && (type == napi_undefined || type == napi_null);
432 }
433 
GetInnerValue(napi_env env,napi_value in,const std::string & prop,bool optional)434 std::pair<napi_status, napi_value> AipNapiUtils::GetInnerValue(
435     napi_env env, napi_value in, const std::string &prop, bool optional)
436 {
437     bool hasProp = false;
438     napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
439     if (status != napi_ok) {
440         return std::make_pair(napi_generic_failure, nullptr);
441     }
442     if (!hasProp) {
443         status = optional ? napi_ok : napi_generic_failure;
444         return std::make_pair(status, nullptr);
445     }
446     napi_value inner = nullptr;
447     status = napi_get_named_property(env, in, prop.c_str(), &inner);
448     if (status != napi_ok || inner == nullptr) {
449         return std::make_pair(napi_generic_failure, nullptr);
450     }
451     if (optional && AipNapiUtils::IsNull(env, inner)) {
452         return std::make_pair(napi_ok, nullptr);
453     }
454     return std::make_pair(napi_ok, inner);
455 }
456 
GetCustomDatabasePath(const std::string & rootDir,const std::string & name,const std::string & customDir)457 std::string GetCustomDatabasePath(
458     const std::string &rootDir, const std::string &name, const std::string &customDir)
459 {
460     std::string databasePath;
461     databasePath.append(rootDir).append(PATH_SPLIT).append(customDir).append(PATH_SPLIT).append(name);
462     return databasePath;
463 }
464 
GetDefaultDatabasePath(const std::string & baseDir,const std::string & name,const std::string & customDir)465 std::string GetDefaultDatabasePath(
466     const std::string &baseDir, const std::string &name, const std::string &customDir)
467 {
468     std::string databaseDir;
469     databaseDir.append(baseDir).append("/rdb/").append(customDir).append(PATH_SPLIT).append(name);
470     return databaseDir;
471 }
472 
Convert2Value(napi_env env,const napi_value & in,napi_value & out)473 napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, napi_value &out)
474 {
475     out = in;
476     return napi_ok;
477 }
478 
Convert2JSValue(napi_env env,const std::vector<uint8_t> & in,napi_value & out)479 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out)
480 {
481     void *native = nullptr;
482     napi_value buffer = nullptr;
483     napi_status status = napi_create_arraybuffer(env, in.size(), &native, &buffer);
484     if (status != napi_ok) {
485         return status;
486     }
487     for (size_t i = 0; i < in.size(); i++) {
488         *(static_cast<uint8_t *>(native) + i) = in[i];
489     }
490     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
491     if (status != napi_ok) {
492         return status;
493     }
494     return napi_ok;
495 }
496 
Convert2JSValue(napi_env env,const std::vector<float> & in,napi_value & out)497 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::vector<float> &in, napi_value &out)
498 {
499     float *native = nullptr;
500     napi_value buffer = nullptr;
501     napi_status status = napi_create_arraybuffer(env, in.size() * sizeof(float), (void **)&native, &buffer);
502     if (status != napi_ok) {
503         return status;
504     }
505     if (native == nullptr) {
506         return status;
507     }
508     for (size_t i = 0; i < in.size(); i++) {
509         *(native + i) = in[i];
510     }
511     status = napi_create_typedarray(env, napi_float32_array, in.size(), buffer, 0, &out);
512     if (status != napi_ok) {
513         return status;
514     }
515     return napi_ok;
516 }
517 
Convert2JSValue(napi_env env,const std::string & in,napi_value & out)518 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::string &in, napi_value &out)
519 {
520     return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
521 }
522 
Convert2JSValue(napi_env env,const double & in,napi_value & out)523 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const double &in, napi_value &out)
524 {
525     return napi_create_double(env, in, &out);
526 }
527 
Convert2JSValue(napi_env env,const bool & in,napi_value & out)528 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const bool &in, napi_value &out)
529 {
530     return napi_get_boolean(env, in, &out);
531 }
532 
Convert2JSValue(napi_env env,const int32_t & in,napi_value & out)533 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const int32_t &in, napi_value &out)
534 {
535     return napi_create_int32(env, in, &out);
536 }
537 
Convert2JSValue(napi_env env,const int64_t & in,napi_value & out)538 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const int64_t &in, napi_value &out)
539 {
540     return napi_create_int64(env, in, &out);
541 }
542 
Convert2JSValue(napi_env env,const uint64_t & in,napi_value & out)543 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const uint64_t &in, napi_value &out)
544 {
545     return napi_create_bigint_uint64(env, in, &out);
546 }
547 
Convert2JSValue(napi_env env,const std::map<std::string,double> & in,napi_value & out)548 napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::map<std::string, double> &in, napi_value &out)
549 {
550     napi_create_object(env, &out);
551     for (auto const &[key, value] : in) {
552         napi_value jsValue = nullptr;
553         Convert2JSValue(env, value, jsValue);
554         napi_set_named_property(env, out, key.c_str(), jsValue);
555     }
556     return napi_ok;
557 }
558 } // namespace DataIntelligence
559 } // namespace OHOS
560