Files
filesystem/doc/path.htm
2003-12-09 18:10:50 +00:00

920 lines
42 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Boost Filesystem path.hpp Header</title>
</head>
<body bgcolor="#FFFFFF">
<h1>
<img border="0" src="../../../c++boost.gif" align="center" width="277" height="86"><a href="../../../boost/filesystem/path.hpp">boost/filesystem/path.hpp</a></h1>
<p>
<a href="#Introduction">Introduction</a><br>
<a href="#Grammar">Grammar for generic path strings</a><br>
<a href="#Canonical">Canonical form</a><br>
<a href="#synopsis">Header synopsis</a><br>
<a href="#Class_path">Class path</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Native_path_representation">Native path
representation</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Representation_example">Representation example</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Caution_POSIX">Caution for POSIX and UNIX
programmers</a><br>
&nbsp;&nbsp;&nbsp; <a href="#relative_paths_good">Good programming practice:
relative paths</a><br>
<a href="#Member">Member functions</a><br>
<a href="#Non-member_functions">Non-member functions</a><br>
<a href="#name_check_mechanism">Default name_check mechansim</a><br>
<a href="#Rationale">Rationale</a><br>
<a href="#decomposition">Path decomposition examples</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>Filesystem Library functions traffic in objects of class <i>path</i>,
provided by this header.&nbsp;The header also supplies non-member functions for error checking.</p>
<p>For actual operations on files and directories, see <a href="operations.htm">
boost/filesystem/operations.hpp documentation</a>.</p>
<p>For file I/O stream operations, see <a href="fstream.htm">boost/filesystem/fstream.hpp
documentation</a>.</p>
<p>The Filesystem Library's <a href="index.htm#Common_Specifications">Common
Specifications</a> apply to all member and non-member functions supplied by this
header.</p>
<p>The <a href="portability_guide.htm">Portability Guide</a> discusses path
naming issues which are important when portability is a concern.</p>
<h2><a name="Class_path">Class path</a></h2>
<p>Class <i>path</i> provides for portable mechanism for representing
<a href="index.htm#path">paths</a> in C++ programs, using a portable generic
path string <a href="#Grammar">grammar</a>.&nbsp;Class <i>path</i>
is concerned with the lexical and syntactic aspects of a path. The path does not
have to exist in the operating system's
filesystem, and may contain names which are not even valid for the current
operating system. </p>
<p><b>Rationale:</b> If Filesystem functions trafficked in <i>std::strings</i> or C-style strings, the
functions
would provide only an illusion of portability since the function calls would be
portable but the strings they operate on would not be portable.</p>
<h2>Conceptual <a name="model">model</a> of a path</h2>
<p>An object of class <i>path</i> can be conceptualized as containing a sequence
of strings. Each string is said to be an element of the path. Each element
represents the name of a directory, or, in the case
of the string representing the element farthest from the root in the directory
hierarchy, the name of a directory or file. The names <code>&quot;..&quot;</code> and
<code>&quot;.&quot;</code> are reserved to represent the concepts of <i>parent-directory</i>
and <i>directory-placeholder</i>.</p>
<p>This conceptual path representation is
independent of any particular representation of the path as a single
string.</p>
<p>There is no requirement that an implementation of class <i>path</i> actually
contain a sequence of strings, but conceptualizing the contents as a sequence of
strings provides
a completely portable way to reason about paths.</p>
<p>So that programs can portably express paths as a single string, class <i>path</i>
defines a <a href="#Grammar">grammar</a> for a portable generic path string
format, and supplies constructor and append operations taking such strings as
arguments. Because user input or third-party library functions may supply path
strings formatted according to operating system specific rules, an additional
constructor is provided which takes a system-specific format as an argument.</p>
<p>Access functions are provided to retrieve the contents of a object of class
<i>path</i> formatted as a portable path string, a directory path string using
the operating system's format, and a file path string using the operating
system's format.&nbsp; Additional access functions retrieve specific portions of
the contained path.</p>
<h2><a name="Grammar">Grammar</a> for portable generic path strings</h2>
<p>The grammar is specified in extended BNF, with terminal symbols in quotes:
</p>
<blockquote>
<pre>path ::= [root] [relative-path] // an empty path is valid</pre>
<pre>root ::= [root-name] [root-directory]</pre>
<pre>root-directory ::= &quot;/&quot;</pre>
<pre>relative-path ::= path-element { &quot;/&quot; path-element } [&quot;/&quot;]</pre>
<pre>path-element ::= name | parent-directory | directory-placeholder</pre>
<pre>name ::= char { char }</pre>
<pre>directory-placeholder ::= &quot;.&quot;</pre>
<pre>parent-directory ::= &quot;..&quot; </pre>
</blockquote>
<p><i>root-name</i> grammar is implementation-defined. <i>
root-name</i> must not be present in generic input. It may be part of the strings returned by <i>path</i>
member functions, and may be present in the <i>src</i> argument to <i>path</i> constructors
when the <i><a href="#native">native</a></i> name check is in effect.</p>
<p><i>char</i> may not be slash ('/') or '\0'.</p>
<p>Although implementation-defined, it is desirable that <i>
root-name</i> have a grammar which is distinguishable from other grammar elements,
and follow the conventions of the operating system.</p>
<p>The optional trailing &quot;/&quot; in a <i>relative-path</i> is allowed as a
notational convenience. It has no semantic meaning and is simply discarded.</p>
<p>Whether or not a generic path string is actually portable to a particular
operating system will depend on the
names used.&nbsp; See the <a href="portability_guide.htm">Portability Guide</a>.</p>
<h2><a name="Canonical">Canonical</a> form</h2>
<p>All operations modifying <i>path</i> objects leave the <i>path</i> object in
canonical form.</p>
<p>An empty path is in canonical form.</p>
<p>A non-empty path is converted to canonical form as if by first converting it
to the <a href="#model">conceptual model</a>, and then:</p>
<ul>
<li>Repeatedly replacing any leading <i>root-directory, parent-directory</i>
elements with a single <i>root-directory</i> element. Rationale: Both POSIX
and Windows specify this reduction; specifying it for canonical form ensures
portable semantics for other operating systems.</li>
<li>Removing each <i>directory-placeholder</i> element.</li>
<li>If the path is now empty, add a single <i>directory-placeholder</i>
element.</li>
</ul>
<h2><a name="Normalized">Normalized</a> form</h2>
<p>Normalized form is the same as canonical form, except that adjacent <i>name, parent-directory</i>
elements are recursively removed.</p>
<p>Thus a non-empty path in normal form either has no <i>
directory-placeholders</i>, or consists solely of one <i>directory-placeholder</i>.
If it has <i>parent-directory</i> elements, they precede all <i>name</i>
elements.</p>
<h2>Header <a href="../../../boost/filesystem/path.hpp">
boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
<pre>namespace boost
{
namespace filesystem
{
class path
{
public:
<a name="name_check_typedef">typedef</a> bool (*name_check)( const std::string &amp; name );
// compiler generates copy constructor,
// copy assignment, and destructor
// constructors:
<a href="#constructors">path</a>();
<a href="#constructors">path</a>( const std::string &amp; src );
<a href="#constructors">path</a>( const char * src );
<a href="#constructors">path</a>( const std::string &amp; src, name_check checker );
<a href="#constructors">path</a>( const char * src, name_check checker );
// append operations:
path &amp; <a href="#operator_slash_equal">operator /=</a> ( const path &amp; rhs );
path <a href="#operator_slash">operator /</a> ( const path &amp; rhs ) const;
// conversion functions:
const std::string & <a href="#string">string</a>() const;
std::string <a href="#native_file_string">native_file_string</a>() const;
std::string <a href="#native_directory_string">native_directory_string</a>() const;
// modification functions:
path &amp; <a href="#normalize">normalize</a>();
// decomposition functions:
path <a href="#root_path">root_path</a>() const;
std::string <a href="#root_name">root_name</a>() const;
std::string <a href="#root_directory">root_directory</a>() const;
path <a href="#relative_path">relative_path</a>() const;
std::string <a href="#leaf">leaf</a>() const;
path <a href="#branch_path">branch_path</a>() const;
// query functions:
bool <a href="#empty">empty</a>() const;
bool <a href="#is_complete">is_complete</a>() const;
bool <a href="#has_root_path">has_root_path</a>() const;
bool <a href="#has_root_name">has_root_name</a>() const;
bool <a href="#has_root_directory">has_root_directory</a>() const;
bool <a href="#has_relative_path">has_relative_path</a>() const;
bool <a href="#has_leaf">has_leaf</a>() const;
bool <a href="#has_branch_path">has_branch_path</a>() const;
// iteration:
typedef <i>implementation-defined</i> <a href="#iterator">iterator</a>;
iterator <a href="#begin">begin</a>() const;
iterator <a href="#end">end</a>() const;
// <a href="#name_check­_mechanism">default name_check</a> mechanism:
static bool <a href="#default_name_check_writable">default_name_check_writable</a>();
static name_check <a href="#default_name_check">default_name_check</a>( name_check new_check );
static name_check <a href="#default_name_check">default_name_check</a>();
private:
std::vector&lt;std::string&gt; m_name; // for exposition only
};
path <a href="#non-member_operator_shift">operator /</a> ( const char * lhs, const path &amp; rhs );
path <a href="#non-member_operator_shift">operator /</a> ( const std::string &amp; lhs, const path &amp; rhs );
// <a href="portability_guide.htm#name_check­_functions">name_check functions</a>
bool <a href="portability_guide.htm#portable_posix_name">portable_posix_name</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#windows_name">windows_name</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#portable_name">portable_name</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#portable_directory_name">portable_directory_name</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#portable_file_name">portable_file_name</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#no_check">no_check</a>( const std::string &amp; name );
bool <a href="portability_guide.htm#native">native</a>( const std::string &amp; name );
}
}</pre>
<p>For the sake of exposition, class <i>path</i> member functions are described
as if the class contains a private member <i>std::vector&lt;std::string&gt; m_name</i>.
Actual implementations may differ.</p>
<p>Class path member, or non-member operator/, functions may throw a
<a href="exception.htm">filesystem_error</a> exception if the path is not in the
syntax specified for the <a href="#Grammar">grammar</a>.</p>
<p><b>Note:</b> There is no guarantee that a <i>path</i> object represents a
path which is considered valid by the current operating system. A path might be
invalid to the operating system because it contains invalid names (too long,
invalid characters, and so on), or because it is a partial path still as yet
unfinished by the program. An invalid path will normally be detected at time of
use, such as by one of the Filesystem Library's <a href="operations.htm">
operations</a> or <a href="fstream.htm">fstream</a> functions.</p>
<p><b>Portability Warning:</b> There is no guarantee that a <i>path</i> object
represents a path which would be portable to another operating system. A path
might be non-portable because it contains names which the operating systems
considers too long or contains invalid characters. A
<a href="#name_check­_mechanism">default name_check mechanism</a> is provided to
aid in the detection of non-portable names, or a name_check function can be
specified in <i>path</i> constructors. The library supplies several
<a href="portability_guide.htm#name_check­_functions">name_check
functions</a>, or users can supply their own.</p>
<h3><a name="Native_path_representation">Native path representation</a></h3>
<p>Several <i>path</i> member functions return representations of <i>m_name</i>
in formats specific to the operating system. These formats are implementation
defined. If an <i>m_name</i>
element contains characters which are invalid under the operating system's
rules, and there is an unambiguous translation between the invalid character and
a valid character, the implementation is required to perform that translation.
For example, if an operating system does not permit lowercase letters in file or
directory names, these letters will be translated to uppercase if unambiguous.
Such translation does not apply to generic path string format representations.</p>
<h3><a name="Representation_example">Representation example</a></h3>
<p>The rule-of-thumb is to use <i>string()</i> when a generic string representation of
the path is required, and use either
<i>native_directory_string()</i> or
<i>native_file_string()</i> when a string representation formatted for
the particular operating system is required.</p>
<p>The difference between the representations returned by <i>string()</i>,
<i>native_directory_string()</i>, and
<i>native_file_string()</i> are illustrated by the following
code:</p>
<blockquote>
<pre>path my_path( &quot;foo/bar/data.txt&quot; );
std::cout
&lt;&lt; &quot;string------------------: &quot; &lt;&lt; my_path.string() &lt;&lt; '\n'
&lt;&lt; &quot;native_directory_string-: &quot; &lt;&lt; my_path.native_directory_string() &lt;&lt; '\n'
&lt;&lt; &quot;native_file_string------: &quot; &lt;&lt; my_path.native_file_string() &lt;&lt; '\n';</pre>
</blockquote>
<p>On POSIX systems, the output would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
native_directory_string-: foo/bar/data.txt
native_file_string------: foo/bar/data.txt</pre>
</blockquote>
<p>On Windows, the output would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
native_directory_string-: foo\bar\data.txt
native_file_string------: foo\bar\data.txt</pre>
</blockquote>
<p>On classic Mac OS, the output would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
native_directory_string-: foo:bar:data.txt
native_file_string------: foo:bar:data.txt</pre>
</blockquote>
<p>On a hypothetical operating system using OpenVMS format representations, it would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
native_directory_string-: [foo.bar.data.txt]
native_file_string------: [foo.bar]data.txt</pre>
</blockquote>
<p>Note that that because OpenVMS uses period as both a directory separator
character and as a separator between filename and extension, <i>
native_directory_string()</i>
in the example produces a useless result. On this operating system, the
programmer should only use this path as a file path. (There is a
<a href="portability_guide.htm#recommendations">portability recommendation</a>
to not use periods in directory names.)</p>
<h3><a name="Caution_POSIX">Caution</a> for POSIX and UNIX programmers</h3>
<p>POSIX and other UNIX-like operating systems have a single root, while most other
operating systems have multiple roots. Multi-root operating systems require a
root-name
such as a drive, device, disk, volume, or share name for a path to be resolved
to an actual specific file or directory.&nbsp;
Because of this, the <i>root()</i> and <i>root_directory()</i> functions return
identical results on UNIX and other single-root operating systems, but different
results on multi-root operating systems. Thus use of the wrong function will not be
apparent on UNIX-like systems, but will result in non-portable code which will
fail when used on multi-root systems. UNIX programmers are cautioned to use
particular care in choosing between <i>root()</i> and <i>root_directory()</i>. If
undecided, use <i>root()</i>.</p>
<p>The same warning applies to <i>has_root()</i> and <i>has_root_directory()</i>.</p>
<h3><a name="relative_paths_good">Good programming practice: relative paths</a></h3>
<p>It is usually bad programming practice to hard-code <a href="#is_complete">
complete paths</a> into programs. Such programs tend to be fragile because they
break when directory trees get reorganized or the programs are moved to other
machines or operating systems.</p>
<p>The most robust way to deal with path completion is to hard-code only
relative paths. When a complete path is required, it can be obtained in several
ways:</p>
<ul>
<li><b>Implicitly</b>. Allow the operating system to complete the path
according to the operating system's path completion algorithm. For example:<pre> create_directory( &quot;foo&quot; ); // operating system will complete path</pre>
</li>
<li><b>User input</b>. The path is often best <a href="#constructors">
constructed</a> with the <i>native</i> name check, so that the user input
follows the operating system's native path format, which will usually be what
the program user expects. For example:<pre> path foo( argv[1], native );
foo /= &quot;foo&quot;;</pre>
</li>
<li><b><a href="operations.htm#initial_path">initial_path()</a></b>.
Particularly for command line programs, specifying paths relative to the
current path at the time the program is started is a common practice. For
example:<pre> path foo( initial_path() / &quot;foo&quot; );</pre>
</li>
<li><b>Algorithmically</b>. See <a href="operations.htm#complete">complete()</a>
and <a href="operations.htm#system_complete">system_complete()</a> functions.</li>
</ul>
<h2><a name="Member">Member</a> functions</h2>
<h3><a name="constructors">constructors</a></h3>
<blockquote>
<pre>path();</pre>
<p><b>Effects:</b> Default constructs an object of class <i>path</i>.</p>
<p><b>Postcondition:</b> path().empty()</p>
<pre>path( const std::string &amp; src, name_check checker );
path( const char * src, name_check checker );
path( const std::string &amp; src );
path( const char * src );</pre>
<p>For the single-argument forms, <code>default_name_check()</code> is used as
<code>checker</code>. </p>
<p><b>Precondition:</b> <code>src != 0</code>.</p>
<p><b>Effects:</b> Select the grammar as follows:</p>
<ul>
<li>If <code>checker == native</code>, the operating system's implementation
defined grammar for paths.</li>
<li>else if <code>checker == no_check</code>, the <a href="#Grammar">generic
path string grammar</a> with optional <i>
root-name</i>.</li>
<li>else the <a href="#Grammar">generic
path string grammar</a> without <i>
root-name</i>.</li>
</ul>
<p>Parse src into a sequence of names, according to the grammar, then, for each name in <code>src</code>,&nbsp; <code>m_name.push_back(
name )</code>.</p>
<p><b>Throws:</b> For each name in <code>src</code>, throw if <code>checker(
name )</code> returns
false.</p>
<p><b>Postcondition:</b> <code>m_name</code> is in
<a href="#Canonical">canonical form</a>. For the single-argument forms only, <code>!default_name_check_writable()</code>.</p>
<p><b>Rationale:</b> The single-argument constructors are not <code>explicit</code> because an intended
use is automatic conversion of strings to paths.</p>
</blockquote>
<h3><a name="operator_slash_equal">operator /=</a></h3>
<blockquote>
<pre>path &amp; operator/=( const path &amp; rhs );</pre>
<p><b>Effects:</b> If any of the following conditions are met, then
m_name.push_back(&quot;/&quot;).</p>
<ul>
<li>has_relative_path().</li>
<li>!is_absolute() &amp;&amp; has_root_name(), and the operating system
requires the system-specific root be absolute</li>
</ul>
<p>&nbsp;Then append <code>rhs.m_name</code> to <code>m_name</code>.</p>
<p>(Footnote: Thus on Windows, (path(&quot;//share&quot;) /= &quot;foo&quot;).string() is
&quot;//share/foo&quot;)</p>
<p><b>Returns:</b> <code>*this</code></p>
<p><b>Postcondition:</b> <code>m_name</code> is in
<a href="#Canonical">canonical form</a>.</p>
<p><b>Rationale:</b> It is not considered an error for <code>rhs</code> to
include a <code>root-directory</code> because <code>m_name</code> might be relative
or empty, and
thus it is valid for rhs to supply <code>root-directory</code>.&nbsp; For example, on Windows, the following must succeed:</p>
<blockquote>
<pre>path p( &quot;c:&quot;, native );
p /= &quot;/foo&quot;;
assert( p.string() == &quot;c:/foo&quot; );</pre>
</blockquote>
</blockquote>
<h3><a name="operator_slash">operator /</a></h3>
<blockquote>
<pre>const path operator/ ( const path &amp; rhs ) const;</pre>
<p><b>Returns:</b> <code>path( *this ) /= rhs</code></p>
<p><b>Rationale:</b> Operator / is supplied because together with operator /=,
it provides a
convenient way for users to supply paths with a variable number of elements.&nbsp;
For example, <code>initial_path() / &quot;src&quot; / test_name</code>.
Operator+ and operator+= were considered as alternatives, but deemed too
easy to confuse with those operators for std::string. Operator&lt;&lt; and
operator=&lt;&lt; were used originally until during public review Dave
Abrahams pointed out that / and /=
match the generic path syntax.</p>
<p><b>Note:</b> Also see <a href="#non-member_operator_shift">non-member <i>
operator/</i></a> functions.</p>
</blockquote>
<h3><a name="normalize">normalize</a></h3>
<blockquote>
<p><code>path &amp; normalize();</code></p>
<p><b>Postcondition:</b> m_name is in <a href="#Normalized">normalized form</a>.</p>
<p><b>Returns:</b> <code>*this</code></p>
</blockquote>
<h3><a name="string">string</a></h3>
<blockquote>
<pre>const std::string &amp; string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted according to
the rules of the <a href="#Grammar">generic path string grammar</a>.</p>
<p><b>Note:</b> The returned string must be unambiguous
according to the grammar. That means that for an operating system with root-names indistinguishable from
relative-path names, names containing &quot;/&quot;, or allowing &quot;.&quot; or &quot;..&quot; as
directory or file names, escapes or other mechanisms will have to be introduced
into the grammar to prevent ambiguities. This has not been done yet, since no
current implementations are on operating systems with any of those problems.</p>
<p><b>See:</b> <a href="#Representation_example">Representation example</a>
above.</p>
</blockquote>
<h3><a name="native_file_string">native_file_string</a></h3>
<blockquote>
<pre>std::string native_file_string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
<a href="#System-specific_Representation">system-specific representation</a> of
a file path.</p>
<p><b>See:</b> <a href="#Representation_example">Representation example</a>
above.</p>
<p><b>Naming rationale</b>: The name is deliberately ugly to warn users that
this function yields non-portable results.</p>
</blockquote>
<h3><a name="native_directory_string">native_directory_string</a></h3>
<blockquote>
<pre>const std::string native_directory_string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
<a href="#System-specific_Representation">system-specific representation</a> of
a directory path.</p>
<p><b>See:</b> <a href="#Representation_example">Representation example</a>
above.</p>
<p><b>Naming rationale</b>: The name is deliberately ugly to warn users that
this function yields non-portable results.</p>
</blockquote>
<h3><a name="root_path">root_path</a></h3>
<blockquote>
<pre>path root_path() const;</pre>
<p><b>Returns:</b> <code>root_name() / root_directory()</code></p>
<p>Portably provides a copy of a path's full root path, if any. See
<a href="#decomposition">Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="root_name">root_name</a></h3>
<blockquote>
<pre>std::string root_name() const;</pre>
<p><b>Returns:</b> If <code>!m_name.empty() &amp;&amp; m_name[0]</code> is a
<a href="#Grammar">root-name</a>, returns m_name[0], else returns a
null string.</p>
<p>Portably provides a copy of a path's <a href="#Grammar">root-name</a>,
if any. See <a href="#decomposition">Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="root_directory">root_directory</a></h3>
<blockquote>
<pre>std::string root_directory() const;</pre>
<p><b>Returns:</b> If the path contains <a href="#Grammar">root-directory</a>,
then <code>string(&quot;/&quot;)</code>, else <code>string()</code>.</p>
<p>Portably provides a copy of a path's <a href="#Grammar">root-directory</a>,
if any. The only possible results are &quot;/&quot; or &quot;&quot;. See <a href="#decomposition">
Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="relative_path">relative_path</a></h3>
<blockquote>
<pre>path relative_path() const;</pre>
<p><b>Returns:</b> A new path containing only the <a href="#Grammar">
relative-path</a> portion of the source path.</p>
<p>Portably provides a copy of a path's relative portion, if any. See
<a href="#decomposition">Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="leaf">leaf</a></h3>
<blockquote>
<pre>std::string leaf() const;</pre>
<p><b>Returns:</b> <code>empty() ? std::string() : m_name.back()</code></p>
<p>A typical use is to obtain a file or directory name without path information
from a path returned by a <a href="operations.htm#directory_iterator">
directory_iterator</a>. See <a href="#decomposition">Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="branch_path">branch_path</a></h3>
<blockquote>
<pre>path branch_path() const;</pre>
<p><b>Returns:</b> <code>m_name.size() &lt;= 1 ? path(&quot;&quot;) : x</code>, where <code>x</code>
is a path constructed from all the elements of <code>m_name</code> except the
last.</p>
<p>A typical use is to obtain the parent path for a path supplied by the user.
See <a href="#decomposition">Path decomposition examples</a>.</p>
</blockquote>
<h3><a name="empty">empty</a></h3>
<blockquote>
<pre>bool empty() const;</pre>
<p><b>Returns:</b> <code>string().empty()</code>.</p>
<p>The <i>path::empty()</i> function determines if a path string itself is
empty. To determine if the file or directory identified by the path is empty,
use the <a href="operations.htm#is_empty">operations.hpp is_empty()</a>
function.</p>
<p><b>Naming rationale:</b> C++ Standard Library containers use the <i>empty</i>
name for the equivalent functions.</p>
</blockquote>
<h3><a name="is_complete">is_complete</a></h3>
<blockquote>
<pre>bool is_complete() const;</pre>
<p><b>Returns:</b> For single-root operating systems, <code>has_root_directory()</code>.
For multi-root operating systems, <code>has_root_directory() &amp;&amp;
has_root_name()</code>.</p>
<p><b>Naming rationale:</b> The alternate name, is_absolute(), causes
confusion and controversy because on multi-root operating systems some people
believe root_name() should participate in is_absolute(), and some
don't. See the <a href="faq.htm#absolute">FAQ</a>.</p>
<p><b><a name="is_complete_note">Note</a>:</b> On most operating systems, a
complete path always unambiguously identifies a specific file or directory. On a few
systems (classic Mac OS, for example), even a complete path may be ambiguous
in unusual cases because the OS does not require unambiguousness.</p>
</blockquote>
<h3><a name="has_root_path">has_root_path</a></h3>
<blockquote>
<pre>bool has_root_path() const;</pre>
<p><b>Returns:</b> <code>has_root_name() || has_root_directory()</code></p>
</blockquote>
<h3><a name="has_root_name">has_root_name</a></h3>
<blockquote>
<pre>bool has_root_name() const;</pre>
<p><b>Returns:</b> <code>!root_name().empty()</code></p>
</blockquote>
<h3><a name="has_root_directory">has_root_directory</a></h3>
<blockquote>
<pre>bool has_root_directory() const;</pre>
<p><b>Returns:</b> <code>!root_directory().empty()</code></p>
</blockquote>
<h3><a name="has_relative_path">has_relative_path</a></h3>
<blockquote>
<pre>bool has_relative_path() const;</pre>
<p><b>Returns:</b> <code>!relative_path().empty()</code></p>
</blockquote>
<h3><a name="has_leaf">has_leaf</a></h3>
<blockquote>
<pre>bool has_leaf() const;</pre>
<p><b>Returns:</b> <code>!leaf().empty()</code></p>
</blockquote>
<h3><a name="has_branch_path">has_branch_path</a></h3>
<blockquote>
<pre>bool has_branch_path() const;</pre>
<p><b>Returns:</b> <code>!branch_path().empty()</code></p>
</blockquote>
<h3><a name="iterator">iterator</a></h3>
<blockquote>
<p><code>typedef <i>implementation-defined</i> iterator;</code></p>
<p>A const iterator meeting the C++ Standard Library requirements for bidirectional
iterators (24.1). The iterator is a class type (so that operator++ and -- will
work on temporaries). The value, reference, and pointer types are <i>std::string</i>,
<i>const std::string &amp;</i>, and <i>const std::string *</i>, respectively.</p>
</blockquote>
<h3><a name="begin">begin</a></h3>
<blockquote>
<p><code>iterator begin() const;</code></p>
<p><b>Returns:</b> <code>m_path.begin()</code></p>
</blockquote>
<h3><a name="end">end</a></h3>
<blockquote>
<p><code>iterator end() const;</code></p>
<p><b>Returns:</b> <code>m_path.end()</code></p>
</blockquote>
<h3><a name="default_name_check_writable">default_name_check_writable</a></h3>
<blockquote>
<p><code>static bool default_name_check_writable();</code></p>
<p><b>Returns:</b> True, unless a <i>default_name_check</i> function has been
previously called. </p>
</blockquote>
<h3><a name="default_name_check">default_name_check</a></h3>
<blockquote>
<p><code>static void default_name_check( name_check new_check );</code></p>
<p><b>Precondition:</b> new_check != 0</p>
<p><b>Postcondition:</b> <code>default_name_check(new_check) &amp;&amp; !default_name_check_writable()</code></p>
<p><b>Throws:</b> if <code>!default_name_check_writable()</code></p>
<p><code>static name_check default_name_check();</code></p>
<p><b>Returns:</b> the default name_check.</p>
<p><b>Postcondition:</b> <code>!default_name_check_writable()</code></p>
</blockquote>
<h2><a name="Non-member_functions">Non-member functions</a></h2>
<h3><a name="non-member_operator_shift">Non-member operator /</a></h3>
<blockquote>
<p><code>path operator / ( const char * lhs, const path &amp; rhs );<br>
path operator / ( const std::string &amp; lhs, const path &amp; rhs );</code></p>
<p><b>Returns:</b> <code>path( lhs ) /= rhs</code></p>
</blockquote>
<h2>Default <a name="name_check­_mechanism">name_check mechanism</a></h2>
<p>It is difficult or impossible to write portable programs without some way to
verify that directory and file names are portable. Without automatic name
checking, verification is tedious, error prone, and ugly. Yet no single name
check function can serve all applications, and within an application
different paths or portions of paths may require different name check
functions. Sometimes there should be no checking at all.</p>
<p>Those needs are met by providing a default name check function to meet an
application's most common needs, and then providing <i>path</i> constructors
which override the default name check function to handle less common needs.
The default name check function can be set by the application, allowing the
most common case for the particular application to be handled by the default
check. </p>
<h3>Dangers</h3>
<p>The default name check function is set and retrieved by <i>path</i> static
member functions, and as such is similar to a global variable. Since global variables are
considered harmful [<a href="design.htm#Wulf-Shaw-73">Wulf-Shaw-73</a>], class
<i>path</i> allows the default name check function can be set only once, and
only before the first use. This turns a dangerous global variable into a
safer global constant. Even with this protection, the ability to set the default name check function is
still a powerful feature, and is still dangerous in that it can change
the behavior of code buried out-of-sight in libraries or elsewhere. Thus
changing the default error check function should only be done when explicitly
specifying the function via the two argument <i>path</i> constructors is not
reasonable.</p>
<h2><a name="Rationale">Rationale</a></h2>
<p>Also see the <a href="faq.htm">FAQ</a> for additional rationale.</p>
<p><b>Function <a name="Naming_Rationale">naming</a>:</b> Class <i>path</i>
member function names and <a href="operations.htm">operations.hpp</a> non-member
function names were chosen to be somewhat distinct from one another. The
objective was to avoid cases like <i>foo.empty()</i> and <i>empty( foo )</i> both being
valid, but with completely different semantics. At one point <i>path::empty()</i>
was renamed <i>path::is_null()</i>, but that caused many coding typos because <i>
std::string::empty()</i> is often used nearby.</p>
<p><b>Decomposition functions:</b> Decomposition functions are provided because without them it is impossible to write portable path
manipulations. Convenience is also a factor.</p>
<p><b>Const vs non-const returns:</b> In some earlier versions of the library,
member functions returned values as const rather than non-const.
See Scott Myers, <i>Effective C++</i>, Item 21. The const qualifiers were
eliminated (1) to conform with C++ Standard Library practice, (2) because
non-const returns allow occasionally useful expressions, and (3) because the
number of coding errors eliminated were deemed rare. A requirement that path::iterator not be a non-class type was added to eliminate errors non-const
iterator errors.</p>
<h2>Path <a name="decomposition">decomposition</a> examples</h2>
<p>It is often useful to extract specific elements from a path object.&nbsp;
While any decomposition can be achieved by iterating over the elements of a
path, convenience functions are provided which are easier to use, more
efficient, and less error prone.</p>
<p>The first column of the table gives the example path, formatted by the
string() function. The second column shows the values which would be returned by
dereferencing each element iterator. The remaining columns show the results of
various expressions.</p>
<table border="1" cellpadding="5" cellspacing="0">
<tr>
<td><b>p.string()</b></td>
<td><b>Elements</b></td>
<td><b>p.root_<br>
path()<br>
&nbsp;</b></td>
<td><b>p.root_<br>
name()</b></td>
<td><b>p.root_<br>
directory()</b></td>
<td><b>p.relative_<br>
path()</b></td>
<td><b>p.root_<br>
directory()<br>
/ p.relative_<br>
path()</b></td>
<td><b>p.root_<br>
name() /<br>
p.relative_<br>
path()</b></td>
<td><b>p.branch_<br>
path()</b></td>
<td><b>p.leaf()</b></td>
</tr>
<tr>
<td><b>All systems</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><code>/</code></td>
<td><code>/</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
</tr>
<tr>
<td><code>foo</code></td>
<td><code>foo</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>foo</code></td>
<td><code>foo</code></td>
<td><code>foo</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><code>/foo</code></td>
<td><code>/,foo</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>foo</code></td>
<td><code>/foo</code></td>
<td><code>foo</code></td>
<td><code>/</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><code>foo/bar</code></td>
<td><code>foo,bar</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>foo/bar</code></td>
<td><code>foo/bar</code></td>
<td><code>foo/bar</code></td>
<td><code>foo</code></td>
<td><code>bar</code></td>
</tr>
<tr>
<td><code>/foo/bar</code></td>
<td><code>/,foo,bar</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>foo/bar</code></td>
<td><code>/foo/bar</code></td>
<td><code>foo/bar</code></td>
<td><code>/foo</code></td>
<td><code>bar</code></td>
</tr>
<tr>
<td><b><code>.</code></b></td>
<td><code>.</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>.</code></td>
<td><code>.</code></td>
<td><code>.</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>.</code></td>
</tr>
<tr>
<td><b><code>..</code></b></td>
<td><code>..</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>..</code></td>
<td><code>..</code></td>
<td><code>..</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>..</code></td>
</tr>
<tr>
<td><code>../foo</code></td>
<td><code>..,foo</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>../foo</code></td>
<td><code>../foo</code></td>
<td><code>../foo</code></td>
<td><code>..</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><b>Windows</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>c:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>c:</code></td>
</tr>
<tr>
<td><code>c:/</code></td>
<td><code>c:,/</code></td>
<td><code>c:/</code></td>
<td><code>c:</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>/</code></td>
</tr>
<tr>
<td><code>c:..</code></td>
<td><code>c:,..</code></td>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>..</code></td>
<td><code>c:..</code></td>
<td><code>c:..</code></td>
<td><code>c:</code></td>
<td><code>..</code></td>
</tr>
<tr>
<td><code>c:foo</code></td>
<td><code>c:,foo</code></td>
<td><code>c:</code></td>
<td><code>c:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>foo</code></td>
<td><code>foo</code></td>
<td><code>c:foo</code></td>
<td><code>c:</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><code>c:/foo</code></td>
<td><code>c:,/,foo</code></td>
<td><code>c:/</code></td>
<td><code>c:</code></td>
<td><code>/</code></td>
<td><code>foo</code></td>
<td><code>/foo</code></td>
<td><code>c:foo</code></td>
<td><code>c:/</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><code>//shr</code></td>
<td><code>//shr</code></td>
<td><code>//shr</code></td>
<td><code>//shr</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>//shr</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>//shr</code></td>
</tr>
<tr>
<td><code>//shr/</code></td>
<td><code>//shr,/</code></td>
<td><code>//shr/</code></td>
<td><code>//shr</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>//shr</code></td>
<td><code>//shr</code></td>
<td><code>/</code></td>
</tr>
<tr>
<td><code>//shr/foo</code></td>
<td><code>//shr,<br>
/,foo</code></td>
<td><code>//shr/</code></td>
<td><code>//shr</code></td>
<td><code>/</code></td>
<td><code>foo</code></td>
<td><code>/foo</code></td>
<td><code>//shr/foo</code></td>
<td><code>//shr/</code></td>
<td><code>foo</code></td>
</tr>
<tr>
<td><code>prn:</code></td>
<td><code>prn:</code></td>
<td><code>prn:</code></td>
<td><code>prn:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>prn:</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>prn:</code></td>
</tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 December, 2003<!--webbot bot="Timestamp" endspan i-checksum="38521" --></p>
<p>© Copyright Beman Dawes, 2002</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>