Ejemplo n.º 1
0
        /// <summary>
        /// Parses a log output string to a list of Items (e.g. ItemGroup with metadata or property string).
        /// </summary>
        /// <param name="message">The message output from the logger.</param>
        /// <param name="prefix">The prefix parsed out (e.g. 'Output Item(s): '.).</param>
        /// <returns>List of items within the list and all metadata.</returns>
        public static BaseNode ParsePropertyOrItemList(string message, string prefix, StringCache stringTable, bool isOutputItem = false)
        {
            if (!TextUtilities.ContainsLineBreak(message))
            {
                var nameValue = TextUtilities.ParseNameValue(message, trimFromStart: prefix.Length);
                if (!isOutputItem)
                {
                    var property = new Property
                    {
                        Name  = stringTable.Intern(nameValue.Key),
                        Value = stringTable.Intern(nameValue.Value)
                    };
                    return(property);
                }
                else
                {
                    var singleItem = new AddItem {
                        Name = stringTable.Intern(nameValue.Key)
                    };
                    var item = new Item {
                        Text = stringTable.Intern(nameValue.Value)
                    };
                    singleItem.AddChild(item);
                    return(singleItem);
                }
            }

            // Can't use a field initializer with ThreadStatic.
            if (lineSpans == null)
            {
                lineSpans = new List <Span>(10240);
            }

            lineSpans.Clear();
            message.CollectLineSpans(lineSpans, includeLineBreakInSpan: false);

            NamedNode parameter = isOutputItem ? new AddItem() : new Parameter();

            if (lineSpans[0].Length > prefix.Length)
            {
                // we have a weird case of multi-line value
                var nameValue = TextUtilities.ParseNameValue(message, lineSpans[0].Skip(prefix.Length));

                parameter.Name = stringTable.Intern(nameValue.Key);

                parameter.AddChild(new Item
                {
                    Text = stringTable.Intern(nameValue.Value)
                });

                for (int i = 1; i < lineSpans.Count; i++)
                {
                    parameter.AddChild(new Item
                    {
                        Text = stringTable.Intern(message.Substring(lineSpans[i]))
                    });
                }

                return(parameter);
            }

            Item     currentItem     = null;
            Property currentProperty = null;

            foreach (var lineSpan in lineSpans)
            {
                if (TextUtilities.IsWhitespace(message, lineSpan))
                {
                    continue;
                }

                var numberOfLeadingSpaces = TextUtilities.GetNumberOfLeadingSpaces(message, lineSpan);
                switch (numberOfLeadingSpaces)
                {
                case 4:
                    if (message[lineSpan.End - 1] == '=')
                    {
                        parameter.Name = stringTable.Intern(message.Substring(lineSpan.Start + 4, lineSpan.Length - 5));
                    }
                    break;

                case 8:
                    var skip8  = message.Substring(lineSpan.Skip(8));
                    var equals = skip8.IndexOf('=');
                    if (equals != -1)
                    {
                        var kvp = TextUtilities.ParseNameValueWithEqualsPosition(skip8, equals);
                        currentProperty = new Property
                        {
                            Name  = stringTable.Intern(kvp.Key),
                            Value = stringTable.Intern(kvp.Value)
                        };
                        parameter.AddChild(currentProperty);
                        currentItem = null;
                    }
                    else
                    {
                        currentItem = new Item
                        {
                            Text = stringTable.Intern(skip8)
                        };
                        parameter.AddChild(currentItem);
                        currentProperty = null;
                    }
                    break;

                case 16:
                    if (currentItem == null && currentProperty != null)
                    {
                        // we incorrectly interpreted the previous line as Property, not Item (because it had '=')
                        // and so we created a property out of name/value.
                        // Fix this by turning it into an Item.
                        if (parameter.LastChild == currentProperty)
                        {
                            currentItem = new Item
                            {
                                Text = stringTable.Intern(currentProperty.Name + "=" + currentProperty.Value)
                            };
                            parameter.Children.RemoveAt(parameter.Children.Count - 1);
                            currentProperty = null;
                            parameter.AddChild(currentItem);
                        }
                    }

                    if (currentItem != null)
                    {
                        var span16   = lineSpan.Skip(16);
                        var equals16 = message.IndexOf(span16, '=');
                        if (equals16 == -1)
                        {
                            // must be a continuation of the metadata value from the previous line
                            if (currentItem.HasChildren)
                            {
                                var metadata = currentItem.Children[currentItem.Children.Count - 1] as Metadata;
                                if (metadata != null)
                                {
                                    var currentLine = message.Substring(span16);
                                    if (!string.IsNullOrEmpty(metadata.Value))
                                    {
                                        metadata.Value = metadata.Value + currentLine;
                                    }
                                    else
                                    {
                                        metadata.Value = currentLine;
                                    }
                                }
                            }
                        }
                        else
                        {
                            var nameValue = TextUtilities.ParseNameValueWithEqualsPosition(message, span16, equals16);
                            var metadata  = new Metadata
                            {
                                Name  = stringTable.Intern(nameValue.Key),
                                Value = stringTable.Intern(nameValue.Value)
                            };
                            currentItem.AddChild(metadata);
                        }
                    }
                    break;

                default:
                    var line = message.Substring(lineSpan);
                    if (numberOfLeadingSpaces == 0 && line == prefix)
                    {
                        continue;
                    }

                    // must be a continuation of a multi-line value
                    if (currentProperty != null)
                    {
                        currentProperty.Value += "\n" + line;
                    }
                    else if (currentItem != null && currentItem.HasChildren)
                    {
                        var metadata = currentItem.Children[currentItem.Children.Count - 1] as Metadata;
                        if (metadata != null)
                        {
                            metadata.Value = (metadata.Value ?? "") + line;
                        }
                    }
                    break;
                }
            }

            return(parameter);
        }