mirror of
https://github.com/BtbN/ClanServer.git
synced 2026-09-06 23:45:15 -05:00
More work on kbinxml
This commit is contained in:
@@ -6,36 +6,165 @@ namespace eAmuseCore.KBinXML
|
||||
{
|
||||
static class EnumHelpers
|
||||
{
|
||||
public static uint FirstU32(this IEnumerable<byte> input)
|
||||
public static IEnumerable<ulong> TakeU64(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
input = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToUInt32(input.ToArray(), 0);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(8);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(8);
|
||||
yield return BitConverter.ToUInt64(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static int FirstI32(this IEnumerable<byte> input)
|
||||
public static IEnumerable<long> TakeS64(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
input = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToInt32(input.ToArray(), 0);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(8);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(8);
|
||||
yield return BitConverter.ToInt64(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<uint> TakeU32(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(4);
|
||||
yield return BitConverter.ToUInt32(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<int> TakeS32(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(4);
|
||||
yield return BitConverter.ToInt32(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<ushort> TakeU16(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(2);
|
||||
yield return BitConverter.ToUInt16(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<short> TakeS16(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(2);
|
||||
yield return BitConverter.ToInt16(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<byte> TakeU8(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
return input.Take(count);
|
||||
}
|
||||
|
||||
public static IEnumerable<sbyte> TakeS8(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
return input.Take(count).Select(b => unchecked((sbyte)b));
|
||||
}
|
||||
|
||||
public static IEnumerable<float> TakeF(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(4);
|
||||
yield return BitConverter.ToSingle(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<double> TakeD(this IEnumerable<byte> input, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var state = input.Take(8);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
state = state.Reverse();
|
||||
input = input.Skip(8);
|
||||
yield return BitConverter.ToDouble(state.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong FirstU64(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeU64(1).First();
|
||||
}
|
||||
|
||||
public static long FirstS64(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeS64(1).First();
|
||||
}
|
||||
|
||||
public static uint FirstU32(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeU32(1).First();
|
||||
}
|
||||
|
||||
public static int FirstS32(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeS32(1).First();
|
||||
}
|
||||
|
||||
public static ushort FirstU16(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToUInt16(input.ToArray(), 0);
|
||||
return input.TakeU16(1).First();
|
||||
}
|
||||
|
||||
public static short FirstI16(this IEnumerable<byte> input)
|
||||
public static short FirstS16(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToInt16(input.ToArray(), 0);
|
||||
return input.TakeS16(1).First();
|
||||
}
|
||||
|
||||
public static byte FirstU8(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeU8(1).First();
|
||||
}
|
||||
|
||||
public static sbyte FirstS8(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeS8(1).First();
|
||||
}
|
||||
|
||||
public static float FirstF(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeF(1).First();
|
||||
}
|
||||
|
||||
public static double FirstD(this IEnumerable<byte> input)
|
||||
{
|
||||
return input.TakeD(1).First();
|
||||
}
|
||||
|
||||
public static IEnumerable<object> Box<T>(this IEnumerable<T> input)
|
||||
{
|
||||
return input.Select(v => (object)v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ namespace eAmuseCore.KBinXML
|
||||
{
|
||||
doc = new XDocument();
|
||||
|
||||
if (input.First() != SIGNATURE)
|
||||
if (input.FirstU8() != SIGNATURE)
|
||||
throw new ArgumentException("Invalid signature", "input");
|
||||
input = input.Skip(1);
|
||||
|
||||
bool compressed;
|
||||
switch (input.First())
|
||||
switch (input.FirstU8())
|
||||
{
|
||||
case SIG_COMPRESSED:
|
||||
compressed = true;
|
||||
@@ -91,10 +91,10 @@ namespace eAmuseCore.KBinXML
|
||||
|
||||
Console.WriteLine("Compressed: " + compressed);
|
||||
|
||||
byte encodingSig = input.First();
|
||||
byte encodingSig = input.FirstU8();
|
||||
input = input.Skip(1);
|
||||
|
||||
if (input.First() != (0xFF ^ encodingSig))
|
||||
if (input.FirstU8() != (0xFF ^ encodingSig))
|
||||
throw new ArgumentException("Encoding signature failed to verify", "input");
|
||||
input = input.Skip(1);
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace eAmuseCore.KBinXML
|
||||
{
|
||||
nodeBuf = nodeBuf.SkipWhile(b => b == 0);
|
||||
|
||||
byte nodeType = nodeBuf.First();
|
||||
byte nodeType = nodeBuf.FirstU8();
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
bool isArray = (nodeType & 64) != 0;
|
||||
@@ -129,7 +129,7 @@ namespace eAmuseCore.KBinXML
|
||||
XmlTypes.Entry nodeTypeEntry = XmlTypes.GetEntryByType(nodeType);
|
||||
|
||||
string name = null;
|
||||
if (nodeType != XmlTypes.NodeEnd.type && nodeType != XmlTypes.EndSection.type)
|
||||
if (nodeType != XmlTypes.NodeEnd.nodeType && nodeType != XmlTypes.EndSection.nodeType)
|
||||
{
|
||||
if (compressed)
|
||||
{
|
||||
@@ -151,7 +151,7 @@ namespace eAmuseCore.KBinXML
|
||||
|
||||
bool skip = true;
|
||||
|
||||
if (nodeType == XmlTypes.EndSection.type)
|
||||
if (nodeType == XmlTypes.EndSection.nodeType)
|
||||
break;
|
||||
|
||||
if (skip)
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace eAmuseCore.KBinXML
|
||||
|
||||
public static string Unpack(ref IEnumerable<byte> nodeBuf)
|
||||
{
|
||||
int length = nodeBuf.First();
|
||||
int length = nodeBuf.FirstU8();
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
int length_bits = length * 6;
|
||||
@@ -60,7 +60,7 @@ namespace eAmuseCore.KBinXML
|
||||
int padding = (8 - (length_bits % 8)) % 8;
|
||||
|
||||
// bytes are in big endian order, BigInteger expects little endian, hence .Reverse() it.
|
||||
BigInteger bits = new BigInteger(nodeBuf.Take(length_bytes).Reverse().ToArray());
|
||||
BigInteger bits = new BigInteger(nodeBuf.TakeU8(length_bytes).Reverse().ToArray());
|
||||
nodeBuf = nodeBuf.Skip(length_bytes);
|
||||
bits >>= padding;
|
||||
|
||||
|
||||
@@ -10,30 +10,136 @@ namespace eAmuseCore.KBinXML
|
||||
{
|
||||
public class Entry
|
||||
{
|
||||
public byte type;
|
||||
public int size;
|
||||
public int count;
|
||||
public string[] names;
|
||||
public string[] names = null;
|
||||
public byte nodeType = 0;
|
||||
public int size = 0;
|
||||
public int count = 0;
|
||||
public Type type = typeof(object);
|
||||
public Func<IEnumerable<byte>, IEnumerable<object>> read = _ => Enumerable.Empty<object>();
|
||||
public bool isVirtual = false;
|
||||
}
|
||||
|
||||
public static readonly Entry NodeStart = new Entry
|
||||
{
|
||||
type = 1
|
||||
names = new[] { "nodeStart" },
|
||||
nodeType = 1,
|
||||
isVirtual = true,
|
||||
};
|
||||
|
||||
public static readonly Entry Void = new Entry
|
||||
{
|
||||
names = new[] { "void" },
|
||||
nodeType = 1,
|
||||
};
|
||||
|
||||
public static readonly Entry S8 = new Entry
|
||||
{
|
||||
names = new[] { "s8" },
|
||||
nodeType = 2,
|
||||
size = 1,
|
||||
count = 1,
|
||||
type = typeof(sbyte),
|
||||
read = input => input.TakeS8(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry U8 = new Entry
|
||||
{
|
||||
names = new[] { "u8" },
|
||||
nodeType = 3,
|
||||
size = 1,
|
||||
count = 1,
|
||||
type = typeof(byte),
|
||||
read = input => input.TakeU8(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry S16 = new Entry
|
||||
{
|
||||
names = new[] { "s16" },
|
||||
nodeType = 4,
|
||||
size = 2,
|
||||
count = 1,
|
||||
type = typeof(short),
|
||||
read = input => input.TakeS16(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry U16 = new Entry
|
||||
{
|
||||
names = new[] { "u16" },
|
||||
nodeType = 5,
|
||||
size = 2,
|
||||
count = 1,
|
||||
type = typeof(ushort),
|
||||
read = input => input.TakeU16(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry S32 = new Entry
|
||||
{
|
||||
names = new[] { "s32" },
|
||||
nodeType = 6,
|
||||
size = 4,
|
||||
count = 1,
|
||||
type = typeof(int),
|
||||
read = input => input.TakeS32(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry U32 = new Entry
|
||||
{
|
||||
names = new[] { "u32" },
|
||||
nodeType = 7,
|
||||
size = 4,
|
||||
count = 1,
|
||||
type = typeof(int),
|
||||
read = input => input.TakeU32(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry S64 = new Entry
|
||||
{
|
||||
names = new[] { "s64" },
|
||||
nodeType = 8,
|
||||
size = 8,
|
||||
count = 1,
|
||||
type = typeof(int),
|
||||
read = input => input.TakeS64(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry U64 = new Entry
|
||||
{
|
||||
names = new[] { "u64" },
|
||||
nodeType = 9,
|
||||
size = 8,
|
||||
count = 1,
|
||||
type = typeof(int),
|
||||
read = input => input.TakeU64(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry Bin = new Entry
|
||||
{
|
||||
names = new[] { "bin", "binary" },
|
||||
nodeType = 10,
|
||||
size = 1,
|
||||
count = -1,
|
||||
type = typeof(byte[]),
|
||||
read = input => input.TakeU64(1).Box(),
|
||||
};
|
||||
|
||||
public static readonly Entry Attr = new Entry
|
||||
{
|
||||
type = 46
|
||||
names = new[] { "attr" },
|
||||
nodeType = 46,
|
||||
};
|
||||
|
||||
public static readonly Entry NodeEnd = new Entry
|
||||
{
|
||||
type = 190
|
||||
names = new[] { "nodeEnd" },
|
||||
nodeType = 190,
|
||||
isVirtual = true,
|
||||
};
|
||||
|
||||
public static readonly Entry EndSection = new Entry
|
||||
{
|
||||
type = 191
|
||||
names = new[] { "endSection" },
|
||||
nodeType = 191,
|
||||
isVirtual = true,
|
||||
};
|
||||
|
||||
private static Dictionary<string, Entry> nameLookupMap = new Dictionary<string, Entry>();
|
||||
@@ -68,7 +174,7 @@ namespace eAmuseCore.KBinXML
|
||||
if (!info.IsStatic)
|
||||
continue;
|
||||
Entry res = info.GetValue(null) as Entry;
|
||||
if (res == null || res.type != type)
|
||||
if (res == null || res.nodeType != type || res.isVirtual)
|
||||
continue;
|
||||
typeLookupMap[type] = res;
|
||||
return res;
|
||||
|
||||
@@ -49,11 +49,6 @@ namespace eAmuseTest
|
||||
Console.WriteLine(BytesToString(rawData));
|
||||
|
||||
KBinXML kbinxml = new KBinXML(rawData);
|
||||
|
||||
Dictionary<int, int> dd = new Dictionary<int, int>();
|
||||
dd[2] = 3;
|
||||
Console.WriteLine("" + dd[2]);
|
||||
Console.WriteLine("" + dd[1]);
|
||||
}
|
||||
|
||||
private static string BytesToString(IEnumerable<byte> bytes)
|
||||
|
||||
Reference in New Issue
Block a user