• 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 { generateFunctionDirect } = require('./function_direct');
16const { generateFunctionSync } = require('./function_sync');
17const { generateFunctionAsync } = require('./function_async');
18const { FuncType, InterfaceList, getArrayType } = require('../tools/common');
19const { jsToC } = require('./param_generate');
20const { cToJs } = require('./return_generate');
21const re = require('../tools/re');
22const { NapiLog } = require('../tools/NapiLog');
23
24let middleBodyTmplete = `
25class [className]_middle {
26public:
27    static napi_value constructor(napi_env env, napi_callback_info info)
28    {
29        XNapiTool *pxt = new XNapiTool(env, info);
30        [className] *p = new [className]();
31        napi_value thisvar = pxt->WrapInstance(reinterpret_cast<DataPtr>(p), release);
32        return thisvar;
33    }
34    static void release(DataPtr p)
35    {
36        void *dataPtr = p;
37        [className] *p2 = static_cast<[className] *>(dataPtr);
38        delete p2;
39    }
40    [static_funcs]
41};`;
42
43function generateVariable(name, type, variable, className) {
44    if (type === 'string') {
45        variable.hDefine += '\n    std::string %s;'.format(name);
46    } else if (type.substring(0, 12) === 'NUMBER_TYPE_') {
47        variable.hDefine += '\n    %s %s;'.format(type, name);
48    } else if (InterfaceList.getValue(type)) {
49        variable.hDefine += '\n    %s %s;'.format(type, name);
50    } else if (type.indexOf('Array<') === 0) {
51        let type2 = getArrayType(type);
52        if (type2 === 'string') {
53            type2 = 'std::string';
54        }
55        if (type2 === 'boolean') {
56            type2 = 'bool';
57        }
58        variable.hDefine += '\n    std::vector<%s> %s;'.format(type2, name);
59    } else if (type === 'boolean') {
60        variable.hDefine += '\n    bool %s;'.format(name);
61    } else if (type.indexOf('[]') === 0) {
62        variable.hDefine += '\n    std::vector<%s> %s;'.format(type, name);
63    } else {
64        NapiLog.logError(`
65        ---- generateVariable fail %s,%s ----
66        `.format(name, type));
67    }
68    variable.middleValue += `
69    static napi_value getvalue_%s(napi_env env, napi_callback_info info)
70    {
71        XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release();
72        void *instPtr = pxt->UnWarpInstance();
73        %s *p = static_cast<%s *>(instPtr);
74        napi_value result = nullptr;
75        `.format(name, className, className) + cToJs('p->' + name, type, 'result') + `
76        delete pxt;
77        return result;
78    }
79    static napi_value setvalue_%s(napi_env env, napi_callback_info info)
80    {
81        std::shared_ptr<XNapiTool> pxt = std::make_shared<XNapiTool>(env, info);
82        void *instPtr = pxt->UnWarpInstance();
83        %s *p = static_cast<%s *>(instPtr);
84        `.format(name, className, className) + jsToC('p->' + name, 'pxt->GetArgv(XNapiTool::ZERO)', type) + `
85        return nullptr;
86    }
87`;
88}
89
90function generateClass(name, data, inNamespace, functiontType) {
91    let resultConnect = connectResult(data, inNamespace, name);
92    let middleFunc = resultConnect[0];
93    let implH = functiontType === 'static' ? '\n' + 'static ' +
94        resultConnect[1].substring(1, resultConnect[1].length) : resultConnect[1];
95    let implCpp = resultConnect[2];
96    let middleInit = resultConnect[3];
97    let middleH = resultConnect[4];
98    let selfNs = '';
99    if (inNamespace.length > 0) {
100        let nsl = inNamespace.split('::');
101        nsl.pop();
102        if (nsl.length >= 2) {
103            selfNs = ', ' + nsl[nsl.length - 1];
104        }
105    }
106    let toolNamespace = getToolNamespace(inNamespace);
107    middleInit += `\n    pxt->DefineClass("%s", %s%s%s_middle::constructor, valueList, funcList%s);\n}\n`
108        .format(name, inNamespace, toolNamespace, name, selfNs);
109    let result = {
110        implH: `
111class %s {
112public:%s
113};`.format(name, implH),
114        implCpp: implCpp,
115        middleBody: middleBodyTmplete.replaceAll('[className]', name).replaceAll('[static_funcs]', middleFunc),
116        middleInit: middleInit,
117        declarationH: `
118class %s;\r`.format(name),
119        middleH: middleH
120    };
121    return result;
122}
123
124function connectResult(data, inNamespace, name) {
125    let implH = '';
126    let implCpp = '';
127    let middleFunc = '';
128    let middleInit = '';
129    let middleH = '';
130    let variable = {
131        hDefine: '',
132        middleValue: '',
133    };
134    let toolNamespace = getToolNamespace(inNamespace);
135    middleInit = `{\n    std::map<const char *, std::map<const char *, napi_callback>> valueList;`;
136    for (let i in data.value) {
137        let v = data.value[i];
138        generateVariable(v.name, v.type, variable, name);
139        middleInit += `
140    valueList["%s"]["getvalue"] = %s%s%s_middle::getvalue_%s;
141    valueList["%s"]["setvalue"] = %s%s%s_middle::setvalue_%s;`
142            .format(v.name, inNamespace, toolNamespace, name, v.name, v.name, inNamespace, toolNamespace, name, v.name);
143    }
144    implH += variable.hDefine;
145    middleFunc += variable.middleValue;
146    middleInit += `\n    std::map<const char *, napi_callback> funcList;`;
147    for (let i in data.function) {
148        let func = data.function[i];
149        let tmp = [];
150        switch (func.type) {
151            case FuncType.DIRECT:
152                tmp = generateFunctionDirect(func, '', name);
153                break;
154            case FuncType.SYNC:
155                tmp = generateFunctionSync(func, '', name);
156                break;
157            case FuncType.ASYNC:
158            case FuncType.PROMISE:
159                tmp = generateFunctionAsync(func, '', name);
160                break;
161            default:
162                tmp = [];
163                break;
164        }
165        middleFunc += tmp[0];
166        implH += tmp[1];
167        implCpp += tmp[2];
168        middleH += tmp[3];
169        middleInit += `\n    funcList["%s"] = %s%s%s_middle::%s_middle;`
170            .format(func.name, inNamespace, toolNamespace, name, func.name);
171    }
172    return [middleFunc, implH, implCpp, middleInit, middleH];
173}
174
175function getToolNamespace(inNamespace) {
176    let index = inNamespace.lastIndexOf('::');
177    let toolNamespace;
178    if (index > 0) {
179        let bodyTmp = inNamespace.substring(0, index);
180        let index2 = bodyTmp.lastIndexOf('::');
181        if (index2 > 0 && index2 < index) {
182            toolNamespace = inNamespace.substring(index2 + 2, index) + '_interface::';
183        } else {
184            toolNamespace = bodyTmp + '_interface::';
185        }
186    } else {
187        toolNamespace = inNamespace + '_interface::';
188    }
189    return toolNamespace;
190}
191
192module.exports = {
193    generateClass
194};