$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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";