feat[csharp]: csharp support compatible field

This commit is contained in:
godotg
2023-10-17 15:44:48 +08:00
parent 6a0f985061
commit 099d5118b3
9 changed files with 76 additions and 206 deletions
@@ -1,44 +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.csharp;
import com.zfoo.protocol.generate.GenerateProtocolFile;
import com.zfoo.protocol.registration.field.IFieldRegistration;
import com.zfoo.protocol.util.StringUtils;
import java.lang.reflect.Field;
import static com.zfoo.protocol.util.FileUtils.LS;
/**
* @author godotg
*/
public class CsCharSerializer implements ICsSerializer {
@Override
public void writeObject(StringBuilder builder, String objectStr, int deep, Field field, IFieldRegistration fieldRegistration) {
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("buffer.WriteChar({});", objectStr)).append(LS);
}
@Override
public String readObject(StringBuilder builder, int deep, Field field, IFieldRegistration fieldRegistration) {
String result = "result" + GenerateProtocolFile.index.getAndIncrement();
GenerateProtocolFile.addTab(builder, deep);
builder.append(StringUtils.format("char {} = buffer.ReadChar();", result)).append(LS);
return result;
}
}
@@ -43,7 +43,9 @@ import static com.zfoo.protocol.util.StringUtils.TAB;
*/
public abstract class GenerateCsUtils {
private static String protocolOutputRootPath = "CsProtocol/";
// custom configuration
public static String protocolOutputRootPath = "zfoocs";
public static String protocolOutputPath = StringUtils.EMPTY;
private static Map<ISerializer, ICsSerializer> csSerializerMap;
@@ -52,10 +54,13 @@ public abstract class GenerateCsUtils {
}
public static void init(GenerateOperation generateOperation) {
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
FileUtils.deleteFile(new File(protocolOutputRootPath));
FileUtils.createDirectory(protocolOutputRootPath);
// if not specify output path, then use current default path
if (StringUtils.isEmpty(generateOperation.getProtocolPath())) {
protocolOutputPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
} else {
protocolOutputPath = generateOperation.getProtocolPath();
}
FileUtils.deleteFile(new File(protocolOutputPath));
csSerializerMap = new HashMap<>();
csSerializerMap.put(BooleanSerializer.INSTANCE, new CsBooleanSerializer());
@@ -76,6 +81,7 @@ public abstract class GenerateCsUtils {
public static void clear() {
csSerializerMap = null;
protocolOutputRootPath = null;
protocolOutputPath = null;
}
/**
@@ -84,14 +90,13 @@ public abstract class GenerateCsUtils {
public static void createProtocolManager() throws IOException {
var list = List.of("csharp/ProtocolManager.cs"
, "csharp/IProtocolRegistration.cs"
, "csharp/IProtocol.cs"
, "csharp/Buffer/ByteBuffer.cs"
, "csharp/Buffer/LittleEndianByteBuffer.cs"
, "csharp/Buffer/BigEndianByteBuffer.cs");
for (var fileName : list) {
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "csharp/")));
var createFile = new File(StringUtils.format("{}/{}", protocolOutputPath, StringUtils.substringAfterFirst(fileName, "csharp/")));
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
}
}
@@ -1,4 +1,4 @@
namespace CsProtocol.Buffer
namespace zfoocs
{
public class BigEndianByteBuffer : ByteBuffer
{
@@ -4,7 +4,7 @@ using System.Text;
// CSharp字节保存在内存的低地址中是根据操作系统来的,所以有可能是大端模式,也有可能是小端模式
// 右移操作>>是带符号右移
namespace CsProtocol.Buffer
namespace zfoocs
{
public abstract class ByteBuffer
{
@@ -49,6 +49,30 @@ namespace CsProtocol.Buffer
readOffset = 0;
}
}
public void AdjustPadding(int predictionLength, int beforeWriteIndex) {
// 因为写入的是可变长的int,如果预留的位置过多,则清除多余的位置
var currentWriteIndex = WriteOffset();
var predictionCount = WriteIntCount(predictionLength);
var length = currentWriteIndex - beforeWriteIndex - predictionCount;
var lengthCount = WriteIntCount(length);
var padding = lengthCount - predictionCount;
if (padding == 0) {
SetWriteOffset(beforeWriteIndex);
WriteInt(length);
SetWriteOffset(currentWriteIndex);
} else {
var bytes = new byte[length];
Array.Copy(buffer, currentWriteIndex - length, bytes, 0, length);
SetWriteOffset(beforeWriteIndex);
WriteInt(length);
WriteBytes(bytes);
}
}
public bool CompatibleRead(int beforeReadIndex, int length) {
return length != -1 && ReadOffset() < length + beforeReadIndex;
}
// -------------------------------------------------get/set-------------------------------------------------
public int WriteOffset()
@@ -69,6 +93,11 @@ namespace CsProtocol.Buffer
writeOffset = writeIndex;
}
public int ReadOffset()
{
return readOffset;
}
public void SetReadOffset(int readIndex)
{
if (readIndex > writeOffset)
@@ -235,6 +264,31 @@ namespace CsProtocol.Buffer
return (int) (value >> 1) ^ -((int) (value) & 1);
}
public int WriteIntCount(int intValue)
{
// 用Zigzag算法压缩int和long的值
// 再用Varint紧凑算法表示数字的有效位
uint value = (uint) ((intValue << 1) ^ (intValue >> 31));
if (value >> 7 == 0)
{
return 1;
}
if (value >> 14 == 0)
{
return 2;
}
if (value >> 21 == 0)
{
return 3;
}
if (value >> 28 == 0)
{
return 4;
}
return 5;
}
// 写入没有压缩的int
public abstract void WriteRawInt(int value);
@@ -391,20 +445,6 @@ namespace CsProtocol.Buffer
public abstract void WriteDouble(double value);
public abstract double ReadDouble();
// *******************************************char***************************************************
public char ReadChar()
{
// need check
var str = ReadString();
return string.IsNullOrEmpty(str) ? char.MinValue : str[0];
}
public void WriteChar(char value)
{
// need check
WriteString(new string(value, 1));
}
// *******************************************String***************************************************
public void WriteString(string value)
@@ -794,38 +834,6 @@ namespace CsProtocol.Buffer
return array;
}
public void WriteCharArray(char[] array)
{
if ((array == null) || (array.Length == 0))
{
WriteInt(0);
}
else
{
WriteInt(array.Length);
int length = array.Length;
for (int index = 0; index < length; index++)
{
WriteChar(array[index]);
}
}
}
public char[] ReadCharArray()
{
int size = ReadInt();
char[] array = new char[size];
if (size > 0)
{
for (int index = 0; index < size; index++)
{
array[index] = ReadChar();
}
}
return array;
}
public void WriteStringArray(string[] array)
{
if ((array == null) || (array.Length == 0))
@@ -1116,38 +1124,6 @@ namespace CsProtocol.Buffer
return list;
}
public void WriteCharList(List<char> list)
{
if ((list == null) || (list.Count == 0))
{
WriteInt(0);
}
else
{
WriteInt(list.Count);
int length = list.Count;
for (int index = 0; index < length; index++)
{
WriteDouble(list[index]);
}
}
}
public List<char> ReadCharList()
{
int size = ReadInt();
List<char> list = new List<char>(size);
if (size > 0)
{
for (int index = 0; index < size; index++)
{
list.Add(ReadChar());
}
}
return list;
}
public void WriteStringList(List<string> list)
{
if ((list == null) || (list.Count == 0))
@@ -1400,37 +1376,6 @@ namespace CsProtocol.Buffer
return set;
}
public void WriteCharSet(HashSet<char> set)
{
if ((set == null) || (set.Count == 0))
{
WriteInt(0);
}
else
{
WriteInt(set.Count);
foreach (var element in set)
{
WriteChar(element);
}
}
}
public HashSet<char> ReadCharSet()
{
int size = ReadInt();
HashSet<char> set = new HashSet<char>();
if (size > 0)
{
for (int index = 0; index < size; index++)
{
set.Add(ReadChar());
}
}
return set;
}
public void WriteStringSet(HashSet<string> set)
{
if ((set == null) || (set.Count == 0))
@@ -1,6 +1,6 @@
using System;
namespace CsProtocol.Buffer
namespace zfoocs
{
public class LittleEndianByteBuffer : ByteBuffer
{
@@ -1,7 +0,0 @@
namespace CsProtocol.Buffer
{
public interface IProtocol
{
short ProtocolId();
}
}
@@ -1,4 +1,4 @@
namespace CsProtocol.Buffer
namespace zfoocs
{
public interface IProtocolRegistration
{
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using CsProtocol.Buffer;
namespace CsProtocol
namespace zfoocs
{
public class ProtocolManager
{
@@ -10,33 +9,12 @@ namespace CsProtocol
private static readonly IProtocolRegistration[] protocolList = new IProtocolRegistration[MAX_PROTOCOL_NUM];
private static readonly Dictionary<Type, short> protocolIdMap = new Dictionary<Type, short>();
public static void InitProtocol()
{
var protocolRegistrationTypeList = new List<Type>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.Equals(typeof(ProtocolManager).Assembly))
{
var results = new List<Type>();
results.AddRange(assembly.GetTypes());
foreach (var type in results)
{
if (type.IsClass && !type.IsAbstract && typeof(IProtocolRegistration).IsAssignableFrom(type))
{
protocolRegistrationTypeList.Add(type);
}
}
}
}
foreach (var protocolRegistrationType in protocolRegistrationTypeList)
{
var protocolRegistration = (IProtocolRegistration) Activator.CreateInstance(protocolRegistrationType);
protocolList[protocolRegistration.ProtocolId()] = protocolRegistration;
}
{}
}
public static IProtocolRegistration GetProtocol(short protocolId)
@@ -44,7 +22,7 @@ namespace CsProtocol
var protocol = protocolList[protocolId];
if (protocol == null)
{
throw new Exception("[protocolId:" + protocolId + "]协议不存在");
throw new Exception("[protocolId:" + protocolId + "] not exist");
}
return protocol;
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using CsProtocol.Buffer;
namespace CsProtocol
namespace zfoocs
{
{}
public class {} : IProtocol
public class {}
{
{}
@@ -15,12 +14,6 @@ namespace CsProtocol
{}
return packet;
}
public short ProtocolId()
{
return {};
}
}