refresh path functionality and names

[SVN r16446]
This commit is contained in:
Beman Dawes
2002-11-27 19:26:45 +00:00
parent c09ff41675
commit 028b2f3140
8 changed files with 343 additions and 122 deletions

View File

@@ -9,9 +9,8 @@ FAQ</h1>
since URI's extend far beyond what most operating systems consider a file or a
directory.&nbsp; Thus for the primary &quot;portable script-style file system
operations&quot; requirement of the Filesystem Library, full URI's appear to be over-specification.</p>
<p><b>Why base the generic-path string format on POSIX?<br>
<br>
</b>POSIX is the basis for the most familiar path-string formats, including the
<p><b>Why base the generic-path string format on POSIX?</b></p>
<p>POSIX is the basis for the most familiar path-string formats, including the
URL portion of URI's and the native Windows format. It is ubiquitous and
familiar.&nbsp; On many systems, it is very easy to implement because it is
either the native operating system format (Unix and Windows) or via a
@@ -23,6 +22,14 @@ POSIX library (z/OS, OS/390, and many more.)</p>
Several early versions did require users to identify each path as a file or
directory path, and this seemed to increase errors and decrease code
readability. There was no apparent upside benefit. </p>
<p><b>Why do some <i>path</i> member function names have a &quot;system_specific_&quot; prefix?</b></p>
<p>To alert users that the results are inherently non-portable. The names are
deliberately ugly to discourage use except where really necessary.</p>
<p><b>Why doesn't path supply operator== and other comparison operators?</b></p>
<p>There is no way to know if two <i>path</i> objects actually represent the
same path.&nbsp; For example, <i>path(&quot;/foo&quot;)</i> and <i>path(&quot;../foo&quot;)</i> may
represent the same path, even though they are textually different. <i>
path::string()'s</i> can be used for textual comparison.</p>
<p><b>Why not support a concept of specific kinds file systems, such as
posix_file_system or windows_file_system.</b></p>
<p>Portability is one of the one or two most important requirements for the
@@ -153,10 +160,7 @@ conditions for error are very different between the source and the target.</p>
detection were evaluated, including at least four complete implementations.&nbsp;
While the details for rejection differed, they all tended to distort the
otherwise simple design of the rest of the library.</p>
<p><b>Why do some path member function names have a &quot;system_specific_&quot; prefix?</b></p>
<p>To alert users that the results are inherently non-portable. The names are
deliberately ugly to discourage use except where really necessary.</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->20 November, 2002<!--webbot bot="Timestamp" endspan i-checksum="39352" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->26 November, 2002<!--webbot bot="Timestamp" endspan i-checksum="39364" --></p>

View File

@@ -179,11 +179,11 @@ ensure names in paths are as portable as desired, but they must be explicitly
called by the user.</p>
<p><b><a name="Naming Rationale">Naming Rationale</a>:</b> Class <i>path</i>
member function names and <a href="operations.htm">operations.hpp</a> non-member
function names are chosen to be distinct from one another. Otherwise, given a
path <i>foo</i>, for example, both <i>foo.empty()</i> and <i>empty( foo )</i>
would be valid, but with completely different semantics. Avoiding this was
considered more important than consistency with some C++ Standard Library naming
conventions, which aren't followed uniformly anyhow, even in the standard.</p>
function names were chosen to be somewhat distinct from one another. The
objective was to avoid both <i>foo.empty()</i> and <i>empty( foo )</i> 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>
<h3><a name="System-specific Representation">System-specific Representation</a></h3>
<p>Several <i>path</i> non-member functions return representations of <i>m_name</i>
in formats specific to the operating system. These formats are implementation
@@ -603,7 +603,7 @@ efficient, and less error prone.</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->24 November, 2002<!--webbot bot="Timestamp" endspan i-checksum="39360" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->26 November, 2002<!--webbot bot="Timestamp" endspan i-checksum="39364" --></p>
</body>

View File

@@ -74,6 +74,7 @@ namespace boost
namespace detail
{
const char * implementation_name(); // helps testing to know name
bool single_rooted_filesystem();
}
// directory_iterator ------------------------------------------------------//

View File

@@ -76,15 +76,17 @@ namespace boost
path branch_path() const;
// query functions:
bool is_null() const { return m_path.size() == 0; }
bool is_absolute() const;
bool empty() const { return m_path.empty(); } // name consistent with std containers
/*
bool has_root_path() const;
bool is_complete() const; // has_root_directory [&& has_system_specific_root()]
bool has_root_path() const; // has_system_specific_root() || has_root_directory()
bool has_system_specific_root() const;
bool has_root_directory() const;
bool has_relative_path() const;
*/
bool has_leaf() const { return !m_path.empty(); }
bool has_branch_path() const;
const std::string & string() const { return m_path; }
std::string system_specific_file_string() const;

View File

@@ -112,6 +112,7 @@ namespace
BOOST_HANDLE & handle, BOOST_SYSTEM_DIRECTORY_TYPE & data )
// Returns: 0 if error, otherwise name
{
// std::cout << "find_first_file " << dir << std::endl;
std::string dirpath( std::string(dir) + "/*" );
return ( (handle = ::FindFirstFileA( dirpath.c_str(), &data ))
== BOOST_INVALID_HANDLE_VALUE ) ? 0 : data.cFileName;
@@ -119,6 +120,7 @@ namespace
inline void find_close( BOOST_HANDLE handle )
{
// std::cout << "find_close" << std::endl;
assert( handle != BOOST_INVALID_HANDLE_VALUE );
::FindClose( handle );
}
@@ -174,8 +176,10 @@ namespace boost
{
#ifdef BOOST_POSIX
const char * implementation_name() { return "POSIX"; }
bool single_rooted_filesystem() { return true; }
#else
const char * implementation_name() { return "Windows"; }
bool single_rooted_filesystem() { return false; }
#endif
} // namespace detail
@@ -204,7 +208,7 @@ namespace boost
m_imp.reset( new dir_itr_imp );
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name;
if ( dir_path.is_null() )
if ( dir_path.empty() )
m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
else
name = find_first_file( dir_path.system_specific_directory_string().c_str(),
@@ -423,7 +427,7 @@ namespace boost
const path & initial_path()
{
static path init_path;
if ( init_path.is_null() ) init_path = current_path();
if ( init_path.empty() ) init_path = current_path();
return init_path;
}

View File

@@ -167,7 +167,7 @@ namespace boost
&& name.find_first_not_of( valid_boost_directory ) == std::string::npos;
}
// path implementation -------------------------------------------------//
// path implementation -----------------------------------------------------//
path::path( const std::string & src )
{
@@ -269,7 +269,7 @@ namespace boost
{
// append '/' if needed
if ( !is_null()
if ( !empty()
&& *(m_path.end()-1) != ':' && *(m_path.end()-1) != '/' )
m_path += '/';
@@ -343,6 +343,8 @@ namespace boost
} // while more elements
}
// path decomposition functions ---------------------------------------------//
path::iterator path::begin() const
{
iterator itr;
@@ -358,6 +360,24 @@ namespace boost
m_path += new_leaf;
}
/*
path & path::make_absolute( const path & root_source )
{
assert( root_source.is_absolute() );
if ( !is_absolute() )
{
path tmp( root_source.root_path() );
tmp /= relative_path();
operator=( tmp );
}
return *this;
}
path & path::make_absolute()
{
return make_absolute( initial_path() );
}
*/
std::string path::leaf() const
{
return m_path.substr( leaf_pos( m_path, m_path.size() ) );
@@ -397,20 +417,6 @@ namespace boost
return path( m_path.substr( 0, end_pos ), system_specific );
}
bool path::is_absolute() const
{
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 2
&& m_path[1] == ':'
&& m_path[2] == '/' ) // "c:/"
|| ( m_path.size() > 3
&& m_path[m_path.size()-1] == ':' ) // "device:"
# endif
;
}
path path::relative_path() const
{
std::string::size_type pos( 0 );
@@ -468,7 +474,73 @@ namespace boost
# endif
}
namespace detail
// path query functions -----------------------------------------------------//
bool path::is_complete() const
{
# ifdef BOOST_WINDOWS
return m_path.size() > 2
&& ( (m_path[1] == ':' && m_path[2] == '/') // "c:/"
|| (m_path[0] == '/' && m_path[1] == '/') // "//share"
|| m_path[m_path.size()-1] == ':' );
# else
return m_path.size() && m_path[0] == '/';
# endif
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 1 && m_path[1] == ':' ) // "c:" and "c:/"
|| ( m_path.size() > 3
&& m_path[m_path.size()-1] == ':' ) // "device:"
# endif
;
}
bool path::has_root_path() const
{
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 1 && m_path[1] == ':' ) // "c:" and "c:/"
|| ( m_path.size() > 3
&& m_path[m_path.size()-1] == ':' ) // "device:"
# endif
;
}
bool path::has_system_specific_root() const
{
# ifdef BOOST_WINDOWS
return m_path.size() > 1
&& ( m_path[1] == ':' // "c:"
|| m_path[m_path.size()-1] == ':' // "prn:"
|| (m_path[0] == '/' && m_path[1] == '/') // "//share"
);
# else
return false;
# endif
}
bool path::has_root_directory() const
{
return ( m_path.size()
&& m_path[0] == '/' ) // covers both "/" and "//share"
# ifdef BOOST_WINDOWS
|| ( m_path.size() > 2
&& m_path[1] == ':' && m_path[2] == '/' ) // "c:/"
# endif
;
}
bool path::has_relative_path() const { return !relative_path().empty(); }
bool path::has_branch_path() const { return !branch_path().empty(); }
// path_itr_imp implementation ----------------------------------------------//
namespace detail
{
void path_itr_imp::operator++()
{

View File

@@ -75,6 +75,10 @@ int test_main( int, char * [] )
<< fs::initial_path().system_specific_file_string()
<< "\"\n";
BOOST_TEST( fs::initial_path().is_complete() );
BOOST_TEST( fs::current_path().is_complete() );
BOOST_TEST( fs::initial_path().string() == fs::current_path().string() );
fs::path dir( fs::initial_path() / "temp_fs_test_directory" );
if ( std::strcmp( fs::detail::implementation_name(), "Windows" ) == 0 )
@@ -125,14 +129,26 @@ int test_main( int, char * [] )
BOOST_TEST( dir_itr->leaf() == "d1" || dir_itr->leaf() == "d2" );
if ( dir_itr->leaf() == "d1" )
{
// Thomas Witt suggested the ++ to verify a compiler problem workaround
// BOOST_TEST( (++fs::directory_iterator(dir))->leaf() == "d2" );
++dir_itr;
BOOST_TEST( (++dir_itr)->leaf() == "d2" );
}
else
{
BOOST_TEST( (++dir_itr)->leaf() == "d1" );
}
}
{ // *i++ must work to meet the standard's InputIterator requirements
fs::directory_iterator dir_itr( dir );
BOOST_TEST( dir_itr->leaf() == "d1" || dir_itr->leaf() == "d2" );
if ( dir_itr->leaf() == "d1" )
{
BOOST_TEST( (*dir_itr++).leaf() == "d1" );
BOOST_TEST( dir_itr->leaf() == "d2" );
}
else
{
BOOST_TEST( (++fs::directory_iterator(dir))->leaf() == "d1" );
BOOST_TEST( (*dir_itr++).leaf() == "d2" );
BOOST_TEST( dir_itr->leaf() == "d1" );
}
}

View File

@@ -64,6 +64,7 @@ int test_main( int, char*[] )
path p1( "fe/fi/fo/fum" );
path p2( p1 );
path p3;
BOOST_TEST( p1.string() != p3.string() );
p3 = p2;
// p1.branch_path() = p2; // should fail
@@ -83,8 +84,8 @@ int test_main( int, char*[] )
BOOST_TEST( path( "foo" ).branch_path().string() == "" );
BOOST_TEST( p1.leaf() == "fum" );
BOOST_TEST( p1.branch_path().string() == "fe/fi/fo" );
BOOST_TEST( path( "" ).is_null() == true );
BOOST_TEST( path( "foo" ).is_null() == false );
BOOST_TEST( path( "" ).empty() == true );
BOOST_TEST( path( "foo" ).empty() == false );
PATH_CHECK( "", "" );
@@ -233,40 +234,97 @@ int test_main( int, char*[] )
BOOST_TEST( *prior( itr_ck.end() ) == std::string( "foo" ) );
BOOST_TEST( prior( itr_ck.end() ) == itr_ck.begin() );
BOOST_TEST( path( "/" ).relative_path().string() == "" );
BOOST_TEST( path( "/" ).branch_path().string() == "" );
BOOST_TEST( path( "/" ).leaf() == "/" );
BOOST_TEST( path( "/" ).system_specific_root() == "" );
BOOST_TEST( path( "/" ).root_directory() == "/" );
BOOST_TEST( path( "/" ).root_path().string() == "/" );
path p;
BOOST_TEST( path( "foo" ).relative_path().string() == "foo" );
BOOST_TEST( path( "foo" ).branch_path().string() == "" );
BOOST_TEST( path( "foo" ).leaf() == "foo" );
BOOST_TEST( path( "foo" ).system_specific_root() == "" );
BOOST_TEST( path( "foo" ).root_directory() == "" );
BOOST_TEST( path( "foo" ).root_path().string() == "" );
p = "";
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "" );
BOOST_TEST( !p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( !p.has_leaf() );
BOOST_TEST( !p.has_branch_path() );
BOOST_TEST( !p.is_complete() );
BOOST_TEST( path( "/foo" ).relative_path().string() == "foo" );
BOOST_TEST( path( "/foo" ).branch_path().string() == "/" );
BOOST_TEST( path( "/foo" ).leaf() == "foo" );
BOOST_TEST( path( "/foo" ).system_specific_root() == "" );
BOOST_TEST( path( "/foo" ).root_directory() == "/" );
BOOST_TEST( path( "/foo" ).root_path().string() == "/" );
p = "/";
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "/" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( !p.has_branch_path() );
BOOST_TEST( fs::detail::single_rooted_filesystem() == p.is_complete() );
BOOST_TEST( path( "foo/bar" ).relative_path().string() == "foo/bar" );
BOOST_TEST( path( "foo/bar" ).branch_path().string() == "foo" );
BOOST_TEST( path( "foo/bar" ).leaf() == "bar" );
BOOST_TEST( path( "foo/bar" ).system_specific_root() == "" );
BOOST_TEST( path( "foo/bar" ).root_directory() == "" );
BOOST_TEST( path( "foo/bar" ).root_path().string() == "" );
p = "foo";
BOOST_TEST( p.relative_path().string() == "foo" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "foo" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "" );
BOOST_TEST( !p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( !p.has_branch_path() );
BOOST_TEST( !p.is_complete() );
BOOST_TEST( path( "/foo/bar" ).relative_path().string() == "foo/bar" );
BOOST_TEST( path( "/foo/bar" ).branch_path().string() == "/foo" );
BOOST_TEST( path( "/foo/bar" ).leaf() == "bar" );
BOOST_TEST( path( "/foo/bar" ).system_specific_root() == "" );
BOOST_TEST( path( "/foo/bar" ).root_directory() == "/" );
BOOST_TEST( path( "/foo/bar" ).root_path().string() == "/" );
p = "/foo";
BOOST_TEST( p.relative_path().string() == "foo" );
BOOST_TEST( p.branch_path().string() == "/" );
BOOST_TEST( p.leaf() == "foo" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( fs::detail::single_rooted_filesystem() == p.is_complete() );
p = "foo/bar";
BOOST_TEST( p.relative_path().string() == "foo/bar" );
BOOST_TEST( p.branch_path().string() == "foo" );
BOOST_TEST( p.leaf() == "bar" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "" );
BOOST_TEST( !p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( !p.is_complete() );
p = "/foo/bar";
BOOST_TEST( p.relative_path().string() == "foo/bar" );
BOOST_TEST( p.branch_path().string() == "/foo" );
BOOST_TEST( p.leaf() == "bar" );
BOOST_TEST( p.system_specific_root() == "" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( !p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( fs::detail::single_rooted_filesystem() == p.is_complete() );
if ( std::strcmp( fs::detail::implementation_name(), "Windows" ) == 0 )
{
@@ -288,61 +346,125 @@ int test_main( int, char*[] )
PATH_CHECK( path( "c:/foo", fs::system_specific ), "c:/foo" );
PATH_CHECK( path( "prn:", fs::system_specific ), "prn:" );
BOOST_TEST( path( "c:", fs::system_specific ).relative_path().string() == "" );
BOOST_TEST( path( "c:", fs::system_specific ).branch_path().string() == "" );
BOOST_TEST( path( "c:", fs::system_specific ).leaf() == "c:" );
BOOST_TEST( path( "c:", fs::system_specific ).system_specific_root() == "c:" );
BOOST_TEST( path( "c:", fs::system_specific ).root_directory() == "" );
BOOST_TEST( path( "c:", fs::system_specific ).root_path().string() == "c:" );
p = path( "c:", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "c:" );
BOOST_TEST( p.system_specific_root() == "c:" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "c:" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( !p.has_branch_path() );
BOOST_TEST( !p.is_complete() );
BOOST_TEST( path( "c:foo", fs::system_specific ).relative_path().string() == "foo" );
BOOST_TEST( path( "c:foo", fs::system_specific ).branch_path().string() == "c:" );
BOOST_TEST( path( "c:foo", fs::system_specific ).leaf() == "foo" );
BOOST_TEST( path( "c:foo", fs::system_specific ).system_specific_root() == "c:" );
BOOST_TEST( path( "c:foo", fs::system_specific ).root_directory() == "" );
BOOST_TEST( path( "c:foo", fs::system_specific ).root_path().string() == "c:" );
p = path( "c:foo", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "foo" );
BOOST_TEST( p.branch_path().string() == "c:" );
BOOST_TEST( p.leaf() == "foo" );
BOOST_TEST( p.system_specific_root() == "c:" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "c:" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( !p.is_complete() );
p = path( "c:/", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "c:" );
BOOST_TEST( p.leaf() == "/" );
BOOST_TEST( p.system_specific_root() == "c:" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "c:/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( p.is_complete() );
BOOST_TEST( path( "c:/", fs::system_specific ).relative_path().string() == "" );
BOOST_TEST( path( "c:/", fs::system_specific ).branch_path().string() == "c:" );
BOOST_TEST( path( "c:/", fs::system_specific ).leaf() == "/" );
BOOST_TEST( path( "c:/", fs::system_specific ).system_specific_root() == "c:" );
BOOST_TEST( path( "c:/", fs::system_specific ).root_directory() == "/" );
BOOST_TEST( path( "c:/", fs::system_specific ).root_path().string() == "c:/" );
p = path( "c:/foo", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "foo" );
BOOST_TEST( p.branch_path().string() == "c:/" );
BOOST_TEST( p.leaf() == "foo" );
BOOST_TEST( p.system_specific_root() == "c:" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "c:/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( p.is_complete() );
BOOST_TEST( path( "c:/foo", fs::system_specific ).relative_path().string() == "foo" );
BOOST_TEST( path( "c:/foo", fs::system_specific ).branch_path().string() == "c:/" );
BOOST_TEST( path( "c:/foo", fs::system_specific ).leaf() == "foo" );
BOOST_TEST( path( "c:/foo", fs::system_specific ).system_specific_root() == "c:" );
BOOST_TEST( path( "c:/foo", fs::system_specific ).root_directory() == "/" );
BOOST_TEST( path( "c:/foo", fs::system_specific ).root_path().string() == "c:/" );
p = path( "//share", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "//share" );
BOOST_TEST( p.system_specific_root() == "//share" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "//share/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( p.is_complete() );
BOOST_TEST( path( "//share", fs::system_specific ).relative_path().string() == "" );
BOOST_TEST( path( "//share", fs::system_specific ).branch_path().string() == "" );
BOOST_TEST( path( "//share", fs::system_specific ).leaf() == "//share" );
BOOST_TEST( path( "//share", fs::system_specific ).system_specific_root() == "//share" );
BOOST_TEST( path( "//share", fs::system_specific ).root_directory() == "/" );
BOOST_TEST( path( "//share", fs::system_specific ).root_path().string() == "//share/" );
p = path( "//share/", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "//share" );
BOOST_TEST( p.leaf() == "/" );
BOOST_TEST( p.system_specific_root() == "//share" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "//share/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( p.is_complete() );
BOOST_TEST( path( "//share/", fs::system_specific ).relative_path().string() == "" );
BOOST_TEST( path( "//share/", fs::system_specific ).branch_path().string() == "//share" );
BOOST_TEST( path( "//share/", fs::system_specific ).leaf() == "/" );
BOOST_TEST( path( "//share/", fs::system_specific ).system_specific_root() == "//share" );
BOOST_TEST( path( "//share/", fs::system_specific ).root_directory() == "/" );
BOOST_TEST( path( "//share/", fs::system_specific ).root_path().string() == "//share/" );
p = path( "//share/foo", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "foo" );
BOOST_TEST( p.branch_path().string() == "//share/" );
BOOST_TEST( p.leaf() == "foo" );
BOOST_TEST( p.system_specific_root() == "//share" );
BOOST_TEST( p.root_directory() == "/" );
BOOST_TEST( p.root_path().string() == "//share/" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( p.has_root_directory() );
BOOST_TEST( p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( p.has_branch_path() );
BOOST_TEST( p.is_complete() );
BOOST_TEST( path( "//share/foo", fs::system_specific ).relative_path().string() == "foo" );
BOOST_TEST( path( "//share/foo", fs::system_specific ).branch_path().string() == "//share/" );
BOOST_TEST( path( "//share/foo", fs::system_specific ).leaf() == "foo" );
BOOST_TEST( path( "//share/foo", fs::system_specific ).system_specific_root() == "//share" );
BOOST_TEST( path( "//share/foo", fs::system_specific ).root_directory() == "/" );
BOOST_TEST( path( "//share/foo", fs::system_specific ).root_path().string() == "//share/" );
BOOST_TEST( path( "prn:", fs::system_specific ).relative_path().string() == "" );
BOOST_TEST( path( "prn:", fs::system_specific ).branch_path().string() == "" );
BOOST_TEST( path( "prn:", fs::system_specific ).leaf() == "prn:" );
BOOST_TEST( path( "prn:", fs::system_specific ).system_specific_root() == "prn:" );
BOOST_TEST( path( "prn:", fs::system_specific ).root_directory() == "" );
BOOST_TEST( path( "prn:", fs::system_specific ).root_path().string() == "prn:" );
p = path( "prn:", fs::system_specific );
BOOST_TEST( p.relative_path().string() == "" );
BOOST_TEST( p.branch_path().string() == "" );
BOOST_TEST( p.leaf() == "prn:" );
BOOST_TEST( p.system_specific_root() == "prn:" );
BOOST_TEST( p.root_directory() == "" );
BOOST_TEST( p.root_path().string() == "prn:" );
BOOST_TEST( p.has_root_path() );
BOOST_TEST( p.has_system_specific_root() );
BOOST_TEST( !p.has_root_directory() );
BOOST_TEST( !p.has_relative_path() );
BOOST_TEST( p.has_leaf() );
BOOST_TEST( !p.has_branch_path() );
BOOST_TEST( p.is_complete() );
itr_ck = path( "c:", fs::system_specific );
BOOST_TEST( *itr_ck.begin() == std::string( "c:" ) );