You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
5.2 KiB
178 lines
5.2 KiB
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace ProtoCSStruct
|
|
{
|
|
public class ProtoMessage
|
|
{
|
|
//字节对齐,4字节或8字节
|
|
public int AlignByte;
|
|
//结构体在内存里大小
|
|
private int SizeOf = int.MaxValue;
|
|
|
|
//是否是需要unsafe 修饰
|
|
public bool Unsafe;
|
|
|
|
public string Name;
|
|
|
|
public List<ProtoMessageField> Fields = new List<ProtoMessageField>();
|
|
|
|
public Dictionary<string, ProtoMessageField> FieldsMap = new Dictionary<string, ProtoMessageField>();
|
|
|
|
public int GetMessageSize()
|
|
{
|
|
if(SizeOf == int.MaxValue)
|
|
{
|
|
Calc();
|
|
}
|
|
return SizeOf;
|
|
}
|
|
|
|
public void Calc()
|
|
{
|
|
if (SizeOf != int.MaxValue)
|
|
{
|
|
return;
|
|
}
|
|
CalcStructSize();
|
|
CalcUnsafe();
|
|
}
|
|
|
|
//结构体的大小,字节对齐
|
|
//结构体的大小其实算错了不要紧,只要算出来不比实际小就没问题
|
|
private void CalcStructSize()
|
|
{
|
|
//缺省8字节对齐
|
|
//往大了对齐肯定不会有错就是了
|
|
//要不然还要递归算,子结构体如果8字节对齐,那么此结构也8字节对齐
|
|
//所以全都8字节对齐算了,无非浪费点内存
|
|
AlignByte = 8;
|
|
|
|
|
|
//如果有int64和uint64,则8字节对齐
|
|
/*
|
|
foreach(var field in Fields)
|
|
{
|
|
if(field.IsRepeated)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(field.FieldType == FieldType.Int64
|
|
|| field.FieldType == FieldType.UInt64)
|
|
{
|
|
AlignByte = 8;
|
|
break;
|
|
}
|
|
}*/
|
|
|
|
int sizeOffset = 0;
|
|
int calcSize = 0;
|
|
//根据对齐,字段大小
|
|
foreach (var field in Fields)
|
|
{
|
|
int fieldSize = 0;
|
|
int multiply = 1;
|
|
if (field.IsRepeated || field.FieldType == FieldType.Bytes)
|
|
{
|
|
multiply = field.RepeatedCount;
|
|
}
|
|
|
|
if (field.FieldType == FieldType.Bool
|
|
|| field.FieldType == FieldType.Bytes)
|
|
{
|
|
fieldSize = 1;
|
|
}
|
|
else if (field.FieldType == FieldType.Int32
|
|
|| field.FieldType == FieldType.UInt32
|
|
|| field.FieldType == FieldType.Enum)
|
|
{
|
|
fieldSize = 4;
|
|
if(sizeOffset % 4 != 0)
|
|
{
|
|
sizeOffset += (4 - (sizeOffset % 4));
|
|
}
|
|
}
|
|
else if (field.FieldType == FieldType.Int64
|
|
|| field.FieldType == FieldType.UInt64)
|
|
{
|
|
fieldSize = 8;
|
|
if (sizeOffset % 8 != 0)
|
|
{
|
|
sizeOffset += (8 - (sizeOffset % 8));
|
|
}
|
|
}
|
|
else if (field.FieldType == FieldType.String)
|
|
{
|
|
fieldSize = field.StringLength * 2 + AlignByte;
|
|
}
|
|
else if (field.FieldType == FieldType.Message)
|
|
{
|
|
fieldSize = field.Message.GetMessageSize();
|
|
}
|
|
|
|
fieldSize = fieldSize * multiply;
|
|
if (field.IsRepeated || field.FieldType == FieldType.Bytes)
|
|
{
|
|
field.RepeatedFiledBuffSize = fieldSize;
|
|
if (field.RepeatedFiledBuffSize % AlignByte != 0) //补齐
|
|
{
|
|
field.RepeatedFiledBuffSize += (AlignByte - (field.RepeatedFiledBuffSize % AlignByte));
|
|
}
|
|
fieldSize = field.RepeatedFiledBuffSize + AlignByte;
|
|
}
|
|
|
|
sizeOffset += fieldSize;
|
|
while (sizeOffset > AlignByte)
|
|
{
|
|
calcSize += AlignByte;
|
|
sizeOffset -= AlignByte;
|
|
}
|
|
}
|
|
|
|
if(sizeOffset > 0)
|
|
{
|
|
calcSize += AlignByte;
|
|
sizeOffset = 0;
|
|
}
|
|
|
|
//只有空结构体,算出来才是0
|
|
if(calcSize == 0)
|
|
{
|
|
SizeOf = AlignByte;
|
|
}
|
|
else
|
|
{
|
|
SizeOf = calcSize;
|
|
}
|
|
}
|
|
|
|
//是否需要unsafe修饰
|
|
private void CalcUnsafe()
|
|
{
|
|
Unsafe = false;
|
|
|
|
/*
|
|
foreach (var field in Fields)
|
|
{
|
|
if(field.FieldType == FieldType.Bytes)
|
|
{
|
|
Unsafe = true;
|
|
return;
|
|
}
|
|
|
|
|
|
if (field.IsRepeated)
|
|
{
|
|
if (field.FieldType != FieldType.String
|
|
&& field.FieldType != FieldType.Message)
|
|
{
|
|
Unsafe = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|