Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Span<T> on all platforms that support it #6130

Merged
merged 1 commit into from Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -451,6 +451,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 @@ -474,60 +475,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 @@ -573,6 +527,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 @@ -582,24 +537,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