|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r63283 - in trunk: boost/filesystem/v3 libs/filesystem/v3/src libs/filesystem/v3/test
From: bdawes_at_[hidden]
Date: 2010-06-24 07:10:39
Author: bemandawes
Date: 2010-06-24 07:10:37 EDT (Thu, 24 Jun 2010)
New Revision: 63283
URL: http://svn.boost.org/trac/boost/changeset/63283
Log:
Provide const codecvt& arguments for all applicable class path functions
Text files modified:
trunk/boost/filesystem/v3/path.hpp | 251 +++++++++++++++++++++++++--------------
trunk/libs/filesystem/v3/src/path.cpp | 13 -
trunk/libs/filesystem/v3/test/path_unit_test.cpp | 63 ++++++++++
3 files changed, 223 insertions(+), 104 deletions(-)
Modified: trunk/boost/filesystem/v3/path.hpp
==============================================================================
--- trunk/boost/filesystem/v3/path.hpp (original)
+++ trunk/boost/filesystem/v3/path.hpp 2010-06-24 07:10:37 EDT (Thu, 24 Jun 2010)
@@ -44,22 +44,6 @@
// //
//------------------------------------------------------------------------------------//
-/*
- Why are there no const codecvt_type& arguments?
- ------------------------------------------------
-
- To hold down the size of the class path interface. Per function codecvt facets
- just aren't needed very often in practice.
-
- An RAII idiom can be used to ensure push/pop behavior as an alternative.
-
- Note that codecvt() is passed to the path_traits::convert functions, since that
- decouples the convert functions from class path.
-
- const codecvt_type & can be added later, but once added, they can never be removed
- since that would break user code.
-*/
-
class BOOST_FILESYSTEM_DECL path
{
public:
@@ -68,12 +52,13 @@
// represent paths.
# ifdef BOOST_WINDOWS_API
- typedef wchar_t value_type;
+ typedef wchar_t value_type;
# else
- typedef char value_type;
+ typedef char value_type;
# endif
- typedef std::basic_string<value_type> string_type;
- typedef path_traits::codecvt_type codecvt_type;
+ typedef std::basic_string<value_type> string_type;
+ typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
+
// ----- character encoding conversions -----
@@ -101,20 +86,6 @@
//
// See m_pathname comments for further important rationale.
- // Design alternative; each function can have an additional overload that
- // supplies a conversion locale. For example:
- //
- // template< class ForwardIterator, class WStringConvert >
- // path(ForwardIterator begin, ForwardIterator end,
- // const std::locale & loc,
- // system::error_code & ec = boost::throws());
- //
- // This alternative was rejected as too complex for the limited benefits;
- // it nearly doubles the size of the interface, and adds a lot of
- // implementation and test code, yet would likely be rarely used. The same
- // effect can be achieved via the much simpler imbue() mechanism.
-
-
// TODO: rules needed for operating systems that use / or .
// differently, or format directory paths differently from file paths.
//
@@ -139,11 +110,28 @@
// multi-byte character strings which may have embedded nulls. Embedded null
// support is required for some Asian languages on Windows.
+ // "const codecvt_type& cvt=codecvt()" default arguments are not used because some
+ // compilers, such as Microsoft prior to VC++ 10, do not handle defaults correctly
+ // in templates.
+
// ----- constructors -----
path(){}
path(const path& p) : m_pathname(p.m_pathname) {}
+
+ template <class Source>
+ path(Source const& source)
+ {
+ path_traits::dispatch(source, m_pathname, codecvt());
+ }
+
+ template <class Source>
+ path(Source const& source, const codecvt_type& cvt)
+ // see note above explaining why codecvt() default arguments are not used
+ {
+ path_traits::dispatch(source, m_pathname, cvt);
+ }
template <class InputIterator>
path(InputIterator begin, InputIterator end)
@@ -156,10 +144,15 @@
}
}
- template <class Source>
- path(Source const& source)
- {
- path_traits::dispatch(source, m_pathname, codecvt());
+ template <class InputIterator>
+ path(InputIterator begin, InputIterator end, const codecvt_type& cvt)
+ {
+ if (begin != end)
+ {
+ std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
+ s(begin, end);
+ path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
+ }
}
// ----- assignments -----
@@ -170,27 +163,41 @@
return *this;
}
+ template <class Source>
+ path& operator=(Source const& source)
+ {
+ m_pathname.clear();
+ path_traits::dispatch(source, m_pathname, codecvt());
+ return *this;
+ }
+
+ template <class Source>
+ path& assign(Source const& source, const codecvt_type& cvt)
+ {
+ m_pathname.clear();
+ path_traits::dispatch(source, m_pathname, cvt);
+ return *this;
+ }
+
template <class InputIterator>
path& assign(InputIterator begin, InputIterator end)
+ {
+ return assign(begin, end, codecvt());
+ }
+
+ template <class InputIterator>
+ path& assign(InputIterator begin, InputIterator end, const codecvt_type& cvt)
{
m_pathname.clear();
if (begin != end)
{
std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
s(begin, end);
- path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, codecvt());
+ path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
}
return *this;
}
- template <class Source>
- path& operator=(Source const& source)
- {
- m_pathname.clear();
- path_traits::dispatch(source, m_pathname, codecvt());
- return *this;
- }
-
// ----- appends -----
// if a separator is added, it is the preferred separator for the platform;
@@ -198,22 +205,34 @@
path& operator/=(const path& p);
- template <class InputIterator>
- path& append(InputIterator begin, InputIterator end);
+ template <class Source>
+ path& operator/=(Source const& source)
+ {
+ return append(source, codecvt());
+ }
template <class Source>
- path& operator/=(Source const& source);
+ path& append(Source const& source, const codecvt_type& cvt);
+
+ template <class InputIterator>
+ path& append(InputIterator begin, InputIterator end)
+ {
+ return append(begin, end, codecvt());
+ }
+
+ template <class InputIterator>
+ path& append(InputIterator begin, InputIterator end, const codecvt_type& cvt);
// ----- modifiers -----
void clear() { m_pathname.clear(); }
path& make_absolute(const path& base);
path& make_preferred()
-# ifdef BOOST_POSIX_API
- { return *this; } // POSIX no effect
-# else // BOOST_WINDOWS_API
- ; // change slashes to backslashes
-# endif
+# ifdef BOOST_POSIX_API
+ { return *this; } // POSIX no effect
+# else // BOOST_WINDOWS_API
+ ; // change slashes to backslashes
+# endif
path& remove_filename();
path& replace_extension(const path& new_extension = path());
void swap(path& rhs) { m_pathname.swap(rhs.m_pathname); }
@@ -245,18 +264,36 @@
template <class String>
String string() const;
+ template <class String>
+ String string(const codecvt_type& cvt) const;
+
# ifdef BOOST_WINDOWS_API
- const std::string string() const;
+ const std::string string() const { return string(codecvt()); }
+ const std::string string(const codecvt_type& cvt) const
+ {
+ std::string tmp;
+ if (!m_pathname.empty())
+ path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
+ tmp, cvt);
+ return tmp;
+ }
+
+ // string_type is std::wstring, so there is no conversion
const std::wstring& wstring() const { return m_pathname; }
+ const std::wstring& wstring(const codecvt_type&) const { return m_pathname; }
# else // BOOST_POSIX_API
- const std::string& string() const { return m_pathname; }
- const std::wstring wstring() const
+ // string_type is std::string, so there is no conversion
+ const std::string& string() const { return m_pathname; }
+ const std::string& string(const codecvt_type&) const { return m_pathname; }
+
+ const std::wstring wstring() const { return wstring(codecvt()); }
+ const std::wstring wstring(const codecvt_type& cvt) const
{
std::wstring tmp;
if (!m_pathname.empty())
path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
- tmp, codecvt());
+ tmp, cvt);
return tmp;
}
@@ -267,13 +304,21 @@
template <class String>
String generic_string() const;
+ template <class String>
+ String generic_string(const codecvt_type& cvt) const;
+
# ifdef BOOST_WINDOWS_API
- const std::string generic_string() const;
+ const std::string generic_string() const { return generic_string(codecvt()); }
+ const std::string generic_string(const codecvt_type& cvt) const;
const std::wstring generic_wstring() const;
+ const std::wstring generic_wstring(const codecvt_type&) const { return generic_wstring(); };
# else // BOOST_POSIX_API
+ // On POSIX-like systems, the generic format is the same as the native format
const std::string& generic_string() const { return m_pathname; }
+ const std::string& generic_string(const codecvt_type&) const { return m_pathname; }
const std::wstring generic_wstring() const { return wstring(); }
+ const std::wstring generic_wstring(const codecvt_type&) const { return wstring(); }
# endif
@@ -312,11 +357,11 @@
// ----- imbue -----
- static std::locale imbue(const std::locale & loc);
+ static std::locale imbue(const std::locale& loc);
// ----- codecvt -----
- static const codecvt_type & codecvt()
+ static const codecvt_type& codecvt()
{
return *wchar_t_codecvt_facet();
}
@@ -453,30 +498,30 @@
// m_pos == m_path_ptr->m_pathname.size()
}; // path::iterator
- //------------------------------------------------------------------------------------//
- // //
- // class scoped_path_locale //
- // //
- //------------------------------------------------------------------------------------//
+ ////------------------------------------------------------------------------------------//
+ //// //
+ //// class scoped_path_locale //
+ //// //
+ ////------------------------------------------------------------------------------------//
- class scoped_path_locale
- {
- public:
- scoped_path_locale(const std::locale & loc)
- : m_saved_locale(loc)
- {
- path::imbue(loc);
- }
-
- ~scoped_path_locale() // never throws()
- {
- try { path::imbue(m_saved_locale); }
- catch (...) {}
- };
-
- private:
- std::locale m_saved_locale;
- };
+ //class scoped_path_locale
+ //{
+ //public:
+ // scoped_path_locale(const std::locale & loc)
+ // : m_saved_locale(loc)
+ // {
+ // path::imbue(loc);
+ // }
+
+ // ~scoped_path_locale() // never throws()
+ // {
+ // try { path::imbue(m_saved_locale); }
+ // catch (...) {}
+ // };
+
+ //private:
+ // std::locale m_saved_locale;
+ //};
//------------------------------------------------------------------------------------//
// //
@@ -581,26 +626,26 @@
//--------------------------------------------------------------------------------------//
template <class InputIterator>
- path& path::append(InputIterator begin, InputIterator end)
+ path& path::append(InputIterator begin, InputIterator end, const codecvt_type& cvt)
{
if (begin == end)
return *this;
string_type::size_type sep_pos(m_append_separator_if_needed());
std::basic_string<typename std::iterator_traits<InputIterator>::value_type>
s(begin, end);
- path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, codecvt());
+ path_traits::convert(s.c_str(), s.c_str()+s.size(), m_pathname, cvt);
if (sep_pos)
m_erase_redundant_separator(sep_pos);
return *this;
}
template <class Source>
- path& path::operator/=(Source const & source)
+ path& path::append(Source const & source, const codecvt_type& cvt)
{
if (path_traits::empty(source))
return *this;
string_type::size_type sep_pos(m_append_separator_if_needed());
- path_traits::dispatch(source, m_pathname, codecvt());
+ path_traits::dispatch(source, m_pathname, cvt);
if (sep_pos)
m_erase_redundant_separator(sep_pos);
return *this;
@@ -611,16 +656,36 @@
//--------------------------------------------------------------------------------------//
template <> inline
- std::string path::string<std::string>() const { return string(); }
+ std::string path::string<std::string>() const
+ { return string(); }
+
+ template <> inline
+ std::wstring path::string<std::wstring>() const
+ { return wstring(); }
+
+ template <> inline
+ std::string path::string<std::string>(const codecvt_type& cvt) const
+ { return string(cvt); }
+
+ template <> inline
+ std::wstring path::string<std::wstring>(const codecvt_type& cvt) const
+ { return wstring(cvt); }
+
+ template <> inline
+ std::string path::generic_string<std::string>() const
+ { return generic_string(); }
template <> inline
- std::wstring path::string<std::wstring>() const { return wstring(); }
+ std::string path::generic_string<std::string>(const codecvt_type& cvt) const
+ { return generic_string(cvt); }
template <> inline
- std::string path::generic_string<std::string>() const { return generic_string(); }
+ std::wstring path::generic_string<std::wstring>() const
+ { return generic_wstring(); }
template <> inline
- std::wstring path::generic_string<std::wstring>() const { return generic_wstring(); }
+ std::wstring path::generic_string<std::wstring>(const codecvt_type& cvt) const
+ { return generic_wstring(cvt); }
} // namespace filesystem3
Modified: trunk/libs/filesystem/v3/src/path.cpp
==============================================================================
--- trunk/libs/filesystem/v3/src/path.cpp (original)
+++ trunk/libs/filesystem/v3/src/path.cpp 2010-06-24 07:10:37 EDT (Thu, 24 Jun 2010)
@@ -148,15 +148,6 @@
# ifdef BOOST_WINDOWS_API
- const std::string path::string() const
- {
- std::string tmp;
- if (!m_pathname.empty())
- path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
- tmp, codecvt());
- return tmp;
- }
-
void path::m_portable()
{
for (string_type::iterator it = m_pathname.begin();
@@ -167,11 +158,11 @@
}
}
- const std::string path::generic_string() const
+ const std::string path::generic_string(const codecvt_type& cvt) const
{
path tmp(*this);
tmp.m_portable();
- return tmp.string();
+ return tmp.string(cvt);
}
const std::wstring path::generic_wstring() const
Modified: trunk/libs/filesystem/v3/test/path_unit_test.cpp
==============================================================================
--- trunk/libs/filesystem/v3/test/path_unit_test.cpp (original)
+++ trunk/libs/filesystem/v3/test/path_unit_test.cpp 2010-06-24 07:10:37 EDT (Thu, 24 Jun 2010)
@@ -175,6 +175,9 @@
path xll(wl); // std::list<wchar_t>
PATH_IS(xll, L"wstring");
BOOST_TEST_EQ(xll.native().size(), 7U);
+
+ // easy-to-make coding errors
+ // path e1(x0, path::codecvt()); // fails to compile, and that is OK
}
path x;
@@ -636,6 +639,65 @@
std::cout << " locale testing complete" << std::endl;
}
+ // test_codecvt_argument -----------------------------------------------------------//
+
+ void test_codecvt_argument()
+ {
+ std::cout << "testing codecvt arguments..." << std::endl;
+
+ // U+2780 is DINGBAT CIRCLED SANS-SERIF DIGIT ONE == 0xE2 0x9E 0x80 in UTF-8
+ // U+1234 is ETHIOPIC SYLLABLE SEE == 0xE1 0x88 0xB4 in UTF-8
+
+ const char * c1 = "\xE2\x9E\x80\xE1\x88\xB4";
+ const std::string s1("\xE2\x9E\x80\xE1\x88\xB4");
+ const std::wstring ws1(L"\u2780\u1234");
+
+ fs::detail::utf8_codecvt_facet cvt;
+
+ // constructors
+ path p(c1, cvt);
+ CHECK(p == path(ws1));
+ path p1(s1.begin(), s1.end(), cvt);
+ CHECK(p1 == path(ws1));
+ // path p2(p1, cvt); // fails to compile, and that is OK
+
+ // assigns
+ p1.clear();
+ p1.assign(s1,cvt);
+ CHECK(p == p1);
+ p1.clear();
+ p1.assign(s1.begin(), s1.end(), cvt);
+ CHECK(p == p1);
+ // p1.assign(p, cvt); // fails to compile, and that is OK
+
+
+ // appends
+ p1.clear();
+ p1.append(s1,cvt);
+ CHECK(p == p1);
+ p1.clear();
+ p1.append(s1.begin(), s1.end(), cvt);
+ CHECK(p == p1);
+ // p1.append(p, cvt); // fails to compile, and that is OK
+
+ // native observers
+# ifdef BOOST_WINDOWS_API
+ CHECK(p.string<std::string>() != s1); // non-Windows systems may have UTF-8 as default
+# endif
+ CHECK(p.string<std::string>(cvt) == s1);
+ CHECK(p.string(cvt) == s1);
+ CHECK(p.string<std::wstring>(cvt) == ws1);
+ CHECK(p.wstring(cvt) == ws1);
+
+ // generic observers
+ CHECK(p.generic_string<std::string>(cvt) == s1);
+ CHECK(p.generic_string(cvt) == s1);
+ CHECK(p.generic_string<std::wstring>(cvt) == ws1);
+ CHECK(p.generic_wstring(cvt) == ws1);
+
+ std::cout << " codecvt arguments testing complete" << std::endl;
+ }
+
// test_overloads ------------------------------------------------------------------//
void test_overloads()
@@ -904,6 +966,7 @@
test_decompositions();
test_queries();
test_imbue_locale();
+ test_codecvt_argument();
test_error_handling();
# if 0
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