ref[cpp]: refactor generate C++ protocol

This commit is contained in:
godotg
2024-05-24 17:26:48 +08:00
parent 102be61edd
commit 26fcf1af85
26 changed files with 629 additions and 567 deletions
@@ -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<ProtocolRegistration> subProtocolFirst(List<ProtocolRegistration> registrations) {
var registrations1 = new ArrayList<ProtocolRegistration>(registrations);
var subFirstRegistrations = new ArrayList<ProtocolRegistration>();
var set = new HashSet<Short>();
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;
}
}
@@ -120,11 +120,11 @@ public abstract class GenerateProtocolNote {
return note;
}
public static void initProtocolNote(List<IProtocolRegistration> protocolRegistrations) {
public static void initProtocolNote(List<ProtocolRegistration> 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<String, String>();
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));
}
}
@@ -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<IProtocolRegistration> protocolRegistrations) {
public static void initProtocolPath(List<ProtocolRegistration> protocolRegistrations) {
// 将需要生成的协议的路径添加到多叉树中
var protocolPathTree = new GeneralTree<IProtocolRegistration>();
var protocolPathTree = new GeneralTree<ProtocolRegistration>();
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<IProtocolRegistration> protocolTreeNode) {
private static void toProtocolPath(TreeNode<ProtocolRegistration> protocolTreeNode) {
var allChildren = protocolTreeNode.flatTreeNodes()
.stream()
.filter(it -> it.getData() != null)
@@ -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();
@@ -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),
@@ -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));
}
}
@@ -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<IProtocolRegistration> registrations) throws IOException;
void mergerProtocol(List<ProtocolRegistration> registrations) throws IOException;
/**
* 折叠协议,生成协议文件会和Java源文件保持相同的目录结构
*/
void foldProtocol(List<IProtocolRegistration> registrations) throws IOException;
void foldProtocol(List<ProtocolRegistration> registrations) throws IOException;
/**
* 默认把所有的协议文件放在同一个更目录下,不做任何操作
*/
void defaultProtocol(List<IProtocolRegistration> registrations) throws IOException;
void defaultProtocol(List<ProtocolRegistration> registrations) throws IOException;
}
@@ -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<ISerializer, ICppSerializer> 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<ProtocolRegistration> 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<ProtocolRegistration> 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<ProtocolRegistration> 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<ProtocolRegistration> 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("<Boolean", "<bool");
typeName = typeName.replace("Boolean>", "bool>");
// 将Byte转为byte
typeName = typeName.replace("Byte[", "int8_t");
typeName = typeName.replace("Byte>", "int8_t>");
typeName = typeName.replace("<Byte", "<int8_t");
// 将Short转为short
typeName = typeName.replace("Short[", "int16_t");
typeName = typeName.replace("Short>", "int16_t>");
typeName = typeName.replace("<Short", "<int16_t");
// 将Integer转为int
typeName = typeName.replace("Integer[", "int32_t");
typeName = typeName.replace("Integer>", "int32_t>");
typeName = typeName.replace("<Integer", "<int32_t");
// 将Long转为long
typeName = typeName.replace("Long[", "int64_t");
typeName = typeName.replace("Long>", "int64_t>");
typeName = typeName.replace("<Long", "<int64_t");
// 将Float转为float
typeName = typeName.replace("Float[", "float");
typeName = typeName.replace("Float>", "float>");
typeName = typeName.replace("<Float", "<float");
// 将Double转为double
typeName = typeName.replace("Double[", "double");
typeName = typeName.replace("Double>", "double>");
typeName = typeName.replace("<Double", "<double");
// 将Character转为Char
typeName = typeName.replace("Character[", "char");
typeName = typeName.replace("Character>", "char>");
typeName = typeName.replace("<Character", "<char");
// 将String转为string
typeName = typeName.replace("String[", "string");
typeName = typeName.replace("String>", "string>");
typeName = typeName.replace("<String", "<string");
// 将Map转为map
typeName = typeName.replace("Map<", "map<");
// 将Set转为set
typeName = typeName.replace("Set<", "set<");
// 将List转为vector
typeName = typeName.replace("List<", "list<");
return typeName;
}
}
@@ -33,7 +33,7 @@ public class CppArraySerializer implements ICppSerializer {
@Override
public Pair<String, String> 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;
@@ -33,7 +33,7 @@ public class CppListSerializer implements ICppSerializer {
@Override
public Pair<String, String> 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;
@@ -33,7 +33,7 @@ public class CppMapSerializer implements ICppSerializer {
@Override
public Pair<String, String> 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);
@@ -33,7 +33,7 @@ public class CppSetSerializer implements ICppSerializer {
@Override
public Pair<String, String> 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);
@@ -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<ISerializer, ICppSerializer> 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<IProtocolRegistration> 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<String, String> valueOfMethod(ProtocolRegistration registration) {
var fields = registration.getFields();
var fieldRegistrations = registration.getFieldRegistrations();
var filedList = new ArrayList<Pair<String, String>>();
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<Pair<String, String>>();
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("<Boolean", "<bool");
typeName = typeName.replace("Boolean>", "bool>");
// 将Byte转为byte
typeName = typeName.replace("Byte[", "int8_t");
typeName = typeName.replace("Byte>", "int8_t>");
typeName = typeName.replace("<Byte", "<int8_t");
// 将Short转为short
typeName = typeName.replace("Short[", "int16_t");
typeName = typeName.replace("Short>", "int16_t>");
typeName = typeName.replace("<Short", "<int16_t");
// 将Integer转为int
typeName = typeName.replace("Integer[", "int32_t");
typeName = typeName.replace("Integer>", "int32_t>");
typeName = typeName.replace("<Integer", "<int32_t");
// 将Long转为long
typeName = typeName.replace("Long[", "int64_t");
typeName = typeName.replace("Long>", "int64_t>");
typeName = typeName.replace("<Long", "<int64_t");
// 将Float转为float
typeName = typeName.replace("Float[", "float");
typeName = typeName.replace("Float>", "float>");
typeName = typeName.replace("<Float", "<float");
// 将Double转为double
typeName = typeName.replace("Double[", "double");
typeName = typeName.replace("Double>", "double>");
typeName = typeName.replace("<Double", "<double");
// 将Character转为Char
typeName = typeName.replace("Character[", "char");
typeName = typeName.replace("Character>", "char>");
typeName = typeName.replace("<Character", "<char");
// 将String转为string
typeName = typeName.replace("String[", "string");
typeName = typeName.replace("String>", "string>");
typeName = typeName.replace("<String", "<string");
// 将Map转为map
typeName = typeName.replace("Map<", "map<");
// 将Set转为set
typeName = typeName.replace("Set<", "set<");
// 将List转为vector
typeName = typeName.replace("List<", "list<");
return typeName;
}
}
@@ -80,7 +80,7 @@ public class CodeGenerateCsharp implements ICodeGenerate {
}
@Override
public void mergerProtocol(List<IProtocolRegistration> registrations) throws IOException {
public void mergerProtocol(List<ProtocolRegistration> 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<IProtocolRegistration> registrations) throws IOException {
public void foldProtocol(List<ProtocolRegistration> 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<IProtocolRegistration> registrations) throws IOException {
public void defaultProtocol(List<ProtocolRegistration> 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<IProtocolRegistration> registrations) throws IOException {
private void createProtocolManagerFile(List<ProtocolRegistration> 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<IProtocolRegistration> protocolList) {
private String protocol_manager_registrations(List<ProtocolRegistration> protocolList) {
var csBuilder = new StringBuilder();
for (var protocol : protocolList) {
var protocolId = protocol.protocolId();
@@ -80,7 +80,7 @@ public abstract class GenerateEsUtils {
esSerializerMap = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> 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);
@@ -86,7 +86,7 @@ public abstract class GenerateGdUtils {
protocolOutputPath = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> 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);
@@ -84,7 +84,7 @@ public abstract class GenerateGoUtils {
/**
* 生成协议依赖的工具类
*/
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> protocolList) throws IOException {
var list = List.of("go/ByteBuffer.go");
for (var fileName : list) {
@@ -80,7 +80,7 @@ public abstract class GenerateJsUtils {
jsSerializerMap = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> 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);
@@ -76,15 +76,15 @@ public class CodeGenerateLua implements ICodeGenerate {
}
@Override
public void mergerProtocol(List<IProtocolRegistration> registrations) throws IOException {
public void mergerProtocol(List<ProtocolRegistration> 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<IProtocolRegistration> registrations) throws IOException {
public void foldProtocol(List<ProtocolRegistration> 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<IProtocolRegistration> registrations) throws IOException {
public void defaultProtocol(List<ProtocolRegistration> 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)
@@ -82,7 +82,7 @@ public abstract class GeneratePyUtils {
pySerializerMap = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> protocolList) throws IOException {
var list = List.of("python/ByteBuffer.py");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
@@ -83,7 +83,7 @@ public abstract class GenerateTsUtils {
tsSerializerMap = null;
}
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
public static void createProtocolManager(List<ProtocolRegistration> 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);
@@ -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};
}
};
@@ -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) {
@@ -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;
}
};
@@ -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
@@ -0,0 +1,12 @@
#ifndef ZFOO_Protocols
#define ZFOO_Protocols
#include "${protocol_root_path}/ByteBuffer.h"
namespace zfoo {
${protocol_class}
${protocol_registration}
}
#endif