diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java index 2f62dce2..ad4c6ff2 100644 --- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java +++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolFile.java @@ -13,17 +13,16 @@ package com.zfoo.protocol.generate; import com.zfoo.protocol.ProtocolManager; +import com.zfoo.protocol.collection.CollectionUtils; import com.zfoo.protocol.exception.UnknownException; import com.zfoo.protocol.registration.IProtocolRegistration; import com.zfoo.protocol.registration.ProtocolAnalysis; import com.zfoo.protocol.registration.ProtocolRegistration; import com.zfoo.protocol.serializer.CodeLanguage; -import com.zfoo.protocol.serializer.cpp.GenerateCppUtils; import com.zfoo.protocol.serializer.es.GenerateEsUtils; import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils; import com.zfoo.protocol.serializer.go.GenerateGoUtils; import com.zfoo.protocol.serializer.javascript.GenerateJsUtils; -import com.zfoo.protocol.serializer.lua.CodeGenerateLua; import com.zfoo.protocol.serializer.python.GeneratePyUtils; import com.zfoo.protocol.serializer.typescript.GenerateTsUtils; import com.zfoo.protocol.util.FileUtils; @@ -32,9 +31,7 @@ import com.zfoo.protocol.util.StringUtils; import java.io.IOException; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; @@ -80,10 +77,6 @@ public abstract class GenerateProtocolFile { return builder.toString(); } - public static void clear() { - generateProtocolFilter = null; - index = null; - } /** * EN: Generate protocol files to various languages @@ -118,6 +111,7 @@ public abstract class GenerateProtocolFile { // 通过协议号,从小到大排序 var generateProtocols = allGenerateProtocols.stream() .sorted((a, b) -> a.protocolId() - b.protocolId()) + .map(it -> (ProtocolRegistration) it) .toList(); // 解析协议的文档注释 @@ -127,13 +121,6 @@ public abstract class GenerateProtocolFile { // 生成C++协议 var generateLanguages = generateOperation.getGenerateLanguages(); - if (generateLanguages.contains(CodeLanguage.Cpp)) { - GenerateCppUtils.init(generateOperation); - GenerateCppUtils.createProtocolManager(generateProtocols); - for (var protocolRegistration : generateProtocols) { - GenerateCppUtils.createCppProtocolFile((ProtocolRegistration) protocolRegistration); - } - } // 生成Golang协议 if (generateLanguages.contains(CodeLanguage.Go)) { @@ -219,4 +206,26 @@ public abstract class GenerateProtocolFile { throw new UnknownException(); } + // 子协议优先生成 + public static List subProtocolFirst(List registrations) { + var registrations1 = new ArrayList(registrations); + var subFirstRegistrations = new ArrayList(); + var set = new HashSet(); + while (!registrations1.isEmpty()) { + for (var i = 0; i < registrations1.size(); i++) { + var registration = registrations1.get(i); + var protocolId = registration.protocolId(); + var subProtocols = ProtocolAnalysis.getAllSubProtocolIds(protocolId); + subProtocols.removeAll(set); + if (CollectionUtils.isEmpty(subProtocols)) { + subFirstRegistrations.add(registration); + set.add(protocolId); + registrations1.remove(registration); + break; + } + } + } + return subFirstRegistrations; + } + } diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java index 0dacd79c..d2050654 100644 --- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java +++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolNote.java @@ -120,11 +120,11 @@ public abstract class GenerateProtocolNote { return note; } - public static void initProtocolNote(List protocolRegistrations) { + public static void initProtocolNote(List protocolRegistrations) { AssertionUtils.notNull(protocolNoteMap, "[{}] duplicate initialization", GenerateProtocolNote.class.getSimpleName()); - for (var protocolRegistration : protocolRegistrations) { - var protocolClazz = protocolRegistration.protocolConstructor().getDeclaringClass(); + for (var registration : protocolRegistrations) { + var protocolClazz = registration.protocolConstructor().getDeclaringClass(); var classNote = StringUtils.EMPTY; var protocolClass = protocolClazz.getDeclaredAnnotation(Note.class); if (protocolClass != null && StringUtils.isNotEmpty(protocolClass.value())) { @@ -132,7 +132,6 @@ public abstract class GenerateProtocolNote { } var fieldNoteMap = new HashMap(); - var registration = (ProtocolRegistration) protocolRegistration; for (var field : registration.getFields()) { var noteDescription = field.getDeclaredAnnotation(Note.class); if (noteDescription == null || StringUtils.isEmpty(noteDescription.value())) { @@ -143,7 +142,7 @@ public abstract class GenerateProtocolNote { fieldNoteMap.put(fieldName, StringUtils.trim(fieldNote)); } - protocolNoteMap.put(protocolRegistration.protocolId(), new Pair<>(classNote, fieldNoteMap)); + protocolNoteMap.put(registration.protocolId(), new Pair<>(classNote, fieldNoteMap)); } } diff --git a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolPath.java b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolPath.java index 3ad54b67..d1b74a53 100644 --- a/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolPath.java +++ b/protocol/src/main/java/com/zfoo/protocol/generate/GenerateProtocolPath.java @@ -16,6 +16,7 @@ import com.zfoo.protocol.collection.CollectionUtils; import com.zfoo.protocol.collection.tree.GeneralTree; import com.zfoo.protocol.collection.tree.TreeNode; import com.zfoo.protocol.registration.IProtocolRegistration; +import com.zfoo.protocol.registration.ProtocolRegistration; import com.zfoo.protocol.serializer.CodeLanguage; import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer; import com.zfoo.protocol.util.AssertionUtils; @@ -153,9 +154,9 @@ public abstract class GenerateProtocolPath { * * @param protocolRegistrations 需要解析的路径 */ - public static void initProtocolPath(List protocolRegistrations) { + public static void initProtocolPath(List protocolRegistrations) { // 将需要生成的协议的路径添加到多叉树中 - var protocolPathTree = new GeneralTree(); + var protocolPathTree = new GeneralTree(); protocolRegistrations.forEach(it -> protocolPathTree.addNode(it.protocolConstructor().getDeclaringClass().getCanonicalName(), it)); var rootTreeNode = protocolPathTree.getRootNode(); @@ -187,7 +188,7 @@ public abstract class GenerateProtocolPath { } } - private static void toProtocolPath(TreeNode protocolTreeNode) { + private static void toProtocolPath(TreeNode protocolTreeNode) { var allChildren = protocolTreeNode.flatTreeNodes() .stream() .filter(it -> it.getData() != null) diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java index 1981bf5b..4be7a8df 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java @@ -25,11 +25,10 @@ import com.zfoo.protocol.generate.GenerateProtocolFile; import com.zfoo.protocol.generate.GenerateProtocolNote; import com.zfoo.protocol.generate.GenerateProtocolPath; import com.zfoo.protocol.registration.field.*; -import com.zfoo.protocol.serializer.cpp.GenerateCppUtils; +import com.zfoo.protocol.serializer.cpp.CodeGenerateCpp; import com.zfoo.protocol.serializer.gdscript.GenerateGdUtils; import com.zfoo.protocol.serializer.go.GenerateGoUtils; import com.zfoo.protocol.serializer.javascript.GenerateJsUtils; -import com.zfoo.protocol.serializer.lua.CodeGenerateLua; import com.zfoo.protocol.serializer.python.GeneratePyUtils; import com.zfoo.protocol.serializer.reflect.*; import com.zfoo.protocol.serializer.typescript.GenerateTsUtils; @@ -399,8 +398,6 @@ public class ProtocolAnalysis { GenerateProtocolNote.clear(); GenerateProtocolPath.clear(); - GenerateProtocolFile.clear(); - GenerateCppUtils.clear(); GenerateGoUtils.clear(); GenerateJsUtils.clear(); GenerateTsUtils.clear(); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java index 4951a743..7b8c53f3 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeLanguage.java @@ -12,6 +12,7 @@ package com.zfoo.protocol.serializer; +import com.zfoo.protocol.serializer.cpp.CodeGenerateCpp; import com.zfoo.protocol.serializer.csharp.CodeGenerateCsharp; import com.zfoo.protocol.serializer.lua.CodeGenerateLua; @@ -25,7 +26,7 @@ public enum CodeLanguage { */ Enhance(1, null), - Cpp(1 << 1, null), + Cpp(1 << 1, CodeGenerateCpp.class), Go(1 << 2, null), diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeTemplatePlaceholder.java b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeTemplatePlaceholder.java index 4fb13368..3526ccde 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/CodeTemplatePlaceholder.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/CodeTemplatePlaceholder.java @@ -24,6 +24,9 @@ import java.util.Map; */ public enum CodeTemplatePlaceholder { + protocol_root_path("${protocol_root_path}"), + protocol_imports("${protocol_imports}"), + protocol_class("${protocol_class}"), protocol_registration("${protocol_registration}"), @@ -74,7 +77,7 @@ public enum CodeTemplatePlaceholder { for (var codeTemplatePlaceholder : CodeTemplatePlaceholder.values()) { if (formatLine.contains(codeTemplatePlaceholder.placeholder)) { - formatLine = formatLine.replace(codeTemplatePlaceholder.placeholder, placeholderMap.get(codeTemplatePlaceholder)); + formatLine = formatLine.replace(codeTemplatePlaceholder.placeholder, placeholderMap.get(codeTemplatePlaceholder)); } } diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/ICodeGenerate.java b/protocol/src/main/java/com/zfoo/protocol/serializer/ICodeGenerate.java index 17321509..2b2de9db 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/ICodeGenerate.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/ICodeGenerate.java @@ -1,7 +1,7 @@ package com.zfoo.protocol.serializer; import com.zfoo.protocol.generate.GenerateOperation; -import com.zfoo.protocol.registration.IProtocolRegistration; +import com.zfoo.protocol.registration.ProtocolRegistration; import java.io.IOException; import java.util.List; @@ -30,16 +30,16 @@ public interface ICodeGenerate { /** * 将一个包下的协议文件生成在一个协议文件里 */ - void mergerProtocol(List registrations) throws IOException; + void mergerProtocol(List registrations) throws IOException; /** * 折叠协议,生成协议文件会和Java源文件保持相同的目录结构 */ - void foldProtocol(List registrations) throws IOException; + void foldProtocol(List registrations) throws IOException; /** * 默认把所有的协议文件放在同一个更目录下,不做任何操作 */ - void defaultProtocol(List registrations) throws IOException; + void defaultProtocol(List registrations) throws IOException; } diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CodeGenerateCpp.java b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CodeGenerateCpp.java new file mode 100644 index 00000000..13bdffa8 --- /dev/null +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CodeGenerateCpp.java @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.protocol.serializer.cpp; + +import com.zfoo.protocol.ProtocolManager; +import com.zfoo.protocol.anno.Compatible; +import com.zfoo.protocol.generate.GenerateOperation; +import com.zfoo.protocol.generate.GenerateProtocolFile; +import com.zfoo.protocol.generate.GenerateProtocolNote; +import com.zfoo.protocol.generate.GenerateProtocolPath; +import com.zfoo.protocol.registration.ProtocolAnalysis; +import com.zfoo.protocol.registration.ProtocolRegistration; +import com.zfoo.protocol.registration.field.IFieldRegistration; +import com.zfoo.protocol.serializer.CodeLanguage; +import com.zfoo.protocol.serializer.CodeTemplatePlaceholder; +import com.zfoo.protocol.serializer.ICodeGenerate; +import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer; +import com.zfoo.protocol.serializer.reflect.*; +import com.zfoo.protocol.util.ClassUtils; +import com.zfoo.protocol.util.FileUtils; +import com.zfoo.protocol.util.ReflectionUtils; +import com.zfoo.protocol.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.zfoo.protocol.util.FileUtils.LS; +import static com.zfoo.protocol.util.StringUtils.TAB; + +/** + * @author godotg + */ +public class CodeGenerateCpp implements ICodeGenerate { + private static final Logger logger = LoggerFactory.getLogger(CodeGenerateCpp.class); + + // custom configuration + public static String protocolOutputRootPath = "zfoocpp"; + private static String protocolOutputPath = StringUtils.EMPTY; + + private static final Map cppSerializerMap = new HashMap<>(); + + public static ICppSerializer cppSerializer(ISerializer serializer) { + return cppSerializerMap.get(serializer); + } + + @Override + public void init(GenerateOperation generateOperation) { + protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath); + FileUtils.deleteFile(new File(protocolOutputPath)); + + cppSerializerMap.put(BooleanSerializer.INSTANCE, new CppBooleanSerializer()); + cppSerializerMap.put(ByteSerializer.INSTANCE, new CppByteSerializer()); + cppSerializerMap.put(ShortSerializer.INSTANCE, new CppShortSerializer()); + cppSerializerMap.put(IntSerializer.INSTANCE, new CppIntSerializer()); + cppSerializerMap.put(LongSerializer.INSTANCE, new CppLongSerializer()); + cppSerializerMap.put(FloatSerializer.INSTANCE, new CppFloatSerializer()); + cppSerializerMap.put(DoubleSerializer.INSTANCE, new CppDoubleSerializer()); + cppSerializerMap.put(StringSerializer.INSTANCE, new CppStringSerializer()); + cppSerializerMap.put(ArraySerializer.INSTANCE, new CppArraySerializer()); + cppSerializerMap.put(ListSerializer.INSTANCE, new CppListSerializer()); + cppSerializerMap.put(SetSerializer.INSTANCE, new CppSetSerializer()); + cppSerializerMap.put(MapSerializer.INSTANCE, new CppMapSerializer()); + cppSerializerMap.put(ObjectProtocolSerializer.INSTANCE, new CppObjectProtocolSerializer()); + } + + @Override + public void mergerProtocol(List registrations) throws IOException { + createTemplateFile(registrations); + + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolManagerTemplate.h"); + var protocol_imports = new StringBuilder(); + var protocol_manager_registrations = new StringBuilder(); + protocol_imports.append(StringUtils.format("#include \"{}/Protocols.h\"", protocolOutputRootPath)).append(LS); + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = new {}Registration();", protocol_id, protocol_class_name)).append(LS); + } + var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_imports, protocol_imports.toString() + , CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString()); + var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap); + var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.h")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated C++ protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + + var protocol_class = new StringBuilder(); + var protocol_registration = new StringBuilder(); + for (var registration : GenerateProtocolFile.subProtocolFirst(registrations)) { + GenerateProtocolFile.index.set(0); + var protocol_id = registration.protocolId(); + + // protocol + protocol_class.append(protocol_class(registration)).append(LS); + + // registration + protocol_registration.append(protocol_registration(registration)).append(LS); + } + + var protocolTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolsTemplate.h"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_root_path, protocolOutputRootPath + ,CodeTemplatePlaceholder.protocol_class, protocol_class.toString() + , CodeTemplatePlaceholder.protocol_registration, protocol_registration.toString() + )); + var outputPath = StringUtils.format("{}/Protocols.h", protocolOutputPath); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated C++ protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + + @Override + public void foldProtocol(List registrations) throws IOException { + createTemplateFile(registrations); + + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolManagerTemplate.h"); + var protocol_imports = new StringBuilder(); + var protocol_manager_registrations = new StringBuilder(); + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocol_imports.append(StringUtils.format("#include \"{}/{}.h\"", protocolOutputRootPath, GenerateProtocolPath.protocolAbsolutePath(protocol_id, CodeLanguage.Cpp))).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = new {}Registration();", protocol_id, protocol_class_name)).append(LS); + } + var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_imports, protocol_imports.toString() + , CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString()); + var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap); + var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.h")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated C++ protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + + var protocolTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolTemplate.h"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_root_path, protocolOutputRootPath + ,CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_imports, protocol_imports_fold(registration) + , CodeTemplatePlaceholder.protocol_class, protocol_class(registration) + , CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration) + )); + + var outputPath = StringUtils.format("{}/{}/{}.h", protocolOutputPath, GenerateProtocolPath.protocolPath(protocol_id), protocol_name); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated C++ protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + } + + @Override + public void defaultProtocol(List registrations) throws IOException { + createTemplateFile(registrations); + + var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolManagerTemplate.h"); + var protocol_imports = new StringBuilder(); + var protocol_manager_registrations = new StringBuilder(); + for (var registration : registrations) { + var protocol_id = registration.protocolId(); + var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocol_imports.append(StringUtils.format("#include \"{}/{}.h\"", protocolOutputRootPath, protocol_class_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = new {}Registration();", protocol_id, protocol_class_name)).append(LS); + } + var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_imports, protocol_imports.toString() + , CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString()); + var formatProtocolManagerTemplate = CodeTemplatePlaceholder.formatTemplate(protocolManagerTemplate, placeholderMap); + var protocolManagerFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.h")); + FileUtils.writeStringToFile(protocolManagerFile, formatProtocolManagerTemplate, true); + logger.info("Generated C++ protocol manager file:[{}] is in path:[{}]", protocolManagerFile.getName(), protocolManagerFile.getAbsolutePath()); + + for (var registration : registrations) { + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + + var protocolTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolTemplate.h"); + var formatProtocolTemplate = CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( + CodeTemplatePlaceholder.protocol_root_path, protocolOutputRootPath + ,CodeTemplatePlaceholder.protocol_name, protocol_name + , CodeTemplatePlaceholder.protocol_imports, protocol_imports_default(registration) + , CodeTemplatePlaceholder.protocol_class, protocol_class(registration) + , CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration) + )); + + var outputPath = StringUtils.format("{}/{}.h", protocolOutputPath, protocol_name); + var file = new File(outputPath); + FileUtils.writeStringToFile(file, formatProtocolTemplate, true); + logger.info("Generated C++ protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + } + } + + + public void createTemplateFile(List registrations) throws IOException { + var list = List.of("cpp/ByteBuffer.h"); + + for (var fileName : list) { + var fileInputStream = ClassUtils.getFileFromClassPath(fileName); + var createFile = new File(StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "cpp/"))); + FileUtils.writeInputStreamToFile(createFile, fileInputStream); + } + } + + private String protocol_class(ProtocolRegistration registration) { + var protocol_id = registration.protocolId(); + var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + + var protocolClassTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolClassTemplate.h"); + var placeholderMap = Map.of( + CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Cpp) + , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) + , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) + ); + return CodeTemplatePlaceholder.formatTemplate(protocolClassTemplate, placeholderMap); + } + + private String protocol_registration(ProtocolRegistration registration) { + var protocol_id = registration.protocolId(); + var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + + var protocolRegistrationTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolRegistrationTemplate.h"); + var placeholderMap = Map.of( + CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Cpp) + , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) + , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) + , CodeTemplatePlaceholder.protocol_read_deserialization, protocol_read_deserialization(registration) + ); + return CodeTemplatePlaceholder.formatTemplate(protocolRegistrationTemplate, placeholderMap); + } + + + private String protocol_imports_fold(ProtocolRegistration registration) { + var protocolId = registration.getId(); + var subProtocols = ProtocolAnalysis.getAllSubProtocolIds(protocolId); + var cppBuilder = new StringBuilder(); + for (var subProtocolId : subProtocols) { + var protocolClassName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId); + var subProtocolPath = StringUtils.format("#include \"{}/{}/{}.h\"", protocolOutputRootPath, GenerateProtocolPath.getCapitalizeProtocolPath(subProtocolId), protocolClassName); + cppBuilder.append(subProtocolPath).append(LS); + } + return cppBuilder.toString(); + } + + private String protocol_imports_default(ProtocolRegistration registration) { + var protocolId = registration.getId(); + var subProtocols = ProtocolAnalysis.getAllSubProtocolIds(protocolId); + var cppBuilder = new StringBuilder(); + for (var subProtocolId : subProtocols) { + var protocolClassName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId); + var subProtocolPath = StringUtils.format("#include \"{}/{}.h\"", protocolOutputRootPath, protocolClassName); + cppBuilder.append(subProtocolPath).append(LS); + } + return cppBuilder.toString(); + } + + private String protocol_field_definition(ProtocolRegistration registration) { + var protocolId = registration.getId(); + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + + var cppBuilder = new StringBuilder(); + var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass()); + for (int i = 0; i < sequencedFields.size(); i++) { + var field = sequencedFields.get(i); + IFieldRegistration fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)]; + var fieldName = field.getName(); + var propertyTypeAndName = cppSerializer(fieldRegistration.serializer()).field(field, fieldRegistration); + var propertyType = propertyTypeAndName.getKey(); + var propertyName = propertyTypeAndName.getValue(); + + var propertyFullName = StringUtils.format("{} {};", propertyType, propertyName); + // 生成注释 + var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Cpp); + for (var fieldNote : fieldNotes) { + cppBuilder.append(fieldNote).append(LS); + } + cppBuilder.append(propertyFullName).append(LS); + } + + return cppBuilder.toString().trim(); + } + + private String protocol_write_serialization(ProtocolRegistration registration) { + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + var cppBuilder = new StringBuilder(); + if (registration.isCompatible()) { + cppBuilder.append("auto beforeWriteIndex = buffer.writerIndex();").append(LS); + cppBuilder.append(StringUtils.format("buffer.writeInt({});", registration.getPredictionLength())).append(LS); + } else { + cppBuilder.append("buffer.writeInt(-1);").append(LS); + } + for (int i = 0; i < fields.length; i++) { + var field = fields[i]; + var fieldRegistration = fieldRegistrations[i]; + var serializer = cppSerializer(fieldRegistration.serializer()); + if (ProtocolManager.isProtocolClass(field.getType())) { + serializer.writeObject(cppBuilder, "&message->" + field.getName(), 0, field, fieldRegistration); + } else { + serializer.writeObject(cppBuilder, "message->" + field.getName(), 0, field, fieldRegistration); + } + } + if (registration.isCompatible()) { + cppBuilder.append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex);", registration.getPredictionLength())).append(LS); + } + return cppBuilder.toString(); + } + + + private String protocol_read_deserialization(ProtocolRegistration registration) { + var fields = registration.getFields(); + var fieldRegistrations = registration.getFieldRegistrations(); + + var cppBuilder = new StringBuilder(); + for (int i = 0; i < fields.length; i++) { + var field = fields[i]; + var fieldRegistration = fieldRegistrations[i]; + + if (field.isAnnotationPresent(Compatible.class)) { + cppBuilder.append("if (buffer.compatibleRead(beforeReadIndex, length)) {").append(LS); + var compatibleReadObject = cppSerializer(fieldRegistration.serializer()).readObject(cppBuilder, 1, field, fieldRegistration); + cppBuilder.append(TAB); + if (ProtocolManager.isProtocolClass(field.getType())) { + cppBuilder.append(StringUtils.format("packet->{} = *{};", field.getName(), compatibleReadObject)); + } else { + cppBuilder.append(StringUtils.format("packet->{} = {};", field.getName(), compatibleReadObject)); + } + cppBuilder.append(LS).append("}").append(LS); + continue; + } + + var readObject = cppSerializer(fieldRegistration.serializer()).readObject(cppBuilder, 0, field, fieldRegistration); + if (ProtocolManager.isProtocolClass(field.getType())) { + cppBuilder.append(StringUtils.format("packet->{} = *{};", field.getName(), readObject)); + } else { + cppBuilder.append(StringUtils.format("packet->{} = {};", field.getName(), readObject)); + } + + cppBuilder.append(LS); + } + return cppBuilder.toString(); + } + + public static String toCppClassName(String typeName) { + typeName = typeName.replaceAll("java.util.|java.lang.", StringUtils.EMPTY); + typeName = typeName.replaceAll("[a-zA-Z0-9_.]*\\.", StringUtils.EMPTY); + + // CSharp不适用基础类型的泛型,会影响性能 + switch (typeName) { + case "boolean": + case "Boolean": + typeName = "bool"; + return typeName; + case "byte": + case "Byte": + typeName = "int8_t"; + return typeName; + case "short": + case "Short": + typeName = "int16_t"; + return typeName; + case "int": + case "Integer": + typeName = "int32_t"; + return typeName; + case "long": + case "Long": + typeName = "int64_t"; + return typeName; + case "Float": + typeName = "float"; + return typeName; + case "Double": + typeName = "double"; + return typeName; + case "Character": + typeName = "char"; + return typeName; + case "String": + typeName = "string"; + return typeName; + default: + } + + // 将boolean转为bool + typeName = typeName.replaceAll("[B|b]oolean\\[", "bool"); + typeName = typeName.replace("", "bool>"); + + // 将Byte转为byte + typeName = typeName.replace("Byte[", "int8_t"); + typeName = typeName.replace("Byte>", "int8_t>"); + typeName = typeName.replace("", "int16_t>"); + typeName = typeName.replace("", "int32_t>"); + typeName = typeName.replace("", "int64_t>"); + typeName = typeName.replace("", "float>"); + typeName = typeName.replace("", "double>"); + typeName = typeName.replace("", "char>"); + typeName = typeName.replace("", "string>"); + typeName = typeName.replace(" field(Field field, IFieldRegistration fieldRegistration) { - var type = GenerateCppUtils.toCppClassName(field.getType().getComponentType().getSimpleName()); + var type = CodeGenerateCpp.toCppClassName(field.getType().getComponentType().getSimpleName()); return new Pair<>(StringUtils.format("vector<{}>", type), field.getName()); } @@ -56,9 +56,9 @@ public class CppArraySerializer implements ICppSerializer { builder.append(StringUtils.format("for (auto {} = 0; {} < {}; {}++) {", i, i, length, i)).append(LS); GenerateProtocolFile.addTab(builder, deep + 1); String element = "element" + GenerateProtocolFile.index.getAndIncrement(); - builder.append(StringUtils.format("{} {} = {}[{}];", GenerateCppUtils.toCppClassName(arrayField.getType().getSimpleName()), element, objectStr, i)).append(LS); + builder.append(StringUtils.format("{} {} = {}[{}];", CodeGenerateCpp.toCppClassName(arrayField.getType().getSimpleName()), element, objectStr, i)).append(LS); - GenerateCppUtils.cppSerializer(arrayField.getArrayElementRegistration().serializer()) + CodeGenerateCpp.cppSerializer(arrayField.getArrayElementRegistration().serializer()) .writeObject(builder, element, deep + 1, field, arrayField.getArrayElementRegistration()); GenerateProtocolFile.addTab(builder, deep); @@ -77,7 +77,7 @@ public class CppArraySerializer implements ICppSerializer { var arrayField = (ArrayField) fieldRegistration; var result = "result" + GenerateProtocolFile.index.getAndIncrement(); - var typeName = GenerateCppUtils.toCppClassName(arrayField.getType().getSimpleName()); + var typeName = CodeGenerateCpp.toCppClassName(arrayField.getType().getSimpleName()); var i = "index" + GenerateProtocolFile.index.getAndIncrement(); var size = "size" + GenerateProtocolFile.index.getAndIncrement(); @@ -88,7 +88,7 @@ public class CppArraySerializer implements ICppSerializer { GenerateProtocolFile.addTab(builder, deep); builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); - var readObject = GenerateCppUtils.cppSerializer(arrayField.getArrayElementRegistration().serializer()) + var readObject = CodeGenerateCpp.cppSerializer(arrayField.getArrayElementRegistration().serializer()) .readObject(builder, deep + 2, field, arrayField.getArrayElementRegistration()); var point = StringUtils.EMPTY; diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppListSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppListSerializer.java index f6e81bbb..d8d0e6c6 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppListSerializer.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppListSerializer.java @@ -33,7 +33,7 @@ public class CppListSerializer implements ICppSerializer { @Override public Pair field(Field field, IFieldRegistration fieldRegistration) { - var type = GenerateCppUtils.toCppClassName(field.getGenericType().toString()); + var type = CodeGenerateCpp.toCppClassName(field.getGenericType().toString()); return new Pair<>(type, field.getName()); } @@ -53,7 +53,7 @@ public class CppListSerializer implements ICppSerializer { String i = "i" + GenerateProtocolFile.index.getAndIncrement(); builder.append(StringUtils.format("for (auto {} : {}) {", i, objectStr)).append(LS); - GenerateCppUtils.cppSerializer(listField.getListElementRegistration().serializer()) + CodeGenerateCpp.cppSerializer(listField.getListElementRegistration().serializer()) .writeObject(builder, i, deep + 1, field, listField.getListElementRegistration()); GenerateProtocolFile.addTab(builder, deep); @@ -71,7 +71,7 @@ public class CppListSerializer implements ICppSerializer { var listField = (ListField) fieldRegistration; var result = "result" + GenerateProtocolFile.index.getAndIncrement(); - var typeName = GenerateCppUtils.toCppClassName(listField.getType().toString()); + var typeName = CodeGenerateCpp.toCppClassName(listField.getType().toString()); var i = "index" + GenerateProtocolFile.index.getAndIncrement(); var size = "size" + GenerateProtocolFile.index.getAndIncrement(); @@ -83,7 +83,7 @@ public class CppListSerializer implements ICppSerializer { GenerateProtocolFile.addTab(builder, deep); builder.append(StringUtils.format("for (int {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); - var readObject = GenerateCppUtils.cppSerializer(listField.getListElementRegistration().serializer()) + var readObject = CodeGenerateCpp.cppSerializer(listField.getListElementRegistration().serializer()) .readObject(builder, deep + 1, field, listField.getListElementRegistration()); var point = StringUtils.EMPTY; diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppMapSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppMapSerializer.java index 5d5a9170..a697560f 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppMapSerializer.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppMapSerializer.java @@ -33,7 +33,7 @@ public class CppMapSerializer implements ICppSerializer { @Override public Pair field(Field field, IFieldRegistration fieldRegistration) { - var type = GenerateCppUtils.toCppClassName(field.getGenericType().toString()); + var type = CodeGenerateCpp.toCppClassName(field.getGenericType().toString()); return new Pair<>(type, field.getName()); } @@ -55,9 +55,9 @@ public class CppMapSerializer implements ICppSerializer { var mapKeyRegistration = mapField.getMapKeyRegistration(); var mapValueRegistration = mapField.getMapValueRegistration(); - GenerateCppUtils.cppSerializer(mapField.getMapKeyRegistration().serializer()) + CodeGenerateCpp.cppSerializer(mapField.getMapKeyRegistration().serializer()) .writeObject(builder, key, deep + 1, field, mapField.getMapKeyRegistration()); - GenerateCppUtils.cppSerializer(mapField.getMapValueRegistration().serializer()) + CodeGenerateCpp.cppSerializer(mapField.getMapValueRegistration().serializer()) .writeObject(builder, value, deep + 1, field, mapField.getMapValueRegistration()); GenerateProtocolFile.addTab(builder, deep); builder.append("}").append(LS); @@ -75,7 +75,7 @@ public class CppMapSerializer implements ICppSerializer { MapField mapField = (MapField) fieldRegistration; String result = "result" + GenerateProtocolFile.index.getAndIncrement(); - var typeName = GenerateCppUtils.toCppClassName(mapField.getType().toString()); + var typeName = CodeGenerateCpp.toCppClassName(mapField.getType().toString()); String size = "size" + GenerateProtocolFile.index.getAndIncrement(); builder.append(StringUtils.format("int32_t {} = buffer.readInt();", size)).append(LS); @@ -88,10 +88,10 @@ public class CppMapSerializer implements ICppSerializer { GenerateProtocolFile.addTab(builder, deep); builder.append(StringUtils.format("for (auto {} = 0; {} < {}; {}++) {", i, i, size, i)).append(LS); - String keyObject = GenerateCppUtils.cppSerializer(mapField.getMapKeyRegistration().serializer()) + String keyObject = CodeGenerateCpp.cppSerializer(mapField.getMapKeyRegistration().serializer()) .readObject(builder, deep + 1, field, mapField.getMapKeyRegistration()); - String valueObject = GenerateCppUtils.cppSerializer(mapField.getMapValueRegistration().serializer()) + String valueObject = CodeGenerateCpp.cppSerializer(mapField.getMapValueRegistration().serializer()) .readObject(builder, deep + 1, field, mapField.getMapValueRegistration()); GenerateProtocolFile.addTab(builder, deep + 1); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppSetSerializer.java b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppSetSerializer.java index 1f0a75f4..1507ca9c 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppSetSerializer.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/CppSetSerializer.java @@ -33,7 +33,7 @@ public class CppSetSerializer implements ICppSerializer { @Override public Pair field(Field field, IFieldRegistration fieldRegistration) { - var type = GenerateCppUtils.toCppClassName(field.getGenericType().toString()); + var type = CodeGenerateCpp.toCppClassName(field.getGenericType().toString()); return new Pair<>(type, field.getName()); } @@ -52,7 +52,7 @@ public class CppSetSerializer implements ICppSerializer { GenerateProtocolFile.addTab(builder, deep); builder.append(StringUtils.format("for (auto {} : {}) {", element, objectStr)).append(LS); - GenerateCppUtils.cppSerializer(setField.getSetElementRegistration().serializer()) + CodeGenerateCpp.cppSerializer(setField.getSetElementRegistration().serializer()) .writeObject(builder, element, deep + 1, field, setField.getSetElementRegistration()); GenerateProtocolFile.addTab(builder, deep); @@ -70,7 +70,7 @@ public class CppSetSerializer implements ICppSerializer { SetField setField = (SetField) fieldRegistration; var result = "result" + GenerateProtocolFile.index.getAndIncrement(); - var typeName = GenerateCppUtils.toCppClassName(setField.getType().toString()); + var typeName = CodeGenerateCpp.toCppClassName(setField.getType().toString()); var i = "index" + GenerateProtocolFile.index.getAndIncrement(); var size = "size" + GenerateProtocolFile.index.getAndIncrement(); @@ -89,7 +89,7 @@ public class CppSetSerializer implements ICppSerializer { point = "*"; } - var readObject = GenerateCppUtils.cppSerializer(setField.getSetElementRegistration().serializer()) + var readObject = CodeGenerateCpp.cppSerializer(setField.getSetElementRegistration().serializer()) .readObject(builder, deep + 1, field, setField.getSetElementRegistration()); GenerateProtocolFile.addTab(builder, deep + 1); builder.append(StringUtils.format("{}.emplace({}{});", result, point, readObject)).append(LS); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/GenerateCppUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/GenerateCppUtils.java deleted file mode 100644 index e3d1543d..00000000 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/cpp/GenerateCppUtils.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (C) 2020 The zfoo Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and limitations under the License. - */ - -package com.zfoo.protocol.serializer.cpp; - -import com.zfoo.protocol.ProtocolManager; -import com.zfoo.protocol.anno.Compatible; -import com.zfoo.protocol.collection.CollectionUtils; -import com.zfoo.protocol.generate.GenerateOperation; -import com.zfoo.protocol.generate.GenerateProtocolFile; -import com.zfoo.protocol.generate.GenerateProtocolNote; -import com.zfoo.protocol.generate.GenerateProtocolPath; -import com.zfoo.protocol.model.Pair; -import com.zfoo.protocol.registration.IProtocolRegistration; -import com.zfoo.protocol.registration.ProtocolAnalysis; -import com.zfoo.protocol.registration.ProtocolRegistration; -import com.zfoo.protocol.registration.field.IFieldRegistration; -import com.zfoo.protocol.serializer.CodeLanguage; -import com.zfoo.protocol.serializer.enhance.EnhanceObjectProtocolSerializer; -import com.zfoo.protocol.serializer.reflect.*; -import com.zfoo.protocol.util.ClassUtils; -import com.zfoo.protocol.util.FileUtils; -import com.zfoo.protocol.util.ReflectionUtils; -import com.zfoo.protocol.util.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.zfoo.protocol.util.FileUtils.LS; -import static com.zfoo.protocol.util.StringUtils.TAB; - -/** - * @author godotg - */ -public abstract class GenerateCppUtils { - private static final Logger logger = LoggerFactory.getLogger(GenerateCppUtils.class); - - // custom configuration - public static String protocolOutputRootPath = "zfoocpp"; - private static String protocolOutputPath = StringUtils.EMPTY; - - private static Map cppSerializerMap; - - public static ICppSerializer cppSerializer(ISerializer serializer) { - return cppSerializerMap.get(serializer); - } - - public static void init(GenerateOperation generateOperation) { - protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath); - FileUtils.deleteFile(new File(protocolOutputPath)); - - cppSerializerMap = new HashMap<>(); - cppSerializerMap.put(BooleanSerializer.INSTANCE, new CppBooleanSerializer()); - cppSerializerMap.put(ByteSerializer.INSTANCE, new CppByteSerializer()); - cppSerializerMap.put(ShortSerializer.INSTANCE, new CppShortSerializer()); - cppSerializerMap.put(IntSerializer.INSTANCE, new CppIntSerializer()); - cppSerializerMap.put(LongSerializer.INSTANCE, new CppLongSerializer()); - cppSerializerMap.put(FloatSerializer.INSTANCE, new CppFloatSerializer()); - cppSerializerMap.put(DoubleSerializer.INSTANCE, new CppDoubleSerializer()); - cppSerializerMap.put(StringSerializer.INSTANCE, new CppStringSerializer()); - cppSerializerMap.put(ArraySerializer.INSTANCE, new CppArraySerializer()); - cppSerializerMap.put(ListSerializer.INSTANCE, new CppListSerializer()); - cppSerializerMap.put(SetSerializer.INSTANCE, new CppSetSerializer()); - cppSerializerMap.put(MapSerializer.INSTANCE, new CppMapSerializer()); - cppSerializerMap.put(ObjectProtocolSerializer.INSTANCE, new CppObjectProtocolSerializer()); - } - - public static void clear() { - cppSerializerMap = null; - protocolOutputRootPath = null; - protocolOutputPath = null; - } - - /** - * 生成协议依赖的工具类 - */ - public static void createProtocolManager(List protocolList) throws IOException { - var list = List.of("cpp/ByteBuffer.h"); - - for (var fileName : list) { - var fileInputStream = ClassUtils.getFileFromClassPath(fileName); - var createFile = new File(StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "cpp/"))); - FileUtils.writeInputStreamToFile(createFile, fileInputStream); - } - - var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolManagerTemplate.h"); - - var headerBuilder = new StringBuilder(); - var initProtocolBuilder = new StringBuilder(); - for (var protocol : protocolList) { - var protocolId = protocol.protocolId(); - headerBuilder.append(StringUtils.format("#include \"{}/{}.h\"", protocolOutputRootPath, GenerateProtocolPath.protocolAbsolutePath(protocolId, CodeLanguage.Cpp))).append(LS); - initProtocolBuilder.append(TAB).append(TAB).append(StringUtils.format("protocols[{}] = new {}Registration();", protocolId, protocol.protocolConstructor().getDeclaringClass().getSimpleName())).append(LS); - } - protocolManagerTemplate = StringUtils.format(protocolManagerTemplate, headerBuilder.toString(), initProtocolBuilder.toString().trim()); - var file = new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.h")); - FileUtils.writeStringToFile(file, protocolManagerTemplate, true); - logger.info("Generated C++ protocol manager file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); - } - - /** - * 生成协议类 - */ - public static void createCppProtocolFile(ProtocolRegistration registration) throws IOException { - GenerateProtocolFile.index.set(0); - - var protocolId = registration.protocolId(); - var registrationConstructor = registration.getConstructor(); - - var protocolClazzName = registrationConstructor.getDeclaringClass().getSimpleName(); - var protocolTemplate = ClassUtils.getFileFromClassPathToString("cpp/ProtocolTemplate.h"); - - // protocol object - var defineProtocolName = protocolClazzName.toUpperCase(); - var includeHeaders = includeSubProtocol(registration); - var classNote = GenerateProtocolNote.classNote(protocolId, CodeLanguage.Cpp, TAB, 1); - var fieldDefinition = fieldDefinition(registration); - var valueOfMethod = valueOfMethod(registration); - var operator = operator(registration); - var writeObject = writeObject(registration); - var readObject = readObject(registration); - - protocolTemplate = StringUtils.format(protocolTemplate, defineProtocolName, defineProtocolName, protocolOutputRootPath, includeHeaders, classNote - , protocolClazzName, fieldDefinition, protocolClazzName, protocolClazzName, valueOfMethod.getKey(), protocolClazzName - , valueOfMethod.getValue().trim(), protocolId, protocolClazzName, operator.trim(), - protocolClazzName, protocolId, protocolClazzName, writeObject.trim(), protocolClazzName, readObject.trim()); - - var outputPath = StringUtils.format("{}/{}/{}.h" - , protocolOutputPath - , GenerateProtocolPath.getProtocolPath(protocolId) - , protocolClazzName); - var file = new File(outputPath); - FileUtils.writeStringToFile(file, protocolTemplate, true); - logger.info("Generated C++ protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); - } - - - private static String includeSubProtocol(ProtocolRegistration registration) { - var protocolId = registration.getId(); - var subProtocols = ProtocolAnalysis.getAllSubProtocolIds(protocolId); - - if (CollectionUtils.isEmpty(subProtocols)) { - return StringUtils.EMPTY; - } - var cppBuilder = new StringBuilder(); - for (var subProtocolId : subProtocols) { - var protocolClassName = EnhanceObjectProtocolSerializer.getProtocolClassSimpleName(subProtocolId); - var subProtocolPath = StringUtils.format("#include \"{}/{}/{}.h\"" - , protocolOutputRootPath - , GenerateProtocolPath.getCapitalizeProtocolPath(protocolId) - , protocolClassName); - subProtocolPath = subProtocolPath.replaceAll("//", StringUtils.SLASH); - cppBuilder.append(subProtocolPath).append(LS); - } - - return cppBuilder.toString(); - } - - private static String fieldDefinition(ProtocolRegistration registration) { - var protocolId = registration.getId(); - var fields = registration.getFields(); - var fieldRegistrations = registration.getFieldRegistrations(); - - var cppBuilder = new StringBuilder(); - var sequencedFields = ReflectionUtils.notStaticAndTransientFields(registration.getConstructor().getDeclaringClass()); - for (int i = 0; i < sequencedFields.size(); i++) { - var field = sequencedFields.get(i); - IFieldRegistration fieldRegistration = fieldRegistrations[GenerateProtocolFile.indexOf(fields, field)]; - var fieldName = field.getName(); - var propertyTypeAndName = cppSerializer(fieldRegistration.serializer()).field(field, fieldRegistration); - var propertyType = propertyTypeAndName.getKey(); - var propertyName = propertyTypeAndName.getValue(); - - var propertyFullName = StringUtils.format("{} {};", propertyType, propertyName); - // 生成注释 - var fieldNotes = GenerateProtocolNote.fieldNotes(protocolId, fieldName, CodeLanguage.Cpp); - for(var fieldNote : fieldNotes) { - cppBuilder.append(TAB + TAB).append(fieldNote).append(LS); - } - cppBuilder.append(TAB + TAB).append(propertyFullName).append(LS); - } - - return cppBuilder.toString().trim(); - } - - private static Pair valueOfMethod(ProtocolRegistration registration) { - var fields = registration.getFields(); - var fieldRegistrations = registration.getFieldRegistrations(); - - var filedList = new ArrayList>(); - for (int i = 0; i < fields.length; i++) { - var field = fields[i]; - var fieldRegistration = fieldRegistrations[i]; - var propertyTypeAndName = cppSerializer(fieldRegistration.serializer()).field(field, fieldRegistration); - filedList.add(propertyTypeAndName); - } - - // ValueOf()方法 - var valueOfParams = filedList.stream() - .map(it -> StringUtils.format("{} {}", it.getKey(), it.getValue())) - .toList(); - var valueOfParamsStr = StringUtils.joinWith(StringUtils.COMMA + " ", valueOfParams.toArray()); - - var cppBuilder = new StringBuilder(); - filedList.forEach(it -> cppBuilder.append(TAB + TAB + TAB).append(StringUtils.format("packet.{} = {};", it.getValue(), it.getValue())).append(LS)); - return new Pair<>(valueOfParamsStr, cppBuilder.toString()); - } - - private static String operator(ProtocolRegistration registration) { - var protocolId = registration.getId(); - var fields = registration.getFields(); - var fieldRegistrations = registration.getFieldRegistrations(); - - var filedList = new ArrayList>(); - for (int i = 0; i < fields.length; i++) { - var field = fields[i]; - var fieldRegistration = fieldRegistrations[i]; - var propertyTypeAndName = cppSerializer(fieldRegistration.serializer()).field(field, fieldRegistration); - filedList.add(propertyTypeAndName); - } - - // bool operator< - var cppBuilder = new StringBuilder(); - for (var fieldPair : filedList) { - cppBuilder.append(TAB + TAB + TAB).append(StringUtils.format("if ({} < _.{}) { return true; }", fieldPair.getValue(), fieldPair.getValue())).append(LS); - cppBuilder.append(TAB + TAB + TAB).append(StringUtils.format("if (_.{} < {}) { return false; }", fieldPair.getValue(), fieldPair.getValue())).append(LS); - } - return cppBuilder.toString(); - } - - private static String writeObject(ProtocolRegistration registration) { - var fields = registration.getFields(); - var fieldRegistrations = registration.getFieldRegistrations(); - var cppBuilder = new StringBuilder(); - if (registration.isCompatible()) { - cppBuilder.append(TAB + TAB + TAB).append("auto beforeWriteIndex = buffer.writerIndex();").append(LS); - cppBuilder.append(TAB + TAB + TAB).append(StringUtils.format("buffer.writeInt({});", registration.getPredictionLength())).append(LS); - } else { - cppBuilder.append(TAB + TAB + TAB).append("buffer.writeInt(-1);").append(LS); - } - for (int i = 0; i < fields.length; i++) { - var field = fields[i]; - var fieldRegistration = fieldRegistrations[i]; - var serializer = cppSerializer(fieldRegistration.serializer()); - if (ProtocolManager.isProtocolClass(field.getType())) { - serializer.writeObject(cppBuilder, "&message->" + field.getName(), 3, field, fieldRegistration); - } else { - serializer.writeObject(cppBuilder, "message->" + field.getName(), 3, field, fieldRegistration); - } - } - if (registration.isCompatible()) { - cppBuilder.append(TAB + TAB + TAB).append(StringUtils.format("buffer.adjustPadding({}, beforeWriteIndex);", registration.getPredictionLength())).append(LS); - } - return cppBuilder.toString(); - } - - - private static String readObject(ProtocolRegistration registration) { - var fields = registration.getFields(); - var fieldRegistrations = registration.getFieldRegistrations(); - - var cppBuilder = new StringBuilder(); - for (int i = 0; i < fields.length; i++) { - var field = fields[i]; - var fieldRegistration = fieldRegistrations[i]; - - if (field.isAnnotationPresent(Compatible.class)) { - cppBuilder.append(TAB + TAB + TAB).append("if (buffer.compatibleRead(beforeReadIndex, length)) {").append(LS); - var compatibleReadObject = cppSerializer(fieldRegistration.serializer()).readObject(cppBuilder, 4, field, fieldRegistration); - cppBuilder.append(TAB + TAB + TAB + TAB); - if (ProtocolManager.isProtocolClass(field.getType())) { - cppBuilder.append(StringUtils.format("packet->{} = *{};", field.getName(), compatibleReadObject)); - } else { - cppBuilder.append(StringUtils.format("packet->{} = {};", field.getName(), compatibleReadObject)); - } - cppBuilder.append(LS).append(TAB + TAB + TAB).append("}").append(LS); - continue; - } - - var readObject = cppSerializer(fieldRegistration.serializer()).readObject(cppBuilder, 3, field, fieldRegistration); - cppBuilder.append(TAB + TAB + TAB); - if (ProtocolManager.isProtocolClass(field.getType())) { - cppBuilder.append(StringUtils.format("packet->{} = *{};", field.getName(), readObject)); - } else { - cppBuilder.append(StringUtils.format("packet->{} = {};", field.getName(), readObject)); - } - - cppBuilder.append(LS); - } - return cppBuilder.toString(); - } - - public static String toCppClassName(String typeName) { - typeName = typeName.replaceAll("java.util.|java.lang.", StringUtils.EMPTY); - typeName = typeName.replaceAll("[a-zA-Z0-9_.]*\\.", StringUtils.EMPTY); - - // CSharp不适用基础类型的泛型,会影响性能 - switch (typeName) { - case "boolean": - case "Boolean": - typeName = "bool"; - return typeName; - case "byte": - case "Byte": - typeName = "int8_t"; - return typeName; - case "short": - case "Short": - typeName = "int16_t"; - return typeName; - case "int": - case "Integer": - typeName = "int32_t"; - return typeName; - case "long": - case "Long": - typeName = "int64_t"; - return typeName; - case "Float": - typeName = "float"; - return typeName; - case "Double": - typeName = "double"; - return typeName; - case "Character": - typeName = "char"; - return typeName; - case "String": - typeName = "string"; - return typeName; - default: - } - - // 将boolean转为bool - typeName = typeName.replaceAll("[B|b]oolean\\[", "bool"); - typeName = typeName.replace("", "bool>"); - - // 将Byte转为byte - typeName = typeName.replace("Byte[", "int8_t"); - typeName = typeName.replace("Byte>", "int8_t>"); - typeName = typeName.replace("", "int16_t>"); - typeName = typeName.replace("", "int32_t>"); - typeName = typeName.replace("", "int64_t>"); - typeName = typeName.replace("", "float>"); - typeName = typeName.replace("", "double>"); - typeName = typeName.replace("", "char>"); - typeName = typeName.replace("", "string>"); - typeName = typeName.replace(" registrations) throws IOException { + public void mergerProtocol(List registrations) throws IOException { createProtocolManagerFile(registrations); var mergerProtocolPathMap = GenerateProtocolPath.mergerProtocolPathMap(); for (var entry : mergerProtocolPathMap.entrySet()) { @@ -112,13 +112,13 @@ public class CodeGenerateCsharp implements ICodeGenerate { } @Override - public void foldProtocol(List registrations) throws IOException { + public void foldProtocol(List registrations) throws IOException { createProtocolManagerFile(registrations); for (var registration : registrations) { var protocolId = registration.protocolId(); var protocolClazzName = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - var formatProtocolTemplate = formatProtocolTemplate((ProtocolRegistration) registration); + var formatProtocolTemplate = formatProtocolTemplate(registration); var outputPath = StringUtils.format("{}/{}/{}.cs", protocolOutputPath, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId), protocolClazzName); var file = new File(outputPath); FileUtils.writeStringToFile(file, formatProtocolTemplate, true); @@ -127,20 +127,20 @@ public class CodeGenerateCsharp implements ICodeGenerate { } @Override - public void defaultProtocol(List registrations) throws IOException { + public void defaultProtocol(List registrations) throws IOException { createProtocolManagerFile(registrations); for (var registration : registrations) { - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - var formatProtocolTemplate = formatProtocolTemplate((ProtocolRegistration) registration); - var outputPath = StringUtils.format("{}/{}.cs", protocolOutputPath, protocol_class_name); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var formatProtocolTemplate = formatProtocolTemplate(registration); + var outputPath = StringUtils.format("{}/{}.cs", protocolOutputPath, protocol_name); var file = new File(outputPath); FileUtils.writeStringToFile(file, formatProtocolTemplate, true); logger.info("Generated C# protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); } } - private void createProtocolManagerFile(List registrations) throws IOException { + private void createProtocolManagerFile(List registrations) throws IOException { var list = List.of("csharp/IProtocolRegistration.cs" , "csharp/Buffer/ByteBuffer.cs" , "csharp/Buffer/LittleEndianByteBuffer.cs" @@ -174,12 +174,12 @@ public class CodeGenerateCsharp implements ICodeGenerate { private String protocol_class(ProtocolRegistration registration) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.getConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.getConstructor().getDeclaringClass().getSimpleName(); var protocolClassTemplate = ClassUtils.getFileFromClassPathToString("csharp/ProtocolClassTemplate.cs"); var placeholderMap = Map.of( CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.CSharp) - , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_name, protocol_name , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) @@ -190,12 +190,12 @@ public class CodeGenerateCsharp implements ICodeGenerate { private String protocol_registration(ProtocolRegistration registration) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.getConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.getConstructor().getDeclaringClass().getSimpleName(); var protocolRegistrationTemplate = ClassUtils.getFileFromClassPathToString("csharp/ProtocolRegistrationTemplate.cs"); var placeholderMap = Map.of( CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.CSharp) - , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_name, protocol_name , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) @@ -204,7 +204,7 @@ public class CodeGenerateCsharp implements ICodeGenerate { return CodeTemplatePlaceholder.formatTemplate(protocolRegistrationTemplate, placeholderMap); } - private String protocol_manager_registrations(List protocolList) { + private String protocol_manager_registrations(List protocolList) { var csBuilder = new StringBuilder(); for (var protocol : protocolList) { var protocolId = protocol.protocolId(); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/es/GenerateEsUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/es/GenerateEsUtils.java index 52e14e2b..ea9c805d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/es/GenerateEsUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/es/GenerateEsUtils.java @@ -80,7 +80,7 @@ public abstract class GenerateEsUtils { esSerializerMap = null; } - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var list = List.of("es/buffer/ByteBuffer.mjs", "es/buffer/long.mjs", "es/buffer/longbits.mjs"); for (var fileName : list) { var fileInputStream = ClassUtils.getFileFromClassPath(fileName); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/gdscript/GenerateGdUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/gdscript/GenerateGdUtils.java index 23b7983d..729cf75f 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/gdscript/GenerateGdUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/gdscript/GenerateGdUtils.java @@ -86,7 +86,7 @@ public abstract class GenerateGdUtils { protocolOutputPath = null; } - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var byteBufferFile = new File(StringUtils.format("{}/{}", protocolOutputPath, "ByteBuffer.gd")); var byteBufferTemplate = ClassUtils.getFileFromClassPathToString("gdscript/buffer/ByteBuffer.gd"); FileUtils.writeStringToFile(byteBufferFile, StringUtils.format(byteBufferTemplate, protocolOutputRootPath), false); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/go/GenerateGoUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/go/GenerateGoUtils.java index 65f4b746..a8e6d4ae 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/go/GenerateGoUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/go/GenerateGoUtils.java @@ -84,7 +84,7 @@ public abstract class GenerateGoUtils { /** * 生成协议依赖的工具类 */ - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var list = List.of("go/ByteBuffer.go"); for (var fileName : list) { diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/javascript/GenerateJsUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/javascript/GenerateJsUtils.java index f53b7375..3fa8080a 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/javascript/GenerateJsUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/javascript/GenerateJsUtils.java @@ -80,7 +80,7 @@ public abstract class GenerateJsUtils { jsSerializerMap = null; } - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var list = List.of("javascript/buffer/ByteBuffer.js", "javascript/buffer/long.js", "javascript/buffer/longbits.js"); for (var fileName : list) { var fileInputStream = ClassUtils.getFileFromClassPath(fileName); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/lua/CodeGenerateLua.java b/protocol/src/main/java/com/zfoo/protocol/serializer/lua/CodeGenerateLua.java index 676e8137..4e7b003b 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/lua/CodeGenerateLua.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/lua/CodeGenerateLua.java @@ -76,15 +76,15 @@ public class CodeGenerateLua implements ICodeGenerate { } @Override - public void mergerProtocol(List registrations) throws IOException { + public void mergerProtocol(List registrations) throws IOException { createTemplateFile(); var protocol_manager_registrations = new StringBuilder(); protocol_manager_registrations.append(StringUtils.format("local Protocols = require(\"{}.Protocols\")", protocolOutputRootPath)).append(LS); for (var registration : registrations) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - protocol_manager_registrations.append(StringUtils.format("protocols[{}] = Protocols.{}", protocol_id, protocol_class_name)).append(LS); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = Protocols.{}", protocol_id, protocol_name)).append(LS); } var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolManagerTemplate.lua"); var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_manager_registrations, protocol_manager_registrations.toString()); @@ -99,19 +99,18 @@ public class CodeGenerateLua implements ICodeGenerate { for (var registration : registrations) { GenerateProtocolFile.index.set(0); var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); // protocol - protocol_class.append(protocol_class((ProtocolRegistration) registration)).append(LS); + protocol_class.append(protocol_class(registration)).append(LS); // registration - protocol_registration.append(protocol_registration((ProtocolRegistration) registration)).append(LS); + protocol_registration.append(protocol_registration(registration)).append(LS); } protocol_registration.append(LS); for (var registration : registrations) { - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - protocol_registration.append(StringUtils.format("Protocols.{} = {}", protocol_class_name, protocol_class_name)).append(LS); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocol_registration.append(StringUtils.format("Protocols.{} = {}", protocol_name, protocol_name)).append(LS); } var protocolTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolsTemplate.lua"); @@ -122,22 +121,22 @@ public class CodeGenerateLua implements ICodeGenerate { var outputPath = StringUtils.format("{}/Protocols.lua", protocolOutputPath); var file = new File(outputPath); FileUtils.writeStringToFile(file, formatProtocolTemplate, true); - logger.info("Generated C# protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); + logger.info("Generated Lua protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); } @Override - public void foldProtocol(List registrations) throws IOException { + public void foldProtocol(List registrations) throws IOException { createTemplateFile(); var protocolManagerRequireBuilder = new StringBuilder(); var protocol_manager_registrations = new StringBuilder(); for (var registration : registrations) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); var path = GenerateProtocolPath.protocolPath(protocol_id); - protocolManagerRequireBuilder.append(StringUtils.format("local {} = require(\"{}.{}.{}\")", protocol_class_name, protocolOutputRootPath, path.replace(StringUtils.SLASH, StringUtils.PERIOD), protocol_class_name)).append(LS); - protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}", protocol_id, protocol_class_name)).append(LS); + protocolManagerRequireBuilder.append(StringUtils.format("local {} = require(\"{}.{}.{}\")", protocol_name, protocolOutputRootPath, path.replace(StringUtils.SLASH, StringUtils.PERIOD), protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}", protocol_id, protocol_name)).append(LS); } var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolManagerTemplate.lua"); @@ -150,9 +149,9 @@ public class CodeGenerateLua implements ICodeGenerate { for (var registration : registrations) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - var formatProtocolTemplate = formatProtocolTemplate((ProtocolRegistration) registration); - var outputPath = StringUtils.format("{}/{}/{}.lua", protocolOutputPath, GenerateProtocolPath.protocolPath(protocol_id), protocol_class_name); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var formatProtocolTemplate = formatProtocolTemplate(registration); + var outputPath = StringUtils.format("{}/{}/{}.lua", protocolOutputPath, GenerateProtocolPath.protocolPath(protocol_id), protocol_name); var file = new File(outputPath); FileUtils.writeStringToFile(file, formatProtocolTemplate, true); logger.info("Generated Lua protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); @@ -160,16 +159,16 @@ public class CodeGenerateLua implements ICodeGenerate { } @Override - public void defaultProtocol(List registrations) throws IOException { + public void defaultProtocol(List registrations) throws IOException { createTemplateFile(); var protocolManagerRequireBuilder = new StringBuilder(); var protocol_manager_registrations = new StringBuilder(); for (var registration : registrations) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - protocolManagerRequireBuilder.append(StringUtils.format("local {} = require(\"{}.{}\")", protocol_class_name, protocolOutputRootPath, protocol_class_name)).append(LS); - protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}", protocol_id, protocol_class_name)).append(LS); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + protocolManagerRequireBuilder.append(StringUtils.format("local {} = require(\"{}.{}\")", protocol_name, protocolOutputRootPath, protocol_name)).append(LS); + protocol_manager_registrations.append(StringUtils.format("protocols[{}] = {}", protocol_id, protocol_name)).append(LS); } var protocolManagerTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolManagerTemplate.lua"); var placeholderMap = Map.of(CodeTemplatePlaceholder.protocol_manager_registrations, protocolManagerRequireBuilder.toString() + protocol_manager_registrations); @@ -180,9 +179,9 @@ public class CodeGenerateLua implements ICodeGenerate { for (var registration : registrations) { - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); - var formatProtocolTemplate = formatProtocolTemplate((ProtocolRegistration) registration); - var outputPath = StringUtils.format("{}/{}.lua", protocolOutputPath, protocol_class_name); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var formatProtocolTemplate = formatProtocolTemplate(registration); + var outputPath = StringUtils.format("{}/{}.lua", protocolOutputPath, protocol_name); var file = new File(outputPath); FileUtils.writeStringToFile(file, formatProtocolTemplate, true); logger.info("Generated Lua protocol file:[{}] is in path:[{}]", file.getName(), file.getAbsolutePath()); @@ -207,24 +206,24 @@ public class CodeGenerateLua implements ICodeGenerate { // 初始化index GenerateProtocolFile.index.set(0); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); var protocolTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolTemplate.lua"); return CodeTemplatePlaceholder.formatTemplate(protocolTemplate, Map.of( CodeTemplatePlaceholder.protocol_class, protocol_class(registration) , CodeTemplatePlaceholder.protocol_registration, protocol_registration(registration) - , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_name, protocol_name )); } private String protocol_class(ProtocolRegistration registration) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); var protocolClassTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolClassTemplate.lua"); var placeholderMap = Map.of( CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Lua) - , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_name, protocol_name , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) @@ -235,12 +234,12 @@ public class CodeGenerateLua implements ICodeGenerate { private String protocol_registration(ProtocolRegistration registration) { var protocol_id = registration.protocolId(); - var protocol_class_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); + var protocol_name = registration.protocolConstructor().getDeclaringClass().getSimpleName(); var protocolRegistrationTemplate = ClassUtils.getFileFromClassPathToString("lua/ProtocolRegistrationTemplate.lua"); var placeholderMap = Map.of( CodeTemplatePlaceholder.protocol_note, GenerateProtocolNote.protocol_note(protocol_id, CodeLanguage.Lua) - , CodeTemplatePlaceholder.protocol_name, protocol_class_name + , CodeTemplatePlaceholder.protocol_name, protocol_name , CodeTemplatePlaceholder.protocol_id, String.valueOf(protocol_id) , CodeTemplatePlaceholder.protocol_field_definition, protocol_field_definition(registration) , CodeTemplatePlaceholder.protocol_write_serialization, protocol_write_serialization(registration) diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java index c61997c8..0c806e66 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/python/GeneratePyUtils.java @@ -82,7 +82,7 @@ public abstract class GeneratePyUtils { pySerializerMap = null; } - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var list = List.of("python/ByteBuffer.py"); for (var fileName : list) { var fileInputStream = ClassUtils.getFileFromClassPath(fileName); diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java index fe5120f5..c491e2d2 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/typescript/GenerateTsUtils.java @@ -83,7 +83,7 @@ public abstract class GenerateTsUtils { tsSerializerMap = null; } - public static void createProtocolManager(List protocolList) throws IOException { + public static void createProtocolManager(List protocolList) throws IOException { var list = List.of("typescript/IByteBuffer.ts", "typescript/buffer/ByteBuffer.ts", "typescript/buffer/Long.ts", "typescript/buffer/Longbits.ts"); for (var fileName : list) { var fileInputStream = ClassUtils.getFileFromClassPath(fileName); diff --git a/protocol/src/main/resources/cpp/ProtocolClassTemplate.h b/protocol/src/main/resources/cpp/ProtocolClassTemplate.h new file mode 100644 index 00000000..04c38cf3 --- /dev/null +++ b/protocol/src/main/resources/cpp/ProtocolClassTemplate.h @@ -0,0 +1,11 @@ +${protocol_note} +class ${protocol_name} : public IProtocol { +public: + ${protocol_field_definition} + + ~${protocol_name}() override = default; + + int16_t protocolId() override { + return ${protocol_id}; + } +}; \ No newline at end of file diff --git a/protocol/src/main/resources/cpp/ProtocolManagerTemplate.h b/protocol/src/main/resources/cpp/ProtocolManagerTemplate.h index a245204a..9ab7634c 100644 --- a/protocol/src/main/resources/cpp/ProtocolManagerTemplate.h +++ b/protocol/src/main/resources/cpp/ProtocolManagerTemplate.h @@ -2,14 +2,14 @@ #define ZFOO_PROTOCOLMANAGER_H #include "ByteBuffer.h" -{} +${protocol_imports} namespace zfoo { const int16_t MAX_PROTOCOL_NUM = 32767; const IProtocolRegistration *protocols[MAX_PROTOCOL_NUM]; void initProtocol() { - {} + ${protocol_manager_registrations} } inline IProtocolRegistration *getProtocol(int16_t protocolId) { diff --git a/protocol/src/main/resources/cpp/ProtocolRegistrationTemplate.h b/protocol/src/main/resources/cpp/ProtocolRegistrationTemplate.h new file mode 100644 index 00000000..423bfe98 --- /dev/null +++ b/protocol/src/main/resources/cpp/ProtocolRegistrationTemplate.h @@ -0,0 +1,29 @@ +class ${protocol_name}Registration : public IProtocolRegistration { +public: + int16_t protocolId() override { + return ${protocol_id}; + } + + void write(ByteBuffer &buffer, IProtocol *packet) override { + if (packet == nullptr) { + buffer.writeInt(0); + return; + } + auto *message = (${protocol_name} *) packet; + ${protocol_write_serialization} + } + + IProtocol *read(ByteBuffer &buffer) override { + auto *packet = new ${protocol_name}(); + auto length = buffer.readInt(); + if (length == 0) { + return packet; + } + auto beforeReadIndex = buffer.readerIndex(); + ${protocol_read_deserialization} + if (length > 0) { + buffer.readerIndex(beforeReadIndex + length); + } + return packet; + } +}; \ No newline at end of file diff --git a/protocol/src/main/resources/cpp/ProtocolTemplate.h b/protocol/src/main/resources/cpp/ProtocolTemplate.h index 26201396..d054186a 100644 --- a/protocol/src/main/resources/cpp/ProtocolTemplate.h +++ b/protocol/src/main/resources/cpp/ProtocolTemplate.h @@ -1,63 +1,12 @@ -#ifndef ZFOO_{}_H -#define ZFOO_{}_H +#ifndef ZFOO_${protocol_name} +#define ZFOO_${protocol_name} -#include "{}/ByteBuffer.h" -{} +#include "${protocol_root_path}/ByteBuffer.h" +${protocol_imports} namespace zfoo { + ${protocol_class} - {} - class {} : public IProtocol { - public: - {} - - ~{}() override = default; - - static {} valueOf({}) { - auto packet = {}(); - {} - return packet; - } - - int16_t protocolId() override { - return {}; - } - - bool operator<(const {} &_) const { - {} - return false; - } - }; - - - class {}Registration : public IProtocolRegistration { - public: - int16_t protocolId() override { - return {}; - } - - void write(ByteBuffer &buffer, IProtocol *packet) override { - if (packet == nullptr) { - buffer.writeInt(0); - return; - } - auto *message = ({} *) packet; - {} - } - - IProtocol *read(ByteBuffer &buffer) override { - auto *packet = new {}(); - auto length = buffer.readInt(); - if (length == 0) { - return packet; - } - auto beforeReadIndex = buffer.readerIndex(); - {} - if (length > 0) { - buffer.readerIndex(beforeReadIndex + length); - } - return packet; - } - }; + ${protocol_registration} } #endif diff --git a/protocol/src/main/resources/cpp/ProtocolsTemplate.h b/protocol/src/main/resources/cpp/ProtocolsTemplate.h new file mode 100644 index 00000000..3fc47458 --- /dev/null +++ b/protocol/src/main/resources/cpp/ProtocolsTemplate.h @@ -0,0 +1,12 @@ +#ifndef ZFOO_Protocols +#define ZFOO_Protocols + +#include "${protocol_root_path}/ByteBuffer.h" + +namespace zfoo { + ${protocol_class} + + ${protocol_registration} +} + +#endif