Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50399 - in sandbox/filesystem-v3: boost/filesystem libs/filesystem/src libs/filesystem/test
From: bdawes_at_[hidden]
Date: 2008-12-29 09:10:45


Author: bemandawes
Date: 2008-12-29 09:10:44 EST (Mon, 29 Dec 2008)
New Revision: 50399
URL: http://svn.boost.org/trac/boost/changeset/50399

Log:
filesystem.v3: refactoring work-in-progress
Text files modified:
   sandbox/filesystem-v3/boost/filesystem/path.hpp | 335 ++++++++++-----------
   sandbox/filesystem-v3/libs/filesystem/src/operations.cpp | 15
   sandbox/filesystem-v3/libs/filesystem/src/path.cpp | 454 +++++++++++++++++------------
   sandbox/filesystem-v3/libs/filesystem/test/path_unit_test.cpp | 601 +++++++++++++++++++++------------------
   4 files changed, 760 insertions(+), 645 deletions(-)

Modified: sandbox/filesystem-v3/boost/filesystem/path.hpp
==============================================================================
--- sandbox/filesystem-v3/boost/filesystem/path.hpp (original)
+++ sandbox/filesystem-v3/boost/filesystem/path.hpp 2008-12-29 09:10:44 EST (Mon, 29 Dec 2008)
@@ -17,6 +17,7 @@
                               TO DO
 
    * Windows, POSIX, conversions for char16_t, char32_t for supporting compilers.
+ * Windows, POSIX, conversions for user-defined types.
    * Add Alternate Data Stream test cases. See http://en.wikipedia.org/wiki/NTFS Features.
    * test case: relational on paths differing only in trailing separator. rationale?
    * Behavior of root_path() has been changed. Change needs to be propagated to trunk.
@@ -137,70 +138,22 @@
 
     BOOST_FILESYSTEM_DECL extern const std::locale * path_locale;
 
-# ifdef BOOST_WINDOWS_PATH
-
- const wchar_t separator = L'/';
- const wchar_t preferred_separator = L'\\';
- const wchar_t * const separators = L"/\\";
- const wchar_t colon = L':';
- const wchar_t dot = L'.';
-
-# else // BOOST_POSIX_PATH
-
- const char separator = '/';
- const char preferred_separator = '/';
- const char * const separators = "/";
- const char colon = ':';
- const char dot = '.';
-
-# endif
-
 # ifdef BOOST_WINDOWS_API
 
     typedef std::wstring string_type;
     typedef string_type::value_type value_type;
     typedef string_type::size_type size_type;
 
- // class path has a number of generic functions that are implemented by
- // detail::convert_append() or detail::convert(). detail::convert_append()
- // functions called indirectly via detail::convert_append_helper() functions
- // to reduce the number of overloads required. Overloads are supplied
- // for all supported character array types to string_type.
-
- // ----- char[] to wstring -----
-
     BOOST_FILESYSTEM_DECL
- void convert_append( const char * begin,
+ void append( const char * begin,
                          const char * end, // 0 for null terminated MBCS
                          std::wstring & target,
                          system::error_code & ec );
 
- inline void convert_append( const char * begin, std::wstring & target,
- system::error_code & ec )
- {
- convert_append( begin, 0, target, ec );
- }
-
- // ----- wchar_t[] to wstring -----
-
- inline void convert_append( const wchar_t * begin, const wchar_t * end,
- std::wstring & target, system::error_code & ec )
- {
- ec.clear();
- target.assign( begin, end ); // but what if throws bad_alloc?
- }
-
- inline void convert_append( const wchar_t * begin, std::wstring & target,
- system::error_code & ec )
- {
- ec.clear();
- target += begin; // but what if throws bad_alloc?
- }
-
     // ----- convert ----
 
     BOOST_FILESYSTEM_DECL
- std::string convert( const std::wstring & src, system::error_code & ec );
+ std::string convert_to_string( const std::wstring & src, system::error_code & ec );
 
 # else // BOOST_POSIX_API
  
@@ -212,7 +165,7 @@
 
     // ----- char[] to string -----
 
- inline void convert_append( const char * begin,
+ inline void append( const char * begin,
                          const char * end, // 0 for null terminated MBCS
                          std::string & target,
                          system::error_code & ec )
@@ -221,7 +174,7 @@
       target.assign( begin, end ); // but what if this throws bad_alloc?
     }
 
- inline void convert_append( const char * begin, std::string & target,
+ inline void append( const char * begin, std::string & target,
       system::error_code & ec )
     {
       ec.clear();
@@ -232,121 +185,127 @@
 
     // ----- wchar_t[] to string -----
 
- inline void convert_append( const wchar_t * begin, const wchar_t * end,
+ inline void append( const wchar_t * begin, const wchar_t * end,
       std::string & target, system::error_code & ec );
 
- inline void convert_append( const wchar_t * begin, std::string & target,
+ inline void append( const wchar_t * begin, std::string & target,
       system::error_code & ec )
     {
- convert_append( begin, 0, target, ec );
+ append( begin, 0, target, ec );
     }
 
     // ----- convert ----
 
     BOOST_FILESYSTEM_DECL
- std::wstring convert( const std::string & src, system::error_code & ec );
+ std::wstring convert_to_wstring( const std::string & src, system::error_code & ec );
 
 # endif
 
 # endif // BOOST_POSIX_API
 
- // helpers ---------------------------------------------------------------//
+} // namespace detail
 
- inline bool is_separator( value_type c )
- {
- return c == separator
-# ifdef BOOST_WINDOWS_PATH
- || c == L'\\'
-# endif
- ;
- }
+ //------------------------------------------------------------------------------------//
+ // //
+ // path_traits //
+ // //
+ // Specializations are provided for char, wchar_t, char16_t, and char32_t value //
+ // types and their related string and iterator types. //
+ // //
+ // Users are permitted to add specializations for additional types. //
+ // //
+ //------------------------------------------------------------------------------------//
 
- // These helpers factor out common code, convert iterators to pointers,
- // and add the locale. Thus they reduce the number of detail::convert_append
- // overloads required.
+namespace path_traits
+{
 
- template< class InputIterator >
- inline void convert_append_helper( InputIterator begin,
- string_type & target, system::error_code & ec )
- {
- BOOST_ASSERT( &*begin );
- convert_append( &*begin, target, ec );
- }
+ template< class I > struct is_iterator { static const bool value = false; };
+ template< class C > struct is_container { static const bool value = false; };
 
- template< class FowardIterator >
- inline void convert_append_helper( FowardIterator begin, FowardIterator end,
- string_type & target, system::error_code & ec )
- {
- if ( begin == end ) return;
- BOOST_ASSERT( &*begin );
- convert_append( &*begin,
- &*begin + std::distance( begin, end ), // avoid dereference of end iterator
- target, ec );
- }
+ template< class charT > // specialization optional
+ inline void append( const charT * begin, // requires: null termination
+ detail::string_type & target, system::error_code & ec )
+ {
+ append( begin, 0, target, ec );
+ }
 
- BOOST_FILESYSTEM_DECL
- void first_element(
- const string_type & src,
- size_type & element_pos,
- size_type & element_size,
- # if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1
- size_type size = string_type::npos
- # else
- size_type size = -1
- # endif
- );
+ template< class charT > // specialization required
+ void append( const charT * begin, const charT * end,
+ detail::string_type & target, system::error_code & ec );
 
- BOOST_FILESYSTEM_DECL
- bool is_non_root_separator( const string_type & str, size_type pos );
- // pos is position of the separator
+ //template< class S > // specialization required
+ //S convert( const detail::string_type & source, system::error_code & ec );
 
- BOOST_FILESYSTEM_DECL
- size_type filename_pos( const string_type & str,
- size_type end_pos ); // end_pos is past-the-end position
- // Returns: 0 if str itself is filename (or empty)
+ //------------------------------------------------------------------------------------//
+ // specializations //
+ //------------------------------------------------------------------------------------//
 
- BOOST_FILESYSTEM_DECL
- size_type root_directory_start( const string_type & path, size_type size );
- // Returns: npos if no root_directory found
+ template<> struct is_iterator<const char *> { static const bool value = true; };
+ template<> struct is_iterator<char *> { static const bool value = true; };
+ template<> struct is_iterator<std::string::iterator> { static const bool value = true; };
+ template<> struct is_iterator<std::string::const_iterator> { static const bool value = true; };
+ template<> struct is_container<std::string> { static const bool value = true; };
 
-} // namespace detail
+ template<> struct is_iterator<const wchar_t *> { static const bool value = true; };
+ template<> struct is_iterator<wchar_t *> { static const bool value = true; };
+ template<> struct is_iterator<std::wstring::iterator> { static const bool value = true; };
+ template<> struct is_iterator<std::wstring::const_iterator> { static const bool value = true; };
+ template<> struct is_container<std::wstring> { static const bool value = true; };
 
- //------------------------------------------------------------------------------------//
- // //
- // traits and conversions //
- // //
- // users are permitted to add specializations for user defined types // //
- // //
- //------------------------------------------------------------------------------------//
+# ifdef BOOST_WINDOWS_API
 
- template< class T > struct pathable_iterator { static const bool value = false; };
- template<> struct pathable_iterator<const char *> { static const bool value = true; };
- template<> struct pathable_iterator<char *> { static const bool value = true; };
- template<> struct pathable_iterator<std::string::iterator> { static const bool value = true; };
- template<> struct pathable_iterator<std::string::const_iterator> { static const bool value = true; };
+ template<>
+ inline void append<char>( const char * begin, const char * end,
+ std::wstring & target, system::error_code & ec )
+ {
+ detail::append( begin, end, target, ec );
+ }
 
- template< class T > struct pathable_container { static const bool value = false; };
- template<> struct pathable_container<std::string> { static const bool value = true; };
+ template<>
+ inline void append<char>( const char * begin, std::wstring & target,
+ system::error_code & ec )
+ {
+ detail::append( begin, 0, target, ec );
+ }
 
-# ifndef BOOST_FILESYSTEM_NARROW_ONLY
- template<> struct pathable_iterator<const wchar_t *> { static const bool value = true; };
- template<> struct pathable_iterator<wchar_t *> { static const bool value = true; };
- template<> struct pathable_iterator<std::wstring::iterator> { static const bool value = true; };
- template<> struct pathable_iterator<std::wstring::const_iterator> { static const bool value = true; };
+ template<>
+ inline void append<wchar_t>( const wchar_t * begin, const wchar_t * end,
+ std::wstring & target, system::error_code & ec )
+ {
+ ec.clear();
+ target.assign( begin, end ); // but what if throws bad_alloc?
+ }
 
- template<> struct pathable_container<std::wstring> { static const bool value = true; };
-# endif
+ template<>
+ inline void append<wchar_t>( const wchar_t * begin, std::wstring & target,
+ system::error_code & ec )
+ {
+ ec.clear();
+ target += begin; // but what if throws bad_alloc?
+ }
 
- template< class T >
- T convert( const detail::string_type & src, system::error_code & ec );
+ //template<>
+ //inline std::string convert<std::string>( const std::wstring & s,
+ // system::error_code & ec )
+ //{
+ // return detail::convert_to_string( s, ec );
+ //}
+
+ //template<>
+ //inline std::wstring convert<std::wstring>( const std::wstring & s,
+ // system::error_code & ec )
+ //{
+ // return s;
+ //}
 
-# ifdef BOOST_WINDOWS_API
- template<> inline std::string convert<std::string>( const std::wstring & s, system::error_code & ec )
- { return detail::convert( s, ec ); }
- template<> inline std::wstring convert<std::wstring>( const std::wstring & s, system::error_code & ec )
- { return s; }
 # endif
 
+# ifdef BOOST_FILESYSTEM_CPP0X_CHAR_TYPES
+ ...
+# endif
+
+} // namespace path_traits
+
   //------------------------------------------------------------------------------------//
   // //
   // class path //
@@ -435,8 +394,8 @@
     template< class InputIterator >
       path( InputIterator begin,
         system::error_code & ec = system::throws,
- typename boost::enable_if<pathable_iterator<InputIterator> >::type* dummy=0 ) // #3
- { detail::convert_append_helper( begin, m_path, ec ); }
+ typename boost::enable_if<path_traits::is_iterator<InputIterator> >::type* dummy=0 ) // #3
+ { m_append( begin, m_path, ec ); }
 
     // construct from (potentially) multi-byte character string, which may have
     // embedded nulls. Embedded null support is required for some Asian languages on
@@ -445,7 +404,7 @@
     template< class ForwardIterator >
       path( ForwardIterator begin, ForwardIterator end,
         system::error_code & ec = system::throws ) // #4
- { detail::convert_append_helper( begin, end, m_path, ec ); }
+ { m_append( begin, end, m_path, ec ); }
 
     // construct from container of (potentially) multi-byte character string,
     // which may have embedded nulls. Embedded null support is required for
@@ -454,8 +413,8 @@
     template< class Container >
       path( const Container & ctr,
         system::error_code & ec = system::throws,
- typename boost::enable_if<pathable_container<Container> >::type* dummy=0 ) // #5
- { detail::convert_append_helper( ctr.begin(), ctr.end(), m_path, ec ); }
+ typename boost::enable_if<path_traits::is_container<Container> >::type* dummy=0 ) // #5
+ { m_append( ctr.begin(), ctr.end(), m_path, ec ); }
 
 
     // ----- assignments -----
@@ -467,21 +426,21 @@
     }
 
     template< class InputIterator >
- typename boost::enable_if<pathable_iterator<InputIterator>, path &>::type
+ typename boost::enable_if<path_traits::is_iterator<InputIterator>, path &>::type
         operator=( InputIterator begin ) // #2
     {
       m_path.clear();
- detail::convert_append_helper( begin, m_path, system::throws );
+ m_append( begin, m_path, system::throws );
       return *this;
     }
 
     template< class InputIterator >
- typename boost::enable_if<pathable_iterator<InputIterator>, path &>::type
+ typename boost::enable_if<path_traits::is_iterator<InputIterator>, path &>::type
         assign( InputIterator begin,
           system::error_code & ec = system::throws ) // #3
     {
       m_path.clear();
- detail::convert_append_helper( begin, m_path, ec );
+ m_append( begin, m_path, ec );
       return *this;
     }
 
@@ -490,26 +449,26 @@
         system::error_code & ec = system::throws ) // #4
     {
       m_path.clear();
- detail::convert_append_helper( begin, end, m_path, ec );
+ m_append( begin, end, m_path, ec );
       return *this;
     }
  
     template< class Container >
- typename boost::enable_if<pathable_container<Container>, path &>::type
+ typename boost::enable_if<path_traits::is_container<Container>, path &>::type
         operator=( const Container & ctr ) // #5
     {
       m_path.clear();
- detail::convert_append_helper( ctr.begin(), ctr.end(), m_path, system::throws );
+ m_append( ctr.begin(), ctr.end(), m_path, system::throws );
       return *this;
     }
  
     template< class Container >
- typename boost::enable_if<pathable_container<Container>, path &>::type
+ typename boost::enable_if<path_traits::is_container<Container>, path &>::type
         assign( const Container & ctr,
         system::error_code & ec = system::throws ) // #6
     {
       m_path.clear();
- detail::convert_append_helper( ctr.begin(), ctr.end(), m_path, ec );
+ m_append( ctr.begin(), ctr.end(), m_path, ec );
       return *this;
     }
 
@@ -523,21 +482,21 @@
     }
 
     template< class InputIterator >
- typename boost::enable_if<pathable_iterator<InputIterator>, path &>::type
+ typename boost::enable_if<path_traits::is_iterator<InputIterator>, path &>::type
         operator/=( InputIterator begin ) // #2
     {
       append_separator_if_needed_();
- detail::convert_append_helper( begin, m_path, system::throws );
+ m_append( begin, m_path, system::throws );
       return *this;
     }
 
     template< class InputIterator >
- typename boost::enable_if<pathable_iterator<InputIterator>, path &>::type
+ typename boost::enable_if<path_traits::is_iterator<InputIterator>, path &>::type
         append( InputIterator begin,
           system::error_code & ec = system::throws ) // #3
     {
       append_separator_if_needed_();
- detail::convert_append_helper( begin, m_path, ec );
+ m_append( begin, m_path, ec );
       return *this;
     }
 
@@ -546,26 +505,26 @@
         system::error_code & ec = system::throws ) // #4
     {
       append_separator_if_needed_();
- detail::convert_append_helper( begin, end, m_path, ec );
+ m_append( begin, end, m_path, ec );
       return *this;
     }
  
     template< class Container >
- typename boost::enable_if<pathable_container<Container>, path &>::type
+ typename boost::enable_if<path_traits::is_container<Container>, path &>::type
         operator/=( const Container & ctr ) // #5
     {
       append_separator_if_needed_();
- detail::convert_append_helper( ctr.begin(), ctr.end(), m_path, system::throws );
+ m_append( ctr.begin(), ctr.end(), m_path, system::throws );
       return *this;
     }
  
     template< class Container >
- typename boost::enable_if<pathable_container<Container>, path &>::type
+ typename boost::enable_if<path_traits::is_container<Container>, path &>::type
         append( const Container & ctr,
         system::error_code & ec = system::throws ) // #6
     {
       append_separator_if_needed_();
- detail::convert_append_helper( ctr.begin(), ctr.end(), m_path, ec );
+ m_append( ctr.begin(), ctr.end(), m_path, ec );
       return *this;
     }
 
@@ -581,12 +540,7 @@
 # endif
     }
 
- path & remove_filename()
- {
- m_path.erase(
- detail::filename_pos( m_path, m_path.size() ) );
- return *this;
- }
+ path & remove_filename();
 
     // ----- conversion operators -----
 
@@ -594,9 +548,14 @@
 
 # ifdef BOOST_WINDOWS_API
 
- operator const std::string() const { return detail::convert( m_path, system::throws ); }
+ operator const std::string() const { return detail::convert_to_string( m_path, system::throws ); }
     operator const std::wstring&() const { return m_path; }
 
+# ifdef BOOST_FILESYSTEM_CPP0X_CHAR_TYPES
+ operator const std::u16string() const { return detail::convert_to_u16string( m_path, system::throws ); }
+ operator const std::u32string() const { return detail::convert_to_u32string( m_path, system::throws ); }
+# endif
+
 # else // BOOST_POSIX_API
 
     operator const std::string&() const { return m_path; }
@@ -609,7 +568,7 @@
     // ----- observers -----
   
     // For operating systems that format file paths differently than directory
- // paths, returns from observers are formatted as file names unless there
+ // paths, return values from observers are formatted as file names unless there
     // is a trailing separator, in which case returns are formatted as directory
     // paths. POSIX and Windows make no such distinction.
 
@@ -621,14 +580,18 @@
 
 # ifdef BOOST_WINDOWS_API
 
- // return formatted "as input"
- const std::string string( system::error_code & ec = system::throws ) const { return detail::convert( m_path, ec ); }
+ // return value is formatted "as input"
+ const std::string string( system::error_code & ec = system::throws ) const { return detail::convert_to_string( m_path, ec ); }
     const std::wstring & wstring() const { return m_path; }
     const std::wstring & wstring( system::error_code & ec ) const { ec.clear(); return m_path; }
 
+# ifdef BOOST_FILESYSTEM_CPP0X_CHAR_TYPES
+ ...
+# endif
+
 # else // BOOST_POSIX_API
 
- // return formatted "as input"
+ // return value is formatted "as input"
     const std::string & string() const { return m_path; }
     const std::string & string( system::error_code & ec ) const { ec.clear(); return m_path; }
 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
@@ -637,14 +600,15 @@
 # endif
 
     
- // return formatted as indicated by function name
 # ifdef BOOST_WINDOWS_PATH
 
+ // return value is formatted as indicated by function name
     const path native() const;
     const path generic() const;
 
 # else // BOOST_POSIX_PATH
 
+ // return value is formatted as indicated by function name
     const path native() const { return m_path; }
     const path generic() const { return m_path; }
 
@@ -703,6 +667,10 @@
     iterator begin() const;
     iterator end() const;
 
+ //------------------------------------------------------------------------------------//
+ // class path private members //
+ //------------------------------------------------------------------------------------//
+
   private:
 
     // m_path has the type, encoding, and format required by the native
@@ -714,6 +682,25 @@
 
     string_type m_path; // Windows: backslashes NOT converted to slashes
 
+ // These helpers factor out common code and convert iterators to pointers.
+ template< class InputIterator >
+ inline void m_append( InputIterator begin,
+ string_type & target, system::error_code & ec )
+ {
+ BOOST_ASSERT( &*begin );
+ path_traits::append( &*begin, target, ec );
+ }
+
+ template< class FowardIterator >
+ inline void m_append( FowardIterator begin, FowardIterator end,
+ string_type & target, system::error_code & ec )
+ {
+ if ( begin == end ) return;
+ BOOST_ASSERT( &*begin );
+ path_traits::append( &*begin,
+ &*begin + std::distance( begin, end ), // avoid dereference of end iterator
+ target, ec );
+ }
 
     void append_separator_if_needed_();
 
@@ -728,12 +715,10 @@
     // see path::iterator::increment/decrement comment below
     static void m_path_iterator_increment( path::iterator & it );
     static void m_path_iterator_decrement( path::iterator & it );
- };
-
+ }; // class path
+
   //------------------------------------------------------------------------------------//
- // //
- // class path::iterator //
- // //
+ // class path::iterator //
   //------------------------------------------------------------------------------------//
  
   class path::iterator

Modified: sandbox/filesystem-v3/libs/filesystem/src/operations.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/src/operations.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/src/operations.cpp 2008-12-29 09:10:44 EST (Mon, 29 Dec 2008)
@@ -167,6 +167,13 @@
 
 namespace
 {
+
+# ifdef BOOST_WINDOWS_PATH
+ const wchar_t dot = L'.';
+# else
+ const char dot = '.';
+# endif
+
   const std::size_t buf_size( 128 );
   const error_code ok;
 
@@ -1518,9 +1525,9 @@
     {
       it.m_imp->dir_entry.assign( p / filename,
         file_stat, symlink_file_stat );
- if ( filename[0] == detail::dot // dot or dot-dot
+ if ( filename[0] == dot // dot or dot-dot
         && (filename.size() == 1
- || (filename[1] == detail::dot
+ || (filename[1] == dot
             && filename.size() == 2)) )
         { it.increment(); }
     }
@@ -1552,9 +1559,9 @@
       }
 
       if ( it.m_imp->handle == 0 ) { it.m_imp.reset(); return; } // eof, make end
- if ( !(filename[0] == detail::dot // !(dot or dot-dot)
+ if ( !(filename[0] == dot // !(dot or dot-dot)
         && (filename.size() == 1
- || (filename[1] == detail::dot
+ || (filename[1] == dot
             && filename.size() == 2))) )
       {
         it.m_imp->dir_entry.replace_filename(

Modified: sandbox/filesystem-v3/libs/filesystem/src/path.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/src/path.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/src/path.cpp 2008-12-29 09:10:44 EST (Mon, 29 Dec 2008)
@@ -1,4 +1,4 @@
-// filesystem path.cpp --------------------------------------------------- //
+// filesystem path.cpp ------------------------------------------------------------- //
 
 // Copyright Beman Dawes 2008
 
@@ -21,179 +21,93 @@
 
 namespace fs = boost::filesystem;
 
+using fs::path;
+
 using std::string;
+using std::wstring;
 
-# ifndef BOOST_FILESYSTEM_NARROW_ONLY
- using std::wstring;
-# endif
+using boost::system::error_code;
+
+//--------------------------------------------------------------------------------------//
+// //
+// class path helpers //
+// //
+//--------------------------------------------------------------------------------------//
 
 namespace
 {
 
+ typedef path::size_type size_type;
+ typedef path::string_type string_type;
+ typedef path::value_type value_type;
+
 # ifdef BOOST_WINDOWS_PATH
 
+ const wchar_t separator = L'/';
+ const wchar_t preferred_separator = L'\\';
+ const wchar_t * const separators = L"/\\";
   const wchar_t * separator_string = L"/";
   const wchar_t * preferred_separator_string = L"\\";
+ const wchar_t colon = L':';
+ const wchar_t dot = L'.';
   const fs::path dot_path( L"." );
 
 # else
 
+ const char separator = '/';
+ const char preferred_separator = '/';
+ const char * const separators = "/";
   const char * separator_string = "/";
   const char * preferred_separator_string = "/";
+ const char colon = ':';
+ const char dot = '.';
   const fs::path dot_path( "." );
 
 # endif
 
-# ifdef BOOST_WINDOWS_API
-
- const std::locale windows_default; // only use is to take address
-
- void windows_convert_append( const char * begin, const char * end,
- // end == 0 for null terminated MBCS
- std::wstring & target, boost::system::error_code & ec );
-
- void locale_convert_append( const char * begin, const char * end,
- // end == 0 for null terminated MBCS
- std::wstring & target, boost::system::error_code & ec );
-# else // BOOST_POSIX_API
-
-
-
-# endif
-
-}
-
-namespace boost
-{
-namespace filesystem
-{
-
-# ifdef BOOST_WINDOWS_API
-
-namespace detail
-{
- const std::locale * path_locale( &windows_default );
-
- // convert_append --------------------------------------------------------//
-
- void convert_append( const char * begin, const char * end,
- std::wstring & target, system::error_code & ec )
- {
- if ( path_locale == &windows_default )
- windows_convert_append( begin, end, target, ec );
- else
- locale_convert_append( begin, end, target, ec );
- }
-
- // convert ---------------------------------------------------------------//
-
- BOOST_FILESYSTEM_DECL
- string convert( const wstring & src, system::error_code & ec )
+ inline bool is_separator( fs::path::value_type c )
   {
- if ( src.empty() ) return std::string();
-
- UINT codepage = AreFileApisANSI() ? CP_THREAD_ACP : CP_OEMCP;
-
- // buffer management strategy; use a probably large enough default buffer,
- // but fallback to an explict allocation if the default buffer is too small
-
- const std::size_t default_buf_sz = MAX_PATH+1;
- char buf[default_buf_sz+1];
- int count;
-
- if ( (count = ::WideCharToMultiByte( codepage, WC_NO_BEST_FIT_CHARS, src.c_str(),
- src.size(), buf, default_buf_sz, 0, 0 )) != 0 ) // success
- {
- ec.clear();
- buf[count] = '\0';
- return std::string( buf );
- }
-
- // TODO: implement fallback
- BOOST_ASSERT(0);
- throw "path::native_string() error handling not implemented yet";
- return std::string();
- }
-
-} // namespace detail
-} // namespace filesystem
-} // namespace boost
-
-namespace
-{
-
- void locale_convert_append( const char * begin, const char * end,
- // end == 0 for null terminated MBCS
- std::wstring & target, boost::system::error_code & ec )
- {
- BOOST_ASSERT( 0 && "not implemented yet" );
+ return c == separator
+# ifdef BOOST_WINDOWS_PATH
+ || c == preferred_separator
+# endif
+ ;
   }
 
+ bool is_non_root_separator( const string_type & str, size_type pos );
+ // pos is position of the separator
 
- void windows_convert_append( const char * begin, const char * end,
- std::wstring & target, boost::system::error_code & ec )
- {
- UINT codepage = AreFileApisANSI() ? CP_THREAD_ACP : CP_OEMCP;
- int size( end == 0 ? -1 : (end - begin) );
-
- // buffer management:
- //
- // if path prefixed by "\\?\" (Windows 'long path' prefix)
- // then use dynamic allocation, else use automatic allocation
-
- bool dynamic_allocation = target.find( L"\\\\?\\" ) == 0
- || ( target.empty()
- && ( (size >= 4 && std::memcmp( begin, "\\\\?\\", 4 ) == 0)
- || (size == -1 && std::strcmp( begin, "\\\\?\\" ) == 0) ) );
-
- wchar_t stack_buf[MAX_PATH+1];
- boost::scoped_array< wchar_t > heap_buf;
- wchar_t * buf = stack_buf;
- int buf_size = sizeof(stack_buf)/sizeof(wchar_t) - 1;
-
- if ( dynamic_allocation )
- {
- // get the allocation size for the buffer
- // rationale for calling MultiByteToWideChar: begin may point to a
- // multi-byte encoded string with embedded nulls, so a simplistic
- // computation of the size can fail
-
- buf_size = ::MultiByteToWideChar( codepage, MB_PRECOMPOSED, begin, size, 0, 0 );
- heap_buf.reset( new wchar_t [buf_size] );
- buf = heap_buf.get();
- }
-
- // perform the conversion
-
- if ( (buf_size = ::MultiByteToWideChar( codepage, MB_PRECOMPOSED, begin,
- size, buf, buf_size )) == 0 )
- {
- // conversion failed
- ec = boost::system::error_code( ::GetLastError(), boost::system::system_category );
- return;
- }
-
- ec.clear();
+ size_type filename_pos( const string_type & str,
+ size_type end_pos ); // end_pos is past-the-end position
+ // Returns: 0 if str itself is filename (or empty)
 
- // perform the append
+ size_type root_directory_start( const string_type & path, size_type size );
+ // Returns: npos if no root_directory found
 
- buf[buf_size] = L'\0';
- target += buf;
- }
+ void first_element(
+ const string_type & src,
+ size_type & element_pos,
+ size_type & element_size,
+# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1
+ size_type size = string_type::npos
+# else
+ size_type size = -1
+# endif
+ );
 
 } // unnamed namespace
 
+//--------------------------------------------------------------------------------------//
+// //
+// class path //
+// //
+//--------------------------------------------------------------------------------------//
+
 namespace boost
 {
 namespace filesystem
 {
 
-# else // BOOST_POSIX_API
-
-# endif // BOOST_POSIX_API
-
-//---------------------- class path member functions -----------------------//
-
 # ifdef BOOST_WINDOWS_PATH
 
   // generic ---------------------------------------------------------------//
@@ -225,7 +139,10 @@
 
     return tmp;
   }
-# endif // BOOST_WINDOWS_PATH
+
+# else // BOOST_POSIX_API
+ ...
+# endif // BOOST_POSIX_API
 
   // append_separator_if_needed_ -------------------------------------------//
 
@@ -233,11 +150,11 @@
   {
     if ( !m_path.empty() &&
 # ifdef BOOST_WINDOWS_PATH
- *(m_path.end()-1) != detail::colon &&
+ *(m_path.end()-1) != colon &&
 # endif
- !detail::is_separator( *(m_path.end()-1) ) )
+ !is_separator( *(m_path.end()-1) ) )
     {
- m_path += detail::preferred_separator;
+ m_path += preferred_separator;
     }
   }
 
@@ -257,11 +174,11 @@
     return ( itr.m_pos != m_path.size()
       && (
           ( itr.m_element.m_path.size() > 1
- && detail::is_separator( itr.m_element.m_path[0] )
- && detail::is_separator( itr.m_element.m_path[1] )
+ && is_separator( itr.m_element.m_path[0] )
+ && is_separator( itr.m_element.m_path[1] )
           )
 # ifdef BOOST_WINDOWS_PATH
- || itr.m_element.m_path[itr.m_element.m_path.size()-1] == detail::colon
+ || itr.m_element.m_path[itr.m_element.m_path.size()-1] == colon
 # endif
          ) )
       ? itr.m_element
@@ -270,7 +187,7 @@
 
   path path::root_directory() const
   {
- size_type pos( detail::root_directory_start( m_path, m_path.size() ) );
+ size_type pos( root_directory_start( m_path, m_path.size() ) );
 
     return pos == string_type::npos
       ? path()
@@ -282,9 +199,9 @@
     iterator itr( begin() );
 
     for ( ; itr.m_pos != m_path.size()
- && ( detail::is_separator( itr.m_element.m_path[0] )
+ && ( is_separator( itr.m_element.m_path[0] )
 # ifdef BOOST_WINDOWS_PATH
- || itr.m_element.m_path[itr.m_element.m_path.size()-1] == detail::colon
+ || itr.m_element.m_path[itr.m_element.m_path.size()-1] == colon
 # endif
            ); ++itr ) {}
 
@@ -293,17 +210,17 @@
 
   path path::parent_path() const
   {
- size_type end_pos( detail::filename_pos( m_path, m_path.size() ) );
+ size_type end_pos( filename_pos( m_path, m_path.size() ) );
 
     bool filename_was_separator( m_path.size()
- && detail::is_separator( m_path[end_pos] ) );
+ && is_separator( m_path[end_pos] ) );
 
     // skip separators unless root directory
- size_type root_dir_pos( detail::root_directory_start( m_path, end_pos ) );
+ size_type root_dir_pos( root_directory_start( m_path, end_pos ) );
     for ( ;
       end_pos > 0
       && (end_pos-1) != root_dir_pos
- && detail::is_separator( m_path[end_pos-1] )
+ && is_separator( m_path[end_pos-1] )
       ;
       --end_pos ) {}
 
@@ -314,11 +231,11 @@
 
   path path::filename() const
   {
- size_type pos( detail::filename_pos( m_path, m_path.size() ) );
+ size_type pos( filename_pos( m_path, m_path.size() ) );
     return (m_path.size()
               && pos
- && detail::is_separator( m_path[pos] )
- && detail::is_non_root_separator(m_path, pos))
+ && is_separator( m_path[pos] )
+ && is_non_root_separator(m_path, pos))
       ? dot_path
       : path( m_path.c_str() + pos );
   }
@@ -326,7 +243,7 @@
   path path::stem() const
   {
     path name( filename() );
- size_type pos( name.m_path.rfind( detail::dot ) );
+ size_type pos( name.m_path.rfind( dot ) );
     return pos == string_type::npos
       ? name
       : path( name.m_path.c_str(), name.m_path.c_str() + pos );
@@ -335,20 +252,32 @@
   path path::extension() const
   {
     path name( filename() );
- size_type pos( name.m_path.rfind( detail::dot ) );
+ size_type pos( name.m_path.rfind( dot ) );
     return pos == string_type::npos
       ? path()
       : path( name.m_path.c_str() + pos );
   }
+
+ path & path::remove_filename()
+ {
+ m_path.erase( filename_pos( m_path, m_path.size() ) );
+ return *this;
+ }
+
+} // namespace filesystem
+} // namespace boost
   
- //---------------------- namespace detail functions -----------------------//
+//--------------------------------------------------------------------------------------//
+// //
+// class path helper implementation //
+// //
+//--------------------------------------------------------------------------------------//
 
-namespace detail
+namespace
 {
-
+
   // is_non_root_separator -------------------------------------------------//
 
- BOOST_FILESYSTEM_DECL
   bool is_non_root_separator( const string_type & str, size_type pos )
     // pos is position of the separator
   {
@@ -370,7 +299,6 @@
 
   // filename_pos ----------------------------------------------------------//
 
- BOOST_FILESYSTEM_DECL
   size_type filename_pos( const string_type & str,
                           size_type end_pos ) // end_pos is past-the-end position
     // return 0 if str itself is filename (or empty)
@@ -400,7 +328,6 @@
 
   // root_directory_start --------------------------------------------------//
 
- BOOST_FILESYSTEM_DECL
   size_type root_directory_start( const string_type & path, size_type size )
   // return npos if no root_directory found
   {
@@ -500,21 +427,25 @@
     return;
   }
 
-} // namespace detail
+} // unnammed namespace
 
- //--------------------------------------------------------------------------//
- // //
- // path::iterator implementation //
- // //
- //--------------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
+// //
+// class path::iterator //
+// //
+//--------------------------------------------------------------------------------------//
 
+namespace boost
+{
+namespace filesystem
+{
 
   path::iterator path::begin() const
   {
     iterator itr;
     itr.m_path_ptr = this;
     detail::size_type element_size;
- detail::first_element( m_path, itr.m_pos, element_size );
+ first_element( m_path, itr.m_pos, element_size );
     itr.m_element = m_path.substr( itr.m_pos, element_size );
     if ( itr.m_element.m_path == preferred_separator_string )
       itr.m_element.m_path = separator_string; // needed for Windows, harmless on POSIX
@@ -545,33 +476,33 @@
 
     // both POSIX and Windows treat paths that begin with exactly two separators specially
     bool was_net( it.m_element.m_path.size() > 2
- && detail::is_separator( it.m_element.m_path[0] )
- && detail::is_separator( it.m_element.m_path[1] )
- && !detail::is_separator( it.m_element.m_path[2] ) );
+ && is_separator( it.m_element.m_path[0] )
+ && is_separator( it.m_element.m_path[1] )
+ && !is_separator( it.m_element.m_path[2] ) );
 
     // process separator (Windows drive spec is only case not a separator)
- if ( detail::is_separator( it.m_path_ptr->m_path[it.m_pos] ) )
+ if ( is_separator( it.m_path_ptr->m_path[it.m_pos] ) )
     {
       // detect root directory
       if ( was_net
 # ifdef BOOST_WINDOWS_PATH
         // case "c:/"
- || it.m_element.m_path[it.m_element.m_path.size()-1] == detail::colon
+ || it.m_element.m_path[it.m_element.m_path.size()-1] == colon
 # endif
          )
       {
- it.m_element.m_path = detail::separator;
+ it.m_element.m_path = separator;
         return;
       }
 
       // bypass separators
       while ( it.m_pos != it.m_path_ptr->m_path.size()
- && detail::is_separator( it.m_path_ptr->m_path[it.m_pos] ) )
+ && is_separator( it.m_path_ptr->m_path[it.m_pos] ) )
         { ++it.m_pos; }
 
       // detect trailing separator, and treat it as ".", per POSIX spec
       if ( it.m_pos == it.m_path_ptr->m_path.size()
- && detail::is_non_root_separator( it.m_path_ptr->m_path, it.m_pos-1 ) )
+ && is_non_root_separator( it.m_path_ptr->m_path, it.m_pos-1 ) )
       {
         --it.m_pos;
         it.m_element = dot_path;
@@ -580,7 +511,7 @@
     }
 
     // get next element
- size_type end_pos( it.m_path_ptr->m_path.find_first_of( detail::separators, it.m_pos ) );
+ size_type end_pos( it.m_path_ptr->m_path.find_first_of( separators, it.m_pos ) );
     if ( end_pos == string_type::npos ) end_pos = it.m_path_ptr->m_path.size();
     it.m_element = it.m_path_ptr->m_path.substr( it.m_pos, end_pos - it.m_pos );
   }
@@ -594,8 +525,8 @@
     // if at end and there was a trailing non-root '/', return "."
     if ( it.m_pos == it.m_path_ptr->m_path.size()
       && it.m_path_ptr->m_path.size() > 1
- && detail::is_separator( it.m_path_ptr->m_path[it.m_pos-1] )
- && detail::is_non_root_separator( it.m_path_ptr->m_path, it.m_pos-1 )
+ && is_separator( it.m_path_ptr->m_path[it.m_pos-1] )
+ && is_non_root_separator( it.m_path_ptr->m_path, it.m_pos-1 )
        )
     {
       --it.m_pos;
@@ -603,18 +534,18 @@
       return;
     }
 
- size_type root_dir_pos( detail::root_directory_start( it.m_path_ptr->m_path, end_pos ) );
+ size_type root_dir_pos( root_directory_start( it.m_path_ptr->m_path, end_pos ) );
 
     // skip separators unless root directory
     for (
       ;
       end_pos > 0
       && (end_pos-1) != root_dir_pos
- && detail::is_separator( it.m_path_ptr->m_path[end_pos-1] )
+ && is_separator( it.m_path_ptr->m_path[end_pos-1] )
       ;
       --end_pos ) {}
 
- it.m_pos = detail::filename_pos( it.m_path_ptr->m_path, end_pos );
+ it.m_pos = filename_pos( it.m_path_ptr->m_path, end_pos );
     it.m_element = it.m_path_ptr->m_path.substr( it.m_pos, end_pos - it.m_pos );
     if ( it.m_element.m_path == preferred_separator_string )
       it.m_element.m_path = separator_string; // needed for Windows, harmless on POSIX
@@ -633,3 +564,154 @@
 
 } // namespace filesystem
 } // namespace boost
+
+//--------------------------------------------------------------------------------------//
+// //
+// path_traits //
+// //
+//--------------------------------------------------------------------------------------//
+
+namespace
+{
+
+# ifdef BOOST_WINDOWS_API
+
+ const std::locale windows_default; // only use is to take address
+
+ void windows_append( const char * begin, const char * end,
+ // end == 0 for null terminated MBCS
+ wstring & target, error_code & ec );
+
+ void locale_append( const char * begin, const char * end,
+ // end == 0 for null terminated MBCS
+ wstring & target, error_code & ec );
+# else // BOOST_POSIX_API
+
+ ...
+
+# endif
+
+} // unnamed namespace
+
+namespace boost
+{
+namespace filesystem
+{
+
+namespace detail
+{
+ const std::locale * path_locale( &windows_default );
+
+ //------------------------------------------------------------------------------------//
+ // append //
+ //------------------------------------------------------------------------------------//
+
+ void append( const char * begin, const char * end,
+ wstring & target, error_code & ec )
+ {
+ if ( path_locale == &windows_default )
+ windows_append( begin, end, target, ec );
+ else
+ locale_append( begin, end, target, ec );
+ }
+
+ //------------------------------------------------------------------------------------//
+ // convert //
+ //------------------------------------------------------------------------------------//
+
+ BOOST_FILESYSTEM_DECL
+ string convert_to_string( const wstring & src, error_code & ec )
+ {
+ if ( src.empty() ) return std::string();
+
+ UINT codepage = AreFileApisANSI() ? CP_THREAD_ACP : CP_OEMCP;
+
+ // buffer management strategy; use a probably large enough default buffer,
+ // but fallback to an explict allocation if the default buffer is too small
+
+ const std::size_t default_buf_sz = MAX_PATH+1;
+ char buf[default_buf_sz+1];
+ int count;
+
+ if ( (count = ::WideCharToMultiByte( codepage, WC_NO_BEST_FIT_CHARS, src.c_str(),
+ src.size(), buf, default_buf_sz, 0, 0 )) != 0 ) // success
+ {
+ ec.clear();
+ buf[count] = '\0';
+ return std::string( buf );
+ }
+
+ // TODO: implement fallback
+ BOOST_ASSERT(0);
+ throw "path::native_string() error handling not implemented yet";
+ return std::string();
+ }
+
+} // namespace detail
+} // namespace filesystem
+} // namespace boost
+
+namespace
+{
+
+ void locale_append( const char * begin, const char * end,
+ // end == 0 for null terminated MBCS
+ wstring & target, error_code & ec )
+ {
+ BOOST_ASSERT( 0 && "not implemented yet" );
+ }
+
+
+ void windows_append( const char * begin, const char * end,
+ wstring & target, error_code & ec )
+ {
+ UINT codepage = AreFileApisANSI() ? CP_THREAD_ACP : CP_OEMCP;
+ int size( end == 0 ? -1 : (end - begin) );
+
+ // buffer management:
+ //
+ // if path prefixed by "\\?\" (Windows 'long path' prefix)
+ // then use dynamic allocation, else use automatic allocation
+
+ bool dynamic_allocation = target.find( L"\\\\?\\" ) == 0
+ || ( target.empty()
+ && ( (size >= 4 && std::memcmp( begin, "\\\\?\\", 4 ) == 0)
+ || (size == -1 && std::strcmp( begin, "\\\\?\\" ) == 0) ) );
+
+ wchar_t stack_buf[MAX_PATH+1];
+ boost::scoped_array< wchar_t > heap_buf;
+ wchar_t * buf = stack_buf;
+ int buf_size = sizeof(stack_buf)/sizeof(wchar_t) - 1;
+
+ if ( dynamic_allocation )
+ {
+ // get the allocation size for the buffer
+ // rationale for calling MultiByteToWideChar: begin may point to a
+ // multi-byte encoded string with embedded nulls, so a simplistic
+ // computation of the size can fail
+
+ buf_size = ::MultiByteToWideChar( codepage, MB_PRECOMPOSED, begin, size, 0, 0 );
+ heap_buf.reset( new wchar_t [buf_size] );
+ buf = heap_buf.get();
+ }
+
+ // perform the conversion
+
+ if ( (buf_size = ::MultiByteToWideChar( codepage, MB_PRECOMPOSED, begin,
+ size, buf, buf_size )) == 0 )
+ {
+ // conversion failed
+ ec = error_code( ::GetLastError(), boost::system::system_category );
+ return;
+ }
+
+ ec.clear();
+
+ // perform the append
+
+ buf[buf_size] = L'\0';
+ target += buf;
+ }
+
+} // unnamed namespace
+

Modified: sandbox/filesystem-v3/libs/filesystem/test/path_unit_test.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/test/path_unit_test.cpp (original)
+++ sandbox/filesystem-v3/libs/filesystem/test/path_unit_test.cpp 2008-12-29 09:10:44 EST (Mon, 29 Dec 2008)
@@ -214,95 +214,95 @@
 
   }
 
-// // test_assignments ----------------------------------------------------------------//
-//
-// void test_assignments()
-// {
-// std::cout << "testing assignments..." << std::endl;
-//
-// y = "path y"; // #2
-// PATH_IS(y, L"path y");
-//
-// x = y; // #1
-// PATH_IS(x, L"path y");
-//
-// x = "const char *"; // #2
-// PATH_IS(x, L"const char *");
-//
-// x = L"const wchar_t *"; // #2
-// PATH_IS(x, L"const wchar_t *");
-//
-// x = string("std::string::iterator").begin(); // #2 w/iterator
-// PATH_IS(x, L"std::string::iterator");
-//
-// x = wstring(L"std::wstring::iterator").begin(); // #2 w/iterator
-// PATH_IS(x, L"std::wstring::iterator");
-//
-// y.assign("path y w/o ec"); // #3 w/o ec
-// PATH_IS(y, L"path y w/o ec");
-//
-// ec = ng;
-// y.assign("path y w/ec", ec); // #3 w/ec
-// PATH_IS(y, L"path y w/ec");
-// IS(ec, ok);
-//
-// x.assign(s.begin(), s.end()); // #4
-// PATH_IS(x, L"string iterators");
-//
-// ec = ng;
-// x.assign(s.begin(), s.end(), ec); // #4 w/ec
-// PATH_IS(x, L"string iterators");
-// IS(ec, ok);
-//
-// x.assign(ws.begin(), ws.end()); // #4
-// PATH_IS(x, L"wstring iterators");
-//
-// x = string("std::string"); // #5
-// PATH_IS(x, L"std::string");
-//
-// x = wstring(L"std::wstring"); // #5
-// PATH_IS(x, L"std::wstring");
-//
-// x.assign(string("std::string")); // #6
-// PATH_IS(x, L"std::string");
-//
-// x.assign(wstring(L"std::wstring")); // #6
-// PATH_IS(x, L"std::wstring");
-//
-// ec = ng;
-// x.assign(string("std::string"), ec); // #6 w/ec
-// PATH_IS(x, L"std::string");
-// IS(ec, ok);
-//
-// }
-//
-// // test_observers ------------------------------------------------------------------//
-//
-// void test_observers()
-// {
-// std::cout << "testing observers..." << std::endl;
-//
-//# ifdef BOOST_WINDOWS_PATH
-//
-// path p( "abc\\def/ghi" );
-//
-// CHECK( wstring( p.c_str() ) == L"abc\\def/ghi" );
-//
-// CHECK( p.string() == "abc\\def/ghi" );
-// CHECK( p.wstring() == L"abc\\def/ghi" );
-//
-// CHECK( p.generic().string() == "abc/def/ghi" );
-// CHECK( p.generic().wstring() == L"abc/def/ghi" );
-//
-// CHECK( p.native().string() == "abc\\def\\ghi" );
-// CHECK( p.native().wstring() == L"abc\\def\\ghi" );
-//
-//# else // BOOST_POSIX_PATH
-//
-//
-//# endif
-// }
-//
+ // test_assignments ----------------------------------------------------------------//
+
+ void test_assignments()
+ {
+ std::cout << "testing assignments..." << std::endl;
+
+ y = "path y"; // #2
+ PATH_IS(y, L"path y");
+
+ x = y; // #1
+ PATH_IS(x, L"path y");
+
+ x = "const char *"; // #2
+ PATH_IS(x, L"const char *");
+
+ x = L"const wchar_t *"; // #2
+ PATH_IS(x, L"const wchar_t *");
+
+ x = string("std::string::iterator").begin(); // #2 w/iterator
+ PATH_IS(x, L"std::string::iterator");
+
+ x = wstring(L"std::wstring::iterator").begin(); // #2 w/iterator
+ PATH_IS(x, L"std::wstring::iterator");
+
+ y.assign("path y w/o ec"); // #3 w/o ec
+ PATH_IS(y, L"path y w/o ec");
+
+ ec = ng;
+ y.assign("path y w/ec", ec); // #3 w/ec
+ PATH_IS(y, L"path y w/ec");
+ IS(ec, ok);
+
+ x.assign(s.begin(), s.end()); // #4
+ PATH_IS(x, L"string iterators");
+
+ ec = ng;
+ x.assign(s.begin(), s.end(), ec); // #4 w/ec
+ PATH_IS(x, L"string iterators");
+ IS(ec, ok);
+
+ x.assign(ws.begin(), ws.end()); // #4
+ PATH_IS(x, L"wstring iterators");
+
+ x = string("std::string"); // #5
+ PATH_IS(x, L"std::string");
+
+ x = wstring(L"std::wstring"); // #5
+ PATH_IS(x, L"std::wstring");
+
+ x.assign(string("std::string")); // #6
+ PATH_IS(x, L"std::string");
+
+ x.assign(wstring(L"std::wstring")); // #6
+ PATH_IS(x, L"std::wstring");
+
+ ec = ng;
+ x.assign(string("std::string"), ec); // #6 w/ec
+ PATH_IS(x, L"std::string");
+ IS(ec, ok);
+
+ }
+
+ // test_observers ------------------------------------------------------------------//
+
+ void test_observers()
+ {
+ std::cout << "testing observers..." << std::endl;
+
+# ifdef BOOST_WINDOWS_PATH
+
+ path p( "abc\\def/ghi" );
+
+ CHECK( wstring( p.c_str() ) == L"abc\\def/ghi" );
+
+ CHECK( p.string() == "abc\\def/ghi" );
+ CHECK( p.wstring() == L"abc\\def/ghi" );
+
+ CHECK( p.generic().string() == "abc/def/ghi" );
+ CHECK( p.generic().wstring() == L"abc/def/ghi" );
+
+ CHECK( p.native().string() == "abc\\def\\ghi" );
+ CHECK( p.native().wstring() == L"abc\\def\\ghi" );
+
+# else // BOOST_POSIX_PATH
+
+
+# endif
+ }
+
 // // test_appends --------------------------------------------------------------------//
 //
 // void test_appends()
@@ -310,93 +310,93 @@
 // std::cout << "testing appends..." << std::endl;
 //
 // }
-//
-// // test_relationals ----------------------------------------------------------------//
-//
-// void test_relationals()
-// {
-// std::cout << "testing relationals..." << std::endl;
-//
-// const path p( "bar" );
-// const path p2( "baz" );
-//
-// CHECK( !(p < p) );
-// CHECK( p < p2 );
-// CHECK( !(p2 < p) );
-// CHECK( p < "baz" );
-// CHECK( p < string("baz") );
-// CHECK( p < L"baz" );
-// CHECK( p < wstring(L"baz") );
-// CHECK( !("baz" < p) );
-// CHECK( !(string("baz") < p) );
-// CHECK( !(L"baz" < p) );
-// CHECK( !(wstring(L"baz") < p) );
-//
-// CHECK( p == p );
-// CHECK( !(p == p2) );
-// CHECK( !(p2 == p) );
-// CHECK( p2 == "baz" );
-// CHECK( p2 == string("baz") );
-// CHECK( p2 == L"baz" );
-// CHECK( p2 == wstring(L"baz") );
-// CHECK( "baz" == p2 );
-// CHECK( string("baz") == p2 );
-// CHECK( L"baz" == p2 );
-// CHECK( wstring(L"baz") == p2 );
-//
-// CHECK( !(p != p) );
-// CHECK( p != p2 );
-// CHECK( p2 != p );
-//
-// CHECK( p <= p );
-// CHECK( p <= p2 );
-// CHECK( !(p2 <= p) );
-//
-// CHECK( !(p > p) );
-// CHECK( !(p > p2) );
-// CHECK( p2 > p );
-//
-// CHECK( p >= p );
-// CHECK( !(p >= p2) );
-// CHECK( p2 >= p );
-//}
-//
-// // test_other_non_members ----------------------------------------------------------//
-//
-// void test_other_non_members()
-// {
-// std::cout << "testing other_non_members..." << std::endl;
-//
-// path p1("foo");
-// path p2("bar");
-//
-// // operator /
-//
-// CHECK( p1 / p2 == path( "foo/bar" ).native() );
-// CHECK( "foo" / p2 == path( "foo/bar" ).native() );
-// CHECK( L"foo" / p2 == path( "foo/bar" ).native() );
-// CHECK( string( "foo" ) / p2 == path( "foo/bar" ).native() );
-// CHECK( wstring( L"foo" ) / p2 == path( "foo/bar" ).native() );
-// CHECK( p1 / "bar" == path( "foo/bar" ).native() );
-// CHECK( p1 / L"bar" == path( "foo/bar" ).native() );
-// CHECK( p1 / string( "bar" ) == path( "foo/bar" ).native() );
-// CHECK( p1 / wstring( L"bar" ) == path( "foo/bar" ).native() );
-//
-// swap( p1, p2 );
-// // swap
-//
-// CHECK( p1 == "bar" );
-// CHECK( p2 == "foo" );
-//
-// // swap( p1, "baz" ); // should fail to compile
-// // swap( p1, L"baz" ); // should fail to compile
-//
-// CHECK( path( "" ).remove_filename() == "" );
-// CHECK( path( "foo" ).remove_filename() == "" );
-// CHECK( path( "foo/bar" ).remove_filename() == "foo/" );
-//
-// }
-//
+
+ // test_relationals ----------------------------------------------------------------//
+
+ void test_relationals()
+ {
+ std::cout << "testing relationals..." << std::endl;
+
+ const path p( "bar" );
+ const path p2( "baz" );
+
+ CHECK( !(p < p) );
+ CHECK( p < p2 );
+ CHECK( !(p2 < p) );
+ CHECK( p < "baz" );
+ CHECK( p < string("baz") );
+ CHECK( p < L"baz" );
+ CHECK( p < wstring(L"baz") );
+ CHECK( !("baz" < p) );
+ CHECK( !(string("baz") < p) );
+ CHECK( !(L"baz" < p) );
+ CHECK( !(wstring(L"baz") < p) );
+
+ CHECK( p == p );
+ CHECK( !(p == p2) );
+ CHECK( !(p2 == p) );
+ CHECK( p2 == "baz" );
+ CHECK( p2 == string("baz") );
+ CHECK( p2 == L"baz" );
+ CHECK( p2 == wstring(L"baz") );
+ CHECK( "baz" == p2 );
+ CHECK( string("baz") == p2 );
+ CHECK( L"baz" == p2 );
+ CHECK( wstring(L"baz") == p2 );
+
+ CHECK( !(p != p) );
+ CHECK( p != p2 );
+ CHECK( p2 != p );
+
+ CHECK( p <= p );
+ CHECK( p <= p2 );
+ CHECK( !(p2 <= p) );
+
+ CHECK( !(p > p) );
+ CHECK( !(p > p2) );
+ CHECK( p2 > p );
+
+ CHECK( p >= p );
+ CHECK( !(p >= p2) );
+ CHECK( p2 >= p );
+}
+
+ // test_other_non_members ----------------------------------------------------------//
+
+ void test_other_non_members()
+ {
+ std::cout << "testing other_non_members..." << std::endl;
+
+ path p1("foo");
+ path p2("bar");
+
+ // operator /
+
+ CHECK( p1 / p2 == path( "foo/bar" ).native() );
+ CHECK( "foo" / p2 == path( "foo/bar" ).native() );
+ CHECK( L"foo" / p2 == path( "foo/bar" ).native() );
+ CHECK( string( "foo" ) / p2 == path( "foo/bar" ).native() );
+ CHECK( wstring( L"foo" ) / p2 == path( "foo/bar" ).native() );
+ CHECK( p1 / "bar" == path( "foo/bar" ).native() );
+ CHECK( p1 / L"bar" == path( "foo/bar" ).native() );
+ CHECK( p1 / string( "bar" ) == path( "foo/bar" ).native() );
+ CHECK( p1 / wstring( L"bar" ) == path( "foo/bar" ).native() );
+
+ swap( p1, p2 );
+ // swap
+
+ CHECK( p1 == "bar" );
+ CHECK( p2 == "foo" );
+
+ // swap( p1, "baz" ); // should fail to compile
+ // swap( p1, L"baz" ); // should fail to compile
+
+ CHECK( path( "" ).remove_filename() == "" );
+ CHECK( path( "foo" ).remove_filename() == "" );
+ CHECK( path( "foo/bar" ).remove_filename() == "foo/" );
+
+ }
+
 // // test_modifiers ------------------------------------------------------------------//
 //
 // void test_modifiers()
@@ -404,119 +404,159 @@
 // std::cout << "testing modifiers..." << std::endl;
 //
 // }
+
+ // test_iterators ------------------------------------------------------------------//
+
+ void test_iterators()
+ {
+ std::cout << "testing iterators..." << std::endl;
+
+ path p1;
+ CHECK( p1.begin() == p1.end() );
+
+ path p2("/");
+ CHECK( p2.begin() != p2.end() );
+ CHECK( *p2.begin() == "/" );
+ CHECK( ++p2.begin() == p2.end() );
+
+ path p3("foo/bar/baz");
+
+ path::iterator it(p3.begin());
+ CHECK( p3.begin() != p3.end() );
+ CHECK( *it == "foo" );
+ CHECK( *++it == "bar" );
+ CHECK( *++it == "baz" );
+ CHECK( *--it == "bar" );
+ CHECK( *--it == "foo" );
+ CHECK( *++it == "bar" );
+ CHECK( *++it == "baz" );
+ CHECK( ++it == p3.end() );
+
+ }
+
+ // test_decompositions -------------------------------------------------------------//
+
+ void test_decompositions()
+ {
+ std::cout << "testing decompositions..." << std::endl;
+
+ CHECK( path("").root_name().string() == "" );
+ CHECK( path("foo").root_name().string() == "" );
+ CHECK( path("/").root_name().string() == "" );
+ CHECK( path("/foo").root_name().string() == "" );
+ CHECK( path("//netname").root_name().string() == "//netname" );
+ CHECK( path("//netname/foo").root_name().string() == "//netname" );
+
+ CHECK( path("").root_directory().string() == "" );
+ CHECK( path("foo").root_directory().string() == "" );
+ CHECK( path("/").root_directory().string() == "/" );
+ CHECK( path("/foo").root_directory().string() == "/" );
+ CHECK( path("//netname").root_directory().string() == "" );
+ CHECK( path("//netname/foo").root_directory().string() == "/" );
+
+ CHECK( path("").root_path().string() == "" );
+ CHECK( path("/").root_path().string() == "/" );
+ CHECK( path("/foo").root_path().string() == "/" );
+ CHECK( path("//netname").root_path().string() == "//netname" );
+ CHECK( path("//netname/foo").root_path().string() == "//netname/" );
+
+# ifdef BOOST_WINDOWS_API
+ CHECK( path("c:/foo").root_path().string() == "c:/" );
+# endif
+
+ CHECK( path("").relative_path().string() == "" );
+ CHECK( path("/").relative_path().string() == "" );
+ CHECK( path("/foo").relative_path().string() == "foo" );
+
+ CHECK( path("").parent_path().string() == "" );
+ CHECK( path("/").parent_path().string() == "" );
+ CHECK( path("/foo").parent_path().string() == "/" );
+ CHECK( path("/foo/bar").parent_path().string() == "/foo" );
+
+ CHECK( path("/foo/bar/baz.zoo").filename().string() == "baz.zoo" );
+
+ CHECK( path("/foo/bar/baz.zoo").stem().string() == "baz" );
+ CHECK( path("/foo/bar.woo/baz").stem().string() == "baz" );
+
+ CHECK( path("/foo/bar/baz.zoo").extension().string() == ".zoo" );
+ CHECK( path("/foo/bar.woo/baz").extension().string() == "" );
+ }
+
+ // test_queries --------------------------------------------------------------------//
+
+ void test_queries()
+ {
+ std::cout << "testing queries..." << std::endl;
+
+ path p1( "" );
+ path p2( "//netname/foo" );
+
+ CHECK( p1.empty() );
+ CHECK( !p1.has_root_path() );
+ CHECK( !p1.has_root_name() );
+ CHECK( !p1.has_root_directory() );
+ CHECK( !p1.has_relative_path() );
+ CHECK( !p1.has_parent_path() );
+ CHECK( !p1.has_filename() );
+ CHECK( !p1.is_complete() );
+
+ CHECK( !p2.empty() );
+ CHECK( p2.has_root_path() );
+ CHECK( p2.has_root_name() );
+ CHECK( p2.has_root_directory() );
+ CHECK( p2.has_relative_path() );
+ CHECK( p2.has_parent_path() );
+ CHECK( p2.has_filename() );
+ CHECK( p2.is_complete() );
+
+ }
+
+// // test_locales --------------------------------------------------------------------//
 //
-// // test_iterators ------------------------------------------------------------------//
-//
-// void test_iterators()
+// void test_locales()
 // {
-// std::cout << "testing iterators..." << std::endl;
-//
-// path p1;
-// CHECK( p1.begin() == p1.end() );
-//
-// path p2("/");
-// CHECK( p2.begin() != p2.end() );
-// CHECK( *p2.begin() == "/" );
-// CHECK( ++p2.begin() == p2.end() );
-//
-// path p3("foo/bar/baz");
-//
-// path::iterator it(p3.begin());
-// CHECK( p3.begin() != p3.end() );
-// CHECK( *it == "foo" );
-// CHECK( *++it == "bar" );
-// CHECK( *++it == "baz" );
-// CHECK( *--it == "bar" );
-// CHECK( *--it == "foo" );
-// CHECK( *++it == "bar" );
-// CHECK( *++it == "baz" );
-// CHECK( ++it == p3.end() );
+// std::cout << "testing locales..." << std::endl;
 //
 // }
+
+// // test_user_supplied_type ---------------------------------------------------------//
 //
-// // test_decompositions -------------------------------------------------------------//
-//
-// void test_decompositions()
-// {
-// std::cout << "testing decompositions..." << std::endl;
-//
-// CHECK( path("").root_name().string() == "" );
-// CHECK( path("foo").root_name().string() == "" );
-// CHECK( path("/").root_name().string() == "" );
-// CHECK( path("/foo").root_name().string() == "" );
-// CHECK( path("//netname").root_name().string() == "//netname" );
-// CHECK( path("//netname/foo").root_name().string() == "//netname" );
-//
-// CHECK( path("").root_directory().string() == "" );
-// CHECK( path("foo").root_directory().string() == "" );
-// CHECK( path("/").root_directory().string() == "/" );
-// CHECK( path("/foo").root_directory().string() == "/" );
-// CHECK( path("//netname").root_directory().string() == "" );
-// CHECK( path("//netname/foo").root_directory().string() == "/" );
-//
-// CHECK( path("").root_path().string() == "" );
-// CHECK( path("/").root_path().string() == "/" );
-// CHECK( path("/foo").root_path().string() == "/" );
-// CHECK( path("//netname").root_path().string() == "//netname" );
-// CHECK( path("//netname/foo").root_path().string() == "//netname/" );
-//
-//# ifdef BOOST_WINDOWS_API
-// CHECK( path("c:/foo").root_path().string() == "c:/" );
-//# endif
-//
-// CHECK( path("").relative_path().string() == "" );
-// CHECK( path("/").relative_path().string() == "" );
-// CHECK( path("/foo").relative_path().string() == "foo" );
-//
-// CHECK( path("").parent_path().string() == "" );
-// CHECK( path("/").parent_path().string() == "" );
-// CHECK( path("/foo").parent_path().string() == "/" );
-// CHECK( path("/foo/bar").parent_path().string() == "/foo" );
-//
-// CHECK( path("/foo/bar/baz.zoo").filename().string() == "baz.zoo" );
+// typedef std::basic_string<long long> llstring;
 //
-// CHECK( path("/foo/bar/baz.zoo").stem().string() == "baz" );
-// CHECK( path("/foo/bar.woo/baz").stem().string() == "baz" );
+//} // unnamed namespace
 //
-// CHECK( path("/foo/bar/baz.zoo").extension().string() == ".zoo" );
-// CHECK( path("/foo/bar.woo/baz").extension().string() == "" );
+//namespace boost
+//{
+// namespace filesystem
+// {
+// template<> struct pathable_iterator<const long long *> { static const bool value = true; };
+// template<> struct pathable_iterator<long long *> { static const bool value = true; };
+// template<> struct pathable_iterator<llstring::iterator> { static const bool value = true; };
+// template<> struct pathable_iterator<llstring::const_iterator> { static const bool value = true; };
+// template<> struct pathable_container<llstring> { static const bool value = true; };
 // }
+//}
 //
-// // test_queries --------------------------------------------------------------------//
+//namespace
+//{
 //
-// void test_queries()
+// void test_user_supplied_type()
 // {
-// std::cout << "testing queries..." << std::endl;
+// std::cout << "testing user supplied type..." << std::endl;
 //
-// path p1( "" );
-// path p2( "//netname/foo" );
+// long long ll_c_str[] = { 'a', 'b', 'c', 0 };
+// llstring ll_str( ll_c_str );
 //
-// CHECK( p1.empty() );
-// CHECK( !p1.has_root_path() );
-// CHECK( !p1.has_root_name() );
-// CHECK( !p1.has_root_directory() );
-// CHECK( !p1.has_relative_path() );
-// CHECK( !p1.has_parent_path() );
-// CHECK( !p1.has_filename() );
-// CHECK( !p1.is_complete() );
-//
-// CHECK( !p2.empty() );
-// CHECK( p2.has_root_path() );
-// CHECK( p2.has_root_name() );
-// CHECK( p2.has_root_directory() );
-// CHECK( p2.has_relative_path() );
-// CHECK( p2.has_parent_path() );
-// CHECK( p2.has_filename() );
-// CHECK( p2.is_complete() );
+// path p1( ll_c_str );
+// CHECK( p1 == path("abc") );
+// CHECK( p1 == "abc" );
+// llstring t1( p1.string<llstring>() );
+// CHECK( t1 == ll_str );
 //
-// }
+// //path p2( ll_str );
 //
-// // test_locales --------------------------------------------------------------------//
-//
-// void test_locales()
-// {
-// std::cout << "testing locales..." << std::endl;
 //
+// //path p3( ll_str.begin(), ll_str.end() );
 // }
 
 } // unnamed namespace
@@ -532,16 +572,17 @@
   test_constructors();
   test_use_cases();
   test_conversion_operators();
- //test_assignments();
- //test_observers();
+ test_assignments();
+ test_observers();
   ////test_appends();
- //test_relationals();
- //test_other_non_members();
+ test_relationals();
+ test_other_non_members();
   //test_modifiers();
- //test_iterators();
- //test_decompositions();
- //test_queries();
+ test_iterators();
+ test_decompositions();
+ test_queries();
   ////test_locales();
+ //test_user_supplied_type();
  
   cout << errors << " errors detected\n";
   


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk