$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r50448 - in sandbox/filesystem-v3: boost/filesystem libs/filesystem/src libs/filesystem/test
From: bdawes_at_[hidden]
Date: 2009-01-03 09:36:52
Author: bemandawes
Date: 2009-01-03 09:36:50 EST (Sat, 03 Jan 2009)
New Revision: 50448
URL: http://svn.boost.org/trac/boost/changeset/50448
Log:
filesystem.v3: all tests (including imbue related tests) passing on Windows
Text files modified: 
   sandbox/filesystem-v3/boost/filesystem/path.hpp               |     1                                         
   sandbox/filesystem-v3/libs/filesystem/src/path.cpp            |   118 ++++++++++++++++++++++++--------------- 
   sandbox/filesystem-v3/libs/filesystem/test/path_test.cpp      |     6 +-                                      
   sandbox/filesystem-v3/libs/filesystem/test/path_unit_test.cpp |     7 +                                       
   4 files changed, 82 insertions(+), 50 deletions(-)
Modified: sandbox/filesystem-v3/boost/filesystem/path.hpp
==============================================================================
--- sandbox/filesystem-v3/boost/filesystem/path.hpp	(original)
+++ sandbox/filesystem-v3/boost/filesystem/path.hpp	2009-01-03 09:36:50 EST (Sat, 03 Jan 2009)
@@ -18,6 +18,7 @@
 
    * Windows, POSIX, conversions for char16_t, char32_t for supporting compilers.
    * Windows, POSIX, conversions for user-defined types.
+   * Need an error category for codecvt errors. Seed path.cpp detail::append, etc.
    * 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.
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	2009-01-03 09:36:50 EST (Sat, 03 Jan 2009)
@@ -28,6 +28,10 @@
 
 using boost::system::error_code;
 
+#ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE
+# define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256
+#endif
+
 //--------------------------------------------------------------------------------------//
 //                                                                                      //
 //                                class path helpers                                    //
@@ -44,6 +48,8 @@
   typedef path::string_type  string_type;
   typedef path::value_type   value_type;
 
+  const std::size_t default_codecvt_buf_size = BOOST_FILESYSTEM_CODECVT_BUF_SIZE;
+
 # ifdef BOOST_WINDOWS_PATH
 
   const wchar_t separator = L'/';
@@ -579,8 +585,8 @@
   //                                                                                    //
   //                     class windows_file_api_codecvt_facet                           //
   //                                                                                    //
-  //  Warning: partial implementation; only do_in and do_out meet the standard library  //
-  //  specifications, and even these do not set from_next.                              //
+  //  Warning: partial implementation; even do_in and do_out only partially meet the    //
+  //  standard library specifications; the "to" buffer must hold the entire result.     //
   //------------------------------------------------------------------------------------//
 
   class windows_file_api_codecvt_facet
@@ -628,6 +634,7 @@
       return error;  // conversion failed
     }
 
+    from_next = from_end;
     to_next = to + count;
     *to_next = L'\0';
     return ok;
@@ -647,6 +654,7 @@
       return error;  // conversion failed
     }
 
+    from_next = from_end;
     to_next = to + count;
     *to_next = '\0';
     return ok;
@@ -733,11 +741,27 @@
   //                                   append                                           //
   //------------------------------------------------------------------------------------//
 
-  void append_error( const char * begin, const char * end )
+  //  actual append done here to factor it out from messy buffer management code;
+  //  this function just assumes the buffer is large enough.
+  inline void do_append( const char * from, const char * from_end,
+                   wchar_t * to, wchar_t * to_end,
+                   wstring & target, error_code & ec )
   {
-    assert( false && "not implemented yet" );
+    std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
+    const char * from_next;
+    wchar_t * to_next;
+
+    if ( wchar_t_codecvt_facet()->in( state, from, from_end, from_next,
+           to, to_end, to_next ) != std::codecvt_base::ok )
+    {
+      assert( 0 && "append error handling not implemented yet" );
+      throw "append error handling not implemented yet";
+    }
+    if ( &ec != &system::throws ) ec.clear();
+    target.append( to, to_next ); 
   }
 
+  BOOST_FILESYSTEM_DECL
   void append( const char * begin, const char * end, wstring & target, error_code & ec )
   {
     if ( !end ) 
@@ -749,68 +773,72 @@
       return;
     }
 
-    std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
-    const char * from_next;
-    wchar_t * to_next;
     std::size_t buf_size = end - begin;  // perhaps too large, but that's OK
-    const std::size_t max_size = 128;
 
     //  dynamically allocate a buffer only if source is unusually large
-    if ( buf_size <= max_size )
+    if ( buf_size > default_codecvt_buf_size )
     {
-      wchar_t buf[max_size];
-      if ( wchar_t_codecvt_facet()->in( state, begin, end,
-            from_next, buf, buf+max_size, to_next ) != std::codecvt_base::ok )
-        append_error( begin, end );
-      else {
-        target.append( buf, to_next ); 
-        if ( &ec != &system::throws ) ec.clear();
-      }
+      boost::scoped_array< wchar_t > buf( new wchar_t [buf_size] );
+      do_append( begin, end, buf.get(), buf.get()+buf_size, target, ec );
     }
     else
     {
-      boost::scoped_array< wchar_t > buf( new wchar_t [ buf_size] ); 
-      if ( wchar_t_codecvt_facet()->in( state, begin, end,
-            from_next, buf.get(), buf.get()+buf_size, to_next ) != std::codecvt_base::ok )
-        append_error( begin, end );
-      else {
-        target.append( buf.get(), to_next ); 
-        if ( &ec != &system::throws ) ec.clear();
-      }
+      wchar_t buf[default_codecvt_buf_size];
+      do_append( begin, end, buf, buf+buf_size, target, ec );
     }
-
   }
 
   //------------------------------------------------------------------------------------//
   //                                  convert                                           //
   //------------------------------------------------------------------------------------//
 
-  BOOST_FILESYSTEM_DECL
-  string convert_to_string( const wstring & src, error_code & ec )
+  //  actual convert done here to factor it out from messy buffer management code;
+  //  this function just assumes the buffer is large enough.
+  inline string  do_convert( const wchar_t * from, const wchar_t * from_end,
+                            char * to, char * to_end, error_code & ec )
   {
-    if ( src.empty() ) return std::string();
+    std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
+    const wchar_t * from_next;
+    char * to_next;
 
-    UINT codepage = AreFileApisANSI() ? CP_THREAD_ACP : CP_OEMCP;
+    if ( wchar_t_codecvt_facet()->out( state, from, from_end,
+          from_next, to, to_end, to_next ) != std::codecvt_base::ok )
+    {
+      assert( 0 && "convert error handling not implemented yet" );
+      throw "convert error handling not implemented yet";
+    }
+    if ( &ec != &system::throws ) ec.clear();
+    return string( to, to_next ); 
+  }
 
-    //  buffer management strategy; use a probably large enough default buffer,
-    //  but fallback to an explict allocation if the default buffer is too small
+  BOOST_FILESYSTEM_DECL
+  string convert_to_string( const wstring & src, error_code & ec )
+  {
+    if ( src.empty() )
+    {
+      if ( &ec != &system::throws ) ec.clear();
+      return std::string();
+    }
 
-    const std::size_t default_buf_sz = MAX_PATH+1;
-    char buf[default_buf_sz+1];
-    int count;
+    //  The codecvt length functions may not be implemented, and I don't reall
+    //  understand them either. Thus this code is really just a guess; it it turns
+    //  out the buffer is too small then an error will be reported and the code
+    //  will have to be fixed.
+    std::size_t buf_size = src.size() * 4;
+    buf_size += 4;  // encodings like shift-JIS need some prefix space
 
-    if ( (count = ::WideCharToMultiByte( codepage, WC_NO_BEST_FIT_CHARS, src.c_str(),
-      src.size(), buf, default_buf_sz, 0, 0 )) != 0 ) // success
+    //  dynamically allocate a buffer only if source is unusually large
+    if ( buf_size > default_codecvt_buf_size )
     {
-      ec.clear();
-      buf[count] = '\0';
-      return std::string( buf );
+      boost::scoped_array< char > buf( new char [buf_size] );
+      return do_convert( src.c_str(), src.c_str()+src.size(),
+        buf.get(), buf.get()+buf_size, ec );
+    }
+    else
+    {
+      char buf[default_codecvt_buf_size];
+      return do_convert( src.c_str(), src.c_str()+src.size(), buf, buf+buf_size, ec );
     }
-
-    // TODO: implement fallback
-    BOOST_ASSERT(0);
-    throw "path::native_string() error handling not implemented yet";
-    return std::string();
   }
 
 }  // namespace detail
Modified: sandbox/filesystem-v3/libs/filesystem/test/path_test.cpp
==============================================================================
--- sandbox/filesystem-v3/libs/filesystem/test/path_test.cpp	(original)
+++ sandbox/filesystem-v3/libs/filesystem/test/path_test.cpp	2009-01-03 09:36:50 EST (Sat, 03 Jan 2009)
@@ -1258,12 +1258,12 @@
   p5 /= "";
   PATH_CHECK( p5, "foo/bar\\" );
   char bf[]= "bar/foo";
-  p5.assign( bf, bf + sizeof(bf) ); 
+  p5.assign( bf, bf + sizeof(bf) - 1 ); 
   PATH_CHECK( p5, bf );
-  p5.append( bf, bf + sizeof(bf) ); 
+  p5.append( bf, bf + sizeof(bf) - 1 ); 
   PATH_CHECK( p5, "bar/foo\\bar/foo" );
 
-  // this code, courtesy of David Whetstone, detected a now fixed bug that
+  // this code, courtesy of David Whetstone, detects a now fixed bug that
   // derefereced the end iterator (assuming debug build with checked itors)
   std::vector<char> v1;
   p5.assign( v1.begin(), v1.end() );
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	2009-01-03 09:36:50 EST (Sat, 03 Jan 2009)
@@ -522,9 +522,11 @@
 
     path p0( L"\u2722" );  // for tests that depend on detail::convert_to_string
     CHECK( p0.string() != "\xE2\x9C\xA2" );
+    string p0_string( p0.string() );
 
     path p1( "\xE2\x9C\xA2" );
     CHECK( p1 != L"\u2722" );
+    wstring p1_wstring( p1.wstring() );
 
     // So that tests are run with known encoding, use Boost UTF-8 codecvt
     std::locale global_loc = std::locale();
@@ -534,13 +536,14 @@
     CHECK( p0.string() == "\xE2\x9C\xA2" );
     path p2( "\xE2\x9C\xA2" );
     CHECK( p2 == L"\u2722" );
+    CHECK( p2.wstring() == L"\u2722" );
 
     path::imbue( old_loc );
 
-    CHECK( p0.string() != "\xE2\x9C\xA2" );
+    CHECK( p0.string() == p0_string );
     path p3( "\xE2\x9C\xA2" );
     CHECK( p3 != L"\u2722" );
-
+    CHECK( p3.wstring() == p1_wstring );
   }
 
 //  //  test_locales  --------------------------------------------------------------------//