Skip to content

Commit

Permalink
Use Span<T> on all platforms that support it (#6130)
Browse files Browse the repository at this point in the history
  • Loading branch information
ladipro committed Feb 9, 2021
1 parent 9657f12 commit 31a98dc
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 65 deletions.
1 change: 0 additions & 1 deletion src/Directory.BeforeCommon.targets
Expand Up @@ -127,7 +127,6 @@
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1' or '$(TargetFramework)' == 'net5.0'">
<DefineConstants>$(DefineConstants);FEATURE_PIPEOPTIONS_CURRENTUSERONLY</DefineConstants>
<DefineConstants Condition="'$(MachineIndependentBuild)' != 'true'">$(DefineConstants);FEATURE_NODE_REUSE</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SPAN</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(GenerateReferenceAssemblySources)' != 'true'">
Expand Down
67 changes: 3 additions & 64 deletions src/Shared/FileUtilities.cs
Expand Up @@ -450,6 +450,7 @@ internal static string FixFilePath(string path)
return string.IsNullOrEmpty(path) || Path.DirectorySeparatorChar == '\\' ? path : path.Replace('\\', '/');//.Replace("//", "/");
}

#if !CLR2COMPATIBILITY
/// <summary>
/// If on Unix, convert backslashes to slashes for strings that resemble paths.
/// The heuristic is if something resembles paths (contains slashes) check if the
Expand All @@ -473,60 +474,13 @@ internal static string MaybeAdjustFilePath(string value, string baseDirectory =
}

// For Unix-like systems, we may want to convert backslashes to slashes
#if FEATURE_SPAN
Span<char> newValue = ConvertToUnixSlashes(value.ToCharArray());
#else
string newValue = ConvertToUnixSlashes(value);
#endif

// Find the part of the name we want to check, that is remove quotes, if present
bool shouldAdjust = newValue.IndexOf('/') != -1 && LooksLikeUnixFilePath(RemoveQuotes(newValue), baseDirectory);
return shouldAdjust ? newValue.ToString() : value;
}

#if !FEATURE_SPAN
private static string ConvertToUnixSlashes(string path)
{
if (path.IndexOf('\\') == -1)
{
return path;
}
StringBuilder unixPath = StringBuilderCache.Acquire(path.Length);
CopyAndCollapseSlashes(path, unixPath);
return StringBuilderCache.GetStringAndRelease(unixPath);
}

#if !CLR2COMPATIBILITY && !FEATURE_SPAN
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static void CopyAndCollapseSlashes(string str, StringBuilder copy)
{
// Performs Regex.Replace(str, @"[\\/]+", "/")
for (int i = 0; i < str.Length; i++)
{
bool isCurSlash = IsAnySlash(str[i]);
bool isPrevSlash = i > 0 && IsAnySlash(str[i - 1]);

if (!isCurSlash || !isPrevSlash)
{
copy.Append(str[i] == '\\' ? '/' : str[i]);
}
}
}

private static string RemoveQuotes(string path)
{
int endId = path.Length - 1;
char singleQuote = '\'';
char doubleQuote = '\"';

bool hasQuotes = path.Length > 2
&& ((path[0] == singleQuote && path[endId] == singleQuote)
|| (path[0] == doubleQuote && path[endId] == doubleQuote));

return hasQuotes ? path.Substring(1, endId - 1) : path;
}
#else
private static Span<char> ConvertToUnixSlashes(Span<char> path)
{
return path.IndexOf('\\') == -1 ? path : CollapseSlashes(path);
Expand Down Expand Up @@ -572,6 +526,7 @@ private static Span<char> RemoveQuotes(Span<char> path)
#endif
internal static bool IsAnySlash(char c) => c == '/' || c == '\\';

#if !CLR2COMPATIBILITY
/// <summary>
/// If on Unix, check if the string looks like a file path.
/// The heuristic is if something resembles paths (contains slashes) check if the
Expand All @@ -581,24 +536,8 @@ private static Span<char> RemoveQuotes(Span<char> path)
/// that
/// </summary>
internal static bool LooksLikeUnixFilePath(string value, string baseDirectory = "")
{
if (NativeMethodsShared.IsWindows)
{
return false;
}

// The first slash will either be at the beginning of the string or after the first directory name
int directoryLength = value.IndexOf('/', 1) + 1;
bool shouldCheckDirectory = directoryLength != 0;

// Check for actual files or directories under / that get missed by the above logic
bool shouldCheckFileOrDirectory = !shouldCheckDirectory && value.Length > 0 && value[0] == '/';

return (shouldCheckDirectory && DefaultFileSystem.DirectoryExists(Path.Combine(baseDirectory, value.Substring(0, directoryLength))))
|| (shouldCheckFileOrDirectory && DefaultFileSystem.DirectoryEntryExists(value));
}
=> LooksLikeUnixFilePath(value.AsSpan(), baseDirectory);

#if FEATURE_SPAN
internal static bool LooksLikeUnixFilePath(ReadOnlySpan<char> value, string baseDirectory = "")
{
if (NativeMethodsShared.IsWindows)
Expand Down

0 comments on commit 31a98dc

Please sign in to comment.