示例#1
0
        /// <summary>
        /// Generate the base config file. This may require UAC, and may require a visual interface,
        /// unlike the rest of the program, which is why it's partitioned off by itself.
        /// </summary>
        public static void Main()
        {
            // Force-generate a clean config file
            KV.KeyValue root    = new KV.KeyValue("config");
            KV.KeyValue dotadir = new KV.KeyValue("dotaDir");
            dotadir.Set(getDotaDir());
            root.AddChild(dotadir);
            string contents = root.ToString();
            // This is system-wide
            string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

            using (StreamWriter writeto = new StreamWriter(path + "/config.txt"))
            {
                writeto.Write(contents);
            }
        }
示例#2
0
        /// <summary>
        /// Grab all of the keyvalues from a string.
        /// </summary>
        /// <param name="contents">The string containing keyvalues</param>
        /// <param name="allowunnamedkeys">Whether or not to allow unnamed blocks (used in bsp entity lump)</param>
        /// <returns>An array containing all root-level KeyValues in the string</returns>
        public static KeyValue[] ParseAllKeyValues(string contents, bool allowunnamedkeys = false)
        {
            parseEnum parseState = parseEnum.lookingForKey;
            KeyValue  basekv     = new KeyValue("base"); // file contents are interpreted as children of this keyvalue
            KeyValue  curparent  = basekv;

            for (int i = 0; i < contents.Length; i++)
            {
                // go until next symbol
                if (contents[i] == ' ' || contents[i] == '\t' || contents[i] == '\n' || contents[i] == '\r')
                {
                    continue;
                }
                switch (parseState)
                {
                case parseEnum.lookingForKey:
                    if (contents[i] == '{')
                    {
                        if (!allowunnamedkeys)
                        {
                            throw new KeyValueParsingException("Hit unnamed key while parsing without unnamed keys enabled.", null);
                        }
                        // This is a special case - some kv files, in particular bsp entity lumps, have unkeyed kvs
                        KeyValue cur = new KeyValue("UNNAMED");
                        curparent.AddChild(cur);
                        curparent  = cur;
                        parseState = parseEnum.lookingForValue;
                    }
                    else if (contents[i] == '"' || contents[i] == '\'')
                    {
                        //quoted key
                        int j = i + 1;
                        if (j >= contents.Length)
                        {
                            throw new KeyValueParsingException("Couldn't find terminating '" + contents[i].ToString() + "' for key started at position " + i.ToString(), null);
                        }
                        while (contents[j] != contents[i])
                        {
                            // handle escaped quotes
                            if (contents[j] == '\\')
                            {
                                j++;
                            }
                            j++;
                            if (j >= contents.Length)
                            {
                                throw new KeyValueParsingException("Couldn't find terminating '" + contents[i].ToString() + "' for key started at position " + i.ToString(), null);
                            }
                        }
                        //ok, now contents[i] and contents[j] are the same character, on either end of the key
                        KeyValue cur = new KeyValue(contents.Substring(i + 1, j - (i + 1)));
                        curparent.AddChild(cur);
                        curparent  = cur;
                        parseState = parseEnum.lookingForValue;
                        i          = j;
                    }
                    else if (Char.IsLetter(contents[i]))
                    {
                        //un-quoted key
                        int j = i;
                        while (contents[j] != ' ' && contents[j] != '\t' && contents[j] != '\n' && contents[j] != '\r')
                        {
                            j++;
                            if (j > contents.Length)
                            {
                                throw new KeyValueParsingException("Couldn't find end of key started at position " + i.ToString(), null);
                            }
                        }
                        KeyValue cur = new KeyValue(contents.Substring(i, j - i));
                        curparent.AddChild(cur);
                        curparent  = cur;
                        parseState = parseEnum.lookingForValue;
                        i          = j;
                    }
                    else if (contents[i] == '}')
                    {
                        //drop one level
                        curparent = curparent.Parent;
                    }
                    else if (contents[i] == '/')
                    {
                        if (i + 1 < contents.Length && contents[i + 1] == '/')
                        {
                            // we're in a comment! throw stuff away until the next \n
                            while (i < contents.Length && contents[i] != '\n')
                            {
                                i++;
                            }
                        }
                    }
                    else
                    {
                        throw new KeyValueParsingException("Unexpected '" + contents[i].ToString() + "' at position " + i.ToString(), null);
                    }
                    break;

                case parseEnum.lookingForValue:
                    if (contents[i] == '{')
                    {
                        // it's a list of children
                        // thankfully, we don't actually need to handle this!
                        parseState = parseEnum.lookingForKey;
                    }
                    else if (contents[i] == '"' || contents[i] == '\'')
                    {
                        //quoted value
                        int j = i + 1;
                        while (contents[j] != contents[i])
                        {
                            // handle escaped quotes
                            if (contents[j] == '\\')
                            {
                                j++;
                            }
                            j++;
                            if (j > contents.Length)
                            {
                                throw new KeyValueParsingException("Couldn't find terminating '" + contents[i].ToString() + "' for key started at position " + i.ToString(), null);
                            }
                        }
                        //ok, now contents[i] and contents[j] are the same character, on either end of the value
                        curparent.Set(contents.Substring(i + 1, j - (i + 1)));
                        curparent  = curparent.Parent;
                        parseState = parseEnum.lookingForKey;
                        i          = j;
                    }
                    else if (contents[i] == '/')
                    {
                        if (i + 1 < contents.Length && contents[i + 1] == '/')
                        {
                            // we're in a comment! throw stuff away until the next \n
                            while (i < contents.Length && contents[i] != '\n')
                            {
                                i++;
                            }
                        }
                    }
                    else if (!Char.IsWhiteSpace(contents[i]))
                    {
                        int j = i;
                        while (contents[j] != ' ' && contents[j] != '\t' && contents[j] != '\n' && contents[j] != '\r')
                        {
                            j++;
                            if (j > contents.Length)
                            {
                                // a value ending the file counts as ending the value
                                break;
                            }
                        }
                        curparent.Set(contents.Substring(i, j - i));
                        curparent  = curparent.Parent;
                        parseState = parseEnum.lookingForKey;
                        i          = j;
                    }
                    else
                    {
                        throw new KeyValueParsingException("Unexpected '" + contents[i].ToString() + "' at position " + i.ToString(), null);
                    }
                    break;
                }
            }
            // At the end of the file, we should be looking for another key
            if (parseState != parseEnum.lookingForKey)
            {
                throw new KeyNotFoundException("File ended while looking for value", null);
            }
            // At the end of the file, all block values should be closed
            if (curparent != basekv)
            {
                throw new KeyNotFoundException("Unterminated child blocks", null);
            }
            KeyValue[] ret = basekv.Children.ToArray <KeyValue>();
            basekv.clearChildParents();
            return(ret);
        }