mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 13:40:20 +03:00
Added examples to std.path
This commit is contained in:
parent
024ebe3e42
commit
c1399d34b0
2 changed files with 241 additions and 207 deletions
|
@ -258,7 +258,6 @@ has_public_example="-etc.c.curl,\
|
|||
-std.net.isemail,\
|
||||
-std.numeric,\
|
||||
-std.parallelism,\
|
||||
-std.path,\
|
||||
-std.process,\
|
||||
-std.range.interfaces,\
|
||||
-std.regex,\
|
||||
|
|
447
std/path.d
447
std/path.d
|
@ -151,6 +151,21 @@ bool isDirSeparator(dchar c) @safe pure nothrow @nogc
|
|||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
version(Windows)
|
||||
{
|
||||
assert( '/'.isDirSeparator);
|
||||
assert( '\\'.isDirSeparator);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( '/'.isDirSeparator);
|
||||
assert(!'\\'.isDirSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Determines whether the given character is a drive separator.
|
||||
|
||||
|
@ -333,14 +348,24 @@ enum CaseSensitive : bool
|
|||
*/
|
||||
osDefault = osDefaultCaseSensitivity
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
assert(baseName!(CaseSensitive.no)("dir/file.EXT", ".ext") == "file");
|
||||
assert(baseName!(CaseSensitive.yes)("dir/file.EXT", ".ext") != "file");
|
||||
|
||||
version(Posix)
|
||||
assert(relativePath!(CaseSensitive.no)("/FOO/bar", "/foo/baz") == "../bar");
|
||||
else
|
||||
assert(relativePath!(CaseSensitive.no)(`c:\FOO\bar`, `c:\foo\baz`) == `..\bar`);
|
||||
}
|
||||
|
||||
version (Windows) private enum osDefaultCaseSensitivity = false;
|
||||
else version (OSX) private enum osDefaultCaseSensitivity = false;
|
||||
else version (Posix) private enum osDefaultCaseSensitivity = true;
|
||||
else static assert(0);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Params:
|
||||
cs = Whether or not suffix matching is case-sensitive.
|
||||
|
@ -356,21 +381,6 @@ else static assert(0);
|
|||
the comparison is case sensitive or not. See the
|
||||
$(LREF filenameCmp) documentation for details.
|
||||
|
||||
Example:
|
||||
---
|
||||
assert(baseName("dir/file.ext") == "file.ext");
|
||||
assert(baseName("dir/file.ext", ".ext") == "file");
|
||||
assert(baseName("dir/file.ext", ".xyz") == "file.ext");
|
||||
assert(baseName("dir/filename", "name") == "file");
|
||||
assert(baseName("dir/subdir/") == "subdir");
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(baseName(`d:file.ext`) == "file.ext");
|
||||
assert(baseName(`d:\dir\file.ext`) == "file.ext");
|
||||
}
|
||||
---
|
||||
|
||||
Note:
|
||||
This function $(I only) strips away the specified suffix, which
|
||||
doesn't necessarily have to represent an extension.
|
||||
|
@ -401,26 +411,6 @@ if (isSomeChar!C)
|
|||
return _baseName(path);
|
||||
}
|
||||
|
||||
private R _baseName(R)(R path)
|
||||
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) || isNarrowString!R)
|
||||
{
|
||||
auto p1 = stripDrive(path);
|
||||
if (p1.empty)
|
||||
{
|
||||
version (Windows) if (isUNC(path))
|
||||
return path[0 .. 1];
|
||||
static if (isSomeString!R)
|
||||
return null;
|
||||
else
|
||||
return p1; // which is empty
|
||||
}
|
||||
|
||||
auto p2 = rtrimDirSeparators(p1);
|
||||
if (p2.empty) return p1[0 .. 1];
|
||||
|
||||
return p2[lastSeparator(p2)+1 .. p2.length];
|
||||
}
|
||||
|
||||
/// ditto
|
||||
inout(C)[] baseName(CaseSensitive cs = CaseSensitive.osDefault, C, C1)
|
||||
(inout(C)[] path, in C1[] suffix)
|
||||
|
@ -436,6 +426,22 @@ if (isSomeChar!C && isSomeChar!C1)
|
|||
else return p;
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
assert(baseName("dir/file.ext") == "file.ext");
|
||||
assert(baseName("dir/file.ext", ".ext") == "file");
|
||||
assert(baseName("dir/file.ext", ".xyz") == "file.ext");
|
||||
assert(baseName("dir/filename", "name") == "file");
|
||||
assert(baseName("dir/subdir/") == "subdir");
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(baseName(`d:file.ext`) == "file.ext");
|
||||
assert(baseName(`d:\dir\file.ext`) == "file.ext");
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
assert(baseName("").empty);
|
||||
|
@ -508,6 +514,26 @@ if (isSomeChar!C && isSomeChar!C1)
|
|||
assert(sa.baseName == "test");
|
||||
}
|
||||
|
||||
private R _baseName(R)(R path)
|
||||
if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) || isNarrowString!R)
|
||||
{
|
||||
auto p1 = stripDrive(path);
|
||||
if (p1.empty)
|
||||
{
|
||||
version (Windows) if (isUNC(path))
|
||||
return path[0 .. 1];
|
||||
static if (isSomeString!R)
|
||||
return null;
|
||||
else
|
||||
return p1; // which is empty
|
||||
}
|
||||
|
||||
auto p2 = rtrimDirSeparators(p1);
|
||||
if (p2.empty) return p1[0 .. 1];
|
||||
|
||||
return p2[lastSeparator(p2)+1 .. p2.length];
|
||||
}
|
||||
|
||||
/** Returns the parent directory of path. On Windows, this
|
||||
includes the drive letter if present.
|
||||
|
||||
|
@ -536,52 +562,6 @@ if (isSomeChar!C)
|
|||
return _dirName(path);
|
||||
}
|
||||
|
||||
private auto _dirName(R)(R path)
|
||||
{
|
||||
static auto result(bool dot, typeof(path[0 .. 1]) p)
|
||||
{
|
||||
static if (isSomeString!R)
|
||||
return dot ? "." : p;
|
||||
else
|
||||
{
|
||||
import std.range : choose, only;
|
||||
return choose(dot, only(cast(ElementEncodingType!R)'.'), p);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.empty)
|
||||
return result(true, path[0 .. 0]);
|
||||
|
||||
auto p = rtrimDirSeparators(path);
|
||||
if (p.empty)
|
||||
return result(false, path[0 .. 1]);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
if (isUNC(p) && uncRootLength(p) == p.length)
|
||||
return result(false, p);
|
||||
|
||||
if (p.length == 2 && isDriveSeparator(p[1]) && path.length > 2)
|
||||
return result(false, path[0 .. 3]);
|
||||
}
|
||||
|
||||
auto i = lastSeparator(p);
|
||||
if (i == -1)
|
||||
return result(true, p);
|
||||
if (i == 0)
|
||||
return result(false, p[0 .. 1]);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
// If the directory part is either d: or d:\
|
||||
// do not chop off the last symbol.
|
||||
if (isDriveSeparator(p[i]) || isDriveSeparator(p[i-1]))
|
||||
return result(false, p[0 .. i+1]);
|
||||
}
|
||||
// Remove any remaining trailing (back)slashes.
|
||||
return result(false, rtrimDirSeparators(p[0 .. i]));
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -673,8 +653,51 @@ private auto _dirName(R)(R path)
|
|||
//static assert(dirName("dir/file".byChar).array == "dir");
|
||||
}
|
||||
|
||||
private auto _dirName(R)(R path)
|
||||
{
|
||||
static auto result(bool dot, typeof(path[0 .. 1]) p)
|
||||
{
|
||||
static if (isSomeString!R)
|
||||
return dot ? "." : p;
|
||||
else
|
||||
{
|
||||
import std.range : choose, only;
|
||||
return choose(dot, only(cast(ElementEncodingType!R)'.'), p);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.empty)
|
||||
return result(true, path[0 .. 0]);
|
||||
|
||||
auto p = rtrimDirSeparators(path);
|
||||
if (p.empty)
|
||||
return result(false, path[0 .. 1]);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
if (isUNC(p) && uncRootLength(p) == p.length)
|
||||
return result(false, p);
|
||||
|
||||
if (p.length == 2 && isDriveSeparator(p[1]) && path.length > 2)
|
||||
return result(false, path[0 .. 3]);
|
||||
}
|
||||
|
||||
auto i = lastSeparator(p);
|
||||
if (i == -1)
|
||||
return result(true, p);
|
||||
if (i == 0)
|
||||
return result(false, p[0 .. 1]);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
// If the directory part is either d: or d:\
|
||||
// do not chop off the last symbol.
|
||||
if (isDriveSeparator(p[i]) || isDriveSeparator(p[i-1]))
|
||||
return result(false, p[0 .. i+1]);
|
||||
}
|
||||
// Remove any remaining trailing (back)slashes.
|
||||
return result(false, rtrimDirSeparators(p[0 .. i]));
|
||||
}
|
||||
|
||||
/** Returns the root directory of the specified path, or `null` if the
|
||||
path is not rooted.
|
||||
|
@ -698,38 +721,6 @@ if (isSomeChar!C)
|
|||
return _rootName(path);
|
||||
}
|
||||
|
||||
private auto _rootName(R)(R path)
|
||||
{
|
||||
if (path.empty)
|
||||
goto Lnull;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
if (isDirSeparator(path[0])) return path[0 .. 1];
|
||||
}
|
||||
else version (Windows)
|
||||
{
|
||||
if (isDirSeparator(path[0]))
|
||||
{
|
||||
if (isUNC(path)) return path[0 .. uncRootLength(path)];
|
||||
else return path[0 .. 1];
|
||||
}
|
||||
else if (path.length >= 3 && isDriveSeparator(path[1]) &&
|
||||
isDirSeparator(path[2]))
|
||||
{
|
||||
return path[0 .. 3];
|
||||
}
|
||||
}
|
||||
else static assert(0, "unsupported platform");
|
||||
|
||||
assert(!isRooted(path));
|
||||
Lnull:
|
||||
static if (is(StringTypeOf!R))
|
||||
return null; // legacy code may rely on null return rather than slice
|
||||
else
|
||||
return path[0 .. 0];
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -777,6 +768,37 @@ Lnull:
|
|||
}
|
||||
}
|
||||
|
||||
private auto _rootName(R)(R path)
|
||||
{
|
||||
if (path.empty)
|
||||
goto Lnull;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
if (isDirSeparator(path[0])) return path[0 .. 1];
|
||||
}
|
||||
else version (Windows)
|
||||
{
|
||||
if (isDirSeparator(path[0]))
|
||||
{
|
||||
if (isUNC(path)) return path[0 .. uncRootLength(path)];
|
||||
else return path[0 .. 1];
|
||||
}
|
||||
else if (path.length >= 3 && isDriveSeparator(path[1]) &&
|
||||
isDirSeparator(path[2]))
|
||||
{
|
||||
return path[0 .. 3];
|
||||
}
|
||||
}
|
||||
else static assert(0, "unsupported platform");
|
||||
|
||||
assert(!isRooted(path));
|
||||
Lnull:
|
||||
static if (is(StringTypeOf!R))
|
||||
return null; // legacy code may rely on null return rather than slice
|
||||
else
|
||||
return path[0 .. 0];
|
||||
}
|
||||
|
||||
/**
|
||||
Get the drive portion of a path.
|
||||
|
@ -804,21 +826,6 @@ if (isSomeChar!C)
|
|||
return _driveName(path);
|
||||
}
|
||||
|
||||
private auto _driveName(R)(R path)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
if (hasDrive(path))
|
||||
return path[0 .. 2];
|
||||
else if (isUNC(path))
|
||||
return path[0 .. uncRootLength(path)];
|
||||
}
|
||||
static if (isSomeString!R)
|
||||
return cast(ElementEncodingType!R[]) null; // legacy code may rely on null return rather than slice
|
||||
else
|
||||
return path[0 .. 0];
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -874,6 +881,20 @@ private auto _driveName(R)(R path)
|
|||
}
|
||||
}
|
||||
|
||||
private auto _driveName(R)(R path)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
if (hasDrive(path))
|
||||
return path[0 .. 2];
|
||||
else if (isUNC(path))
|
||||
return path[0 .. uncRootLength(path)];
|
||||
}
|
||||
static if (isSomeString!R)
|
||||
return cast(ElementEncodingType!R[]) null; // legacy code may rely on null return rather than slice
|
||||
else
|
||||
return path[0 .. 0];
|
||||
}
|
||||
|
||||
/** Strips the drive from a Windows path. On POSIX, the path is returned
|
||||
unaltered.
|
||||
|
@ -896,16 +917,6 @@ if (isSomeChar!C)
|
|||
return _stripDrive(path);
|
||||
}
|
||||
|
||||
private auto _stripDrive(R)(R path)
|
||||
{
|
||||
version(Windows)
|
||||
{
|
||||
if (hasDrive!(BaseOf!R)(path)) return path[2 .. path.length];
|
||||
else if (isUNC!(BaseOf!R)(path)) return path[uncRootLength!(BaseOf!R)(path) .. path.length];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -956,6 +967,16 @@ private auto _stripDrive(R)(R path)
|
|||
}
|
||||
}
|
||||
|
||||
private auto _stripDrive(R)(R path)
|
||||
{
|
||||
version(Windows)
|
||||
{
|
||||
if (hasDrive!(BaseOf!R)(path)) return path[2 .. path.length];
|
||||
else if (isUNC!(BaseOf!R)(path)) return path[uncRootLength!(BaseOf!R)(path) .. path.length];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/* Helper function that returns the position of the filename/extension
|
||||
separator dot in path.
|
||||
|
@ -1085,12 +1106,6 @@ if (isSomeChar!C)
|
|||
return _stripExtension(path);
|
||||
}
|
||||
|
||||
private auto _stripExtension(R)(R path)
|
||||
{
|
||||
immutable i = extSeparatorPos(path);
|
||||
return i == -1 ? path : path[0 .. i];
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -1127,6 +1142,11 @@ private auto _stripExtension(R)(R path)
|
|||
assert(stripExtension("file.ext1.ext2"d.byDchar).array == "file.ext1");
|
||||
}
|
||||
|
||||
private auto _stripExtension(R)(R path)
|
||||
{
|
||||
immutable i = extSeparatorPos(path);
|
||||
return i == -1 ? path : path[0 .. i];
|
||||
}
|
||||
|
||||
/** Sets or replaces an extension.
|
||||
|
||||
|
@ -1240,18 +1260,6 @@ if (isSomeChar!C1 && isSomeChar!C2)
|
|||
return _withExtension(path, ext);
|
||||
}
|
||||
|
||||
private auto _withExtension(R, C)(R path, C[] ext)
|
||||
{
|
||||
import std.range : only, chain;
|
||||
import std.utf : byUTF;
|
||||
|
||||
alias CR = Unqual!(ElementEncodingType!R);
|
||||
auto dot = only(CR('.'));
|
||||
if (ext.length == 0 || ext[0] == '.')
|
||||
dot.popFront(); // so dot is an empty range, too
|
||||
return chain(stripExtension(path).byUTF!CR, dot, ext.byUTF!CR);
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -1279,6 +1287,18 @@ private auto _withExtension(R, C)(R path, C[] ext)
|
|||
assert(equal(sa.withExtension(".txt"), "foo.txt"));
|
||||
}
|
||||
|
||||
private auto _withExtension(R, C)(R path, C[] ext)
|
||||
{
|
||||
import std.range : only, chain;
|
||||
import std.utf : byUTF;
|
||||
|
||||
alias CR = Unqual!(ElementEncodingType!R);
|
||||
auto dot = only(CR('.'));
|
||||
if (ext.length == 0 || ext[0] == '.')
|
||||
dot.popFront(); // so dot is an empty range, too
|
||||
return chain(stripExtension(path).byUTF!CR, dot, ext.byUTF!CR);
|
||||
}
|
||||
|
||||
/** Params:
|
||||
path = A path name.
|
||||
ext = The default extension to use.
|
||||
|
@ -1344,28 +1364,6 @@ if (isSomeChar!C1 && isSomeChar!C2)
|
|||
return _withDefaultExtension(path, ext);
|
||||
}
|
||||
|
||||
private auto _withDefaultExtension(R, C)(R path, C[] ext)
|
||||
{
|
||||
import std.range : only, chain;
|
||||
import std.utf : byUTF;
|
||||
|
||||
alias CR = Unqual!(ElementEncodingType!R);
|
||||
auto dot = only(CR('.'));
|
||||
immutable i = extSeparatorPos(path);
|
||||
if (i == -1)
|
||||
{
|
||||
if (ext.length > 0 && ext[0] == '.')
|
||||
ext = ext[1 .. $]; // remove any leading . from ext[]
|
||||
}
|
||||
else
|
||||
{
|
||||
// path already has an extension, so make these empty
|
||||
ext = ext[0 .. 0];
|
||||
dot.popFront();
|
||||
}
|
||||
return chain(path.byUTF!CR, dot, ext.byUTF!CR);
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -1395,6 +1393,28 @@ private auto _withDefaultExtension(R, C)(R path, C[] ext)
|
|||
assert(equal(sa.withDefaultExtension(".txt"), "foo.txt"));
|
||||
}
|
||||
|
||||
private auto _withDefaultExtension(R, C)(R path, C[] ext)
|
||||
{
|
||||
import std.range : only, chain;
|
||||
import std.utf : byUTF;
|
||||
|
||||
alias CR = Unqual!(ElementEncodingType!R);
|
||||
auto dot = only(CR('.'));
|
||||
immutable i = extSeparatorPos(path);
|
||||
if (i == -1)
|
||||
{
|
||||
if (ext.length > 0 && ext[0] == '.')
|
||||
ext = ext[1 .. $]; // remove any leading . from ext[]
|
||||
}
|
||||
else
|
||||
{
|
||||
// path already has an extension, so make these empty
|
||||
ext = ext[0 .. 0];
|
||||
dot.popFront();
|
||||
}
|
||||
return chain(path.byUTF!CR, dot, ext.byUTF!CR);
|
||||
}
|
||||
|
||||
/** Combines one or more path segments.
|
||||
|
||||
This function takes a set of path segments, given as an input
|
||||
|
@ -2532,35 +2552,17 @@ if (isConvertibleToString!R)
|
|||
|
||||
/** Determines whether a path starts at a root directory.
|
||||
|
||||
Params: path = A path name.
|
||||
Returns: Whether a path starts at a root directory.
|
||||
Params:
|
||||
path = A path name.
|
||||
Returns:
|
||||
Whether a path starts at a root directory.
|
||||
|
||||
On POSIX, this function returns true if and only if the path starts
|
||||
with a slash (/).
|
||||
---
|
||||
version (Posix)
|
||||
{
|
||||
assert(isRooted("/"));
|
||||
assert(isRooted("/foo"));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("../foo"));
|
||||
}
|
||||
---
|
||||
|
||||
On Windows, this function returns true if the path starts at
|
||||
the root directory of the current drive, of some other drive,
|
||||
or of a network drive.
|
||||
---
|
||||
version (Windows)
|
||||
{
|
||||
assert(isRooted(`\`));
|
||||
assert(isRooted(`\foo`));
|
||||
assert(isRooted(`d:\foo`));
|
||||
assert(isRooted(`\\foo\bar`));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("d:foo"));
|
||||
}
|
||||
---
|
||||
*/
|
||||
bool isRooted(R)(R path)
|
||||
if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
||||
|
@ -2571,6 +2573,27 @@ if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
|||
else version (Windows) return isAbsolute!(BaseOf!R)(path);
|
||||
}
|
||||
|
||||
///
|
||||
@safe unittest
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
assert( isRooted("/"));
|
||||
assert( isRooted("/foo"));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("../foo"));
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert( isRooted(`\`));
|
||||
assert( isRooted(`\foo`));
|
||||
assert( isRooted(`d:\foo`));
|
||||
assert( isRooted(`\\foo\bar`));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("d:foo"));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
|
@ -2596,9 +2619,6 @@ if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
|||
assert(!isRooted(DirEntry("foo")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Determines whether a path is absolute or not.
|
||||
|
||||
Params: path = A path name.
|
||||
|
@ -4076,6 +4096,21 @@ string expandTilde(string inputPath) nothrow
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
@system unittest
|
||||
{
|
||||
version (Posix)
|
||||
{
|
||||
import std.process : environment;
|
||||
|
||||
auto oldHome = environment["HOME"];
|
||||
scope(exit) environment["HOME"] = oldHome;
|
||||
|
||||
environment["HOME"] = "dmd/test";
|
||||
assert(expandTilde("~/") == "dmd/test/");
|
||||
assert(expandTilde("~") == "dmd/test");
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue