Files
filesystem/doc/path.htm
Beman Dawes 7b1b8e5b35 i18n initial commit
[SVN r27780]
2005-03-23 13:22:58 +00:00

971 lines
45 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="../../../boost.png" align="center" width="277" height="86"><a href="../../../boost/filesystem/path.hpp">boost/filesystem/basic_path.hpp</a></h1>
<p>
<a href="#Introduction">Introduction</a><br>
<a href="#Grammar">Grammar for generic path strings</a><br>
<a href="#Normalized">Normalized Form</a><br>
<a href="#synopsis">Header synopsis</a><br>
<a href="#Class_path">Class basic_path</a><br>
&nbsp;&nbsp;&nbsp; <a href="#System-specific-path-representation">
System-specific 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>
&nbsp;&nbsp;&nbsp; <a href="#Path_equality">Path equality vs path equivalence</a><br>
<a href="#Member">Member functions</a><br>
<a href="#Non-member_functions">Non-member functions</a><br>
<a href="#Rationale">Rationale</a><br>
<a href="#decomposition">Path decomposition examples</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>Boost.Filesystem traffics in objects of class template <i>basic_path</i>,
provided by this header.&nbsp;The header also declares functions for error checking
and class template <i>basic_filesystem_error</i>.</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
basic_path
naming issues which are important when portability is a concern.</p>
<h2><a name="Class_path">Class basic_path</a></h2>
<p>Class template <i>basic_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>. When portability is not a
requirement, native file system specific formats can be used.&nbsp;Class <i>
basic_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
file system, and may contain names which are not even valid for the current
operating system. </p>
<p><b>Rationale:</b> If the library's functions trafficked in <i>std::string</i> or C-style strings, the
functions
would provide only an illusion of portability since while the syntax of function calls would be
portable, the semantics of the strings they operate on would not be portable. A
number of supporting functions are also neatly packaged in class <i>basic_path</i>.</p>
<h2>Conceptual <a name="model">model</a> of a path</h2>
<p>An object of class <i>basic_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 operating system's representation of the path as a single
string.</p>
<p>There is no requirement that an implementation of class <i>basic_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>
basic_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.</p>
<p>Access functions are provided to retrieve the contents of a object of class
<i>basic_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 basic_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] | separator separator name</pre>
<pre>root-directory ::= separator</pre>
<pre>relative-path ::= path-element { separator path-element } [separator]</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;
separator ::= &quot;/&quot; // an implementation may define additional alternate separators </pre>
</blockquote>
<p><i>root-name</i> grammar is implementation-defined for the particular
operating system. For example, it is used to represent drive specifiers for the
Window operating system. It is not used for POSIX implementations.</p>
<p><i>char</i> may not be slash ('/') or '\0'. In additional, operating and
file systems place additional restrictions on the characters which may
appear in names. See <a href="portability_guide.htm#recommendations">File and
Directory Name Recommendations</a>.</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 meaning, if any, of a <i>root</i> in the form <i>separator separator name</i>
is operating system dependent.</p>
<p>An optional trailing &quot;/&quot; is allowed in a <i>relative-basic_path</i>. It
has no particular meaning to class <i>basic_path</i>. It may or may not have meaning
to operations functions, depending on the particular operating system. It will
be ignored by operations functions on operating systems for which a trailing &quot;/&quot;
is ignored or invalid.</p>
<p>Whether or not a generic path string is actually portable to a particular
operating system or file system will depend on the
names used.&nbsp; See the <a href="portability_guide.htm">Portability Guide</a>.</p>
<h2><a name="Normalized">Normalized</a> form</h2>
<p>In Normalized form, adjacent <i>name, parent-directory</i>
elements are recursively removed. Except in a single element path, <i>
directory-placeholders</i> are 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/basic_path.hpp</a> <a name="synopsis">synopsis</a></h2>
<pre>namespace boost
{
namespace filesystem
{
template&lt;class String, class Traits&gt; class basic_path;
typedef basic_path&lt; string_type, detail::path_traits &gt; path;
typedef basic_path&lt; std::wstring, detail::wpath_traits &gt; wpath;
template&lt;class String, class Traits&gt;
class basic_path
{
public:
typedef basic_path&lt;String, Traits&gt; path_type;
typedef String string_type;
typedef Traits traits_type;
typedef typename Traits::external_string_type external_string_type;
// compiler generates copy constructor and copy assignment
// constructors:
<a href="#Class_path">basic_path</a>();
<a href="#Class_path">basic_path</a>( const string_type &amp; src );
<a href="#Class_path">basic_path</a>( const char * src );
~basic_path();
// append operations:
basic_path &amp; <a href="#operator_slash_equal">operator /=</a> ( const basic_path &amp; rhs );
basic_path &amp; <a href="#operator_slash_equal">operator /=</a> ( const string_type &amp; rhs );
basic_path &amp; <a href="#operator_slash_equal">operator /=</a> ( const typename string_type::value_type * rhs );
basic_path <a href="#operator_slash">operator /</a> ( const basic_path &amp; rhs ) const;
basic_path <a href="#operator_slash">operator /</a> ( const string_type &amp; rhs ) const;
basic_path <a href="#operator_slash">operator /</a> ( const typename string_type::value_type * rhs ) const;
// modification functions:
basic_path &amp; <a href="#normalize">normalize</a>();
basic_path &amp; <a href="#remove_leaf">remove_leaf</a>();
// conversion functions:
const string_type &amp; <a href="#string">string</a>() const;
const string_type <a href="#file_string">file_string</a>() const;
const string_type <a href="#directory_string">directory_string</a>() const;
const external_string_type <a href="#external_file_string">external_file_string</a>() const;
const external_string_type <a href="#external_directory_string">external_directory_string</a>() const;
// decomposition functions:
basic_path <a href="#root_path">root_path</a>() const;
string_type <a href="#root_name">root_name</a>() const;
string_type <a href="#root_directory">root_directory</a>() const;
basic_path <a href="#relative_path">relative_path</a>() const;
string_type <a href="#leaf">leaf</a>() const;
basic_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;
// relational operators:
bool <a href="#operator_eq">operator==</a>( const basic_path &amp; that ) const;
bool <a href="#operator_ne">operator!=</a>( const basic_path &amp; that ) const;
bool <a href="#operator_lt">operator&lt;</a>( const basic_path &amp; that ) const;
bool <a href="#operator_le">operator&lt;=</a>( const basic_path &amp; that ) const;
bool <a href="#operator_gt">operator&gt;</a>( const basic_path &amp; that ) const;
bool <a href="#operator_ge">operator&gt;=</a>( const basic_path &amp; that ) const;
private:
std::vector&lt;string_type&gt; m_name; // for exposition only
bool m_trailing_separator; // for exposition only
};
template&lt;class String, class Traits&gt;
basic_path&lt;String, Traits&gt;
operator/( const String &amp; lhs, const basic_path&lt;String, Traits&gt; &amp; rhs );
template&lt;class String, class Traits&gt;
basic_path&lt;String, Traits&gt;
operator/( const typename String::value_type * lhs, const basic_path&lt;String, Traits&gt; &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#native">native</a>( const std::string &amp; name );
}
}</pre>
<p>For the sake of exposition, class <i>basic_path</i> member functions are described
as if the class contains the indicated private members.
Actual implementations may differ.</p>
<p>For functions <i>string</i>, <i>file_string</i>, <i>directory_string</i>, <i>
external_file_string</i>, and <i>external_directory_string</i>, implementations
are permitted to return either <code>const</code> or <code>const &amp;</code>
values.</p>
<p>Class path member, or non-member operator/, functions may throw a
<a href="exception.htm">basic_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>basic_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 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>basic_path</i> object
represents a path which would be portable to another operating system or file
system. A path
might be non-portable because it contains names which the operating system
considers too long or containing invalid characters. To detect portability
problems, the library supplies several
<a href="portability_guide.htm#name_check­_functions">name_check
functions</a>.</p>
<h3><a name="System-specific-path-representation">System-specific path
representation</a></h3>
<p>Several <i>basic_path</i> member functions return representations of <i>m_name</i>
in formats specific to the operating system. For POSIX, the system specific
format is the same as the <a href="#Grammar">generic grammar</a>. For Window,
the system specific format is the same as the <a href="#Grammar">generic grammar</a>
except that the alternate separator (backslash) is always used. For other
operating systems, the system specific format is implementation
defined.</p>
<p>For operating systems other than POSIX and Windows, if an <i>m_name</i>
element contains characters which are invalid under the operating system's
rules, and there is an unambiguous and reasonable 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 must be translated
to uppercase if unambiguous. Such translation does not apply to the representation
returned by <code>string()</code>.</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 basic_path is required, and use either
<i>directory_string()</i> or
<i>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>directory_string()</i>, and
<i>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;directory_string--------: &quot; &lt;&lt; my_path.directory_string() &lt;&lt; '\n'
&lt;&lt; &quot;file_string-------------: &quot; &lt;&lt; my_path.file_string() &lt;&lt; '\n';</pre>
</blockquote>
<p>On POSIX systems, the output would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
directory_string--------: foo/bar/data.txt
file_string-------------: foo/bar/data.txt</pre>
</blockquote>
<p>On Windows, the output would be:</p>
<blockquote>
<pre>string------------------: foo/bar/data.txt
directory_string--------: foo\bar\data.txt
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
directory_string--------: foo:bar:data.txt
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
directory_string--------: [foo.bar.data.txt]
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>
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 also 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 basic_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 basic_path completion is to hard-code only
relative paths. When a complete basic_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><a href="operations.htm#initial_path">initial_path()</a></b>.
Particularly for command line programs, specifying paths relative to the
current directory's path at the time the program is started is a common practice. For
example:<pre> path foo( initial_path&lt;path&gt;() / &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>
<h3><a name="Path_equality">Path equality</a> vs path equivalence</h3>
<p>Are paths &quot;abc&quot; and &quot;ABC&quot; equal? No, never, if you determine equality via
class <i>basic_path</i>'s <code>operator==</code>, which considers only the two path's
lexical representations.</p>
<p>Do paths &quot;abc&quot; and &quot;ABC&quot; resolve to the same file or directory? The answer is
&quot;yes&quot;, &quot;no&quot;, or &quot;maybe&quot; depending on the operating
system and external file system. The operations function
<i>equivalent()</i> is the only way to determine if two paths
resolve to the same external file system entity.</p>
<p>Programmers wishing to determine if two paths are &quot;the same&quot; must decide if
&quot;the same&quot; means &quot;the same representation&quot; or &quot;resolve to the same actual file or
directory&quot;, and choose the appropriate function accordingly.</p>
<h2><a name="Member">Member</a> functions</h2>
<h3><a name="constructors">constructors</a></h3>
<blockquote>
<pre>basic_path();</pre>
<p><b>Effects:</b> Default constructs an object of class <i>basic_path</i>.</p>
<p><b>Postcondition:</b> basic_path().empty()</p>
<pre>basic_path( const string_type &amp; src );
basic_path( const char * src );</pre>
<p><b>Precondition:</b> <code>src != 0</code>.</p>
<p><b>Throws:</b> If <code>src</code> is invalid according to the
<a href="#Grammar">grammar</a>. Note that because the grammar is extremely
permissive, the only invalid character combination is two adjacent slashes,
and even this is valid at the beginning of a path.</p>
<p><b>Effects:</b> For each element in <code>src</code>, as determined by the
<a href="#Grammar">grammar</a>, <code>m_name.push_back(element)</code>. Set
<code>m_trailing_separator</code> to true if <code>src</code> has a trailing
separator, else false.</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>basic_path &amp; operator/=( const basic_path &amp; rhs );
basic_path &amp; operator /=( const string_type &amp; rhs );
basic_path &amp; operator /=( const typename string_type::value_type * rhs );</pre>
<p><b>Effects:</b> For each element in <code>rhs</code>, as determined by the
<a href="#Grammar">grammar</a>, <code>m_name.push_back(element)</code>. Set
<code>m_trailing_separator</code> to true if <code>rhs</code> has a trailing
separator, else false.</p>
<p><b>Returns:</b> <code>*this</code></p>
</blockquote>
<h3><a name="operator_slash">operator /</a></h3>
<blockquote>
<pre>basic_path operator/( const basic_path &amp; rhs ) const;
basic_path operator/( const string_type &amp; rhs ) const;
basic_path operator/( const typename string_type::value_type * rhs ) const;</pre>
<p><b>Returns:</b> <code>basic_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&lt;path&gt;() / &quot;src&quot; / src_name</code>.
Operator+ and operator+= were considered as alternative names, but deemed too
easy to confuse with those operators for std::basic_string. Operator&lt;&lt; and
operator=&lt;&lt; were used until 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>basic_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="remove_leaf">remove_leaf</a></h3>
<blockquote>
<pre>basic_path &amp; remove_leaf();</pre>
<p><b>Effects:</b> If <code>has_branch_path()</code> then <code>
m_name.pop_back()</code>.</p>
<p><b>Returns:</b> <code>*this</code></p>
<p><b>Rationale:</b> This function is needed to implement directory iterators.
It is made public so other uses can benefit from the functionality.</p>
</blockquote>
<h3><a name="string">string</a></h3>
<blockquote>
<pre>const string_type &amp; string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted as a string according to
the rules of the <a href="#Grammar">grammar</a>, with a separator appended if
<code>m_trailing_separator</code> is true.</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="file_string">file_string</a></h3>
<blockquote>
<pre>const string_type file_string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
<a href="#System-specific-path-representation">system-specific representation</a> of
a file path.</p>
<p><b>See:</b> <a href="#Representation_example">Representation example</a>
above.</p>
</blockquote>
<h3><a name="directory_string">directory_string</a></h3>
<blockquote>
<pre>const string_type directory_string() const;</pre>
<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
<a href="#System-specific-path-representation">system-specific representation</a> of
a directory path.</p>
<p><b>See:</b> <a href="#Representation_example">Representation example</a>
above.</p>
</blockquote>
<h3><a name="external_file_string">external_file_string</a></h3>
<blockquote>
<pre>const external_string_type external_file_string() const;</pre>
<p><b>Returns:</b> <code>file_string()</code>, converted to the type and
encoding of <code>external_string_type</code>.</p>
<p>Using <i>wpath</i> as an example, on Linux the external string type will be
<i>string_type</i>, and the external encoding will normally be
<a href="design.htm#Kuhn">UTF-8</a>. On Windows the <i>wpath</i> internal and
external string types are both <i>std::wstring</i>, and the encoding of both
is <a href="design.htm#UTF-16">UTF-16</a>.</p>
</blockquote>
<h3><a name="external_directory_string">external_directory_string</a></h3>
<blockquote>
<pre>const external_string_type external_directory_string() const;</pre>
<p><b>Returns:</b> <code>directory_string()</code>, converted to the type and
encoding of <code>external_string_type</code>.</p>
</blockquote>
<h3><a name="root_path">root_path</a></h3>
<blockquote>
<pre>basic_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>string_type 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>string_type 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>basic_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>string_type leaf() const;</pre>
<p><b>Returns:</b> <code>empty() ? string_type() : 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>basic_path branch_path() const;</pre>
<p><b>Returns:</b> <code>m_name.size() &lt;= 1 ? path_type(&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>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::basic_string&lt;&gt;</i>,
<i>const std::basic_string&lt;&gt; &amp;</i>, and <i>const std::basic_string&lt;&gt; *</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="operator_eq">operator</a> ==</h3>
<blockquote>
<pre>bool operator==( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>!(*this &lt; that) &amp;&amp; !(that &lt; *this)</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</p>
</blockquote>
<h3><a name="operator_ne">operator !=</a></h3>
<blockquote>
<pre>bool operator!=( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>!(*this == that)</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</p>
</blockquote>
<h3><a name="operator_lt">operator</a> &lt;</h3>
<blockquote>
<pre>bool operator&lt;( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>std::lexicographical_compare( begin(), end(),
that.begin(), that.end() )</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</p>
<p><b>Rationale:</b> Relational operators are provided to ease uses such as
specifying paths as keys in associative containers. Lexicographical comparison
is used because:</p>
<ol>
<li>Even though not a full-fledged standard container, paths are enough like
containers to merit meeting the C++ Standard Library's container comparison
requirements (23.1 table 65).</li>
<li>The alternative is to return <code>this-&gt;string() &lt; that.string()</code>.
But basic_path::string() as currently specified can yield non-unique results for
differing paths. The case (from Peter Dimov) is <code>basic_path(&quot;first/&quot;)/&quot;second&quot;</code>
and <code>basic_path(&quot;first&quot;)/&quot;second&quot;</code> both returning a string() of <code>
&quot;first/second&quot;</code>. <b><i>[TODO: reanalyze this. It doesn't
make sense anymore Did something change?]</i></b></li>
</ol>
</blockquote>
<h3><a name="operator_le">operator</a> &lt;=</h3>
<blockquote>
<pre>bool operator&lt;=( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>!(that &lt; *this)</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</p>
</blockquote>
<h3><a name="operator_gt">operator</a> &gt;</h3>
<blockquote>
<pre>bool operator&gt;( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>that &lt; *this</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</p>
</blockquote>
<h3><a name="operator_ge">operator</a> &gt;=</h3>
<blockquote>
<pre>bool operator&gt;=( const basic_path &amp; that ) const;</pre>
<p><b>Returns:</b> <code>!(*this &lt; that)</code></p>
<p>See <a href="#Path_equality">Path equality vs basic_path equivalence</a>.</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>template&lt;class String, class Traits&gt;<br>
basic_path&lt;String, Traits&gt; operator/( <br>
&nbsp; const typename String::value_type * lhs, const basic_path&lt;String, Traits&gt;
&amp; rhs );<br>
<br>
template&lt;class String, class Traits&gt;<br>
basic_path&lt;String, Traits&gt; operator/(<br>
&nbsp; const String &amp; lhs, const basic_path&lt;String, Traits&gt; &amp; rhs );</code></p>
<p><b>Returns:</b> <code>basic_path( lhs ) /= rhs</code></p>
</blockquote>
<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>basic_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>basic_path::empty()</i>
was renamed <i>basic_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
basic_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
basic_path::iterator be a class type was added to eliminate non-const
iterator errors. The returns from conversion functions are still const
qualified, to ensure that user programs do not break if implementations change
from return by value to return by reference, as they are permitted to do.</p>
<h2>Path <a name="decomposition">decomposition</a> examples</h2>
<p>It is often useful to extract specific elements from a <i>basic_path</i> object.&nbsp;
While any decomposition can be achieved by iterating over the elements of a
<i>basic_path</i>, 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>//net</code></td>
<td><code>//net</code></td>
<td><code>//net</code></td>
<td><code>//net</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>//net</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>//net</code></td>
</tr>
<tr>
<td><code>//net/</code></td>
<td><code>//net,/</code></td>
<td><code>//net/</code></td>
<td><code>//net</code></td>
<td><code>/</code></td>
<td><code>&quot;&quot;</code></td>
<td><code>/</code></td>
<td><code>//net</code></td>
<td><code>//net</code></td>
<td><code>/</code></td>
</tr>
<tr>
<td><code>//net/foo</code></td>
<td><code>//net,<br>
/,foo</code></td>
<td><code>//net/</code></td>
<td><code>//net</code></td>
<td><code>/</code></td>
<td><code>foo</code></td>
<td><code>/foo</code></td>
<td><code>//net/foo</code></td>
<td><code>//net/</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 -->22 March, 2005<!--webbot bot="Timestamp" endspan i-checksum="28898" --></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>