From 1a0ab95594da0a818134308d04dd43e491c01d00 Mon Sep 17 00:00:00 2001 From: Georg Gast Date: Fri, 14 Oct 2022 13:16:00 +0200 Subject: [PATCH] Implementations for std::pmr::string (#267) --- .../boost/archive/basic_binary_iprimitive.hpp | 12 +++++ .../boost/archive/basic_binary_oprimitive.hpp | 14 ++++++ .../archive/impl/basic_binary_iprimitive.ipp | 34 ++++++++++++++ .../archive/impl/basic_binary_oprimitive.ipp | 25 ++++++++++ .../boost/archive/impl/basic_xml_grammar.hpp | 10 ++++ .../boost/archive/impl/text_iarchive_impl.ipp | 36 ++++++++++++++- .../boost/archive/impl/text_oarchive_impl.ipp | 22 +++++++++ .../boost/archive/impl/xml_iarchive_impl.ipp | 46 +++++++++++++++++++ .../boost/archive/impl/xml_oarchive_impl.ipp | 26 +++++++++++ include/boost/archive/text_iarchive.hpp | 12 +++++ include/boost/archive/text_oarchive.hpp | 12 +++++ include/boost/archive/xml_iarchive.hpp | 14 +++++- include/boost/archive/xml_oarchive.hpp | 12 +++++ include/boost/serialization/string.hpp | 8 ++++ src/basic_xml_grammar.ipp | 15 ++++++ 15 files changed, 296 insertions(+), 2 deletions(-) diff --git a/include/boost/archive/basic_binary_iprimitive.hpp b/include/boost/archive/basic_binary_iprimitive.hpp index f197ead00d..aacd3ab149 100644 --- a/include/boost/archive/basic_binary_iprimitive.hpp +++ b/include/boost/archive/basic_binary_iprimitive.hpp @@ -43,6 +43,10 @@ namespace std{ } // namespace std #endif +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #include #include #include @@ -107,9 +111,17 @@ class BOOST_SYMBOL_VISIBLE basic_binary_iprimitive { } BOOST_ARCHIVE_OR_WARCHIVE_DECL void load(std::string &s); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_OR_WARCHIVE_DECL void + load(std::pmr::string &s); + #endif #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_OR_WARCHIVE_DECL void load(std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_OR_WARCHIVE_DECL void + load(std::pmr::wstring& ws); + #endif #endif BOOST_ARCHIVE_OR_WARCHIVE_DECL void load(char * t); diff --git a/include/boost/archive/basic_binary_oprimitive.hpp b/include/boost/archive/basic_binary_oprimitive.hpp index bf44ac50d1..f4cc091284 100644 --- a/include/boost/archive/basic_binary_oprimitive.hpp +++ b/include/boost/archive/basic_binary_oprimitive.hpp @@ -37,6 +37,10 @@ namespace std{ } // namespace std #endif +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #include #include #include @@ -101,9 +105,19 @@ class BOOST_SYMBOL_VISIBLE basic_binary_oprimitive { } BOOST_ARCHIVE_OR_WARCHIVE_DECL void save(const std::string &s); + + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_OR_WARCHIVE_DECL void + save(const std::pmr::string &s); + #endif + #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_OR_WARCHIVE_DECL void save(const std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_OR_WARCHIVE_DECL void + save(const std::pmr::wstring& ws); + #endif #endif BOOST_ARCHIVE_OR_WARCHIVE_DECL void save(const char * t); diff --git a/include/boost/archive/impl/basic_binary_iprimitive.ipp b/include/boost/archive/impl/basic_binary_iprimitive.ipp index e2d051080e..f2a8d046d4 100644 --- a/include/boost/archive/impl/basic_binary_iprimitive.ipp +++ b/include/boost/archive/impl/basic_binary_iprimitive.ipp @@ -114,6 +114,24 @@ basic_binary_iprimitive::load(std::string & s) load_binary(&(*s.begin()), l); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL void +basic_binary_iprimitive::load(std::pmr::string & s) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(l); + // note breaking a rule here - could be a problem on some platform + if(0 < l) + load_binary(&(*s.begin()), l); +} +#endif + template BOOST_ARCHIVE_OR_WARCHIVE_DECL void basic_binary_iprimitive::load(char * s) @@ -139,6 +157,22 @@ basic_binary_iprimitive::load(std::wstring & ws) // note breaking a rule here - is could be a problem on some platform load_binary(const_cast(ws.data()), l * sizeof(wchar_t) / sizeof(char)); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL void +basic_binary_iprimitive::load(std::pmr::wstring& ws) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if (NULL != ws.data()) + #endif + ws.resize(l); + // note breaking a rule here - is could be a problem on some platform + load_binary(const_cast(ws.data()), l * sizeof(wchar_t) / sizeof(char)); +} +#endif #endif template diff --git a/include/boost/archive/impl/basic_binary_oprimitive.ipp b/include/boost/archive/impl/basic_binary_oprimitive.ipp index 7b042173a4..5ee7456f19 100644 --- a/include/boost/archive/impl/basic_binary_oprimitive.ipp +++ b/include/boost/archive/impl/basic_binary_oprimitive.ipp @@ -20,6 +20,10 @@ namespace std{ } // namespace std #endif +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #ifndef BOOST_NO_CWCHAR #include #ifdef BOOST_NO_STDC_NAMESPACE @@ -70,6 +74,17 @@ basic_binary_oprimitive::save(const std::string &s) save_binary(s.data(), l); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL void +basic_binary_oprimitive::save(const std::pmr::string &s) +{ + std::size_t l = static_cast(s.size()); + this->This()->save(l); + save_binary(s.data(), l); +} +#endif + #ifndef BOOST_NO_CWCHAR #ifndef BOOST_NO_INTRINSIC_WCHAR_T template @@ -91,6 +106,16 @@ basic_binary_oprimitive::save(const std::wstring &ws) this->This()->save(l); save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL void +basic_binary_oprimitive::save(const std::pmr::wstring& ws) +{ + std::size_t l = ws.size(); + this->This()->save(l); + save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); +} +#endif #endif #endif // BOOST_NO_CWCHAR diff --git a/include/boost/archive/impl/basic_xml_grammar.hpp b/include/boost/archive/impl/basic_xml_grammar.hpp index 8f70e3d2cf..563bac49ca 100644 --- a/include/boost/archive/impl/basic_xml_grammar.hpp +++ b/include/boost/archive/impl/basic_xml_grammar.hpp @@ -57,6 +57,10 @@ #include #include +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + namespace boost { namespace archive { @@ -74,6 +78,9 @@ class BOOST_SYMBOL_VISIBLE basic_xml_grammar { private: typedef typename std::basic_istream IStream; typedef typename std::basic_string StringType; + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + typedef typename std::pmr::basic_string PmrStringType; + #endif typedef typename boost::spirit::classic::chset chset_t; typedef typename boost::spirit::classic::chlit chlit_t; typedef typename boost::spirit::classic::scanner< @@ -162,6 +169,9 @@ class BOOST_SYMBOL_VISIBLE basic_xml_grammar { bool parse_start_tag(IStream & is) /*const*/; bool parse_end_tag(IStream & is) const; bool parse_string(IStream & is, StringType & s) /*const*/; + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + bool parse_string(IStream & is, PmrStringType & s) /*const*/; + #endif void init(IStream & is); bool windup(IStream & is); basic_xml_grammar(); diff --git a/include/boost/archive/impl/text_iarchive_impl.ipp b/include/boost/archive/impl/text_iarchive_impl.ipp index a3a80c04de..ba678c2fc7 100644 --- a/include/boost/archive/impl/text_iarchive_impl.ipp +++ b/include/boost/archive/impl/text_iarchive_impl.ipp @@ -56,6 +56,24 @@ text_iarchive_impl::load(std::string &s) if(0 < size) is.read(&(*s.begin()), size); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +text_iarchive_impl::load(std::pmr::string& s) +{ + std::size_t size; + *this->This() >> size; + // skip separating space + is.get(); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if (NULL != s.data()) + #endif + s.resize(size); + if (0 < size) + is.read(&(*s.begin()), size); +} +#endif #ifndef BOOST_NO_CWCHAR #ifndef BOOST_NO_INTRINSIC_WCHAR_T @@ -88,7 +106,23 @@ text_iarchive_impl::load(std::wstring &ws) is.get(); is.read((char *)ws.data(), size * sizeof(wchar_t)/sizeof(char)); } - +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +text_iarchive_impl::load(std::pmr::wstring& ws) +{ + std::size_t size; + *this->This() >> size; + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if (NULL != ws.data()) + #endif + ws.resize(size); + // skip separating space + is.get(); + is.read((char*)ws.data(), size * sizeof(wchar_t) / sizeof(char)); +} +#endif // BOOST_NO_CXX17_HDR_MEMORY_RESOURCE #endif // BOOST_NO_STD_WSTRING #endif // BOOST_NO_CWCHAR diff --git a/include/boost/archive/impl/text_oarchive_impl.ipp b/include/boost/archive/impl/text_oarchive_impl.ipp index 26fbc23adb..cd938698e8 100644 --- a/include/boost/archive/impl/text_oarchive_impl.ipp +++ b/include/boost/archive/impl/text_oarchive_impl.ipp @@ -54,6 +54,17 @@ text_oarchive_impl::save(const std::string &s) this->This()->newtoken(); os << s; } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +text_oarchive_impl::save(const std::pmr::string& s) +{ + const std::size_t size = s.size(); + *this->This() << size; + this->This()->newtoken(); + os << s; +} +#endif #ifndef BOOST_NO_CWCHAR #ifndef BOOST_NO_INTRINSIC_WCHAR_T @@ -78,6 +89,17 @@ text_oarchive_impl::save(const std::wstring &ws) this->This()->newtoken(); os.write((const char *)(ws.data()), l * sizeof(wchar_t)/sizeof(char)); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +text_oarchive_impl::save(const std::pmr::wstring& ws) +{ + const std::size_t l = ws.size(); + *this->This() << l; + this->This()->newtoken(); + os.write((const char*)(ws.data()), l * sizeof(wchar_t) / sizeof(char)); +} +#endif #endif #endif // BOOST_NO_CWCHAR diff --git a/include/boost/archive/impl/xml_iarchive_impl.ipp b/include/boost/archive/impl/xml_iarchive_impl.ipp index b0847d4a1b..1a5c0607d2 100644 --- a/include/boost/archive/impl/xml_iarchive_impl.ipp +++ b/include/boost/archive/impl/xml_iarchive_impl.ipp @@ -85,6 +85,40 @@ xml_iarchive_impl::load(std::wstring &ws){ ws += wc; } } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +xml_iarchive_impl::load(std::pmr::wstring& ws) { + std::string s; + bool result = gimpl->parse_string(is, s); + 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 != ws.data()) + #endif + ws.resize(0); + std::mbstate_t mbs = std::mbstate_t(); + const char* start = s.data(); + const char* end = start + s.size(); + while (start < end) { + wchar_t wc; + std::size_t count = std::mbrtowc(&wc, start, end - start, &mbs); + if (count == static_cast(-1)) + boost::serialization::throw_exception( + iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + ) + ); + if (count == static_cast(-2)) + continue; + start += count; + ws += wc; + } +} +#endif // BOOST_NO_CXX17_HDR_MEMORY_RESOURCE #endif // BOOST_NO_STD_WSTRING #ifndef BOOST_NO_INTRINSIC_WCHAR_T @@ -134,6 +168,18 @@ xml_iarchive_impl::load(std::string &s){ ); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +xml_iarchive_impl::load(std::pmr::string &s){ + bool result = gimpl->parse_string(is, s); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); +} +#endif + template BOOST_ARCHIVE_DECL void xml_iarchive_impl::load(char * s){ diff --git a/include/boost/archive/impl/xml_oarchive_impl.ipp b/include/boost/archive/impl/xml_oarchive_impl.ipp index 0f4ccbbf98..e7a81e2090 100644 --- a/include/boost/archive/impl/xml_oarchive_impl.ipp +++ b/include/boost/archive/impl/xml_oarchive_impl.ipp @@ -58,6 +58,16 @@ xml_oarchive_impl::save(const std::wstring & ws){ // save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data())); save_iterator(os, ws.data(), ws.data() + ws.size()); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +xml_oarchive_impl::save(const std::pmr::wstring& ws) { + // at least one library doesn't typedef value_type for strings + // so rather than using string directly make a pointer iterator out of it + // save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data())); + save_iterator(os, ws.data(), ws.data() + ws.size()); +} +#endif #endif #ifndef BOOST_NO_INTRINSIC_WCHAR_T @@ -84,6 +94,22 @@ xml_oarchive_impl::save(const std::string & s){ boost::archive::iterators::ostream_iterator(os) ); } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +BOOST_ARCHIVE_DECL void +xml_oarchive_impl::save(const std::pmr::string& s) { + // at least one library doesn't typedef value_type for strings + // so rather than using string directly make a pointer iterator out of it + typedef boost::archive::iterators::xml_escape< + const char* + > xml_escape_translator; + std::copy( + xml_escape_translator(s.data()), + xml_escape_translator(s.data() + s.size()), + boost::archive::iterators::ostream_iterator(os) + ); +} +#endif template BOOST_ARCHIVE_DECL void diff --git a/include/boost/archive/text_iarchive.hpp b/include/boost/archive/text_iarchive.hpp index 73fc39f5f8..01769e2e98 100644 --- a/include/boost/archive/text_iarchive.hpp +++ b/include/boost/archive/text_iarchive.hpp @@ -25,6 +25,10 @@ #include #include +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #include // must be the last header #ifdef BOOST_MSVC @@ -73,9 +77,17 @@ class BOOST_SYMBOL_VISIBLE text_iarchive_impl : #endif BOOST_ARCHIVE_DECL void load(std::string &s); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + load(std::pmr::string& s); + #endif #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_DECL void load(std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + load(std::pmr::wstring& ws); + #endif #endif template void load_override(T & t){ diff --git a/include/boost/archive/text_oarchive.hpp b/include/boost/archive/text_oarchive.hpp index f94f876d7a..5d8e6955db 100644 --- a/include/boost/archive/text_oarchive.hpp +++ b/include/boost/archive/text_oarchive.hpp @@ -32,6 +32,10 @@ namespace std{ #include #include +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #include // must be the last header #ifdef BOOST_MSVC @@ -78,9 +82,17 @@ class BOOST_SYMBOL_VISIBLE text_oarchive_impl : #endif BOOST_ARCHIVE_DECL void save(const std::string &s); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + save(const std::pmr::string& s); + #endif #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_DECL void save(const std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + save(const std::pmr::wstring& ws); + #endif #endif BOOST_ARCHIVE_DECL text_oarchive_impl(std::ostream & os, unsigned int flags); diff --git a/include/boost/archive/xml_iarchive.hpp b/include/boost/archive/xml_iarchive.hpp index 2d04edcb4a..e89980cc1b 100644 --- a/include/boost/archive/xml_iarchive.hpp +++ b/include/boost/archive/xml_iarchive.hpp @@ -27,6 +27,10 @@ #include // must be the last header +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -84,11 +88,19 @@ class BOOST_SYMBOL_VISIBLE xml_iarchive_impl : BOOST_ARCHIVE_DECL void load(wchar_t * t); #endif + BOOST_ARCHIVE_DECL void + load(std::string &s); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE BOOST_ARCHIVE_DECL void - load(std::string &s); + load(std::pmr::string &s); + #endif #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_DECL void load(std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + load(std::pmr::wstring &ws); + #endif #endif template void load_override(T & t){ diff --git a/include/boost/archive/xml_oarchive.hpp b/include/boost/archive/xml_oarchive.hpp index 84871b2d5f..516258f761 100644 --- a/include/boost/archive/xml_oarchive.hpp +++ b/include/boost/archive/xml_oarchive.hpp @@ -34,6 +34,10 @@ namespace std{ #include // must be the last header +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +#endif + #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4511 4512) @@ -79,9 +83,17 @@ class BOOST_SYMBOL_VISIBLE xml_oarchive_impl : #endif BOOST_ARCHIVE_DECL void save(const std::string &s); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + save(const std::pmr::string& s); + #endif #ifndef BOOST_NO_STD_WSTRING BOOST_ARCHIVE_DECL void save(const std::wstring &ws); + #ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + BOOST_ARCHIVE_DECL void + save(const std::pmr::wstring& ws); + #endif #endif BOOST_ARCHIVE_DECL xml_oarchive_impl(std::ostream & os, unsigned int flags); diff --git a/include/boost/serialization/string.hpp b/include/boost/serialization/string.hpp index edcbd4b143..0f3907a041 100644 --- a/include/boost/serialization/string.hpp +++ b/include/boost/serialization/string.hpp @@ -27,4 +27,12 @@ BOOST_CLASS_IMPLEMENTATION(std::string, boost::serialization::primitive_type) BOOST_CLASS_IMPLEMENTATION(std::wstring, boost::serialization::primitive_type) #endif +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +#include +BOOST_CLASS_IMPLEMENTATION(std::pmr::string, boost::serialization::primitive_type) +#ifndef BOOST_NO_STD_WSTRING +BOOST_CLASS_IMPLEMENTATION(std::pmr::wstring, boost::serialization::primitive_type) +#endif +#endif // BOOST_NO_CXX17_HDR_MEMORY_RESOURCE + #endif // BOOST_SERIALIZATION_STRING_HPP diff --git a/src/basic_xml_grammar.ipp b/src/basic_xml_grammar.ipp index dcec1cc6be..f6ece82980 100644 --- a/src/basic_xml_grammar.ipp +++ b/src/basic_xml_grammar.ipp @@ -241,6 +241,21 @@ bool basic_xml_grammar::parse_string(IStream & is, StringType & s){ return result; } +#ifndef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE +template +bool basic_xml_grammar::parse_string(IStream & is, PmrStringType & s){ + rv.contents.resize(0); + bool result = my_parse(is, content, '<'); + // note: unget caused a problem with dinkumware. replace with + // is.unget(); + // putback another delimiter instead + is.putback('<'); + if(result) + s = rv.contents; + return result; +} +#endif + template basic_xml_grammar::basic_xml_grammar(){ init_chset();