Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
DotNetAnywhere/corlib/System.IO/Path.cs
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
693 lines (605 sloc)
22.1 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if !LOCALTEST | |
namespace System.IO { | |
public static class Path { | |
/* static Path() { | |
InvalidPathChars = GetInvalidPathChars(); | |
if (Environment.Platform == PlatformID.Unix) { | |
AltDirectorySeparatorChar = '/'; | |
DirectorySeparatorChar = '/'; | |
PathSeparator = ';'; | |
VolumeSeparatorChar = '/'; | |
} else { | |
AltDirectorySeparatorChar = '/'; | |
DirectorySeparatorChar = '\\'; | |
PathSeparator = ';'; | |
VolumeSeparatorChar = ':'; | |
} | |
DirectorySeparatorStr = DirectorySeparatorChar.ToString(); | |
dirEqualsVolume = (DirectorySeparatorChar == VolumeSeparatorChar); | |
} | |
public static readonly char AltDirectorySeparatorChar; | |
public static readonly char DirectorySeparatorChar; | |
internal static readonly string DirectorySeparatorStr; | |
public static readonly char[] InvalidPathChars; | |
public static readonly char PathSeparator; | |
public static readonly char VolumeSeparatorChar; | |
private static bool dirEqualsVolume; | |
public static char[] GetInvalidPathChars() { | |
// return a new array as we do not want anyone to be able to change the values | |
if (Environment.Platform == PlatformID.Unix) { | |
return new char[] { '\x00' }; | |
} else { | |
return new char[] { | |
'\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', | |
'\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', | |
'\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', | |
'\x1E', '\x1F' }; | |
} | |
} | |
private static bool IsDsc(char c) { | |
return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; | |
} | |
private static string WindowsDriveAdjustment(string path) { | |
// two special cases to consider when a drive is specified | |
if (path.Length < 2) { | |
return path; | |
} | |
if ((path[1] != ':') || !Char.IsLetter(path[0])) { | |
return path; | |
} | |
string current = Directory.GetCurrentDirectory(); | |
// first, only the drive is specified | |
if (path.Length == 2) { | |
// then if the current directory is on the same drive | |
if (current[0] == path[0]) { | |
path = current; // we return it | |
} else { | |
path += '\\'; | |
} | |
} else if ((path[2] != Path.DirectorySeparatorChar) && (path[2] != Path.AltDirectorySeparatorChar)) { | |
// second, the drive + a directory is specified *without* a separator between them (e.g. C:dir). | |
// If the current directory is on the specified drive... | |
if (current[0] == path[0]) { | |
// then specified directory is appended to the current drive directory | |
path = Path.Combine(current, path.Substring(2, path.Length - 2)); | |
} else { | |
// if not, then just pretend there was a separator (Path.Combine won't work in this case) | |
path = String.Concat(path.Substring(0, 2), DirectorySeparatorStr, path.Substring(2, path.Length - 2)); | |
} | |
} | |
return path; | |
} | |
public static bool IsPathRooted(string path) { | |
if (path == null || path.Length == 0) { | |
return false; | |
} | |
if (path.IndexOfAny(InvalidPathChars) != -1) { | |
throw new ArgumentException("Illegal characters in path", "path"); | |
} | |
char c = path[0]; | |
return (c == DirectorySeparatorChar || | |
c == AltDirectorySeparatorChar || | |
(!dirEqualsVolume && path.Length > 1 && path[1] == VolumeSeparatorChar)); | |
} | |
static string CanonicalizePath(string path) { | |
// STEP 1: Check for empty string | |
if (path == null) { | |
return path; | |
} | |
if (Environment.IsRunningOnWindows) { | |
path = path.Trim(); | |
} | |
if (path.Length == 0) { | |
return path; | |
} | |
// STEP 2: Check to see if this is only a root | |
string root = Path.GetPathRoot(path); | |
// it will return '\' for path '\', while it should return 'c:\' or so. | |
// Note: commenting this out makes the ened for the (target == 1...) check in step 5 | |
//if (root == path) return path; | |
// STEP 3: split the directories, this gets rid of consecutative "/"'s | |
string[] dirs = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); | |
// STEP 4: Get rid of directories containing . and .. | |
int target = 0; | |
for (int i = 0; i < dirs.Length; i++) { | |
if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0)) { | |
continue; | |
} else if (dirs[i] == "..") { | |
if (target != 0) { | |
target--; | |
} | |
} else { | |
dirs[target++] = dirs[i]; | |
} | |
} | |
// STEP 5: Combine everything. | |
if (target == 0 || (target == 1 && dirs[0] == "")) { | |
return root; | |
} else { | |
string ret = String.Join(DirectorySeparatorStr, dirs, 0, target); | |
if (Environment.IsRunningOnWindows) { | |
if (!SameRoot(root, ret)) { | |
ret = root + ret; | |
} | |
// In GetFullPath(), it is assured that here never comes UNC. So this must only applied to such path that starts with '\', without drive specification. | |
if (!IsDsc(path[0]) && SameRoot(root, path)) { | |
if (ret.Length <= 2 && !ret.EndsWith(DirectorySeparatorStr)) { // '\' after "c:" | |
ret += Path.DirectorySeparatorChar; | |
} | |
return ret; | |
} else { | |
string current = Directory.GetCurrentDirectory(); | |
if (current.Length > 1 && current[1] == Path.VolumeSeparatorChar) { | |
// DOS local file path | |
if (ret.Length == 0 || IsDsc(ret[0])) { | |
ret += '\\'; | |
} | |
return current.Substring(0, 2) + ret; | |
} else if (IsDsc(current[current.Length - 1]) && IsDsc(ret[0])) { | |
return current + ret.Substring(1); | |
} else { | |
return current + ret; | |
} | |
} | |
} | |
return ret; | |
} | |
} | |
public static string GetFullPath(string path) { | |
if (path == null) { | |
throw new ArgumentNullException("path"); | |
} | |
if (path.Trim().Length == 0) { | |
string msg = "The specified path is not of a legal form (empty)."; | |
throw new ArgumentException(msg, "path"); | |
} | |
// adjust for drives, i.e. a special case for windows | |
if (Environment.IsRunningOnWindows) { | |
path = WindowsDriveAdjustment(path); | |
} | |
// if the supplied path ends with a separator... | |
char end = path[path.Length - 1]; | |
if (path.Length >= 2 && IsDsc(path[0]) && IsDsc(path[1])) { | |
if (path.Length == 2 || path.IndexOf(path[0], 2) < 0) { | |
throw new ArgumentException("UNC pass should be of the form \\\\server\\share."); | |
} | |
if (path[0] != DirectorySeparatorChar) { | |
path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); | |
} | |
} else { | |
if (!IsPathRooted(path)) { | |
path = Directory.GetCurrentDirectory() + DirectorySeparatorStr + path; | |
} else if (DirectorySeparatorChar == '\\' && path.Length >= 2 && IsDsc(path[0]) && !IsDsc(path[1])) { // like `\abc\def' | |
string current = Directory.GetCurrentDirectory(); | |
if (current[1] == VolumeSeparatorChar) { | |
path = current.Substring(0, 2) + path; | |
} else { | |
path = current.Substring(0, current.IndexOf('\\', current.IndexOf("\\\\") + 1)); | |
} | |
} | |
path = CanonicalizePath(path); | |
} | |
// if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one | |
if (IsDsc(end) && (path[path.Length - 1] != DirectorySeparatorChar)) { | |
path += DirectorySeparatorChar; | |
} | |
return path; | |
}*/ | |
public static readonly char[] InvalidPathChars; | |
public static readonly char AltDirectorySeparatorChar; | |
public static readonly char DirectorySeparatorChar; | |
public static readonly char PathSeparator; | |
internal static readonly string DirectorySeparatorStr; | |
public static readonly char VolumeSeparatorChar; | |
private static readonly char[] PathSeparatorChars; | |
private static readonly bool dirEqualsVolume; | |
// class methods | |
public static string ChangeExtension(string path, string extension) { | |
if (path == null) | |
return null; | |
if (path.IndexOfAny(InvalidPathChars) != -1) | |
throw new ArgumentException("Illegal characters in path", "path"); | |
int iExt = findExtension(path); | |
if (extension == null) | |
return iExt < 0 ? path : path.Substring(0, iExt); | |
else if (extension == String.Empty) | |
return iExt < 0 ? path + '.' : path.Substring(0, iExt + 1); | |
else if (path.Length != 0) { | |
if (extension.Length > 0 && extension[0] != '.') | |
extension = "." + extension; | |
} else | |
extension = String.Empty; | |
if (iExt < 0) { | |
return path + extension; | |
} else if (iExt > 0) { | |
string temp = path.Substring(0, iExt); | |
return temp + extension; | |
} | |
return extension; | |
} | |
public static string Combine(string path1, string path2) { | |
if (path1 == null) | |
throw new ArgumentNullException("path1"); | |
if (path2 == null) | |
throw new ArgumentNullException("path2"); | |
if (path1 == String.Empty) | |
return path2; | |
if (path2 == String.Empty) | |
return path1; | |
if (path1.IndexOfAny(InvalidPathChars) != -1) | |
throw new ArgumentException("Illegal characters in path", "path1"); | |
if (path2.IndexOfAny(InvalidPathChars) != -1) | |
throw new ArgumentException("Illegal characters in path", "path2"); | |
//TODO???: UNC names | |
// LAMESPEC: MS says that if path1 is not empty and path2 is a full path | |
// it should throw ArgumentException | |
if (IsPathRooted(path2)) | |
return path2; | |
char p1end = path1[path1.Length - 1]; | |
if (p1end != DirectorySeparatorChar && p1end != AltDirectorySeparatorChar && p1end != VolumeSeparatorChar) | |
return path1 + DirectorySeparatorChar + path2; | |
return path1 + path2; | |
} | |
public static string GetDirectoryName(string path) { | |
// LAMESPEC: For empty string MS docs say both | |
// return null AND throw exception. Seems .NET throws. | |
if (path == String.Empty) { | |
throw new ArgumentException(); | |
} | |
if (path == null || GetPathRoot(path) == path) { | |
return null; | |
} | |
CheckArgument.WhitespaceOnly(path); | |
CheckArgument.PathChars(path); | |
int nLast = path.LastIndexOfAny(PathSeparatorChars); | |
if (nLast == 0) { | |
nLast++; | |
} | |
if (nLast > 0) { | |
string ret = path.Substring(0, nLast); | |
int l = ret.Length; | |
if (l >= 2 && ret[l - 1] == VolumeSeparatorChar) { | |
return ret + DirectorySeparatorChar; | |
} else { | |
return ret; | |
} | |
} | |
return String.Empty; | |
} | |
public static string GetExtension(string path) { | |
if (path == null) { | |
return null; | |
} | |
if (path.IndexOfAny(InvalidPathChars) != -1) { | |
throw new ArgumentException("Illegal characters in path", "path"); | |
} | |
int iExt = findExtension(path); | |
if (iExt > -1) { | |
if (iExt < path.Length - 1) { | |
return path.Substring(iExt); | |
} | |
} | |
return string.Empty; | |
} | |
public static string GetFileName(string path) { | |
if (path == null || path == String.Empty) { | |
return path; | |
} | |
if (path.IndexOfAny(InvalidPathChars) != -1) { | |
throw new ArgumentException("Illegal characters in path", "path"); | |
} | |
int nLast = path.LastIndexOfAny(PathSeparatorChars); | |
if (nLast >= 0) { | |
return path.Substring(nLast + 1); | |
} | |
return path; | |
} | |
public static string GetFileNameWithoutExtension(string path) { | |
return ChangeExtension(GetFileName(path), null); | |
} | |
public static string GetFullPath(string path) { | |
string fullpath = InsecureGetFullPath(path); | |
return fullpath; | |
} | |
internal static string WindowsDriveAdjustment(string path) { | |
// two special cases to consider when a drive is specified | |
if (path.Length < 2) { | |
return path; | |
} | |
if ((path[1] != ':') || !Char.IsLetter(path[0])) { | |
return path; | |
} | |
string current = Directory.GetCurrentDirectory(); | |
// first, only the drive is specified | |
if (path.Length == 2) { | |
// then if the current directory is on the same drive | |
if (current[0] == path[0]) { | |
path = current; // we return it | |
} else { | |
path += '\\'; | |
} | |
} else if ((path[2] != Path.DirectorySeparatorChar) && (path[2] != Path.AltDirectorySeparatorChar)) { | |
// second, the drive + a directory is specified *without* a separator between them (e.g. C:dir). | |
// If the current directory is on the specified drive... | |
if (current[0] == path[0]) { | |
// then specified directory is appended to the current drive directory | |
path = Path.Combine(current, path.Substring(2, path.Length - 2)); | |
} else { | |
// if not, then just pretend there was a separator (Path.Combine won't work in this case) | |
path = String.Concat(path.Substring(0, 2), DirectorySeparatorStr, path.Substring(2, path.Length - 2)); | |
} | |
} | |
return path; | |
} | |
// insecure - do not call directly | |
internal static string InsecureGetFullPath(string path) { | |
if (path == null) { | |
throw new ArgumentNullException("path"); | |
} | |
if (path.Trim().Length == 0) { | |
string msg = "The specified path is not of a legal form (empty)."; | |
throw new ArgumentException(msg, "path"); | |
} | |
// adjust for drives, i.e. a special case for windows | |
if (Environment.IsRunningOnWindows) { | |
path = WindowsDriveAdjustment(path); | |
} | |
// if the supplied path ends with a separator... | |
char end = path[path.Length - 1]; | |
if (path.Length >= 2 && | |
IsDsc(path[0]) && | |
IsDsc(path[1])) { | |
if (path.Length == 2 || path.IndexOf(path[0], 2) < 0) { | |
throw new ArgumentException("UNC pass should be of the form \\\\server\\share."); | |
} | |
if (path[0] != DirectorySeparatorChar) { | |
path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); | |
} | |
} else { | |
if (!IsPathRooted(path)) { | |
path = Directory.GetCurrentDirectory() + DirectorySeparatorStr + path; | |
} else if (DirectorySeparatorChar == '\\' && | |
path.Length >= 2 && | |
IsDsc(path[0]) && | |
!IsDsc(path[1])) { // like `\abc\def' | |
string current = Directory.GetCurrentDirectory(); | |
if (current[1] == VolumeSeparatorChar) { | |
path = current.Substring(0, 2) + path; | |
} else { | |
path = current.Substring(0, current.IndexOf('\\', current.IndexOf("\\\\") + 1)); | |
} | |
} | |
path = CanonicalizePath(path); | |
} | |
// if the original ended with a [Alt]DirectorySeparatorChar then ensure the full path also ends with one | |
if (IsDsc(end) && (path[path.Length - 1] != DirectorySeparatorChar)) { | |
path += DirectorySeparatorChar; | |
} | |
return path; | |
} | |
static bool IsDsc(char c) { | |
return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; | |
} | |
public static string GetPathRoot(string path) { | |
if (path == null) | |
return null; | |
if (path == String.Empty) | |
throw new ArgumentException("This specified path is invalid."); | |
if (!IsPathRooted(path)) | |
return String.Empty; | |
if (DirectorySeparatorChar == '/') { | |
// UNIX | |
return IsDsc(path[0]) ? DirectorySeparatorStr : String.Empty; | |
} else { | |
// Windows | |
int len = 2; | |
if (path.Length == 1 && IsDsc(path[0])) | |
return DirectorySeparatorStr; | |
else 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 | |
if (len < path.Length) { | |
len++; | |
while (len < path.Length && !IsDsc(path[len])) len++; | |
} | |
return DirectorySeparatorStr + | |
DirectorySeparatorStr + | |
path.Substring(2, len - 2).Replace(AltDirectorySeparatorChar, DirectorySeparatorChar); | |
} else if (IsDsc(path[0])) { | |
// path starts with '\' or '/' | |
return DirectorySeparatorStr; | |
} else if (path[1] == VolumeSeparatorChar) { | |
// C:\folder | |
if (path.Length >= 3 && (IsDsc(path[2]))) len++; | |
} else | |
return Directory.GetCurrentDirectory().Substring(0, 2);// + path.Substring (0, len); | |
return path.Substring(0, len); | |
} | |
} | |
public static string GetTempFileName() { | |
throw new NotImplementedException(); | |
} | |
/*public static string GetTempPath() { | |
string p = get_temp_path(); | |
if (p.Length > 0 && p[p.Length - 1] != DirectorySeparatorChar) | |
return p + DirectorySeparatorChar; | |
return p; | |
} | |
//private static extern string get_temp_path(); | |
*/ | |
public static bool HasExtension(string path) { | |
if (path == null || path.Trim() == String.Empty) | |
return false; | |
int pos = findExtension(path); | |
return 0 <= pos && pos < path.Length - 1; | |
} | |
public static bool IsPathRooted(string path) { | |
if (path == null || path.Length == 0) | |
return false; | |
if (path.IndexOfAny(InvalidPathChars) != -1) | |
throw new ArgumentException("Illegal characters in path", "path"); | |
char c = path[0]; | |
return (c == DirectorySeparatorChar || | |
c == AltDirectorySeparatorChar || | |
(!dirEqualsVolume && path.Length > 1 && path[1] == VolumeSeparatorChar)); | |
} | |
public static char[] GetInvalidFileNameChars () | |
{ | |
// return a new array as we do not want anyone to be able to change the values | |
if (Environment.IsRunningOnWindows) { | |
return new char [41] { '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', | |
'\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', | |
'\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', | |
'\x1E', '\x1F', '\x22', '\x3C', '\x3E', '\x7C', ':', '*', '?', '\\', '/' }; | |
} else { | |
return new char [2] { '\x00', '/' }; | |
} | |
} | |
public static char[] GetInvalidPathChars () | |
{ | |
// return a new array as we do not want anyone to be able to change the values | |
if (Environment.IsRunningOnWindows) { | |
return new char [36] { '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', | |
'\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', | |
'\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', | |
'\x1E', '\x1F' }; | |
} else { | |
return new char [1] { '\x00' }; | |
} | |
} | |
public static string GetRandomFileName () | |
{ | |
throw new NotImplementedException(); | |
} | |
// private class methods | |
private static int findExtension(string path) { | |
// method should return the index of the path extension | |
// start or -1 if no valid extension | |
if (path != null) { | |
int iLastDot = path.LastIndexOf('.'); | |
int iLastSep = path.LastIndexOfAny(PathSeparatorChars); | |
if (iLastDot > iLastSep) | |
return iLastDot; | |
} | |
return -1; | |
} | |
static Path() { | |
if (Environment.Platform == PlatformID.Unix) { | |
AltDirectorySeparatorChar = '/'; | |
DirectorySeparatorChar = '/'; | |
PathSeparator = ';'; | |
VolumeSeparatorChar = '/'; | |
} else { | |
AltDirectorySeparatorChar = '/'; | |
DirectorySeparatorChar = '\\'; | |
PathSeparator = ';'; | |
VolumeSeparatorChar = ':'; | |
} | |
// this copy will be modifiable ("by design") | |
InvalidPathChars = GetInvalidPathChars (); | |
// internal fields | |
DirectorySeparatorStr = DirectorySeparatorChar.ToString(); | |
PathSeparatorChars = new char[] { | |
DirectorySeparatorChar, | |
AltDirectorySeparatorChar, | |
VolumeSeparatorChar | |
}; | |
dirEqualsVolume = (DirectorySeparatorChar == VolumeSeparatorChar); | |
} | |
static bool SameRoot(string root, string path) { | |
// compare root - if enough details are available | |
if ((root.Length < 2) || (path.Length < 2)) | |
return false; | |
// same volume/drive | |
if (!root[0].Equals(path[0])) | |
return false; | |
// presence if the separator | |
if (path[1] != Path.VolumeSeparatorChar) | |
return false; | |
if ((root.Length > 2) && (path.Length > 2)) { | |
// but don't directory compare the directory separator | |
return (IsDsc(root[2]) && IsDsc(path[2])); | |
} | |
return true; | |
} | |
static string CanonicalizePath(string path) { | |
// STEP 1: Check for empty string | |
if (path == null) | |
return path; | |
if (Environment.IsRunningOnWindows) | |
path = path.Trim(); | |
if (path.Length == 0) | |
return path; | |
// STEP 2: Check to see if this is only a root | |
string root = Path.GetPathRoot(path); | |
// it will return '\' for path '\', while it should return 'c:\' or so. | |
// Note: commenting this out makes the ened for the (target == 1...) check in step 5 | |
//if (root == path) return path; | |
// STEP 3: split the directories, this gets rid of consecutative "/"'s | |
string[] dirs = path.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); | |
// STEP 4: Get rid of directories containing . and .. | |
int target = 0; | |
for (int i = 0; i < dirs.Length; i++) { | |
if (dirs[i] == "." || (i != 0 && dirs[i].Length == 0)) | |
continue; | |
else if (dirs[i] == "..") { | |
if (target != 0) | |
target--; | |
} else | |
dirs[target++] = dirs[i]; | |
} | |
// STEP 5: Combine everything. | |
if (target == 0 || (target == 1 && dirs[0] == "")) | |
return root; | |
else { | |
string ret = String.Join(DirectorySeparatorStr, dirs, 0, target); | |
if (Environment.IsRunningOnWindows) { | |
if (!SameRoot(root, ret)) | |
ret = root + ret; | |
// In GetFullPath(), it is assured that here never comes UNC. So this must only applied to such path that starts with '\', without drive specification. | |
if (!IsDsc(path[0]) && SameRoot(root, path)) { | |
if (ret.Length <= 2 && !ret.EndsWith(DirectorySeparatorStr)) // '\' after "c:" | |
ret += Path.DirectorySeparatorChar; | |
return ret; | |
} else { | |
string current = Directory.GetCurrentDirectory(); | |
if (current.Length > 1 && current[1] == Path.VolumeSeparatorChar) { | |
// DOS local file path | |
if (ret.Length == 0 || IsDsc(ret[0])) | |
ret += '\\'; | |
return current.Substring(0, 2) + ret; | |
} else if (IsDsc(current[current.Length - 1]) && IsDsc(ret[0])) | |
return current + ret.Substring(1); | |
else | |
return current + ret; | |
} | |
} | |
return ret; | |
} | |
} | |
// required for FileIOPermission (and most proibably reusable elsewhere too) | |
// both path MUST be "full paths" | |
static internal bool IsPathSubsetOf(string subset, string path) { | |
if (subset.Length > path.Length) | |
return false; | |
// check that everything up to the last separator match | |
int slast = subset.LastIndexOfAny(PathSeparatorChars); | |
if (String.Compare(subset, 0, path, 0, slast) != 0) | |
return false; | |
slast++; | |
// then check if the last segment is identical | |
int plast = path.IndexOfAny(PathSeparatorChars, slast); | |
if (plast >= slast) { | |
return String.Compare(subset, slast, path, slast, path.Length - plast) == 0; | |
} | |
if (subset.Length != path.Length) | |
return false; | |
return String.Compare(subset, slast, path, slast, subset.Length - slast) == 0; | |
} | |
} | |
} | |
#endif |