Skip version (dotnet/corefxdotnet/coreclr#28835)
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>
Wed, 13 Jun 2018 00:16:31 +0000 (17:16 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 14 Jun 2018 13:39:49 +0000 (06:39 -0700)
Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
Commit migrated from https://github.com/dotnet/coreclr/commit/46c08c4c6e3af1562b6a4dff1c8d6ccda21aec38

src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.cs

index 00cb12e..c9defac 100644 (file)
@@ -116,6 +116,25 @@ namespace System.IO
         /// <param name="rootLength">The length of the root of the given path</param>
         internal static string RemoveRelativeSegments(string path, int rootLength)
         {
+            Span<char> initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
+            ValueStringBuilder sb = new ValueStringBuilder(initialBuffer);
+
+            if (RemoveRelativeSegments(path.AsSpan(), rootLength, ref sb))
+            {
+                path = sb.ToString();
+            }
+
+            sb.Dispose();
+            return path;
+        }
+
+        /// <summary>
+        /// Try to remove relative segments from the given path (without combining with a root).
+        /// </summary>
+        /// <param name="rootLength">The length of the root of the given path</param>
+        /// <returns>"true" if the path was modified</returns>
+        internal static bool RemoveRelativeSegments(ReadOnlySpan<char> path, int rootLength, ref ValueStringBuilder sb)
+        {
             Debug.Assert(rootLength > 0);
             bool flippedSeparator = false;
 
@@ -126,15 +145,12 @@ namespace System.IO
             if (PathInternal.IsDirectorySeparator(path[skip - 1]))
                 skip--;
 
-            Span<char> initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
-            ValueStringBuilder sb = new ValueStringBuilder(initialBuffer);
-
             // 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.
             if (skip > 0)
             {
-                sb.Append(path.AsSpan(0, skip));
+                sb.Append(path.Slice(0, skip));
             }
 
             for (int i = skip; i < path.Length; i++)
@@ -182,7 +198,7 @@ namespace System.IO
 
                         i += 2;
                         continue;
-                    }
+                   }
                 }
 
                 // Normalize the directory separator if needed
@@ -198,11 +214,16 @@ namespace System.IO
             // If we haven't changed the source path, return the original
             if (!flippedSeparator && sb.Length == path.Length)
             {
-                sb.Dispose();
-                return path;
+                return false;
+            }
+
+            // We may have eaten the trailing separator from the root when we started and not replaced it
+            if (skip != rootLength && sb.Length < rootLength)
+            {
+                sb.Append(path[rootLength - 1]);
             }
 
-            return sb.Length < rootLength ? path.Substring(0, rootLength) : sb.ToString();
+            return true;
         }
     }
 }