Parcourir la source

2003-05-07 Ben Maurer <[email protected]>
* Path.cs
(GetPathRoot) Added support for UNC paths.
(CanonicalizePath) Added optimizations per Miguel's requests.
* PathTest.cs
Even more GetFullPath () tests. Includes UNC tests.

svn path=/trunk/mcs/; revision=14383

Ben Maurer il y a 23 ans
Parent
commit
347a32ffdd

+ 5 - 0
mcs/class/corlib/System.IO/ChangeLog

@@ -1,3 +1,8 @@
+2003-05-07  Ben Maurer <[email protected]>
+	* Path.cs 
+	(GetPathRoot) Added support for UNC paths.
+	(CanonicalizePath) Added optimizations per Miguel's requests.
+
 2003-05-06  Ville Palo <[email protected]>
 
 	* BufferedStream.cs: 

+ 41 - 30
mcs/class/corlib/System.IO/Path.cs

@@ -170,19 +170,37 @@ namespace System.IO
 			return CanonicalizePath (path);
 		}
 
+		static bool IsDsc (char c) {
+			return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar;
+		}
+		
 		public static string GetPathRoot (string path)
 		{
-			if (path == null)
-				return null;
-
-			if (!IsPathRooted (path))
-				return String.Empty;
-
-			int i = path.IndexOfAny (new char [] {DirectorySeparatorChar, AltDirectorySeparatorChar});
-			if (i == -1)
-				return null; // This should never happen, cause IsPathRooted returned true
-
-			return path.Substring (0, i + 1);
+			if (path == null) return null;
+			if (!IsPathRooted (path)) return String.Empty;
+			
+			if (DirectorySeparatorChar == '/') {
+				// UNIX
+				return IsDsc (path [0]) ? DirectorySeparatorChar.ToString () : String.Empty;
+			} else {
+				// Windows
+				int len = 2;
+				
+				if (path.Length <= 2) return String.Empty;
+					
+				if (IsDsc (path [0]) && IsDsc (path[1])) {
+					// UNC: \\server or \\server\share
+					// Get server
+					while (len < path.Length && !IsDsc (path [len])) len++;
+					// Get share
+					while (len < path.Length && !IsDsc (path [len])) len++;				
+				} else if (path[1] == VolumeSeparatorChar) {
+					// C:\folder
+					if (path.Length >= 3 && (IsDsc (path [2]))) len++;
+				}
+				
+				return path.Substring (0, len);
+			}
 		}
 
 		public static string GetTempFileName ()
@@ -282,7 +300,7 @@ namespace System.IO
 		static string CanonicalizePath (string path) {
 			
 			// STEP 1: Check for empty string
-			if (path == null || path == String.Empty) return path;
+			if (path == null) return path;
 			path.Trim ();
 			if (path == String.Empty) return path;
 			
@@ -294,34 +312,27 @@ namespace System.IO
 			if (dir == String.Empty) return path;
 			
 			string file = GetFileName (path);
-			string result = root;
+			
 			// STEP 3: split the directories, this gets rid of consecutative "/"'s
 			string [] dirs = dir.Split (DirectorySeparatorChar, AltDirectorySeparatorChar);
 			
 			// STEP 4: Get rid of directories containing . and ..
+			int target = 0;
+			
 			for (int i = 0; i < dirs.Length; i++) {
-				if (dirs [i] == ".")
-					dirs [i] = String.Empty;
+				if (dirs [i] == "." || dirs [i] == String.Empty) continue;
 				else if (dirs [i] == "..") {
-					dirs [i] = String.Empty;
-					int j = i;
-					while (i-- > 0) {
-						if (dirs [i] != String.Empty) {
-							dirs [i] = String.Empty;
-							break;
-						}
-					}
+					if (target != 0) target--;
 				}
+				else
+					dirs [target++] = dirs [i];
 			}
 			
 			// STEP 5: Combine everything.
-			for (int i = 0; i < dirs.Length; i++) {
-				if (dirs [i] != String.Empty)
-					result += dirs [i] + DirectorySeparatorChar;
-			}
-			
-			result += file;
-			return result;
+			if (target == 0)
+				return root + file;
+			else
+				return root + String.Join (DirectorySeparatorChar.ToString (), dirs, 0, target) + DirectorySeparatorChar + file;
 		}
 	}
 }

+ 7 - 0
mcs/class/corlib/Test/System.IO/ChangeLog

@@ -1,3 +1,7 @@
+2003-05-07  Ben Maurer <[email protected]>
+	* PathTest.cs
+	Even more GetFullPath () tests. Includes UNC tests.
+	
 2003-05-06  Ville Palo <[email protected]>
 
 	* DirectoryInfoTest.cs: Removed OS-specific test
@@ -261,3 +265,6 @@
 	* MemoryStreamTest.cs: wrapped try-catch blocks around read/write/seek
 	tests. These were throwing exceptions that NUnit wasn't catching.  I 
 	don't think it used to behave this way before .NET.1.0.
+2003-05-04  Ben Maurer <[email protected]>
+	* Path.cs 
+	(CanonicalizePath) Added optimizations per Miguel's requests.

+ 70 - 4
mcs/class/corlib/Test/System.IO/PathTest.cs

@@ -4,9 +4,13 @@
 // Authors:
 // 	Marcin Szczepanski ([email protected])
 // 	Gonzalo Paniagua Javier ([email protected])
+//	Ben Maurer ([email protected])
+//	Gilles Freart ([email protected])
 //
 // (c) Marcin Szczepanski 
 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
+// (c) 2003 Ben Maurer
+// (c) 2003 Gilles Freart
 //
 
 #define NUNIT // Comment out this one if you wanna play with the test without using NUnit
@@ -314,11 +318,73 @@ namespace MonoTests.System.IO
 			string testFullPath = Path.GetFullPath ("foo.txt");
 			string expected = current + DSC + "foo.txt";
 			AssertEquals ("GetFullPath #01", expected, testFullPath);
-			
-			testFullPath = Path.GetFullPath ("a/./../foo.txt");
-			expected = current + DSC + "foo.txt";
-			AssertEquals ("GetFullPath #02", expected, testFullPath);
 
+			testFullPath = Path.GetFullPath ("a//./.././foo.txt");
+			AssertEquals ("GetFullPath #02", expected, testFullPath);
+			string root = Windows ? "C:\\" : "/";
+			string [,] test = new string [,] {		
+				{"root////././././././../root/././../root", "root"},
+				{"root/", "root/"},
+				{"root/./", "root/"},
+				{"root/./", "root/"},
+				{"root/../", ""},
+				{"root/../", ""},
+				{"root/../..", ""},
+				{"root/.hiddenfile", "root/.hiddenfile"},
+				{"root/. /", "root/. /"},
+				{"root/.. /", "root/.. /"},
+				{"root/..weirdname", "root/..weirdname"},
+				{"root/..", ""},
+				{"root/../a/b/../../..", ""},
+				{"root/./..", ""},
+				{"..", ""},
+				{".", ""},
+				{"root//dir", "root/dir"},
+				{"root/.              /", "root/.              /"},
+				{"root/..             /", "root/..             /"},
+				{"root/      .              /", "root/      .              /"},
+				{"root/      ..             /", "root/      ..             /"},
+				{"root/./", "root/"},
+				{"root/..                      /", "root/..                   /"},
+				{".//", ""}
+			};
+			for (int i = 0; i < test.GetUpperBound (1); i++) {
+				AssertEquals (String.Format ("GetFullPath #{0}", i), root + test [i, 1], Path.GetFullPath (root + test [i, 0]));
+			}
+			
+			if (Windows) {
+				string uncroot = @"\\server\share\";
+				string [,] testunc = new string [,] {		
+					{"root////././././././../root/././../root", "root"},
+					{"root/", "root/"},
+					{"root/./", "root/"},
+					{"root/./", "root/"},
+					{"root/../", ""},
+					{"root/../", ""},
+					{"root/../..", ""},
+					{"root/.hiddenfile", "root/.hiddenfile"},
+					{"root/. /", "root/. /"},
+					{"root/.. /", "root/.. /"},
+					{"root/..weirdname", "root/..weirdname"},
+					{"root/..", ""},
+					{"root/../a/b/../../..", ""},
+					{"root/./..", ""},
+					{"..", ""},
+					{".", ""},
+					{"root//dir", "root/dir"},
+					{"root/.              /", "root/.              /"},
+					{"root/..             /", "root/..             /"},
+					{"root/      .              /", "root/      .              /"},
+					{"root/      ..             /", "root/      ..             /"},
+					{"root/./", "root/"},
+					{"root/..                      /", "root/..                   /"},
+					{".//", ""}
+				};
+				for (int i = 0; i < test.GetUpperBound (1); i++) {
+					AssertEquals (String.Format ("GetFullPath UNC #{0}", i), uncroot + test [i, 1], Path.GetFullPath (uncroot + test [i, 0]));
+				}	
+			}
+			
 			try {
 				testFullPath = Path.GetFullPath (null);
 				Fail ("GetFullPath Fail #01");