Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/IO/Path.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.cs187
1 files changed, 62 insertions, 125 deletions
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.cs b/src/System.Private.CoreLib/shared/System/IO/Path.cs
index 41ae1cd0b..7b4565a13 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.cs
@@ -6,7 +6,14 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
+#if MS_IO_REDIST
+using System;
+using System.IO;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
// Provides methods for processing file system strings in a cross-platform manner.
// Most of the methods don't do a complete parsing (such as examining a UNC hostname),
@@ -79,10 +86,10 @@ namespace System.IO
/// </remarks>
public static string GetDirectoryName(string path)
{
- if (path == null || PathInternal.IsEffectivelyEmpty(path))
+ if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan()))
return null;
- int end = GetDirectoryNameOffset(path);
+ int end = GetDirectoryNameOffset(path.AsSpan());
return end >= 0 ? PathInternal.NormalizeDirectorySeparators(path.Substring(0, end)) : null;
}
@@ -130,7 +137,7 @@ namespace System.IO
if (path == null)
return null;
- return new string(GetExtension(path.AsSpan()));
+ return GetExtension(path.AsSpan()).ToString();
}
/// <summary>
@@ -173,7 +180,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -204,7 +211,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -388,9 +395,9 @@ namespace System.IO
public static string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2)
{
if (path1.Length == 0)
- return new string(path2);
+ return path2.ToString();
if (path2.Length == 0)
- return new string(path1);
+ return path1.ToString();
return JoinInternal(path1, path2);
}
@@ -409,6 +416,16 @@ namespace System.IO
return JoinInternal(path1, path2, path3);
}
+ public static string Join(string path1, string path2)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan());
+ }
+
+ public static string Join(string path1, string path2, string path3)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan());
+ }
+
public static bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten)
{
charsWritten = 0;
@@ -477,22 +494,6 @@ namespace System.IO
return true;
}
- private static string CombineInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
- {
- if (first.Length == 0)
- return second.Length == 0
- ? string.Empty
- : new string(second);
-
- if (second.Length == 0)
- return new string(first);
-
- if (IsPathRooted(second))
- return new string(second);
-
- return JoinInternal(first, second);
- }
-
private static string CombineInternal(string first, string second)
{
if (string.IsNullOrEmpty(first))
@@ -504,7 +505,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return second;
- return JoinInternal(first, second);
+ return JoinInternal(first.AsSpan(), second.AsSpan());
}
private static string CombineInternal(string first, string second, string third)
@@ -521,7 +522,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third);
- return JoinInternal(first, second, third);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan());
}
private static string CombineInternal(string first, string second, string third, string fourth)
@@ -542,10 +543,10 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third, fourth);
- return JoinInternal(first, second, third, fourth);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan(), fourth.AsSpan());
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
{
Debug.Assert(first.Length > 0 && second.Length > 0, "should have dealt with empty paths");
@@ -554,7 +555,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + (hasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length, HasSeparator: hasSeparator),
(destination, state) =>
@@ -567,7 +572,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0, "should have dealt with empty paths");
@@ -578,7 +583,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, FirstHasSeparator: firstHasSeparator, ThirdHasSeparator: thirdHasSeparator),
@@ -595,7 +604,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0 && fourth.Length > 0, "should have dealt with empty paths");
@@ -608,7 +617,12 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third), u = &MemoryMarshal.GetReference(fourth))
{
+
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + fourth.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1) + (fourthHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, Fourth: (IntPtr)u, FourthLength:fourth.Length,
@@ -688,93 +702,6 @@ namespace System.IO
}
/// <summary>
- /// Try to remove relative segments from the given path (without combining with a root).
- /// </summary>
- /// <param name="skip">Skip the specified number of characters before evaluating.</param>
- private static string RemoveRelativeSegments(string path, int skip = 0)
- {
- bool flippedSeparator = false;
-
- // Remove "//", "/./", and "/../" from the path by copying each character to the output,
- // except the ones we're removing, such that the builder contains the normalized path
- // at the end.
- StringBuilder sb = StringBuilderCache.Acquire(path.Length);
- if (skip > 0)
- {
- sb.Append(path, 0, skip);
- }
-
- for (int i = skip; i < path.Length; i++)
- {
- char c = path[i];
-
- if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
- {
- // Skip this character if it's a directory separator and if the next character is, too,
- // e.g. "parent//child" => "parent/child"
- if (PathInternal.IsDirectorySeparator(path[i + 1]))
- {
- continue;
- }
-
- // Skip this character and the next if it's referring to the current directory,
- // e.g. "parent/./child" => "parent/child"
- if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
- path[i + 1] == '.')
- {
- i++;
- continue;
- }
-
- // Skip this character and the next two if it's referring to the parent directory,
- // e.g. "parent/child/../grandchild" => "parent/grandchild"
- if (i + 2 < path.Length &&
- (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
- path[i + 1] == '.' && path[i + 2] == '.')
- {
- // Unwind back to the last slash (and if there isn't one, clear out everything).
- int s;
- for (s = sb.Length - 1; s >= 0; s--)
- {
- if (PathInternal.IsDirectorySeparator(sb[s]))
- {
- sb.Length = s;
- break;
- }
- }
- if (s < 0)
- {
- sb.Length = 0;
- }
-
- i += 2;
- continue;
- }
- }
-
- // Normalize the directory separator if needed
- if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
- {
- c = PathInternal.DirectorySeparatorChar;
- flippedSeparator = true;
- }
-
- sb.Append(c);
- }
-
- if (flippedSeparator || sb.Length != path.Length)
- {
- return StringBuilderCache.GetStringAndRelease(sb);
- }
- else
- {
- // We haven't changed the source path, return the original
- StringBuilderCache.Release(sb);
- return path;
- }
- }
-
- /// <summary>
/// Create a relative path from one path to another. Paths will be resolved before calculating the difference.
/// Default path comparison for the active platform will be used (OrdinalIgnoreCase for Windows or Mac, Ordinal for Unix).
/// </summary>
@@ -790,7 +717,7 @@ namespace System.IO
private static string GetRelativePath(string relativeTo, string path, StringComparison comparisonType)
{
if (string.IsNullOrEmpty(relativeTo)) throw new ArgumentNullException(nameof(relativeTo));
- if (PathInternal.IsEffectivelyEmpty(path)) throw new ArgumentNullException(nameof(path));
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan())) throw new ArgumentNullException(nameof(path));
Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
relativeTo = GetFullPath(relativeTo);
@@ -808,10 +735,10 @@ namespace System.IO
// Trailing separators aren't significant for comparison
int relativeToLength = relativeTo.Length;
- if (PathInternal.EndsInDirectorySeparator(relativeTo))
+ if (PathInternal.EndsInDirectorySeparator(relativeTo.AsSpan()))
relativeToLength--;
- bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path);
+ bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path.AsSpan());
int pathLength = path.Length;
if (pathEndsInSeparator)
pathLength--;
@@ -834,13 +761,14 @@ namespace System.IO
// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength)
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append("..");
- for (int i = commonLength; i < relativeToLength; i++)
+ for (int i = commonLength + 1; i < relativeToLength; i++)
{
if (PathInternal.IsDirectorySeparator(relativeTo[i]))
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append(DirectorySeparatorChar);
+ sb.Append("..");
}
}
}
@@ -852,11 +780,20 @@ namespace System.IO
}
// Now add the rest of the "to" path, adding back the trailing separator
- int count = pathLength - commonLength;
+ int differenceLength = pathLength - commonLength;
if (pathEndsInSeparator)
- count++;
+ differenceLength++;
+
+ if (differenceLength > 0)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(DirectorySeparatorChar);
+ }
+
+ sb.Append(path, commonLength, differenceLength);
+ }
- sb.Append(path, commonLength, count);
return StringBuilderCache.GetStringAndRelease(sb);
}