KBinXML logic fully implemented

This commit is contained in:
BtbN
2019-04-15 21:54:46 +02:00
parent 01a097d638
commit e4fda86b33
4 changed files with 96 additions and 28 deletions

View File

@@ -168,10 +168,13 @@ namespace eAmuseCore.KBinXML
return input.Select(v => (object)v);
}
public static IEnumerable<byte> TakeByteArrayAligned(ref IEnumerable<byte> input)
public static IEnumerable<byte> TakeBytesAligned(ref IEnumerable<byte> input, int size = -1)
{
int size = input.FirstS32();
input = input.Skip(4);
if (size < 0)
{
size = input.FirstS32();
input = input.Skip(4);
}
var res = input.Take(size);
input = input.Skip(size);
@@ -183,9 +186,9 @@ namespace eAmuseCore.KBinXML
return res;
}
public static string TakeStringAligned(ref IEnumerable<byte> input, Encoding encoding)
public static string TakeStringAligned(ref IEnumerable<byte> input, Encoding encoding, int size = -1)
{
byte[] data = TakeByteArrayAligned(ref input).ToArray();
byte[] data = TakeBytesAligned(ref input, size).ToArray();
return encoding.GetString(data, 0, data.Length - 1); // drop final null byte
}
}

View File

@@ -89,8 +89,6 @@ namespace eAmuseCore.KBinXML
}
input = input.Skip(1);
Console.WriteLine("Compressed: " + compressed);
byte encodingSig = input.FirstU8();
input = input.Skip(1);
@@ -111,6 +109,9 @@ namespace eAmuseCore.KBinXML
private void ParseNodes(IEnumerable<byte> nodeBuf, IEnumerable<byte> dataBuf, bool compressed)
{
IEnumerable<byte> dataByteBuf = Enumerable.Empty<byte>();
IEnumerable<byte> dataWordBuf = Enumerable.Empty<byte>();
uint dataSize = dataBuf.FirstU32();
dataBuf = dataBuf.Skip(4);
@@ -147,9 +148,6 @@ namespace eAmuseCore.KBinXML
}
}
Console.WriteLine("Name: " + name);
Console.WriteLine("Type: " + nodeType);
XmlTypes.Entry nodeTypeEntry = null;
bool startNode = false;
@@ -158,7 +156,6 @@ namespace eAmuseCore.KBinXML
case XmlTypes.AttrType:
string attrVal = EnumHelpers.TakeStringAligned(ref dataBuf, encoding);
node.SetAttributeValue(name, attrVal);
Console.WriteLine("Attr val: " + attrVal);
break;
case XmlTypes.NodeEndType:
node = node.Parent;
@@ -185,9 +182,68 @@ namespace eAmuseCore.KBinXML
if (startNode)
continue;
node.SetAttributeValue("__type", nodeTypeEntry.names[0]);
int varCount = nodeTypeEntry.count;
int arrCount = 1;
if (varCount < 0)
{
varCount = dataBuf.FirstS32();
dataBuf = dataBuf.Skip(4);
isArray = true;
}
else if (isArray)
{
arrCount = dataBuf.FirstS32() / (nodeTypeEntry.size * nodeTypeEntry.count);
dataBuf = dataBuf.Skip(4);
node.SetAttributeValue("__count", arrCount);
}
int totCount = arrCount * varCount;
int totSize = totCount * nodeTypeEntry.size;
IEnumerable<byte> data = null;
if (isArray || totSize > 2)
{
data = EnumHelpers.TakeBytesAligned(ref dataBuf, totCount * nodeTypeEntry.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);
}
if (nodeType == XmlTypes.Bin.nodeType)
{
node.SetAttributeValue("__size", totCount);
node.Value = string.Join("", data.Select(b => Convert.ToString(b, 16).PadLeft(2, '0')));
}
else if (nodeType == XmlTypes.Str.nodeType)
{
node.Value = encoding.GetString(data.ToArray(), 0, totCount - 1);
}
else
{
node.Value = string.Join(" ", XmlTypes.DataToString(data, nodeTypeEntry));
}
}
doc = new XDocument(fakeroot.Elements().First());
doc = new XDocument(fakeroot.FirstNode);
Console.WriteLine(doc.ToString());
}
}

View File

@@ -20,7 +20,7 @@ namespace eAmuseCore.KBinXML
public int size = 0;
public int count = 0;
public Type type = typeof(object);
public Func<IEnumerable<byte>, IEnumerable<object>> read = _ => Enumerable.Empty<object>();
public Func<IEnumerable<byte>, string> toString;
}
public static readonly Entry Void = new Entry
@@ -36,7 +36,7 @@ namespace eAmuseCore.KBinXML
size = 1,
count = 1,
type = typeof(sbyte),
read = input => input.TakeS8(1).Box(),
toString = input => input.FirstS8().ToString(),
};
public static readonly Entry U8 = new Entry
@@ -46,7 +46,7 @@ namespace eAmuseCore.KBinXML
size = 1,
count = 1,
type = typeof(byte),
read = input => input.TakeU8(1).Box(),
toString = input => input.FirstU8().ToString(),
};
public static readonly Entry S16 = new Entry
@@ -56,7 +56,7 @@ namespace eAmuseCore.KBinXML
size = 2,
count = 1,
type = typeof(short),
read = input => input.TakeS16(1).Box(),
toString = input => input.FirstS16().ToString(),
};
public static readonly Entry U16 = new Entry
@@ -66,7 +66,7 @@ namespace eAmuseCore.KBinXML
size = 2,
count = 1,
type = typeof(ushort),
read = input => input.TakeU16(1).Box(),
toString = input => input.FirstU16().ToString(),
};
public static readonly Entry S32 = new Entry
@@ -76,7 +76,7 @@ namespace eAmuseCore.KBinXML
size = 4,
count = 1,
type = typeof(int),
read = input => input.TakeS32(1).Box(),
toString = input => input.FirstS32().ToString(),
};
public static readonly Entry U32 = new Entry
@@ -86,7 +86,7 @@ namespace eAmuseCore.KBinXML
size = 4,
count = 1,
type = typeof(int),
read = input => input.TakeU32(1).Box(),
toString = input => input.FirstU32().ToString(),
};
public static readonly Entry S64 = new Entry
@@ -96,7 +96,7 @@ namespace eAmuseCore.KBinXML
size = 8,
count = 1,
type = typeof(int),
read = input => input.TakeS64(1).Box(),
toString = input => input.FirstS64().ToString(),
};
public static readonly Entry U64 = new Entry
@@ -106,27 +106,27 @@ namespace eAmuseCore.KBinXML
size = 8,
count = 1,
type = typeof(int),
read = input => input.TakeU64(1).Box(),
toString = input => input.FirstU64().ToString(),
};
public static readonly Entry Bin = new Entry
{
names = new[] { "bin", "binary" },
nodeType = 10,
size = 4,
size = 1,
count = -1,
type = typeof(byte[]),
read = input => input.TakeU64(1).Box(),
type = typeof(byte),
toString = null, // special case, cannot be handled here
};
public static readonly Entry Str = new Entry
{
names = new[] { "str", "string" },
nodeType = 11,
size = 4,
size = 1,
count = -1,
type = typeof(byte[]),
read = input => input.TakeU64(1).Box(),
type = typeof(byte),
toString = null, // special case, cannot be handled here
};
private static Dictionary<string, Entry> nameLookupMap = new Dictionary<string, Entry>();
@@ -169,5 +169,14 @@ namespace eAmuseCore.KBinXML
return null;
}
public static IEnumerable<string> DataToString(IEnumerable<byte> dataBuf, Entry entry)
{
while (dataBuf.Any())
{
yield return entry.toString(dataBuf);
dataBuf = dataBuf.Skip(entry.size);
}
}
}
}

View File

@@ -46,7 +46,7 @@ namespace eAmuseTest
else if (compress != "none")
throw new ArgumentException("Unsupported compression algorithm");
Console.WriteLine("" + ((3 - 4) % 4));
Console.WriteLine(BitConverter.ToString(new byte[] { 1, 2, 3, 4 }));
KBinXML kbinxml = new KBinXML(rawData);
}