Beispiel #1
0
        private static void SetDictionaryNodeGeneric <TKey, TValue>(Node node, Dictionary <TKey, TValue> dictionary, FileStyle style, bool forceArrayMode = false)
        {
            bool keyIsBase = BaseTypes.IsBaseType(typeof(TKey));

            if (keyIsBase && !forceArrayMode && !style.AlwaysArrayDictionaries)
            {
                // we might have switched between standard and array dictionary storage, and if so, children need to be reset
                if (node.ChildNodeType != NodeChildrenType.key)
                {
                    node.ClearChildren(newChildrenType: NodeChildrenType.key);
                }

                var CurrentKeys = new List <string>(capacity: dictionary.Count);
                foreach (var key in dictionary.Keys)
                {
                    var value = dictionary[key];

                    string keyAsText = BaseTypes.SerializeBaseType <TKey>(key, style);

                    if (!Utilities.IsValidKey(keyAsText))
                    {
                        SetDictionaryNodeGeneric(node, dictionary, style, forceArrayMode: true);
                        return;
                    }

                    CurrentKeys.Add(keyAsText);
                    KeyNode child = node.GetChildAddressedByName(keyAsText);
                    NodeManager.SetNodeData <TValue>(child, value, style);
                }

                // make sure that old data in the file is deleted when a new dictionary is saved.
                // node.ClearChildren() is not used because we want to keep comments and whitespace intact as much as possible.
                foreach (var key in node.GetChildKeys())
                {
                    if (!CurrentKeys.Contains(key))
                    {
                        node.RemoveChild(key);
                    }
                }
            }
            else // save dictionary as KeyValuePair<TKey, TValue>[]
            {
                // we might have switched between standard and array dictionary storage, and if so, children need to be reset
                if (node.ChildNodeType != NodeChildrenType.list)
                {
                    node.ClearChildren(newChildrenType: NodeChildrenType.list);
                }

                var array = GetWritableKeyValuePairArray(dictionary);
                NodeManager.SetNodeData(node, array, array.GetType(), style);
            }
        }
Beispiel #2
0
        private static Node GetNodeFromLine(string line, DataFile file)
        {
            var  DataType = GetDataLineType(line);
            Node node     = null;

            switch (DataType)
            {
            case DataLineType.key:
                node = new KeyNode(rawText: line, file);
                break;

            case DataLineType.list:
                node = new ListNode(rawText: line, file);
                break;

            default:
                throw new FormatException($"format error on line: {line}");
            }

            return(node);
        }
Beispiel #3
0
        public KeyNode GetChildAddressedByName(string name)
        {
            EnsureProperChildType(NodeChildrenType.key);

            foreach (var node in ChildNodes)
            {
                var keynode = node as KeyNode;
                if (keynode.Key == name)
                {
                    return(keynode);
                }
            }

            return(CreateKeyNode(name));

            KeyNode CreateKeyNode(string key)
            {
                var newnode = new KeyNode(GetProperChildIndentation(), key, File);

                AddChild(newnode);
                return(newnode);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Parses lines of SUCC into a data structure
        /// </summary>
        internal static (List <Line>, Dictionary <string, KeyNode>) DataStructureFromSUCC(string[] lines, ReadableDataFile fileRef) // I am so, so sorry. If you need to understand this function for whatever reason... may god give you guidance.
        {
            // if the file is empty
            // do this because otherwise new files are created with a newline at the top
            if (lines.Length == 1 && lines[0] == "")
            {
                return(new List <Line>(), new Dictionary <string, KeyNode>());
            }


            var TopLevelLines = new List <Line>();
            var TopLevelNodes = new Dictionary <string, KeyNode>();

            var  NestingNodeStack     = new Stack <Node>(); // the top of the stack is the node that new nodes should be children of
            bool DoingMultiLineString = false;

            var file = fileRef as DataFile; // this will be null if fileRef is a ReadOnlyDataFile

            // parse the input line by line
            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                if (line.Contains('\t'))
                {
                    throw new FormatException("a SUCC file cannot contain tabs. Please use spaces instead.");
                }

                if (DoingMultiLineString)
                {
                    if (NestingNodeStack.Peek().ChildNodeType != NodeChildrenType.multiLineString)
                    {
                        throw new Exception("oh f**k, we were supposed to be doing a multi-line string but the top of the node stack isn't a multi-line string node!");
                    }

                    var newboi = new MultiLineStringNode(rawText: line, file);

                    NestingNodeStack.Peek().AddChild(newboi);

                    if (newboi.IsTerminator)
                    {
                        DoingMultiLineString = false;
                        NestingNodeStack.Pop();
                    }

                    continue;
                }

                if (LineHasData(line))
                {
                    Node node = GetNodeFromLine(line, file);

boobies:

                    if (NestingNodeStack.Count == 0) // if this is a top-level node
                    {
                        if (!(node is KeyNode))
                        {
                            throw new FormatException($"top level lines must be key nodes. Line {i} does not conform to this: '{line}'");
                        }
                        TopLevelLines.Add(node);
                        KeyNode heck = node as KeyNode;
                        TopLevelNodes.Add(heck.Key, heck);
                    }
                    else // if this is NOT a top-level node
                    {
                        int StackTopIndentation = NestingNodeStack.Peek().IndentationLevel;
                        int LineIndentation     = line.GetIndentationLevel();

                        if (LineIndentation > StackTopIndentation) // if this should be a child of the stack top
                        {
                            Node newParent = NestingNodeStack.Peek();
                            if (newParent.ChildNodes.Count == 0) // if this is the first child of the parent, assign the parent's child type
                            {
                                if (node is KeyNode)
                                {
                                    newParent.ChildNodeType = NodeChildrenType.key;
                                }
                                else if (node is ListNode)
                                {
                                    newParent.ChildNodeType = NodeChildrenType.list;
                                }
                                else
                                {
                                    throw new Exception("what the f**k?");
                                }
                            }
                            else // if the parent already has children, check for errors with this line
                            {
                                CheckNewSiblingForErrors(child: node, newParent: newParent);
                            }

                            newParent.AddChild(node);
                        }
                        else // if this should NOT be a child of the stack top
                        {
                            NestingNodeStack.Pop();
                            goto boobies;
                        }
                    }

                    if (node.Value == "") // if this is a node with children
                    {
                        NestingNodeStack.Push(node);
                    }

                    if (node.Value == MultiLineStringNode.Terminator) // if this is the start of a multi line string
                    {
                        NestingNodeStack.Push(node);
                        node.ChildNodeType   = NodeChildrenType.multiLineString;
                        DoingMultiLineString = true;
                    }
                }
                else // line has no data
                {
                    Line NoDataLine = new Line(rawText: line);

                    if (NestingNodeStack.Count == 0)
                    {
                        TopLevelLines.Add(NoDataLine);
                    }
                    else
                    {
                        NestingNodeStack.Peek().AddChild(NoDataLine);
                    }
                }
            }

            return(TopLevelLines, TopLevelNodes);
        }