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