Main/Assets/Code/Logic/_Helper/ProtoBufUtils.cs
2025-01-25 04:38:09 +08:00

656 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
using ProtoBuf;
using Thousandto.Core.Base;
namespace Thousandto.Plugins.Common
{
/// <summary>
/// ProtoBuf工具
/// </summary>
public class ProtoBufUtils
{
//多线程使用
public static object WriteLocker = new object();
public static object ReadLocker = new object();
//计数器作为单个消息子结构体临时id
private static int _counter = 0;
//long 最大值
private const long Int64Max = 9223372036854775807;
//int 最大值
private const int Int32Max = 2147483647;
//缓存
private static byte[] _bytesCache = new byte[256 * 1024];
//当前写入位置
private static int _writePos = 0;
//UTF8编码
private static readonly UTF8Encoding Encoding = new UTF8Encoding();
//子结构体字典
private static Dictionary<int, SubItemInfo> SubItemInfoDic = new Dictionary<int, SubItemInfo>(23);
//当前反序列化后的byte数组
private static byte[] _readbytes = null;
//==================================================[Write]===================================================
//初始化重置
public static void InitWriteData()
{
_writePos = 0;
_counter = 0;
}
//获取子结构体临时id
public static int GetSubItemInfoId()
{
return ++_counter;
}
//1.设置一个位置空长度(这里默认都设置1个byte)
public static void SetEmptyLength(int SubItemInfoId)//, int Count = 1)
{
if (!SubItemInfoDic.ContainsKey(SubItemInfoId))
{
SubItemInfo msgInfo = new SubItemInfo
{
LBeginIndex = _writePos,
LCount = 1
};
SubItemInfoDic.Add(SubItemInfoId, msgInfo);
}
else
{
var subItemInfo = SubItemInfoDic[SubItemInfoId];
subItemInfo.LBeginIndex = _writePos;
subItemInfo.LCount = 1;
}
//for (int i = 0; i < Count; i++)
//{
_bytesCache[_writePos++] = 0;
//}
}
//设置子结构体的开始索引
public static void SetVBeginIndex(int SubItemInfoId)
{
if (!SubItemInfoDic.ContainsKey(SubItemInfoId))
{
Debug.LogError("Error SetBeginIndex");
return;
}
SubItemInfoDic[SubItemInfoId].VBeginIndex = _writePos;
}
//设置子结构体的结束索引
public static void SetVEndIndex(int SubItemInfoId)
{
if (!SubItemInfoDic.ContainsKey(SubItemInfoId))
{
Debug.LogError("Error SetEndIndex");
return;
}
SubItemInfoDic[SubItemInfoId].VEndIndex = _writePos;
}
//检查真实长度是否大于一个byte的存储如果大于就需要整体偏移最后设置真实的长度
public static int CheckAndSetLength(int SubItemInfoId)
{
if (!SubItemInfoDic.ContainsKey(SubItemInfoId))
{
Debug.LogError("Error CheckAndSetLength");
return 0;
}
int length = 1;
SubItemInfo subItemInfo = SubItemInfoDic[SubItemInfoId];
int realLength = subItemInfo.VEndIndex - subItemInfo.VBeginIndex;
int lengthIndex = subItemInfo.LBeginIndex;
if (realLength > 127)
{
if (realLength > 16383)
{
//偏移2个位置
Move(lengthIndex + 1, lengthIndex + 3, realLength);
length = 3;
}
else
{
//偏移1个位置
Move(lengthIndex + 1, lengthIndex + 2, realLength);
length = 2;
}
}
//设置真实的长度
do
{
_bytesCache[lengthIndex++] = (byte)(realLength & 0x7F | 0x80);
}
while ((realLength >>= 7) != 0);
_bytesCache[lengthIndex - 1] &= 0x7F;
return length;
}
//byte数组中的内容整体移动
private static void Move(int srcOffset, int desOffset, int count)
{
Buffer.BlockCopy(_bytesCache, srcOffset, _bytesCache, desOffset, count);
_writePos += desOffset - srcOffset;
}
//获取数据
public static byte[] GetData()
{
var bytes = GetByteArrFormPool(_writePos);
Buffer.BlockCopy(_bytesCache, 0, bytes, 0, _writePos);
return bytes;
}
//从缓存池获取bytes
private static byte[] GetByteArrFormPool(int length)
{
return BytesPool.GetBytes(length);
}
//回收bytes
public static void Free(byte[] bytes)
{
BytesPool.Free(bytes);
}
//写内容头
public static void WriteHeader(int fieldNumber, WireType wireType)
{
uint header = (((uint)fieldNumber) << 3) | (((uint)wireType) & 7);
WriteUInt32Variant(header);
}
//=========[T-V]========
//可变长度Variant 32位
private static uint Zig(int value)
{
return (uint)((value << 1) ^ (value >> 31));
}
//可变长度Variant 64位
private static ulong Zig(long value)
{
return (ulong)((value << 1) ^ (value >> 63));
}
//可变长度write type = 0
private static void WriteUInt32Variant(uint value)
{
do
{
_bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80);
}
while ((value >>= 7) != 0);
_bytesCache[_writePos - 1] &= 0x7F;
}
//可变长度write type = 0
private static void WriteUInt64Variant(ulong value)
{
do
{
_bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80);
}
while ((value >>= 7) != 0);
_bytesCache[_writePos - 1] &= 0x7F;
}
//bool
public static void WriteBoolean(int fieldNumber, bool value)
{
WriteHeader(fieldNumber, WireType.Variant);
WriteUInt32Variant(value ? (uint)1 : (uint)0);
}
//int32
public static void WriteInt32(int fieldNumber, int value)
{
WriteHeader(fieldNumber, WireType.Variant);
if (value >= 0)
WriteUInt32Variant((uint)value);
else
{
_bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 7 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 14 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 21 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 28 & 0xF);
}
}
//int64
public static void WriteInt64(int fieldNumber, long value)
{
WriteHeader(fieldNumber, WireType.Variant);
if (value >= 0)
WriteUInt64Variant((ulong)value);
else
{
_bytesCache[_writePos++] = (byte)(value & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 7 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 14 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 21 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 28 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 35 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 42 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 49 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)(value >> 56 & 0x7F | 0x80);
_bytesCache[_writePos++] = (byte)1;
}
}
//uint32
public static void WriteUint32(int fieldNumber, uint value)
{
WriteHeader(fieldNumber, WireType.Variant);
WriteUInt32Variant(value);
}
//uint64
public static void WriteUint64(int fieldNumber, ulong value)
{
WriteHeader(fieldNumber, WireType.Variant);
WriteUInt64Variant(value);
}
//sint32
public static void WriteSint32(int fieldNumber, int value)
{
WriteHeader(fieldNumber, WireType.Variant);
WriteUInt32Variant(Zig(value));
}
//sint64
public static void WriteSint64(int fieldNumber, long value)
{
WriteHeader(fieldNumber, WireType.Variant);
WriteUInt64Variant(Zig(value));
}
//=========[固定32位]========
//32位写入byte数组
private static void WriteInt32ToBuffer(uint value)
{
_bytesCache[_writePos++] = (byte)value;
_bytesCache[_writePos++] = (byte)(value >> 8);
_bytesCache[_writePos++] = (byte)(value >> 16);
_bytesCache[_writePos++] = (byte)(value >> 24);
}
//Fixed32
public static void WriteFixed32(int fieldNumber, uint value)
{
WriteHeader(fieldNumber, WireType.Fixed32);
WriteInt32ToBuffer(value);
}
//float
public static void WriteFloat(int fieldNumber, float value)
{
WriteHeader(fieldNumber, WireType.Fixed32);
WriteInt32ToBuffer(MathLib.Float2Uint(value));
}
//=========[固定64位]========
//64位写入byte数组
private static void WriteInt64ToBuffer(ulong value)
{
_bytesCache[_writePos++] = (byte)value;
_bytesCache[_writePos++] = (byte)(value >> 8);
_bytesCache[_writePos++] = (byte)(value >> 16);
_bytesCache[_writePos++] = (byte)(value >> 24);
_bytesCache[_writePos++] = (byte)(value >> 32);
_bytesCache[_writePos++] = (byte)(value >> 40);
_bytesCache[_writePos++] = (byte)(value >> 48);
_bytesCache[_writePos++] = (byte)(value >> 56);
}
//Fixed64
public static void WriteFixed64(int fieldNumber, ulong value)
{
WriteHeader(fieldNumber, WireType.Fixed64);
WriteInt64ToBuffer(value);
}
//double
public static void WriteDouble(int fieldNumber, double value)
{
WriteHeader(fieldNumber, WireType.Fixed64);
WriteInt64ToBuffer(MathLib.Double2Ulong(value));
}
//==========[T-L-V]=======
//string
public static void WriteString(int fieldNumber, string value)
{
if (value == null)
{
WriteHeader(fieldNumber, WireType.String);
WriteUInt32Variant(0);
return;
}
int len = value.Length;
if (len == 0)
{
WriteHeader(fieldNumber, WireType.String);
WriteUInt32Variant(0);
return;
}
WriteHeader(fieldNumber, WireType.String);
int predicted = Encoding.GetByteCount(value);
WriteUInt32Variant((uint)predicted);
Encoding.GetBytes(value, 0, value.Length, _bytesCache, _writePos);
_writePos += predicted;
}
//byte[]
public static void WriteBytes(int fieldNumber, byte[] value)
{
if (value == null)
{
return;
}
int len = value.Length;
if (len == 0)
{
WriteHeader(fieldNumber, WireType.String);
WriteUInt32Variant(0);
return;
}
Buffer.BlockCopy(value, 0, _bytesCache, _writePos, len);
_writePos += len;
}
//==================================================[Read]===================================================
//可变长度Variant 32位
private static int Zag(uint ziggedValue)
{
int value = (int)ziggedValue;
return ((value >> 1) & Int32Max) ^ (-(value & 0x01));
}
//可变长度Variant 64位
private static long Zag(ulong ziggedValue)
{
long value = (long)ziggedValue;
return ((value >> 1) & ~Int64Max) ^ (-(value & 0x01L));
}
//初始化重置
public static void InitReadData(byte[] bytes, ref int readPos)
{
_readbytes = bytes;
readPos = 0;
}
//field_number 不能为负数
public static int ReadFieldNumber(ref int readPos)
{
int fieldNumber = 0;
int count = 1;
fieldNumber = (_readbytes[readPos] >> 3) & 0x4F;
while (_readbytes[readPos] >> 7 == 1)
{
fieldNumber |= (_readbytes[++readPos] & 0x7F) << (count++ * 7 - 3);
};
++readPos;
return fieldNumber;
}
//bool
public static bool ReadBoolean(ref int readPos)
{
return _readbytes[readPos++] == 1;
}
//Int32
public static int ReadInt32(ref int readPos)
{
//容错处理
return (int)ReadInt64(ref readPos);
//int result = 0;
//int count = 1;
//result = _readbytes[readPos] & 0x7F;
//while (_readbytes[readPos] >> 7 == 1)
//{
// result |= (_readbytes[++readPos] & 0x7F) << (count++ * 7);
//};
//++readPos;
//if(result < 0)
//{
// Debug.LogError(result +","+readPos);
// DebugBytes(_readbytes);
//}
//return result;
}
//Int64
public static long ReadInt64(ref int readPos)
{
long result = 0;
int count = 1;
result = _readbytes[readPos] & 0x7F;
while (_readbytes[readPos] >> 7 == 1)
{
result |= (long)(_readbytes[++readPos] & 0x7F) << (count++ * 7);
};
++readPos;
return result;
}
//Uint32
public static uint ReadUint32(ref int readPos)
{
uint result = 0;
int count = 1;
result = (uint)(_readbytes[readPos] & 0x7F);
while (_readbytes[readPos] >> 7 == 1)
{
result |= (uint)(_readbytes[++readPos] & 0x7F) << (count++ * 7);
};
++readPos;
return result;
}
//Uint64
public static ulong ReadUint64(ref int readPos)
{
ulong result = 0;
int count = 1;
result = (ulong)(_readbytes[readPos] & 0x7F);
while (_readbytes[readPos] >> 7 == 1)
{
result |= (ulong)(_readbytes[++readPos] & 0x7F) << (count++ * 7);
};
++readPos;
return result;
}
//sint32
public static int ReadSint32(ref int readPos)
{
return Zag(ReadUint32(ref readPos));
}
//sint64
public static long ReadSint64(ref int readPos)
{
return Zag(ReadUint64(ref readPos));
}
//Fixed32
public static uint ReadFixed32(ref int readPos)
{
return (uint)_readbytes[readPos++]
| (uint)_readbytes[readPos++] << 8
| (uint)_readbytes[readPos++] << 16
| (uint)_readbytes[readPos++] << 24;
}
//float
public static float ReadFloat(ref int readPos)
{
uint value = ReadFixed32(ref readPos);
return MathLib.Uint2Float(value);
}
//Fixed64
public static ulong ReadFixed64(ref int readPos)
{
return _readbytes[readPos++]
| (ulong)_readbytes[readPos++] << 8
| (ulong)_readbytes[readPos++] << 16
| (ulong)_readbytes[readPos++] << 24
| (ulong)_readbytes[readPos++] << 32
| (ulong)_readbytes[readPos++] << 40
| (ulong)_readbytes[readPos++] << 48
| (ulong)_readbytes[readPos++] << 56;
}
//double
public static double ReadDouble(ref int readPos)
{
ulong value = ReadFixed64(ref readPos);
return MathLib.Ulong2Double(value);
}
//=================T-L-V
//string
public static string ReadString(ref int readPos)
{
int len = ReadInt32(ref readPos);
if (len == 0)
{
return "";
}
string s = Encoding.GetString(_readbytes, readPos, len);
readPos += len;
return s;
}
//bytes
public static byte[] ReadBytes(ref int readPos)
{
int len = ReadInt32(ref readPos);
if (len == 0)
{
return null;
}
byte[] bytes = new byte[len];
Buffer.BlockCopy(_readbytes, readPos, bytes, 0, len);
readPos += len;
return bytes;
}
public static void DebugBytes()
{
DebugBytes(GetData());
}
public static void DebugBytes(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(bytes[i]);
sb.Append(" ");
}
Debug.Log(sb.ToString());
return;
}
Debug.Log(string.Empty);
}
public static byte[] Serialize(IMessageInfo msg)
{
lock (WriteLocker)
{
InitWriteData();
int headLength = msg.WriteMessage(1) + 1;
var bytes = GetByteArrFormPool(_writePos - headLength);
Buffer.BlockCopy(_bytesCache, headLength, bytes, 0, _writePos - headLength);
return bytes;
}
}
public static void Deserialize(IMessageInfo msg, byte[] bytes)
{
lock (ReadLocker)
{
int readPos = 0;
InitReadData(bytes, ref readPos);
msg.ReadMessage(ref readPos, bytes.Length);
}
}
//子结构体信息
private class SubItemInfo
{
//L: 开始索引
public int LBeginIndex = 0;
//L: 预留长度
public int LCount = 0;
//V: 开始索引
public int VBeginIndex = 0;
//V: 结束索引
public int VEndIndex = 0;
}
//byte数组对象池
private class BytesPool
{
//bytes缓存
public static Dictionary<int, byte[]> _cacheByteDic = new Dictionary<int, byte[]>();
private static int _size = 0;
public static byte[] GetBytes(int length)
{
byte[] bytes = null;
if (!_cacheByteDic.TryGetValue(length, out bytes))
{
return new byte[length];
}
_cacheByteDic.Remove(length);
return bytes;
}
public static void Free(byte[] bytes)
{
if (bytes != null)
{
int length = bytes.Length;
if (_size + length > 1048576)
{
var iter = _cacheByteDic.GetEnumerator();
int maxLength = 0;
while (iter.MoveNext())
{
int itemLength = iter.Current.Value.Length;
if (itemLength > maxLength)
{
maxLength = itemLength;
}
}
_cacheByteDic.Remove(maxLength);
}
if (!_cacheByteDic.ContainsKey(length))
{
_cacheByteDic.Add(length, bytes);
_size += length;
}
}
}
}
}
}