Re: [Boost-bugs] [Boost C++ Libraries] #11981: boost::archive::xml_woarchive with locale dosen't work

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #11981: boost::archive::xml_woarchive with locale dosen't work
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2017-09-29 10:38:08


#11981: boost::archive::xml_woarchive with locale dosen't work
-------------------------+-------------------------------------------------
  Reporter: anonymous | Owner: Robert Ramey
      Type: Bugs | Status: reopened
 Milestone: To Be | Component: serialization
  Determined |
   Version: Boost | Severity: Regression
  1.65.0 | Keywords: locale, xml_woarchive,
Resolution: | serialization
-------------------------+-------------------------------------------------
Changes (by matsu):

 * status: closed => reopened
 * version: Boost 1.60.0 => Boost 1.65.0
 * resolution: wontfix =>

Comment:

 This problem still exists on boost 1.65.1.
 Platform. Windows 10 Japanese 64bit. Visual Studio 2017 Update 1.

 Abort is called at this line.
 {{{
 oa << boost::serialization::make_nvp("string", std::string("日本語文字列
 "));
 }}}

 This is because std::string is not always UTF-8 encoding.
 It depends on the locale, in my case it is Shift_JIS encording.
 But utf8_codecvt_facet is always used in xml_woarchive_impl.ipp.

 I have changed utf8_codecvt_facet to mbstowcs_s and it works well.
 mbstowcs_s refers the locale and converts accordingly.

 xml_woarchive_impl.ipp
 {{{
 #define BOOST_NO_UTF8 // my change
 #ifdef BOOST_NO_UTF8
 #include <stdlib.h>
 #else
 #include <boost/archive/iterators/wchar_from_mb.hpp>
 #endif

 // copy chars to output escaping to xml and widening characters as we go
 template<class InputIterator>
 void save_iterator(std::wostream &os, InputIterator begin, InputIterator
 end){
 #ifdef BOOST_NO_UTF8
     std::size_t len = end - begin + 1;
     std::vector<wchar_t> dst(len);
     if (::mbstowcs_s(&len, dst.data(), len, begin, len - 1) != 0) {
         throw std::system_error(errno, std::system_category());
     }
     std::copy(
         dst.data(),
         dst.data() + len - 1,
         boost::archive::iterators::ostream_iterator<wchar_t>(os)
     );
 #else
     typedef iterators::wchar_from_mb<
         iterators::xml_escape<InputIterator>
> xmbtows;
     std::copy(
         xmbtows(begin),
         xmbtows(end),
         boost::archive::iterators::ostream_iterator<wchar_t>(os)
     );
 #endif
 }
 }}}

 xml_wiarchive_impl.ipp
 {{{
 #define BOOST_NO_UTF8 // my change
 #ifdef BOOST_NO_UTF8
 #include <stdlib.h>
 #else
 #include <boost/archive/iterators/wchar_from_mb.hpp>
 #endif

 void copy_to_ptr(char * s, const std::wstring & ws){
 #ifdef BOOST_NO_UTF8
     std::size_t len = ws.size() * sizeof(wchar_t) + 1;
     if (::wcstombs_s(&len, s, len, ws.c_str(), len - 1) != 0) {
         throw std::system_error(errno, std::system_category());
     }
 #else
     std::copy(
         iterators::mb_from_wchar<std::wstring::const_iterator>(
             ws.begin()
         ),
         iterators::mb_from_wchar<std::wstring::const_iterator>(
             ws.end()
         ),
         s
     );
     s[ws.size()] = 0;
 #endif
 }

 template<class Archive>
 BOOST_WARCHIVE_DECL void
 xml_wiarchive_impl<Archive>::load(std::string & s){
     std::wstring ws;
     bool result = gimpl->parse_string(is, ws);
     if(! result)
         boost::serialization::throw_exception(
 xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
         );
     #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
     if(NULL != s.data())
     #endif
         s.resize(0);
 #ifdef BOOST_NO_UTF8
     std::size_t len = ws.size() * sizeof(wchar_t) + 1;
     s.resize(len);
     if (::wcstombs_s(&len, &s[0], len, ws.c_str(), _TRUNCATE) != 0) {
         throw std::system_error(errno, std::system_category());
     }
     s.resize(len - 1);
 #else
     s.reserve(ws.size());
     std::copy(
         iterators::mb_from_wchar<std::wstring::iterator>(
             ws.begin()
         ),
         iterators::mb_from_wchar<std::wstring::iterator>(
             ws.end()
         ),
         std::back_inserter(s)
     );
 #endif
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac10/boost/ticket/11981#comment:7>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-09-29 10:44:22 UTC