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

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;
}
}
}
*/
}
}
}