using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
using ProtoBuf;
using Thousandto.Core.Base;
namespace Thousandto.Plugins.Common
{
///
/// ProtoBuf工具
///
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 SubItemInfoDic = new Dictionary(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 _cacheByteDic = new Dictionary();
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;
}
}
}
}
}
}