备份CatanBuilding瘦身独立工程
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
namespace com.fpnn.msgpack
|
||||
{
|
||||
public class MsgPackException: Exception
|
||||
{
|
||||
public MsgPackException(string message) : base(message) { }
|
||||
public MsgPackException(String message, Exception ex) : base(message, ex) { }
|
||||
}
|
||||
|
||||
public class UnsupportedTypeException : MsgPackException
|
||||
{
|
||||
public UnsupportedTypeException(string message) : base(message) { }
|
||||
static public UnsupportedTypeException Create(Object obj)
|
||||
{
|
||||
string typeFullName = obj.GetType().FullName;
|
||||
return new UnsupportedTypeException("FPNN MsgPacker unsupported type: " + typeFullName);
|
||||
}
|
||||
}
|
||||
|
||||
public class UnrecognizedDataException : MsgPackException
|
||||
{
|
||||
public UnrecognizedDataException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public class InsufficientException : MsgPackException
|
||||
{
|
||||
public InsufficientException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public class InvalidDataException : MsgPackException
|
||||
{
|
||||
public InvalidDataException(string message) : base(message) { }
|
||||
public InvalidDataException(string message, Exception ex) : base(message, ex) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cbd313282dcd4053aa29bb130a65452
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,566 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace com.fpnn.msgpack
|
||||
{
|
||||
public static class MsgPacker
|
||||
{
|
||||
public delegate void PackItem(Stream stream, Object obj);
|
||||
|
||||
private static readonly Dictionary<string, PackItem> _packDict;
|
||||
|
||||
static MsgPacker()
|
||||
{
|
||||
_packDict = new Dictionary<string, PackItem>
|
||||
{
|
||||
{ "System.Boolean", PackBoolean },
|
||||
|
||||
{ "System.Decimal", PackDecimal },
|
||||
{ "System.Double", PackDouble },
|
||||
{ "System.Single", PackFloat },
|
||||
|
||||
{ "System.SByte", PackInteger },
|
||||
{ "System.Int16", PackInteger },
|
||||
{ "System.Int32", PackInteger },
|
||||
{ "System.Int64", PackInteger },
|
||||
|
||||
{ "System.Byte", PackUInteger },
|
||||
{ "System.Char", PackUInteger },
|
||||
{ "System.UInt16", PackUInteger },
|
||||
{ "System.UInt32", PackUInteger },
|
||||
{ "System.UInt64", PackUInteger },
|
||||
|
||||
{ "System.String", PackString },
|
||||
{ "System.Tuple", PackTuple },
|
||||
{ "System.DateTime", PackTimestamp },
|
||||
{ "System.Byte[]", PackBinary }
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* May throw exception in UnsupportedTypeException type.
|
||||
*/
|
||||
static public void Pack(Stream stream, Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
PackNull(stream);
|
||||
return;
|
||||
}
|
||||
|
||||
string typeFullName = obj.GetType().FullName;
|
||||
int idx = typeFullName.IndexOf('`');
|
||||
if (idx != -1)
|
||||
{
|
||||
typeFullName = typeFullName.Substring(0, idx);
|
||||
}
|
||||
|
||||
if (_packDict.TryGetValue(typeFullName, out PackItem packer))
|
||||
{
|
||||
packer(stream, obj);
|
||||
}
|
||||
else if (obj is IEnumerable)
|
||||
{
|
||||
PackIEnumerable(stream, obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw UnsupportedTypeException.Create(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackNull(Stream stream)
|
||||
{
|
||||
byte sign = 0xc0;
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
|
||||
static public void PackBoolean(Stream stream, Object obj)
|
||||
{
|
||||
Boolean v = (bool)obj;
|
||||
if (v)
|
||||
{
|
||||
byte sign = 0xc3;
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte sign = 0xc2;
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackInteger(Stream stream, Object obj)
|
||||
{
|
||||
Int64 value = (Int64)Convert.ChangeType(obj, TypeCode.Int64);
|
||||
|
||||
if (value >= 0)
|
||||
{
|
||||
PackUInteger(stream, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((0xFFFFFFFFFFFFFFE0 & (UInt64)value) == 0xFFFFFFFFFFFFFFE0)
|
||||
{
|
||||
sbyte sbyteValue = (sbyte)value;
|
||||
stream.WriteByte((byte)sbyteValue);
|
||||
}
|
||||
else if ((0xFFFFFFFFFFFFFF80 & (UInt64)value) == 0xFFFFFFFFFFFFFF80)
|
||||
{
|
||||
sbyte sbyteValue = (sbyte)value;
|
||||
|
||||
byte sign = 0xd0;
|
||||
stream.WriteByte(sign);
|
||||
stream.WriteByte((byte)sbyteValue);
|
||||
}
|
||||
else if ((0xFFFFFFFFFFFF8000 & (UInt64)value) == 0xFFFFFFFFFFFF8000)
|
||||
{
|
||||
short shortValue = (short)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xd1;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else if ((0xFFFFFFFF80000000 & (UInt64)value) == 0xFFFFFFFF80000000)
|
||||
{
|
||||
Int32 int32Value = (Int32)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(int32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xd2;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Int64 int64Value = (Int64)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(int64Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xd3;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackUInteger(Stream stream, Object obj)
|
||||
{
|
||||
UInt64 value = (UInt64)Convert.ChangeType(obj, TypeCode.UInt64);
|
||||
|
||||
if (value <= 127)
|
||||
{
|
||||
byte byteValue = (byte)value;
|
||||
stream.WriteByte(byteValue);
|
||||
}
|
||||
else if (value <= 0xFF)
|
||||
{
|
||||
byte sign = 0xcc;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
byte byteValue = (byte)value;
|
||||
stream.WriteByte(byteValue);
|
||||
}
|
||||
else if (value <= 0xFFFF)
|
||||
{
|
||||
ushort shortValue = (ushort)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xcd;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else if (value <= 0xFFFFFFFF)
|
||||
{
|
||||
UInt32 uint32Value = (UInt32)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xce;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 uint64Value = (UInt64)value;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint64Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xcf;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackFloat(Stream stream, Object obj)
|
||||
{
|
||||
//-- float in C# memory already is IEEE 754
|
||||
|
||||
float value = (float)obj;
|
||||
byte[] byteArray = BitConverter.GetBytes(value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(byteArray);
|
||||
|
||||
byte sign = 0xca;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(byteArray, 0, 4);
|
||||
}
|
||||
|
||||
static public void PackDouble(Stream stream, Object obj)
|
||||
{
|
||||
//-- double in C# memory already is IEEE 754
|
||||
|
||||
double value = (double)obj;
|
||||
byte[] byteArray = BitConverter.GetBytes(value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(byteArray);
|
||||
|
||||
byte sign = 0xcb;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(byteArray, 0, 8);
|
||||
}
|
||||
|
||||
static public void PackDecimal(Stream stream, Object obj)
|
||||
{
|
||||
Decimal dec = (Decimal)obj;
|
||||
double value = Decimal.ToDouble(dec);
|
||||
|
||||
PackDouble(stream, value);
|
||||
}
|
||||
|
||||
static public void PackString(Stream stream, Object obj)
|
||||
{
|
||||
string stringValue = (string)obj;
|
||||
|
||||
UTF8Encoding utf8Encoding = new UTF8Encoding(); //-- NO BOM.
|
||||
byte[] rawData = utf8Encoding.GetBytes(stringValue);
|
||||
|
||||
if (rawData.Length <= 31)
|
||||
{
|
||||
byte sign = (byte)(rawData.Length | 0xA0);
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
else if (rawData.Length <= 255)
|
||||
{
|
||||
byte sign = 0xd9;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
byte lengthByte = (byte)rawData.Length;
|
||||
stream.WriteByte(lengthByte);
|
||||
}
|
||||
else if (rawData.Length <= 65535)
|
||||
{
|
||||
byte sign = 0xda;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
ushort shortValue = (ushort)rawData.Length;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte sign = 0xdb;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
UInt32 uint32Value = (UInt32)rawData.Length;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
|
||||
stream.Write(rawData, 0, rawData.Length);
|
||||
}
|
||||
|
||||
static public void PackBinary(Stream stream, Object obj)
|
||||
{
|
||||
byte[] binaryData = (byte[])obj;
|
||||
|
||||
if (binaryData.Length <= 255)
|
||||
{
|
||||
byte sign = 0xc4;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
byte lengthByte = (byte)binaryData.Length;
|
||||
stream.WriteByte(lengthByte);
|
||||
}
|
||||
else if (binaryData.Length <= 65535)
|
||||
{
|
||||
byte sign = 0xc5;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
ushort shortValue = (ushort)binaryData.Length;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte sign = 0xc6;
|
||||
stream.WriteByte(sign);
|
||||
|
||||
UInt32 uint32Value = (UInt32)binaryData.Length;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
|
||||
stream.Write(binaryData, 0, binaryData.Length);
|
||||
}
|
||||
|
||||
static public void PackArray(Stream stream, Object obj)
|
||||
{
|
||||
IEnumerable ie = (IEnumerable)obj;
|
||||
IEnumerator it = ie.GetEnumerator();
|
||||
it.Reset();
|
||||
|
||||
int count = 0;
|
||||
|
||||
while (it.MoveNext())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count <= 15)
|
||||
{
|
||||
byte sign = (byte)(count | 0x90);
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
else if (count <= 65535)
|
||||
{
|
||||
ushort shortValue = (ushort)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xdc;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 uint32Value = (UInt32)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xdd;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
|
||||
it.Reset();
|
||||
|
||||
while (it.MoveNext())
|
||||
{
|
||||
Object o = it.Current;
|
||||
Pack(stream, o);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackDictionary(Stream stream, Object obj)
|
||||
{
|
||||
IEnumerable ie = (IEnumerable)obj;
|
||||
IEnumerator it = ie.GetEnumerator();
|
||||
it.Reset();
|
||||
|
||||
int count = 0;
|
||||
|
||||
while (it.MoveNext())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count <= 15)
|
||||
{
|
||||
byte sign = (byte)(count | 0x80);
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
else if (count <= 65535)
|
||||
{
|
||||
ushort shortValue = (ushort)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xde;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 uint32Value = (UInt32)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xdf;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
|
||||
it.Reset();
|
||||
IDictionaryEnumerator id = (IDictionaryEnumerator)it;
|
||||
while (it.MoveNext())
|
||||
{
|
||||
Object k = id.Key;
|
||||
Pack(stream, k);
|
||||
|
||||
Object v = id.Value;
|
||||
Pack(stream, v);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackTimestamp(Stream stream, Object obj)
|
||||
{
|
||||
DateTime userDate = (DateTime)obj;
|
||||
DateTime utcUserDate = userDate.ToUniversalTime();
|
||||
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
TimeSpan diff = utcUserDate - origin;
|
||||
Int64 seconds = (Int64)Math.Floor(diff.TotalSeconds);
|
||||
Int64 milliseconds = (Int64)Math.Floor(diff.TotalMilliseconds);
|
||||
Int64 nonaseconds = (milliseconds - seconds * 1000) * 1000 * 1000;
|
||||
|
||||
if (nonaseconds == 0 && ((UInt64)seconds >> 32) == 0)
|
||||
{
|
||||
UInt32 secondsValue = (UInt32)seconds;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(secondsValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xd6;
|
||||
stream.WriteByte(sign);
|
||||
sbyte type = -1;
|
||||
stream.WriteByte((byte)type);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
else if (((UInt64)seconds >> 34) == 0)
|
||||
{
|
||||
UInt64 rawData = ((UInt64)nonaseconds << 34) | (UInt64)seconds;
|
||||
byte[] byteArray = BitConverter.GetBytes(rawData);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(byteArray);
|
||||
|
||||
byte sign = 0xd7;
|
||||
stream.WriteByte(sign);
|
||||
sbyte type = -1;
|
||||
stream.WriteByte((byte)type);
|
||||
stream.Write(byteArray, 0, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 nanos = (UInt32)nonaseconds;
|
||||
byte[] secondsBytes = BitConverter.GetBytes(seconds);
|
||||
byte[] nanosBytes = BitConverter.GetBytes(nanos);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(secondsBytes);
|
||||
Array.Reverse(nanosBytes);
|
||||
}
|
||||
|
||||
byte sign = 0xc7;
|
||||
stream.WriteByte(sign);
|
||||
sign = 12;
|
||||
stream.WriteByte(sign);
|
||||
sbyte type = -1;
|
||||
stream.WriteByte((byte)type);
|
||||
stream.Write(nanosBytes, 0, 4);
|
||||
stream.Write(secondsBytes, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackTuple(Stream stream, Object obj)
|
||||
{
|
||||
Type objType = obj.GetType();
|
||||
var props = objType.GetProperties();
|
||||
int count = props.Length;
|
||||
|
||||
if (count <= 15)
|
||||
{
|
||||
byte sign = (byte)(count | 0x90);
|
||||
stream.WriteByte(sign);
|
||||
}
|
||||
else if (count <= 65535)
|
||||
{
|
||||
ushort shortValue = (ushort)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(shortValue);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xdc;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 uint32Value = (UInt32)count;
|
||||
byte[] lenBuffer = BitConverter.GetBytes(uint32Value);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(lenBuffer);
|
||||
|
||||
byte sign = 0xdd;
|
||||
stream.WriteByte(sign);
|
||||
stream.Write(lenBuffer, 0, 4);
|
||||
}
|
||||
|
||||
foreach (System.Reflection.PropertyInfo prop in props)
|
||||
{
|
||||
Object subObj = prop.GetValue(obj, null);
|
||||
Pack(stream, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static public void PackIEnumerable(Stream stream, Object obj)
|
||||
{
|
||||
IEnumerable ie = (IEnumerable)obj;
|
||||
IEnumerator it = ie.GetEnumerator();
|
||||
it.Reset();
|
||||
|
||||
if (it is IDictionaryEnumerator)
|
||||
PackDictionary(stream, obj);
|
||||
else
|
||||
PackArray(stream, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90c2b19d237af4d54ab342ee0ce9ecb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,868 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace com.fpnn.msgpack
|
||||
{
|
||||
public static class MsgUnpacker
|
||||
{
|
||||
public static Dictionary<Object, Object> Unpack(byte[] binary)
|
||||
{
|
||||
return Unpack(binary, 0);
|
||||
}
|
||||
|
||||
public static Dictionary<Object, Object> Unpack(byte[] binary, int offset, int length = 0)
|
||||
{
|
||||
SAXInfo info = new SAXInfo(binary)
|
||||
{
|
||||
currIdx = offset
|
||||
};
|
||||
|
||||
int endIndx = info.binary.Length;
|
||||
if (length > 0)
|
||||
endIndx = Math.Min(offset + length, info.binary.Length);
|
||||
|
||||
try
|
||||
{
|
||||
while (endIndx > info.currIdx)
|
||||
{
|
||||
UnpackNext(info);
|
||||
}
|
||||
}
|
||||
catch (ArgumentOutOfRangeException e)
|
||||
{
|
||||
throw new InvalidDataException("Incomplete msgPack binary data.", e);
|
||||
}
|
||||
|
||||
if (info.GetRootObject() is Dictionary<Object, Object> dict)
|
||||
return dict;
|
||||
|
||||
throw new InvalidDataException("MsgPack binary is not dictionary.");
|
||||
}
|
||||
|
||||
public static Object Unpack(byte[] binary, int offset, out int endOffset)
|
||||
{
|
||||
if (binary == null || binary.Length == 0)
|
||||
throw new InvalidDataException("MsgPack binary is empty.");
|
||||
|
||||
SAXInfo info = new SAXInfo(binary)
|
||||
{
|
||||
currIdx = offset
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
UnpackNext(info);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException e)
|
||||
{
|
||||
throw new InvalidDataException("Incomplete msgPack binary data.", e);
|
||||
}
|
||||
|
||||
endOffset = info.currIdx;
|
||||
|
||||
return info.GetRootObject();
|
||||
}
|
||||
|
||||
//------------[ Private Methods ]-----------//
|
||||
|
||||
private class ContainerInfo
|
||||
{
|
||||
private Dictionary<object, object> dict;
|
||||
private List<object> list;
|
||||
private object key;
|
||||
private bool wantKey;
|
||||
|
||||
public ContainerInfo(bool isDictionary, int capacity)
|
||||
{
|
||||
if (isDictionary)
|
||||
{
|
||||
dict = new Dictionary<object, object>(capacity);
|
||||
wantKey = true;
|
||||
}
|
||||
else
|
||||
list = new List<object>(capacity);
|
||||
}
|
||||
|
||||
public Object GetContainer()
|
||||
{
|
||||
if (dict != null)
|
||||
{
|
||||
if (wantKey == false)
|
||||
throw new InsufficientException("Invalid msgPack binary: dictionary lost value.");
|
||||
return dict;
|
||||
}
|
||||
else
|
||||
return list;
|
||||
}
|
||||
|
||||
public void Add(Object obj)
|
||||
{
|
||||
if (dict != null)
|
||||
{
|
||||
if (wantKey)
|
||||
{
|
||||
key = obj;
|
||||
wantKey = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dict.Add(key, obj);
|
||||
wantKey = true;
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SAXInfo
|
||||
{
|
||||
private Stack<ContainerInfo> containerStack;
|
||||
private object rootbject;
|
||||
//-- public fields
|
||||
public readonly byte[] binary;
|
||||
public int currIdx;
|
||||
|
||||
public SAXInfo(byte[] binary)
|
||||
{
|
||||
containerStack = new Stack<ContainerInfo>();
|
||||
this.binary = binary;
|
||||
currIdx = 0;
|
||||
}
|
||||
|
||||
public void Add(object obj)
|
||||
{
|
||||
if (containerStack.Count > 0)
|
||||
{
|
||||
containerStack.Peek().Add(obj);
|
||||
}
|
||||
else if (rootbject == null)
|
||||
{
|
||||
rootbject = obj;
|
||||
}
|
||||
else
|
||||
throw new InvalidDataException("MsgPack binary has parallel roots.");
|
||||
}
|
||||
|
||||
public void AddContainer(ContainerInfo container)
|
||||
{
|
||||
Add(container.GetContainer());
|
||||
containerStack.Push(container);
|
||||
}
|
||||
|
||||
public void PopContainer()
|
||||
{
|
||||
containerStack.Pop();
|
||||
}
|
||||
|
||||
public Object GetRootObject()
|
||||
{
|
||||
if (containerStack.Count > 0)
|
||||
throw new InsufficientException("Invalid msgPack binary: insufficient binary data.");
|
||||
|
||||
return rootbject;
|
||||
}
|
||||
}
|
||||
|
||||
private delegate void UnpackItem(SAXInfo info);
|
||||
|
||||
private static readonly Dictionary<byte, UnpackItem> _unpackDict;
|
||||
|
||||
static MsgUnpacker()
|
||||
{
|
||||
_unpackDict = new Dictionary<byte, UnpackItem>
|
||||
{
|
||||
{ 0xc0, UnpackNil },
|
||||
// { 0xc1, UnpackData }, //-- (never used) in msgpack SPEC: https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||
{ 0xc2, UnpackFalse },
|
||||
{ 0xc3, UnpackTrue },
|
||||
|
||||
{ 0xc4, UnpackBin8 },
|
||||
{ 0xc5, UnpackBin16 },
|
||||
{ 0xc6, UnpackBin32 },
|
||||
{ 0xc7, UnpackExt8 },
|
||||
|
||||
{ 0xc8, UnpackExt16 },
|
||||
{ 0xc9, UnpackExt32 },
|
||||
{ 0xca, UnpackFloat32 },
|
||||
{ 0xcb, UnpackFloat64 },
|
||||
|
||||
{ 0xcc, UnpackUInt8 },
|
||||
{ 0xcd, UnpackUInt16 },
|
||||
{ 0xce, UnpackUInt32 },
|
||||
{ 0xcf, UnpackUInt64 },
|
||||
|
||||
{ 0xd0, UnpackInt8 },
|
||||
{ 0xd1, UnpackInt16 },
|
||||
{ 0xd2, UnpackInt32 },
|
||||
{ 0xd3, UnpackInt64 },
|
||||
|
||||
{ 0xd4, UnpackFixExt1 },
|
||||
{ 0xd5, UnpackFixExt2 },
|
||||
{ 0xd6, UnpackFixExt4 },
|
||||
{ 0xd7, UnpackFixExt8 },
|
||||
|
||||
{ 0xd8, UnpackFixExt16 },
|
||||
{ 0xd9, UnpackStr8 },
|
||||
{ 0xda, UnpackStr16 },
|
||||
{ 0xdb, UnpackStr32 },
|
||||
|
||||
{ 0xdc, UnpackArray16 },
|
||||
{ 0xdd, UnpackArray32 },
|
||||
{ 0xde, UnpackMap16 },
|
||||
{ 0xdf, UnpackMap32 },
|
||||
};
|
||||
}
|
||||
|
||||
private static void UnpackNext(SAXInfo info)
|
||||
{
|
||||
byte sign = info.binary[info.currIdx];
|
||||
info.currIdx++;
|
||||
|
||||
if (_unpackDict.TryGetValue(sign, out UnpackItem unpacker))
|
||||
{
|
||||
unpacker(info);
|
||||
}
|
||||
else if (sign <= 0x7f)
|
||||
{
|
||||
UnpackPositiveFixInt(info);
|
||||
}
|
||||
else if (sign <= 0x8f)
|
||||
{
|
||||
UnpackFixMap(info);
|
||||
}
|
||||
else if (sign <= 0x9f)
|
||||
{
|
||||
UnpackFixArray(info);
|
||||
}
|
||||
else if (sign <= 0xbf)
|
||||
{
|
||||
UnpackFixStr(info);
|
||||
}
|
||||
else if (sign <= 0xff)
|
||||
{
|
||||
UnpackNegativeFixInt(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnrecognizedDataException("Msgpack first byte: 0x" + sign.ToString("X2"));
|
||||
}
|
||||
}
|
||||
|
||||
//------------[ Delegate Methods ]-----------//
|
||||
|
||||
private static void UnpackNil(SAXInfo info)
|
||||
{
|
||||
info.Add(null);
|
||||
}
|
||||
|
||||
private static void UnpackFalse(SAXInfo info)
|
||||
{
|
||||
info.Add(false);
|
||||
}
|
||||
|
||||
private static void UnpackTrue(SAXInfo info)
|
||||
{
|
||||
info.Add(true);
|
||||
}
|
||||
|
||||
private static void UnpackBin8(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx];
|
||||
info.currIdx++;
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(info.binary, info.currIdx, data, 0, length);
|
||||
info.currIdx += length;
|
||||
|
||||
info.Add(data);
|
||||
}
|
||||
|
||||
private static void UnpackBin16(SAXInfo info)
|
||||
{
|
||||
ushort length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(info.binary, info.currIdx, data, 0, length);
|
||||
info.currIdx += length;
|
||||
|
||||
info.Add(data);
|
||||
}
|
||||
|
||||
private static void UnpackBin32(SAXInfo info)
|
||||
{
|
||||
UInt32 length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(info.binary, info.currIdx, data, 0, length);
|
||||
info.currIdx += (int)length;
|
||||
|
||||
info.Add(data);
|
||||
}
|
||||
|
||||
private static void UnpackExt8(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx];
|
||||
sbyte type = (sbyte)info.binary[info.currIdx + 1];
|
||||
|
||||
if (length != 12 || type != -1)
|
||||
throw new UnsupportedTypeException("Unsupported msgPack ext8 format. type " + type + ", data length: " + length);
|
||||
|
||||
info.currIdx += 2;
|
||||
|
||||
byte[] secondsBuffer = new byte[8];
|
||||
byte[] nanosecondsBuffer = new byte[4];
|
||||
|
||||
Array.Copy(info.binary, info.currIdx, nanosecondsBuffer, 0, 4);
|
||||
Array.Copy(info.binary, info.currIdx + 4, secondsBuffer, 0, 8);
|
||||
info.currIdx += 12;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(secondsBuffer);
|
||||
Array.Reverse(nanosecondsBuffer);
|
||||
}
|
||||
|
||||
UInt32 nanoseconds = BitConverter.ToUInt32(nanosecondsBuffer, 0);
|
||||
Int64 seconds = BitConverter.ToInt64(secondsBuffer, 0);
|
||||
|
||||
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
TimeSpan offset = new TimeSpan(seconds * 1000 * 1000 * 10 + nanoseconds / 100);
|
||||
|
||||
info.Add(origin.Add(offset));
|
||||
}
|
||||
|
||||
private static void UnpackExt16(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx + 2];
|
||||
throw new UnsupportedTypeException("Unsupported msgPack ext16 format. type " + type);
|
||||
}
|
||||
|
||||
private static void UnpackExt32(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx + 4];
|
||||
throw new UnsupportedTypeException("Unsupported msgPack ext32 format. type " + type);
|
||||
}
|
||||
|
||||
private static void UnpackFloat32(SAXInfo info)
|
||||
{
|
||||
//-- float in C# memory already is IEEE 754
|
||||
|
||||
float value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToSingle(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToSingle(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackFloat64(SAXInfo info)
|
||||
{
|
||||
//-- float in C# memory already is IEEE 754
|
||||
|
||||
double value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[8];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 8);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToDouble(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToDouble(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 8;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackUInt8(SAXInfo info)
|
||||
{
|
||||
byte value = info.binary[info.currIdx];
|
||||
info.currIdx++;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackUInt16(SAXInfo info)
|
||||
{
|
||||
ushort value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToUInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToUInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackUInt32(SAXInfo info)
|
||||
{
|
||||
UInt32 value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackUInt64(SAXInfo info)
|
||||
{
|
||||
UInt64 value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[8];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 8);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToUInt64(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToUInt64(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 8;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackInt8(SAXInfo info)
|
||||
{
|
||||
sbyte value = (sbyte)info.binary[info.currIdx];
|
||||
info.currIdx++;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackInt16(SAXInfo info)
|
||||
{
|
||||
short value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackInt32(SAXInfo info)
|
||||
{
|
||||
Int32 value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackInt64(SAXInfo info)
|
||||
{
|
||||
Int64 value;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[8];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 8);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
value = BitConverter.ToInt64(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = BitConverter.ToInt64(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 8;
|
||||
|
||||
info.Add(value);
|
||||
}
|
||||
|
||||
private static void UnpackFixExt1(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx];
|
||||
throw new UnsupportedTypeException("Unsupported msgPack fix ext 1 format. type " + type);
|
||||
}
|
||||
private static void UnpackFixExt2(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx];
|
||||
throw new UnsupportedTypeException("Unsupported msgPack fix ext 2 format. type " + type);
|
||||
}
|
||||
private static void UnpackFixExt4(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx];
|
||||
if (type != -1)
|
||||
throw new UnsupportedTypeException("Unsupported msgPack fix ext 4 format. type " + type);
|
||||
|
||||
info.currIdx++;
|
||||
|
||||
|
||||
UInt32 seconds;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
seconds = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
seconds = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
|
||||
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
TimeSpan offset = new TimeSpan(seconds * 1000 * 1000 * 10);
|
||||
|
||||
info.Add(origin.Add(offset));
|
||||
}
|
||||
private static void UnpackFixExt8(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx];
|
||||
if (type != -1)
|
||||
throw new UnsupportedTypeException("Unsupported msgPack fix ext 8 format. type " + type);
|
||||
|
||||
info.currIdx++;
|
||||
|
||||
|
||||
UInt64 timeValue;
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[8];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 8);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
timeValue = BitConverter.ToUInt64(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeValue = BitConverter.ToUInt64(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 8;
|
||||
|
||||
|
||||
UInt32 nanoseconds = (UInt32)(timeValue >> 34);
|
||||
Int64 seconds = (Int64)(timeValue & 0x00000003FFFFFFFF);
|
||||
|
||||
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
TimeSpan offset = new TimeSpan(seconds * 1000 * 1000 * 10 + nanoseconds / 100);
|
||||
|
||||
info.Add(origin.Add(offset));
|
||||
}
|
||||
private static void UnpackFixExt16(SAXInfo info)
|
||||
{
|
||||
sbyte type = (sbyte)info.binary[info.currIdx];
|
||||
throw new UnsupportedTypeException("Unsupported msgPack fix ext 16 format. type " + type);
|
||||
}
|
||||
|
||||
private static void UnpackString(SAXInfo info, int length)
|
||||
{
|
||||
UTF8Encoding utf8Encoding = new UTF8Encoding(false, true); //-- NO BOM.
|
||||
try
|
||||
{
|
||||
string str = utf8Encoding.GetString(info.binary, info.currIdx, length);
|
||||
info.currIdx += length;
|
||||
info.Add(str);
|
||||
return;
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
catch (ArgumentOutOfRangeException ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
catch (DecoderFallbackException)
|
||||
{
|
||||
//-- Do nothing, through the cache block.
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
//-- Do nothing, through the cache block.
|
||||
}
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(info.binary, info.currIdx, data, 0, length);
|
||||
info.currIdx += length;
|
||||
info.Add(data);
|
||||
}
|
||||
private static void UnpackStr8(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx];
|
||||
info.currIdx++;
|
||||
|
||||
UnpackString(info, length);
|
||||
}
|
||||
private static void UnpackStr16(SAXInfo info)
|
||||
{
|
||||
ushort length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
UnpackString(info, length);
|
||||
}
|
||||
private static void UnpackStr32(SAXInfo info)
|
||||
{
|
||||
UInt32 length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
UnpackString(info, (int)length);
|
||||
}
|
||||
private static void UnpackArray16(SAXInfo info)
|
||||
{
|
||||
ushort length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(false, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (ushort i = 0; i < length; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
private static void UnpackArray32(SAXInfo info)
|
||||
{
|
||||
UInt32 length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(false, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (UInt32 i = 0; i < length; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
|
||||
private static void UnpackMap16(SAXInfo info)
|
||||
{
|
||||
ushort length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[2];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 2);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt16(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt16(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 2;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(true, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (UInt32 i = 0; i < length * 2; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
private static void UnpackMap32(SAXInfo info)
|
||||
{
|
||||
UInt32 length;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
byte[] lengthBuffer = new byte[4];
|
||||
Array.Copy(info.binary, info.currIdx, lengthBuffer, 0, 4);
|
||||
Array.Reverse(lengthBuffer);
|
||||
|
||||
length = BitConverter.ToUInt32(lengthBuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = BitConverter.ToUInt32(info.binary, info.currIdx);
|
||||
}
|
||||
info.currIdx += 4;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(true, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (UInt32 i = 0; i < length * 2; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
private static void UnpackPositiveFixInt(SAXInfo info)
|
||||
{
|
||||
sbyte value = (sbyte)info.binary[info.currIdx - 1];
|
||||
info.Add(value);
|
||||
}
|
||||
private static void UnpackFixMap(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx - 1];
|
||||
length &= 0x0F;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(true, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (ushort i = 0; i < length * 2; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
private static void UnpackFixArray(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx - 1];
|
||||
length &= 0x0F;
|
||||
|
||||
ContainerInfo container = new ContainerInfo(false, (int)length);
|
||||
info.AddContainer(container);
|
||||
|
||||
for (byte i = 0; i < length; i++)
|
||||
UnpackNext(info);
|
||||
|
||||
info.PopContainer();
|
||||
}
|
||||
private static void UnpackFixStr(SAXInfo info)
|
||||
{
|
||||
byte length = info.binary[info.currIdx - 1];
|
||||
length &= 0x1F;
|
||||
|
||||
UnpackString(info, length);
|
||||
}
|
||||
private static void UnpackNegativeFixInt(SAXInfo info)
|
||||
{
|
||||
byte value = info.binary[info.currIdx - 1];
|
||||
info.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9de0a1029a27403da718c42c6440c19
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
## FPNN MsgPack Implement
|
||||
|
||||
* **[msgpack SPEC](https://github.com/msgpack/msgpack/blob/master/spec.md)**
|
||||
* **[Project Home](https://github.com/highras/msgpack-csharp)**
|
||||
|
||||
### Compatibility Version:
|
||||
|
||||
C# .Net Standard 2.0
|
||||
|
||||
### For Packer:
|
||||
|
||||
* input kinds:
|
||||
|
||||
null, bool, sbyte, byte, short, ushort, Int32, UInt32, Int64, Uint64, float, double, string
|
||||
|
||||
Decimal, Tuple
|
||||
|
||||
byte[], DateTime, IEnumerable (such as List, Dictionary, List\<object\>, Dictionary\<object, object\>, ...)
|
||||
|
||||
* usage:
|
||||
|
||||
using com.fpnn.msgpack;
|
||||
void MsgPacker.Pack(Stream stream, Object obj);
|
||||
|
||||
|
||||
### For Unpacker:
|
||||
|
||||
* output kinds:
|
||||
|
||||
Object, which maybe the following kinds:
|
||||
|
||||
null, bool, sbyte, byte, short, ushort, Int32, UInt32, Int64, Uint64, float, double, string
|
||||
|
||||
byte[], DateTime, List\<object\>, Dictionary\<object, object\>
|
||||
|
||||
* usage:
|
||||
|
||||
using com.fpnn.msgpack;
|
||||
Dictionary<Object, Object> MsgUnpacker.Unpack(byte[] binary);
|
||||
|
||||
Dictionary<Object, Object> MsgUnpacker.Unpack(byte[] binary, int offset, int length = 0);
|
||||
|
||||
//-- unpack one object.
|
||||
Object MsgUnpacker.Unpack(byte[] binary, int offset, out int endOffset);
|
||||
|
||||
|
||||
### Exception:
|
||||
|
||||
using com.fpnn.msgpack;
|
||||
public class MsgPackException: Exception;
|
||||
public class UnsupportedTypeException : MsgPackException;
|
||||
public class UnrecognizedDataException : MsgPackException;
|
||||
public class InsufficientException : MsgPackException;
|
||||
public class InvalidDataException : MsgPackException;
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 730f8ecda09534c29b067b8300af136b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user