Tree building

This commit is contained in:
BtbN
2019-04-15 20:00:47 +02:00
parent afcf733c39
commit 01a097d638
4 changed files with 79 additions and 38 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace eAmuseCore.KBinXML
{
@@ -166,5 +167,26 @@ namespace eAmuseCore.KBinXML
{
return input.Select(v => (object)v);
}
public static IEnumerable<byte> TakeByteArrayAligned(ref IEnumerable<byte> input)
{
int size = input.FirstS32();
input = input.Skip(4);
var res = input.Take(size);
input = input.Skip(size);
int align = 4 - (size % 4);
if (align != 4)
input = input.Skip(align);
return res;
}
public static string TakeStringAligned(ref IEnumerable<byte> input, Encoding encoding)
{
byte[] data = TakeByteArrayAligned(ref input).ToArray();
return encoding.GetString(data, 0, data.Length - 1); // drop final null byte
}
}
}

View File

@@ -114,9 +114,11 @@ namespace eAmuseCore.KBinXML
uint dataSize = dataBuf.FirstU32();
dataBuf = dataBuf.Skip(4);
XElement node = doc.Root;
XElement fakeroot = new XElement("fakeroot");
XElement node = fakeroot;
while (nodeBuf.Any())
bool nodesLeft = true;
while (nodesLeft && nodeBuf.Any())
{
nodeBuf = nodeBuf.SkipWhile(b => b == 0);
@@ -126,10 +128,8 @@ namespace eAmuseCore.KBinXML
bool isArray = (nodeType & 64) != 0;
nodeType = (byte)(nodeType & ~64);
XmlTypes.Entry nodeTypeEntry = XmlTypes.GetEntryByType(nodeType);
string name = null;
if (nodeType != XmlTypes.NodeEnd.nodeType && nodeType != XmlTypes.EndSection.nodeType)
string name = "";
if (nodeType != XmlTypes.NodeEndType && nodeType != XmlTypes.SectionEndType)
{
if (compressed)
{
@@ -148,15 +148,47 @@ namespace eAmuseCore.KBinXML
}
Console.WriteLine("Name: " + name);
Console.WriteLine("Type: " + nodeType);
bool skip = true;
XmlTypes.Entry nodeTypeEntry = null;
bool startNode = false;
if (nodeType == XmlTypes.EndSection.nodeType)
break;
switch (nodeType)
{
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;
break;
case XmlTypes.SectionEndType:
nodesLeft = false;
break;
case XmlTypes.NodeStartType:
startNode = true;
break;
default:
nodeTypeEntry = XmlTypes.GetEntryByType(nodeType);
if (nodeTypeEntry == null)
throw new NotImplementedException("nodeType " + nodeType + " is not implemented");
break;
}
if (skip)
if (nodeTypeEntry == null && !startNode)
continue;
XElement child = new XElement(name);
node.Add(child);
node = child;
if (startNode)
continue;
}
doc = new XDocument(fakeroot.Elements().First());
Console.WriteLine(doc.ToString());
}
}
}

View File

@@ -8,6 +8,11 @@ namespace eAmuseCore.KBinXML
{
public static class XmlTypes
{
public const int NodeStartType = 1;
public const int AttrType = 46;
public const int NodeEndType = 190;
public const int SectionEndType = 191;
public class Entry
{
public string[] names = null;
@@ -16,16 +21,8 @@ namespace eAmuseCore.KBinXML
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
{
names = new[] { "nodeStart" },
nodeType = 1,
isVirtual = true,
};
public static readonly Entry Void = new Entry
{
names = new[] { "void" },
@@ -116,30 +113,20 @@ namespace eAmuseCore.KBinXML
{
names = new[] { "bin", "binary" },
nodeType = 10,
size = 1,
size = 4,
count = -1,
type = typeof(byte[]),
read = input => input.TakeU64(1).Box(),
};
public static readonly Entry Attr = new Entry
public static readonly Entry Str = new Entry
{
names = new[] { "attr" },
nodeType = 46,
};
public static readonly Entry NodeEnd = new Entry
{
names = new[] { "nodeEnd" },
nodeType = 190,
isVirtual = true,
};
public static readonly Entry EndSection = new Entry
{
names = new[] { "endSection" },
nodeType = 191,
isVirtual = true,
names = new[] { "str", "string" },
nodeType = 11,
size = 4,
count = -1,
type = typeof(byte[]),
read = input => input.TakeU64(1).Box(),
};
private static Dictionary<string, Entry> nameLookupMap = new Dictionary<string, Entry>();
@@ -174,7 +161,7 @@ namespace eAmuseCore.KBinXML
if (!info.IsStatic)
continue;
Entry res = info.GetValue(null) as Entry;
if (res == null || res.nodeType != type || res.isVirtual)
if (res == null || res.nodeType != type)
continue;
typeLookupMap[type] = res;
return res;

View File

@@ -46,7 +46,7 @@ namespace eAmuseTest
else if (compress != "none")
throw new ArgumentException("Unsupported compression algorithm");
Console.WriteLine(BytesToString(rawData));
Console.WriteLine("" + ((3 - 4) % 4));
KBinXML kbinxml = new KBinXML(rawData);
}