Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions src/Build/Evaluation/Expander.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,6 @@ private void FlushFirstValueIfNeeded()
/// Enabled by ExpanderOptions.Truncate.
/// </summary>
private const int ItemLimitPerExpansion = 3;
private static readonly char[] s_singleQuoteChar = { '\'' };
private static readonly char[] s_backtickChar = { '`' };
private static readonly char[] s_doubleQuoteChar = { '"' };

/// <summary>
/// The CultureInfo from the invariant culture. Used to avoid allocations for
Expand Down Expand Up @@ -785,37 +782,34 @@ private static void AddArgument(List<string> arguments, SpanBasedStringBuilder a
// we reached the end of an argument, add the builder's final result
// to our arguments.
argumentBuilder.Trim();
string argValue = argumentBuilder.ToString();

// We support passing of null through the argument constant value null
if (String.Equals("null", argValue, StringComparison.OrdinalIgnoreCase))
if (argumentBuilder.Equals("null", StringComparison.OrdinalIgnoreCase))
{
arguments.Add(null);
}
else
{
if (argValue.Length > 0)
if (argumentBuilder.Length > 0)
{
if (argValue[0] == '\'' && argValue[argValue.Length - 1] == '\'')
if (argumentBuilder[0] == '\'' && argumentBuilder[argumentBuilder.Length - 1] == '\'')
{
arguments.Add(argValue.Trim(s_singleQuoteChar));
argumentBuilder.Trim('\'');
}
else if (argValue[0] == '`' && argValue[argValue.Length - 1] == '`')
else if (argumentBuilder[0] == '`' && argumentBuilder[argumentBuilder.Length - 1] == '`')
{
arguments.Add(argValue.Trim(s_backtickChar));
argumentBuilder.Trim('`');
}
else if (argValue[0] == '"' && argValue[argValue.Length - 1] == '"')
else if (argumentBuilder[0] == '"' && argumentBuilder[argumentBuilder.Length - 1] == '"')
{
arguments.Add(argValue.Trim(s_doubleQuoteChar));
}
else
{
arguments.Add(argValue);
argumentBuilder.Trim('"');
}

arguments.Add(argumentBuilder.ToString());
}
else
{
arguments.Add(argValue);
arguments.Add(string.Empty);
}
}
}
Expand Down
121 changes: 114 additions & 7 deletions src/StringTools/SpanBasedStringBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,48 @@ public SpanBasedStringBuilder(int capacity = 4)
/// </summary>
public int Capacity => _spans.Capacity;

public char this[int index]
{
get
{
if (index < 0 || index >= Length)
{
throw new ArgumentOutOfRangeException(nameof(index));
}

int adjustedIndex = index;
foreach (ReadOnlyMemory<char> span in _spans)
{
if (adjustedIndex < span.Length)
{
return span.Span[adjustedIndex];
}
else
{
adjustedIndex -= span.Length;
}
}

// Should never reach here if Length is correct
throw new IndexOutOfRangeException();
}
}

/// <summary>
/// Creates a new enumerator for enumerating characters in this string. Does not allocate.
/// </summary>
/// <returns>The enumerator.</returns>
public Enumerator GetEnumerator()
{
return new Enumerator(_spans);
}

public bool Equals(ReadOnlySpan<char> other)
{
return Equals(other, StringComparison.Ordinal);
}

public bool Equals(ReadOnlySpan<char> other, StringComparison comparison)
{
if (_spans.Count == 0 && other.IsEmpty)
{
Expand All @@ -135,7 +176,7 @@ public bool Equals(ReadOnlySpan<char> other)
int otherIndex = 0;
foreach (ReadOnlyMemory<char> internalSpan in _spans)
{
if (!MemoryExtensions.Equals(other.Slice(otherIndex, internalSpan.Length), internalSpan.Span, StringComparison.Ordinal))
if (!MemoryExtensions.Equals(other.Slice(otherIndex, internalSpan.Length), internalSpan.Span, comparison))
{
return false;
}
Expand All @@ -146,13 +187,29 @@ public bool Equals(ReadOnlySpan<char> other)
return true;
}

/// <summary>
/// Creates a new enumerator for enumerating characters in this string. Does not allocate.
/// </summary>
/// <returns>The enumerator.</returns>
public Enumerator GetEnumerator()
public bool Equals(string other)
{
return new Enumerator(_spans);
return Equals(other, StringComparison.Ordinal);
}

public bool Equals(string other, StringComparison comparison)
{
if (other.Length != Length)
{
return false;
}

int index = 0;
ReadOnlySpan<char> inputSpan = other.AsSpan();
foreach (ReadOnlyMemory<char> memory in _spans)
{
if (!MemoryExtensions.Equals(memory.Span, inputSpan.Slice(index, memory.Length), comparison))
{
return false;
}
}

return true;
}

/// <summary>
Expand Down Expand Up @@ -252,6 +309,28 @@ public void TrimStart()
}
}

public void TrimStart(char c)
{
for (int spanIdx = 0; spanIdx < _spans.Count; spanIdx++)
{
ReadOnlySpan<char> span = _spans[spanIdx].Span;
int i = 0;
while (i < span.Length && span[i] == c)
{
i++;
}
if (i > 0)
{
_spans[spanIdx] = _spans[spanIdx].Slice(i);
Length -= i;
}
if (!_spans[spanIdx].IsEmpty)
{
return;
}
}
}

/// <summary>
/// Removes trailing white-space characters from the string.
/// </summary>
Expand All @@ -277,6 +356,28 @@ public void TrimEnd()
}
}

public void TrimEnd(char c)
{
for (int spanIdx = _spans.Count - 1; spanIdx >= 0; spanIdx--)
{
ReadOnlySpan<char> span = _spans[spanIdx].Span;
int i = span.Length - 1;
while (i >= 0 && span[i] == c)
{
i--;
}
if (i + 1 < span.Length)
{
_spans[spanIdx] = _spans[spanIdx].Slice(0, i + 1);
Length -= span.Length - (i + 1);
}
if (!_spans[spanIdx].IsEmpty)
{
return;
}
}
}

/// <summary>
/// Removes leading and trailing white-space characters from the string.
/// </summary>
Expand All @@ -286,6 +387,12 @@ public void Trim()
TrimEnd();
}

public void Trim(char c)
{
TrimStart(c);
TrimEnd(c);
}

/// <summary>
/// Clears this instance making it represent an empty string.
/// </summary>
Expand Down
Loading