• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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*/
15const { writeFile } = require("../tools/FileRW");
16const re = require("../tools/re");
17
18let xNapiToolH = `\
19#ifndef CC_TOOL_H
20#define CC_TOOL_H
21
22#include <node_api.h>
23#include <string>
24#include <memory>
25#include <map>
26#include <any>
27#include <vector>
28#include <cmath>
29
30struct AsyncFunc
31{
32    napi_env env_;
33    napi_ref funcRef_;
34    napi_ref thisVarRef_;
35};
36
37class XNapiTool
38{
39public:
40    void RegistAsyncFunc(std::string name, napi_value func);
41    void UnregistAsyncFunc(std::string name);
42    static std::map<std::string, AsyncFunc> asyncFuncs_;
43    static void CallAsyncFunc(AsyncFunc * pAsyncFuncs, napi_value ret);
44
45    using CallbackFunction = void (*)(XNapiTool *pxt, void *data);
46    using RELEASE_INSTANCE = void (*)(void *p);
47    static napi_value UndefinedValue(napi_env env);
48    const uint32_t DEFAULT_ARG_COUNT = 8;
49    napi_value UndefinedValue();
50
51    napi_value CreateSubObject(napi_value parent, const char *name);
52    void DefineFunction(const char *funcName, napi_callback callback, napi_value dest = nullptr);
53    void DefineClass(const char *className, napi_callback constructorFunc,
54        std::map<const char *, std::map<const char *, napi_callback>> &valueList, std::map<const char *,
55        napi_callback> &funcList, napi_value dest = nullptr);
56
57
58    void SetEnumProperty(napi_value dstObj, const char *propName, const std::any objValue);
59    void CreateEnumObject(const char *enumName, std::map<const char *, std::any> enumMap);
60
61    XNapiTool(napi_env env, napi_callback_info info);
62    XNapiTool(napi_env env, napi_value exports);
63    ~XNapiTool();
64
65    bool SwapJs2CBool(napi_value value);
66    int32_t SwapJs2CInt32(napi_value value);
67    uint32_t SwapJs2CUint32(napi_value value);
68    int64_t SwapJs2CInt64(napi_value value);
69    double_t SwapJs2CDouble(napi_value value);
70    size_t SwapJs2CUtf8(napi_value value, std::string &str);
71
72    napi_value SwapC2JsBool(bool value);
73    napi_value SwapC2JsInt32(int32_t value);
74    napi_value SwapC2JsUint32(uint32_t value);
75    napi_value SwapC2JsInt64(int64_t value);
76    napi_value SwapC2JsDouble(double_t value);
77    napi_value SwapC2JsUtf8(const char *value);
78
79    napi_value GetArgv(uint32_t p);
80    uint32_t GetArgc();
81
82    napi_value GetValueProperty(napi_value value, const char *propertyName);
83    napi_value SetValueProperty(napi_value &value, const char *propertyName, napi_value property);
84
85    napi_value CreateArray(napi_value &value);
86    uint32_t GetArrayLength(napi_value value);
87    napi_value GetArrayElement(napi_value value, uint32_t p);
88    napi_value SetArrayElement(napi_value &value, uint32_t p, napi_value ele);
89
90    uint32_t GetMapLength(napi_value value);
91    napi_value GetMapElementName(napi_value value, uint32_t p);
92    napi_value GetMapElementValue(napi_value value, const char * p);
93    napi_value SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value);
94
95    std::string GetUnionType(napi_value object);
96
97    std::string GetAnyType(napi_value object);
98    std::string GetAnyArrayType(napi_value object);
99    void SetAnyValue(std::string &any_type, napi_value argv, std::any &any);
100    void GetAnyValue (std::string any_type, napi_value &result, std::any any);
101    void GetObjectValue(napi_value &result, std::map<std::string, std::any> valueIn);
102
103    napi_value SyncCallBack(napi_value func, size_t argc, napi_value *args);
104
105    napi_value StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func = nullptr);
106    void FinishAsync(size_t argc, napi_value *args);
107
108    bool IsFailed()
109    {
110        return bFailed_;
111    }
112    napi_value GetError()
113    {
114        return error_;
115    }
116    napi_env GetEnv()
117    {
118        return env_;
119    }
120
121    napi_value tmp_value;
122
123    // create code related class
124public:
125    static void WrapFinalize(napi_env env, void *data, void *hint);
126    void ReleaseInstance();
127    napi_value WrapInstance(void *instance, RELEASE_INSTANCE ri);
128    void *UnWarpInstance();
129
130    void SetAsyncInstance(void *p);
131    void *GetAsyncInstance();
132
133private:
134    napi_env env_;
135    napi_value exports_;
136
137    // analyze params
138    napi_value argv_[8];
139    size_t argc_size;
140    napi_value thisVar_;
141    void *data_;
142
143    // error message
144    napi_value error_;
145    bool bFailed_;
146    bool CheckFailed(bool b, const char *errStr);
147    bool CheckValueType(napi_value value, napi_valuetype type);
148
149    // asynchronous call related code
150    static void AsyncExecute(napi_env env, void *p);
151    void AsyncExecuteFunction();
152    static void AsyncComplete(napi_env env, napi_status status, void *p);
153    void AsyncCompleteFunction();
154    napi_ref callbackFunc_;
155    napi_async_work work_;
156    bool asyncNeedRelease_;
157    CallbackFunction executeFunction_;
158    CallbackFunction completeFunction_;
159    void *valueData_;
160    napi_deferred deferred_;
161    enum class AsyncMode
162    {
163        NONE,
164        CALLBACK,
165        PROMISE,
166    };
167    AsyncMode asyncMode_;
168
169private:
170    napi_ref wrapper_;
171    void *pInstance_;
172    RELEASE_INSTANCE releaseInstance_;
173    void *asyncInstance_;
174};
175
176#endif
177`
178
179let xNapiToolCpp = `
180
181#include "tool_utility.h"
182#include <cassert>
183#include <cstring>
184#include <uv.h>
185
186#define CC_ASSERT(btrue) \\
187    if (!(btrue)) {      \\
188                         \\
189    }                    \\
190    assert(btrue);
191
192XNapiTool::XNapiTool(napi_env env, napi_callback_info info)
193{
194    env_ = env;
195    bFailed_ = false;
196    executeFunction_ = nullptr;
197    completeFunction_ = nullptr;
198    valueData_ = nullptr;
199    asyncNeedRelease_ = false;
200    asyncMode_ = AsyncMode::NONE;
201    pInstance_ = nullptr;
202    releaseInstance_ = nullptr;
203    wrapper_ = nullptr;
204
205    argc_size = DEFAULT_ARG_COUNT;
206
207    napi_status result_status = napi_get_cb_info(env, info, &argc_size, argv_, &thisVar_, &data_);
208    CheckFailed(result_status == napi_ok, "get args fail");
209}
210
211XNapiTool::XNapiTool(napi_env env, napi_value exports)
212{
213    env_ = env;
214    exports_ = exports;
215
216    asyncMode_ = AsyncMode::NONE;
217    wrapper_ = nullptr;
218}
219
220XNapiTool::~XNapiTool()
221{
222    if (asyncMode_ == AsyncMode::PROMISE) {
223        napi_status result_status = napi_delete_async_work(env_, work_);
224        CC_ASSERT(result_status == napi_ok);
225    }
226    if (asyncMode_ == AsyncMode::CALLBACK) {
227        napi_status result_status = napi_delete_reference(env_, callbackFunc_);
228        CC_ASSERT(result_status == napi_ok);
229        result_status = napi_delete_async_work(env_, work_);
230        CC_ASSERT(result_status == napi_ok);
231    }
232    if (wrapper_ != nullptr) {
233        napi_status result_status = napi_delete_reference(env_, wrapper_);
234        CC_ASSERT(result_status == napi_ok);
235    }
236}
237
238bool XNapiTool::SwapJs2CBool(napi_value value)
239{
240    bool result;
241    napi_status result_status = napi_get_value_bool(env_, value, &result);
242    if (CheckFailed(result_status == napi_ok, "swap_js_2_c_bool fail"))
243        return -1;
244    return result;
245}
246
247napi_value XNapiTool::GetArgv(uint32_t p)
248{
249    if (CheckFailed(p < argc_size, "GetArgv失败"))
250        return error_;
251
252    return argv_[p];
253}
254
255uint32_t XNapiTool::GetArgc()
256{
257    return argc_size;
258}
259
260napi_value XNapiTool::GetValueProperty(napi_value value, const char *propertyName)
261{
262    napi_value result;
263    napi_status result_status = napi_get_named_property(env_, value, propertyName, &result);
264    CC_ASSERT(result_status == napi_ok);
265    return result;
266}
267
268napi_value XNapiTool::SetValueProperty(napi_value &value, const char *propertyName, napi_value property)
269{
270    napi_status result_status;
271    if (value == nullptr) {
272        result_status = napi_create_object(env_, &value);
273        CC_ASSERT(result_status == napi_ok);
274    }
275    result_status = napi_set_named_property(env_, value, propertyName, property);
276    CC_ASSERT(result_status == napi_ok);
277    return value;
278}
279
280napi_value XNapiTool::CreateArray(napi_value &value)
281{
282    if (value == nullptr) {
283        napi_status result_status = napi_create_array(env_, &value);
284        CC_ASSERT(result_status == napi_ok);
285    }
286    return value;
287}
288
289uint32_t XNapiTool::GetArrayLength(napi_value value)
290{
291    uint32_t ret;
292    napi_status result_status = napi_get_array_length(env_, value, &ret);
293    CC_ASSERT(result_status == napi_ok);
294    return ret;
295}
296
297napi_value XNapiTool::GetArrayElement(napi_value value, uint32_t p)
298{
299    napi_value result;
300    napi_status result_status = napi_get_element(env_, value, p, &result);
301    CC_ASSERT(result_status == napi_ok);
302    return result;
303}
304
305napi_value XNapiTool::SetArrayElement(napi_value &value, uint32_t p, napi_value ele)
306{
307    napi_status result_status;
308    if (value == nullptr) {
309        result_status = napi_create_array(env_, &value);
310        CC_ASSERT(result_status == napi_ok);
311    }
312    result_status = napi_set_element(env_, value, p, ele);
313    CC_ASSERT(result_status == napi_ok);
314    return value;
315}
316
317uint32_t XNapiTool::GetMapLength(napi_value value)
318{
319    napi_value name_result;
320    napi_get_property_names(env_, value, &name_result);
321    uint32_t ret;
322    napi_status result_status = napi_get_array_length(env_, name_result, &ret);
323    CC_ASSERT(result_status == napi_ok);
324    return ret;
325}
326
327napi_value XNapiTool::GetMapElementName(napi_value value, uint32_t p)
328{
329    napi_value name_result;
330    napi_get_property_names(env_, value, &name_result);
331    napi_value result;
332    napi_status result_status = napi_get_element(env_, name_result, p, &result);
333    CC_ASSERT(result_status == napi_ok);
334    return result;
335}
336
337napi_value XNapiTool::GetMapElementValue(napi_value value, const char * utf8Name)
338{
339    napi_value result;
340    napi_status result_status = napi_get_named_property(env_, value, utf8Name, &result);
341    CC_ASSERT(result_status == napi_ok);
342    return result;
343}
344
345napi_value XNapiTool::SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value)
346{
347    napi_status result_status;
348    if (value == nullptr) {
349        result_status = napi_create_object(env_, &value);
350        CC_ASSERT(result_status == napi_ok);
351    }
352    result_status = napi_set_named_property(env_, value, ele_key, ele_value);
353    CC_ASSERT(result_status == napi_ok);
354    return value;
355}
356
357std::string XNapiTool::GetAnyType(napi_value object){
358    napi_valuetype result;
359    napi_typeof(env_, object, &result);
360    if (result == napi_string) {
361        return "string";
362    } else if (result == napi_number) {
363        return "number";
364    } else if (result == napi_boolean) {
365        return "boolean";
366    } else if (result == napi_object) {
367        bool is_array;
368        napi_is_array(env_, object, &is_array);
369        if (is_array) {
370            napi_value arr_value_result;
371            napi_valuetype arr_type_result;
372            napi_get_element (env_, object, 0, &arr_value_result);
373            napi_typeof(env_, arr_value_result, &arr_type_result);
374            if (arr_type_result == napi_string) {
375                return "arr_string";
376            } else if (arr_type_result == napi_number) {
377                return "arr_number";
378            } else if (arr_type_result == napi_boolean) {
379                return "arr_boolean";
380            } else {
381                return nullptr;
382            }
383        }
384        napi_value obj_name_value;
385        napi_value obj_name_result;
386        napi_valuetype obj_name_type;
387        std::string obj_name_string;
388        napi_get_property_names (env_, object, &obj_name_value);
389        napi_get_element (env_, obj_name_value, 0, &obj_name_result);
390        napi_typeof(env_, obj_name_result, &obj_name_type);
391        if (obj_name_type == napi_string) {
392            napi_value obj_value;
393            napi_valuetype obj_value_type;
394            SwapJs2CUtf8(obj_name_result, obj_name_string);
395            napi_get_named_property (env_, object, obj_name_string.c_str(), &obj_value);
396            napi_typeof(env_, obj_value, &obj_value_type);
397            if (obj_value_type == napi_string) {
398                return "map_string";
399            } else if (obj_value_type == napi_number) {
400                return "map_number";
401            } else if (obj_value_type == napi_boolean) {
402                return "map_boolean";
403            } else {
404                return nullptr;
405            }
406        }
407        return nullptr;
408    } else {
409        return nullptr;
410    }
411}
412
413std::string XNapiTool::GetAnyArrayType(napi_value object){
414    napi_valuetype result;
415    napi_typeof(env_, object, &result);
416    if (result == napi_object) {
417        bool is_array;
418        napi_is_array(env_, object, &is_array);
419        if (is_array) {
420            napi_value arr_value_result;
421            napi_valuetype arr_type_result;
422            napi_get_element (env_, object, 0, &arr_value_result);
423            napi_typeof(env_, arr_value_result, &arr_type_result);
424            if (arr_type_result == napi_string) {
425                return "arr_string";
426            } else if (arr_type_result == napi_number) {
427                return "arr_number";
428            } else if (arr_type_result == napi_boolean) {
429                return "arr_boolean";
430            } else {
431                return nullptr;
432            }
433        }
434        return nullptr;
435    }
436    return nullptr;
437}
438
439void XNapiTool::SetAnyValue(std::string &any_type, napi_value argv, std::any &any)
440{
441    if (any_type == "string") {
442        std::string any_string;
443        SwapJs2CUtf8(argv, any_string);
444        any = any_string;
445        return;
446    } else if (any_type == "boolean") {
447        bool any_bool;
448        any_bool = SwapJs2CBool(argv);
449        any = any_bool;
450        return;
451    } else if (any_type == "number") {
452        std::uint32_t any_number;
453        any_number = SwapJs2CInt32(argv);
454        any = any_number;
455        return;
456    } else if (any_type.substr(0,3) == "arr") {
457        uint32_t len=GetArrayLength(argv);
458        if (any_type == "arr_string") {
459            std::vector<std::string> any_arr_string;
460            for(uint32_t i=0;i<len;i++) {
461                std::string tt;
462                SwapJs2CUtf8(GetArrayElement(argv, i), tt);
463                any_arr_string.push_back(tt);
464            }
465            any = any_arr_string;
466            return;
467        } else if (any_type == "arr_number") {
468            std::vector<std::uint32_t> any_arr_number;
469            for(uint32_t i=0;i<len;i++) {
470                uint32_t tt;
471                tt = SwapJs2CInt32(GetArrayElement(argv, i));
472                any_arr_number.push_back(tt);
473            }
474            any = any_arr_number;
475            return;
476        } else if (any_type == "arr_boolean") {
477            std::vector<bool> any_arr_boolean;
478            for(uint32_t i=0;i<len;i++) {
479                bool tt;
480                tt = SwapJs2CBool(GetArrayElement(argv,i));
481                any_arr_boolean.push_back(tt);
482            }
483            any = any_arr_boolean;
484            return;
485        }
486        return;
487    }  else if (any_type.substr(0,3) == "map") {
488        uint32_t len = GetMapLength(argv);
489        if (any_type == "map_string") {
490            std::map<std::string,std::string> any_map_string;
491            for(uint32_t i=0;i<len;i++) {
492                std::string tt1;
493                std::string tt2;
494                SwapJs2CUtf8(GetMapElementName(argv,i), tt1);
495                SwapJs2CUtf8(GetMapElementValue(argv,tt1.c_str()), tt2);
496                any_map_string.insert(std::make_pair(tt1, tt2));
497            }
498            any = any_map_string;
499            return;
500        } else if (any_type == "map_number") {
501            std::map<std::string,std::uint32_t> any_map_number;
502            for(uint32_t i=0;i<len;i++) {
503                std::string tt1;
504                uint32_t tt2;
505                SwapJs2CUtf8(GetMapElementName(argv,i), tt1);
506                tt2 = SwapJs2CInt32(GetMapElementValue(argv,tt1.c_str()));
507                any_map_number.insert(std::make_pair(tt1, tt2));
508            }
509            any = any_map_number;
510            return;
511        } else if (any_type == "map_boolean") {
512            std::map<std::string,bool> any_map_boolean;
513            for(uint32_t i=0;i<len;i++) {
514                std::string tt1;
515                bool tt2;
516                SwapJs2CUtf8(GetMapElementName(argv,i), tt1);
517                tt2 = SwapJs2CBool(GetMapElementValue(argv,tt1.c_str()));
518                any_map_boolean.insert(std::make_pair(tt1, tt2));
519            }
520            any = any_map_boolean;
521            return;
522        }
523        return;
524    }
525    return;
526}
527
528void XNapiTool::GetAnyValue (std::string any_type, napi_value &result, std::any any)
529{
530    result = nullptr;
531    if (any_type == "string") {
532        std::string any_string = std::any_cast<std::string>(any);
533        result = SwapC2JsUtf8(any_string.c_str());
534        return;
535    } else if (any_type == "boolean") {
536        bool any_bool = std::any_cast<bool>(any);
537        result = SwapC2JsBool(any_bool);
538        return;
539    } else if (any_type == "number") {
540        std::uint32_t any_number = std::any_cast<std::uint32_t>(any);
541        if (typeid(any_number) == typeid(int32_t))
542            result = SwapC2JsInt32(any_number);
543        else if (typeid(any_number) == typeid(uint32_t))
544            result = SwapC2JsUint32(any_number);
545        else if (typeid(any_number) == typeid(int64_t))
546            result = SwapC2JsInt64(any_number);
547        else if (typeid(any_number) == typeid(double_t))
548            result = SwapC2JsDouble(any_number);
549        return;
550    } else if (any_type.substr(0,3) == "arr") {
551        result = nullptr;
552        if (any_type == "arr_string") {
553            std::vector<std::string> any_arr_string = std::any_cast<std::vector<std::string>>(any);
554            uint32_t len=any_arr_string.size();
555            for(uint32_t i=0;i<len;i++) {
556                napi_value tnv = nullptr;
557                tnv = SwapC2JsUtf8(any_arr_string[i].c_str());
558                SetArrayElement(result, i, tnv);
559            }
560            return;
561        } else if (any_type == "arr_number") {
562            std::vector<std::uint32_t> any_arr_number = std::any_cast<std::vector<std::uint32_t>>(any);
563            uint32_t len=any_arr_number.size();
564            for(uint32_t i=0;i<len;i++) {
565                napi_value tnv = nullptr;
566                if (typeid(any_arr_number[i]) == typeid(int32_t)){
567                    tnv = SwapC2JsInt32(any_arr_number[i]);
568                }
569                else if (typeid(any_arr_number[i]) == typeid(uint32_t)){
570                    tnv = SwapC2JsUint32(any_arr_number[i]);
571                }
572                else if (typeid(any_arr_number[i]) == typeid(int64_t)){
573                    tnv = SwapC2JsInt64(any_arr_number[i]);
574                }
575                else if (typeid(any_arr_number[i]) == typeid(double_t)){
576                    tnv = SwapC2JsDouble(any_arr_number[i]);
577                }
578                SetArrayElement(result, i, tnv);
579            }
580            return;
581        } else if (any_type == "arr_boolean") {
582            std::vector<bool> any_arr_boolean = std::any_cast<std::vector<bool>>(any);
583            uint32_t len=any_arr_boolean.size();
584            for(uint32_t i=0;i<len;i++) {
585                napi_value tnv = nullptr;
586                tnv = SwapC2JsBool(any_arr_boolean[i]);
587                SetArrayElement(result, i, tnv);
588            }
589            return;
590        }
591        return;
592    } else if (any_type.substr(0,3) == "map") {
593        if (any_type == "map_string") {
594            std::map<std::string,std::string> any_map_string = std::any_cast<std::map<std::string,std::string>>(any);
595            for (auto i = any_map_string.begin(); i != any_map_string.end(); i++)
596            {
597                const char * tnv1;
598                napi_value tnv2 = nullptr;
599                tnv1 = (i -> first).c_str();
600                tnv2 = SwapC2JsUtf8(i->second.c_str());
601                SetMapElement(result, tnv1, tnv2);
602            }
603            return;
604        } else if (any_type == "map_number") {
605            std::map<std::string,std::uint32_t> any_map_number =
606            std::any_cast<std::map<std::string,std::uint32_t>>(any);
607            for (auto i = any_map_number.begin(); i != any_map_number.end(); i++)
608            {
609                const char * tnv1;
610                napi_value tnv2 = nullptr;
611                tnv1 = (i -> first).c_str();
612                if (typeid(i->second) == typeid(int32_t)){
613                    tnv2 = SwapC2JsInt32(i->second);
614                }
615                else if (typeid(i->second) == typeid(uint32_t)){
616                    tnv2 = SwapC2JsUint32(i->second);
617                }
618                else if (typeid(i->second) == typeid(int64_t)){
619                    tnv2 = SwapC2JsInt64(i->second);
620                }
621                else if (typeid(i->second) == typeid(double_t)){
622                    tnv2 = SwapC2JsDouble(i->second);
623                }
624                SetMapElement(result, tnv1, tnv2);
625            }
626            return;
627        } else if (any_type == "map_boolean") {
628            std::map<std::string,bool> any_map_boolean = std::any_cast<std::map<std::string,bool>>(any);
629            for (auto i = any_map_boolean.begin(); i != any_map_boolean.end(); i++)
630            {
631                const char * tnv1;
632                napi_value tnv2 = nullptr;
633                tnv1 = (i -> first).c_str();
634                tnv2 = SwapC2JsBool(i->second);
635                SetMapElement(result, tnv1, tnv2);
636            }
637            return;
638        }
639        return;
640    }
641    return;
642}
643
644std::string XNapiTool::GetUnionType(napi_value object){
645    napi_valuetype result;
646    napi_typeof(env_, object, &result);
647    if (result == napi_string) {
648        return "string";
649    } else if (result == napi_number) {
650        return "number";
651    } else if (result == napi_boolean) {
652        return "boolean";
653    } else {
654        return nullptr;
655    }
656}
657
658void XNapiTool::GetObjectValue(napi_value &result, std::map<std::string, std::any> valueIn)
659{
660    //napi_value result = nullptr;
661    napi_create_object(env_, &result);
662
663    /*std::map<std::string,std::uint32_t> any_map_number =
664    std::any_cast<std::map<std::string, std::uint32_t>>(valueIn);
665    */
666
667    for (auto i = valueIn.begin(); i != valueIn.end(); i++)
668    {
669        const char * tnv1;
670        std::any anyValue;
671        napi_value tnv2 = nullptr;
672        tnv1 = (i -> first).c_str();
673
674        if (typeid(i->second) == typeid(int32_t)){
675            tnv2 = SwapC2JsInt32(std::any_cast<int32_t>(i->second));
676        }
677        else if (typeid(i->second) == typeid(uint32_t)){
678            tnv2 = SwapC2JsUint32(std::any_cast<uint32_t>(i->second));
679        }
680        else if (typeid(i->second) == typeid(int64_t)){
681            tnv2 = SwapC2JsInt64(std::any_cast<int64_t>(i->second));
682        }
683        else if (typeid(i->second) == typeid(double_t)){
684            tnv2 = SwapC2JsDouble(std::any_cast<double_t>(i->second));
685        }
686        else if (typeid(i->second) == typeid(char *)){
687            tnv2 = SwapC2JsUtf8(std::any_cast<char *>(i->second));
688        }
689        else if (typeid(i->second) == typeid(bool)){
690            tnv2 = SwapC2JsBool(std::any_cast<bool>(i->second));
691        }
692
693        SetMapElement(result, tnv1, tnv2);
694    }
695    return;
696}
697
698bool XNapiTool::CheckFailed(bool b, const char *errStr)
699{
700    if (bFailed_) {
701        return true;
702    }
703    if (b) {
704        return false;
705    }
706
707    napi_value errCode = nullptr;
708    napi_value errMessage = nullptr;
709
710    napi_create_string_utf8(env_, "x_tool", strlen("x_tool"), &errCode);
711    napi_create_string_utf8(env_, errStr, strlen(errStr), &errMessage);
712    napi_create_error(env_, errCode, errMessage, &error_);
713    printf("tool_utility err : %s\\n", errStr);
714
715    bFailed_ = true;
716    return true;
717}
718
719int32_t XNapiTool::SwapJs2CInt32(napi_value value)
720{
721    int32_t result;
722    napi_status result_status = napi_get_value_int32(env_, value, &result);
723    if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail"))
724        return -1;
725    return result;
726}
727
728uint32_t XNapiTool::SwapJs2CUint32(napi_value value)
729{
730    uint32_t result;
731    napi_status result_status = napi_get_value_uint32(env_, value, &result);
732    if (CheckFailed(result_status == napi_ok, "swap_js_2_c_uint32 fail"))
733        return -1;
734    return result;
735}
736
737int64_t XNapiTool::SwapJs2CInt64(napi_value value)
738{
739    int64_t result;
740    napi_status result_status = napi_get_value_int64(env_, value, &result);
741    if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail"))
742        return -1;
743    return result;
744}
745
746double_t XNapiTool::SwapJs2CDouble(napi_value value)
747{
748    double_t result;
749    napi_status result_status = napi_get_value_double(env_, value, &result);
750    if (CheckFailed(result_status == napi_ok, "swap_js_2_c_int32 fail"))
751        return -1;
752    return result;
753}
754
755size_t XNapiTool::SwapJs2CUtf8(napi_value value, std::string &str)
756{
757    char buf[1024];
758    size_t result;
759    napi_status result_status = napi_get_value_string_utf8(env_, value, buf, 1024, &result);
760    if (CheckFailed(result_status == napi_ok, "napi_get_value_string_utf8 fail"))
761        return -1;
762    str = buf;
763    return result;
764}
765
766napi_value XNapiTool::SwapC2JsBool(bool value)
767{
768    napi_value result;
769    napi_status result_status = napi_get_boolean(env_, value, &result);
770    CC_ASSERT(result_status == napi_ok);
771    return result;
772}
773
774napi_value XNapiTool::SwapC2JsInt32(int32_t value)
775{
776    napi_value result;
777    napi_status result_status = napi_create_int32(env_, value, &result);
778    CC_ASSERT(result_status == napi_ok);
779    return result;
780}
781
782napi_value XNapiTool::SwapC2JsUint32(uint32_t value)
783{
784    napi_value result;
785    napi_status result_status = napi_create_uint32(env_, value, &result);
786    CC_ASSERT(result_status == napi_ok);
787    return result;
788}
789
790napi_value XNapiTool::SwapC2JsInt64(int64_t value)
791{
792    napi_value result;
793    napi_status result_status = napi_create_int64(env_, value, &result);
794    CC_ASSERT(result_status == napi_ok);
795    return result;
796}
797
798napi_value XNapiTool::SwapC2JsDouble(double_t value)
799{
800    napi_value result;
801    napi_status result_status = napi_create_double(env_, value, &result);
802    CC_ASSERT(result_status == napi_ok);
803    return result;
804}
805
806napi_value XNapiTool::SwapC2JsUtf8(const char *value)
807{
808    napi_value result;
809    napi_status result_status = napi_create_string_utf8(env_, value, NAPI_AUTO_LENGTH, &result);
810    CC_ASSERT(result_status == napi_ok);
811    return result;
812}
813
814bool XNapiTool::CheckValueType(napi_value value, napi_valuetype type)
815{
816    napi_valuetype valueType;
817    napi_status result_status = napi_typeof(env_, value, &valueType);
818    CC_ASSERT(result_status == napi_ok);
819    if (CheckFailed(valueType == type, "传入参数类型不是回调函数"))
820        return false;
821    return true;
822}
823
824napi_value XNapiTool::SyncCallBack(napi_value func, size_t argc, napi_value *args)
825{
826    napi_value cb_result;
827    napi_status result_status = napi_call_function(env_, thisVar_, func, argc, args, &cb_result);
828    CC_ASSERT(result_status == napi_ok);
829    return cb_result;
830}
831
832void XNapiTool::AsyncExecuteFunction()
833{
834    if (executeFunction_ != nullptr) {
835        executeFunction_(this, valueData_);
836    }
837}
838void XNapiTool::AsyncExecute(napi_env env, void *p)
839{
840    XNapiTool *pxt = (XNapiTool *)p;
841    pxt->AsyncExecuteFunction();
842}
843void XNapiTool::AsyncCompleteFunction()
844{
845    if (completeFunction_ != nullptr) {
846        completeFunction_(this, valueData_);
847    }
848}
849void XNapiTool::AsyncComplete(napi_env env, napi_status status, void *p)
850{
851    XNapiTool *pxt = (XNapiTool *)p;
852    pxt->AsyncCompleteFunction();
853    delete pxt;
854}
855
856napi_value XNapiTool::StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func)
857{
858    napi_value result;
859    napi_status result_status;
860
861    if (func == nullptr) {
862        // promise
863        result_status = napi_create_promise(env_, &deferred_, &result);
864        CC_ASSERT(result_status == napi_ok);
865        asyncMode_ = AsyncMode::PROMISE;
866    } else {
867        // callback
868        result_status = napi_create_reference(env_, func, 1, &callbackFunc_);
869        CC_ASSERT(result_status == napi_ok);
870        asyncMode_ = AsyncMode::CALLBACK;
871        result = UndefinedValue(env_);
872    }
873
874    asyncNeedRelease_ = true;
875    executeFunction_ = pe;
876    completeFunction_ = pc;
877    valueData_ = data;
878
879    napi_value resourceName = nullptr;
880    result_status = napi_create_string_utf8(env_, "tool_utility", NAPI_AUTO_LENGTH, &resourceName);
881    CC_ASSERT(result_status == napi_ok);
882    result_status = napi_create_async_work(env_, nullptr, resourceName, XNapiTool::AsyncExecute,
883        XNapiTool::AsyncComplete, this, &work_);
884    CC_ASSERT(result_status == napi_ok);
885    result_status = napi_queue_async_work(env_, work_);
886    CC_ASSERT(result_status == napi_ok);
887
888    return result;
889}
890
891void XNapiTool::FinishAsync(size_t argc, napi_value *args)
892{
893    if (asyncMode_ == AsyncMode::PROMISE) {
894        if (argc > 1) {
895            napi_resolve_deferred(env_, deferred_, args[1]);
896        } else {
897            napi_reject_deferred(env_, deferred_, SwapC2JsUtf8("promise fail"));
898        }
899        return;
900    }
901    napi_value result = 0;
902    napi_value cb = 0;
903
904    napi_status result_status = napi_get_reference_value(env_, callbackFunc_, &cb);
905    CC_ASSERT(result_status == napi_ok);
906    result_status = napi_call_function(env_, thisVar_, cb, argc, args, &result);
907    CC_ASSERT(result_status == napi_ok);
908}
909
910napi_value XNapiTool::UndefinedValue(napi_env env)
911{
912    napi_value result;
913    napi_get_undefined(env, &result);
914    return result;
915}
916
917napi_value XNapiTool::UndefinedValue()
918{
919    napi_value result;
920    napi_get_undefined(env_, &result);
921    return result;
922}
923
924napi_value XNapiTool::CreateSubObject(napi_value parent, const char *name)
925{
926    napi_value result;
927    napi_status result_status = napi_create_object(env_, &result);
928    CC_ASSERT(result_status == napi_ok);
929
930    result_status = napi_set_named_property(env_, parent, name, result);
931    CC_ASSERT(result_status == napi_ok);
932
933    return result;
934}
935
936void XNapiTool::DefineFunction(const char *funcName, napi_callback callback, napi_value dest)
937{
938    if (dest == nullptr)
939        dest = exports_;
940    napi_property_descriptor descriptor[] = {
941        {funcName, 0, callback, 0, 0, 0, napi_default, 0}};
942
943    napi_status result_status = napi_define_properties(env_, dest, 1, descriptor);
944    CC_ASSERT(result_status == napi_ok);
945}
946
947void XNapiTool::SetEnumProperty(napi_value dstObj, const char *propName, std::any objValue)
948{
949    napi_value prop = nullptr;
950    napi_status result_status = napi_invalid_arg;
951
952    if (objValue.type() == typeid(int32_t)) {
953        result_status = napi_create_int32(env_, std::any_cast<int32_t>(objValue), &prop);
954    } else if (objValue.type() == typeid(uint32_t)) {
955        result_status = napi_create_uint32(env_, std::any_cast<uint32_t>(objValue), &prop);
956    } else if (objValue.type() == typeid(int64_t)) {
957        result_status = napi_create_int64(env_, std::any_cast<int64_t>(objValue), &prop);
958    } else if (objValue.type() == typeid(double_t)) {
959        result_status = napi_create_double(env_, std::any_cast<double_t>(objValue), &prop);
960    } else if (objValue.type() == typeid(const char *)){
961        result_status = napi_create_string_utf8(env_, std::any_cast<const char *>(objValue), NAPI_AUTO_LENGTH, &prop);
962    }
963
964    CC_ASSERT(result_status == napi_ok);
965    result_status = napi_set_named_property(env_, dstObj, propName, prop);
966    CC_ASSERT(result_status == napi_ok);
967}
968
969void XNapiTool::CreateEnumObject(const char *enumName, std::map<const char *, std::any> enumMap)
970{
971    napi_value enumObj = nullptr;
972    napi_create_object(env_, &enumObj);
973
974    for (auto it = enumMap.begin(); it != enumMap.end(); it++) {
975        SetEnumProperty(enumObj, it->first, it->second);
976    }
977
978    napi_property_descriptor exportEnum[] = {
979        {enumName, 0, 0, 0, 0, enumObj, napi_enumerable, 0}
980    };
981    napi_status result_status = napi_define_properties(env_, exports_, 1, exportEnum);
982    CC_ASSERT(result_status == napi_ok);
983}
984
985void XNapiTool::DefineClass(const char *className, napi_callback constructorFunc,
986    std::map<const char *, std::map<const char *, napi_callback>> &valueList,
987    std::map<const char *, napi_callback> &funcList, napi_value dest)
988{
989    if (dest == nullptr)
990        dest = exports_;
991    napi_value tmpClass = nullptr;
992    napi_property_descriptor funcs[funcList.size() + valueList.size()];
993
994    uint32_t p = 0;
995    for (auto it = valueList.begin(); it != valueList.end(); it++) {
996        funcs[p++] = {it->first, 0, 0, it->second["getvalue"], it->second["setvalue"], 0, napi_default, 0}; // get,set
997    }
998    for (auto it = funcList.begin(); it != funcList.end(); it++) {
999        funcs[p++] = {it->first, 0, it->second, 0, 0, 0, napi_default, 0};
1000    }
1001
1002    napi_status result_status = napi_define_class(env_, className, NAPI_AUTO_LENGTH, constructorFunc,
1003    nullptr, p, funcs, &tmpClass);
1004    CC_ASSERT(result_status == napi_ok);
1005
1006    result_status = napi_set_named_property(env_, dest, className, tmpClass);
1007    CC_ASSERT(result_status == napi_ok);
1008}
1009
1010void XNapiTool::WrapFinalize(napi_env env, void *data, void *hint)
1011{
1012    XNapiTool *pxt = (XNapiTool *)data;
1013    pxt->ReleaseInstance();
1014    delete pxt;
1015}
1016
1017void XNapiTool::ReleaseInstance()
1018{
1019    if (releaseInstance_ != nullptr) {
1020        releaseInstance_(pInstance_);
1021    }
1022}
1023
1024napi_value XNapiTool::WrapInstance(void *instance, RELEASE_INSTANCE ri)
1025{
1026    pInstance_ = instance;
1027    releaseInstance_ = ri;
1028    napi_status result_status = napi_wrap(env_, thisVar_, this, WrapFinalize, nullptr, &wrapper_);
1029    CC_ASSERT(result_status == napi_ok);
1030    return thisVar_;
1031}
1032
1033void *XNapiTool::UnWarpInstance()
1034{
1035    XNapiTool *p;
1036    napi_status result_status = napi_unwrap(env_, thisVar_, (void **)&p);
1037    CC_ASSERT(result_status == napi_ok);
1038    return p->pInstance_;
1039}
1040
1041void XNapiTool::SetAsyncInstance(void *p)
1042{
1043    asyncInstance_ = p;
1044}
1045
1046void *XNapiTool::GetAsyncInstance()
1047{
1048    return asyncInstance_;
1049}
1050
1051std::map<std::string, AsyncFunc> XNapiTool::asyncFuncs_;
1052void XNapiTool::RegistAsyncFunc(std::string name, napi_value func)
1053{
1054    if (XNapiTool::asyncFuncs_.count(name) > 0) {
1055        UnregistAsyncFunc(name);
1056    }
1057    XNapiTool::asyncFuncs_[name].env_ = env_;
1058    napi_status result_status = napi_create_reference(env_, func, 1, &XNapiTool::asyncFuncs_[name].funcRef_);
1059    CC_ASSERT(result_status == napi_ok);
1060    result_status = napi_create_reference(env_, thisVar_, 1, &XNapiTool::asyncFuncs_[name].thisVarRef_);
1061    CC_ASSERT(result_status == napi_ok);
1062}
1063
1064void XNapiTool::UnregistAsyncFunc(std::string name)
1065{
1066    if (XNapiTool::asyncFuncs_.count(name) <= 0) {
1067        return;
1068    }
1069    napi_status result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].funcRef_);
1070    CC_ASSERT(result_status == napi_ok);
1071    result_status = napi_delete_reference(env_, XNapiTool::asyncFuncs_[name].thisVarRef_);
1072    CC_ASSERT(result_status == napi_ok);
1073    XNapiTool::asyncFuncs_.erase(name);
1074}
1075
1076void XNapiTool::CallAsyncFunc(AsyncFunc * pAsyncFuncs, napi_value ret)
1077{
1078    uv_loop_s *loop = nullptr;
1079    napi_get_uv_event_loop(pAsyncFuncs->env_, &loop);
1080    uv_work_t *work = new uv_work_t;
1081
1082    struct AsyncCallData
1083    {
1084        napi_ref resultRef;
1085        AsyncFunc *p;
1086    };
1087    AsyncCallData *data = (AsyncCallData *)malloc(sizeof(AsyncCallData));
1088    napi_create_reference(pAsyncFuncs->env_, ret, 1, &data->resultRef);
1089    data->p = pAsyncFuncs;
1090    work->data = data;
1091
1092    uv_queue_work(
1093        loop,
1094        work,
1095        [](uv_work_t *) {},
1096        [](uv_work_t *work, int status)
1097        {
1098            AsyncCallData *data = (AsyncCallData *)work->data;
1099            AsyncFunc *paf = data->p;
1100            napi_handle_scope scope = nullptr;
1101            napi_open_handle_scope(paf->env_, &scope);
1102
1103            napi_value cb = 0;
1104            napi_status result_status = napi_get_reference_value(paf->env_, paf->funcRef_, &cb);
1105            CC_ASSERT(result_status == napi_ok);
1106
1107            napi_value thisvar = 0;
1108            result_status = napi_get_reference_value(paf->env_, paf->thisVarRef_, &thisvar);
1109            CC_ASSERT(result_status == napi_ok);
1110
1111            napi_value retValue = 0;
1112            result_status = napi_get_reference_value(paf->env_, data->resultRef, &retValue);
1113            CC_ASSERT(result_status == napi_ok);
1114            napi_value args[1] = {retValue};
1115
1116            napi_value cb_result;
1117            result_status = napi_call_function(paf->env_, thisvar, cb, 1, args, &cb_result);
1118            CC_ASSERT(result_status == napi_ok);
1119
1120            result_status = napi_delete_reference(paf->env_, data->resultRef);
1121            CC_ASSERT(result_status == napi_ok);
1122
1123            napi_close_handle_scope(paf->env_, scope);
1124            free(data);
1125            delete work;
1126        });
1127}
1128`
1129
1130function generateBase(destDir, license) {
1131    writeFile(re.pathJoin(destDir, "tool_utility.h"), null != license ? (license + "\n" + xNapiToolH) : xNapiToolH)
1132    writeFile(re.pathJoin(destDir, "tool_utility.cpp"), null != license ? (license + "\n" + xNapiToolCpp):xNapiToolCpp)
1133}
1134
1135module.exports = {
1136    generateBase
1137}