mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-15 06:44:10 +02:00
590 lines
17 KiB
Beef
590 lines
17 KiB
Beef
![]() |
// This file contains portions of code released by Microsoft under the MIT license as part
|
|||
|
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
|||
|
// The original source was submitted to https://github.com/Microsoft/referencesource
|
|||
|
|
|||
|
using System.Text;
|
|||
|
using System.Diagnostics;
|
|||
|
|
|||
|
namespace System.IO
|
|||
|
{
|
|||
|
public static class Path
|
|||
|
{
|
|||
|
#if BF_PLATFORM_WINDOWS
|
|||
|
public const char8 DirectorySeparatorChar = '\\';
|
|||
|
#else
|
|||
|
public const char8 DirectorySeparatorChar = '/';
|
|||
|
#endif //BF_PLATFORM_WINDOWS
|
|||
|
|
|||
|
// Platform specific alternate directory separator char8acter.
|
|||
|
// This is backslash ('\') on Unix, and slash ('/') on Windows
|
|||
|
// and MacOS.
|
|||
|
//
|
|||
|
#if BF_PLATFORM_WINDOWS
|
|||
|
public const char8 AltDirectorySeparatorChar = '/';
|
|||
|
#else
|
|||
|
public const char8 AltDirectorySeparatorChar = '\\';
|
|||
|
#endif //BF_PLATFORM_WINDOWS
|
|||
|
|
|||
|
// Platform specific volume separator char8acter. This is colon (':')
|
|||
|
// on Windows and MacOS, and slash ('/') on Unix. This is mostly
|
|||
|
// useful for parsing paths like "c:\windows" or "MacVolume:System Folder".
|
|||
|
//
|
|||
|
#if BF_PLATFORM_WINDOWS
|
|||
|
public const char8 VolumeSeparatorChar = ':';
|
|||
|
#else
|
|||
|
public const char8 VolumeSeparatorChar = '/';
|
|||
|
#endif //BF_PLATFORM_WINDOWS
|
|||
|
|
|||
|
// Make this public sometime.
|
|||
|
// The max total path is 260, and the max individual component length is 255.
|
|||
|
// For example, D:\<256 char8 file name> isn't legal, even though it's under 260 char8s.
|
|||
|
internal const int32 MaxPath = 260;
|
|||
|
private const int32 MaxDirectoryLength = 255;
|
|||
|
|
|||
|
public static void GetFullPath(String inPartialPath, String outFullPath)
|
|||
|
{
|
|||
|
Platform.GetStrHelper(outFullPath, scope (outPtr, outSize, outResult) =>
|
|||
|
{
|
|||
|
Platform.BfpFile_GetFullPath(inPartialPath, outPtr, outSize, (Platform.BfpFileResult*)outResult);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
internal static void CheckInvalidPathChars(StringView path, bool checkAdditional = false)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public static void GetFileName(String inPath, String outFileName)
|
|||
|
{
|
|||
|
if (inPath == null)
|
|||
|
return;
|
|||
|
|
|||
|
CheckInvalidPathChars(inPath);
|
|||
|
|
|||
|
int length = inPath.Length;
|
|||
|
for (int i = length; --i >= 0; )
|
|||
|
{
|
|||
|
char8 ch = inPath[i];
|
|||
|
if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar)
|
|||
|
{
|
|||
|
outFileName.Append(inPath, i + 1, length - i - 1);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
outFileName.Append(inPath);
|
|||
|
}
|
|||
|
|
|||
|
internal static String NormalizePath(String path, bool fullCheck)
|
|||
|
{
|
|||
|
return NormalizePath(path, fullCheck, MaxPath);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
internal static String NormalizePath(String path, bool fullCheck, bool expandShortPaths)
|
|||
|
{
|
|||
|
return NormalizePath(path, fullCheck, MaxPath, expandShortPaths);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
internal static String NormalizePath(String path, bool fullCheck, int32 maxPathLength)
|
|||
|
{
|
|||
|
return NormalizePath(path, fullCheck, maxPathLength, true);
|
|||
|
}
|
|||
|
|
|||
|
internal static String NormalizePath(String path, bool fullCheck, int32 maxPathLength, bool expandShortPaths)
|
|||
|
{
|
|||
|
//TODO: Implement
|
|||
|
return path;
|
|||
|
}
|
|||
|
|
|||
|
internal static String RemoveLongPathPrefix(String path)
|
|||
|
{
|
|||
|
//TODO: Implement
|
|||
|
return path;
|
|||
|
}
|
|||
|
|
|||
|
public static Result<void> GetDirectoryPath(StringView path, String outDir)
|
|||
|
{
|
|||
|
String usePath = scope String(Math.Min(MaxPath, path.Length));
|
|||
|
usePath.Append(path);
|
|||
|
|
|||
|
//String origPath = path;
|
|||
|
//if (usePath != null)
|
|||
|
{
|
|||
|
CheckInvalidPathChars(usePath);
|
|||
|
String normalizedPath = NormalizePath(usePath, false);
|
|||
|
|
|||
|
// If there are no permissions for PathDiscovery to this path, we should NOT expand the short paths
|
|||
|
// as this would leak information about paths to which the user would not have access to.
|
|||
|
if (usePath.Length > 0)
|
|||
|
{
|
|||
|
// If we were passed in a path with \\?\ we need to remove it as FileIOPermission does not like it.
|
|||
|
String tempPath = Path.RemoveLongPathPrefix(usePath);
|
|||
|
|
|||
|
// FileIOPermission cannot handle paths that contain ? or *
|
|||
|
// So we only pass to FileIOPermission the text up to them.
|
|||
|
int32 pos = 0;
|
|||
|
while (pos < tempPath.Length && (tempPath[pos] != '?' && tempPath[pos] != '*'))
|
|||
|
pos++;
|
|||
|
// GetFullPath will Demand that we have the PathDiscovery FileIOPermission and thus throw
|
|||
|
// SecurityException if we don't.
|
|||
|
// While we don't use the result of this call we are using it as a consistent way of
|
|||
|
// doing the security checks.
|
|||
|
if (pos > 0)
|
|||
|
{
|
|||
|
//Path.GetFullPath(tempPath.Substring(0, pos));
|
|||
|
String newPath = scope String(usePath.Length - pos);
|
|||
|
newPath.Append(usePath, pos);
|
|||
|
usePath = newPath;
|
|||
|
}
|
|||
|
/*}
|
|||
|
catch (SecurityException) {
|
|||
|
// If the user did not have permissions to the path, make sure that we don't leak expanded short paths
|
|||
|
// Only re-normalize if the original path had a ~ in it.
|
|||
|
if (path.IndexOf("~", StringComparison.Ordinal) != -1)
|
|||
|
{
|
|||
|
normalizedPath = NormalizePath(path, /*fullCheck*/ false, /*expandShortPaths*/ false);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (PathTooLongException) { }
|
|||
|
catch (NotSupportedException) { } // Security can throw this on "c:\foo:"
|
|||
|
catch (IOException) { }
|
|||
|
catch (ArgumentException) { } // The normalizePath with fullCheck will throw this for file: and http:*/
|
|||
|
}
|
|||
|
|
|||
|
usePath = normalizedPath;
|
|||
|
|
|||
|
int root = GetRootLength(usePath);
|
|||
|
int i = usePath.Length;
|
|||
|
if (i > root)
|
|||
|
{
|
|||
|
i = usePath.Length;
|
|||
|
if (i == root) return .Err;
|
|||
|
while (i > root && usePath[--i] != DirectorySeparatorChar && usePath[i] != AltDirectorySeparatorChar) {}
|
|||
|
outDir.Append(usePath, 0, i);
|
|||
|
return .Ok;
|
|||
|
}
|
|||
|
}
|
|||
|
return .Err;
|
|||
|
}
|
|||
|
|
|||
|
// Gets the length of the root DirectoryInfo or whatever DirectoryInfo markers
|
|||
|
// are specified for the first part of the DirectoryInfo name.
|
|||
|
//
|
|||
|
internal static int GetRootLength(String path)
|
|||
|
{
|
|||
|
CheckInvalidPathChars(path);
|
|||
|
|
|||
|
int i = 0;
|
|||
|
int length = path.Length;
|
|||
|
|
|||
|
#if BF_PLATFORM_WINDOWS
|
|||
|
if (length >= 1 && (IsDirectorySeparator(path[0])))
|
|||
|
{
|
|||
|
// handles UNC names and directories off current drive's root.
|
|||
|
i = 1;
|
|||
|
if (length >= 2 && (IsDirectorySeparator(path[1])))
|
|||
|
{
|
|||
|
i = 2;
|
|||
|
int32 n = 2;
|
|||
|
while (i < length && ((path[i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) || --n > 0)) i++;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (length >= 2 && path[1] == VolumeSeparatorChar)
|
|||
|
{
|
|||
|
// handles A:\foo.
|
|||
|
i = 2;
|
|||
|
if (length >= 3 && (IsDirectorySeparator(path[2]))) i++;
|
|||
|
}
|
|||
|
return i;
|
|||
|
#else
|
|||
|
if (length >= 1 && (IsDirectorySeparator(path[0]))) {
|
|||
|
i = 1;
|
|||
|
}
|
|||
|
return i;
|
|||
|
#endif //BF_PLATFORM_WINDOWS
|
|||
|
}
|
|||
|
|
|||
|
internal static bool IsDirectorySeparator(char8 c)
|
|||
|
{
|
|||
|
return (c==DirectorySeparatorChar || c == AltDirectorySeparatorChar);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
public static char8[] GetInvalidPathChars()
|
|||
|
{
|
|||
|
return RealInvalidPathChars;
|
|||
|
}
|
|||
|
|
|||
|
public static char8[] GetInvalidFileNameChars()
|
|||
|
{
|
|||
|
return (char8[]) InvalidFileNameChars.Clone();
|
|||
|
} */
|
|||
|
|
|||
|
public static void GetFileNameWithoutExtension(String inPath, String outFileName)
|
|||
|
{
|
|||
|
int lastSlash = Math.Max(inPath.LastIndexOf('\\'), inPath.LastIndexOf('/'));
|
|||
|
|
|||
|
int i;
|
|||
|
if ((i = inPath.LastIndexOf('.')) != -1)
|
|||
|
{
|
|||
|
int len = i - lastSlash - 1;
|
|||
|
if (len > 0)
|
|||
|
outFileName.Append(inPath, lastSlash + 1, i - lastSlash - 1);
|
|||
|
}
|
|||
|
else
|
|||
|
outFileName.Append(inPath, lastSlash + 1);
|
|||
|
}
|
|||
|
|
|||
|
public static Result<void> GetExtension(String inPath, String outExt)
|
|||
|
{
|
|||
|
int i;
|
|||
|
if ((i = inPath.LastIndexOf('.')) != -1)
|
|||
|
outExt.Append(inPath, i);
|
|||
|
return .Ok;
|
|||
|
}
|
|||
|
|
|||
|
public static Result<void> GetTempPath(String outPath)
|
|||
|
{
|
|||
|
Platform.GetStrHelper(outPath, scope (outPtr, outSize, outResult) =>
|
|||
|
{
|
|||
|
Platform.BfpFile_GetTempPath(outPtr, outSize, (Platform.BfpFileResult*)outResult);
|
|||
|
});
|
|||
|
|
|||
|
return .Ok;
|
|||
|
}
|
|||
|
|
|||
|
public static Result<void> GetTempFileName(String outPath)
|
|||
|
{
|
|||
|
Platform.GetStrHelper(outPath, scope (outPtr, outSize, outResult) =>
|
|||
|
{
|
|||
|
Platform.BfpFile_GetTempFileName(outPtr, outSize, (Platform.BfpFileResult*)outResult);
|
|||
|
});
|
|||
|
|
|||
|
return .Ok;
|
|||
|
}
|
|||
|
|
|||
|
public static void InternalCombine(String target, params String[] components)
|
|||
|
{
|
|||
|
for (var component in components)
|
|||
|
{
|
|||
|
if ((target.Length > 0) && (!target.EndsWith("\\")) && (!target.EndsWith("/")))
|
|||
|
target.Append(Path.DirectorySeparatorChar);
|
|||
|
target.Append(component);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void GetActualPathName(StringView inPath, String outPath)
|
|||
|
{
|
|||
|
Platform.GetStrHelper(outPath, scope (outPtr, outSize, outResult) =>
|
|||
|
{
|
|||
|
Platform.BfpFile_GetActualPath(scope String()..Append(inPath), outPtr, outSize, (Platform.BfpFileResult*)outResult);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
public static bool Equals(StringView filePathA, StringView filePathB)
|
|||
|
{
|
|||
|
Debug.Assert(!filePathA.Contains(Path.AltDirectorySeparatorChar));
|
|||
|
Debug.Assert(!filePathB.Contains(Path.AltDirectorySeparatorChar));
|
|||
|
return filePathA.Equals(filePathB, !Environment.IsFileSystemCaseSensitive);
|
|||
|
}
|
|||
|
|
|||
|
static void GetDriveStringTo(String outDrive, String path)
|
|||
|
{
|
|||
|
if ((path.Length >= 2) && (path[1] == ':'))
|
|||
|
outDrive.Append(path, 0, 2);
|
|||
|
}
|
|||
|
|
|||
|
public static void GetRelativePath(StringView fullPath, StringView curDir, String outRelPath)
|
|||
|
{
|
|||
|
String curPath1 = scope String(curDir);
|
|||
|
String curPath2 = scope String(fullPath);
|
|||
|
|
|||
|
if (curPath1.Contains(Path.AltDirectorySeparatorChar))
|
|||
|
curPath1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
|||
|
if (curPath2.Contains(Path.AltDirectorySeparatorChar))
|
|||
|
curPath1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
|||
|
|
|||
|
String driveString1 = scope String();
|
|||
|
GetDriveStringTo(driveString1, curPath1);
|
|||
|
String driveString2 = scope String();
|
|||
|
GetDriveStringTo(driveString2, curPath2);
|
|||
|
|
|||
|
StringComparison compareType = Environment.IsFileSystemCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
|
|||
|
|
|||
|
// On seperate drives?
|
|||
|
if (!String.Equals(driveString1, driveString2, compareType))
|
|||
|
{
|
|||
|
outRelPath.Set(fullPath);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (driveString1.Length > 0)
|
|||
|
curPath1.Remove(0, Math.Min(driveString1.Length + 1, curPath1.Length));
|
|||
|
if (driveString2.Length > 0)
|
|||
|
curPath2.Remove(0, Math.Min(driveString2.Length + 1, curPath2.Length));
|
|||
|
|
|||
|
while ((curPath1.Length > 0) && (curPath2.Length > 0))
|
|||
|
{
|
|||
|
int slashPos1 = curPath1.IndexOf(Path.DirectorySeparatorChar);
|
|||
|
if (slashPos1 == -1)
|
|||
|
slashPos1 = curPath1.Length;
|
|||
|
int slashPos2 = curPath2.IndexOf(Path.DirectorySeparatorChar);
|
|||
|
if (slashPos2 == -1)
|
|||
|
slashPos2 = curPath2.Length;
|
|||
|
|
|||
|
String section1 = scope String();
|
|||
|
section1.Append(curPath1, 0, slashPos1);
|
|||
|
String section2 = scope String();
|
|||
|
section2.Append(curPath2, 0, slashPos2);
|
|||
|
|
|||
|
if (!String.Equals(section1, section2, compareType))
|
|||
|
{
|
|||
|
// a/b/c
|
|||
|
// d/e/f
|
|||
|
|
|||
|
while (curPath1.Length > 0)
|
|||
|
{
|
|||
|
slashPos1 = curPath1.IndexOf(Path.DirectorySeparatorChar);
|
|||
|
if (slashPos1 == -1)
|
|||
|
slashPos1 = curPath1.Length;
|
|||
|
|
|||
|
if (slashPos1 + 1 >= curPath1.Length)
|
|||
|
curPath1.Clear();
|
|||
|
else
|
|||
|
curPath1.Remove(0, slashPos1 + 1);
|
|||
|
if (Path.DirectorySeparatorChar == '\\')
|
|||
|
curPath2.Insert(0, "..\\");
|
|||
|
else
|
|||
|
curPath2.Insert(0, "../");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (slashPos1 + 1 >= curPath1.Length)
|
|||
|
curPath1.Clear();
|
|||
|
else
|
|||
|
curPath1.Remove(0, slashPos1 + 1);
|
|||
|
|
|||
|
if (slashPos2 + 2 >= curPath2.Length)
|
|||
|
curPath1 = "";
|
|||
|
else
|
|||
|
curPath2.Remove(0, slashPos2 + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
outRelPath.Set(curPath2);
|
|||
|
}
|
|||
|
|
|||
|
public static void GetAbsolutePath(StringView relPath, StringView relToAbsPath, String outAbsPath)
|
|||
|
{
|
|||
|
String driveString = null;
|
|||
|
|
|||
|
var relPath;
|
|||
|
if (relPath == outAbsPath)
|
|||
|
relPath = scope:: String(relPath);
|
|||
|
|
|||
|
if ((relPath.Length >= 2) && (relPath[1] == ':'))
|
|||
|
{
|
|||
|
outAbsPath.Append(relPath);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ((relPath.Length > 1) &&
|
|||
|
(relPath[0] == '/') || (relPath[0] == '\\'))
|
|||
|
{
|
|||
|
outAbsPath.Append(relPath);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
int startLen = outAbsPath.Length;
|
|||
|
outAbsPath.Append(relToAbsPath);
|
|||
|
//outAbsPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
|||
|
|
|||
|
char8 slashChar = Path.DirectorySeparatorChar;
|
|||
|
|
|||
|
if ((outAbsPath.Length >= 2) && (outAbsPath[1] == ':'))
|
|||
|
{
|
|||
|
driveString = scope:: String();
|
|||
|
driveString.Append(outAbsPath, 0, 2);
|
|||
|
outAbsPath.Remove(0, 2);
|
|||
|
}
|
|||
|
|
|||
|
// Append a trailing slash if necessary
|
|||
|
if ((outAbsPath.Length > 0) && (outAbsPath[outAbsPath.Length - 1] != '\\') && (outAbsPath[outAbsPath.Length - 1] != '/'))
|
|||
|
outAbsPath.Append(slashChar);
|
|||
|
|
|||
|
int32 relIdx = 0;
|
|||
|
for (; ;)
|
|||
|
{
|
|||
|
if (outAbsPath.Length == 0)
|
|||
|
break;
|
|||
|
|
|||
|
int32 firstSlash = -1;
|
|||
|
for (int32 i = relIdx; i < relPath.Length; i++)
|
|||
|
if ((relPath[i] == '\\') || (relPath[i] == '/'))
|
|||
|
{
|
|||
|
firstSlash = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
if (firstSlash == -1)
|
|||
|
break;
|
|||
|
|
|||
|
String chDir = scope String();
|
|||
|
chDir.Append(relPath, relIdx, firstSlash - relIdx);
|
|||
|
|
|||
|
//relPath.Substring(relIdx, firstSlash - relIdx, chDir);
|
|||
|
//chDir.Append(relPath.Ptr + relIdx, firstSlash - relIdx);
|
|||
|
|
|||
|
relIdx = firstSlash + 1;
|
|||
|
|
|||
|
if (chDir == "..")
|
|||
|
{
|
|||
|
int32 lastDirStart = (int32)outAbsPath.Length - 1;
|
|||
|
while ((lastDirStart > 0) && (outAbsPath[lastDirStart - 1] != '\\') && (outAbsPath[lastDirStart - 1] != '/'))
|
|||
|
lastDirStart--;
|
|||
|
|
|||
|
String lastDir = scope String();
|
|||
|
lastDir.Append(outAbsPath, lastDirStart, outAbsPath.Length - lastDirStart - 1);
|
|||
|
if (lastDir == "..")
|
|||
|
{
|
|||
|
outAbsPath.Append("..");
|
|||
|
outAbsPath.Append(Path.DirectorySeparatorChar);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//newPath.erase(newPath.begin() + lastDirStart, newPath.end());
|
|||
|
outAbsPath.Remove(lastDirStart, outAbsPath.Length - lastDirStart);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (chDir == "")
|
|||
|
{
|
|||
|
outAbsPath.Append(Path.DirectorySeparatorChar);
|
|||
|
break;
|
|||
|
}
|
|||
|
else if (chDir != ".")
|
|||
|
{
|
|||
|
//newPath += chDir + slashChar;
|
|||
|
outAbsPath.Append(chDir);
|
|||
|
outAbsPath.Append(Path.DirectorySeparatorChar);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (driveString != null)
|
|||
|
outAbsPath.Insert(0, driveString);
|
|||
|
//relPath.Substring(relIdx, outAbsPath);
|
|||
|
outAbsPath.Append(relPath, relIdx);
|
|||
|
//outAbsPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
|||
|
for (int i = startLen; i < outAbsPath.Length; i++)
|
|||
|
{
|
|||
|
if (outAbsPath[i] == Path.AltDirectorySeparatorChar)
|
|||
|
outAbsPath[i] = Path.DirectorySeparatorChar;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static bool WildcareCompare(StringView path, StringView wildcard)
|
|||
|
{
|
|||
|
bool matches = true;
|
|||
|
char8* afterLastWild = null; // The location after the last '*', if we’ve encountered one
|
|||
|
char8* afterLastPath = null; // The location in the path string, from which we started after last wildcard
|
|||
|
char8 t, w;
|
|||
|
|
|||
|
char8* pathPtr = path.Ptr;
|
|||
|
char8* pathEnd = path.EndPtr;
|
|||
|
char8* wildPtr = wildcard.Ptr;
|
|||
|
char8* wildEnd = wildcard.EndPtr;
|
|||
|
|
|||
|
// Walk the text strings one character at a time.
|
|||
|
while (true)
|
|||
|
{
|
|||
|
// How do you match a unique text string?
|
|||
|
if (pathPtr == pathEnd)
|
|||
|
{
|
|||
|
// Easy: unique up on it!
|
|||
|
if (wildPtr == wildEnd)
|
|||
|
{
|
|||
|
break; // "x" matches "x"
|
|||
|
}
|
|||
|
w = *wildPtr;
|
|||
|
if (w == '*')
|
|||
|
{
|
|||
|
wildPtr++;
|
|||
|
continue;// "x*" matches "x" or "xy"
|
|||
|
}
|
|||
|
else if (afterLastPath != null)
|
|||
|
{
|
|||
|
if (afterLastPath == pathEnd)
|
|||
|
{
|
|||
|
matches = false;
|
|||
|
break;
|
|||
|
}
|
|||
|
pathPtr = afterLastPath++;
|
|||
|
wildPtr = afterLastWild;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
matches = false;
|
|||
|
break; // "x" doesn't match "xy"
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
t = *pathPtr;
|
|||
|
w = *wildPtr;
|
|||
|
|
|||
|
if (!Environment.IsFileSystemCaseSensitive)
|
|||
|
{
|
|||
|
t = t.ToUpper;
|
|||
|
w = w.ToUpper;
|
|||
|
}
|
|||
|
|
|||
|
// How do you match a tame text string?
|
|||
|
if (t != w)
|
|||
|
{
|
|||
|
// The tame way: unique up on it!
|
|||
|
if (w == '*')
|
|||
|
{
|
|||
|
afterLastWild = ++wildPtr;
|
|||
|
afterLastPath = pathPtr;
|
|||
|
if (wildPtr == wildEnd)
|
|||
|
{
|
|||
|
break; // "*" matches "x"
|
|||
|
}
|
|||
|
w = *wildPtr;
|
|||
|
continue; // "*y" matches "xy"
|
|||
|
}
|
|||
|
else if (afterLastWild != null)
|
|||
|
{
|
|||
|
if (afterLastWild != wildPtr)
|
|||
|
{
|
|||
|
wildPtr = afterLastWild;
|
|||
|
w = *wildPtr;
|
|||
|
|
|||
|
if (!Environment.IsFileSystemCaseSensitive)
|
|||
|
w = w.ToUpper;
|
|||
|
|
|||
|
if (t == w)
|
|||
|
{
|
|||
|
wildPtr++;
|
|||
|
}
|
|||
|
}
|
|||
|
pathPtr++;
|
|||
|
continue; // "*sip*" matches "mississippi"
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
matches = false;
|
|||
|
break; // "x" doesn't match "y"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pathPtr++;
|
|||
|
wildPtr++;
|
|||
|
}
|
|||
|
|
|||
|
return matches;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|