UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

243 lines 11 kB
import fs from "fs-extra"; import path from "path"; import { ProtocolStructParser } from "./ProtocolStructParser.js"; import { Byte } from "./Byte.js"; import { toolchain } from "../tools/toolchain.js"; var EBaseType; (function (EBaseType) { EBaseType[EBaseType["char"] = 0] = "char"; EBaseType[EBaseType["uchar"] = 1] = "uchar"; EBaseType[EBaseType["byte"] = 2] = "byte"; EBaseType[EBaseType["short"] = 3] = "short"; EBaseType[EBaseType["ushort"] = 4] = "ushort"; EBaseType[EBaseType["int"] = 5] = "int"; EBaseType[EBaseType["uint"] = 6] = "uint"; EBaseType[EBaseType["longlong"] = 7] = "longlong"; EBaseType[EBaseType["ulonglong"] = 8] = "ulonglong"; EBaseType[EBaseType["string"] = 9] = "string"; EBaseType[EBaseType["max"] = 10] = "max"; })(EBaseType || (EBaseType = {})); ; var ETypeFlagV1; (function (ETypeFlagV1) { ETypeFlagV1[ETypeFlagV1["has_count"] = 268435456] = "has_count"; ETypeFlagV1[ETypeFlagV1["has_ver"] = 536870912] = "has_ver"; ETypeFlagV1[ETypeFlagV1["has_refer"] = 1073741824] = "has_refer"; ETypeFlagV1[ETypeFlagV1["has_select"] = 2147483648] = "has_select"; ETypeFlagV1[ETypeFlagV1["mask"] = 268435455] = "mask"; })(ETypeFlagV1 || (ETypeFlagV1 = {})); var ETypeFlagV2; (function (ETypeFlagV2) { ETypeFlagV2[ETypeFlagV2["has_count"] = 16777216] = "has_count"; ETypeFlagV2[ETypeFlagV2["has_ver"] = 33554432] = "has_ver"; ETypeFlagV2[ETypeFlagV2["has_refer"] = 67108864] = "has_refer"; ETypeFlagV2[ETypeFlagV2["has_select"] = 134217728] = "has_select"; ETypeFlagV2[ETypeFlagV2["safeprintf"] = 268435456] = "safeprintf"; ETypeFlagV2[ETypeFlagV2["mask"] = 16777215] = "mask"; })(ETypeFlagV2 || (ETypeFlagV2 = {})); const FIELD_NAME_MAX_LEN = 2048; export class Xml2CSBytes { static write(filePath) { class NameMgr { static names = []; static getNameIdx(name) { let nameIdx = this.names.indexOf(name); if (nameIdx < 0) { this.names.push(name); nameIdx = this.names.length - 1; } return nameIdx; } } class TypeMgr { static ins = new TypeMgr(); types = []; version = 1; constructor() { if (toolchain.projCfg.xml2protocol.useCSBytes === 'YES_V2') { this.version = 2; } console.log('Xml2CSBytes will build ss.bytes with version ' + this.version); for (let i = 0; i < EBaseType.max; i++) { this.types.push({ name: EBaseType[i], offset: 0, type: "base" }); } } getType(type) { type = this.convertType(type); let t = this.types.find(i => i.name == type); if (t) return this.types.indexOf(t); this.types.push({ name: type, offset: -1, type: "struct" }); return this.types.length - 1; } ; setTypeOffset(type, offset) { type = this.convertType(type); let t = this.types.find(i => i.name == type); console.assert(t.offset < 0); t.offset = offset; } isStructType(type) { type = this.convertType(type); let t = this.types.find(i => i.name == type); return t.type == "struct"; } serializedType(type) { type = this.convertType(type); let t = this.types.find(i => i.name == type); return t.offset >= 0; } convertType(type) { return type == "String" ? "string" : type; } } function getMacroValue(value) { if (!isNaN(Number(value))) return Number(value); let rt = ProtocolStructParser.Instance.getMacro(value)?._attributes.value; if (!isNaN(Number(rt))) return Number(rt); console.error("failed! 未找到宏定义:" + value); process.exit(1); } let writer = new Byte(new ArrayBuffer(5 * 1024 * 1024)); function writeStructType(st) { //writer.writeString(st._attributes.name); let valuemapPos = 0; let isUnion = st._attributes.class == "union"; let valueAndFieldMap = []; if (isUnion) { let fieldCount = 0; for (let entry of st.entries) { if (entry._attributes.value) fieldCount++; } writer.writeUint8(1); // union flag writer.writeUint32(fieldCount); valuemapPos = writer.Pos; writer.skip(fieldCount * 2 * 4); // 用来存放value哈希过后的bucket的节点个数和偏移量, {bucketNodesCount, bucketOffset}[] } else { writer.writeUint8(0); // struct flag writer.writeUint32(st.entries.length); } let attTypes = []; for (let entry of st.entries) { let att = entry._attributes; if (isUnion && !att.value) { continue; } const ETypeFlag = TypeMgr.ins.version > 1 ? ETypeFlagV2 : ETypeFlagV1; let nameIdx = NameMgr.getNameIdx(att.name); let type = TypeMgr.ins.getType(att.type); if (type > ETypeFlag.mask) { throw new Error('type overflow!'); } if (TypeMgr.ins.version > 1) { if (att.safeprintf) type = type | ETypeFlagV2.safeprintf; } if (isUnion) { let count = 0; if (att.size) count = getMacroValue(att.size); if (att.count) count = getMacroValue(att.count); if (count > 0xffff) { console.log("failed! 数组太长:" + st._attributes.name + "." + att.name); process.exit(1); } valueAndFieldMap.push({ value: getMacroValue(att.value), fieldType: type, fieldNameIdx: (count << 16) | nameIdx }); } else { writer.writeUint16(nameIdx); // write name_idx if (att.version) type = type | ETypeFlag.has_ver; if (att.count || att.size) type = type | ETypeFlag.has_count; if (att.refer) type = type | ETypeFlag.has_refer; if (att.select) type = type | ETypeFlag.has_select; writer.writeUint32(type); // write type if (att.version) writer.writeUint32(Number(att.version)); if (att.count) { writer.writeUint32(getMacroValue(att.count)); } ; if (att.size) { writer.writeUint32(getMacroValue(att.size)); } if (att.refer) { writer.writeUint16(NameMgr.getNameIdx(att.refer)); } if (att.select) { writer.writeUint16(NameMgr.getNameIdx(att.select)); } } attTypes.push(att.type); } for (let attType of attTypes) { if (TypeMgr.ins.isStructType(attType) && !TypeMgr.ins.serializedType(attType)) { TypeMgr.ins.setTypeOffset(attType, writer.Pos); writeStructType(ProtocolStructParser.Instance.getStructDef(attType)); } } if (isUnion) { valueAndFieldMap.sort((a, b) => a.value - b.value); // 生成hash的bucket节点 let bucketsOffset = []; for (let bucketIdx = 0, size = valueAndFieldMap.length; bucketIdx < size; bucketIdx++) { let bucketNodes = []; for (let vf of valueAndFieldMap) { if ((vf.value % size) == bucketIdx) { bucketNodes.push({ value: vf.value, fieldType: vf.fieldType, fieldNameIdx: vf.fieldNameIdx }); } } bucketsOffset.push({ bucketNodesCount: bucketNodes.length, bucketOffset: writer.Pos }); for (let node of bucketNodes) { writer.writeUint32(node.value); writer.writeUint32(node.fieldType); writer.writeUint32(node.fieldNameIdx); } } // 回填 {bucketNodesCount, bucketOffset}[] writer.resetPos(valuemapPos); for (let vf of bucketsOffset) { writer.writeUint32(vf.bucketNodesCount); writer.writeUint32(vf.bucketOffset); } writer.restorePos(); } } //写入文件头 writer.writeUint32(TypeMgr.ins.version); // 文件版本 writer.writeUint32(getMacroValue('VERSION')); // 协议版本 let typesBytesSizePos = writer.Pos; writer.skip(4); // 所有类型的字节长度 let headSize = writer.Pos; const bodyDef = ProtocolStructParser.Instance.getStructDef("CSMsgBody"); writeStructType(bodyDef); let typesEndPos = writer.Pos; // 回填所有类型的字节长度 writer.resetPos(typesBytesSizePos); writer.writeUint32(typesEndPos - headSize); writer.restorePos(); // 写入字段名names writer.writeUint16(NameMgr.names.length); // name个数 for (let name of NameMgr.names) { if ((name.length + 1) > FIELD_NAME_MAX_LEN) throw new Error("协议字段名超长, 字段名" + name); writer.writeUTF8String(name, false); } // 写入structtype在文件中的偏移量 writer.writeUint16(TypeMgr.ins.types.length); // type个数 for (let type of TypeMgr.ins.types) { writer.writeUint32(type.offset); } if (!fs.existsSync(path.dirname(filePath))) { fs.mkdirSync(path.dirname(filePath)); } fs.writeFileSync(filePath, writer.NewBuffer, { flag: "w" }); } } //# sourceMappingURL=Xml2CSBytes.js.map