mirror of
https://github.com/BtbN/ClanServer.git
synced 2026-09-08 00:15:14 -05:00
Refactoring
This commit is contained in:
@@ -77,7 +77,6 @@ namespace eAmuseCore.KBinXML
|
||||
throw new ArgumentException("Invalid signature", "input");
|
||||
input = input.Skip(1);
|
||||
|
||||
bool compressed;
|
||||
switch (input.FirstU8())
|
||||
{
|
||||
case SIG_COMPRESSED:
|
||||
@@ -100,20 +99,98 @@ namespace eAmuseCore.KBinXML
|
||||
|
||||
encoding = GetEncoding(encodingSig);
|
||||
|
||||
uint nodeEnd = input.FirstU32();
|
||||
int nodeSize = input.FirstS32();
|
||||
input = input.Skip(4);
|
||||
|
||||
IEnumerable<byte> nodeBuf = input.Take((int)nodeEnd);
|
||||
IEnumerable<byte> dataBuf = input.Skip((int)nodeEnd);
|
||||
nodeBuf = input.Take(nodeSize);
|
||||
dataBuf = input.Skip(nodeSize);
|
||||
dataByteBuf = dataWordBuf = Enumerable.Empty<byte>();
|
||||
|
||||
ParseNodes(nodeBuf, dataBuf, compressed);
|
||||
ParseNodes();
|
||||
}
|
||||
|
||||
private void ParseNodes(IEnumerable<byte> nodeBuf, IEnumerable<byte> dataBuf, bool compressed)
|
||||
{
|
||||
IEnumerable<byte> dataByteBuf = Enumerable.Empty<byte>();
|
||||
IEnumerable<byte> dataWordBuf = Enumerable.Empty<byte>();
|
||||
private IEnumerable<byte> nodeBuf = Enumerable.Empty<byte>(), dataBuf = Enumerable.Empty<byte>();
|
||||
private IEnumerable<byte> dataByteBuf = Enumerable.Empty<byte>(), dataWordBuf = Enumerable.Empty<byte>();
|
||||
bool compressed = false;
|
||||
|
||||
IEnumerable<byte> TakeDataAligned(int size, bool isArray)
|
||||
{
|
||||
if (size <= 0)
|
||||
{
|
||||
return Enumerable.Empty<byte>();
|
||||
}
|
||||
else if (size == 1 && !isArray)
|
||||
{
|
||||
if (!dataByteBuf.Any())
|
||||
{
|
||||
dataByteBuf = dataBuf;
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
}
|
||||
var res = dataByteBuf.Take(1);
|
||||
dataByteBuf = dataByteBuf.Skip(1);
|
||||
return res;
|
||||
}
|
||||
else if (size == 2 && !isArray)
|
||||
{
|
||||
if (!dataWordBuf.Any())
|
||||
{
|
||||
dataWordBuf = dataBuf;
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
}
|
||||
var res = dataWordBuf.Take(2);
|
||||
dataWordBuf = dataWordBuf.Skip(2);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EnumHelpers.TakeBytesAligned(ref dataBuf, size);
|
||||
}
|
||||
}
|
||||
|
||||
void SetNodeValue(XElement node, IEnumerable<byte> data, KValueAttribute nodeAttrs, int varCount, int arrCount)
|
||||
{
|
||||
if (nodeAttrs.NodeType == XmlTypes.XmlTypes.BinType)
|
||||
{
|
||||
node.SetAttributeValue("__size", varCount);
|
||||
node.SetValue(XmlTypes.Bin.FromBytes(data));
|
||||
}
|
||||
else if (nodeAttrs.NodeType == XmlTypes.XmlTypes.StrType)
|
||||
{
|
||||
node.SetValue(XmlTypes.Str.FromBytes(data, encoding));
|
||||
}
|
||||
else
|
||||
{
|
||||
node.SetValue(XmlTypes.XmlTypes.MakeNodeFromBytes(nodeAttrs, arrCount, data));
|
||||
}
|
||||
}
|
||||
|
||||
private string GetNodeName(byte nodeType)
|
||||
{
|
||||
if (nodeType != XmlTypes.XmlTypes.NodeEndType && nodeType != XmlTypes.XmlTypes.SectionEndType)
|
||||
{
|
||||
if (compressed)
|
||||
{
|
||||
return SixBit.Unpack(ref nodeBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = (nodeBuf.First() & ~64) + 1;
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
byte[] nameBytes = nodeBuf.Take(length).ToArray();
|
||||
nodeBuf = nodeBuf.Skip(length);
|
||||
|
||||
return encoding.GetString(nameBytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseNodes()
|
||||
{
|
||||
uint dataSize = dataBuf.FirstU32();
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
|
||||
@@ -131,24 +208,7 @@ namespace eAmuseCore.KBinXML
|
||||
bool isArray = (nodeType & 64) != 0;
|
||||
nodeType = (byte)(nodeType & ~64);
|
||||
|
||||
string name = "";
|
||||
if (nodeType != XmlTypes.XmlTypes.NodeEndType && nodeType != XmlTypes.XmlTypes.SectionEndType)
|
||||
{
|
||||
if (compressed)
|
||||
{
|
||||
name = SixBit.Unpack(ref nodeBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = (nodeBuf.First() & ~64) + 1;
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
byte[] nameBytes = nodeBuf.Take(length).ToArray();
|
||||
nodeBuf = nodeBuf.Skip(length);
|
||||
|
||||
name = encoding.GetString(nameBytes);
|
||||
}
|
||||
}
|
||||
string name = GetNodeName(nodeType);
|
||||
|
||||
KValueAttribute nodeAttrs = null;
|
||||
bool startNode = false;
|
||||
@@ -202,49 +262,9 @@ namespace eAmuseCore.KBinXML
|
||||
int totCount = arrCount * varCount;
|
||||
int totSize = totCount * nodeAttrs.Size;
|
||||
|
||||
IEnumerable<byte> data = null;
|
||||
if (isArray || totSize > 2)
|
||||
{
|
||||
data = EnumHelpers.TakeBytesAligned(ref dataBuf, totCount * nodeAttrs.Size);
|
||||
}
|
||||
else if (totSize == 1)
|
||||
{
|
||||
if (!dataByteBuf.Any())
|
||||
{
|
||||
dataByteBuf = dataBuf;
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
}
|
||||
data = dataByteBuf.Take(1);
|
||||
dataByteBuf = dataByteBuf.Skip(1);
|
||||
}
|
||||
else if (totSize == 2)
|
||||
{
|
||||
if (!dataWordBuf.Any())
|
||||
{
|
||||
dataWordBuf = dataBuf;
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
}
|
||||
data = dataWordBuf.Take(2);
|
||||
dataWordBuf = dataWordBuf.Skip(2);
|
||||
}
|
||||
else if (totSize == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
IEnumerable<byte> data = TakeDataAligned(totSize, isArray);
|
||||
|
||||
if (nodeType == XmlTypes.XmlTypes.BinType)
|
||||
{
|
||||
node.SetAttributeValue("__size", totCount);
|
||||
node.SetValue(XmlTypes.Bin.FromBytes(data));
|
||||
}
|
||||
else if (nodeType == XmlTypes.XmlTypes.StrType)
|
||||
{
|
||||
node.SetValue(XmlTypes.Str.FromBytes(data, encoding));
|
||||
}
|
||||
else
|
||||
{
|
||||
node.SetValue(XmlTypes.XmlTypes.MakeNodeFromBytes(nodeType, arrCount, data));
|
||||
}
|
||||
SetNodeValue(node, data, nodeAttrs, varCount, arrCount);
|
||||
}
|
||||
|
||||
doc = new XDocument(fakeroot.FirstNode);
|
||||
|
||||
@@ -4,8 +4,22 @@ using System.Linq;
|
||||
|
||||
namespace eAmuseCore.KBinXML
|
||||
{
|
||||
public class KValueList<T> : List<T>
|
||||
public interface IKValue
|
||||
{
|
||||
string ToString();
|
||||
IEnumerable<byte> ToBytes();
|
||||
}
|
||||
|
||||
public class KValueList<T> : List<T>, IKValue where T : IKValue
|
||||
{
|
||||
public IEnumerable<byte> ToBytes()
|
||||
{
|
||||
IEnumerable<byte> res = Enumerable.Empty<byte>();
|
||||
foreach (IKValue val in this)
|
||||
res = res.Concat(val.ToBytes());
|
||||
return res;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", this.Select(v => v.ToString()));
|
||||
@@ -32,9 +46,8 @@ namespace eAmuseCore.KBinXML
|
||||
public int Size { get; set; }
|
||||
|
||||
|
||||
private static Dictionary<string, KValueAttribute> nameLookupMap = new Dictionary<string, KValueAttribute>();
|
||||
private static Dictionary<byte, KValueAttribute> typeLookupMap = new Dictionary<byte, KValueAttribute>();
|
||||
private static Dictionary<byte, Type> classLookupMap = new Dictionary<byte, Type>();
|
||||
private static readonly Dictionary<string, KValueAttribute> nameLookupMap = new Dictionary<string, KValueAttribute>();
|
||||
private static readonly Dictionary<byte, KValueAttribute> typeLookupMap = new Dictionary<byte, KValueAttribute>();
|
||||
|
||||
public static void Register(KValueAttribute attr)
|
||||
{
|
||||
@@ -59,7 +72,7 @@ namespace eAmuseCore.KBinXML
|
||||
}
|
||||
}
|
||||
|
||||
public class KValue<T>
|
||||
public class KValue<T> : IKValue
|
||||
{
|
||||
public T Value { get; set; }
|
||||
|
||||
@@ -71,7 +84,29 @@ namespace eAmuseCore.KBinXML
|
||||
return (Value != null) ? Value.ToString() : "";
|
||||
}
|
||||
|
||||
protected KValueAttribute KValAttr => GetType().GetCustomAttributes(typeof(KValueAttribute), true).First() as KValueAttribute;
|
||||
public virtual IEnumerable<byte> ToBytes()
|
||||
{
|
||||
if (Value == null)
|
||||
return Enumerable.Empty<byte>();
|
||||
|
||||
IEnumerable<byte> res = BitConverter.GetBytes(Convert.ToUInt64(Value));
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
res = res.Reverse();
|
||||
|
||||
return res.Skip(8 - Size);
|
||||
}
|
||||
|
||||
protected KValueAttribute KValAttr
|
||||
{
|
||||
get
|
||||
{
|
||||
var res = GetType().GetCustomAttributes(typeof(KValueAttribute), true).FirstOrDefault() as KValueAttribute;
|
||||
if (res == null)
|
||||
throw new InvalidOperationException("KValue types need KValueAttributes!");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public int NodeType => KValAttr.NodeType;
|
||||
|
||||
|
||||
@@ -8,13 +8,16 @@ using System.Collections;
|
||||
|
||||
namespace eAmuseCore.KBinXML.XmlTypes
|
||||
{
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
[KValue(1, "void", Count = 1, Size = 0)]
|
||||
public class Void : KValue<object>
|
||||
{
|
||||
public Void(object _) => Value = null;
|
||||
static public Void FromString(object _) => new Void(null);
|
||||
static public Void FromString(string input) => new Void(null);
|
||||
|
||||
static public Void FromBytes(IEnumerable<byte> input) => new Void(null);
|
||||
}
|
||||
#pragma warning restore IDE0060
|
||||
|
||||
[KValue(2, "s8", Count = 1, Size = 1)]
|
||||
public class S8 : KValue<sbyte>
|
||||
@@ -90,6 +93,8 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
return string.Join("", Value.Select(b => Convert.ToString(b, 16).PadLeft(2, '0')));
|
||||
}
|
||||
|
||||
public override IEnumerable<byte> ToBytes() => Value;
|
||||
|
||||
static public Bin FromString(string input)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -105,6 +110,8 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
|
||||
public override string ToString() => Value;
|
||||
|
||||
public override IEnumerable<byte> ToBytes() => Encoding.UTF8.GetBytes(Value);
|
||||
|
||||
static public Str FromString(string input) => new Str(input);
|
||||
|
||||
static public Str FromBytes(IEnumerable<byte> input, Encoding encoding)
|
||||
@@ -121,6 +128,8 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
|
||||
public override IEnumerable<byte> ToBytes() => Value.GetAddressBytes();
|
||||
|
||||
static public IP4 FromString(string input) => new IP4(IPAddress.Parse(input));
|
||||
|
||||
static public IP4 FromBytes(IEnumerable<byte> input) => new IP4(new IPAddress(input.Take(4).ToArray()));
|
||||
@@ -135,7 +144,7 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
public const int NodeEndType = 190;
|
||||
public const int SectionEndType = 191;
|
||||
|
||||
private static Dictionary<byte, Type> lookupMap = new Dictionary<byte, Type>();
|
||||
private static readonly Dictionary<byte, Type> lookupMap = new Dictionary<byte, Type>();
|
||||
|
||||
public static void RegisterAll()
|
||||
{
|
||||
@@ -171,9 +180,9 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
return lookupMap[type];
|
||||
}
|
||||
|
||||
public static object MakeNodeFromBytes(byte type, int count, IEnumerable<byte> data)
|
||||
public static object MakeNodeFromBytes(KValueAttribute attrs, int count, IEnumerable<byte> data)
|
||||
{
|
||||
Type valType = GetByType(type);
|
||||
Type valType = GetByType(attrs.NodeType);
|
||||
MethodInfo fromBytes = valType.GetMethod("FromBytes", BindingFlags.Static | BindingFlags.Public);
|
||||
|
||||
if (count <= 1)
|
||||
@@ -184,8 +193,7 @@ namespace eAmuseCore.KBinXML.XmlTypes
|
||||
{
|
||||
Type listType = typeof(KValueList<>).MakeGenericType(valType);
|
||||
IList list = (IList)Activator.CreateInstance(listType);
|
||||
var attr = KValueAttribute.GetAttrByType(type);
|
||||
int size = attr.Size * attr.Count;
|
||||
int size = attrs.Size * attrs.Count;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,9 @@ namespace eAmuseTest
|
||||
else if (compress != "none")
|
||||
throw new ArgumentException("Unsupported compression algorithm");
|
||||
|
||||
//KBinXML kbinxml = new KBinXML(rawData);
|
||||
Console.WriteLine(BytesToString(BitConverter.GetBytes((byte)1)));
|
||||
|
||||
KBinXML kbinxml = new KBinXML(rawData);
|
||||
|
||||
KBinXML testDoc = new KBinXML(ExtractResource("eAmuseTest.testcases_out.kbin"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user