Boost logo

Boost-Commit :

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 --------------------------------------------------------------------//


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