From 73bd35f56189da4e9f5aaf4625247078e0486887 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 1 Mar 2021 23:23:37 -0800 Subject: Optimize SourceLineNumber and add support for setting Parent --- src/WixToolset.Data/SourceLineNumber.cs | 123 +++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/WixToolset.Data/SourceLineNumber.cs b/src/WixToolset.Data/SourceLineNumber.cs index 8ec65201..970f17e7 100644 --- a/src/WixToolset.Data/SourceLineNumber.cs +++ b/src/WixToolset.Data/SourceLineNumber.cs @@ -34,11 +34,35 @@ namespace WixToolset.Data this.LineNumber = lineNumber; } + /// + /// Constructor for a source with a parent and no line information. + /// + /// File name of the source. + /// Parent of this source line number + public SourceLineNumber(string fileName, SourceLineNumber parent) + { + this.FileName = fileName; + this.Parent = parent; + } + + /// + /// Constructor for a source with a parent and line information. + /// + /// File name of the source. + /// Parent of this source line number + /// Line number of the source. + public SourceLineNumber(string fileName, SourceLineNumber parent, int lineNumber) + { + this.FileName = fileName; + this.Parent = parent; + this.LineNumber = lineNumber; + } + /// /// Gets the file name of the source. /// /// File name for the source. - public string FileName { get; private set; } + public string FileName { get; } /// /// Gets or sets the line number of the source. @@ -49,19 +73,13 @@ namespace WixToolset.Data /// /// Gets or sets the parent source line number that included this source line number. /// - public SourceLineNumber Parent { get; set; } + public SourceLineNumber Parent { get; private set; } /// /// Gets the file name and line information. /// /// File name and line information. - public string QualifiedFileName - { - get - { - return this.LineNumber.HasValue ? String.Concat(this.FileName, "*", this.LineNumber) : this.FileName; - } - } + public string QualifiedFileName => this.LineNumber.HasValue ? String.Concat(this.FileName, "*", this.LineNumber) : this.FileName; internal static SourceLineNumber Deserialize(JsonObject jsonObject) { @@ -101,37 +119,46 @@ namespace WixToolset.Data /// Encoded string to parse. public static SourceLineNumber CreateFromEncoded(string encodedSourceLineNumbers) { - string[] linesSplit = encodedSourceLineNumbers.Split('|'); + var linesSplitIndex = encodedSourceLineNumbers.IndexOf('|'); - SourceLineNumber first = null; - SourceLineNumber parent = null; - for (int i = 0; i < linesSplit.Length; ++i) + // The most common case is that there is a single encoded line, + // so optimize for that case. + if (linesSplitIndex < 0) { - string[] filenameSplit = linesSplit[i].Split('*'); - SourceLineNumber source; - - if (2 == filenameSplit.Length) - { - source = new SourceLineNumber(filenameSplit[0], Convert.ToInt32(filenameSplit[1])); - } - else - { - source = new SourceLineNumber(filenameSplit[0]); - } + return DecodeSourceLineNumber(encodedSourceLineNumbers, 0, -1); + } + else // decode the multiple lines. + { + var startLine = 0; - if (null != parent) + SourceLineNumber first = null; + SourceLineNumber parent = null; + while (startLine < encodedSourceLineNumbers.Length) { - parent.Parent = source; + var source = DecodeSourceLineNumber(encodedSourceLineNumbers, startLine, linesSplitIndex - 1); + + if (null != parent) + { + parent.Parent = source; + } + + parent = source; + if (null == first) + { + first = parent; + } + + if (linesSplitIndex < 0) + { + break; + } + + startLine = linesSplitIndex + 1; + linesSplitIndex = encodedSourceLineNumbers.IndexOf('|', startLine); } - parent = source; - if (null == first) - { - first = parent; - } + return first; } - - return first; } /// @@ -159,11 +186,8 @@ namespace WixToolset.Data /// Optional line number offset into XML file not already included in the line information. public static SourceLineNumber CreateFromXObject(XObject node, int offset = 0) { - string uri = node.BaseUri; - IXmlLineInfo lineInfo = node as IXmlLineInfo; - - SourceLineNumber result = CreateFromUri(uri); - if (null != result && null != lineInfo) + var result = CreateFromUri(node.BaseUri); + if (null != result && node is IXmlLineInfo lineInfo) { result.LineNumber = lineInfo.LineNumber + offset; } @@ -191,12 +215,12 @@ namespace WixToolset.Data /// public string GetEncoded() { - StringBuilder sb = new StringBuilder(this.QualifiedFileName); + var sb = new StringBuilder(this.QualifiedFileName); - for (SourceLineNumber source = this.Parent; null != source; source = source.Parent) + for (var parent = this.Parent; null != parent; parent = parent.Parent) { sb.Append("|"); - sb.Append(source.QualifiedFileName); + sb.Append(parent.QualifiedFileName); } return sb.ToString(); @@ -209,8 +233,7 @@ namespace WixToolset.Data /// True if SourceLineNumbers are equivalent. public override bool Equals(object obj) { - SourceLineNumber other = obj as SourceLineNumber; - return null != other && + return obj is SourceLineNumber other && this.LineNumber.HasValue == other.LineNumber.HasValue && (!this.LineNumber.HasValue || this.LineNumber == other.LineNumber) && this.FileName.Equals(other.FileName, StringComparison.OrdinalIgnoreCase) && @@ -234,5 +257,19 @@ namespace WixToolset.Data { return this.LineNumber.HasValue && !String.IsNullOrEmpty(this.FileName) ? String.Concat(this.FileName, "(", this.LineNumber, ")") : this.FileName ?? String.Empty; } + + private static SourceLineNumber DecodeSourceLineNumber(string encoded, int startIndex, int endIndex) + { + if (endIndex < 0) + { + endIndex = encoded.Length - 1; + } + + var count = endIndex - startIndex; + var filenameSplitIndex = encoded.LastIndexOf('*', endIndex - 1, count); + return (filenameSplitIndex < 0) ? new SourceLineNumber(encoded) : + new SourceLineNumber(encoded.Substring(startIndex, filenameSplitIndex - startIndex), + Convert.ToInt32(encoded.Substring(filenameSplitIndex + 1, endIndex - filenameSplitIndex))); + } } } -- cgit v1.2.3-55-g6feb