private static void ProcessNodeStart(ByteArrayReadStream stream, Stack <ParsingNode> nodeStack) { if (!nodeStack.TryPeek(out var currentNode)) { throw new MalformedWorldException(); } if (currentNode.Children.Count == 0) { currentNode.DataEnd = stream.Position; } var childType = stream.ReadByte(); if (stream.IsOver) { throw new MalformedWorldException(); } var child = new ParsingNode { Type = (NodeType)childType, DataBegin = stream.Position// + sizeof(MarkupByte) }; currentNode.Children.Add(child); nodeStack.Push(child); }
private static void ParseTreeAfterRootNodeStart( ByteArrayReadStream stream, Stack <ParsingNode> nodeStack ) { while (!stream.IsOver) { var currentMark = (MarkupByte)stream.ReadByte(); switch (currentMark) { case MarkupByte.Start: ProcessNodeStart(stream, nodeStack); break; case MarkupByte.End: ProcessNodeEnd(stream, nodeStack); break; case MarkupByte.Escape: ProcessNodeEscape(stream); break; default: /// If it's not a <see cref="ParsingWorldNode.NodeMarker"/>, then it's just prop data /// and we can safely skip it. break; } } }
private static ParsingNode ParseTree(ByteArrayReadStream stream) { // Skipping the first 4 bytes coz they are used to store a... identifier? stream.Skip(IdentifierLength); var firstMarker = (MarkupByte)stream.ReadByte(); if (firstMarker != MarkupByte.Start) { throw new MalformedWorldException(); } var guessedMaximumNodeDepth = 128; var nodeStack = new Stack <ParsingNode>(capacity: guessedMaximumNodeDepth); var rootNodeType = (byte)stream.ReadByte(); var rootNode = new ParsingNode() { Type = (NodeType)rootNodeType, DataBegin = (int)stream.Position }; nodeStack.Push(rootNode); ParseTreeAfterRootNodeStart(stream, nodeStack); if (nodeStack.Count != 0) { throw new MalformedWorldException(); } return(rootNode); }
private static void ProcessNodeEscape(ByteArrayReadStream stream) { var escapedByte = stream.ReadByte(); if (stream.IsOver) { throw new MalformedWorldException(); } }
private static void ProcessNodeEnd(ByteArrayReadStream stream, Stack <ParsingNode> nodeStack) { if (!nodeStack.TryPeek(out var currentNode)) { throw new MalformedWorldException(); } if (currentNode.Children.Count == 0) { currentNode.DataEnd = stream.Position; } nodeStack.Pop(); }
public static ParsingTree ParseWorld(byte[] serializedWorldData) { if (serializedWorldData == null) { throw new ArgumentNullException(nameof(serializedWorldData)); } if (serializedWorldData.Length < MinimumWorldSize) { throw new MalformedWorldException(); } var stream = new ByteArrayReadStream(serializedWorldData); var rootNode = ParseTree(stream); return(new ParsingTree(serializedWorldData, rootNode)); }
public ParsingStream(ParsingTree tree, ParsingNode node) { if (tree == null) { throw new ArgumentNullException(nameof(tree)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } UnderlayingStream = new ByteArrayReadStream( array: tree.Data, position: node.DataBegin); BeginPosition = node.DataBegin; EndPosition = node.DataEnd; // The buffer must be at least as big as the largest non-string // object we can parse. Currently it's a uint32. _parsingBuffer = new byte[sizeof(UInt32)]; }