digitalmars.D.announce - Some path functions
- Kramer (1010/1010) Jul 30 2006 I have some functions for the path module that I'd like to submit to the...
- Kramer (635/635) Jul 30 2006 Here's the unittests. An excessive amount to be sure, but, hey,
- Bruno Medeiros (7/13) Aug 17 2006 Seems nice (haven't used yet though, maybe in the future, for shell
- Kramer (3/15) Aug 17 2006 Thanks. Hopefully, they're useful. :)
I have some functions for the path module that I'd like to submit to the general public. I haven't worked on them for about half a year and I had submitted them to Walter for inclusion into Phobos a while back, but he's got far more pressing issues (like bug fixes and spec. stability) to concern himself with. The list of included functions: getRoots isRoot containsRoot normPath // normalize a path; similar to the Python version // http://docs.python.org/lib/module-os.path.html isNormPath normCase // normalize the case normSep // normalize the separators for the given os join // variadic join absPath // includes a private isAbs because the one in std.path doesn't seem to be working expandPath // similar to the Ruby version // http://www.rubycentral.com/ref/ref_c_file.html#expand_path I offer the code free to anyone; use it as you may, it's public domain. I hope it works, but offer no assurances on it's quality and am not responsible for it's use in other code. It compiles clean under DMD 0.163 on Windows, but I haven't tested it on Linux since I wrote it -- I no longer have access to a Linux box. The functions use an internal isAbs function because when I was writing the code I found the one in Phobos to not be accurate. I'm probably wrong on that front, so to get the Phobos isAbs functionality, remove the internal one (the internal one returns a bool instead of an int, so any compares will need to be modified). Hopefully someone will find it useful, but in the end, I just wanted to do my small share to contribute to this fantastic language. Walter, keep up the good work on this language. But I have to say, honestly, to the community, keep up the good work and motivation. I've never come across a more intelligent and dedicated langauge community. And friendly by the way. It's always a pleasure reading the newsgroups. Onward, upward and D-ward! -Kramer P.S. - I'm having some trouble attaching the code so I'm just pasting it in this message. Formatting will be screwy I'm sure, but I'm not sure how else to post. I think my file is too large to send, so I'm leaving out the unittests in this message and will past them in another. /** * Author: Joe Zuccarello * Date: February 2006 * * By the author's permission, this code is considered in the public domain for modification and * redistribution at will. */ private import std.string, std.path, std.file, std.regexp, std.utf, std.stdarg, std.format; version(Windows) private import std.c.windows.windows; version(Windows) { extern(Windows) { export { DWORD GetLogicalDriveStringsA(DWORD, LPTSTR); DWORD GetLogicalDriveStringsW(DWORD, LPWSTR); } } } private static const char[] wSep = r"\", lSep = "/", rSeps = "[\\\\/]"; // For regexp use void main() {} /** * Returns all roots for the system. * * This will return all the roots that are know by the system. * * For Windows, it will be the drives that are available. * For Linux, it will always return root "/". * * Note, this function uses the Windows API to retrieve the roots. If is ANSI characters are being * used, getRoots will attemp to convert it to UTF8. If the UTF8 code throws a UTF exception, * that exception will not be caught and will be propogated to the caller code. * * Authors: Joe Zuccarello * * Date: February 14, 2006 * * Returns: All roots for the system. * * Throws: (Windows) UtfException on conversion error from ANSI to UTF-8 if the OS is using ANSI. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * // Assume roots "A:\", "C:\" and "D:\" exist * getRoots() => "A:\", "C:\", "D:\" * } * version(linux) * { * getRoots() => "/" * } * --------- */ char[][] getRoots() { char[][] rtnBuffer; version(Windows) { DWORD bufferLen = 50, rtnVal; char[] buffer; // Unicode void getDrivesW() { wchar[] wBuffer; wBuffer.length = bufferLen; rtnVal = GetLogicalDriveStringsW(bufferLen, wBuffer); buffer = std.utf.toUTF8(wBuffer); } // ANSI void getDrivesA() { char* tmpBuf = std.windows.charset.toMBSz(buffer); rtnVal = GetLogicalDriveStringsA(bufferLen, tmpBuf); buffer = std.windows.charset.fromMBSz(tmpBuf); } // Set initial buffer size buffer.length = bufferLen; if (useWfuncs) { getDrivesW(); } else { getDrivesA(); } while (rtnVal > bufferLen) { bufferLen = rtnVal; buffer.length = bufferLen; if (useWfuncs) { getDrivesW(); } else { getDrivesA(); } } rtnBuffer.length = buffer.length; int j = 0; for (int i, nullCnt = 0; i < buffer.length && nullCnt < 2; i++) { if (buffer[i..(i + 1)] != "\0") { rtnBuffer[j] ~= buffer[i..(i + 1)]; nullCnt = 0; } else { nullCnt++; j++; } } rtnBuffer.length = j - 1; return rtnBuffer.dup; } else version(linux) { rtnBuffer ~= "/"; return rtnBuffer.dup; } else { pragma(msg, "Unsupported OS"); static assert(0); } } /** * Returns true/false whether a path is a root of the system. * * This can be used to test a path to see if it's a root of the system. * * Authors: Joe Zuccarello * * Date: February 14, 2006 * * Returns: true/false whether a path is a root of the system. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * // Assume on Windows, c:\ exists * isRoot(r"c:\") => true * } * version(linux) * { * isRoot("/") => true * } * --------- */ bool isRoot(char[] path, bool caseSensitive = false) { char[][] roots = getRoots(); foreach (char[] x; roots) { if (caseSensitive == true) { if (x == path) { return true; } } else { if (std.string.tolower(x) == std.string.tolower(path)) { return true; } } } return false; } /** * Returns true/false whether a path contains a root of the system. * * This can be used to test a path, to determine if it starts with a system root. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: true/false whether a path starts with a system root. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * // Assume on Windows, c:\ exists * containsRoot(r"c:\directory\file") => true * containsRoot(r"\directory\file") => false * } * version(linux) * { * containsRoot("/usr/d/src") => true * containsRoot("../d/src") => false * containsRoot("\d/src") => false * } * --------- */ bool containsRoot(char[] path, bool caseSensitive = false) { char[][] roots = getRoots(); foreach (char[] x; roots) { if (caseSensitive == true) { if (std.string.find(path, x) == 0) { return true; } } else { if (std.string.ifind(path, x) == 0) { return true; } } } return false; } /** * Test whether a path is normalized. * * Use this to test whether a path is normalized. * * Note: This function does not handle UNC paths. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: true/false whether a path is normalized. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * isNormPath(r"directory1\..\directory2\file\.") => false * // This one returns true, because there's no parent directory to collapse to. * isNormPath(r"..\directory\file") => true * } * version(linux) * { * isNormPath("/dir/../file") => false * isNormPath("/file") => true * } * --------- */ bool isNormPath(char[] path) { RegExp re; version(Windows) { // Special cases if (path == "." || path == ".." || (path == r"\" || path == "/") || std.regexp.find(path, "^\\.\\." ~ "(" ~ rSeps ~ "\\.\\.)+") != -1 || std.regexp.find(path, "^[a-zA-Z]*:" ~ rSeps ~ "$") != -1) { return true; } else { // Look for the following. If found, then this is not a normalized path if (std.regexp.find(path, rSeps ~ "$") != -1 || std.regexp.find(path, rSeps ~ "\\.\\." ~ "(" ~ rSeps ~ "|$)") != -1 || std.regexp.find(path, rSeps ~ "\\." ~ "(" ~ rSeps ~ "|$)") != -1 || std.regexp.find(path, "^\\." ~ rSeps) != -1 || std.regexp.find(path, rSeps ~ "{2,}") != -1) { return false; } else { return true; } } } else version(linux) { // Special cases if (path == "." || path == ".." || (path == r"\" || path == "/") || std.regexp.find(path, "^\\.\\." ~ "(" ~ rSeps ~ "\\.\\.)+") != -1) { return true; } else { // Look for the following. If found, then this is not a normalized path if (std.regexp.find(path, lSep ~ "$") != -1 || std.regexp.find(path, lSep ~ "\\.\\." ~ "(" ~ lSep ~ "|$)") != -1 || std.regexp.find(path, lSep ~ "\\." ~ "(" ~ lSep ~ "|$)") != -1 || std.regexp.find(path, "^\\." ~ lSep) != -1 || std.regexp.find(path, lSep ~ "{2,}") != -1) { return false; } else { return true; } } } else { pragma(msg, "Unsupported OS"); static assert(0); } } /** * Normalizes a path. * * This will normalize a path by collapsing redundant separators and parent/current directory * references. It will also remove any trailing separators and normalize separators as appropriate * for the OS. * * Inspired by the Python v2.4.2 implementation. * * Note: This function does not handle UNC paths. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: A normalized path. * * Version: * * License: Public domain. * * Examples: * --------- * normPath("/dir1/../dir2/./file/") => "/dir2/file" * normPath("/dir..../file/./") => "/dir..../file" * --------- */ char[] normPath(char[] path) out(result) { assert(isNormPath(result)); } body { int pcIdx, pcIdx2; char[][] pathComps; // path components after splitting char[] result, drive; // Normalize the separators for the os path = normSep(path); // Sanity check. No need to process a separator, curdir or pardir reference. if (path != sep && path != curdir && path != pardir) { // Remove the drive from the path version(Windows) { int idx = std.string.find(path, ":"); drive ~= idx != -1 ? path[0..(idx + 1)] : ""; if (idx != -1) { if ((idx + 1) < path.length) { path = path[(idx + 1)..$]; } else { path = ""; } } } // Remove repeating separators path = std.string.squeeze(path, sep); // If there's an initial separator even after a drive, save it off if (path != "") { if (path[0..1] == sep) { drive ~= sep; } } // Split the path components pathComps = std.string.split(path, sep); while (pcIdx < pathComps.length) { // Current directory if (pathComps[pcIdx] == curdir) { if (pathComps.length == 1) { pathComps.length = 0; } else if (pathComps.length > 1) { // At the beginning if (pcIdx == 0) { pathComps = pathComps[1..$]; } // At the end else if ((pcIdx + 1) == pathComps.length) { pathComps = pathComps[0..pcIdx]; } // In the middle else { pathComps = pathComps[0..pcIdx] ~ pathComps[(pcIdx + 1)..$]; } } } // Parent directory reference else if (pathComps[pcIdx] == pardir) { if (pathComps.length == 1) { pcIdx++; } else if (pathComps.length > 1) { // At the beginning if (pcIdx == 0) { // We don't know what to do with this, so move on pcIdx++; } // Found a reference but there was a separator before it. Need // to remove this reference. else if (pcIdx == 1 && pathComps[(pcIdx - 1)] == "") { // Delete the reference if ((pcIdx + 1) < pathComps.length) { pathComps = pathComps[0..pcIdx] ~ pathComps[(pcIdx + 1)..$]; pcIdx--; } else { pathComps = pathComps[0..pcIdx]; } } else { if (pathComps[(pcIdx - 1)] != pardir) { if ((pcIdx + 1) < pathComps.length) { // Delete the reference and the preceding entry pathComps = pathComps[0..(pcIdx - 1)] ~ pathComps[(pcIdx + 1)..$]; pcIdx--; } // End of line else { pathComps = pathComps[0..(pcIdx - 1)]; } } else { pcIdx++; } } } } // Something else else { pcIdx++; } } // Delete any blank chunks out of the array for joining later for (int i = 0; i < pathComps.length; i++) { if (pathComps[i] == "") { if (pathComps.length == 1) { pathComps.length = 0; } else if (pathComps.length > 1) { // At the beginning if (i == 0) { pathComps = pathComps[1..$]; } // At the end else if ((i + 1) == pathComps.length) { pathComps = pathComps[0..i]; } // In the middle. This should already have been taken care of from the logic near // the top of this function from using the squeeze and then split, there shouldn't be // any blank chunks in the middle. } } } result = std.string.join(pathComps, sep); } // Path was either a separator, curdir or pardir reference else { result = path; } if (result == "" && drive == "") { result = curdir; } else { result = drive ~ result; } return result.dup; } /** * Normalize the case and separators of a path. * * This will normalize the case for a path depending on the operating system in use. For case * -insensitive os's (such as Windows), the path will be lower-cased. For case sensitive os's (such * as Linux), the path case will not be changed. On Windows, forward slashes will be converted to * backward slashes and on Linux, backward slashes will be converted to forward slashes. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: Normalized case and separators for a path. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * normCase(r"C:\directory1\Subdirectory/FILE) => "c:\directory1\subdirectory\file" * } * version(linux) * { * normCase(r"\usr/src\Path.d") => "\usr/src\Path.d" * } * --------- */ char[] normCase(char[] path) { version(Windows) { // Take care of the case path = std.string.tolower(path); } path = normSep(path); return path.dup; } /** * * Normalizes the separators in a path. * * Use this to normalize separators as appropriate for the operating system in use. On Windows, * forward slashes * will be converted to backward slashes. On Linux, the path will just be * returned. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: Normalized separators for a path. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * normSep(r"c:/directory\file") => "c:\directory\file" * } * version(linux) * { * normSep(r"/dir1\dir2\dir3/file") => "/dir1\dir2\dir3/file" * } * --------- */ char[] normSep(char[] path) { version(Windows) { // Convert separators if (std.regexp.find(path, lSep) != -1) { path = std.string.replace(path, lSep, wSep); return path.dup; } else { return path; } } else version(linux) { return path; } else { pragma(msg, "Unsupported OS"); static assert(0); } } /** * Joins an arbitrary number of paths together, using std.path.join as the main joining component. * * This will take an arbitrary number of paths and join them by passing them to std.path.join to do * the actual joining. *** Join rules follow that of std.path.join *** * * Note, this function may attempt to convert non-UTF8 characters to UTF8. If the UTF8 code throws * a UTF exception, that exception will not be caught and will be propogated to the caller code. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: A path joined of one or more separate paths. * * Throws: UtfException on error from conversion of wchar or dchar parameters. * * Version: * * License: Public domain. * * Examples: * --------- * join(r"\dir1", "dir2", "dir3/file") => "\dir1\dir2\dir3/file" * --------- */ char[] join(...) { char[] pathX, rtnPath; char[] toStringW(wchar c) { wchar[] result; result.length = 1; result[0] = c; return std.utf.toUTF8(result); } char[] toStringD(dchar c) { dchar[] result; result.length = 1; result[0] = c; return std.utf.toUTF8(result); } for (int i = 0; i < _arguments.length; i++) { if (_arguments[i] == typeid(char[])) { pathX = va_arg!(char[])(_argptr); } else if (_arguments[i] == typeid(wchar[])) { pathX = std.string.toUTF8(va_arg!(wchar[])(_argptr)); } else if (_arguments[i] == typeid(dchar[])) { pathX = std.string.toUTF8(va_arg!(dchar[])(_argptr)); } else if (_arguments[i] == typeid(char)) { pathX = std.string.toString(va_arg!(char)(_argptr)); } else if (_arguments[i] == typeid(wchar)) { pathX = toStringW(va_arg!(wchar)(_argptr)); } else if (_arguments[i] == typeid(dchar)) { pathX = toStringD(va_arg!(dchar)(_argptr)); } if (pathX != "") { rtnPath = std.path.join(rtnPath, pathX); pathX = ""; } } return rtnPath.dup; } /** * Returns a normalized absolutized path. * * If the path is not absolute, it will be joined with the current working directory. If it is an * absolute path, nothing will be joined with it. In either case, the path will also be checked to * see if it is normalized. If it's not, it will be normalized. * * Note: This function does not handle UNC paths. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: A normalized absolutized path. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * // Assume c:\ is the current working directory * absPath(r"file") => "c:\file" * absPath(r"c:\d/src\project") => "c:\d\src\project" * absPath(r".\dir\file\..\dir2\file2") => "c:\dir\dir2\file2" * } * version(linux) * { * // Assume /usr is the current working directory * absPath("d/bin") => "/usr/d/bin" * absPath("/d/lib") => "/d/lib" * absPath("d/src/../file") => "/usr/d/file" * } * --------- */ char[] absPath(char[] path) out(result) { assert(isNormPath(result)); } body { bool changed; version(Windows) { // Path is not absolute //if (std.regexp.find(path, "^[a-zA-Z]*:\\\\") == -1) if (isAbs(path) == false) { path = std.path.join(getcwd(), path); changed = true; } } else version(linux) { // Path is not absolute //if (path[0..1] != r"\" && path[0..1] != "/") if (isAbs(path) == false) { path = std.path.join(getcwd(), path); changed = true; } } else { pragma(msg, "Unsupported OS"); static assert(0); } // Normalize the path if (isNormPath(path) == false) { path = normPath(path); changed = true; } if (changed == true) { return path.dup; } else { return path; } } private bool isAbs(char[] path) { version(Windows) { if (std.regexp.find(path, "^[a-zA-Z]*:\\\\") != -1) { return true; } else { return false; } } else version(linux) { if (path[0..1] == "/") { return true; } else { return false; } } else { pragma(msg, "Unsupported OS"); static assert(0); } } /** * Expands a path into a normalized absolutized path, with a optional reference directory to use * with relative paths. * * This will take a path and expand it into a normalized absolutized version of itself. An optional * reference directory can be provided as well. If the path passed in is relative, the reference * directory will be used to precede the path. If the reference directory is a relative directory, * the reference directory and the path will be appended to the current working directory. * * Note: This function does not handle UNC paths. * * Authors: Joe Zuccarello * * Date: February 15, 2006 * * Returns: A normalized absolutized path. * * Version: * * License: Public domain. * * Examples: * --------- * version(Windows) * { * // Assume c:\ is the current working directory * expandPath("file") => "c:\file" * expandPath(r"\dir\file") => "c:\dir\file" * expandPath("file", r"\dir") => "c:\dir\file" * } * version(linux) * { * // Assume /usr is the current working directory * expandPath("file") => "/usr/file" * expandPath(r"/dir/file") => "/usr/dir/file" * expandPath("file", "/dir") => "/usr/dir/file" * } * --------- */ char[] expandPath(char[] path, char[] dir = "") { char[] result; if (path != "") { // Path is absolute; ditch the dir and return this after normalizing. if (isAbs(path) == true) { result = normPath(path); } // Path is not absolute else { if (dir != "") { // Check if dir is absolute if (isAbs(dir) == true) { result = normPath(dir ~ sep ~ path); } // Dir is not absolute, but it is a directory (at least that's // what the caller is telling us. else { result = normPath(getcwd() ~ sep ~ dir ~ sep ~ path); } } // Dir is empty and path is not absolute else { result = normPath(getcwd() ~ sep ~ path); } } } // Path is empty, check dir else { if (dir != "") { // Check if dir is absolute if (isAbs(dir) == true) { result = normPath(dir); } else { result = normPath(getcwd() ~ sep ~ dir); } } // Path and dir are empty else { result = ""; } } return result.dup; }
Jul 30 2006
Here's the unittests. An excessive amount to be sure, but, hey, sometimes overly verifing your code can be fun. :) // isRoot unittest { version(Windows) { // Valid roots assert(isRoot(getDrive(getcwd()) ~ sep)); assert(isRoot(std.string.toupper(getDrive(getcwd()) ~ sep), true)); // Invalid roots char[][] roots = getRoots(); char[] lastRoot = roots[($ - 1)]; char[] succRoot = std.string.succ(lastRoot[0..($ - 2)]) ~ lastRoot[($ - 2)..$]; assert(!isRoot(succRoot)); assert(!isRoot(std.string.tolower(getDrive(getcwd()) ~ sep), true)); } else version(linux) { // Valid roots assert(isRoot("/")); assert(isRoot(getRoots()[0])); // Invalid roots assert(!isRoot("../")); assert(!isRoot(r"\")); } else { pragma(msg, "Unsupported OS"); static assert(0); } } // containsRoot unittest { version(Windows) { // Valid roots assert(containsRoot(getcwd())); assert(containsRoot(getDrive(getcwd()) ~ sep)); assert(containsRoot(std.string.toupper(getcwd()), true)); // Invalid roots int idx = std.string.find(getcwd(), getDrive(getcwd())); assert(!containsRoot(getcwd()[idx..(getDrive(getcwd()).length)])); assert(!containsRoot(std.string.tolower(getcwd()), true)); assert(!containsRoot(std.string.tolower(getDrive(getcwd()) ~ sep), true)); assert(!containsRoot(r"\directory\file")); } else version(linux) { // Valid roots assert(containsRoot("/usr/d/src")); // Invalid roots assert(!containsRoot("../d/src")); assert(!containsRoot(r"\d/src")); } else { pragma(msg, "Unsupported OS"); static assert(0); } } // isNormPath unittest { version(Windows) { assert(!isNormPath(r" .\")); assert(!isNormPath(r".\")); assert(!isNormPath(r"\.")); assert(!isNormPath(r"\.\")); assert(!isNormPath(r"..\")); assert(!isNormPath(r"\..")); assert(!isNormPath(r"\..\")); assert(!isNormPath(r"\\")); } else version(linux) { assert(isNormPath(r" .\")); assert(isNormPath(r".\")); assert(isNormPath(r"\.")); assert(isNormPath(r"\.\")); assert(isNormPath(r"..\")); assert(isNormPath(r"\..")); assert(isNormPath(r"\..\")); assert(isNormPath(r"\\")); } else { pragma(msg, "Unsupported OS"); static assert(0); } // These patterns are not normalized paths assert(!isNormPath("//")); assert(!isNormPath(" ./")); assert(!isNormPath("./")); assert(!isNormPath("/.")); assert(!isNormPath("/./")); assert(!isNormPath("../")); assert(!isNormPath("/..")); assert(!isNormPath("/../")); assert(!isNormPath(r"\/")); // These patterns are normalized paths assert(isNormPath("")); assert(isNormPath(" ")); assert(isNormPath(" ")); assert(isNormPath(" a b c")); assert(isNormPath("b")); assert(isNormPath(".")); assert(isNormPath("..")); assert(isNormPath(r"\")); assert(isNormPath("/")); assert(isNormPath(r"..\..")); assert(isNormPath("../..")); // Now test the patterns that are part of the normPath unittest, duh duh dun... assert(isNormPath(normPath(""))); assert(isNormPath(normPath(" "))); assert(isNormPath(normPath(" "))); assert(isNormPath(normPath("."))); assert(isNormPath(normPath(".."))); assert(isNormPath(normPath(r"\"))); assert(isNormPath(normPath("/"))); assert(isNormPath(normPath("/."))); assert(isNormPath(normPath("./"))); assert(isNormPath(normPath(r"\."))); assert(isNormPath(normPath(r".\"))); assert(isNormPath(normPath(r".\dir1\dir2\file"))); assert(isNormPath(normPath("./dir1/dir2/file"))); assert(isNormPath(normPath(r"dir1\dir2\file\."))); assert(isNormPath(normPath("dir1/dir2/file/."))); assert(isNormPath(normPath(r"\dir1\dir2\file\."))); assert(isNormPath(normPath("/dir1/dir2/file/."))); assert(isNormPath(normPath(r".\dir1\dir2\file\."))); assert(isNormPath(normPath("./dir1/dir2/file/."))); assert(isNormPath(normPath(r".\.\dir1\dir2\file\."))); assert(isNormPath(normPath("././dir1/dir2/file/."))); assert(isNormPath(normPath(r".\.\dir1\dir2\file\.\."))); assert(isNormPath(normPath("././dir1/dir2/file/./."))); assert(isNormPath(normPath(r"dir1\.\dir2"))); assert(isNormPath(normPath("dir1/./dir2"))); assert(isNormPath(normPath(r"dir1\.\.\.\dir2\.\file"))); assert(isNormPath(normPath("dir1/./././dir2/./file"))); assert(isNormPath(normPath(r".\."))); assert(isNormPath(normPath("./."))); assert(isNormPath(normPath(r"\.\"))); assert(isNormPath(normPath("/./"))); assert(isNormPath(normPath(r"\.\.\."))); assert(isNormPath(normPath("/././."))); assert(isNormPath(normPath(r".\.\.\"))); assert(isNormPath(normPath("./././"))); assert(isNormPath(normPath("dir"))); assert(isNormPath(normPath("c:"))); assert(isNormPath(normPath(r"c:\.."))); assert(isNormPath(normPath("c:/.."))); assert(isNormPath(normPath(r"\dir"))); assert(isNormPath(normPath("/dir"))); assert(isNormPath(normPath(r"\dir1\file"))); assert(isNormPath(normPath("/dir1/file"))); assert(isNormPath(normPath(r"\dir1\file\"))); assert(isNormPath(normPath("/dir1/file/"))); assert(isNormPath(normPath(r"\dir1\file\.."))); assert(isNormPath(normPath("/dir1/file/.."))); assert(isNormPath(normPath(r"\dir1\dir2\..\file"))); assert(isNormPath(normPath("/dir1/dir2/../file"))); assert(isNormPath(normPath(r"\dir1\file.."))); assert(isNormPath(normPath("/dir1/file.."))); assert(isNormPath(normPath(r"\dir1\file\..\.."))); assert(isNormPath(normPath("/dir1/file/../.."))); assert(isNormPath(normPath("c:..file"))); assert(isNormPath(normPath(r"c:\..\dir1\..\file"))); assert(isNormPath(normPath("c:/../dir1/../file"))); assert(isNormPath(normPath(r"c:..file\dir1"))); assert(isNormPath(normPath("c:..file/dir1"))); assert(isNormPath(normPath(r"c:..file\dir1\.."))); assert(isNormPath(normPath("c:..file/dir1/.."))); assert(isNormPath(normPath("."))); assert(isNormPath(normPath(r"c:\"))); assert(isNormPath(normPath("c:/"))); assert(isNormPath(normPath(r"c:\dir1\.\"))); assert(isNormPath(normPath("c:/dir1/./"))); assert(isNormPath(normPath(r"c:\dir1\.\file"))); assert(isNormPath(normPath("c:/dir1/./file"))); assert(isNormPath(normPath(r"c:\dir1\.\file\"))); assert(isNormPath(normPath("c:/dir1/./file/"))); assert(isNormPath(normPath(r"c:\dir1\..\file"))); assert(isNormPath(normPath("c:/dir1/../file"))); assert(isNormPath(normPath(r"c:\dir1\..\file\"))); assert(isNormPath(normPath("c:/dir1/../file/"))); assert(isNormPath(normPath(r"c:\dir1\..\file\."))); assert(isNormPath(normPath("c:/dir1/../file/."))); assert(isNormPath(normPath(r"c:\dir1\..\file\.\"))); assert(isNormPath(normPath("c:/dir1/../file/./"))); assert(isNormPath(normPath(r"c:\dir1\..\file\.."))); assert(isNormPath(normPath("c:/dir1/../file/.."))); assert(isNormPath(normPath(r"\\\dir1\file"))); assert(isNormPath(normPath("///dir1/file"))); assert(isNormPath(normPath(r"\\\dir1\..\dir2\file"))); assert(isNormPath(normPath("///dir1/../dir2/file"))); assert(isNormPath(normPath(r"\\\file"))); assert(isNormPath(normPath("///file"))); assert(isNormPath(normPath(r"..\.."))); assert(isNormPath(normPath("../.."))); assert(isNormPath(normPath(r"..\\\.."))); assert(isNormPath(normPath("..///.."))); assert(isNormPath(normPath(r"..\"))); assert(isNormPath(normPath("../"))); assert(isNormPath(normPath(r"..\\\\"))); assert(isNormPath(normPath("..////"))); assert(isNormPath(normPath(r".\"))); assert(isNormPath(normPath("./"))); assert(isNormPath(normPath(r"\.\file"))); assert(isNormPath(normPath("/./file"))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep ~ "file"))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep ~ "file" ~ sep))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file"))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ "."))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ "." ~ sep))); assert(isNormPath(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ ".."))); assert(isNormPath(normPath(sep ~ sep ~ sep ~ "dir1" ~ sep ~ "file"))); assert(isNormPath(normPath(sep ~ sep ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "dir2" ~ sep ~ "file"))); assert(isNormPath(normPath(sep ~ sep ~ sep ~ "file"))); assert(isNormPath(normPath(".." ~ sep ~ ".."))); assert(isNormPath(normPath(".." ~ sep ~ sep ~ sep ~ ".."))); assert(isNormPath(normPath(".." ~ sep))); assert(isNormPath(normPath(".." ~ sep ~ sep ~ sep ~ sep))); assert(isNormPath(normPath("." ~ sep))); assert(isNormPath(normPath(sep ~ "." ~ sep ~ "file"))); assert(isNormPath(normPath(r"~\dir"))); assert(isNormPath(normPath("~/dir"))); assert(isNormPath(normPath(sep ~ ".."))); assert(isNormPath(normPath(sep ~ ".." ~ sep))); assert(isNormPath(normPath(sep ~ ".." ~ sep ~ "dir"))); assert(isNormPath(normPath(sep ~ "..file"))); assert(isNormPath(normPath(sep ~ ".file"))); assert(isNormPath(normPath(".file"))); assert(isNormPath(normPath("file."))); assert(isNormPath(normPath("file.file" ~ sep ~ "." ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ ".."))); assert(isNormPath(normPath("file$."))); } // normPath unittest { version(Windows) { assert(normPath("c:") == "c:"); assert(normPath("c:" ~ sep ~ "..") == r"c:" ~ sep); assert(normPath("c:" ~ sep ~ ".." ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file") == "c:" ~ sep ~ "file"); assert(normPath("c:" ~ sep) == "c:" ~ sep); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep) == "c:" ~ sep ~ "dir1"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep ~ "file") == "c:" ~ sep ~ "dir1" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ "." ~ sep ~ "file" ~ sep) == "c:" ~ sep ~ "dir1" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file") == "c:" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep) == "c:" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ ".") == "c:" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ "." ~ sep) == "c:" ~ sep ~ "file"); assert(normPath("c:" ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "file" ~ sep ~ "..") == "c:" ~ sep); assert(normPath(r"\\/dir1////\\dir2//..\\\\file/./") == sep ~ "dir1" ~ sep ~ "file"); } else version(linux) { assert(normPath("c:/../file") == "file"); assert(normPath(r"c:\..\file") == r"c:\..\file"); assert(normPath("~/dir") == "~/dir"); } else { pragma(msg, "Unsupported OS"); static assert(0); } assert(normPath("") == "."); assert(normPath(r" ./") == r" ."); assert(normPath(" ") == " "); assert(normPath(" ") == " "); assert(normPath(".") == "."); assert(normPath("..") == ".."); assert(normPath(sep) == sep); assert(normPath(sep ~ curdir) == sep); assert(normPath(curdir ~ sep) == curdir); assert(normPath(curdir ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file") == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath("dir1" ~ sep ~ "dir2" ~ sep ~ "file" ~ sep ~ curdir) == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath(sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file" ~ sep ~ curdir) == sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath(curdir ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file" ~ sep ~ curdir) == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath(curdir ~ sep ~ curdir ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file" ~ sep ~ curdir) == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath(curdir ~ sep ~ curdir ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file" ~ sep ~ curdir ~ sep ~ curdir) == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath("dir1" ~ sep ~ curdir ~ sep ~ "dir2") == "dir1" ~ sep ~ "dir2"); assert(normPath("dir1" ~ sep ~ curdir ~ sep ~ curdir ~ sep ~ curdir ~ sep ~ "dir2" ~ sep ~ curdir ~ sep ~ "file") == "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(normPath(curdir ~ sep ~ curdir) == curdir); assert(normPath(sep ~ curdir ~ sep) == sep); assert(normPath(sep ~ curdir ~ sep ~ curdir ~ sep ~ curdir) == sep); assert(normPath(curdir ~ sep ~ curdir ~ sep ~ curdir ~ sep) == curdir); assert(normPath("dir") == "dir"); assert(normPath(sep ~ "dir") == sep ~ "dir"); assert(normPath(sep ~ "dir1" ~ sep ~ "file") == sep ~ "dir1" ~ sep ~ "file"); assert(normPath(sep ~ "dir1" ~ sep ~ "file" ~ sep) == sep ~ "dir1" ~ sep ~ "file"); assert(normPath(sep ~ "dir1" ~ sep ~ "file" ~ sep ~ "..") == sep ~ "dir1"); assert(normPath(sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ ".." ~ sep ~ "file") == sep ~ "dir1" ~ sep ~ "file"); assert(normPath(sep ~ "dir1" ~ sep ~ "file..") == sep ~ "dir1" ~ sep ~ "file.."); assert(normPath(sep ~ "dir1" ~ sep ~ "file" ~ sep ~ ".." ~ sep ~ "..") == sep); assert(normPath("c:..file") == "c:..file"); assert(normPath("c:..file" ~ sep ~ "dir1") == "c:..file" ~ sep ~ "dir1"); assert(normPath("c:..file" ~ sep ~ "dir1" ~ sep ~ "..") == "c:..file"); assert(normPath(sep ~ sep ~ sep ~ "dir1" ~ sep ~ "file") == sep ~ "dir1" ~ sep ~ "file"); assert(normPath(sep ~ sep ~ sep ~ "dir1" ~ sep ~ ".." ~ sep ~ "dir2" ~ sep ~ "file") == sep ~ "dir2" ~ sep ~ "file"); assert(normPath(sep ~ sep ~ sep ~ "file") == sep ~ "file"); assert(normPath(".." ~ sep ~ "..") == ".." ~ sep ~ ".."); assert(normPath(".." ~ sep ~ sep ~ sep ~ "..") == ".." ~ sep ~ ".."); assert(normPath(".." ~ sep) == ".."); assert(normPath(".." ~ sep ~ sep ~ sep ~ sep) == ".."); assert(normPath("." ~ sep) == "."); assert(normPath(sep ~ "." ~ sep ~ "file") == sep ~ "file"); assert(normPath(r"~\dir") == r"~\dir"); assert(normPath("~") == "~"); assert(normPath(sep ~ "..") == sep); assert(normPath(sep ~ ".." ~ sep) == sep); assert(normPath(sep ~ ".." ~ sep ~ "dir") == sep ~ "dir"); assert(normPath(sep ~ "..file") == sep ~ "..file"); assert(normPath(sep ~ ".file") == sep ~ ".file"); assert(normPath(".file") == ".file"); assert(normPath("file.") == "file."); assert(normPath("file.file" ~ sep ~ "." ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "..") == "file.file" ~ sep ~ "dir1"); assert(normPath("file$.") == "file$."); } // normCase unittest { version(Windows) { assert(normCase(r"C:/dir1\file1/dir2/File2") == r"c:\dir1\file1\dir2\file2"); } else version(linux) { assert(normCase(r"/Dir1\file1\DIR2/file2") == r"/Dir1\file1\DIR2/file2"); } else { pragma(msg, "Unsupported OS"); static assert(0); } } // normSep unittest { version(Windows) { assert(normSep(r"c:/dir\file") == r"c:\dir\file"); } else version(linux) { assert(normSep(r"\dir1/dir2\file") == r"\dir1/dir2\file"); } else { pragma(msg, "Unsupported OS"); static assert(0); } } // join unittest { assert(join(r"\dir/file", "file2", r"file3\file4") == r"\dir/file" ~ sep ~ "file2" ~ sep ~ r"file3\file4"); assert(join(r"\dir1\file") == r"\dir1\file"); assert(join(r"\dir1\file", r"dir2\file") == r"\dir1\file" ~ sep ~ r"dir2\file"); assert(join(r"\dir1\file", r"dir2\file", r"dir3\file") == r"\dir1\file" ~ sep ~ r"dir2\file" ~ sep ~ r"dir3\file"); assert(join("file1", "file2", "file3", "file4") == "file1" ~ sep ~ "file2" ~ sep ~ "file3" ~ sep ~ "file4"); assert(join("file1", "file2"w, "file3"d, "file4"c) == "file1" ~ sep ~ "file2" ~ sep ~ "file3" ~ sep ~ "file4"); assert(join("f", "i"w, "l"d, "e"c) == "f" ~ sep ~ "i" ~ sep ~ "l" ~ sep ~ "e"); char c = 'i'; wchar w = 'l'; dchar d = 'e'; assert(join("f", c, w, d) == "f" ~ sep ~ "i" ~ sep ~ "l" ~ sep ~ "e"); assert(join('f', 'i', 'l', 'e') == "f" ~ sep ~ "i" ~ sep ~ "l" ~ sep ~ "e"); version(Windows) { assert(join("file1", r"\dir1\file2") == r"\dir1\file2"); assert(join(r"\file1", r"\dir1") == r"\dir1"); assert(join(r"\file1", "dir1", r"c:\dir2\file2") == r"c:\dir2\file2"); assert(join("file1", r"\dir1", r"c:\dir2", r"d:\dir3", r"file3") == r"d:\dir3\file3"); } version(linux) { assert(join("file1", r"/dir1\file2") == r"/dir1\file2"); assert(join(r"\file1", r"\dir1") == r"\file1/\dir1"); assert(join(r"\file1", "dir1", r"c:\dir2\file2") == r"\file1/dir1/c:\dir2\file2"); assert(join("file1", r"\dir1", r"c:\dir2", r"d:\dir3", r"file3") == r"file1/\dir1/c:\dir2/d:\dir3/file3"); } } // absPath unittest { version(Windows) { assert(absPath(r"c:\dir1\file1\") == r"c:\dir1\file1"); } else version(linux) { assert(absPath("file") == std.path.join(getcwd(), "file")); } else { pragma(msg, "Unsupported OS"); static assert(0); } assert(absPath("file") == std.path.join(getcwd(), "file")); assert(absPath(r"\dir1\file") == std.path.join(getcwd(), r"\dir1\file")); assert(absPath(getcwd())); assert(absPath(absPath(getcwd()))); assert(absPath(absPath(getDirName(getcwd())))); } // expandPath unittest { version(Windows) { assert(expandPath("", "u:") == getcwd() ~ sep ~ "u:"); assert(expandPath("", r"u:\") == r"u:\"); assert(expandPath("", r"u:\dir1") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\file\..") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\..\file\.") == r"u:\file"); assert(expandPath("", r"\dir1\\:file") == getcwd() ~ r"\dir1\:file"); assert(expandPath("", r"\:dir1\\file") == getcwd() ~ r"\:dir1\file"); assert(expandPath("", "u:") == getcwd() ~ r"\u:"); assert(expandPath("", r"u:\") == r"u:\"); assert(expandPath("", r"u:\dir1") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\file\..") == r"u:\dir1"); assert(expandPath("", r"u:\dir1\..\file\.") == r"u:\file"); assert(expandPath("file", r"p:\" ~ "dir1") == r"p:\" ~ "dir1" ~ sep ~ "file"); assert(expandPath("file", r"p:\" ~ "dir1" ~ sep) == r"p:\" ~ "dir1" ~ sep ~ "file"); assert(expandPath("file", r"p:\" ~ "dir1" ~ sep ~ sep) == r"p:\" ~ "dir1" ~ sep ~ "file"); assert(expandPath("file", "p:\\dir1\\\\dir2\\") == "p:" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file", "p:\\dir1\\\\dir2\\\\\\dir3\\\\\\\\dir4\\\\") == "p:" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "dir3" ~ sep ~ "dir4" ~ sep ~ "file"); assert(expandPath("file", "p:") == getcwd() ~ sep ~ "p:" ~ sep ~ "file"); assert(expandPath("file", "p:\\") == "p:" ~ sep ~ "file"); assert(expandPath("file" , "p:\\dir\\.") == "p:" ~ sep ~ "dir" ~ sep ~ "file"); assert(expandPath("file" , "p:\\dir1\\.\\dir2\\") == "p:" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file" , "p:\\dir1\\.\\dir2\\.") == "p:" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file" , "p:\\dir1\\.\\dir2\\.\\") == "p:" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("", r"\") == getcwd()); assert(expandPath("", r"\dir1") == getcwd() ~ r"\dir1"); assert(expandPath("", r"\dir1\\file") == getcwd() ~ r"\dir1\file"); assert(expandPath("", r"\..\dir1\\file") == getDirName(getcwd()) ~ r"\dir1\file"); assert(expandPath("", r"\\\dir1\\file\\..\\dir2\\dir3\\..") == getcwd() ~ r"\dir1\dir2"); assert(expandPath("file") == getcwd() ~ r"\file"); assert(expandPath(r"\dir\file") == getcwd() ~ r"\dir\file"); assert(expandPath("file", r"\dir") == getcwd() ~ r"\dir\file"); assert(expandPath("file", r"....\") == getcwd() ~ sep ~ "...." ~ sep ~ "file"); assert(expandPath("file", "a.\\") == getcwd() ~ sep ~ "a." ~ sep ~ "file"); assert(expandPath("file", "..\\..") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", "..\\..\\") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", "..\\..\\..\\") == getDirName(getDirName(getDirName(getcwd()))) ~ sep ~ "file"); assert(expandPath("file", "..\\..\\..\\..\\") == getDirName(getDirName(getDirName(getDirName(getcwd())))) ~ sep ~ "file"); assert(expandPath("file" , ".\\dir") == getcwd() ~ sep ~ "dir" ~ sep ~ "file"); assert(expandPath("file" , "dir1\\.") == getcwd() ~ sep ~ "dir1" ~ sep ~ "file"); assert(expandPath("file" , "dir1\\.\\dir2") == getcwd() ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file" , ".\\dir1\\.\\dir2") == getcwd() ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file" , ".\\dir1\\.\\dir2\\.") == getcwd() ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file" , ".\\..\\..\\.\\.") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", ".\\..\\.\\.\\..\\") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file" , r"\\.\\dir1\\.\\dir2\\.") == getcwd() ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file", "\\.\\") == getcwd() ~ sep ~ "file"); assert(expandPath("file", "\\") == getcwd() ~ sep ~ "file"); assert(expandPath("file", "\\\\") == getcwd() ~ sep ~ "file"); assert(expandPath("file", "\\..\\..") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", r"c:\..\..") == r"c:\file"); assert(expandPath("file", "\\..\\..\\") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath(r"\dir1\dir2/file", "/refdir") == getcwd() ~ sep ~ "refdir" ~ sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); } else version(linux) { assert(expandPath("file") == getcwd() ~ "/file"); assert(expandPath(r"/dir/file") == "/dir/file"); assert(expandPath("file", "/dir") == "/dir/file"); assert(expandPath("", r"\") == getcwd() ~ r"/\"); assert(expandPath("", "/") == "/"); assert(expandPath("", r"\dir1") == getcwd() ~ r"/\dir1"); assert(expandPath("", r"\dir1\\file") == getcwd() ~ r"/\dir1\\file"); assert(expandPath("", r"/dir1\\file///file2") == r"/dir1\\file/file2"); assert(expandPath("", r"\..\dir1\\file") == getcwd() ~ r"/\..\dir1\\file"); assert(expandPath("", r"\\\dir1\\file\\..\\dir2\\dir3\\..") == getcwd() ~ r"/\\\dir1\\file\\..\\dir2\\dir3\\.."); assert(expandPath("", r"/dir1/file/../dir2/dir3/..") == "/dir1/dir2"); assert(expandPath("file") == getcwd() ~ "/file"); assert(expandPath(r"\dir\file") == getcwd() ~ r"/\dir\file"); assert(expandPath(r"/dir\file") == r"/dir\file"); assert(expandPath("file", r"\dir") == getcwd() ~ r"/\dir/file"); assert(expandPath("file", r"....\") == getcwd() ~ sep ~ r"....\" ~ sep ~ "file"); assert(expandPath("file", r"a.\") == getcwd() ~ sep ~ r"a.\" ~ sep ~ "file"); assert(expandPath("file", r"..\..") == getcwd() ~ r"/..\../file"); assert(expandPath("file", "../..") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", r"..\..\") == getcwd() ~ r"/..\..\/file"); assert(expandPath("file", "../../") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", r"..\..\..\") == getcwd() ~ r"/..\..\..\/file"); assert(expandPath("file", "../../../") == getDirName(getDirName(getDirName(getcwd()))) ~ sep ~ "file"); assert(expandPath("file", r"..\..\..\..\") == getcwd() ~ r"/..\..\..\..\/file"); assert(expandPath("file", "../../../../") == getDirName(getDirName(getDirName(getDirName(getcwd())))) ~ sep ~ "file"); assert(expandPath("file", r".\dir") == getcwd() ~ r"/.\dir/file"); assert(expandPath("file", r"dir1\.") == getcwd() ~ r"/dir1\./file"); assert(expandPath("file", r"dir1\.\dir2") == getcwd() ~ r"/dir1\.\dir2/file"); assert(expandPath("file", r".\dir1\.\dir2") == getcwd() ~ r"/.\dir1\.\dir2/file"); assert(expandPath("file", r".\dir1\.\dir2\.") == getcwd() ~ r"/.\dir1\.\dir2\./file"); assert(expandPath("file", r".\..\..\.\.") == getcwd() ~ r"/.\..\..\.\./file"); assert(expandPath("file", "./../.././.") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file", r".\..\.\.\..\") == getcwd() ~ r"/.\..\.\.\..\/file"); assert(expandPath("file", "./../././../") == getDirName(getDirName(getcwd())) ~ sep ~ "file"); assert(expandPath("file" , r"\\.\\dir1\\.\\dir2\\.") == getcwd() ~ r"/\\.\\dir1\\.\\dir2\\./file"); assert(expandPath("file" , "//.//dir1//.//dir2//.") == sep ~ "dir1" ~ sep ~ "dir2" ~ sep ~ "file"); assert(expandPath("file", r"\.\") == getcwd() ~ r"/\.\/file"); assert(expandPath("file", r"\") == getcwd() ~ r"/\/file"); assert(expandPath("file", r"\\") == getcwd() ~ r"/\\/file"); assert(expandPath("file", r"\..\..") == getcwd() ~ r"/\..\../file"); assert(expandPath("file", "/../..") == "/file"); assert(expandPath("file", r"\..\..\") == getcwd() ~ r"/\..\..\/file"); assert(expandPath(r"\dir1\dir2/file", "/refdir") == r"/refdir/\dir1\dir2/file"); } else { pragma(msg, "Unsupported OS"); static assert(0); } assert(expandPath("") == ""); assert(expandPath("file") == getcwd() ~ sep ~ "file"); assert(expandPath("file", "") == getcwd() ~ sep ~ "file"); assert(expandPath("file", "..") == getDirName(getcwd()) ~ sep ~ "file"); assert(expandPath("..") == getDirName(getcwd())); assert(expandPath(getcwd())); assert(expandPath(getcwd(), "")); assert(expandPath(getcwd(), getcwd())); assert(expandPath(getcwd(), "refdir")); }
Jul 30 2006
Kramer wrote:I have some functions for the path module that I'd like to submit to the general public. I haven't worked on them for about half a year and I had submitted them to Walter for inclusion into Phobos a while back, but he's got far more pressing issues (like bug fixes and spec. stability) to concern himself with.Seems nice (haven't used yet though, maybe in the future, for shell scripting). And indeed it seems like it would be a good addition for Phobos (std.path). -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 17 2006
Bruno Medeiros wrote:Kramer wrote:Thanks. Hopefully, they're useful. :) -KramerI have some functions for the path module that I'd like to submit to the general public. I haven't worked on them for about half a year and I had submitted them to Walter for inclusion into Phobos a while back, but he's got far more pressing issues (like bug fixes and spec. stability) to concern himself with.Seems nice (haven't used yet though, maybe in the future, for shell scripting). And indeed it seems like it would be a good addition for Phobos (std.path).
Aug 17 2006