Example #1
0
        static List <MiniYamlNode> FromLines(string[] lines, string filename)
        {
            var levels = new List <List <MiniYamlNode> >();

            levels.Add(new List <MiniYamlNode>());

            var lineNo = 0;

            foreach (var ll in lines)
            {
                var line = ll;
                ++lineNo;
                if (line.Contains('#'))
                {
                    line = line.Substring(0, line.IndexOf('#')).TrimEnd(' ', '\t');
                }
                var t = line.TrimStart(' ', '\t');
                if (t.Length == 0)
                {
                    continue;
                }
                var level    = line.Length - t.Length;
                var location = new MiniYamlNode.SourceLocation {
                    Filename = filename, Line = lineNo
                };

                if (levels.Count <= level)
                {
                    throw new YamlException("Bad indent in miniyaml at {0}".F(location));
                }
                while (levels.Count > level + 1)
                {
                    levels.RemoveAt(levels.Count - 1);
                }

                var d   = new List <MiniYamlNode>();
                var rhs = SplitAtColon(ref t);
                levels[level].Add(new MiniYamlNode(t, rhs, d, location));

                levels.Add(d);
            }

            return(levels[0]);
        }
Example #2
0
        static List <MiniYamlNode> FromLines(IEnumerable <string> lines, string filename, bool discardCommentsAndWhitespace, Dictionary <string, string> stringPool)
        {
            if (stringPool == null)
            {
                stringPool = new Dictionary <string, string>();
            }

            var levels = new List <List <MiniYamlNode> >();

            levels.Add(new List <MiniYamlNode>());

            var lineNo = 0;

            foreach (var ll in lines)
            {
                var line = ll;
                ++lineNo;

                var keyStart  = 0;
                var level     = 0;
                var spaces    = 0;
                var textStart = false;

                string key      = null;
                string value    = null;
                string comment  = null;
                var    location = new MiniYamlNode.SourceLocation {
                    Filename = filename, Line = lineNo
                };

                if (line.Length > 0)
                {
                    var currChar = line[keyStart];

                    while (!(currChar == '\n' || currChar == '\r') && keyStart < line.Length && !textStart)
                    {
                        currChar = line[keyStart];
                        switch (currChar)
                        {
                        case ' ':
                            spaces++;
                            if (spaces >= SpacesPerLevel)
                            {
                                spaces = 0;
                                level++;
                            }

                            keyStart++;
                            break;

                        case '\t':
                            level++;
                            keyStart++;
                            break;

                        default:
                            textStart = true;
                            break;
                        }
                    }

                    if (levels.Count <= level)
                    {
                        throw new YamlException("Bad indent in miniyaml at {0}".F(location));
                    }

                    while (levels.Count > level + 1)
                    {
                        levels.RemoveAt(levels.Count - 1);
                    }

                    // Extract key, value, comment from line as `<key>: <value>#<comment>`
                    // The # character is allowed in the value if escaped (\#).
                    // Leading and trailing whitespace is always trimmed from keys.
                    // Leading and trailing whitespace is trimmed from values unless they
                    // are marked with leading or trailing backslashes
                    var keyLength    = line.Length - keyStart;
                    var valueStart   = -1;
                    var valueLength  = 0;
                    var commentStart = -1;
                    for (var i = 0; i < line.Length; i++)
                    {
                        if (valueStart < 0 && line[i] == ':')
                        {
                            valueStart  = i + 1;
                            keyLength   = i - keyStart;
                            valueLength = line.Length - i - 1;
                        }

                        if (commentStart < 0 && line[i] == '#' && (i == 0 || line[i - 1] != '\\'))
                        {
                            commentStart = i + 1;
                            if (commentStart <= keyLength)
                            {
                                keyLength = i - keyStart;
                            }
                            else
                            {
                                valueLength = i - valueStart;
                            }

                            break;
                        }
                    }

                    if (keyLength > 0)
                    {
                        key = line.Substring(keyStart, keyLength).Trim();
                    }

                    if (valueStart >= 0)
                    {
                        var trimmed = line.Substring(valueStart, valueLength).Trim();
                        if (trimmed.Length > 0)
                        {
                            value = trimmed;
                        }
                    }

                    if (commentStart >= 0 && !discardCommentsAndWhitespace)
                    {
                        comment = line.Substring(commentStart);
                    }

                    // Remove leading/trailing whitespace guards
                    if (value != null && value.Length > 1)
                    {
                        var trimLeading  = value[0] == '\\' && (value[1] == ' ' || value[1] == '\t') ? 1 : 0;
                        var trimTrailing = value[value.Length - 1] == '\\' && (value[value.Length - 2] == ' ' || value[value.Length - 2] == '\t') ? 1 : 0;
                        if (trimLeading + trimTrailing > 0)
                        {
                            value = value.Substring(trimLeading, value.Length - trimLeading - trimTrailing);
                        }
                    }

                    // Remove escape characters from #
                    if (value != null && value.IndexOf('#') != -1)
                    {
                        value = value.Replace("\\#", "#");
                    }
                }

                if (key != null || !discardCommentsAndWhitespace)
                {
                    key     = key == null ? null : stringPool.GetOrAdd(key, key);
                    value   = value == null ? null : stringPool.GetOrAdd(value, value);
                    comment = comment == null ? null : stringPool.GetOrAdd(comment, comment);

                    var nodes = new List <MiniYamlNode>();
                    levels[level].Add(new MiniYamlNode(key, value, comment, nodes, location));

                    levels.Add(nodes);
                }
            }

            foreach (var nodes in levels)
            {
                nodes.TrimExcess();
            }

            return(levels[0]);
        }
Example #3
0
        static List <MiniYamlNode> FromLines(IEnumerable <string> lines, string filename)
        {
            var levels = new List <List <MiniYamlNode> >();

            levels.Add(new List <MiniYamlNode>());

            var lineNo = 0;

            foreach (var ll in lines)
            {
                var line = ll;
                ++lineNo;

                var commentIndex = line.IndexOf('#');
                if (commentIndex != -1)
                {
                    line = line.Substring(0, commentIndex).TrimEnd(' ', '\t');
                }

                if (line.Length == 0)
                {
                    continue;
                }

                var charPosition = 0;
                var level        = 0;
                var spaces       = 0;
                var textStart    = false;
                var currChar     = line[charPosition];

                while (!(currChar == '\n' || currChar == '\r') && charPosition < line.Length && !textStart)
                {
                    currChar = line[charPosition];
                    switch (currChar)
                    {
                    case ' ':
                        spaces++;
                        if (spaces >= SpacesPerLevel)
                        {
                            spaces = 0;
                            level++;
                        }

                        charPosition++;
                        break;

                    case '\t':
                        level++;
                        charPosition++;
                        break;

                    default:
                        textStart = true;
                        break;
                    }
                }

                var realText = line.Substring(charPosition);
                if (realText.Length == 0)
                {
                    continue;
                }

                var location = new MiniYamlNode.SourceLocation {
                    Filename = filename, Line = lineNo
                };

                if (levels.Count <= level)
                {
                    throw new YamlException("Bad indent in miniyaml at {0}".F(location));
                }

                while (levels.Count > level + 1)
                {
                    levels.RemoveAt(levels.Count - 1);
                }

                var d   = new List <MiniYamlNode>();
                var rhs = SplitAtColon(ref realText);
                levels[level].Add(new MiniYamlNode(realText, rhs, d, location));

                levels.Add(d);
            }

            return(levels[0]);
        }
Example #4
0
        static List <MiniYamlNode> FromLines(IEnumerable <ReadOnlyMemory <char> > lines, string filename, bool discardCommentsAndWhitespace, Dictionary <string, string> stringPool)
        {
            if (stringPool == null)
            {
                stringPool = new Dictionary <string, string>();
            }

            var levels = new List <List <MiniYamlNode> >();

            levels.Add(new List <MiniYamlNode>());

            var lineNo = 0;

            foreach (var ll in lines)
            {
                var line = ll.Span;
                ++lineNo;

                var keyStart  = 0;
                var level     = 0;
                var spaces    = 0;
                var textStart = false;

                ReadOnlySpan <char> key     = default;
                ReadOnlySpan <char> value   = default;
                ReadOnlySpan <char> comment = default;
                var location = new MiniYamlNode.SourceLocation {
                    Filename = filename, Line = lineNo
                };

                if (line.Length > 0)
                {
                    var currChar = line[keyStart];

                    while (!(currChar == '\n' || currChar == '\r') && keyStart < line.Length && !textStart)
                    {
                        currChar = line[keyStart];
                        switch (currChar)
                        {
                        case ' ':
                            spaces++;
                            if (spaces >= SpacesPerLevel)
                            {
                                spaces = 0;
                                level++;
                            }

                            keyStart++;
                            break;

                        case '\t':
                            level++;
                            keyStart++;
                            break;

                        default:
                            textStart = true;
                            break;
                        }
                    }

                    if (levels.Count <= level)
                    {
                        throw new YamlException($"Bad indent in miniyaml at {location}");
                    }

                    while (levels.Count > level + 1)
                    {
                        levels[levels.Count - 1].TrimExcess();
                        levels.RemoveAt(levels.Count - 1);
                    }

                    // Extract key, value, comment from line as `<key>: <value>#<comment>`
                    // The # character is allowed in the value if escaped (\#).
                    // Leading and trailing whitespace is always trimmed from keys.
                    // Leading and trailing whitespace is trimmed from values unless they
                    // are marked with leading or trailing backslashes
                    var keyLength    = line.Length - keyStart;
                    var valueStart   = -1;
                    var valueLength  = 0;
                    var commentStart = -1;
                    for (var i = 0; i < line.Length; i++)
                    {
                        if (valueStart < 0 && line[i] == ':')
                        {
                            valueStart  = i + 1;
                            keyLength   = i - keyStart;
                            valueLength = line.Length - i - 1;
                        }

                        if (commentStart < 0 && line[i] == '#' && (i == 0 || line[i - 1] != '\\'))
                        {
                            commentStart = i + 1;
                            if (commentStart <= keyLength)
                            {
                                keyLength = i - keyStart;
                            }
                            else
                            {
                                valueLength = i - valueStart;
                            }

                            break;
                        }
                    }

                    if (keyLength > 0)
                    {
                        key = line.Slice(keyStart, keyLength).Trim();
                    }

                    if (valueStart >= 0)
                    {
                        var trimmed = line.Slice(valueStart, valueLength).Trim();
                        if (trimmed.Length > 0)
                        {
                            value = trimmed;
                        }
                    }

                    if (commentStart >= 0 && !discardCommentsAndWhitespace)
                    {
                        comment = line.Slice(commentStart);
                    }

                    if (value.Length > 1)
                    {
                        // Remove leading/trailing whitespace guards
                        var trimLeading  = value[0] == '\\' && (value[1] == ' ' || value[1] == '\t') ? 1 : 0;
                        var trimTrailing = value[value.Length - 1] == '\\' && (value[value.Length - 2] == ' ' || value[value.Length - 2] == '\t') ? 1 : 0;
                        if (trimLeading + trimTrailing > 0)
                        {
                            value = value.Slice(trimLeading, value.Length - trimLeading - trimTrailing);
                        }

                        // Remove escape characters from #
                        if (value.Contains("\\#", StringComparison.Ordinal))
                        {
                            value = value.ToString().Replace("\\#", "#");
                        }
                    }
                }

                if (!key.IsEmpty || !discardCommentsAndWhitespace)
                {
                    var keyString   = key.IsEmpty ? null : key.ToString();
                    var valueString = value.IsEmpty ? null : value.ToString();

                    // Note: We need to support empty comments here to ensure that empty comments
                    // (i.e. a lone # at the end of a line) can be correctly re-serialized
                    var commentString = comment == default ? null : comment.ToString();

                    keyString     = keyString == null ? null : stringPool.GetOrAdd(keyString, keyString);
                    valueString   = valueString == null ? null : stringPool.GetOrAdd(valueString, valueString);
                    commentString = commentString == null ? null : stringPool.GetOrAdd(commentString, commentString);

                    var nodes = new List <MiniYamlNode>();
                    levels[level].Add(new MiniYamlNode(keyString, valueString, commentString, nodes, location));

                    levels.Add(nodes);
                }
            }

            foreach (var nodes in levels)
            {
                nodes.TrimExcess();
            }

            return(levels[0]);
        }