mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 14:10:30 +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.net.isemail,\
|
||||||
-std.numeric,\
|
-std.numeric,\
|
||||||
-std.parallelism,\
|
-std.parallelism,\
|
||||||
-std.path,\
|
|
||||||
-std.process,\
|
-std.process,\
|
||||||
-std.range.interfaces,\
|
-std.range.interfaces,\
|
||||||
-std.regex,\
|
-std.regex,\
|
||||||
|
|
447
std/path.d
447
std/path.d
|
@ -151,6 +151,21 @@ bool isDirSeparator(dchar c) @safe pure nothrow @nogc
|
||||||
return false;
|
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.
|
/* Determines whether the given character is a drive separator.
|
||||||
|
|
||||||
|
@ -333,14 +348,24 @@ enum CaseSensitive : bool
|
||||||
*/
|
*/
|
||||||
osDefault = osDefaultCaseSensitivity
|
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;
|
version (Windows) private enum osDefaultCaseSensitivity = false;
|
||||||
else version (OSX) private enum osDefaultCaseSensitivity = false;
|
else version (OSX) private enum osDefaultCaseSensitivity = false;
|
||||||
else version (Posix) private enum osDefaultCaseSensitivity = true;
|
else version (Posix) private enum osDefaultCaseSensitivity = true;
|
||||||
else static assert(0);
|
else static assert(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Params:
|
Params:
|
||||||
cs = Whether or not suffix matching is case-sensitive.
|
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
|
the comparison is case sensitive or not. See the
|
||||||
$(LREF filenameCmp) documentation for details.
|
$(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:
|
Note:
|
||||||
This function $(I only) strips away the specified suffix, which
|
This function $(I only) strips away the specified suffix, which
|
||||||
doesn't necessarily have to represent an extension.
|
doesn't necessarily have to represent an extension.
|
||||||
|
@ -401,26 +411,6 @@ if (isSomeChar!C)
|
||||||
return _baseName(path);
|
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
|
/// ditto
|
||||||
inout(C)[] baseName(CaseSensitive cs = CaseSensitive.osDefault, C, C1)
|
inout(C)[] baseName(CaseSensitive cs = CaseSensitive.osDefault, C, C1)
|
||||||
(inout(C)[] path, in C1[] suffix)
|
(inout(C)[] path, in C1[] suffix)
|
||||||
|
@ -436,6 +426,22 @@ if (isSomeChar!C && isSomeChar!C1)
|
||||||
else return p;
|
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
|
@safe unittest
|
||||||
{
|
{
|
||||||
assert(baseName("").empty);
|
assert(baseName("").empty);
|
||||||
|
@ -508,6 +514,26 @@ if (isSomeChar!C && isSomeChar!C1)
|
||||||
assert(sa.baseName == "test");
|
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
|
/** Returns the parent directory of path. On Windows, this
|
||||||
includes the drive letter if present.
|
includes the drive letter if present.
|
||||||
|
|
||||||
|
@ -536,52 +562,6 @@ if (isSomeChar!C)
|
||||||
return _dirName(path);
|
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
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -673,8 +653,51 @@ private auto _dirName(R)(R path)
|
||||||
//static assert(dirName("dir/file".byChar).array == "dir");
|
//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
|
/** Returns the root directory of the specified path, or `null` if the
|
||||||
path is not rooted.
|
path is not rooted.
|
||||||
|
@ -698,38 +721,6 @@ if (isSomeChar!C)
|
||||||
return _rootName(path);
|
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
|
@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.
|
Get the drive portion of a path.
|
||||||
|
@ -804,21 +826,6 @@ if (isSomeChar!C)
|
||||||
return _driveName(path);
|
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
|
@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
|
/** Strips the drive from a Windows path. On POSIX, the path is returned
|
||||||
unaltered.
|
unaltered.
|
||||||
|
@ -896,16 +917,6 @@ if (isSomeChar!C)
|
||||||
return _stripDrive(path);
|
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
|
@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
|
/* Helper function that returns the position of the filename/extension
|
||||||
separator dot in path.
|
separator dot in path.
|
||||||
|
@ -1085,12 +1106,6 @@ if (isSomeChar!C)
|
||||||
return _stripExtension(path);
|
return _stripExtension(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private auto _stripExtension(R)(R path)
|
|
||||||
{
|
|
||||||
immutable i = extSeparatorPos(path);
|
|
||||||
return i == -1 ? path : path[0 .. i];
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -1127,6 +1142,11 @@ private auto _stripExtension(R)(R path)
|
||||||
assert(stripExtension("file.ext1.ext2"d.byDchar).array == "file.ext1");
|
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.
|
/** Sets or replaces an extension.
|
||||||
|
|
||||||
|
@ -1240,18 +1260,6 @@ if (isSomeChar!C1 && isSomeChar!C2)
|
||||||
return _withExtension(path, ext);
|
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
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -1279,6 +1287,18 @@ private auto _withExtension(R, C)(R path, C[] ext)
|
||||||
assert(equal(sa.withExtension(".txt"), "foo.txt"));
|
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:
|
/** Params:
|
||||||
path = A path name.
|
path = A path name.
|
||||||
ext = The default extension to use.
|
ext = The default extension to use.
|
||||||
|
@ -1344,28 +1364,6 @@ if (isSomeChar!C1 && isSomeChar!C2)
|
||||||
return _withDefaultExtension(path, ext);
|
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
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -1395,6 +1393,28 @@ private auto _withDefaultExtension(R, C)(R path, C[] ext)
|
||||||
assert(equal(sa.withDefaultExtension(".txt"), "foo.txt"));
|
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.
|
/** Combines one or more path segments.
|
||||||
|
|
||||||
This function takes a set of path segments, given as an input
|
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.
|
/** Determines whether a path starts at a root directory.
|
||||||
|
|
||||||
Params: path = A path name.
|
Params:
|
||||||
Returns: Whether a path starts at a root directory.
|
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
|
On POSIX, this function returns true if and only if the path starts
|
||||||
with a slash (/).
|
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
|
On Windows, this function returns true if the path starts at
|
||||||
the root directory of the current drive, of some other drive,
|
the root directory of the current drive, of some other drive,
|
||||||
or of a network 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)
|
bool isRooted(R)(R path)
|
||||||
if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
||||||
|
@ -2571,6 +2573,27 @@ if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
||||||
else version (Windows) return isAbsolute!(BaseOf!R)(path);
|
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
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -2596,9 +2619,6 @@ if (isRandomAccessRange!R && isSomeChar!(ElementType!R) ||
|
||||||
assert(!isRooted(DirEntry("foo")));
|
assert(!isRooted(DirEntry("foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Determines whether a path is absolute or not.
|
/** Determines whether a path is absolute or not.
|
||||||
|
|
||||||
Params: path = A path name.
|
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
|
@system unittest
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue