Skip to content

Instantly share code, notes, and snippets.

@milseman
Last active November 25, 2020 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milseman/d8bef5d49f1ae3db97b19f9ffd0f85a8 to your computer and use it in GitHub Desktop.
Save milseman/d8bef5d49f1ae3db97b19f9ffd0f85a8 to your computer and use it in GitHub Desktop.
C# path examples
using System;
using System.IO;
using System.Linq;
using System.Diagnostics;
namespace HelloWorld { class Program {
// Info: {fullyQualified, root, fullPath}
// Traditional path test cases:
static string[] traditionalPaths = {
// {false, nil, <unchanged>}
@"",
// {false, nil, C:\Users\User\Documents\PathExplorer\C}
@"C",
// {false, C:, C:\Users\User\Documents\PathExplorer}
@"C:",
// {true, C:\, <unchanged>}
@"C:\",
// {false, nil, C:\Users\User\Documents\PathExplorer\ABC:\}
@"ABC:\",
// {false, nil, C:\Users\User\Documents\PathExplorer\:\}
@":\",
// {false, nil, <unchanged>}
@"1:\",
// {true, C:\, <unchanged>}
@"C:\foo\bar.exe",
// {false, C:, C:\Users\User\Documents\PathExplorer\foo\bar}
@"C:foo\bar",
// {false, \, C:\foo\bar.exe}
@"\foo\bar.exe",
// {false, nil, C:\Users\User\Documents\PathExplorer\foo\bar.exe}
@"foo\bar.exe",
// {false, \, C:\}
@"\",
// {false, \, C:\}
@"/",
// {true, c:\, c:\}
@"c:/",
// {true, c:\, c:\foo\bar\}
@"c:/foo/bar/",
};
// UNC path test cases:
static string[] uncPaths = {
// {true, \\server\share, <unchanged>}
@"\\server\share\",
// {true, \\server\share, <unchanged>}
@"\\server\share",
// {true, \\server\share, <unchanged>}
@"\\server\share\folder\file.txt",
// {true, \\server\, <unchanged>}
@"\\server\",
// {true, \\server, <unchanged>}
@"\\server",
// {true, \\system07\C$, <unchanged>}
@"\\system07\C$\foo",
// {true, \\system07\ABC$, <unchanged>}
@"\\system07\ABC$\foo",
// {true, \\system07\ABC:, <unchanged>}
@"\\system07\ABC:\foo",
// {true, \\system07\ABC, <unchanged>}
@"\\system07\ABC\foo",
// {true, \\system07\C:, <unchanged>}
@"\\system07\C:\foo",
// {true, \\server1\util, <unchanged>}
@"\\server1\util\file\",
// {true, \\server1\e:, \\server1\e:\util\file\}
@"\\server1\e:\util\\file\",
// {true, \\.\UNC\server\share, <unchanged>}
@"\\.\UNC\server\share\foo",
// {true, \\.\UNC\Server\Share, <unchanged>}
@"\\.\UNC\Server\Share\Test\Foo.txt",
// {true, \\server, <unchanged>}
@"\\server",
// {true, \\server\, <unchanged>}
@"\\server\",
// {true, \\server\, \\server\}
@"\\server\\",
// {true, \\server\, \\server\folder}
@"\\server\\folder",
// {true, \\server\x, <unchanged>}
@"\\server\x\folder",
// {true, \\server\, \\server\folder\file.txt}
@"\\server\\folder\file.txt",
// {true, \\, <unchanged>}
@"\\",
// {true, \\x, <unchanged>}
@"\\x",
// {true, \\, <unchanged>}
@"\\\",
// {true, \\, \\\}
@"\\\\",
// {true, \\, \\}
@"//",
// {true, \\server\share, \\server\share}
@"//server/share",
// {true, \\server\share, \\server\share\file}
@"//server/share/file",
// {true, \\server\, \\server\file}
@"//server//file",
// {true, \\server\, \\server\file}
@"/\server//file",
// {true, \\.hidden\file, <unchanged>}
@"\\.hidden\file",
// {true, \\?question\file, <unchanged>}
@"\\?question\file",
};
// DOS device path test cases:
static string[] devicePaths = {
// {true, \\.\volume\, <unchanged>}
@"\\.\volume\foo",
// {true, \\.\C:\, <unchanged>}
@"\\.\C:\Test\Foo.txt",
// {true, \\?\C:\, <unchanged>}
@"\\?\C:\Test\Foo.txt",
// {true, \\?\C$\, <unchanged>}
@"\\?\C$\Test\Foo.txt",
// {true, \\?\C:foo\, <unchanged>}
@"\\?\C:foo\Foo.txt",
// {true, \\?\C$foo\, <unchanged>}
@"\\?\C$foo\Foo.txt",
// {true, \\?\server1\, <unchanged>}
@"\\?\server1\e:\util\\file\",
// {true, \\?\server1\, <unchanged>}
@"\\?\server1\util\\file\",
// {true, \\?\server1\, <unchanged>}
@"\\?\server1\util\file\",
// {true, \\.\CON, <unchanged>}
@"\\.\CON",
// {true, \\.\CON\, <unchanged>}
@"\\.\CON\",
// {true, \\.\LPT1, <unchanged>}
@"\\.\LPT1",
// {true, \\.\COM1, <unchanged>}
@"\\.\COM1",
// {true, \\., \\.\}
@"\\.",
// {true, \\.\, <unchanged>}
@"\\.\",
// {true, \\.\vol, <unchanged>}
@"\\.\vol",
};
// DOS device GUID-volume path test cases:
static string[] guidPaths = {
// {true, \\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\, <unchanged>}
@"\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt",
// {true, \\?\Volume{b75e2c83-0000-0000-0000-602f00000000}\, <unchanged>}
@"\\?\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt",
// {true, \\server\Volume{b75e2c83-0000-0000-0000-602f00000000}, <unchanged>}
@"\\server\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt",
// {true, \\.\UNC\server\Volume{b75e2c83-0000-0000-0000-602f00000000}, <unchanged>}
@"\\.\UNC\server\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt",
};
// Legacy DOS device path test cases:
static string[] legacyDevicePaths = {
// {false, nil, \\.\CON}
@"CON",
// {false, nil, C:\Users\User\Documents\PathExplorer\CON\}
@"CON\",
// {false, nil, \\.\CON}
@"CON.TXT",
// {false, nil, C:\Users\User\Documents\PathExplorer\CON.TXT\}
@"CON.TXT\",
// {false, nil, C:\Users\User\Documents\PathExplorer\CON.TXT\FILE.TXT}
@"CON.TXT\FILE.TXT",
// {false, nil, \\.\LPT1}
@"LPT1",
// {false, nil, C:\Users\User\Documents\PathExplorer\LPT1\}
@"LPT1\",
// {false, nil, \\.\LPT1}
@"LPT1.TXT",
// {false, nil, C:\Users\User\Documents\PathExplorer\LPT1.TXT\}
@"LPT1.TXT\",
// {false, nil, \\.\LPT1}
@"LPT1.XTX",
// {false, nil, \\.\COM1}
@"COM1",
// {false, nil, C:\Users\User\Documents\PathExplorer\COM1\}
@"COM1\",
// {false, nil, \\.\COM1}
@"COM1.TXT",
// {false, nil, C:\Users\User\Documents\PathExplorer\COM1.TXT\}
@"COM1.TXT\",
// {false, nil, C:\Users\User\Documents\PathExplorer\CON1}
@"CON1",
// {false, nil, C:\Users\User\Documents\PathExplorer\LPT1\FILE.TXT}
@"LPT1\FILE.TXT",
// {false, nil, C:\Users\User\Documents\PathExplorer\COM}
@"COM",
// {false, nil, C:\Users\User\Documents\PathExplorer\COM1.TXT\FILE.TXT}
@"COM1.TXT\FILE.TXT",
};
static void print(string content) {
Console.WriteLine(content.TrimEnd());
}
// Print out the path test cases and associated output as source-idempotent code
static void printPathStats(string title, string name, string[] paths) {
int length = 0;
int rootLength = 0;
bool hasRelative = false;
foreach (string path in paths) {
length = Math.Max(length, path.Length);
rootLength = Math.Max(rootLength, path.Length > 0 ? Path.GetPathRoot(path).Length : 0);
hasRelative = hasRelative || !Path.IsPathFullyQualified(path);
}
print($"// {title} test cases:");
print($"static string[] {name} = {'{'}");
foreach (string path in paths) {
bool rooted = Path.IsPathRooted(path);
string pathRoot = Path.GetPathRoot(path);
bool fullyQualified = Path.IsPathFullyQualified(path);
Debug.Assert(rooted == (pathRoot != "" && pathRoot != null));
string rootStr = rooted ? pathRoot : "nil";
string qual = fullyQualified ? "true, " : "false, ";
string root = $"{rootStr}, {new string(' ', Math.Max(0, rootLength - rootStr.Length))}";
string full = "<unchanged>";
if (path != "") {
string fullPath = Path.GetFullPath(path);
if (path != fullPath) {
full = fullPath;
}
}
string prefix = $" @\"{path}\"";
string comment = $" // {{{qual}{root}{full}}}";
string output = $"{prefix},{new string(' ', length - path.Length)}";
print(comment);
print(output);
print("");
}
print("};");
print("");
}
static void Main(string[] args)
{
print("// Info: {fullyQualified, root, fullPath}");
print("");
printPathStats("Traditional path", "traditionalPaths", traditionalPaths);
printPathStats("UNC path", "uncPaths", uncPaths);
printPathStats("DOS device path", "devicePaths", devicePaths);
printPathStats("DOS device GUID-volume path", "guidPaths", guidPaths);
printPathStats("Legacy DOS device path", "legacyDevicePaths", legacyDevicePaths);
}
} } // namespace HelloWorld { class Program {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment