Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/filesystem/doc/path.htm @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 46.0 KB
Line 
1<html>
2
3<head>
4<meta http-equiv="Content-Language" content="en-us">
5<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
6<meta name="ProgId" content="FrontPage.Editor.Document">
7<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
8<title>Boost Filesystem path.hpp Header</title>
9</head>
10
11<body bgcolor="#FFFFFF">
12
13<h1>
14<img border="0" src="../../../boost.png" align="center" width="277" height="86"><a href="../../../boost/filesystem/path.hpp">boost/filesystem/path.hpp</a></h1>
15
16<p>
17<a href="#Introduction">Introduction</a><br>
18<a href="#Grammar">Grammar for generic path strings</a><br>
19<a href="#Canonical">Canonical form</a><br>
20<a href="#synopsis">Header synopsis</a><br>
21<a href="#Class_path">Class path</a><br>
22&nbsp;&nbsp;&nbsp; <a href="#Native_path_representation">Native path
23representation</a><br>
24&nbsp;&nbsp;&nbsp; <a href="#Representation_example">Representation example</a><br>
25&nbsp;&nbsp;&nbsp; <a href="#Caution_POSIX">Caution for POSIX and UNIX
26programmers</a><br>
27&nbsp;&nbsp;&nbsp; <a href="#relative_paths_good">Good programming practice:
28relative paths</a><br>
29&nbsp;&nbsp;&nbsp; <a href="#Path_equality">Path equality vs path equivalence</a><br>
30<a href="#Member">Member functions</a><br>
31<a href="#Non-member_functions">Non-member functions</a><br>
32<a href="#name_check­_mechanism">Default name_check mechansim</a><br>
33<a href="#Rationale">Rationale</a><br>
34<a href="#decomposition">Path decomposition examples</a></p>
35<h2><a name="Introduction">Introduction</a></h2>
36
37<p>Filesystem Library functions traffic in objects of class <i>path</i>,
38provided by this header.&nbsp;The header also supplies non-member functions for error checking.</p>
39
40<p>For actual operations on files and directories, see <a href="operations.htm">
41boost/filesystem/operations.hpp documentation</a>.</p>
42
43<p>For file I/O stream operations, see <a href="fstream.htm">boost/filesystem/fstream.hpp
44documentation</a>.</p>
45
46<p>The Filesystem Library's <a href="index.htm#Common_Specifications">Common
47Specifications</a> apply to all member and non-member functions supplied by this
48header.</p>
49
50<p>The <a href="portability_guide.htm">Portability Guide</a> discusses path
51naming issues which are important when portability is a concern.</p>
52<h2><a name="Class_path">Class path</a></h2>
53<p>Class <i>path</i> provides for portable mechanism for representing
54<a href="index.htm#path">paths</a> in C++ programs, using a portable generic
55path string <a href="#Grammar">grammar</a>.&nbsp;Class <i>path</i> 
56is concerned with the lexical and syntactic aspects of a path. The path does not
57have to exist in the operating system's
58filesystem, and may contain names which are not even valid for the current
59operating system. </p>
60<p><b>Rationale:</b> If Filesystem functions trafficked in <i>std::strings</i> or C-style strings, the
61functions
62would provide only an illusion of portability since the function calls would be
63portable but the strings they operate on would not be portable.</p>
64<h2>Conceptual <a name="model">model</a> of a path</h2>
65<p>An object of class <i>path</i> can be conceptualized as containing a sequence
66of strings. Each string is said to be an element of the path. Each element
67represents the name of a directory, or, in the case
68of the string representing the element farthest from the root in the directory
69hierarchy, the name of a directory or file. The names <code>&quot;..&quot;</code> and
70<code>&quot;.&quot;</code> are reserved to represent the concepts of <i>parent-directory</i> 
71and <i>directory-placeholder</i>.</p>
72<p>This conceptual path representation is
73 
74independent of any particular representation of the path as a single
75string.</p>
76<p>There is no requirement that an implementation of class <i>path</i> actually
77contain a sequence of strings, but conceptualizing the contents as a sequence of
78strings provides
79a completely portable way to reason about paths.</p>
80<p>So that programs can portably express paths as a single string, class <i>path</i> 
81defines a <a href="#Grammar">grammar</a> for a portable generic path string
82format, and supplies constructor and append operations taking such strings as
83arguments. Because user input or third-party library functions may supply path
84strings formatted according to operating system specific rules, an additional
85constructor is provided which takes a system-specific format as an argument.</p>
86<p>Access functions are provided to retrieve the contents of a object of class
87<i>path</i> formatted as a portable path string, a directory path string using
88the operating system's format, and a file path string using the operating
89system's format.&nbsp; Additional access functions retrieve specific portions of
90the contained path.</p>
91<h2><a name="Grammar">Grammar</a> for portable generic path strings</h2>
92<p>The grammar is specified in extended BNF, with terminal symbols in quotes:
93</p>
94<blockquote>
95  <pre>path ::= [root] [relative-path]  // an empty path is valid</pre>
96  <pre>root ::= [root-name] [root-directory]</pre>
97  <pre>root-directory ::= separator</pre>
98  <pre>relative-path ::= path-element { separator path-element } [separator]</pre>
99  <pre>path-element ::= name | parent-directory | directory-placeholder</pre>
100  <pre>name ::= char { char }</pre>
101  <pre>directory-placeholder ::= &quot;.&quot;</pre>
102  <pre>parent-directory ::= &quot;..&quot;
103
104separator ::= &quot;/&quot;  // an implementation may define additional separators </pre>
105</blockquote>
106<p><i>root-name</i> grammar is implementation-defined. <i>
107root-name</i> must not be present in generic input. It may be part of the strings returned by <i>path</i> 
108member functions, and may be present in the <i>src</i> argument to <i>path</i> constructors
109when the <i><a href="portability_guide.htm#native">native</a></i> name check is in effect.</p>
110<p><i>char</i> may not be slash ('/') or '\0'. In additional, many operating and
111file systems may place additional restrictions on the characters which may
112appear in names. See <a href="portability_guide.htm#recommendations">File and
113Directory Name Recommendations</a>.</p>
114<p>Although implementation-defined, it is desirable that <i>
115root-name</i> have a grammar which is distinguishable from other grammar elements,
116and follow the conventions of the operating system.</p>
117<p>The optional trailing &quot;/&quot; in a <i>relative-path</i> is allowed as a
118notational convenience. It has no semantic meaning and is simply discarded.</p>
119<p>Whether or not a generic path string is actually portable to a particular
120operating system will depend on the
121names used.&nbsp; See the <a href="portability_guide.htm">Portability Guide</a>.</p>
122<h2><a name="Canonical">Canonical</a> form</h2>
123<p>All operations modifying <i>path</i> objects leave the <i>path</i> object in
124canonical form.</p>
125<p>An empty path is in canonical form.</p>
126<p>A non-empty path is converted to canonical form as if by first converting it
127to the <a href="#model">conceptual model</a>, and then:</p>
128<ul>
129  <li>Repeatedly replacing any leading <i>root-directory, parent-directory</i> 
130  elements with a single <i>root-directory</i> element. Rationale: Both POSIX
131  and Windows specify this reduction; specifying it for canonical form ensures
132  portable semantics for other operating systems.</li>
133  <li>Removing each <i>directory-placeholder</i> element.</li>
134  <li>If the path is now empty, add a single <i>directory-placeholder</i> 
135  element.</li>
136</ul>
137<h2><a name="Normalized">Normalized</a> form</h2>
138<p>Normalized form is the same as canonical form, except that adjacent <i>name, parent-directory</i> 
139elements are recursively removed.</p>
140<p>Thus a non-empty path in normal form either has no <i>
141directory-placeholders</i>, or consists solely of one <i>directory-placeholder</i>.
142If it has <i>parent-directory</i> elements, they precede all <i>name</i> 
143elements.</p>
144<h2>Header <a href="../../../boost/filesystem/path.hpp">
145boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
146<pre>namespace boost
147{
148  namespace filesystem
149  {
150    class path
151    {
152    public:
153      <a name="name_check_typedef">typedef</a> bool (*name_check)( const std::string &amp; name );
154
155      // compiler generates copy constructor,
156      // copy assignment, and destructor
157
158      // constructors:
159      <a href="#constructors">path</a>();
160      <a href="#constructors">path</a>( const std::string &amp; src );
161      <a href="#constructors">path</a>( const char * src );
162      <a href="#constructors">path</a>( const std::string &amp; src, name_check checker );
163      <a href="#constructors">path</a>( const char * src, name_check checker );
164
165      // append operations:
166      path &amp; <a href="#operator_slash_equal">operator /=</a> ( const path &amp; rhs );
167      path   <a href="#operator_slash">operator /</a>  ( const path &amp; rhs ) const;
168
169      // conversion functions:
170      const std::string & <a href="#string">string</a>() const;
171      std::string <a href="#native_file_string">native_file_string</a>() const;
172      std::string <a href="#native_directory_string">native_directory_string</a>() const;
173     
174      // modification functions:
175      path &amp;      <a href="#normalize">normalize</a>();
176
177      // decomposition functions:
178      path        <a href="#root_path">root_path</a>() const;
179      std::string <a href="#root_name">root_name</a>() const;
180      std::string <a href="#root_directory">root_directory</a>() const;
181      path        <a href="#relative_path">relative_path</a>() const;
182      std::string <a href="#leaf">leaf</a>() const;
183      path        <a href="#branch_path">branch_path</a>() const;
184     
185      // query functions:
186      bool <a href="#empty">empty</a>() const;
187      bool <a href="#is_complete">is_complete</a>() const;
188      bool <a href="#has_root_path">has_root_path</a>() const;
189      bool <a href="#has_root_name">has_root_name</a>() const;
190      bool <a href="#has_root_directory">has_root_directory</a>() const;
191      bool <a href="#has_relative_path">has_relative_path</a>() const;
192      bool <a href="#has_leaf">has_leaf</a>() const;
193      bool <a href="#has_branch_path">has_branch_path</a>() const;
194     
195      // iteration:
196      typedef <i>implementation-defined</i> <a href="#iterator">iterator</a>;
197      iterator <a href="#begin">begin</a>() const;
198      iterator <a href="#end">end</a>() const;
199
200      // <a href="#name_check­_mechanism">default name_check</a> mechanism:
201      static bool <a href="#default_name_check_writable">default_name_check_writable</a>();
202      static void <a href="#default_name_check">default_name_check</a>( name_check new_check );
203      static name_check <a href="#default_name_check">default_name_check</a>();</pre>
204<pre>      // relational operators:
205      bool <a href="#operator_eq">operator==</a>( const path &amp; that ) const;
206      bool <a href="#operator_ne">operator!=</a>( const path &amp; that ) const;
207      bool <a href="#operator_lt">operator&lt;</a>( const path &amp; that ) const;
208      bool <a href="#operator_le">operator&lt;=</a>( const path &amp; that ) const;
209      bool <a href="#operator_gt">operator&gt;</a>( const path &amp; that ) const;
210      bool <a href="#operator_ge">operator&gt;=</a>( const path &amp; that ) const;
211
212    private:
213      std::vector&lt;std::string&gt; m_name;  // for exposition only
214    };
215
216    path <a href="#non-member_operator_shift">operator /</a> ( const char * lhs, const path &amp; rhs );
217    path <a href="#non-member_operator_shift">operator /</a> ( const std::string &amp; lhs, const path &amp; rhs );
218
219    // <a href="portability_guide.htm#name_check­_functions">name_check functions</a>
220    bool <a href="portability_guide.htm#portable_posix_name">portable_posix_name</a>( const std::string &amp; name );
221    bool <a href="portability_guide.htm#windows_name">windows_name</a>( const std::string &amp; name );
222    bool <a href="portability_guide.htm#portable_name">portable_name</a>( const std::string &amp; name );
223    bool <a href="portability_guide.htm#portable_directory_name">portable_directory_name</a>( const std::string &amp; name );
224    bool <a href="portability_guide.htm#portable_file_name">portable_file_name</a>( const std::string &amp; name );
225    bool <a href="portability_guide.htm#no_check">no_check</a>( const std::string &amp; name );
226    bool <a href="portability_guide.htm#native">native</a>( const std::string &amp; name );
227  }
228}</pre>
229<p>For the sake of exposition, class <i>path</i> member functions are described
230as if the class contains a private member <i>std::vector&lt;std::string&gt; m_name</i>.
231Actual implementations may differ.</p>
232<p>Class path member, or non-member operator/, functions may throw a
233<a href="exception.htm">filesystem_error</a> exception if the path is not in the
234syntax specified for the <a href="#Grammar">grammar</a>.</p>
235<p><b>Note:</b> There is no guarantee that a <i>path</i> object represents a
236path which is considered valid by the current operating system. A path might be
237invalid to the operating system because it contains invalid names (too long,
238invalid characters, and so on), or because it is a partial path still as yet
239unfinished by the program. An invalid path will normally be detected at time of
240use, such as by one of the Filesystem Library's <a href="operations.htm">
241operations</a> or <a href="fstream.htm">fstream</a> functions.</p>
242<p><b>Portability Warning:</b> There is no guarantee that a <i>path</i> object
243represents a path which would be portable to another operating system. A path
244might be non-portable because it contains names which the operating systems
245considers too long or contains invalid characters. A
246<a href="#name_check­_mechanism">default name_check mechanism</a> is provided to
247aid in the detection of non-portable names, or a name_check function can be
248specified in <i>path</i> constructors. The library supplies several
249<a href="portability_guide.htm#name_check­_functions">name_check
250functions</a>, or users can supply their own.</p>
251<h3><a name="Native_path_representation">Native path representation</a></h3>
252<p>Several <i>path</i> member functions return representations of <i>m_name</i> 
253in formats specific to the operating system. These formats are implementation
254defined. If an <i>m_name</i> 
255element contains characters which are invalid under the operating system's
256rules, and there is an unambiguous translation between the invalid character and
257a valid character, the implementation is required to perform that translation.
258For example, if an operating system does not permit lowercase letters in file or
259directory names, these letters will be translated to uppercase if unambiguous.
260Such translation does not apply to generic path string format representations.</p>
261<h3><a name="Representation_example">Representation example</a></h3>
262<p>The rule-of-thumb is to use <i>string()</i> when a generic string representation of
263the path is required, and use either
264<i>native_directory_string()</i> or
265<i>native_file_string()</i> when a string representation formatted for
266the particular operating system is required.</p>
267<p>The difference between the representations returned by <i>string()</i>,
268<i>native_directory_string()</i>, and
269<i>native_file_string()</i> are illustrated by the following
270code:</p>
271<blockquote>
272  <pre>path my_path( &quot;foo/bar/data.txt&quot; );
273std::cout
274  &lt;&lt; &quot;string------------------: &quot; &lt;&lt; my_path.string() &lt;&lt; '\n'
275  &lt;&lt; &quot;native_directory_string-: &quot; &lt;&lt; my_path.native_directory_string() &lt;&lt; '\n'
276  &lt;&lt; &quot;native_file_string------: &quot; &lt;&lt; my_path.native_file_string() &lt;&lt; '\n';</pre>
277</blockquote>
278<p>On POSIX systems, the output  would be:</p>
279<blockquote>
280  <pre>string------------------: foo/bar/data.txt
281native_directory_string-: foo/bar/data.txt
282native_file_string------: foo/bar/data.txt</pre>
283</blockquote>
284<p>On Windows, the output  would be:</p>
285<blockquote>
286  <pre>string------------------: foo/bar/data.txt
287native_directory_string-: foo\bar\data.txt
288native_file_string------: foo\bar\data.txt</pre>
289</blockquote>
290<p>On classic Mac OS, the output would be:</p>
291<blockquote>
292  <pre>string------------------: foo/bar/data.txt
293native_directory_string-: foo:bar:data.txt
294native_file_string------: foo:bar:data.txt</pre>
295</blockquote>
296<p>On a hypothetical operating system using OpenVMS format representations, it would be:</p>
297<blockquote>
298  <pre>string------------------: foo/bar/data.txt
299native_directory_string-: [foo.bar.data.txt]
300native_file_string------: [foo.bar]data.txt</pre>
301</blockquote>
302<p>Note that that because OpenVMS uses period as both a directory separator
303character and as a separator between filename and extension, <i>
304native_directory_string()</i> 
305in the example produces a useless result. On this operating system, the
306programmer should only use this path as a file path. (There is a
307<a href="portability_guide.htm#recommendations">portability recommendation</a> 
308to not use periods in directory names.)</p>
309<h3><a name="Caution_POSIX">Caution</a> for POSIX and UNIX programmers</h3>
310<p>POSIX and other UNIX-like operating systems have a single root, while most other
311operating systems have multiple roots. Multi-root operating systems require a
312root-name
313such as a drive, device, disk, volume, or share name for a path to be resolved
314to an actual specific file or directory.&nbsp; 
315Because of this, the <i>root()</i> and <i>root_directory()</i> functions return
316identical results on UNIX and other single-root operating systems, but different
317results on multi-root operating systems. Thus use of the wrong function will not be
318apparent on UNIX-like systems, but will result in non-portable code which will
319fail when used on multi-root systems. UNIX programmers are cautioned to use
320particular care in choosing between <i>root()</i> and <i>root_directory()</i>. If
321undecided, use <i>root()</i>.</p>
322<p>The same warning applies to <i>has_root()</i> and <i>has_root_directory()</i>.</p>
323<h3><a name="relative_paths_good">Good programming practice: relative paths</a></h3>
324<p>It is usually bad programming practice to hard-code <a href="#is_complete">
325complete paths</a> into programs. Such programs tend to be fragile because they
326break when directory trees get reorganized or the programs are moved to other
327machines or operating systems.</p>
328<p>The most robust way to deal with path completion is to hard-code only
329relative paths. When a complete path is required, it can be obtained in several
330ways:</p>
331<ul>
332  <li><b>Implicitly</b>. Allow the operating system to complete the path
333  according to the operating system's path completion algorithm. For example:<pre>    create_directory( &quot;foo&quot; ); // operating system will complete path</pre>
334  </li>
335  <li><b>User input</b>. The path is often best <a href="#constructors">
336  constructed</a> with the <i>native</i> name check, so that the user input
337  follows the operating system's native path format, which will usually be what
338  the program user expects. For example:<pre>    path foo( argv[1], native );
339    foo /= &quot;foo&quot;;</pre>
340  </li>
341  <li><b><a href="operations.htm#initial_path">initial_path()</a></b>.
342  Particularly for command line programs, specifying paths relative to the
343  current path at the time the program is started is a common practice. For
344  example:<pre>    path foo( initial_path() / &quot;foo&quot; );</pre>
345  </li>
346  <li><b>Algorithmically</b>. See <a href="operations.htm#complete">complete()</a> 
347  and <a href="operations.htm#system_complete">system_complete()</a> functions.</li>
348</ul>
349<h3><a name="Path_equality">Path equality</a> vs path equivalence</h3>
350<p>Are paths &quot;abc&quot; and &quot;ABC&quot; equal? No, never, if you determine equality via
351class <i>path</i>'s <code>operator==</code>, which considers only the two paths
352lexical representations.</p>
353<p>Do paths &quot;abc&quot; and &quot;ABC&quot; resolve to the same file or directory? The answer is
354&quot;yes&quot;, &quot;no&quot;, or &quot;maybe&quot; depending on the external file system. The (pending)
355operations function equivalent() is the only way to determine if two paths
356resolve to the same external file system entity.</p>
357<p>Programmers wishing to determine if two paths are &quot;the same&quot; must decide if
358that means &quot;the same representation&quot; or &quot;resolve to the same actual file or
359directory&quot;, and choose the appropriate function accordingly.</p>
360<h2><a name="Member">Member</a> functions</h2>
361<h3><a name="constructors">constructors</a></h3>
362<blockquote>
363  <pre>path();</pre>
364  <p><b>Effects:</b> Default constructs an object of class <i>path</i>.</p>
365  <p><b>Postcondition:</b> path().empty()</p>
366  <pre>path( const std::string &amp; src, name_check checker );
367path( const char * src, name_check checker );
368path( const std::string &amp; src );
369path( const char * src );</pre>
370  <p>For the single-argument forms, <code>default_name_check()</code> is used as
371  <code>checker</code>. </p>
372  <p><b>Precondition:</b> <code>src != 0</code>.</p>
373  <p><b>Effects:</b> Select the grammar as follows:</p>
374  <ul>
375    <li>If <code>checker == native</code>, the operating system's implementation
376    defined grammar for paths.</li>
377    <li>else if <code>checker == no_check</code>, the <a href="#Grammar">generic
378  path string grammar</a> with optional <i>
379  root-name</i>.</li>
380    <li>else the <a href="#Grammar">generic
381  path string grammar</a> without <i>
382  root-name</i>.</li>
383  </ul>
384  <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(
385  name )</code>.</p>
386  <p><b>Throws:</b> For each name in <code>src</code>, throw if <code>checker(
387  name )</code> returns
388  false.</p>
389  <p><b>Postcondition:</b> <code>m_name</code> is in
390  <a href="#Canonical">canonical form</a>. For the single-argument forms only, <code>!default_name_check_writable()</code>.</p>
391  <p><b>Rationale:</b> The single-argument constructors are not <code>explicit</code> because an intended
392  use is automatic conversion of strings to paths.</p>
393</blockquote>
394<h3><a name="operator_slash_equal">operator /=</a></h3>
395<blockquote>
396  <pre>path &amp; operator/=( const path &amp; rhs );</pre>
397  <p><b>Effects:</b> If any of the following conditions are met, then
398  m_name.push_back(&quot;/&quot;).</p>
399  <ul>
400    <li>has_relative_path().</li>
401    <li>!is_absolute() &amp;&amp; has_root_name(), and the operating system
402    requires the system-specific root be absolute</li>
403  </ul>
404  <p>&nbsp;Then append <code>rhs.m_name</code> to <code>m_name</code>.</p>
405  <p>(Footnote: Thus on Windows, (path(&quot;//share&quot;) /= &quot;foo&quot;).string() is
406  &quot;//share/foo&quot;)</p>
407  <p><b>Returns:</b> <code>*this</code></p>
408  <p><b>Postcondition:</b> <code>m_name</code> is in
409  <a href="#Canonical">canonical form</a>.</p>
410  <p><b>Rationale:</b> It is not considered an error for <code>rhs</code> to
411  include a <code>root-directory</code> because <code>m_name</code> might be relative
412  or empty, and
413  thus it is valid for rhs to supply <code>root-directory</code>.&nbsp; For example, on Windows, the following must succeed:</p>
414  <blockquote>
415    <pre>path p( &quot;c:&quot;, native );
416p /= &quot;/foo&quot;;
417assert( p.string() == &quot;c:/foo&quot; );</pre>
418  </blockquote>
419  </blockquote>
420<h3><a name="operator_slash">operator /</a></h3>
421<blockquote>
422  <pre>const path operator/ ( const path &amp; rhs ) const;</pre>
423  <p><b>Returns:</b> <code>path( *this ) /= rhs</code></p>
424  <p><b>Rationale:</b> Operator / is supplied because together with operator /=,
425  it provides a
426  convenient way for users to supply paths with a variable number of elements.&nbsp; 
427  For example, <code>initial_path() / &quot;src&quot; / test_name</code>.
428  Operator+ and operator+= were considered as alternatives, but deemed too
429  easy to confuse with those operators for std::string. Operator&lt;&lt; and
430  operator=&lt;&lt; were used originally until during public review Dave
431  Abrahams pointed out that / and /=
432  match the generic path syntax.</p>
433  <p><b>Note:</b> Also see <a href="#non-member_operator_shift">non-member <i>
434  operator/</i></a> functions.</p>
435  </blockquote>
436<h3><a name="normalize">normalize</a></h3>
437<blockquote>
438<p><code>path &amp; normalize();</code></p>
439<p><b>Postcondition:</b> m_name is in <a href="#Normalized">normalized form</a>.</p>
440<p><b>Returns:</b> <code>*this</code></p>
441</blockquote>
442<h3><a name="string">string</a></h3>
443<blockquote>
444  <pre>const std::string &amp; string() const;</pre>
445<p><b>Returns:</b> The contents of <code>m_name</code>, formatted according to
446the rules of the <a href="#Grammar">generic path string grammar</a>.</p>
447<p><b>Note:</b> The returned string must be unambiguous
448according to the grammar. That means that for an operating system with root-names indistinguishable from 
449relative-path names, names containing &quot;/&quot;, or allowing &quot;.&quot; or &quot;..&quot; as
450directory or file names, escapes or other mechanisms will have to be introduced
451into the grammar to prevent ambiguities. This has not been done yet, since no
452current implementations are on operating systems with any of those problems.</p>
453<p><b>See:</b> <a href="#Representation_example">Representation example</a> 
454above.</p>
455</blockquote>
456<h3><a name="native_file_string">native_file_string</a></h3>
457<blockquote>
458  <pre>std::string native_file_string() const;</pre>
459<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
460<a href="#Native_path_representation">native representation</a> of
461a file path.</p>
462<p><b>See:</b> <a href="#Representation_example">Representation example</a> 
463above.</p>
464<p><b>Naming rationale</b>: The name is deliberately ugly to warn users that
465this function yields non-portable results.</p>
466</blockquote>
467<h3><a name="native_directory_string">native_directory_string</a></h3>
468<blockquote>
469  <pre>const std::string native_directory_string() const;</pre>
470<p><b>Returns:</b> The contents of <code>m_name</code>, formatted in the
471<a href="#Native_path_representation">native representation</a> of
472a directory path.</p>
473<p><b>See:</b> <a href="#Representation_example">Representation example</a> 
474above.</p>
475<p><b>Naming rationale</b>: The name is deliberately ugly to warn users that
476this function yields non-portable results.</p>
477</blockquote>
478<h3><a name="root_path">root_path</a></h3>
479<blockquote>
480  <pre>path root_path() const;</pre>
481  <p><b>Returns:</b> <code>root_name() / root_directory()</code></p>
482<p>Portably provides a copy of a path's full root path, if any. See
483<a href="#decomposition">Path decomposition examples</a>.</p>
484</blockquote>
485<h3><a name="root_name">root_name</a></h3>
486<blockquote>
487  <pre>std::string root_name() const;</pre>
488  <p><b>Returns:</b> If <code>!m_name.empty() &amp;&amp; m_name[0]</code> is a
489  <a href="#Grammar">root-name</a>, returns m_name[0], else returns a
490  null string.</p>
491<p>Portably provides a copy of a path's <a href="#Grammar">root-name</a>,
492if any. See <a href="#decomposition">Path decomposition examples</a>.</p>
493</blockquote>
494<h3><a name="root_directory">root_directory</a></h3>
495<blockquote>
496  <pre>std::string root_directory() const;</pre>
497  <p><b>Returns:</b> If the path contains <a href="#Grammar">root-directory</a>,
498  then <code>string(&quot;/&quot;)</code>, else <code>string()</code>.</p>
499  <p>Portably provides a copy of a path's <a href="#Grammar">root-directory</a>,
500  if any. The only possible results are &quot;/&quot; or &quot;&quot;. See <a href="#decomposition">
501  Path decomposition examples</a>.</p>
502</blockquote>
503<h3><a name="relative_path">relative_path</a></h3>
504<blockquote>
505  <pre>path relative_path() const;</pre>
506  <p><b>Returns:</b> A new path containing only the <a href="#Grammar">
507  relative-path</a> portion of the source path.</p>
508  <p>Portably provides a copy of a path's relative portion, if any. See
509  <a href="#decomposition">Path decomposition examples</a>.</p>
510</blockquote>
511<h3><a name="leaf">leaf</a></h3>
512<blockquote>
513  <pre>std::string leaf() const;</pre>
514<p><b>Returns:</b> <code>empty() ? std::string() : m_name.back()</code></p>
515<p>A typical use is to obtain a file or directory name without path information
516from a path returned by a <a href="operations.htm#directory_iterator">
517directory_iterator</a>. See <a href="#decomposition">Path decomposition examples</a>.</p>
518</blockquote>
519<h3><a name="branch_path">branch_path</a></h3>
520<blockquote>
521  <pre>path branch_path() const;</pre>
522<p><b>Returns:</b> <code>m_name.size() &lt;= 1 ? path(&quot;&quot;) : x</code>, where <code>x</code> 
523is a path constructed from all the elements of <code>m_name</code> except the
524last.</p>
525<p>A typical use is to obtain the parent path for a path supplied by the user.
526See <a href="#decomposition">Path decomposition examples</a>.</p>
527</blockquote>
528<h3><a name="empty">empty</a></h3>
529<blockquote>
530  <pre>bool empty() const;</pre>
531<p><b>Returns:</b> <code>string().empty()</code>.</p>
532  <p>The <i>path::empty()</i> function determines if a path string itself is
533  empty. To determine if the file or directory identified by the path is empty,
534  use the <a href="operations.htm#is_empty">operations.hpp is_empty()</a> 
535  function.</p>
536  <p><b>Naming rationale:</b> C++ Standard Library containers use the <i>empty</i> 
537  name for the equivalent functions.</p>
538</blockquote>
539<h3><a name="is_complete">is_complete</a></h3>
540<blockquote>
541  <pre>bool is_complete() const;</pre>
542  <p><b>Returns:</b> For single-root operating systems, <code>has_root_directory()</code>.
543  For multi-root operating systems, <code>has_root_directory() &amp;&amp; 
544  has_root_name()</code>.</p>
545  <p><b>Naming rationale:</b> The alternate name, is_absolute(), causes
546  confusion and controversy because on multi-root operating systems some people
547  believe root_name() should participate in is_absolute(), and some
548  don't. See the <a href="faq.htm#absolute">FAQ</a>.</p>
549  <p><b><a name="is_complete_note">Note</a>:</b> On most operating systems, a
550  complete path always unambiguously identifies a specific file or directory. On a few
551  systems (classic Mac OS, for example), even a complete path may be ambiguous
552  in unusual cases because the OS does not require unambiguousness.</p>
553</blockquote>
554<h3><a name="has_root_path">has_root_path</a></h3>
555<blockquote>
556  <pre>bool has_root_path() const;</pre>
557  <p><b>Returns:</b> <code>has_root_name() || has_root_directory()</code></p>
558</blockquote>
559<h3><a name="has_root_name">has_root_name</a></h3>
560<blockquote>
561  <pre>bool has_root_name() const;</pre>
562  <p><b>Returns:</b> <code>!root_name().empty()</code></p>
563</blockquote>
564<h3><a name="has_root_directory">has_root_directory</a></h3>
565<blockquote>
566  <pre>bool has_root_directory() const;</pre>
567  <p><b>Returns:</b> <code>!root_directory().empty()</code></p>
568</blockquote>
569<h3><a name="has_relative_path">has_relative_path</a></h3>
570<blockquote>
571  <pre>bool has_relative_path() const;</pre>
572  <p><b>Returns:</b> <code>!relative_path().empty()</code></p>
573</blockquote>
574<h3><a name="has_leaf">has_leaf</a></h3>
575<blockquote>
576  <pre>bool has_leaf() const;</pre>
577  <p><b>Returns:</b> <code>!leaf().empty()</code></p>
578</blockquote>
579<h3><a name="has_branch_path">has_branch_path</a></h3>
580<blockquote>
581  <pre>bool has_branch_path() const;</pre>
582  <p><b>Returns:</b> <code>!branch_path().empty()</code></p>
583</blockquote>
584<h3><a name="iterator">iterator</a></h3>
585<blockquote>
586<p><code>typedef <i>implementation-defined</i> iterator;</code></p>
587<p>A const iterator meeting the C++ Standard Library requirements for bidirectional
588iterators (24.1). The iterator is a class type (so that operator++ and -- will
589work on temporaries). The value, reference, and pointer types are <i>std::string</i>,
590<i>const std::string &amp;</i>, and <i>const std::string *</i>, respectively.</p>
591</blockquote>
592<h3><a name="begin">begin</a></h3>
593<blockquote>
594<p><code>iterator begin() const;</code></p>
595<p><b>Returns:</b> <code>m_path.begin()</code></p>
596</blockquote>
597<h3><a name="end">end</a></h3>
598<blockquote>
599<p><code>iterator end() const;</code></p>
600<p><b>Returns:</b> <code>m_path.end()</code></p>
601</blockquote>
602<h3><a name="default_name_check_writable">default_name_check_writable</a></h3>
603<blockquote>
604<p><code>static bool default_name_check_writable();</code></p>
605<p><b>Returns:</b> True, unless a <i>default_name_check</i> function has been
606previously called. </p>
607</blockquote>
608<h3><a name="default_name_check">default_name_check</a></h3>
609<blockquote>
610<p><code>static void default_name_check( name_check new_check );</code></p>
611<p><b>Precondition:</b> new_check != 0</p>
612<p><b>Postcondition:</b> <code>default_name_check(new_check) &amp;&amp; !default_name_check_writable()</code></p>
613<p><b>Throws:</b> if <code>!default_name_check_writable()</code></p>
614<p><code>static name_check default_name_check();</code></p>
615<p><b>Returns:</b> the default name_check.</p>
616<p><b>Postcondition:</b> <code>!default_name_check_writable()</code></p>
617</blockquote>
618<h3><a name="operator_eq">operator</a> ==</h3>
619<blockquote>
620  <pre>bool operator==( const path &amp; that ) const;</pre>
621  <p><b>Returns:</b> <code>!(*this &lt; that) &amp;&amp; !(that &lt; *this)</code></p>
622  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
623</blockquote>
624<h3><a name="operator_ne">operator !=</a></h3>
625<blockquote>
626  <pre>bool operator!=( const path &amp; that ) const;</pre>
627  <p><b>Returns:</b> <code>!(*this == that)</code></p>
628  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
629</blockquote>
630<h3><a name="operator_lt">operator</a> &lt;</h3>
631<blockquote>
632  <pre>bool operator&lt;( const path &amp; that ) const;</pre>
633  <p><b>Returns:</b> <code>std::lexicographical_compare( begin(), end(),
634  that.begin(), that.end() )</code></p>
635  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
636  <p><b>Rationale:</b> Relational operators are provided to ease uses such as
637  specifying paths as keys in associative containers. Lexicographical comparison
638  is used because:</p>
639  <ol>
640    <li>Even though not a full-fledged standard container, paths are enough like
641    containers to merit meeting the C++ Standard Library's container comparison
642    requirements (23.1 table 65).</li>
643    <li>The alternative is to return <code>this-&gt;string(), that.string()</code>.
644    But path::string() as currently specified can yield non-unique results for
645    differing paths. The case (from Peter Dimov) is <code>path(&quot;first/&quot;)/&quot;second&quot;</code> 
646    and <code>path(&quot;first&quot;)/&quot;second&quot;</code> both returning a string() of <code>
647    &quot;first//second&quot;</code>.</li>
648  </ol>
649</blockquote>
650<h3><a name="operator_le">operator</a> &lt;=</h3>
651<blockquote>
652  <pre>bool operator&lt;=( const path &amp; that ) const;</pre>
653  <p><b>Returns:</b> <code>!(that &lt; *this)</code></p>
654  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
655</blockquote>
656<h3><a name="operator_gt">operator</a> &gt;</h3>
657<blockquote>
658  <pre>bool operator&gt;( const path &amp; that ) const;</pre>
659  <p><b>Returns:</b> <code>that &lt; *this</code></p>
660  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
661</blockquote>
662<h3><a name="operator_ge">operator</a> &gt;=</h3>
663<blockquote>
664  <pre>bool operator&gt;=( const path &amp; that ) const;</pre>
665  <p><b>Returns:</b> <code>!(*this &lt; that)</code></p>
666  <p>See <a href="#Path_equality">Path equality vs path equivalence</a>.</p>
667</blockquote>
668<h2><a name="Non-member_functions">Non-member functions</a></h2>
669<h3><a name="non-member_operator_shift">Non-member operator /</a></h3>
670<blockquote>
671<p><code>path operator / ( const char * lhs, const path &amp; rhs );<br>
672path operator / ( const std::string &amp; lhs, const path &amp; rhs );</code></p>
673<p><b>Returns:</b> <code>path( lhs ) /= rhs</code></p>
674</blockquote>
675<h2>Default <a name="name_check­_mechanism">name_check mechanism</a></h2>
676<p>It is difficult or impossible to write portable programs without some way to
677verify that directory and file names are portable. Without automatic name
678checking, verification is tedious, error prone, and ugly. Yet no single name
679check function can serve all applications, and within an application
680different paths or portions of paths may require different name check
681functions. Sometimes there should be no checking at all.</p>
682<p>Those needs are met by providing a default name check function to meet an
683application's most common needs, and then providing <i>path</i> constructors
684which override the default name check function to handle less common needs.
685The default name check function can be set by the application, allowing the
686most common case for the particular application to be handled by the default
687check. </p>
688<h3>Dangers</h3>
689<p>The default name check function is set and retrieved by <i>path</i> static
690member functions, and as such is similar to a global variable. Since global variables are
691considered harmful [<a href="design.htm#Wulf-Shaw-73">Wulf-Shaw-73</a>], class
692<i>path</i> allows the default name check function to be set only once, and
693only before the first use. This turns a dangerous global variable into a
694safer global constant. Even with this protection, the ability to set the default name check function is
695still a powerful feature, and is still dangerous in that it can change
696the behavior of code buried out-of-sight in libraries or elsewhere. Thus
697changing the default error check function should only be done when explicitly
698specifying the function via the two argument <i>path</i> constructors is not
699reasonable.</p>
700<h2><a name="Rationale">Rationale</a></h2>
701<p>Also see the <a href="faq.htm">FAQ</a> for additional rationale.</p>
702<p><b>Function <a name="Naming_Rationale">naming</a>:</b> Class <i>path</i> 
703member function names and <a href="operations.htm">operations.hpp</a> non-member
704function names were chosen to be somewhat distinct from one another. The
705objective was to avoid cases like <i>foo.empty()</i> and <i>empty( foo )</i> both being
706valid, but with completely different semantics. At one point <i>path::empty()</i> 
707was renamed <i>path::is_null()</i>, but that caused many coding typos because <i>
708std::string::empty()</i> is often used nearby.</p>
709<p><b>Decomposition functions:</b> Decomposition functions are provided because without them it is impossible to write portable path
710manipulations. Convenience is also a factor.</p>
711  <p><b>Const vs non-const returns:</b> In some earlier versions of the library,
712  member functions returned values as const rather than non-const.
713  See Scott Myers, <i>Effective C++</i>, Item 21. The const qualifiers were
714  eliminated (1) to conform with C++ Standard Library practice, (2) because
715  non-const returns allow occasionally useful expressions, and (3) because the
716  number of coding errors eliminated were deemed rare. A requirement that path::iterator be a  class type was added to eliminate non-const
717  iterator errors.</p>
718<h2>Path <a name="decomposition">decomposition</a> examples</h2>
719<p>It is often useful to extract specific elements from a path object.&nbsp; 
720While any decomposition can be achieved by iterating over the elements of a
721path, convenience functions are provided which are easier to use, more
722efficient, and less error prone.</p>
723<p>The first column of the table gives the example path, formatted by the
724string() function. The second column shows the values which would be returned by
725dereferencing each element iterator. The remaining columns show the results of
726various expressions.</p>
727<table border="1" cellpadding="5" cellspacing="0">
728  <tr>
729    <td><b>p.string()</b></td>
730    <td><b>Elements</b></td>
731    <td><b>p.root_<br>
732    path()<br>
733&nbsp;</b></td>
734    <td><b>p.root_<br>
735    name()</b></td>
736    <td><b>p.root_<br>
737    directory()</b></td>
738    <td><b>p.relative_<br>
739    path()</b></td>
740    <td><b>p.root_<br>
741    directory()<br>
742    / p.relative_<br>
743    path()</b></td>
744    <td><b>p.root_<br>
745    name() /<br>
746    p.relative_<br>
747    path()</b></td>
748    <td><b>p.branch_<br>
749    path()</b></td>
750    <td><b>p.leaf()</b></td>
751  </tr>
752  <tr>
753    <td><b>All systems</b></td>
754    <td>&nbsp;</td>
755    <td>&nbsp;</td>
756    <td>&nbsp;</td>
757    <td>&nbsp;</td>
758    <td>&nbsp;</td>
759    <td>&nbsp;</td>
760    <td>&nbsp;</td>
761    <td>&nbsp;</td>
762    <td>&nbsp;</td>
763  </tr>
764  <tr>
765    <td><code>/</code></td>
766    <td><code>/</code></td>
767    <td><code>/</code></td>
768    <td><code>&quot;&quot;</code></td>
769    <td><code>/</code></td>
770    <td><code>&quot;&quot;</code></td>
771    <td><code>/</code></td>
772    <td><code>&quot;&quot;</code></td>
773    <td><code>&quot;&quot;</code></td>
774    <td><code>/</code></td>
775  </tr>
776  <tr>
777    <td><code>foo</code></td>
778    <td><code>foo</code></td>
779    <td><code>&quot;&quot;</code></td>
780    <td><code>&quot;&quot;</code></td>
781    <td><code>&quot;&quot;</code></td>
782    <td><code>foo</code></td>
783    <td><code>foo</code></td>
784    <td><code>foo</code></td>
785    <td><code>&quot;&quot;</code></td>
786    <td><code>foo</code></td>
787  </tr>
788  <tr>
789    <td><code>/foo</code></td>
790    <td><code>/,foo</code></td>
791    <td><code>/</code></td>
792    <td><code>&quot;&quot;</code></td>
793    <td><code>/</code></td>
794    <td><code>foo</code></td>
795    <td><code>/foo</code></td>
796    <td><code>foo</code></td>
797    <td><code>/</code></td>
798    <td><code>foo</code></td>
799  </tr>
800  <tr>
801    <td><code>foo/bar</code></td>
802    <td><code>foo,bar</code></td>
803    <td><code>&quot;&quot;</code></td>
804    <td><code>&quot;&quot;</code></td>
805    <td><code>&quot;&quot;</code></td>
806    <td><code>foo/bar</code></td>
807    <td><code>foo/bar</code></td>
808    <td><code>foo/bar</code></td>
809    <td><code>foo</code></td>
810    <td><code>bar</code></td>
811  </tr>
812  <tr>
813    <td><code>/foo/bar</code></td>
814    <td><code>/,foo,bar</code></td>
815    <td><code>/</code></td>
816    <td><code>&quot;&quot;</code></td>
817    <td><code>/</code></td>
818    <td><code>foo/bar</code></td>
819    <td><code>/foo/bar</code></td>
820    <td><code>foo/bar</code></td>
821    <td><code>/foo</code></td>
822    <td><code>bar</code></td>
823  </tr>
824  <tr>
825    <td><b><code>.</code></b></td>
826    <td><code>.</code></td>
827    <td><code>&quot;&quot;</code></td>
828    <td><code>&quot;&quot;</code></td>
829    <td><code>&quot;&quot;</code></td>
830    <td><code>.</code></td>
831    <td><code>.</code></td>
832    <td><code>.</code></td>
833    <td><code>&quot;&quot;</code></td>
834    <td><code>.</code></td>
835  </tr>
836  <tr>
837    <td><b><code>..</code></b></td>
838    <td><code>..</code></td>
839    <td><code>&quot;&quot;</code></td>
840    <td><code>&quot;&quot;</code></td>
841    <td><code>&quot;&quot;</code></td>
842    <td><code>..</code></td>
843    <td><code>..</code></td>
844    <td><code>..</code></td>
845    <td><code>&quot;&quot;</code></td>
846    <td><code>..</code></td>
847  </tr>
848  <tr>
849    <td><code>../foo</code></td>
850    <td><code>..,foo</code></td>
851    <td><code>&quot;&quot;</code></td>
852    <td><code>&quot;&quot;</code></td>
853    <td><code>&quot;&quot;</code></td>
854    <td><code>../foo</code></td>
855    <td><code>../foo</code></td>
856    <td><code>../foo</code></td>
857    <td><code>..</code></td>
858    <td><code>foo</code></td>
859  </tr>
860  <tr>
861    <td><b>Windows</b></td>
862    <td>&nbsp;</td>
863    <td>&nbsp;</td>
864    <td>&nbsp;</td>
865    <td>&nbsp;</td>
866    <td>&nbsp;</td>
867    <td>&nbsp;</td>
868    <td>&nbsp;</td>
869    <td>&nbsp;</td>
870    <td>&nbsp;</td>
871  </tr>
872  <tr>
873    <td><code>c:</code></td>
874    <td><code>c:</code></td>
875    <td><code>c:</code></td>
876    <td><code>c:</code></td>
877    <td><code>&quot;&quot;</code></td>
878    <td><code>&quot;&quot;</code></td>
879    <td><code>&quot;&quot;</code></td>
880    <td><code>c:</code></td>
881    <td><code>&quot;&quot;</code></td>
882    <td><code>c:</code></td>
883  </tr>
884  <tr>
885    <td><code>c:/</code></td>
886    <td><code>c:,/</code></td>
887    <td><code>c:/</code></td>
888    <td><code>c:</code></td>
889    <td><code>/</code></td>
890    <td><code>&quot;&quot;</code></td>
891    <td><code>/</code></td>
892    <td><code>c:</code></td>
893    <td><code>c:</code></td>
894    <td><code>/</code></td>
895  </tr>
896  <tr>
897    <td><code>c:..</code></td>
898    <td><code>c:,..</code></td>
899    <td><code>c:</code></td>
900    <td><code>c:</code></td>
901    <td><code>&quot;&quot;</code></td>
902    <td><code>..</code></td>
903    <td><code>c:..</code></td>
904    <td><code>c:..</code></td>
905    <td><code>c:</code></td>
906    <td><code>..</code></td>
907  </tr>
908  <tr>
909    <td><code>c:foo</code></td>
910    <td><code>c:,foo</code></td>
911    <td><code>c:</code></td>
912    <td><code>c:</code></td>
913    <td><code>&quot;&quot;</code></td>
914    <td><code>foo</code></td>
915    <td><code>foo</code></td>
916    <td><code>c:foo</code></td>
917    <td><code>c:</code></td>
918    <td><code>foo</code></td>
919  </tr>
920  <tr>
921    <td><code>c:/foo</code></td>
922    <td><code>c:,/,foo</code></td>
923    <td><code>c:/</code></td>
924    <td><code>c:</code></td>
925    <td><code>/</code></td>
926    <td><code>foo</code></td>
927    <td><code>/foo</code></td>
928    <td><code>c:foo</code></td>
929    <td><code>c:/</code></td>
930    <td><code>foo</code></td>
931  </tr>
932  <tr>
933    <td><code>//shr</code></td>
934    <td><code>//shr</code></td>
935    <td><code>//shr</code></td>
936    <td><code>//shr</code></td>
937    <td><code>&quot;&quot;</code></td>
938    <td><code>&quot;&quot;</code></td>
939    <td><code>&quot;&quot;</code></td>
940    <td><code>//shr</code></td>
941    <td><code>&quot;&quot;</code></td>
942    <td><code>//shr</code></td>
943  </tr>
944  <tr>
945    <td><code>//shr/</code></td>
946    <td><code>//shr,/</code></td>
947    <td><code>//shr/</code></td>
948    <td><code>//shr</code></td>
949    <td><code>/</code></td>
950    <td><code>&quot;&quot;</code></td>
951    <td><code>/</code></td>
952    <td><code>//shr</code></td>
953    <td><code>//shr</code></td>
954    <td><code>/</code></td>
955  </tr>
956  <tr>
957    <td><code>//shr/foo</code></td>
958    <td><code>//shr,<br>
959    /,foo</code></td>
960    <td><code>//shr/</code></td>
961    <td><code>//shr</code></td>
962    <td><code>/</code></td>
963    <td><code>foo</code></td>
964    <td><code>/foo</code></td>
965    <td><code>//shr/foo</code></td>
966    <td><code>//shr/</code></td>
967    <td><code>foo</code></td>
968  </tr>
969  <tr>
970    <td><code>prn:</code></td>
971    <td><code>prn:</code></td>
972    <td><code>prn:</code></td>
973    <td><code>prn:</code></td>
974    <td><code>&quot;&quot;</code></td>
975    <td><code>&quot;&quot;</code></td>
976    <td><code>&quot;&quot;</code></td>
977    <td><code>prn:</code></td>
978    <td><code>&quot;&quot;</code></td>
979    <td><code>prn:</code></td>
980  </tr>
981</table>
982<hr>
983<p>Revised
984<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->02 August, 2005<!--webbot bot="Timestamp" endspan i-checksum="34600" --></p>
985
986<p>© Copyright Beman Dawes, 2002</p>
987<p> Use, modification, and distribution are subject to the Boost Software
988License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
989LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
990www.boost.org/LICENSE_1_0.txt</a>)</p>
991
992</body>
993
994</html>
Note: See TracBrowser for help on using the repository browser.