/// <summary> /// parses the key value tree of file specified at the path /// </summary> /// <param name="path">the path to parse</param> /// <returns>the parsed path</returns> public async Task <KeyValueNode> Parse(string path) { using (var sr = new StreamReader(File.OpenRead(path))) { var data = await sr.ReadToEndAsync(); var root = new KeyValueNode(); root.Key = "Root"; root.Children = new Dictionary <string, List <KeyValueNode> >(); var toReturn = ParseHelper(root, data, 0, data.Length); return(toReturn); } }
public KeyValueNode BuildNode() { var toReturn = new KeyValueNode(); toReturn.Key = KeyBuilder.ToString(); if (ValueBuilder.Length > 0) { toReturn.Value = ValueBuilder.ToString(); } else { toReturn.Children = new Dictionary <string, List <KeyValueNode> >(); } return(toReturn); }
/// <summary> /// parse helper method /// </summary> /// <param name="parent"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="count"></param> /// <returns></returns> private KeyValueNode ParseHelper(KeyValueNode parent, string data, int startIndex, int count) { var i = startIndex; var currentNode = new FileParsingState(); while (i < startIndex + count) { var currentChar = data[i]; ProcessState(currentNode, currentChar, i); if (currentNode.State != FileParsingStateEnum.Finished) { i++; continue; } var nextNode = currentNode.BuildNode(); if (nextNode.IsLeaf) { parent[nextNode.Key] = nextNode; } else { var toAdd = ParseHelper(nextNode, data, currentNode.ChildrenStartIndex, currentNode.ChildrenIndexCount); parent[toAdd.Key] = toAdd; } var oldNode = currentNode; currentNode = new FileParsingState(); if (oldNode.IncludeCurrentInNext) { if (currentChar == '"') { currentNode.State = FileParsingStateEnum.ParsingEscapedKey; } else { currentNode.State = FileParsingStateEnum.ParsingKey; currentNode.KeyBuilder.Append(currentChar); } } i++; } //this cleanup code handles case where non whitespace char is directly against closing bracket var lastNode = currentNode.BuildNode(); if (!string.IsNullOrWhiteSpace(lastNode.Key)) { if (!parent.Children.ContainsKey(lastNode.Key)) { parent.Children[lastNode.Key] = new List <KeyValueNode>(); } if (currentNode.State != FileParsingStateEnum.Initial && !parent.Children[lastNode.Key].Contains(lastNode)) { parent.Children[lastNode.Key].Add(lastNode); } } return(parent); }