awtk/tools/object_gen/gen_object.js
lixianjing e53e74db80 Revert "update gen_object"
This reverts commit 47b555896d.
2022-03-01 16:30:04 +08:00

584 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs')
const path = require('path')
const fse = require('fs-extra')
class CodeGen {
genPropDecls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
result = json.props.map(iter => {
let propDecl = `
/**
* @property {${iter.type}} ${iter.name}
* @annotation ["readable"]
* ${iter.desc}
*/
${iter.type} ${iter.name};
`
return propDecl;
}).join('');
return result;
}
genPropSetterDecls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
result = json.props.map(iter => {
return `
/**
* @method ${className}_set_${iter.name}
* 设置 ${iter.desc}
* @param {${className}_t*} ${className} ${className}对象。
* @param {${this.mapType(iter.type)}} ${iter.name} ${iter.desc}
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t ${className}_set_${iter.name}(${className}_t* ${className}, ${this.genParamDecl(iter.type, iter.name)});
`
}).join('');
return result;
}
genPropDefines(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const uclassName = json.name.toUpperCase();
result = json.props.map(iter => {
const uPropName = iter.name.toUpperCase();
return `#define ${uclassName}_PROP_${uPropName} "${iter.name}"`
}).join('\n');
return result;
}
genAssignValue(type, name, value) {
if (type.indexOf("char*") >= 0) {
return `${name} = tk_str_copy(${name}, ${value});`;
} else {
return `${name} = ${value};`;
}
}
mapType(type) {
if (type.indexOf("char*") >= 0) {
return `const char*`;
} else {
return type;
}
}
genParamDecl(type, name) {
return `${this.mapType(type)} ${name}`;
}
genPropSetterImpls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map(iter => {
let type = `${iter.type}`;
const paramDecl = this.genParamDecl(iter.type, iter.name);
const assignValue = this.genAssignValue(iter.type, `${className}->${iter.name}`, iter.name);
let propSetter = `
ret_t ${className}_set_${iter.name}(${className}_t* ${className}, ${paramDecl}) {
return_value_if_fail(${className} != NULL, RET_BAD_PARAMS);
${assignValue}
return RET_OK;
}
`
return propSetter;
}).join('');
return result;
}
genPropList(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const uclassName = json.name.toUpperCase();
result = json.props.map(iter => {
const uPropName = iter.name.toUpperCase();
return ` ${uclassName}_PROP_${uPropName}`
}).join(',\n');
return result;
}
genToValue(clsName, type, name) {
switch (type) {
case 'int8_t':
case 'int16_t':
case 'int32_t':
case 'int64_t':
case 'uint8_t':
case 'uint16_t':
case 'uint32_t':
case 'uint64_t':
case 'bool_t':
case 'float_t':
case 'float':
case 'double': {
let typeName = type.replace(/_t$/, '');
return `value_set_${typeName}(v, ${clsName}->${name});`;
}
case 'char*': {
return `value_set_str(v, ${clsName}->${name});`;
}
case 'void*': {
return `value_set_pointer(v, ${clsName}->${name});`;
}
case 'color_t': {
return `value_set_uint32(v, ${clsName}->${name}.color);`;
}
default: {
console.log(`not supported ${type} for ${name}`);
process.exit(0);
}
}
}
genFromValue(clsName, type, name) {
let typeName = '';
switch (type) {
case 'int8_t':
case 'int16_t':
case 'int32_t':
case 'int64_t':
case 'uint8_t':
case 'uint16_t':
case 'uint32_t':
case 'uint64_t':
case 'bool_t':
case 'float_t':
case 'float':
case 'double': {
typeName = type.replace(/_t$/, '');
break;
}
case 'color_t': {
return `${clsName}_set_${name}(${clsName}, color_parse(value_str(v)));`;
break;
}
case 'char*': {
typeName = 'str';
break;
}
case 'void*': {
typeName = 'pointer';
break;
}
default: {
console.log(`not supported ${type} for ${name}`);
process.exit(0);
}
}
return `${clsName}_set_${name}(${clsName}, value_${typeName}(v));`;
}
genSetPropDispatch(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map((iter, index) => {
const uPropName = iter.name.toUpperCase();
const propMacro = `${uclassName}_PROP_${uPropName}`
let setProp = '';
if (index) {
setProp = `\n } else if (tk_str_eq(${propMacro}, name)) {\n`
} else {
setProp = ` if (tk_str_eq(${propMacro}, name)) {\n`
}
setProp += ` ${this.genFromValue(className, iter.type, iter.name)}\n`;
setProp += ' return RET_OK;';
return setProp;
}).join('');
result += '\n }';
return result;
}
genPropInits(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
result = json.props.map((iter) => {
if (iter.init_value) {
if (iter.type === 'char*' && iter.init_value != 'NULL') {
return ` ${className}->${iter.name} = tk_strdup("${iter.init_value}");\n`;
} else {
return ` ${className}->${iter.name} = ${iter.init_value};\n`;
}
}
}).join('');
return result;
}
genFreeProps(json) {
let result = '';
const className = json.name;
if (!json.props || !json.props.length) {
return result;
}
result = json.props.map((iter, index) => {
if (iter.type.indexOf('char*') >= 0) {
return ` TKMEM_FREE(${className}->${iter.name});\n`;
} else {
return '';
}
}).join('');
return result;
}
genGetPropDispatch(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map((iter, index) => {
const uPropName = iter.name.toUpperCase();
const propMacro = `${uclassName}_PROP_${uPropName}`
let setProp = '';
if (index) {
setProp = `\n } else if (tk_str_eq(${propMacro}, name)) {\n`
} else {
setProp = ` if (tk_str_eq(${propMacro}, name)) {\n`
}
setProp += ` ${this.genToValue(className, iter.type, iter.name)}\n`;
setProp += ' return RET_OK;';
return setProp;
}).join('');
result += '\n }';
return result;
}
genH(json) {
let parent = "";
let includes = '#include "tkc/object.h"\n';
let parentAnnotation = "";
const className = json.name;
const uclassName = json.name.toUpperCase();
if (json.parent) {
parent = `${json.parent}_t ${json.parent};`
parentAnnotation = `@parent ${json.parent}`
if (json.parent != 'object') {
includes = `#include "${json.parent}.h"\n`
}
}
if (json.includes) {
json.includes.forEach(iter => {
includes += `#include "${iter}"\n`
});
}
return `
/**
* File: ${className}.h
* Author: AWTK Develop Team
* Brief: ${json.desc}
*
* Copyright (c) ${json.copyright}
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* ${json.date} ${json.author} created
*
*/
#ifndef TK_${uclassName}_H
#define TK_${uclassName}_H
${includes}
BEGIN_C_DECLS
/**
* @class ${className}_t
* ${parentAnnotation}
* ${json.desc}
*/
typedef struct _${className}_t {
${parent}
${this.genPropDecls(json)}
} ${className}_t;
${this.genPropSetterDecls(json)}
${this.genPropDefines(json)}
/*public for subclass*/
/**
* @method ${className}_deinit
* ~初始化对象。
* @param {${className}_t*} ${className} ${className}对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t ${className}_deinit(${className}_t* ${className});
/**
* @method ${className}_init
* 初始化对象。
* @param {${className}_t*} ${className} ${className}对象。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
${className}_t* ${className}_init(${className}_t* ${className});
/**
* @method ${className}_set_prop
* 设置属性。
* @param {${className}_t*} ${className} ${className}对象。
* @param {const char*} name 属性名。
* @param {const value_t*} v 属性值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t ${className}_set_prop(${className}_t* ${className}, const char* name, const value_t* v);
/**
* @method ${className}_get_prop
* 获取属性。
* @param {${className}_t*} ${className} ${className}对象。
* @param {const char*} name 属性名。
* @param {value_t*} v 属性值。
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败。
*/
ret_t ${className}_get_prop(${className}_t* ${className}, const char* name, value_t* v);
/**
* @method ${className}_cast
* 类型转换。
* @param {${className}_t*} ${className} ${className}对象。
*
* @return {${className}_t*} 返回非NULL表示成功否则表示失败。
*/
${className}_t* ${className}_cast(object_t* obj);
/**
* @method ${className}_create
* 创建对象。
* @return {${className}_t*} 返回非NULL表示成功否则表示失败。
*/
${className}_t* ${className}_create(void);
#define ${uclassName}(obj) ${className}_cast(OBJECT(obj))
END_C_DECLS
#endif/*TK_${uclassName}_H*/
`
}
genC(json) {
let parent = "";
let parentUpper = "";
let parentSetProp = "";
let parentGetProp = "";
let parentInit = "";
let parentDeinit = "";
const className = json.name;
const uclassName = json.name.toUpperCase();
if (json.parent) {
parent = json.parent;
parentUpper = parent.toUpperCase();
if(parent !== 'object') {
parentSetProp = `
if(${parent}_set_prop(${parentUpper}(${className}), name, v) == RET_OK) {
return RET_OK;
}`
parentGetProp = `
if(${parent}_get_prop(${parentUpper}(${className}), name, v) == RET_OK) {
return RET_OK;
}`
parentInit = ` ${parent}_init(${parentUpper}(${className}));`;
parentDeinit = ` ${parent}_deinit(${parentUpper}(${className}));`;
}
}
return `
/**
* File: ${className}.c
* Author: AWTK Develop Team
* Brief: ${json.desc}
*
* Copyright (c) ${json.copyright}
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* ${json.date} ${json.author} created
*
*/
#include "tkc/mem.h"
#include "tkc/str.h"
#include "tkc/utils.h"
#include "${className}.h"
${this.genPropSetterImpls(json)}
ret_t ${className}_set_prop(${className}_t* ${className}, const char* name, const value_t* v) {
return_value_if_fail(${className} != NULL && name != NULL && v != NULL , RET_BAD_PARAMS);
${parentSetProp}
${this.genSetPropDispatch(json)}
return RET_NOT_FOUND;
}
static ret_t ${className}_set_prop_obj(object_t* obj, const char* name, const value_t* v) {
${className}_t* ${className} = ${uclassName}(obj);
return_value_if_fail(${className} != NULL && name != NULL && v != NULL , RET_BAD_PARAMS);
return ${className}_set_prop(${className}, name, v);
}
ret_t ${className}_get_prop(${className}_t* ${className}, const char* name, value_t* v) {
return_value_if_fail(${className} != NULL && name != NULL && v != NULL , RET_BAD_PARAMS);
${parentGetProp}
${this.genGetPropDispatch(json)}
return RET_NOT_FOUND;
}
static ret_t ${className}_get_prop_obj(object_t* obj, const char* name, value_t* v) {
${className}_t* ${className} = ${uclassName}(obj);
return_value_if_fail(${className} != NULL && name != NULL && v != NULL , RET_BAD_PARAMS);
return ${className}_get_prop(${className}, name, v);
}
ret_t ${className}_deinit(${className}_t* ${className}) {
return_value_if_fail(${className} != NULL, RET_BAD_PARAMS);
${this.genFreeProps(json)}
${parentDeinit}
return RET_OK;
}
static ret_t ${className}_on_destroy(object_t* obj) {
return ${className}_deinit(${uclassName}(obj));
}
static const object_vtable_t s_${className}_vtable = {.type = "${className}",
.desc = "${className}",
.size = sizeof(${className}_t),
.is_collection = FALSE,
.on_destroy = ${className}_on_destroy,
.get_prop = ${className}_get_prop_obj,
.set_prop = ${className}_set_prop_obj};
${className}_t* ${className}_init(${className}_t* ${className}) {
return_value_if_fail(${className} != NULL, NULL);
${parentInit}
${this.genPropInits(json)}
return ${className};
}
${className}_t* ${className}_create(void) {
object_t* o = object_create(&s_${className}_vtable);
return_value_if_fail(o != NULL, NULL);
return ${className}_init(${uclassName}(o));
}
${className}_t* ${className}_cast(object_t* obj) {
return_value_if_fail(obj != NULL && obj->vt == &s_${className}_vtable, NULL);
return (${className}_t*)(obj);
}
`
}
genJson(json) {
const header = this.genH(json);
const content = this.genC(json);
const headerFileName = `${json.name}.h`
const contentFileName = `${json.name}.c`
fs.writeFileSync(headerFileName, '\ufeff' + header);
fs.writeFileSync(contentFileName, '\ufeff' + content);
console.log(`output to ${headerFileName} and ${contentFileName}`);
}
genFile(filename) {
this.genJson(JSON.parse(fs.readFileSync(filename).toString()));
}
static run(sourceIDL) {
const gen = new CodeGen();
gen.genFile(sourceIDL);
}
}
if (process.argv.length < 3) {
console.log(`Usage: node index.js foo.json`);
process.exit(0);
}
CodeGen.run(process.argv[2], process.argv[3], process.argv[4]);