diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2023-08-18 11:52:29 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2023-08-18 15:18:47 +0300 |
commit | b4f93a19b70aa5276a2ae7e17fc82c37be6c207e (patch) | |
tree | 08ddd00d6ab23a377add49eadecc85d7ad5e4e8a /contrib | |
parent | 8a2b6dd59ef13047ade3ea1bf0827706e42ed699 (diff) | |
download | ydb-b4f93a19b70aa5276a2ae7e17fc82c37be6c207e.tar.gz |
Update contrib/restricted/boost/locale to 1.83.0
Diffstat (limited to 'contrib')
102 files changed, 3631 insertions, 3051 deletions
diff --git a/contrib/restricted/boost/io/include/boost/io/detail/buffer_fill.hpp b/contrib/restricted/boost/io/include/boost/io/detail/buffer_fill.hpp new file mode 100644 index 0000000000..b25a884473 --- /dev/null +++ b/contrib/restricted/boost/io/include/boost/io/detail/buffer_fill.hpp @@ -0,0 +1,39 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_BUFFER_FILL_HPP +#define BOOST_IO_DETAIL_BUFFER_FILL_HPP + +#include <iosfwd> +#include <cstddef> + +namespace boost { +namespace io { +namespace detail { + +template<class charT, class traits> +inline bool +buffer_fill(std::basic_streambuf<charT, traits>& buf, charT ch, + std::size_t size) +{ + charT fill[] = { ch, ch, ch, ch, ch, ch, ch, ch }; + enum { + chunk = sizeof fill / sizeof(charT) + }; + for (; size > chunk; size -= chunk) { + if (static_cast<std::size_t>(buf.sputn(fill, chunk)) != chunk) { + return false; + } + } + return static_cast<std::size_t>(buf.sputn(fill, size)) == size; +} + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/contrib/restricted/boost/io/include/boost/io/detail/ostream_guard.hpp b/contrib/restricted/boost/io/include/boost/io/detail/ostream_guard.hpp new file mode 100644 index 0000000000..6999d81344 --- /dev/null +++ b/contrib/restricted/boost/io/include/boost/io/detail/ostream_guard.hpp @@ -0,0 +1,45 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_OSTREAM_GUARD_HPP +#define BOOST_IO_DETAIL_OSTREAM_GUARD_HPP + +#include <boost/config.hpp> +#include <iosfwd> + +namespace boost { +namespace io { +namespace detail { + +template<class Char, class Traits> +class ostream_guard { +public: + explicit ostream_guard(std::basic_ostream<Char, Traits>& os) BOOST_NOEXCEPT + : os_(&os) { } + + ~ostream_guard() BOOST_NOEXCEPT_IF(false) { + if (os_) { + os_->setstate(std::basic_ostream<Char, Traits>::badbit); + } + } + + void release() BOOST_NOEXCEPT { + os_ = 0; + } + +private: + ostream_guard(const ostream_guard&); + ostream_guard& operator=(const ostream_guard&); + + std::basic_ostream<Char, Traits>* os_; +}; + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/contrib/restricted/boost/io/include/boost/io/ostream_put.hpp b/contrib/restricted/boost/io/include/boost/io/ostream_put.hpp new file mode 100644 index 0000000000..97627f8e81 --- /dev/null +++ b/contrib/restricted/boost/io/include/boost/io/ostream_put.hpp @@ -0,0 +1,50 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_OSTREAM_PUT_HPP +#define BOOST_IO_OSTREAM_PUT_HPP + +#include <boost/io/detail/buffer_fill.hpp> +#include <boost/io/detail/ostream_guard.hpp> + +namespace boost { +namespace io { + +template<class charT, class traits> +inline std::basic_ostream<charT, traits>& +ostream_put(std::basic_ostream<charT, traits>& os, const charT* data, + std::size_t size) +{ + typedef std::basic_ostream<charT, traits> stream; + detail::ostream_guard<charT, traits> guard(os); + typename stream::sentry entry(os); + if (entry) { + std::basic_streambuf<charT, traits>& buf = *os.rdbuf(); + std::size_t width = static_cast<std::size_t>(os.width()); + if (width <= size) { + if (static_cast<std::size_t>(buf.sputn(data, size)) != size) { + return os; + } + } else if ((os.flags() & stream::adjustfield) == stream::left) { + if (static_cast<std::size_t>(buf.sputn(data, size)) != size || + !detail::buffer_fill(buf, os.fill(), width - size)) { + return os; + } + } else if (!detail::buffer_fill(buf, os.fill(), width - size) || + static_cast<std::size_t>(buf.sputn(data, size)) != size) { + return os; + } + os.width(0); + } + guard.release(); + return os; +} + +} /* io */ +} /* boost */ + +#endif diff --git a/contrib/restricted/boost/locale/CMakeLists.darwin-x86_64.txt b/contrib/restricted/boost/locale/CMakeLists.darwin-x86_64.txt index c712fd71a3..6be36e40a8 100644 --- a/contrib/restricted/boost/locale/CMakeLists.darwin-x86_64.txt +++ b/contrib/restricted/boost/locale/CMakeLists.darwin-x86_64.txt @@ -28,6 +28,7 @@ target_link_libraries(restricted-boost-locale PUBLIC restricted-boost-iterator restricted-boost-predef restricted-boost-thread + restricted-boost-utility ) target_sources(restricted-boost-locale PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp diff --git a/contrib/restricted/boost/locale/CMakeLists.linux-aarch64.txt b/contrib/restricted/boost/locale/CMakeLists.linux-aarch64.txt index 49c58834ef..453c9e00ef 100644 --- a/contrib/restricted/boost/locale/CMakeLists.linux-aarch64.txt +++ b/contrib/restricted/boost/locale/CMakeLists.linux-aarch64.txt @@ -29,6 +29,7 @@ target_link_libraries(restricted-boost-locale PUBLIC restricted-boost-iterator restricted-boost-predef restricted-boost-thread + restricted-boost-utility ) target_sources(restricted-boost-locale PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp diff --git a/contrib/restricted/boost/locale/CMakeLists.linux-x86_64.txt b/contrib/restricted/boost/locale/CMakeLists.linux-x86_64.txt index 49c58834ef..453c9e00ef 100644 --- a/contrib/restricted/boost/locale/CMakeLists.linux-x86_64.txt +++ b/contrib/restricted/boost/locale/CMakeLists.linux-x86_64.txt @@ -29,6 +29,7 @@ target_link_libraries(restricted-boost-locale PUBLIC restricted-boost-iterator restricted-boost-predef restricted-boost-thread + restricted-boost-utility ) target_sources(restricted-boost-locale PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/locale/src/boost/locale/posix/codecvt.cpp diff --git a/contrib/restricted/boost/locale/CMakeLists.windows-x86_64.txt b/contrib/restricted/boost/locale/CMakeLists.windows-x86_64.txt index 76b190df2c..62aa96d9ae 100644 --- a/contrib/restricted/boost/locale/CMakeLists.windows-x86_64.txt +++ b/contrib/restricted/boost/locale/CMakeLists.windows-x86_64.txt @@ -28,6 +28,7 @@ target_link_libraries(restricted-boost-locale PUBLIC restricted-boost-iterator restricted-boost-predef restricted-boost-thread + restricted-boost-utility ) target_sources(restricted-boost-locale PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp diff --git a/contrib/restricted/boost/locale/README.md b/contrib/restricted/boost/locale/README.md index a8e73bc55a..2cc876784e 100644 --- a/contrib/restricted/boost/locale/README.md +++ b/contrib/restricted/boost/locale/README.md @@ -5,7 +5,7 @@ Part of the [Boost C++ Libraries](http://github.com/boostorg). Boost.Locale is a library that provides high quality localization facilities in a C++ way. It was originally designed a part of [CppCMS](http://cppcms.sourceforge.net/) - a C++ Web Framework project and then contributed to Boost. -Boost.Locale gives powerful tools for development of cross platform localized software - the software that talks to users in their language. +Boost.Locale gives powerful tools for development of cross-platform localized software - the software that talks to users in their language. Provided Features: @@ -21,7 +21,7 @@ Provided Features: - Support for `char` and `wchar_t` - Experimental support for C++11 `char16_t` and `char32_t` strings and streams. -Boost.Locale enhances and unifies the standard library's API the way it becomes useful and convenient for development of cross platform and "cross-culture" software. +Boost.Locale enhances and unifies the standard library's API the way it becomes useful and convenient for development of cross-platform and "cross-culture" software. In order to achieve this goal Boost.Locale uses the-state-of-the-art Unicode and Localization library: ICU - International Components for Unicode. @@ -38,7 +38,7 @@ Distributed under the [Boost Software License, Version 1.0](https://www.boost.or ### Properties * C++11 -* Formatted with clang-format, see [`tools/format_source.sh`](https://github.com/boostorg/locale/blob/develop/tools/format_source.sh) +* Formatted with clang-format, see [`tools/format_sources.sh`](https://github.com/boostorg/locale/blob/develop/tools/format_sources.sh) ### Build Status diff --git a/contrib/restricted/boost/locale/include/boost/locale.hpp b/contrib/restricted/boost/locale/include/boost/locale.hpp index 1840bf5163..28709aa5ff 100644 --- a/contrib/restricted/boost/locale/include/boost/locale.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale.hpp @@ -21,5 +21,6 @@ #include <boost/locale/localization_backend.hpp> #include <boost/locale/message.hpp> #include <boost/locale/util.hpp> +#include <boost/locale/util/locale_data.hpp> #endif diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/facets.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/facets.hpp index 4d443c9aa8..61dc2bef63 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/boundary/facets.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/facets.hpp @@ -8,6 +8,8 @@ #define BOOST_LOCALE_BOUNDARY_FACETS_HPP_INCLUDED #include <boost/locale/boundary/types.hpp> +#include <boost/locale/detail/facet_id.hpp> +#include <boost/locale/detail/is_supported_char.hpp> #include <locale> #include <vector> @@ -49,16 +51,14 @@ namespace boost { namespace locale { /// with marks typedef std::vector<break_info> index_type; - template<typename CharType> - class boundary_indexing; - -#ifdef BOOST_LOCALE_DOXYGEN - /// \brief This facet generates an index for boundary analysis - /// for a given text. + /// \brief This facet generates an index for boundary analysis of a given text. /// - /// It is specialized for 4 types of characters \c char_t, \c wchar_t, \c char16_t and \c char32_t + /// It is implemented for supported character types, at least \c char, \c wchar_t template<typename Char> - class BOOST_LOCALE_DECL boundary_indexing : public std::locale::facet { + class BOOST_SYMBOL_VISIBLE boundary_indexing : public std::locale::facet, + public boost::locale::detail::facet_id<boundary_indexing<Char>> { + BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char); + public: /// Default constructor typical for facets boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {} @@ -69,56 +69,8 @@ namespace boost { namespace locale { /// index is never empty, even if the range [begin,end) is empty it consists /// of at least one boundary point with the offset 0. virtual index_type map(boundary_type t, const Char* begin, const Char* end) const = 0; - - /// Identification of this facet - static std::locale::id id; - }; - -#else - - template<> - class BOOST_LOCALE_DECL boundary_indexing<char> : public std::locale::facet { - public: - boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {} - ~boundary_indexing(); - virtual index_type map(boundary_type t, const char* begin, const char* end) const = 0; - static std::locale::id id; }; - template<> - class BOOST_LOCALE_DECL boundary_indexing<wchar_t> : public std::locale::facet { - public: - boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {} - ~boundary_indexing(); - virtual index_type map(boundary_type t, const wchar_t* begin, const wchar_t* end) const = 0; - - static std::locale::id id; - }; - -# ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template<> - class BOOST_LOCALE_DECL boundary_indexing<char16_t> : public std::locale::facet { - public: - boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {} - ~boundary_indexing(); - virtual index_type map(boundary_type t, const char16_t* begin, const char16_t* end) const = 0; - static std::locale::id id; - }; -# endif - -# ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template<> - class BOOST_LOCALE_DECL boundary_indexing<char32_t> : public std::locale::facet { - public: - boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {} - ~boundary_indexing(); - virtual index_type map(boundary_type t, const char32_t* begin, const char32_t* end) const = 0; - static std::locale::id id; - }; -# endif - -#endif - /// @} } // namespace boundary diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp index 6143ac4616..fb4319b1bf 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/index.hpp @@ -11,9 +11,9 @@ #include <boost/locale/boundary/facets.hpp> #include <boost/locale/boundary/segment.hpp> #include <boost/locale/boundary/types.hpp> -#include <boost/cstdint.hpp> #include <boost/iterator/iterator_facade.hpp> #include <algorithm> +#include <cstdint> #include <iterator> #include <locale> #include <memory> @@ -133,7 +133,7 @@ namespace boost { namespace locale { namespace boundary { typedef mapping<base_iterator> mapping_type; typedef segment<base_iterator> segment_type; - segment_index_iterator() : current_(0, 0), map_(0), mask_(0), full_select_(false) {} + segment_index_iterator() : current_(0, 0), map_(nullptr), mask_(0), full_select_(false) {} segment_index_iterator(base_iterator p, const mapping_type* map, rule_type mask, bool full_select) : map_(map), mask_(mask), full_select_(full_select) @@ -221,11 +221,10 @@ namespace boost { namespace locale { namespace boundary { void set(base_iterator p) { - size_t dist = std::distance(map_->begin(), p); - index_type::const_iterator b = map_->index().begin(), e = map_->index().end(); - index_type::const_iterator boundary_point = std::upper_bound(b, e, break_info(dist)); + const auto b = map_->index().begin(), e = map_->index().end(); + auto boundary_point = std::upper_bound(b, e, break_info(std::distance(map_->begin(), p))); while(boundary_point != e && (boundary_point->rule & mask_) == 0) - boundary_point++; + ++boundary_point; current_.first = current_.second = boundary_point - b; @@ -259,9 +258,8 @@ namespace boost { namespace locale { namespace boundary { void update_rule() { - if(current_.second != size()) { + if(current_.second != size()) value_.rule(index()[current_.second].rule); - } } size_t get_offset(size_t ind) const { @@ -297,7 +295,7 @@ namespace boost { namespace locale { namespace boundary { typedef mapping<base_iterator> mapping_type; typedef boundary_point<base_iterator> boundary_point_type; - boundary_point_index_iterator() : current_(0), map_(0), mask_(0) {} + boundary_point_index_iterator() : current_(0), map_(nullptr), mask_(0) {} boundary_point_index_iterator(bool is_begin, const mapping_type* map, rule_type mask) : map_(map), mask_(mask) @@ -358,14 +356,13 @@ namespace boost { namespace locale { namespace boundary { { size_t dist = std::distance(map_->begin(), p); - index_type::const_iterator b = index().begin(); - index_type::const_iterator e = index().end(); - index_type::const_iterator ptr = std::lower_bound(b, e, break_info(dist)); + const auto b = index().begin(), e = index().end(); + const auto ptr = std::lower_bound(b, e, break_info(dist)); - if(ptr == index().end()) + if(ptr == e) current_ = size() - 1; else - current_ = ptr - index().begin(); + current_ = ptr - b; while(!valid_offset(current_)) current_++; @@ -388,9 +385,8 @@ namespace boost { namespace locale { namespace boundary { void update_rule() { - if(current_ != size()) { + if(current_ != size()) value_.rule(index()[current_].rule); - } } size_t get_offset(size_t ind) const { diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp index 796fc19956..9e38188e3f 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/segment.hpp @@ -359,10 +359,10 @@ namespace boost { namespace locale { namespace boundary { /// Write the segment to the stream character by character template<typename CharType, typename TraitsType, typename Iterator> std::basic_ostream<CharType, TraitsType>& operator<<(std::basic_ostream<CharType, TraitsType>& out, - const segment<Iterator>& tok) + const segment<Iterator>& seg) { - for(Iterator p = tok.begin(), e = tok.end(); p != e; ++p) - out << *p; + for(const auto& p : seg) + out << p; return out; } diff --git a/contrib/restricted/boost/locale/include/boost/locale/boundary/types.hpp b/contrib/restricted/boost/locale/include/boost/locale/boundary/types.hpp index 9fac23b172..fa927915aa 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/boundary/types.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/boundary/types.hpp @@ -8,7 +8,7 @@ #define BOOST_LOCALE_BOUNDARY_TYPES_HPP_INCLUDED #include <boost/locale/config.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> #ifdef BOOST_MSVC # pragma warning(push) diff --git a/contrib/restricted/boost/locale/include/boost/locale/collator.hpp b/contrib/restricted/boost/locale/include/boost/locale/collator.hpp index dfef535d23..b45f15475f 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/collator.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/collator.hpp @@ -17,8 +17,6 @@ namespace boost { namespace locale { - class info; - /// \defgroup collation Collation /// /// This module introduces collation related classes @@ -173,7 +171,7 @@ namespace boost { namespace locale { public: /// Create a comparator class for locale \a l and with collation leval \a level /// - /// \note throws std::bad_cast if l does not have \ref collator facet installed + /// \throws std::bad_cast: \a l does not have \ref collator facet installed comparator(const std::locale& l = std::locale(), collate_level level = default_level) : locale_(l), level_(level) {} diff --git a/contrib/restricted/boost/locale/include/boost/locale/config.hpp b/contrib/restricted/boost/locale/include/boost/locale/config.hpp index 821ba7fe7d..9c8e6c2f2f 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/config.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/config.hpp @@ -72,6 +72,16 @@ #else # define BOOST_LOCALE_USE_WIN32_API 0 #endif + +// To be used to suppress false positives of UBSAN +#if defined(__clang__) && defined(__has_attribute) +# if __has_attribute(no_sanitize) +# define BOOST_LOCALE_NO_SANITIZE(what) __attribute__((no_sanitize(what))) +# endif +#endif +#if !defined(BOOST_LOCALE_NO_SANITIZE) +# define BOOST_LOCALE_NO_SANITIZE(what) +#endif /// \endcond #endif // boost/locale/config.hpp diff --git a/contrib/restricted/boost/locale/include/boost/locale/conversion.hpp b/contrib/restricted/boost/locale/include/boost/locale/conversion.hpp index 09fa75faf7..f5626fdc61 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/conversion.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/conversion.hpp @@ -7,6 +7,8 @@ #ifndef BOOST_LOCALE_CONVERTER_HPP_INCLUDED #define BOOST_LOCALE_CONVERTER_HPP_INCLUDED +#include <boost/locale/detail/facet_id.hpp> +#include <boost/locale/detail/is_supported_char.hpp> #include <boost/locale/util/string.hpp> #include <locale> @@ -35,76 +37,24 @@ namespace boost { namespace locale { }; }; - template<typename CharType> - class converter; - -#ifdef BOOST_LOCALE_DOXYGEN - /// /// \brief The facet that implements text manipulation /// - /// It is used to performs text conversion operations defined by \ref converter_base::conversion_type. - /// It is specialized for four types of characters \c char, \c wchar_t, \c char16_t, \c char32_t + /// It is used to perform text conversion operations defined by \ref converter_base::conversion_type. + /// It is implemented for supported character types, at least \c char, \c wchar_t template<typename Char> - class BOOST_LOCALE_DECL converter : public converter_base, public std::locale::facet { - public: - /// Locale identification - static std::locale::id id; + class BOOST_SYMBOL_VISIBLE converter : public converter_base, + public std::locale::facet, + public detail::facet_id<converter<Char>> { + BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char); + public: /// Standard constructor converter(size_t refs = 0) : std::locale::facet(refs) {} - /// Convert text in range [\a begin, \a end) according to conversion method \a how. Parameter /// \a flags is used for specification of normalization method like nfd, nfc etc. virtual std::basic_string<Char> convert(conversion_type how, const Char* begin, const Char* end, int flags = 0) const = 0; }; -#else - - template<> - class BOOST_LOCALE_DECL converter<char> : public converter_base, public std::locale::facet { - public: - static std::locale::id id; - - converter(size_t refs = 0) : std::locale::facet(refs) {} - ~converter(); - virtual std::string convert(conversion_type how, const char* begin, const char* end, int flags = 0) const = 0; - }; - - template<> - class BOOST_LOCALE_DECL converter<wchar_t> : public converter_base, public std::locale::facet { - public: - static std::locale::id id; - converter(size_t refs = 0) : std::locale::facet(refs) {} - ~converter(); - virtual std::wstring - convert(conversion_type how, const wchar_t* begin, const wchar_t* end, int flags = 0) const = 0; - }; - -# ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template<> - class BOOST_LOCALE_DECL converter<char16_t> : public converter_base, public std::locale::facet { - public: - static std::locale::id id; - converter(size_t refs = 0) : std::locale::facet(refs) {} - ~converter(); - virtual std::u16string - convert(conversion_type how, const char16_t* begin, const char16_t* end, int flags = 0) const = 0; - }; -# endif - -# ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template<> - class BOOST_LOCALE_DECL converter<char32_t> : public converter_base, public std::locale::facet { - public: - static std::locale::id id; - converter(size_t refs = 0) : std::locale::facet(refs) {} - ~converter(); - virtual std::u32string - convert(conversion_type how, const char32_t* begin, const char32_t* end, int flags = 0) const = 0; - }; -# endif - -#endif /// The type that defined <a href="http://unicode.org/reports/tr15/#Norm_Forms">normalization form</a> enum norm_type { @@ -121,7 +71,7 @@ namespace boost { namespace locale { /// in account the locale encoding, because Unicode decomposition and composition are meaningless outside /// of a Unicode character set. /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> normalize(const CharType* begin, const CharType* end, @@ -137,7 +87,7 @@ namespace boost { namespace locale { /// in account the locale encoding, because Unicode decomposition and composition are meaningless outside /// of a Unicode character set. /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> normalize(const std::basic_string<CharType>& str, norm_type n = norm_default, @@ -152,7 +102,7 @@ namespace boost { namespace locale { /// in account the locale encoding, because Unicode decomposition and composition are meaningless outside /// of a Unicode character set. /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> normalize(const CharType* str, norm_type n = norm_default, const std::locale& loc = std::locale()) @@ -164,7 +114,7 @@ namespace boost { namespace locale { /// Convert a string in range [begin,end) to upper case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_upper(const CharType* begin, const CharType* end, const std::locale& loc = std::locale()) @@ -174,7 +124,7 @@ namespace boost { namespace locale { /// Convert a string \a str to upper case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_upper(const std::basic_string<CharType>& str, const std::locale& loc = std::locale()) { @@ -183,7 +133,7 @@ namespace boost { namespace locale { /// Convert a NULL terminated string \a str to upper case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_upper(const CharType* str, const std::locale& loc = std::locale()) { @@ -194,7 +144,7 @@ namespace boost { namespace locale { /// Convert a string in range [begin,end) to lower case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_lower(const CharType* begin, const CharType* end, const std::locale& loc = std::locale()) @@ -204,7 +154,7 @@ namespace boost { namespace locale { /// Convert a string \a str to lower case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_lower(const std::basic_string<CharType>& str, const std::locale& loc = std::locale()) { @@ -213,7 +163,7 @@ namespace boost { namespace locale { /// Convert a NULL terminated string \a str to lower case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_lower(const CharType* str, const std::locale& loc = std::locale()) { @@ -224,7 +174,7 @@ namespace boost { namespace locale { /// Convert a string in range [begin,end) to title case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_title(const CharType* begin, const CharType* end, const std::locale& loc = std::locale()) @@ -234,7 +184,7 @@ namespace boost { namespace locale { /// Convert a string \a str to title case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_title(const std::basic_string<CharType>& str, const std::locale& loc = std::locale()) { @@ -243,7 +193,7 @@ namespace boost { namespace locale { /// Convert a NULL terminated string \a str to title case according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> to_title(const CharType* str, const std::locale& loc = std::locale()) { @@ -254,7 +204,7 @@ namespace boost { namespace locale { /// Fold case of a string in range [begin,end) according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> fold_case(const CharType* begin, const CharType* end, const std::locale& loc = std::locale()) @@ -264,7 +214,7 @@ namespace boost { namespace locale { /// Fold case of a string \a str according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> fold_case(const std::basic_string<CharType>& str, const std::locale& loc = std::locale()) @@ -274,7 +224,7 @@ namespace boost { namespace locale { /// Fold case of a NULL terminated string \a str according to locale \a loc /// - /// \note throws std::bad_cast if loc does not have \ref converter facet installed + /// \throws std::bad_cast: \a loc does not have \ref converter facet installed template<typename CharType> std::basic_string<CharType> fold_case(const CharType* str, const std::locale& loc = std::locale()) { diff --git a/contrib/restricted/boost/locale/include/boost/locale/date_time.hpp b/contrib/restricted/boost/locale/include/boost/locale/date_time.hpp index 8006c60e89..46b171bc35 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/date_time.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/date_time.hpp @@ -470,29 +470,29 @@ namespace boost { namespace locale { public: /// Create calendar taking locale and timezone information from ios_base instance. /// - /// \note throws std::bad_cast if ios does not have a locale with installed \ref calendar_facet + /// \throws std::bad_cast: \a ios does not have a locale with installed \ref calendar_facet /// facet installed calendar(std::ios_base& ios); /// Create calendar with locale \a l and time_zone \a zone /// - /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: \a l does not have \ref calendar_facet facet installed calendar(const std::locale& l, const std::string& zone); /// Create calendar with locale \a l and default timezone /// - /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: \a l does not have \ref calendar_facet facet installed calendar(const std::locale& l); /// Create calendar with default locale and timezone \a zone /// - /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: global locale does not have \ref calendar_facet facet installed calendar(const std::string& zone); /// Create calendar with default locale and timezone /// - /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: global locale does not have \ref calendar_facet facet installed calendar(); ~calendar(); @@ -515,9 +515,9 @@ namespace boost { namespace locale { int first_day_of_week() const; /// get calendar's locale - std::locale get_locale() const; + const std::locale& get_locale() const; /// get calendar's time zone - std::string get_time_zone() const; + const std::string& get_time_zone() const; /// Check if the calendar is Gregorian bool is_gregorian() const; @@ -562,13 +562,13 @@ namespace boost { namespace locale { public: /// Default constructor, uses default calendar initialized date_time object to current time. /// - /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed date_time(); /// Copy a date_time date_time(const date_time& other); - // Move construct a new date_time - date_time(date_time&&) = default; + // Move construct a date_time + date_time(date_time&&) noexcept = default; /// copy date_time and change some fields according to the \a set date_time(const date_time& other, const date_time_period_set& set); @@ -576,11 +576,11 @@ namespace boost { namespace locale { /// assign the date_time date_time& operator=(const date_time& other); // Move assign a date_time - date_time& operator=(date_time&&) = default; + date_time& operator=(date_time&&) noexcept = default; /// Create a date_time object using POSIX time \a time and default calendar /// - /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed date_time(double time); /// Create a date_time object using POSIX time \a time and calendar \a cal @@ -591,7 +591,7 @@ namespace boost { namespace locale { /// Create a date_time object using default calendar and define values given in \a set /// - /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed + /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed date_time(const date_time_period_set& set); /// Create a date_time object using calendar \a cal and define values given in \a set @@ -672,6 +672,9 @@ namespace boost { namespace locale { /// This time can be fetched from Operating system clock using C function time, gettimeofday and others. void time(double v); + /// Get the name of the associated timezone + std::string timezone() const; + /// compare date_time in the timeline (ignores difference in calendar, timezone etc) bool operator==(const date_time& other) const; /// compare date_time in the timeline (ignores difference in calendar, timezone etc) @@ -686,7 +689,7 @@ namespace boost { namespace locale { bool operator>=(const date_time& other) const; /// swaps two dates - efficient, does not throw - void swap(date_time& other); + void swap(date_time& other) noexcept; /// calculate the distance from this date_time to \a other in terms of periods \a f int difference(const date_time& other, period::period_type f) const; @@ -710,7 +713,7 @@ namespace boost { namespace locale { /// /// For example: /// \code - /// date_time now(time(0),hebrew_calendar) + /// date_time now(time(nullptr),hebrew_calendar) /// std::cout << "Year: " << period::year(now) << " Full Date:" << now; /// \endcode /// diff --git a/contrib/restricted/boost/locale/include/boost/locale/date_time_facet.hpp b/contrib/restricted/boost/locale/include/boost/locale/date_time_facet.hpp index c67efc7c2c..2f3344ba6e 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/date_time_facet.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/date_time_facet.hpp @@ -8,7 +8,8 @@ #define BOOST_LOCALE_DATE_TIME_FACET_HPP_INCLUDED #include <boost/locale/config.hpp> -#include <boost/cstdint.hpp> +#include <boost/locale/detail/facet_id.hpp> +#include <cstdint> #include <locale> #ifdef BOOST_MSVC @@ -91,7 +92,7 @@ namespace boost { namespace locale { /// This class defines generic calendar class, it is used by date_time and calendar /// objects internally. It is less useful for end users, but it is build for localization /// backend implementation - class BOOST_LOCALE_DECL abstract_calendar { + class BOOST_SYMBOL_VISIBLE abstract_calendar { public: /// Type that defines how to fetch the value enum value_type { @@ -163,20 +164,16 @@ namespace boost { namespace locale { /// Check of two calendars have same rules virtual bool same(const abstract_calendar* other) const = 0; - virtual ~abstract_calendar(); + virtual ~abstract_calendar() = default; }; /// \brief the facet that generates calendar for specific locale - class BOOST_LOCALE_DECL calendar_facet : public std::locale::facet { + class BOOST_SYMBOL_VISIBLE calendar_facet : public std::locale::facet, public detail::facet_id<calendar_facet> { public: /// Basic constructor calendar_facet(size_t refs = 0) : std::locale::facet(refs) {} - ~calendar_facet(); /// Create a new calendar that points to current point of time. virtual abstract_calendar* create_calendar() const = 0; - - /// Locale id (needed to work with std::locale) - static std::locale::id id; }; }} // namespace boost::locale diff --git a/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp b/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp new file mode 100644 index 0000000000..ee669349a1 --- /dev/null +++ b/contrib/restricted/boost/locale/include/boost/locale/detail/encoding.hpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2022-2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_DETAIL_ENCODING_HPP_INCLUDED +#define BOOST_LOCALE_DETAIL_ENCODING_HPP_INCLUDED + +#include <boost/locale/config.hpp> +#include <boost/locale/encoding_errors.hpp> +#include <boost/utility/string_view.hpp> +#include <memory> +#include <string> + +/// \cond INTERNAL +namespace boost { namespace locale { namespace conv { namespace detail { + template<typename CharIn, typename CharOut> + class BOOST_SYMBOL_VISIBLE charset_converter { + public: + using char_out_type = CharOut; + using char_in_type = CharIn; + using string_type = std::basic_string<CharOut>; + + virtual ~charset_converter() = default; + virtual string_type convert(const CharIn* begin, const CharIn* end) = 0; + string_type convert(const boost::basic_string_view<CharIn>& text) + { + return convert(text.data(), text.data() + text.length()); + } + }; + + using narrow_converter = charset_converter<char, char>; + + template<typename CharType> + using utf_encoder = charset_converter<char, CharType>; + + template<typename CharType> + using utf_decoder = charset_converter<CharType, char>; + + enum class conv_backend { Default, IConv, ICU, WinAPI }; + + template<typename Char> + BOOST_LOCALE_DECL std::unique_ptr<utf_encoder<Char>> + make_utf_encoder(const std::string& charset, method_type how, conv_backend impl = conv_backend::Default); + template<typename Char> + BOOST_LOCALE_DECL std::unique_ptr<utf_decoder<Char>> + make_utf_decoder(const std::string& charset, method_type how, conv_backend impl = conv_backend::Default); + BOOST_LOCALE_DECL std::unique_ptr<narrow_converter> + make_narrow_converter(const std::string& src_encoding, + const std::string& target_encoding, + method_type how, + conv_backend impl = conv_backend::Default); +}}}} // namespace boost::locale::conv::detail + +/// \endcond + +#endif diff --git a/contrib/restricted/boost/locale/include/boost/locale/detail/facet_id.hpp b/contrib/restricted/boost/locale/include/boost/locale/detail/facet_id.hpp new file mode 100644 index 0000000000..7405149905 --- /dev/null +++ b/contrib/restricted/boost/locale/include/boost/locale/detail/facet_id.hpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2022-2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_DETAIL_FACET_ID_HPP_INCLUDED +#define BOOST_LOCALE_DETAIL_FACET_ID_HPP_INCLUDED + +#include <boost/locale/config.hpp> +#include <locale> + +/// \cond INTERNAL +namespace boost { namespace locale { namespace detail { +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wundefined-var-template" +#endif + /// CRTP base class to hold the id required for facets + /// + /// Required because the id needs to be defined in a CPP file and hence ex/imported for shared libraries. + /// However the virtual classes need to be declared as BOOST_VISIBLE to combine the VTables because otherwise + /// casts/virtual-calls might be flagged as invalid by UBSAN + template<class Derived> + struct BOOST_LOCALE_DECL facet_id { + static std::locale::id id; + }; +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +}}} // namespace boost::locale::detail + +/// \endcond + +#endif diff --git a/contrib/restricted/boost/locale/include/boost/locale/detail/is_supported_char.hpp b/contrib/restricted/boost/locale/include/boost/locale/detail/is_supported_char.hpp new file mode 100644 index 0000000000..d9fb092e5a --- /dev/null +++ b/contrib/restricted/boost/locale/include/boost/locale/detail/is_supported_char.hpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2022-2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_DETAIL_IS_SUPPORTED_CHAR_HPP_INCLUDED +#define BOOST_LOCALE_DETAIL_IS_SUPPORTED_CHAR_HPP_INCLUDED + +#include <boost/locale/config.hpp> +#include <type_traits> + +/// \cond INTERNAL +namespace boost { namespace locale { namespace detail { + /// Trait, returns true iff the argument is a supported character type + template<typename Char> + struct is_supported_char : std::false_type {}; + + template<> + struct is_supported_char<char> : std::true_type {}; + template<> + struct is_supported_char<wchar_t> : std::true_type {}; + +#ifdef BOOST_LOCALE_ENABLE_CHAR16_T + template<> + struct is_supported_char<char16_t> : std::true_type {}; +#endif + +#ifdef BOOST_LOCALE_ENABLE_CHAR32_T + template<> + struct is_supported_char<char32_t> : std::true_type {}; +#endif + + template<typename Char> + using enable_if_is_supported_char = typename std::enable_if<is_supported_char<Char>::value>::type; + +}}} // namespace boost::locale::detail + +#define BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char) \ + static_assert(boost::locale::detail::is_supported_char<Char>::value, "Unsupported Char type") + +/// \endcond + +#endif diff --git a/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp b/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp index 0947028cdf..d0e1d9d07e 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/encoding.hpp @@ -8,10 +8,12 @@ #define BOOST_LOCALE_ENCODING_HPP_INCLUDED #include <boost/locale/config.hpp> +#include <boost/locale/detail/encoding.hpp> #include <boost/locale/encoding_errors.hpp> #include <boost/locale/encoding_utf.hpp> #include <boost/locale/info.hpp> #include <boost/locale/util/string.hpp> +#include <memory> #ifdef BOOST_MSVC # pragma warning(push) @@ -22,114 +24,161 @@ namespace boost { namespace locale { /// \brief Namespace that contains all functions related to character set conversion namespace conv { - /// \defgroup codepage Character conversion functions + + /// \defgroup Charset conversion functions /// /// @{ - /// convert text in range [begin,end) encoded with \a charset to UTF string according to policy \a how + /// convert text in range [begin,end) encoded with \a charset to UTF according to policy \a how + /// + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::basic_string<CharType> + BOOST_LOCALE_DECL std::basic_string<CharType> to_utf(const char* begin, const char* end, const std::string& charset, method_type how = default_method); - /// convert UTF text in range [begin,end) to a text encoded with \a charset according to policy \a how + /// convert UTF text in range [begin,end) to text encoded with \a charset according to policy \a how + /// + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::string from_utf(const CharType* begin, - const CharType* end, - const std::string& charset, - method_type how = default_method); + BOOST_LOCALE_DECL std::string from_utf(const CharType* begin, + const CharType* end, + const std::string& charset, + method_type how = default_method); - /// convert string to UTF string from text in range [begin,end) encoded according to locale \a loc according to - /// policy \a how + /// convert \a text encoded with \a charset to UTF according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> std::basic_string<CharType> - to_utf(const char* begin, const char* end, const std::locale& loc, method_type how = default_method) + to_utf(const std::string& text, const std::string& charset, method_type how = default_method) { - return to_utf<CharType>(begin, end, std::use_facet<info>(loc).encoding(), how); + return to_utf<CharType>(text.c_str(), text.c_str() + text.size(), charset, how); } - /// convert UTF text in range [begin,end) to a text encoded according to locale \a loc according to policy \a - /// how + /// Convert \a text encoded with \a charset to UTF according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::string - from_utf(const CharType* begin, const CharType* end, const std::locale& loc, method_type how = default_method) + std::basic_string<CharType> + to_utf(const char* text, const std::string& charset, method_type how = default_method) { - return from_utf(begin, end, std::use_facet<info>(loc).encoding(), how); + return to_utf<CharType>(text, util::str_end(text), charset, how); } - /// convert a string \a text encoded with \a charset to UTF string + /// convert text in range [begin,end) in locale encoding given by \a loc to UTF according to + /// policy \a how + /// + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> std::basic_string<CharType> - to_utf(const std::string& text, const std::string& charset, method_type how = default_method) + to_utf(const char* begin, const char* end, const std::locale& loc, method_type how = default_method) { - return to_utf<CharType>(text.c_str(), text.c_str() + text.size(), charset, how); + return to_utf<CharType>(begin, end, std::use_facet<info>(loc).encoding(), how); } - /// Convert a \a text from \a charset to UTF string + /// Convert \a text in locale encoding given by \a loc to UTF according to policy \a how + /// + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::string - from_utf(const std::basic_string<CharType>& text, const std::string& charset, method_type how = default_method) + std::basic_string<CharType> + to_utf(const std::string& text, const std::locale& loc, method_type how = default_method) { - return from_utf(text.c_str(), text.c_str() + text.size(), charset, how); + return to_utf<CharType>(text, std::use_facet<info>(loc).encoding(), how); } - /// Convert a \a text from \a charset to UTF string + /// Convert \a text in locale encoding given by \a loc to UTF according to policy \a how + /// + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::basic_string<CharType> - to_utf(const char* text, const std::string& charset, method_type how = default_method) + std::basic_string<CharType> to_utf(const char* text, const std::locale& loc, method_type how = default_method) { - return to_utf<CharType>(text, util::str_end(text), charset, how); + return to_utf<CharType>(text, std::use_facet<info>(loc).encoding(), how); } - /// Convert a \a text from UTF to \a charset + /// convert \a text from UTF to text encoded with \a charset according to policy \a how + /// + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::string from_utf(const CharType* text, const std::string& charset, method_type how = default_method) + std::string + from_utf(const std::basic_string<CharType>& text, const std::string& charset, method_type how = default_method) { - return from_utf(text, util::str_end(text), charset, how); + return from_utf(text.c_str(), text.c_str() + text.size(), charset, how); } - /// Convert a \a text in locale encoding given by \a loc to UTF + /// Convert \a text from UTF to \a charset according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::basic_string<CharType> - to_utf(const std::string& text, const std::locale& loc, method_type how = default_method) + std::string from_utf(const CharType* text, const std::string& charset, method_type how = default_method) { - return to_utf<CharType>(text.c_str(), text.c_str() + text.size(), loc, how); + return from_utf(text, util::str_end(text), charset, how); } - /// Convert a \a text in UTF to locale encoding given by \a loc + /// Convert UTF text in range [begin,end) to text in locale encoding given by \a loc according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> std::string - from_utf(const std::basic_string<CharType>& text, const std::locale& loc, method_type how = default_method) + from_utf(const CharType* begin, const CharType* end, const std::locale& loc, method_type how = default_method) { - return from_utf(text.c_str(), text.c_str() + text.size(), loc, how); + return from_utf(begin, end, std::use_facet<info>(loc).encoding(), how); } - /// Convert a \a text in locale encoding given by \a loc to UTF + /// Convert \a text from UTF to locale encoding given by \a loc according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> - std::basic_string<CharType> to_utf(const char* text, const std::locale& loc, method_type how = default_method) + std::string + from_utf(const std::basic_string<CharType>& text, const std::locale& loc, method_type how = default_method) { - return to_utf<CharType>(text, util::str_end(text), loc, how); + return from_utf(text, std::use_facet<info>(loc).encoding(), how); } - /// Convert a \a text in UTF to locale encoding given by \a loc + /// Convert \a text from UTF to locale encoding given by \a loc according to policy \a how /// - /// \note throws std::bad_cast if the loc does not have \ref info facet installed + /// \throws std::bad_cast: \a loc does not have \ref info facet installed + /// \throws invalid_charset_error: Character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) template<typename CharType> std::string from_utf(const CharType* text, const std::locale& loc, method_type how = default_method) { - return from_utf(text, util::str_end(text), loc, how); + return from_utf(text, std::use_facet<info>(loc).encoding(), how); } - /// Convert a text in range [begin,end) to \a to_encoding from \a from_encoding + /// Convert a text in range [begin,end) to \a to_encoding from \a from_encoding according to + /// policy \a how + /// + /// \throws invalid_charset_error: Either character set is not supported + /// \throws conversion_error: when the conversion fails (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) BOOST_LOCALE_DECL std::string between(const char* begin, const char* end, @@ -137,73 +186,126 @@ namespace boost { namespace locale { const std::string& from_encoding, method_type how = default_method); - /// Convert a \a text to \a to_encoding from \a from_encoding + /// Convert \a text to \a to_encoding from \a from_encoding according to + /// policy \a how + /// + /// \throws invalid_charset_error: Either character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) inline std::string between(const char* text, const std::string& to_encoding, const std::string& from_encoding, method_type how = default_method) { - return boost::locale::conv::between(text, util::str_end(text), to_encoding, from_encoding, how); + return between(text, util::str_end(text), to_encoding, from_encoding, how); } - /// Convert a \a text to \a to_encoding from \a from_encoding + /// Convert \a text to \a to_encoding from \a from_encoding according to + /// policy \a how + /// + /// \throws invalid_charset_error: Either character set is not supported + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be + /// encoded or decoded) inline std::string between(const std::string& text, const std::string& to_encoding, const std::string& from_encoding, method_type how = default_method) { - return boost::locale::conv::between(text.c_str(), - text.c_str() + text.size(), - to_encoding, - from_encoding, - how); + return between(text.c_str(), text.c_str() + text.size(), to_encoding, from_encoding, how); } - /// \cond INTERNAL - - template<> - BOOST_LOCALE_DECL std::basic_string<char> - to_utf(const char* begin, const char* end, const std::string& charset, method_type how); - - template<> - BOOST_LOCALE_DECL std::string - from_utf(const char* begin, const char* end, const std::string& charset, method_type how); - - template<> - BOOST_LOCALE_DECL std::basic_string<wchar_t> - to_utf(const char* begin, const char* end, const std::string& charset, method_type how); - - template<> - BOOST_LOCALE_DECL std::string - from_utf(const wchar_t* begin, const wchar_t* end, const std::string& charset, method_type how); - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template<> - BOOST_LOCALE_DECL std::basic_string<char16_t> - to_utf(const char* begin, const char* end, const std::string& charset, method_type how); - - template<> - BOOST_LOCALE_DECL std::string - from_utf(const char16_t* begin, const char16_t* end, const std::string& charset, method_type how); -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template<> - BOOST_LOCALE_DECL std::basic_string<char32_t> - to_utf(const char* begin, const char* end, const std::string& charset, method_type how); - - template<> - BOOST_LOCALE_DECL std::string - from_utf(const char32_t* begin, const char32_t* end, const std::string& charset, method_type how); -#endif - - /// \endcond - /// @} + /// Converter class to decode a narrow string using a local encoding and encode it with UTF + template<typename CharType> + class utf_encoder { + std::unique_ptr<detail::utf_encoder<CharType>> impl_; + + public: + using char_type = CharType; + using string_type = std::basic_string<CharType>; + + /// Create an instance to convert text encoded with \a charset to UTF according to policy \a how + /// + /// Note: When converting only a single text \ref to_utf is likely faster. + /// \throws invalid_charset_error: Character set is not supported + utf_encoder(const std::string& charset, method_type how = default_method) : + impl_(detail::make_utf_encoder<CharType>(charset, how)) + {} + + /// Convert text in range [begin,end) to UTF + /// + /// \throws conversion_error: Conversion failed + string_type convert(const char* begin, const char* end) const { return impl_->convert(begin, end); } + /// Convert \a text to UTF + /// + /// \throws conversion_error: Conversion failed + string_type convert(const boost::string_view& text) const { return impl_->convert(text); } + /// Convert \a text to UTF + /// + /// \throws conversion_error: Conversion failed + string_type operator()(const boost::string_view& text) const { return convert(text); } + }; + + /// Converter class to decode an UTF string and encode it using a local encoding + template<typename CharType> + class utf_decoder { + std::unique_ptr<detail::utf_decoder<CharType>> impl_; + + public: + using char_type = CharType; + using stringview_type = boost::basic_string_view<CharType>; + + /// Create an instance to convert UTF text to text encoded with \a charset according to policy \a how + /// + /// Note: When converting only a single text \ref from_utf is likely faster. + /// \throws invalid_charset_error: Character set is not supported + utf_decoder(const std::string& charset, method_type how = default_method) : + impl_(detail::make_utf_decoder<CharType>(charset, how)) + {} + + /// Convert UTF text in range [begin,end) to local encoding + /// + /// \throws conversion_error: Conversion failed + std::string convert(const CharType* begin, const CharType* end) const { return impl_->convert(begin, end); } + /// Convert \a text from UTF to local encoding + /// + /// \throws conversion_error: Conversion failed + std::string convert(const stringview_type& text) const { return impl_->convert(text); } + /// Convert \a text from UTF to local encoding + /// + /// \throws conversion_error: Conversion failed + std::string operator()(const stringview_type& text) const { return convert(text); } + }; + + class narrow_converter { + std::unique_ptr<detail::narrow_converter> impl_; + + public: + /// Create converter to convert text from \a src_encoding to \a target_encoding according to policy \a how + /// + /// \throws invalid_charset_error: Either character set is not supported + narrow_converter(const std::string& src_encoding, + const std::string& target_encoding, + method_type how = default_method) : + impl_(detail::make_narrow_converter(src_encoding, target_encoding, how)) + {} + + /// Convert text in range [begin,end) + /// + /// \throws conversion_error: Conversion failed + std::string convert(const char* begin, const char* end) const { return impl_->convert(begin, end); } + /// Convert \a text + /// + /// \throws conversion_error: Conversion failed + std::string convert(const boost::string_view& text) const { return impl_->convert(text); } + /// Convert \a text + /// + /// \throws conversion_error: Conversion failed + std::string operator()(const boost::string_view& text) const { return convert(text); } + }; } // namespace conv - -}} // namespace boost::locale +}} // namespace boost::locale #ifdef BOOST_MSVC # pragma warning(pop) diff --git a/contrib/restricted/boost/locale/include/boost/locale/encoding_errors.hpp b/contrib/restricted/boost/locale/include/boost/locale/encoding_errors.hpp index 6643a6394e..97f0f6b4eb 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/encoding_errors.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/encoding_errors.hpp @@ -33,7 +33,7 @@ namespace boost { namespace locale { namespace conv { public: /// Create an error for charset \a charset invalid_charset_error(const std::string& charset) : - std::runtime_error("Invalid or unsupported charset:" + charset) + std::runtime_error("Invalid or unsupported charset: " + charset) {} }; diff --git a/contrib/restricted/boost/locale/include/boost/locale/encoding_utf.hpp b/contrib/restricted/boost/locale/include/boost/locale/encoding_utf.hpp index ed1e5db3c4..c19e67d3b8 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/encoding_utf.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/encoding_utf.hpp @@ -23,27 +23,28 @@ namespace boost { namespace locale { namespace conv { /// @{ /// Convert a Unicode text in range [begin,end) to other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template<typename CharOut, typename CharIn> std::basic_string<CharOut> utf_to_utf(const CharIn* begin, const CharIn* end, method_type how = default_method) { std::basic_string<CharOut> result; result.reserve(end - begin); - typedef std::back_insert_iterator<std::basic_string<CharOut>> inserter_type; - inserter_type inserter(result); - utf::code_point c; + std::back_insert_iterator<std::basic_string<CharOut>> inserter(result); while(begin != end) { - c = utf::utf_traits<CharIn>::template decode<const CharIn*>(begin, end); + const utf::code_point c = utf::utf_traits<CharIn>::decode(begin, end); if(c == utf::illegal || c == utf::incomplete) { if(how == stop) throw conversion_error(); - } else { - utf::utf_traits<CharOut>::template encode<inserter_type>(c, inserter); - } + } else + utf::utf_traits<CharOut>::encode(c, inserter); } return result; } /// Convert a Unicode NULL terminated string \a str other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template<typename CharOut, typename CharIn> std::basic_string<CharOut> utf_to_utf(const CharIn* str, method_type how = default_method) { @@ -51,6 +52,8 @@ namespace boost { namespace locale { namespace conv { } /// Convert a Unicode string \a str other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template<typename CharOut, typename CharIn> std::basic_string<CharOut> utf_to_utf(const std::basic_string<CharIn>& str, method_type how = default_method) { diff --git a/contrib/restricted/boost/locale/include/boost/locale/format.hpp b/contrib/restricted/boost/locale/include/boost/locale/format.hpp index 67a925da2d..266b65c735 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/format.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/format.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -12,6 +13,7 @@ #include <boost/locale/message.hpp> #include <sstream> #include <stdexcept> +#include <string> #include <vector> #ifdef BOOST_MSVC @@ -35,15 +37,15 @@ namespace boost { namespace locale { typedef std::basic_ostream<CharType> stream_type; typedef void (*writer_type)(stream_type& output, const void* ptr); - formattible() : pointer_(0), writer_(&formattible::void_write) {} + formattible() noexcept : pointer_(nullptr), writer_(&formattible::void_write) {} - formattible(const formattible&) = default; - formattible(formattible&&) = default; - formattible& operator=(const formattible&) = default; - formattible& operator=(formattible&&) = default; + formattible(const formattible&) noexcept = default; + formattible(formattible&&) noexcept = default; + formattible& operator=(const formattible&) noexcept = default; + formattible& operator=(formattible&&) noexcept = default; template<typename Type> - explicit formattible(const Type& value) + explicit formattible(const Type& value) noexcept { pointer_ = static_cast<const void*>(&value); writer_ = &write<Type>; @@ -173,10 +175,12 @@ namespace boost { namespace locale { /// \endcode /// /// - /// Invalid formatting strings are slightly ignored. This would prevent from translator - /// to crash the program in unexpected location. + /// Invalid formatting strings are silently ignored. + /// This protects against a translator crashing the program in an unexpected location. template<typename CharType> class basic_format { + int throw_if_params_bound() const; + public: typedef CharType char_type; ///< Underlying character type typedef basic_message<char_type> message_type; ///< The translation message type @@ -199,16 +203,12 @@ namespace boost { namespace locale { void operator=(const basic_format& other) = delete; /// Moveable basic_format(basic_format&& other) : - message_(std::move(other.message_)), format_(std::move(other.format_)), translate_(other.translate_), - parameters_count_(0) - { - if(other.parameters_count_) - throw std::invalid_argument("Can't move a basic_format with bound parameters"); - } + message_((other.throw_if_params_bound(), std::move(other.message_))), format_(std::move(other.format_)), + translate_(other.translate_), parameters_count_(0) + {} basic_format& operator=(basic_format&& other) { - if(other.parameters_count_) - throw std::invalid_argument("Can't move a basic_format with bound parameters"); + other.throw_if_params_bound(); message_ = std::move(other.message_); format_ = std::move(other.format_); translate_ = other.translate_; @@ -262,39 +262,37 @@ namespace boost { namespace locale { private: class format_guard { public: - format_guard(detail::format_parser& fmt) : fmt_(&fmt), restored_(false) {} + format_guard(detail::format_parser& fmt) : fmt_(fmt), restored_(false) {} void restore() { if(restored_) return; - fmt_->restore(); + fmt_.restore(); restored_ = true; } ~format_guard() { - try { - restore(); - } catch(...) { - } + // clang-format off + try { restore(); } catch(...) {} + // clang-format on } private: - detail::format_parser* fmt_; + detail::format_parser& fmt_; bool restored_; }; void format_output(stream_type& out, const string_type& sformat) const { - char_type obrk = '{'; - char_type cbrk = '}'; - char_type eq = '='; - char_type comma = ','; - char_type quote = '\''; - - size_t pos = 0; - size_t size = sformat.size(); + constexpr char_type obrk = '{'; + constexpr char_type cbrk = '}'; + constexpr char_type eq = '='; + constexpr char_type comma = ','; + constexpr char_type quote = '\''; + + const size_t size = sformat.size(); const CharType* format = sformat.c_str(); - while(format[pos] != 0) { + for(size_t pos = 0; format[pos];) { if(format[pos] != obrk) { if(format[pos] == cbrk && format[pos + 1] == cbrk) { out << cbrk; @@ -305,13 +303,11 @@ namespace boost { namespace locale { } continue; } - - if(pos + 1 < size && format[pos + 1] == obrk) { + pos++; + if(format[pos] == obrk) { out << obrk; - pos += 2; continue; } - pos++; detail::format_parser fmt(out, static_cast<void*>(&out), &basic_format::imbue_locale); @@ -322,13 +318,8 @@ namespace boost { namespace locale { std::string svalue; string_type value; bool use_svalue = true; - for(; format[pos]; pos++) { - char_type c = format[pos]; - if(c == comma || c == eq || c == cbrk) - break; - else { - key += static_cast<char>(c); - } + for(char_type c = format[pos]; !(c == 0 || c == comma || c == eq || c == cbrk); c = format[++pos]) { + key += static_cast<char>(c); } if(format[pos] == eq) { @@ -359,22 +350,19 @@ namespace boost { namespace locale { } } - if(use_svalue) { + if(use_svalue) fmt.set_one_flag(key, svalue); - } else + else fmt.set_flag_with_str(key, value); - if(format[pos] == comma) { - pos++; - continue; - } else if(format[pos] == cbrk) { - unsigned position = fmt.get_position(); - out << get(position); - guard.restore(); + if(format[pos] == comma) pos++; - break; - } else { - guard.restore(); + else { + if(format[pos] == cbrk) { + unsigned position = fmt.get_position(); + out << get(position); + pos++; + } break; } } @@ -400,7 +388,7 @@ namespace boost { namespace locale { return parameters_[id]; } - static void imbue_locale(void* ptr, const std::locale& l) { reinterpret_cast<stream_type*>(ptr)->imbue(l); } + static void imbue_locale(void* ptr, const std::locale& l) { static_cast<stream_type*>(ptr)->imbue(l); } static constexpr unsigned base_params_ = 8; @@ -438,6 +426,13 @@ namespace boost { namespace locale { typedef basic_format<char32_t> u32format; #endif + template<typename CharType> + int basic_format<CharType>::throw_if_params_bound() const + { + if(parameters_count_) + throw std::invalid_argument("Can't move a basic_format with bound parameters"); + return 0; + } /// @} }} // namespace boost::locale diff --git a/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp b/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp index 70397eed89..936ce7e12d 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/formatting.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -8,9 +9,9 @@ #define BOOST_LOCALE_FORMATTING_HPP_INCLUDED #include <boost/locale/time_zone.hpp> -#include <boost/locale/util/string.hpp> #include <boost/assert.hpp> -#include <boost/cstdint.hpp> +#include <boost/utility/string_view.hpp> +#include <cstdint> #include <cstring> #include <istream> #include <ostream> @@ -129,15 +130,13 @@ namespace boost { namespace locale { template<typename CharType> void date_time_pattern(const std::basic_string<CharType>& str) { - string_set& s = date_time_pattern_set(); - s.set(str.c_str()); + date_time_pattern_set().set<CharType>(str); } /// Get date/time pattern (strftime like) template<typename CharType> std::basic_string<CharType> date_time_pattern() const { - const string_set& s = date_time_pattern_set(); - return s.get<CharType>(); + return date_time_pattern_set().get<CharType>(); } /// \cond INTERNAL @@ -159,23 +158,24 @@ namespace boost { namespace locale { void swap(string_set& other); template<typename Char> - void set(const Char* s) + void set(const boost::basic_string_view<Char> s) { - BOOST_ASSERT(s); + BOOST_ASSERT(!s.empty()); delete[] ptr; ptr = nullptr; type = &typeid(Char); - size = sizeof(Char) * (util::str_end(s) - s + 1); - ptr = new char[size]; - memcpy(ptr, s, size); + size = sizeof(Char) * s.size(); + ptr = size ? new char[size] : nullptr; + memcpy(ptr, s.data(), size); } template<typename Char> std::basic_string<Char> get() const { - if(type == 0 || *type != typeid(Char)) + if(type == nullptr || *type != typeid(Char)) throw std::bad_cast(); - std::basic_string<Char> result = reinterpret_cast<const Char*>(ptr); + std::basic_string<Char> result(size / sizeof(Char), Char(0)); + memcpy(&result.front(), ptr, size); return result; } diff --git a/contrib/restricted/boost/locale/include/boost/locale/generator.hpp b/contrib/restricted/boost/locale/include/boost/locale/generator.hpp index bfbd528071..f9ae9c777d 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/generator.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/generator.hpp @@ -8,7 +8,7 @@ #define BOOST_LOCALE_GENERATOR_HPP #include <boost/locale/hold_ptr.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> #include <locale> #include <memory> #include <string> @@ -182,12 +182,6 @@ namespace locale { /// Shortcut to generate(id) std::locale operator()(const std::string& id) const { return generate(id); } - /// Set backend specific option - void set_option(const std::string& name, const std::string& value); - - /// Clear backend specific options - void clear_options(); - private: void set_all_options(localization_backend& backend, const std::string& id) const; diff --git a/contrib/restricted/boost/locale/include/boost/locale/generic_codecvt.hpp b/contrib/restricted/boost/locale/include/boost/locale/generic_codecvt.hpp index 428a9f0914..449b1de728 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/generic_codecvt.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/generic_codecvt.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -8,28 +9,37 @@ #define BOOST_LOCALE_GENERIC_CODECVT_HPP #include <boost/locale/utf.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> #include <locale> namespace boost { namespace locale { -#ifndef BOOST_LOCALE_DOXYGEN - // - // Make sure that mbstate can keep 16 bit of UTF-16 sequence - // - static_assert(sizeof(std::mbstate_t) >= 2, "std::mbstate_t is to small"); -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1700 -// up to MSVC 11 (2012) do_length is non-standard it counts wide characters instead of narrow and does not change -// mbstate -# define BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST -#endif + static_assert(sizeof(std::mbstate_t) >= 2, "std::mbstate_t is to small to store an UTF-16 codepoint"); + namespace detail { + // Avoid including cstring for std::memcpy + inline void copy_uint16_t(void* dst, const void* src) + { + unsigned char* cdst = static_cast<unsigned char*>(dst); + const unsigned char* csrc = static_cast<const unsigned char*>(src); + cdst[0] = csrc[0]; + cdst[1] = csrc[1]; + } + inline uint16_t read_state(const std::mbstate_t& src) + { + uint16_t dst; + copy_uint16_t(&dst, &src); + return dst; + } + inline void write_state(std::mbstate_t& dst, const uint16_t src) + { + copy_uint16_t(&dst, &src); + } + } // namespace detail /// \brief A base class that used to define constants for generic_codecvt class generic_codecvt_base { public: - /// Initial state for converting to or from unicode code points, used by initial_state in derived classes + /// Initial state for converting to or from Unicode code points, used by initial_state in derived classes enum initial_convertion_state { to_unicode_state, ///< The state would be used by to_unicode functions from_unicode_state ///< The state would be used by from_unicode functions @@ -47,13 +57,13 @@ namespace boost { namespace locale { /// that creates initial state /// - `int max_encoding_length() const` - a maximal length that one Unicode code point is represented, for UTF-8 for /// example it is 4 from ISO-8859-1 it is 1 - /// - `utf::code_point to_unicode(state_type &state,char const *&begin,char const *end)` - extract first code point - /// from the text in range [begin,end), in case of success begin would point to the next character sequence to be - /// encoded to next code point, in case of incomplete sequence - utf::incomplete shell be returned, and in case of - /// invalid input sequence utf::illegal shell be returned and begin would remain unmodified - /// - `utf::code_point from_unicode(state_type &state,utf::code_point u,char *begin,char const *end)` - convert a - /// unicode code point `u` into a character sequence at [begin,end). Return the length of the sequence in case of - /// success, utf::incomplete in case of not enough room to encode the code point of utf::illegal in case conversion + /// - `utf::code_point to_unicode(state_type& state, const char*& begin, const char* end)` - extract first code + /// point from the text in range [begin,end), in case of success begin would point to the next character sequence to + /// be encoded to next code point, in case of incomplete sequence - utf::incomplete shell be returned, and in case + /// of invalid input sequence utf::illegal shell be returned and begin would remain unmodified + /// - `utf::len_or_error from_unicode(state_type &state, utf::code_point u, char* begin, const char* end)` - convert + /// a Unicode code point `u` into a character sequence at [begin,end). Return the length of the sequence in case of + /// success, utf::incomplete in case of not enough room to encode the code point, or utf::illegal in case conversion /// can not be performed /// /// @@ -62,7 +72,7 @@ namespace boost { namespace locale { /// \code /// /// template<typename CharType> - /// class latin1_codecvt :boost::locale::generic_codecvt<CharType,latin1_codecvt<CharType> > + /// class latin1_codecvt: boost::locale::generic_codecvt<CharType,latin1_codecvt<CharType> > /// { /// public: /// @@ -84,15 +94,15 @@ namespace boost { namespace locale { /// return 1; /// } /// - /// boost::locale::utf::code_point to_unicode(state_type &,char const *&begin,char const *end) const + /// boost::locale::utf::code_point to_unicode(state_type&, const char*& begin, const char* end) const /// { /// if(begin == end) /// return boost::locale::utf::incomplete; /// return *begin++; /// } /// - /// boost::locale::utf::code_point from_unicode(state_type &,boost::locale::utf::code_point u,char *begin,char - /// const *end) const + /// boost::locale::utf::len_or_error from_unicode(state_type&, boost::locale::utf::code_point u, + /// char* begin, const char* end) const /// { /// if(u >= 256) /// return boost::locale::utf::illegal; @@ -110,23 +120,21 @@ namespace boost { namespace locale { /// /// \code /// template<typename CharType> - /// class icu_codecvt :boost::locale::generic_codecvt<CharType,icu_codecvt<CharType> > + /// class icu_codecvt: boost::locale::generic_codecvt<CharType,icu_codecvt<CharType>> /// { /// public: /// /// /* Standard codecvt constructor */ /// icu_codecvt(std::string const &name,refs = 0): - /// boost::locale::generic_codecvt<CharType,latin1_codecvt<CharType> >(refs) + /// boost::locale::generic_codecvt<CharType,icu_codecvt<CharType>>(refs) /// { ... } /// - /// /* State is unused but required by generic_codecvt */ - /// struct std::unique_ptr<UConverter,void (*)(UConverter*)> state_type; + /// using state_type = std::unique_ptr<UConverter,void (*)(UConverter*)>; /// - /// state_type &&initial_state(generic_codecvt_base::initial_convertion_state /*unused*/) const + /// state_type initial_state(generic_codecvt_base::initial_convertion_state /*unused*/) const /// { /// UErrorCode err = U_ZERO_ERROR; - /// state_type ptr(ucnv_safeClone(converter_,0,0,&err,ucnv_close); - /// return std::move(ptr); + /// return state_type(ucnv_safeClone(converter_,0,0,&err),ucnv_close); /// } /// /// boost::locale::utf::code_point to_unicode(state_type &ptr,char const *&begin,char const *end) const @@ -160,8 +168,7 @@ namespace boost { namespace locale { protected: std::codecvt_base::result do_unshift(std::mbstate_t& s, char* from, char* /*to*/, char*& next) const override { - boost::uint16_t& state = *reinterpret_cast<boost::uint16_t*>(&s); - if(state != 0) + if(*reinterpret_cast<char*>(&s) != 0) return std::codecvt_base::error; next = from; return std::codecvt_base::ok; @@ -170,47 +177,28 @@ namespace boost { namespace locale { int do_max_length() const noexcept override { return implementation().max_encoding_length(); } bool do_always_noconv() const noexcept override { return false; } - int do_length( -#ifdef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST - const -#endif - std::mbstate_t& std_state, - const char* from, - const char* from_end, - size_t max) const override + int do_length(std::mbstate_t& std_state, const char* from, const char* from_end, size_t max) const override { -#ifndef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST + bool state = *reinterpret_cast<char*>(&std_state) != 0; const char* save_from = from; - boost::uint16_t& state = *reinterpret_cast<boost::uint16_t*>(&std_state); -#else - const size_t start_max = max; - boost::uint16_t state = *reinterpret_cast<const boost::uint16_t*>(&std_state); -#endif - typename CodecvtImpl::state_type cvt_state = - implementation().initial_state(generic_codecvt_base::to_unicode_state); + auto cvt_state = implementation().initial_state(to_unicode_state); while(max > 0 && from < from_end) { const char* prev_from = from; - boost::uint32_t ch = implementation().to_unicode(cvt_state, from, from_end); + const utf::code_point ch = implementation().to_unicode(cvt_state, from, from_end); if(ch == boost::locale::utf::incomplete || ch == boost::locale::utf::illegal) { from = prev_from; break; } max--; if(ch > 0xFFFF) { - if(state == 0) { + if(!state) from = prev_from; - state = 1; - } else { - state = 0; - } + state = !state; } } -#ifndef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST + *reinterpret_cast<char*>(&std_state) = state; return static_cast<int>(from - save_from); -#else - return static_cast<int>(start_max - max); -#endif } std::codecvt_base::result do_in(std::mbstate_t& std_state, @@ -226,15 +214,14 @@ namespace boost { namespace locale { // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) // according to standard. We use it to keep a flag 0/1 for surrogate pair writing // - // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observed + // if 0/false no codepoint above >0xFFFF observed, else a codepoint above 0xFFFF was observed // and first pair is written, but no input consumed - boost::uint16_t& state = *reinterpret_cast<boost::uint16_t*>(&std_state); - typename CodecvtImpl::state_type cvt_state = - implementation().initial_state(generic_codecvt_base::to_unicode_state); + bool state = *reinterpret_cast<char*>(&std_state) != 0; + auto cvt_state = implementation().initial_state(to_unicode_state); while(to < to_end && from < from_end) { const char* from_saved = from; - uint32_t ch = implementation().to_unicode(cvt_state, from, from_end); + utf::code_point ch = implementation().to_unicode(cvt_state, from, from_end); if(ch == boost::locale::utf::illegal) { from = from_saved; @@ -247,9 +234,9 @@ namespace boost { namespace locale { break; } // Normal codepoints go directly to stream - if(ch <= 0xFFFF) { + if(ch <= 0xFFFF) *to++ = static_cast<uchar>(ch); - } else { + else { // For other codepoints we do the following // // 1. We can't consume our input as we may find ourselves @@ -260,22 +247,21 @@ namespace boost { namespace locale { // once again and then we would consume our input together with writing // second surrogate pair ch -= 0x10000; - boost::uint16_t w1 = static_cast<boost::uint16_t>(0xD800 | (ch >> 10)); - boost::uint16_t w2 = static_cast<boost::uint16_t>(0xDC00 | (ch & 0x3FF)); - if(state == 0) { + std::uint16_t w1 = static_cast<std::uint16_t>(0xD800 | (ch >> 10)); + std::uint16_t w2 = static_cast<std::uint16_t>(0xDC00 | (ch & 0x3FF)); + if(!state) { from = from_saved; *to++ = w1; - state = 1; - } else { + } else *to++ = w2; - state = 0; - } + state = !state; } } from_next = from; to_next = to; - if(r == std::codecvt_base::ok && (from != from_end || state != 0)) + if(r == std::codecvt_base::ok && (from != from_end || state)) r = std::codecvt_base::partial; + *reinterpret_cast<char*>(&std_state) = state; return r; } @@ -294,22 +280,21 @@ namespace boost { namespace locale { // // State: state!=0 - a first surrogate pair was observed (state = first pair), // we expect the second one to come and then zero the state - boost::uint16_t& state = *reinterpret_cast<boost::uint16_t*>(&std_state); - typename CodecvtImpl::state_type cvt_state = - implementation().initial_state(generic_codecvt_base::from_unicode_state); + std::uint16_t state = detail::read_state(std_state); + auto cvt_state = implementation().initial_state(from_unicode_state); while(to < to_end && from < from_end) { - boost::uint32_t ch = 0; + utf::code_point ch = 0; if(state != 0) { // if the state indicates that 1st surrogate pair was written // we should make sure that the second one that comes is actually // second surrogate - boost::uint16_t w1 = state; - boost::uint16_t w2 = *from; + std::uint16_t w1 = state; + std::uint16_t w2 = *from; // we don't forward from as writing may fail to incomplete or // partial conversion if(0xDC00 <= w2 && w2 <= 0xDFFF) { - boost::uint16_t vh = w1 - 0xD800; - boost::uint16_t vl = w2 - 0xDC00; + std::uint16_t vh = w1 - 0xD800; + std::uint16_t vl = w2 - 0xDC00; ch = ((uint32_t(vh) << 10) | vl) + 0x10000; } else { // Invalid surrogate @@ -338,7 +323,7 @@ namespace boost { namespace locale { r = std::codecvt_base::error; break; } - boost::uint32_t len = implementation().from_unicode(cvt_state, ch, to, to_end); + const utf::code_point len = implementation().from_unicode(cvt_state, ch, to, to_end); if(len == boost::locale::utf::incomplete) { r = std::codecvt_base::partial; break; @@ -354,6 +339,7 @@ namespace boost { namespace locale { to_next = to; if(r == std::codecvt_base::ok && (from != from_end || state != 0)) r = std::codecvt_base::partial; + detail::write_state(std_state, state); return r; } }; @@ -383,25 +369,13 @@ namespace boost { namespace locale { int do_max_length() const noexcept override { return implementation().max_encoding_length(); } bool do_always_noconv() const noexcept override { return false; } - int do_length( -#ifdef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST - const -#endif - std::mbstate_t& /*state*/, - const char* from, - const char* from_end, - size_t max) const override + int do_length(std::mbstate_t& /*state*/, const char* from, const char* from_end, size_t max) const override { -#ifndef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST const char* start_from = from; -#else - const size_t start_max = max; -#endif - typename CodecvtImpl::state_type cvt_state = - implementation().initial_state(generic_codecvt_base::to_unicode_state); + auto cvt_state = implementation().initial_state(to_unicode_state); while(max > 0 && from < from_end) { const char* save_from = from; - boost::uint32_t ch = implementation().to_unicode(cvt_state, from, from_end); + const utf::code_point ch = implementation().to_unicode(cvt_state, from, from_end); if(ch == boost::locale::utf::incomplete || ch == boost::locale::utf::illegal) { from = save_from; break; @@ -409,11 +383,7 @@ namespace boost { namespace locale { max--; } -#ifndef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST return static_cast<int>(from - start_from); -#else - return static_cast<int>(start_max - max); -#endif } std::codecvt_base::result do_in(std::mbstate_t& /*state*/, @@ -426,16 +396,11 @@ namespace boost { namespace locale { { std::codecvt_base::result r = std::codecvt_base::ok; - // mbstate_t is POD type and should be initialized to 0 (i.a. state = stateT()) - // according to standard. We use it to keep a flag 0/1 for surrogate pair writing - // - // if 0 no code above >0xFFFF observed, of 1 a code above 0xFFFF observed - // and first pair is written, but no input consumed - auto cvt_state = implementation().initial_state(generic_codecvt_base::to_unicode_state); + auto cvt_state = implementation().initial_state(to_unicode_state); while(to < to_end && from < from_end) { const char* from_saved = from; - uint32_t ch = implementation().to_unicode(cvt_state, from, from_end); + const utf::code_point ch = implementation().to_unicode(cvt_state, from, from_end); if(ch == boost::locale::utf::illegal) { r = std::codecvt_base::error; @@ -465,15 +430,14 @@ namespace boost { namespace locale { char*& to_next) const override { std::codecvt_base::result r = std::codecvt_base::ok; - auto cvt_state = implementation().initial_state(generic_codecvt_base::from_unicode_state); + auto cvt_state = implementation().initial_state(from_unicode_state); while(to < to_end && from < from_end) { - boost::uint32_t ch = 0; - ch = *from; + const std::uint32_t ch = *from; if(!boost::locale::utf::is_valid_codepoint(ch)) { r = std::codecvt_base::error; break; } - boost::uint32_t len = implementation().from_unicode(cvt_state, ch, to, to_end); + const utf::code_point len = implementation().from_unicode(cvt_state, ch, to, to_end); if(len == boost::locale::utf::incomplete) { r = std::codecvt_base::partial; break; diff --git a/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp b/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp index 675f5192c4..aff76b1cdc 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/gnu_gettext.hpp @@ -7,11 +7,18 @@ #ifndef BOOST_LOCLAE_GNU_GETTEXT_HPP #define BOOST_LOCLAE_GNU_GETTEXT_HPP +#include <boost/locale/detail/is_supported_char.hpp> #include <boost/locale/message.hpp> #include <functional> #include <stdexcept> +#include <type_traits> #include <vector> +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface... +#endif + namespace boost { namespace locale { /// \addtogroup message /// @{ @@ -25,7 +32,7 @@ namespace boost { namespace locale { /// also allows providing functions for charset conversion. Note, you need to provide them, /// so this structure is not useful for wide characters without subclassing and it will also /// ignore gettext catalogs that use a charset different from \a encoding. - struct messages_info { + struct BOOST_LOCALE_DECL messages_info { messages_info() : language("C"), locale_category("LC_MESSAGES") {} std::string language; ///< The language we load the catalog for, like "ru", "en", "de" @@ -53,7 +60,7 @@ namespace boost { namespace locale { /// "UTF-8" domain(const std::string& n) { - size_t pos = n.find('/'); + const size_t pos = n.find('/'); if(pos == std::string::npos) { name = n; encoding = "UTF-8"; @@ -80,7 +87,7 @@ namespace boost { namespace locale { /// encoded in \a encoding character set into std::vector<char> and return it. /// /// - If the file does not exist, it should return an empty vector. - /// - If a error occurs during file read it should throw a error. + /// - If an error occurs during file read it should throw an exception. /// /// \note The user should support only the encodings the locales are created for. So if the user /// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter. @@ -90,32 +97,19 @@ namespace boost { namespace locale { /// The callback for handling custom file systems, if it is empty, the real OS file-system /// is being used. callback_type callback; + + /// Get paths to folders which may contain catalog files + std::vector<std::string> get_catalog_paths() const; + + private: + /// Get a list of folder names for the language, country and variant + std::vector<std::string> get_lang_folders() const; }; /// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get /// information about where to read them from and uses it for character set conversion (if needed) - template<typename CharType> - message_format<CharType>* create_messages_facet(const messages_info& info); - - /// \cond INTERNAL - - template<> - BOOST_LOCALE_DECL message_format<char>* create_messages_facet(const messages_info& info); - - template<> - BOOST_LOCALE_DECL message_format<wchar_t>* create_messages_facet(const messages_info& info); - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template<> - BOOST_LOCALE_DECL message_format<char16_t>* create_messages_facet(const messages_info& info); -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template<> - BOOST_LOCALE_DECL message_format<char32_t>* create_messages_facet(const messages_info& info); -#endif - - /// \endcond + template<typename CharType, class = boost::locale::detail::enable_if_is_supported_char<CharType>> + BOOST_LOCALE_DECL message_format<CharType>* create_messages_facet(const messages_info& info); } // namespace gnu_gettext @@ -123,4 +117,8 @@ namespace boost { namespace locale { }} // namespace boost::locale +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + #endif diff --git a/contrib/restricted/boost/locale/include/boost/locale/hold_ptr.hpp b/contrib/restricted/boost/locale/include/boost/locale/hold_ptr.hpp index 851ddbf210..c421b29013 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/hold_ptr.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/hold_ptr.hpp @@ -8,6 +8,7 @@ #define BOOST_LOCALE_HOLD_PTR_H #include <boost/locale/config.hpp> +#include <boost/core/exchange.hpp> namespace boost { namespace locale { /// \brief a smart pointer similar to std::unique_ptr but the @@ -28,7 +29,7 @@ namespace boost { namespace locale { hold_ptr(const hold_ptr&) = delete; hold_ptr& operator=(const hold_ptr&) = delete; // Movable - hold_ptr(hold_ptr&& other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; } + hold_ptr(hold_ptr&& other) noexcept : ptr_(exchange(other.ptr_, nullptr)) {} hold_ptr& operator=(hold_ptr&& other) noexcept { swap(other); @@ -70,7 +71,7 @@ namespace boost { namespace locale { } /// Swap two pointers - void swap(hold_ptr& other) + void swap(hold_ptr& other) noexcept { T* tmp = other.ptr_; other.ptr_ = ptr_; diff --git a/contrib/restricted/boost/locale/include/boost/locale/info.hpp b/contrib/restricted/boost/locale/include/boost/locale/info.hpp index e10f134f86..37b5358d5f 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/info.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/info.hpp @@ -8,6 +8,7 @@ #define BOOST_LOCALE_INFO_HPP_INCLUDED #include <boost/locale/config.hpp> +#include <boost/locale/detail/facet_id.hpp> #include <locale> #include <string> @@ -21,12 +22,8 @@ namespace boost { namespace locale { /// \brief a facet that holds general information about locale /// /// This facet should be always created in order to make all Boost.Locale functions work - class BOOST_LOCALE_DECL info : public std::locale::facet { + class BOOST_SYMBOL_VISIBLE info : public std::locale::facet, public detail::facet_id<info> { public: - ~info(); - - static std::locale::id id; ///< This member uniquely defines this facet, required by STL - /// String information about the locale enum string_propery { language_property, ///< ISO 639 language id diff --git a/contrib/restricted/boost/locale/include/boost/locale/localization_backend.hpp b/contrib/restricted/boost/locale/include/boost/locale/localization_backend.hpp index 37df24e283..bb163cd245 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/localization_backend.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/localization_backend.hpp @@ -70,29 +70,31 @@ namespace boost { namespace locale { localization_backend_manager(const localization_backend_manager&); /// Assign localization_backend_manager localization_backend_manager& operator=(const localization_backend_manager&); + /// Move construct localization_backend_manager + localization_backend_manager(localization_backend_manager&&) noexcept; + /// Move assign localization_backend_manager + localization_backend_manager& operator=(localization_backend_manager&&) noexcept; /// Destructor ~localization_backend_manager(); - /// Create new localization backend according to current settings. - std::unique_ptr<localization_backend> get() const; + /// Create new localization backend according to current settings. Ownership is passed to caller + std::unique_ptr<localization_backend> create() const; - BOOST_DEPRECATED("This function is deprecated, use 'get()' instead") - std::unique_ptr<localization_backend> get_unique_ptr() const { return get(); } + BOOST_DEPRECATED("This function is deprecated, use 'create()' instead") + std::unique_ptr<localization_backend> get() const { return create(); } // LCOV_EXCL_LINE + BOOST_DEPRECATED("This function is deprecated, use 'create()' instead") + std::unique_ptr<localization_backend> get_unique_ptr() const { return create(); } // LCOV_EXCL_LINE /// Add new backend to the manager, each backend should be uniquely defined by its name. /// /// This library provides: "icu", "posix", "winapi" and "std" backends. void add_backend(const std::string& name, std::unique_ptr<localization_backend> backend); - /// Create new localization backend according to current settings. Ownership is passed to caller - localization_backend* create() const; - - /// Add new backend to the manager, each backend should be uniquely defined by its name. - /// ownership on backend is transfered - /// - /// This library provides: "icu", "posix", "winapi" and "std" backends. - void adopt_backend(const std::string& name, localization_backend* backend); + // clang-format off + BOOST_DEPRECATED("This function is deprecated, use 'add_backend' instead") + void adopt_backend(const std::string& name, localization_backend* backend) { add_backend(name, std::unique_ptr<localization_backend>(backend)); } // LCOV_EXCL_LINE + // clang-format on /// Clear backend void remove_all_backends(); diff --git a/contrib/restricted/boost/locale/include/boost/locale/message.hpp b/contrib/restricted/boost/locale/include/boost/locale/message.hpp index 3aacc5801a..b0a512c18a 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/message.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/message.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -7,12 +8,15 @@ #ifndef BOOST_LOCALE_MESSAGE_HPP_INCLUDED #define BOOST_LOCALE_MESSAGE_HPP_INCLUDED +#include <boost/locale/detail/facet_id.hpp> +#include <boost/locale/detail/is_supported_char.hpp> #include <boost/locale/formatting.hpp> #include <boost/locale/util/string.hpp> #include <locale> #include <memory> #include <set> #include <string> +#include <type_traits> #ifdef BOOST_MSVC # pragma warning(push) @@ -36,24 +40,23 @@ namespace boost { namespace locale { /// @{ /// - /// \cond INTERNAL - - template<typename CharType> - struct base_message_format; - - /// \endcond + /// Type used for the count/n argument to the translation functions choosing between singular and plural forms + using count_type = long long; /// \brief This facet provides message formatting abilities template<typename CharType> - class BOOST_SYMBOL_VISIBLE message_format : public base_message_format<CharType> { + class BOOST_SYMBOL_VISIBLE message_format : public std::locale::facet, + public detail::facet_id<message_format<CharType>> { + BOOST_LOCALE_ASSERT_IS_SUPPORTED(CharType); + public: /// Character type typedef CharType char_type; /// String type typedef std::basic_string<CharType> string_type; - /// Default constructor - message_format(size_t refs = 0) : base_message_format<CharType>(refs) {} + /// Standard constructor + message_format(size_t refs = 0) : std::locale::facet(refs) {} /// This function returns a pointer to the string for a message defined by a \a context /// and identification string \a id. Both create a single key for message lookup in @@ -75,7 +78,7 @@ namespace boost { namespace locale { /// /// If a translated string is found, it is returned, otherwise NULL is returned virtual const char_type* - get(int domain_id, const char_type* context, const char_type* single_id, int n) const = 0; + get(int domain_id, const char_type* context, const char_type* single_id, count_type n) const = 0; /// Convert a string that defines \a domain to the integer id used by \a get functions virtual int domain(const std::string& domain) const = 0; @@ -87,9 +90,6 @@ namespace boost { namespace locale { /// Note: for char_type that is char16_t, char32_t and wchar_t it is no-op, returns /// msg virtual const char_type* convert(const char_type* msg, string_type& buffer) const = 0; - - protected: - virtual ~message_format() = default; }; /// \cond INTERNAL @@ -146,48 +146,54 @@ namespace boost { namespace locale { typedef message_format<char_type> facet_type; ///< The type of the facet the messages are fetched with /// Create default empty message - basic_message() : n_(0), c_id_(0), c_context_(0), c_plural_(0) {} + basic_message() : n_(0), c_id_(nullptr), c_context_(nullptr), c_plural_(nullptr) {} /// Create a simple message from 0 terminated string. The string should exist /// until the message is destroyed. Generally useful with static constant strings - explicit basic_message(const char_type* id) : n_(0), c_id_(id), c_context_(0), c_plural_(0) {} + explicit basic_message(const char_type* id) : n_(0), c_id_(id), c_context_(nullptr), c_plural_(nullptr) {} /// Create a simple plural form message from 0 terminated strings. The strings should exist /// until the message is destroyed. Generally useful with static constant strings. /// /// \a n is the number, \a single and \a plural are singular and plural forms of the message - explicit basic_message(const char_type* single, const char_type* plural, int n) : - n_(n), c_id_(single), c_context_(0), c_plural_(plural) + explicit basic_message(const char_type* single, const char_type* plural, count_type n) : + n_(n), c_id_(single), c_context_(nullptr), c_plural_(plural) {} /// Create a simple message from 0 terminated strings, with context /// information. The string should exist /// until the message is destroyed. Generally useful with static constant strings explicit basic_message(const char_type* context, const char_type* id) : - n_(0), c_id_(id), c_context_(context), c_plural_(0) + n_(0), c_id_(id), c_context_(context), c_plural_(nullptr) {} /// Create a simple plural form message from 0 terminated strings, with context. The strings should exist /// until the message is destroyed. Generally useful with static constant strings. /// /// \a n is the number, \a single and \a plural are singular and plural forms of the message - explicit basic_message(const char_type* context, const char_type* single, const char_type* plural, int n) : - n_(n), c_id_(single), c_context_(context), c_plural_(plural) + explicit basic_message(const char_type* context, + const char_type* single, + const char_type* plural, + count_type n) : + n_(n), + c_id_(single), c_context_(context), c_plural_(plural) {} /// Create a simple message from a string. - explicit basic_message(const string_type& id) : n_(0), c_id_(0), c_context_(0), c_plural_(0), id_(id) {} + explicit basic_message(const string_type& id) : + n_(0), c_id_(nullptr), c_context_(nullptr), c_plural_(nullptr), id_(id) + {} /// Create a simple plural form message from strings. /// /// \a n is the number, \a single and \a plural are single and plural forms of the message - explicit basic_message(const string_type& single, const string_type& plural, int number) : - n_(number), c_id_(0), c_context_(0), c_plural_(0), id_(single), plural_(plural) + explicit basic_message(const string_type& single, const string_type& plural, count_type number) : + n_(number), c_id_(nullptr), c_context_(nullptr), c_plural_(nullptr), id_(single), plural_(plural) {} /// Create a simple message from a string with context. explicit basic_message(const string_type& context, const string_type& id) : - n_(0), c_id_(0), c_context_(0), c_plural_(0), id_(id), context_(context) + n_(0), c_id_(nullptr), c_context_(nullptr), c_plural_(nullptr), id_(id), context_(context) {} /// Create a simple plural form message from strings. @@ -196,41 +202,40 @@ namespace boost { namespace locale { explicit basic_message(const string_type& context, const string_type& single, const string_type& plural, - int number) : + count_type number) : n_(number), - c_id_(0), c_context_(0), c_plural_(0), id_(single), context_(context), plural_(plural) + c_id_(nullptr), c_context_(nullptr), c_plural_(nullptr), id_(single), context_(context), plural_(plural) {} /// Copy an object basic_message(const basic_message&) = default; - basic_message(basic_message&&) = default; + basic_message(basic_message&&) noexcept = default; /// Assign other message object to this one basic_message& operator=(const basic_message&) = default; - basic_message& operator=(basic_message&&) = default; + basic_message& + operator=(basic_message&&) noexcept(std::is_nothrow_move_assignable<string_type>::value) = default; /// Swap two message objects - void swap(basic_message& other) + void + swap(basic_message& other) noexcept(noexcept(std::declval<string_type&>().swap(std::declval<string_type&>()))) { - std::swap(n_, other.n_); - std::swap(c_id_, other.c_id_); - std::swap(c_context_, other.c_context_); - std::swap(c_plural_, other.c_plural_); - - id_.swap(other.id_); - context_.swap(other.context_); - plural_.swap(other.plural_); + using std::swap; + swap(n_, other.n_); + swap(c_id_, other.c_id_); + swap(c_context_, other.c_context_); + swap(c_plural_, other.c_plural_); + swap(id_, other.id_); + swap(context_, other.context_); + swap(plural_, other.plural_); } + friend void swap(basic_message& x, basic_message& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } /// Message class can be explicitly converted to string class operator string_type() const { return str(); } /// Translate message to a string in the default global locale, using default domain - string_type str() const - { - std::locale loc; - return str(loc, 0); - } + string_type str() const { return str(std::locale()); } /// Translate message to a string in the locale \a locale, using default domain string_type str(const std::locale& locale) const { return str(locale, 0); } @@ -245,23 +250,14 @@ namespace boost { namespace locale { } /// Translate message to a string using the default locale and message domain \a domain_id - string_type str(const std::string& domain_id) const - { - int id = 0; - std::locale loc; - if(std::has_facet<facet_type>(loc)) - id = std::use_facet<facet_type>(loc).domain(domain_id); - return str(loc, id); - } + string_type str(const std::string& domain_id) const { return str(std::locale(), domain_id); } /// Translate message to a string using locale \a loc and message domain index \a id string_type str(const std::locale& loc, int id) const { string_type buffer; const char_type* ptr = write(loc, id, buffer); - if(ptr == buffer.c_str()) - return buffer; - else + if(ptr != buffer.c_str()) buffer = ptr; return buffer; } @@ -282,7 +278,7 @@ namespace boost { namespace locale { if(c_plural_) return c_plural_; if(plural_.empty()) - return 0; + return nullptr; return plural_.c_str(); } const char_type* context() const @@ -290,7 +286,7 @@ namespace boost { namespace locale { if(c_context_) return c_context_; if(context_.empty()) - return 0; + return nullptr; return context_.c_str(); } @@ -298,7 +294,6 @@ namespace boost { namespace locale { const char_type* write(const std::locale& loc, int domain_id, string_type& buffer) const { - const char_type* translated = 0; static const char_type empty_string[1] = {0}; const char_type* id = this->id(); @@ -308,33 +303,32 @@ namespace boost { namespace locale { if(*id == 0) return empty_string; - const facet_type* facet = 0; + const facet_type* facet = nullptr; if(std::has_facet<facet_type>(loc)) facet = &std::use_facet<facet_type>(loc); + const char_type* translated = nullptr; if(facet) { - if(!plural) { + if(!plural) translated = facet->get(domain_id, context, id); - } else { + else translated = facet->get(domain_id, context, id, n_); - } } if(!translated) { const char_type* msg = plural ? (n_ == 1 ? id : plural) : id; - if(facet) { + if(facet) translated = facet->convert(msg, buffer); - } else { + else translated = detail::string_cast_traits<char_type>::cast(msg, buffer); - } } return translated; } /// members - int n_; + count_type n_; const char_type* c_id_; const char_type* c_context_; const char_type* c_plural_; @@ -383,15 +377,15 @@ namespace boost { namespace locale { /// \brief Translate a plural message form, \a single and \a plural are not copied template<typename CharType> - inline basic_message<CharType> translate(const CharType* single, const CharType* plural, int n) + inline basic_message<CharType> translate(const CharType* single, const CharType* plural, count_type n) { return basic_message<CharType>(single, plural, n); } - /// \brief Translate a plural message from in constext, \a context, \a single and \a plural are not copied + /// \brief Translate a plural message from in context, \a context, \a single and \a plural are not copied template<typename CharType> inline basic_message<CharType> - translate(const CharType* context, const CharType* single, const CharType* plural, int n) + translate(const CharType* context, const CharType* single, const CharType* plural, count_type n) { return basic_message<CharType>(context, single, plural, n); } @@ -411,12 +405,12 @@ namespace boost { namespace locale { return basic_message<CharType>(context, msg); } - /// \brief Translate a plural message form in constext, \a context, \a single and \a plural are copied + /// \brief Translate a plural message form in context, \a context, \a single and \a plural are copied template<typename CharType> inline basic_message<CharType> translate(const std::basic_string<CharType>& context, const std::basic_string<CharType>& single, const std::basic_string<CharType>& plural, - int n) + count_type n) { return basic_message<CharType>(context, single, plural, n); } @@ -424,7 +418,7 @@ namespace boost { namespace locale { /// \brief Translate a plural message form, \a single and \a plural are copied template<typename CharType> inline basic_message<CharType> - translate(const std::basic_string<CharType>& single, const std::basic_string<CharType>& plural, int n) + translate(const std::basic_string<CharType>& single, const std::basic_string<CharType>& plural, count_type n) { return basic_message<CharType>(single, plural, n); } @@ -442,7 +436,7 @@ namespace boost { namespace locale { /// Translate plural form according to locale \a loc template<typename CharType> std::basic_string<CharType> - ngettext(const CharType* s, const CharType* p, int n, const std::locale& loc = std::locale()) + ngettext(const CharType* s, const CharType* p, count_type n, const std::locale& loc = std::locale()) { return basic_message<CharType>(s, p, n).str(loc); } @@ -456,8 +450,11 @@ namespace boost { namespace locale { /// Translate plural form according to locale \a loc in domain \a domain template<typename CharType> - std::basic_string<CharType> - dngettext(const char* domain, const CharType* s, const CharType* p, int n, const std::locale& loc = std::locale()) + std::basic_string<CharType> dngettext(const char* domain, + const CharType* s, + const CharType* p, + count_type n, + const std::locale& loc = std::locale()) { return basic_message<CharType>(s, p, n).str(loc, domain); } @@ -475,7 +472,7 @@ namespace boost { namespace locale { std::basic_string<CharType> npgettext(const CharType* context, const CharType* s, const CharType* p, - int n, + count_type n, const std::locale& loc = std::locale()) { return basic_message<CharType>(context, s, p, n).str(loc); @@ -495,51 +492,12 @@ namespace boost { namespace locale { const CharType* context, const CharType* s, const CharType* p, - int n, + count_type n, const std::locale& loc = std::locale()) { return basic_message<CharType>(context, s, p, n).str(loc, domain); } - /// \cond INTERNAL - - template<> - struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet { - base_message_format(size_t refs = 0) : std::locale::facet(refs) {} - ~base_message_format(); - static std::locale::id id; - }; - - template<> - struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet { - base_message_format(size_t refs = 0) : std::locale::facet(refs) {} - ~base_message_format(); - static std::locale::id id; - }; - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - - template<> - struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet { - base_message_format(size_t refs = 0) : std::locale::facet(refs) {} - ~base_message_format(); - static std::locale::id id; - }; - -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - - template<> - struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet { - base_message_format(size_t refs = 0) : std::locale::facet(refs) {} - ~base_message_format(); - static std::locale::id id; - }; - -#endif - - /// \endcond /// @} namespace as { diff --git a/contrib/restricted/boost/locale/include/boost/locale/utf.hpp b/contrib/restricted/boost/locale/include/boost/locale/utf.hpp index 841b10f67e..a30f736b21 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/utf.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/utf.hpp @@ -8,7 +8,7 @@ #define BOOST_LOCALE_UTF_HPP_INCLUDED #include <boost/locale/config.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> namespace boost { namespace locale { /// \brief Namespace that holds basic operations on UTF encoded sequences @@ -16,13 +16,16 @@ namespace boost { namespace locale { /// All functions defined in this namespace do not require linking with Boost.Locale library namespace utf { /// \brief The integral type that can hold a Unicode code point - typedef uint32_t code_point; + using code_point = uint32_t; /// \brief Special constant that defines illegal code point constexpr code_point illegal = 0xFFFFFFFFu; /// \brief Special constant that defines incomplete code point constexpr code_point incomplete = 0xFFFFFFFEu; + /// Either a length/size or an error (illegal/incomplete) + using len_or_error = code_point; + /// \brief the function checks if \a v is a valid code point inline bool is_valid_codepoint(code_point v) { @@ -125,15 +128,14 @@ namespace boost { namespace locale { static int width(code_point value) { - if(value <= 0x7F) { + if(value <= 0x7F) return 1; - } else if(value <= 0x7FF) { + else if(value <= 0x7FF) return 2; - } else if(BOOST_LIKELY(value <= 0xFFFF)) { + else if(BOOST_LIKELY(value <= 0xFFFF)) return 3; - } else { + else return 4; - } } static bool is_trail(char_type ci) @@ -235,9 +237,9 @@ namespace boost { namespace locale { template<typename Iterator> static Iterator encode(code_point value, Iterator out) { - if(value <= 0x7F) { + if(value <= 0x7F) *out++ = static_cast<char_type>(value); - } else if(value <= 0x7FF) { + else if(value <= 0x7FF) { *out++ = static_cast<char_type>((value >> 6) | 0xC0); *out++ = static_cast<char_type>((value & 0x3F) | 0x80); } else if(BOOST_LIKELY(value <= 0xFFFF)) { @@ -285,9 +287,8 @@ namespace boost { namespace locale { if(BOOST_UNLIKELY(current == last)) return incomplete; uint16_t w1 = *current++; - if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) return w1; - } if(w1 > 0xDBFF) return illegal; if(current == last) @@ -301,9 +302,8 @@ namespace boost { namespace locale { static code_point decode_valid(It& current) { uint16_t w1 = *current++; - if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) return w1; - } uint16_t w2 = *current++; return combine_surrogate(w1, w2); } @@ -313,9 +313,9 @@ namespace boost { namespace locale { template<typename It> static It encode(code_point u, It out) { - if(BOOST_LIKELY(u <= 0xFFFF)) { + if(BOOST_LIKELY(u <= 0xFFFF)) *out++ = static_cast<char_type>(u); - } else { + else { u -= 0x10000; *out++ = static_cast<char_type>(0xD800 | (u >> 10)); *out++ = static_cast<char_type>(0xDC00 | (u & 0x3FF)); diff --git a/contrib/restricted/boost/locale/include/boost/locale/utf8_codecvt.hpp b/contrib/restricted/boost/locale/include/boost/locale/utf8_codecvt.hpp index d2884c6770..797d907346 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/utf8_codecvt.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/utf8_codecvt.hpp @@ -9,7 +9,8 @@ #include <boost/locale/generic_codecvt.hpp> #include <boost/locale/utf.hpp> -#include <boost/cstdint.hpp> +#include <boost/assert.hpp> +#include <cstdint> #include <locale> namespace boost { namespace locale { @@ -39,12 +40,11 @@ namespace boost { namespace locale { return c; } - static utf::code_point from_unicode(state_type&, utf::code_point u, char* begin, const char* end) + static utf::len_or_error from_unicode(state_type&, utf::code_point u, char* begin, const char* end) { - if(!utf::is_valid_codepoint(u)) - return utf::illegal; - int width; - if((width = utf::utf_traits<char>::width(u)) > end - begin) + BOOST_ASSERT(utf::is_valid_codepoint(u)); + const auto width = utf::utf_traits<char>::width(u); + if(width > end - begin) return utf::incomplete; utf::utf_traits<char>::encode(u, begin); return width; diff --git a/contrib/restricted/boost/locale/include/boost/locale/util.hpp b/contrib/restricted/boost/locale/include/boost/locale/util.hpp index d5bf8ddcca..5eaf450556 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/util.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/util.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -10,7 +11,7 @@ #include <boost/locale/generator.hpp> #include <boost/locale/utf.hpp> #include <boost/assert.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> #include <locale> #include <memory> #include <typeinfo> @@ -68,11 +69,11 @@ namespace boost { namespace locale { /// This value should be returned when an illegal input sequence or code-point is observed: /// For example if a UCS-32 code-point is in the range reserved for UTF-16 surrogates /// or an invalid UTF-8 sequence is found - static constexpr uint32_t illegal = utf::illegal; + static constexpr utf::code_point illegal = utf::illegal; /// This value is returned in following cases: The of incomplete input sequence was found or /// insufficient output buffer was provided so complete output could not be written. - static constexpr uint32_t incomplete = utf::incomplete; + static constexpr utf::code_point incomplete = utf::incomplete; virtual ~base_converter(); @@ -110,7 +111,7 @@ namespace boost { namespace locale { /// if invalid input sequence found, i.e. there is a sequence [\a begin, \a code_point_end) such as \a /// code_point_end <= \a end that is illegal for this encoding, \a illegal is returned and begin stays /// unchanged. For example if *begin = 0xFF and begin < end for UTF-8, then \a illegal is returned. - virtual uint32_t to_unicode(const char*& begin, const char* end) + virtual utf::code_point to_unicode(const char*& begin, const char* end) { if(begin == end) return incomplete; @@ -132,7 +133,7 @@ namespace boost { namespace locale { /// -# If end - begin >= N, c1, ... cN are written starting at begin and N is returned /// -# If end - begin < N, incomplete is returned, it is unspecified what would be /// stored in bytes in range [begin,end) - virtual uint32_t from_unicode(uint32_t u, char* begin, const char* end) + virtual utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end) { if(begin == end) return incomplete; @@ -144,7 +145,7 @@ namespace boost { namespace locale { }; /// This function creates a \a base_converter that can be used for conversion between UTF-8 and - /// unicode code points + /// Unicode code points BOOST_LOCALE_DECL std::unique_ptr<base_converter> create_utf8_converter(); BOOST_DEPRECATED("This function is deprecated, use 'create_utf8_converter()'") @@ -185,15 +186,10 @@ namespace boost { namespace locale { return create_codecvt(in, std::unique_ptr<base_converter>(cvt), type); } - /// This function creates a \a base_converter that can be used for conversion between UTF-8 and - /// unicode code points + BOOST_DEPRECATED("This function is deprecated, use 'create_utf8_converter()'") BOOST_LOCALE_DECL base_converter* create_utf8_converter_new_ptr(); - /// This function creates a \a base_converter that can be used for conversion between single byte - /// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points, - /// - /// If \a encoding is not supported, empty pointer is returned. You should check if - /// the returned pointer is NULL. + BOOST_DEPRECATED("This function is deprecated, use 'create_simple_converter()'") BOOST_LOCALE_DECL base_converter* create_simple_converter_new_ptr(const std::string& encoding); /// Install utf8 codecvt to UTF-16 or UTF-32 into locale \a in and return @@ -204,8 +200,8 @@ namespace boost { namespace locale { /// This function installs codecvt that can be used for conversion between single byte /// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points, /// - /// Throws boost::locale::conv::invalid_charset_error if the character set is not supported or isn't single byte - /// character set + /// \throws boost::locale::conv::invalid_charset_error: Character set is not supported or isn't a single + /// byte character set BOOST_LOCALE_DECL std::locale create_simple_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type); } // namespace util diff --git a/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp b/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp index 2a04bdcba9..397c404d60 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/util/locale_data.hpp @@ -27,10 +27,11 @@ namespace boost { namespace locale { namespace util { bool utf8_; public: - // Default to C locale with US-ASCII encoding + /// Default to C locale with US-ASCII encoding locale_data(); - // Construct from the parsed locale \see \ref parse - // Throws `std::invalid_argument` if parsing fails + /// Construct from the parsed locale \see \ref parse + /// + /// \throws std::invalid_argument: parsing failed explicit locale_data(const std::string& locale_name); /// Return language (usually 2 lowercase letters, i.e. ISO-639 or 'C') @@ -39,24 +40,25 @@ namespace boost { namespace locale { namespace util { const std::string& country() const { return country_; } /// Return encoding/codeset, e.g. ISO8859-1 or UTF-8 const std::string& encoding() const { return encoding_; } + /// Set encoding, will be made uppercase by default as-if it was parsed + /// Returns \c *this for chaining + locale_data& encoding(std::string new_encoding, bool uppercase = true); /// Return variant/modifier, e.g. euro or stroke const std::string& variant() const { return variant_; } /// Return iff the encoding is UTF-8 bool is_utf8() const { return utf8_; } - /// <summary> - /// Parse a locale identifier of the form [language[_territory][.codeset][@modifier]] - /// Allows a dash as the delimiter: [language-territory] + /// Parse a locale identifier of the form `[language[_territory][.codeset][@modifier]]` /// + /// Allows a dash as the delimiter: `[language-territory]` /// Return true if the identifier is valid: /// - `language` is given and consists of ASCII letters /// - `territory`, if given, consists of ASCII letters /// - Any field started by a delimiter (`_`, `-`, `.`, `@`) is not empty /// Otherwise parsing is aborted. Valid values already parsed stay set, other are defaulted. - /// </summary> bool parse(const std::string& locale_name); - /// Get a representation in the form [language[_territory][.codeset][@modifier]] + /// Get a representation in the form `[language[_territory][.codeset][@modifier]]` /// codeset is omitted if it is US-ASCII std::string to_string() const; diff --git a/contrib/restricted/boost/locale/include/boost/locale/util/string.hpp b/contrib/restricted/boost/locale/include/boost/locale/util/string.hpp index 14e52e65af..9ab9521c55 100644 --- a/contrib/restricted/boost/locale/include/boost/locale/util/string.hpp +++ b/contrib/restricted/boost/locale/include/boost/locale/util/string.hpp @@ -8,6 +8,7 @@ #define BOOST_LOCALE_UTIL_STRING_HPP #include <boost/locale/config.hpp> +#include <limits> namespace boost { namespace locale { namespace util { /// Return the end of a C-string, i.e. the pointer to the trailing NULL byte @@ -19,21 +20,27 @@ namespace boost { namespace locale { namespace util { return str; } - inline bool is_upper_ascii(const char c) + inline constexpr bool is_upper_ascii(const char c) { return 'A' <= c && c <= 'Z'; } - inline bool is_lower_ascii(const char c) + inline constexpr bool is_lower_ascii(const char c) { return 'a' <= c && c <= 'z'; } - inline bool is_numeric_ascii(const char c) + inline constexpr bool is_numeric_ascii(const char c) { return '0' <= c && c <= '9'; } + /// Cast an unsigned char to a (possibly signed) char avoiding implementation defined behavior + constexpr char to_char(unsigned char c) + { + return static_cast<char>((c - std::numeric_limits<char>::min()) + std::numeric_limits<char>::min()); + } + }}} // namespace boost::locale::util #endif
\ No newline at end of file diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp b/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp index 631b526161..34b01395bc 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/encoding/codepage.cpp @@ -1,163 +1,235 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include <boost/locale/encoding.hpp> -#include <boost/locale/hold_ptr.hpp> -#include <memory> -#include <string> +#include "boost/locale/util/make_std_unique.hpp" -#include "boost/locale/encoding/conv.hpp" #if BOOST_LOCALE_USE_WIN32_API # define BOOST_LOCALE_WITH_WCONV #endif #ifdef BOOST_LOCALE_WITH_ICONV -# include "boost/locale/encoding/iconv_codepage.ipp" +# include "boost/locale/encoding/iconv_converter.hpp" #endif #ifdef BOOST_LOCALE_WITH_ICU -# include "boost/locale/encoding/uconv_codepage.ipp" +# include "boost/locale/encoding/uconv_converter.hpp" #endif #ifdef BOOST_LOCALE_WITH_WCONV -# include "boost/locale/encoding/wconv_codepage.ipp" +# include "boost/locale/encoding/wconv_converter.hpp" #endif namespace boost { namespace locale { namespace conv { - namespace impl { - std::string convert_between(const char* begin, - const char* end, - const char* to_charset, - const char* from_charset, - method_type how) + std::string between(const char* begin, + const char* end, + const std::string& to_charset, + const std::string& from_charset, + method_type how) + { +#ifdef BOOST_LOCALE_WITH_ICONV + { + impl::iconv_between cvt; + if(cvt.open(to_charset, from_charset, how)) + return cvt.convert(begin, end); + } +#endif +#ifdef BOOST_LOCALE_WITH_ICU { - hold_ptr<converter_between> cvt; + impl::uconv_between cvt; + if(cvt.open(to_charset, from_charset, how)) + return cvt.convert(begin, end); + } +#endif +#ifdef BOOST_LOCALE_WITH_WCONV + { + impl::wconv_between cvt; + if(cvt.open(to_charset, from_charset, how)) + return cvt.convert(begin, end); + } +#endif + throw invalid_charset_error(std::string(to_charset) + " or " + from_charset); + } + + template<typename CharType> + std::basic_string<CharType> to_utf(const char* begin, const char* end, const std::string& charset, method_type how) + { #ifdef BOOST_LOCALE_WITH_ICONV - cvt.reset(new iconv_between()); - if(cvt->open(to_charset, from_charset, how)) - return cvt->convert(begin, end); + { + impl::iconv_to_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } +#endif +#ifdef BOOST_LOCALE_WITH_ICU + { + impl::uconv_to_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } +#endif +#ifdef BOOST_LOCALE_WITH_WCONV + { + impl::wconv_to_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } +#endif + throw invalid_charset_error(charset); + } + + template<typename CharType> + std::string from_utf(const CharType* begin, const CharType* end, const std::string& charset, method_type how) + { +#ifdef BOOST_LOCALE_WITH_ICONV + { + impl::iconv_from_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } #endif #ifdef BOOST_LOCALE_WITH_ICU - cvt.reset(new uconv_between()); - if(cvt->open(to_charset, from_charset, how)) - return cvt->convert(begin, end); + { + impl::uconv_from_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } #endif #ifdef BOOST_LOCALE_WITH_WCONV - cvt.reset(new wconv_between()); - if(cvt->open(to_charset, from_charset, how)) - return cvt->convert(begin, end); + { + impl::wconv_from_utf<CharType> cvt; + if(cvt.open(charset, how)) + return cvt.convert(begin, end); + } #endif - throw invalid_charset_error(std::string(to_charset) + " or " + from_charset); + throw invalid_charset_error(charset); + } + + namespace detail { + template<class T> + static std::unique_ptr<T> move_to_ptr(T& c) + { + return make_std_unique<T>(std::move(c)); } - template<typename CharType> - std::basic_string<CharType> convert_to(const char* begin, const char* end, const char* charset, method_type how) + template<typename Char> + std::unique_ptr<utf_encoder<Char>> + make_utf_encoder(const std::string& charset, method_type how, conv_backend impl) { - hold_ptr<converter_to_utf<CharType>> cvt; #ifdef BOOST_LOCALE_WITH_ICONV - cvt.reset(new iconv_to_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::IConv) { + impl::iconv_to_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif #ifdef BOOST_LOCALE_WITH_ICU - cvt.reset(new uconv_to_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::ICU) { + impl::uconv_to_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif #ifdef BOOST_LOCALE_WITH_WCONV - cvt.reset(new wconv_to_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::WinAPI) { + impl::wconv_to_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif throw invalid_charset_error(charset); } - template<typename CharType> - std::string convert_from(const CharType* begin, const CharType* end, const char* charset, method_type how) + template<typename Char> + std::unique_ptr<utf_decoder<Char>> + make_utf_decoder(const std::string& charset, method_type how, conv_backend impl) { - hold_ptr<converter_from_utf<CharType>> cvt; #ifdef BOOST_LOCALE_WITH_ICONV - cvt.reset(new iconv_from_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::IConv) { + impl::iconv_from_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif #ifdef BOOST_LOCALE_WITH_ICU - cvt.reset(new uconv_from_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::ICU) { + impl::uconv_from_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif #ifdef BOOST_LOCALE_WITH_WCONV - cvt.reset(new wconv_from_utf<CharType>()); - if(cvt->open(charset, how)) - return cvt->convert(begin, end); + if(impl == conv_backend::Default || impl == conv_backend::WinAPI) { + impl::wconv_from_utf<Char> cvt; + if(cvt.open(charset, how)) + return move_to_ptr(cvt); + } #endif throw invalid_charset_error(charset); } - - } // namespace impl - - using namespace impl; - - std::string between(const char* begin, - const char* end, - const std::string& to_charset, - const std::string& from_charset, - method_type how) - { - return convert_between(begin, end, to_charset.c_str(), from_charset.c_str(), how); - } - - template<> - std::basic_string<char> to_utf(const char* begin, const char* end, const std::string& charset, method_type how) - { - return convert_to<char>(begin, end, charset.c_str(), how); - } - - template<> - std::string from_utf(const char* begin, const char* end, const std::string& charset, method_type how) - { - return convert_from<char>(begin, end, charset.c_str(), how); - } - - template<> - std::basic_string<wchar_t> to_utf(const char* begin, const char* end, const std::string& charset, method_type how) - { - return convert_to<wchar_t>(begin, end, charset.c_str(), how); + std::unique_ptr<narrow_converter> make_narrow_converter(const std::string& src_encoding, + const std::string& target_encoding, + method_type how, + conv_backend impl) + { +#ifdef BOOST_LOCALE_WITH_ICONV + if(impl == conv_backend::Default || impl == conv_backend::IConv) { + impl::iconv_between cvt; + if(cvt.open(target_encoding, src_encoding, how)) + return move_to_ptr(cvt); + } +#endif +#ifdef BOOST_LOCALE_WITH_ICU + if(impl == conv_backend::Default || impl == conv_backend::ICU) { + impl::uconv_between cvt; + if(cvt.open(target_encoding, src_encoding, how)) + return move_to_ptr(cvt); + } +#endif +#ifdef BOOST_LOCALE_WITH_WCONV + if(impl == conv_backend::Default || impl == conv_backend::WinAPI) { + impl::wconv_between cvt; + if(cvt.open(target_encoding, src_encoding, how)) + return move_to_ptr(cvt); + } +#endif + throw invalid_charset_error(std::string(src_encoding) + " or " + target_encoding); + } + } // namespace detail + +#define BOOST_LOCALE_INSTANTIATE(CHARTYPE) \ + namespace detail { \ + template class charset_converter<char, CHARTYPE>; \ + template BOOST_LOCALE_DECL std::unique_ptr<utf_encoder<CHARTYPE>> \ + make_utf_encoder(const std::string& charset, method_type how, conv_backend impl); \ + template BOOST_LOCALE_DECL std::unique_ptr<utf_decoder<CHARTYPE>> \ + make_utf_decoder(const std::string& charset, method_type how, conv_backend impl); \ + } \ + template BOOST_LOCALE_DECL std::basic_string<CHARTYPE> to_utf<CHARTYPE>(const char* begin, \ + const char* end, \ + const std::string& charset, \ + method_type how); \ + template BOOST_LOCALE_DECL std::string from_utf<CHARTYPE>(const CHARTYPE* begin, \ + const CHARTYPE* end, \ + const std::string& charset, \ + method_type how) +#define BOOST_LOCALE_INSTANTIATE_NO_CHAR(CHARTYPE) \ + BOOST_LOCALE_INSTANTIATE(CHARTYPE); \ + namespace detail { \ + template class charset_converter<CHARTYPE, char>; \ } - template<> - std::string from_utf(const wchar_t* begin, const wchar_t* end, const std::string& charset, method_type how) - { - return convert_from<wchar_t>(begin, end, charset.c_str(), how); - } + BOOST_LOCALE_INSTANTIATE(char); + BOOST_LOCALE_INSTANTIATE_NO_CHAR(wchar_t); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template<> - std::basic_string<char16_t> to_utf(const char* begin, const char* end, const std::string& charset, method_type how) - { - return convert_to<char16_t>(begin, end, charset.c_str(), how); - } - - template<> - std::string from_utf(const char16_t* begin, const char16_t* end, const std::string& charset, method_type how) - { - return convert_from<char16_t>(begin, end, charset.c_str(), how); - } + BOOST_LOCALE_INSTANTIATE_NO_CHAR(char16_t); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template<> - std::basic_string<char32_t> to_utf(const char* begin, const char* end, const std::string& charset, method_type how) - { - return convert_to<char32_t>(begin, end, charset.c_str(), how); - } - - template<> - std::string from_utf(const char32_t* begin, const char32_t* end, const std::string& charset, method_type how) - { - return convert_from<char32_t>(begin, end, charset.c_str(), how); - } + BOOST_LOCALE_INSTANTIATE_NO_CHAR(char32_t); #endif }}} // namespace boost::locale::conv diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/conv.hpp b/contrib/restricted/boost/locale/src/boost/locale/encoding/conv.hpp deleted file mode 100644 index 6d2ab68cac..0000000000 --- a/contrib/restricted/boost/locale/src/boost/locale/encoding/conv.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_LOCALE_CONV_IMPL_HPP -#define BOOST_LOCALE_CONV_IMPL_HPP - -#include <boost/locale/config.hpp> -#include <boost/locale/encoding.hpp> - -namespace boost { namespace locale { namespace conv { namespace impl { - - template<typename CharType> - const char* utf_name() - { - switch(sizeof(CharType)) { - case 1: return "UTF-8"; - case 2: { - const int16_t endianMark = 1; - const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1; - return isLittleEndian ? "UTF-16LE" : "UTF-16BE"; - } - case 4: { - const int32_t endianMark = 1; - const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1; - return isLittleEndian ? "UTF-32LE" : "UTF-32BE"; - } - } - return "Unknown Character Encoding"; - } - - class converter_between { - public: - typedef char char_type; - typedef std::string string_type; - - virtual bool open(const char* to_charset, const char* from_charset, method_type how) = 0; - - virtual std::string convert(const char* begin, const char* end) = 0; - - virtual ~converter_between() = default; - }; - - template<typename CharType> - class converter_from_utf { - public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; - - virtual bool open(const char* charset, method_type how) = 0; - - virtual std::string convert(const CharType* begin, const CharType* end) = 0; - - virtual ~converter_from_utf() = default; - }; - - template<typename CharType> - class converter_to_utf { - public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; - - virtual bool open(const char* charset, method_type how) = 0; - - virtual string_type convert(const char* begin, const char* end) = 0; - - virtual ~converter_to_utf() = default; - }; -}}}} // namespace boost::locale::conv::impl - -#endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_codepage.ipp b/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_codepage.ipp deleted file mode 100644 index a5f7ab3f00..0000000000 --- a/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_codepage.ipp +++ /dev/null @@ -1,175 +0,0 @@ -// -// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP -#define BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP - -#include <boost/locale/encoding.hpp> -#include "boost/locale/encoding/conv.hpp" -#include "boost/locale/util/iconv.hpp" -#include <cerrno> - -namespace boost { namespace locale { namespace conv { namespace impl { - - class iconverter_base { - public: - iconverter_base() : cvt_((iconv_t)(-1)) {} - ~iconverter_base() { close(); } - - bool do_open(const char* to, const char* from, method_type how) - { - close(); - cvt_ = iconv_open(to, from); - how_ = how; - return cvt_ != (iconv_t)(-1); - } - - template<typename OutChar, typename InChar> - std::basic_string<OutChar> real_convert(const InChar* ubegin, const InChar* uend) - { - std::basic_string<OutChar> sresult; - - sresult.reserve(uend - ubegin); - - OutChar result[64]; - - char* out_start = reinterpret_cast<char*>(&result[0]); - const char* begin = reinterpret_cast<const char*>(ubegin); - const char* end = reinterpret_cast<const char*>(uend); - - enum { normal, unshifting, done } state = normal; - - while(state != done) { - size_t in_left = end - begin; - size_t out_left = sizeof(result); - - char* out_ptr = out_start; - size_t res = 0; - if(in_left == 0) - state = unshifting; - - if(state == normal) - res = conv(&begin, &in_left, &out_ptr, &out_left); - else - res = conv(0, 0, &out_ptr, &out_left); - - int err = errno; - - size_t output_count = (out_ptr - out_start) / sizeof(OutChar); - - if(res != 0 && res != (size_t)(-1)) { - if(how_ == stop) { - throw conversion_error(); - } - } - - sresult.append(&result[0], output_count); - - if(res == (size_t)(-1)) { - if(err == EILSEQ || err == EINVAL) { - if(how_ == stop) { - throw conversion_error(); - } - - if(begin != end) { - begin += sizeof(InChar); - if(begin >= end) - break; - } else { - break; - } - } else if(err == E2BIG) { - continue; - } else { - // We should never get there - // but if we do - if(how_ == stop) - throw conversion_error(); - else - break; - } - } - if(state == unshifting) - state = done; - } - return sresult; - } - - private: - void close() - { - if(cvt_ != (iconv_t)(-1)) { - iconv_close(cvt_); - cvt_ = (iconv_t)(-1); - } - } - - size_t conv(const char** inbuf, size_t* inchar_left, char** outbuf, size_t* outchar_left) - { - return call_iconv(cvt_, inbuf, inchar_left, outbuf, outchar_left); - } - - iconv_t cvt_; - method_type how_; - }; - - template<typename CharType> - class iconv_from_utf : public converter_from_utf<CharType> { - public: - typedef CharType char_type; - - bool open(const char* charset, method_type how) override - { - return self_.do_open(charset, utf_name<CharType>(), how); - } - - std::string convert(const char_type* ubegin, const char_type* uend) override - { - return self_.template real_convert<char, char_type>(ubegin, uend); - } - - private: - iconverter_base self_; - }; - - class iconv_between : public converter_between { - public: - bool open(const char* to_charset, const char* from_charset, method_type how) override - { - return self_.do_open(to_charset, from_charset, how); - } - std::string convert(const char* begin, const char* end) override - { - return self_.real_convert<char, char>(begin, end); - } - - private: - iconverter_base self_; - }; - - template<typename CharType> - class iconv_to_utf : public converter_to_utf<CharType> { - public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; - - bool open(const char* charset, method_type how) override - { - return self_.do_open(utf_name<CharType>(), charset, how); - } - - string_type convert(const char* begin, const char* end) override - { - return self_.template real_convert<char_type, char>(begin, end); - } - - private: - iconverter_base self_; - }; - -}}}} // namespace boost::locale::conv::impl - -#endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp b/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp new file mode 100644 index 0000000000..38a8f485ea --- /dev/null +++ b/contrib/restricted/boost/locale/src/boost/locale/encoding/iconv_converter.hpp @@ -0,0 +1,145 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP +#define BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP + +#include <boost/locale/encoding.hpp> +#include "boost/locale/util/encoding.hpp" +#include "boost/locale/util/iconv.hpp" +#include <cerrno> +#include <string> + +namespace boost { namespace locale { namespace conv { namespace impl { + + class iconverter_base { + public: + bool do_open(const char* to, const char* from, method_type how) + { + cvt_ = iconv_open(to, from); + how_ = how; + return static_cast<bool>(cvt_); + } + + template<typename OutChar, typename InChar> + std::basic_string<OutChar> real_convert(const InChar* ubegin, const InChar* uend) + { + std::basic_string<OutChar> sresult; + + sresult.reserve(uend - ubegin); + + OutChar tmp_buf[64]; + + char* out_start = reinterpret_cast<char*>(tmp_buf); + const char* begin = reinterpret_cast<const char*>(ubegin); + const char* end = reinterpret_cast<const char*>(uend); + + bool is_unshifting = false; + + for(;;) { + size_t in_left = end - begin; + size_t out_left = sizeof(tmp_buf); + char* out_ptr = out_start; + + if(in_left == 0) + is_unshifting = true; + + const size_t res = (!is_unshifting) ? conv(&begin, &in_left, &out_ptr, &out_left) : + conv(nullptr, nullptr, &out_ptr, &out_left); + + if(res != 0 && res != (size_t)(-1)) { + if(how_ == stop) + throw conversion_error(); + } + + const size_t output_count = (out_ptr - out_start) / sizeof(OutChar); + sresult.append(tmp_buf, output_count); + + if(res == (size_t)(-1)) { + const int err = errno; + if(err == EILSEQ || err == EINVAL) { + if(how_ == stop) + throw conversion_error(); + + if(begin != end) { + begin += sizeof(InChar); + if(begin >= end) + break; + } else + break; + } else if(err == E2BIG) + continue; + else // Invalid error code, shouldn't ever happen or iconv has a bug + throw conversion_error(); // LCOV_EXCL_LINE + } + if(is_unshifting) + break; + } + return sresult; + } + + private: + size_t conv(const char** inbuf, size_t* inchar_left, char** outbuf, size_t* outchar_left) + { + return call_iconv(cvt_, inbuf, inchar_left, outbuf, outchar_left); + } + + iconv_handle cvt_; + method_type how_; + }; + + template<typename CharType> + class iconv_from_utf final : public detail::utf_decoder<CharType> { + public: + bool open(const std::string& charset, method_type how) + { + return self_.do_open(charset.c_str(), util::utf_name<CharType>(), how); + } + + std::string convert(const CharType* ubegin, const CharType* uend) override + { + return self_.template real_convert<char>(ubegin, uend); + } + + private: + iconverter_base self_; + }; + + class iconv_between final : public detail::narrow_converter { + public: + bool open(const std::string& to_charset, const std::string& from_charset, method_type how) + { + return self_.do_open(to_charset.c_str(), from_charset.c_str(), how); + } + std::string convert(const char* begin, const char* end) override + { + return self_.real_convert<char, char>(begin, end); + } + + private: + iconverter_base self_; + }; + + template<typename CharType> + class iconv_to_utf final : public detail::utf_encoder<CharType> { + public: + bool open(const std::string& charset, method_type how) + { + return self_.do_open(util::utf_name<CharType>(), charset.c_str(), how); + } + + std::basic_string<CharType> convert(const char* begin, const char* end) override + { + return self_.template real_convert<CharType>(begin, end); + } + + private: + iconverter_base self_; + }; + +}}}} // namespace boost::locale::conv::impl + +#endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_codepage.ipp b/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_converter.hpp index 1c2b7ed73b..53a1405532 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_codepage.ipp +++ b/contrib/restricted/boost/locale/src/boost/locale/encoding/uconv_converter.hpp @@ -8,7 +8,6 @@ #define BOOST_LOCALE_IMPL_UCONV_CODEPAGE_HPP #include <boost/locale/encoding.hpp> #include <boost/locale/hold_ptr.hpp> -#include "boost/locale/encoding/conv.hpp" #include "boost/locale/icu/icu_util.hpp" #include "boost/locale/icu/uconv.hpp" #include <unicode/ucnv.h> @@ -16,32 +15,23 @@ namespace boost { namespace locale { namespace conv { namespace impl { template<typename CharType> - class uconv_to_utf : public converter_to_utf<CharType> { + class uconv_to_utf final : public detail::utf_encoder<CharType> { public: - typedef CharType char_type; - - typedef std::basic_string<char_type> string_type; - - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { - close(); try { using impl_icu::cpcvt_type; cvt_from_.reset(new from_type(charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop)); cvt_to_.reset(new to_type("UTF-8", how == skip ? cpcvt_type::skip : cpcvt_type::stop)); } catch(const std::exception& /*e*/) { - close(); + cvt_from_.reset(); + cvt_to_.reset(); return false; } return true; } - void close() - { - cvt_from_.reset(); - cvt_to_.reset(); - } - string_type convert(const char* begin, const char* end) override + std::basic_string<CharType> convert(const char* begin, const char* end) override { try { return cvt_to_->std(cvt_from_->icu_checked(begin, end)); @@ -59,27 +49,21 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<typename CharType> - class uconv_from_utf : public converter_from_utf<CharType> { + class uconv_from_utf final : public detail::utf_decoder<CharType> { public: - typedef CharType char_type; - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { - close(); try { using impl_icu::cpcvt_type; cvt_from_.reset(new from_type("UTF-8", how == skip ? cpcvt_type::skip : cpcvt_type::stop)); cvt_to_.reset(new to_type(charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop)); } catch(const std::exception& /*e*/) { - close(); + cvt_from_.reset(); + cvt_to_.reset(); return false; } return true; } - void close() - { - cvt_from_.reset(); - cvt_to_.reset(); - } std::string convert(const CharType* begin, const CharType* end) override { @@ -98,26 +82,21 @@ namespace boost { namespace locale { namespace conv { namespace impl { hold_ptr<to_type> cvt_to_; }; - class uconv_between : public converter_between { + class uconv_between final : public detail::narrow_converter { public: - bool open(const char* to_charset, const char* from_charset, method_type how) override + bool open(const std::string& to_charset, const std::string& from_charset, method_type how) { - close(); try { using impl_icu::cpcvt_type; cvt_from_.reset(new from_type(from_charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop)); cvt_to_.reset(new to_type(to_charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop)); } catch(const std::exception& /*e*/) { - close(); + cvt_from_.reset(); + cvt_to_.reset(); return false; } return true; } - void close() - { - cvt_from_.reset(); - cvt_to_.reset(); - } std::string convert(const char* begin, const char* end) override { diff --git a/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_codepage.ipp b/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_converter.hpp index bf97fd5070..1a0325565e 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_codepage.ipp +++ b/contrib/restricted/boost/locale/src/boost/locale/encoding/wconv_converter.hpp @@ -11,7 +11,6 @@ # define NOMINMAX #endif #include <boost/locale/encoding.hpp> -#include "boost/locale/encoding/conv.hpp" #include "boost/locale/util/encoding.hpp" #include <algorithm> #include <cstddef> @@ -23,21 +22,6 @@ namespace boost { namespace locale { namespace conv { namespace impl { - size_t remove_substitutions(std::vector<char>& v) - { - if(std::find(v.begin(), v.end(), 0) == v.end()) { - return v.size(); - } - std::vector<char> v2; - v2.reserve(v.size()); - for(unsigned i = 0; i < v.size(); i++) { - if(v[i] != 0) - v2.push_back(v[i]); - } - v.swap(v2); - return v.size(); - } - void multibyte_to_wide_one_by_one(int codepage, const char* begin, const char* end, std::vector<wchar_t>& buf) { buf.reserve(end - begin); @@ -82,7 +66,7 @@ namespace boost { namespace locale { namespace conv { namespace impl { } buf.resize(n); - if(MultiByteToWideChar(codepage, flags, begin, static_cast<int>(num_chars), &buf.front(), n) == 0) + if(MultiByteToWideChar(codepage, flags, begin, static_cast<int>(num_chars), buf.data(), n) == 0) throw conversion_error(); } @@ -92,33 +76,31 @@ namespace boost { namespace locale { namespace conv { namespace impl { bool do_skip, std::vector<char>& buf) { + buf.clear(); if(begin == end) return; BOOL substitute = FALSE; - BOOL* substitute_ptr = codepage == 65001 || codepage == 65000 ? 0 : &substitute; + BOOL* substitute_ptr = (codepage == CP_UTF7 || codepage == CP_UTF8) ? nullptr : &substitute; char subst_char = 0; - char* subst_char_ptr = codepage == 65001 || codepage == 65000 ? 0 : &subst_char; + char* subst_char_ptr = (codepage == CP_UTF7 || codepage == CP_UTF8) ? nullptr : &subst_char; - const std::ptrdiff_t num_chars = end - begin; - if(num_chars > std::numeric_limits<int>::max()) + if((end - begin) > std::numeric_limits<int>::max()) throw conversion_error(); - int n = - WideCharToMultiByte(codepage, 0, begin, static_cast<int>(num_chars), 0, 0, subst_char_ptr, substitute_ptr); + const int num_chars = static_cast<int>(end - begin); + int n = WideCharToMultiByte(codepage, 0, begin, num_chars, nullptr, 0, subst_char_ptr, substitute_ptr); + // Some codepages don't support substitutions + if(n == 0 && GetLastError() == ERROR_INVALID_PARAMETER) { + subst_char_ptr = nullptr; + substitute_ptr = nullptr; + n = WideCharToMultiByte(codepage, 0, begin, num_chars, nullptr, 0, subst_char_ptr, substitute_ptr); + } buf.resize(n); - if(WideCharToMultiByte(codepage, - 0, - begin, - static_cast<int>(num_chars), - &buf[0], - n, - subst_char_ptr, - substitute_ptr) - == 0) + if(WideCharToMultiByte(codepage, 0, begin, num_chars, buf.data(), n, subst_char_ptr, substitute_ptr) == 0) throw conversion_error(); if(substitute) { if(do_skip) - remove_substitutions(buf); + buf.erase(std::remove(buf.begin(), buf.end(), subst_char), buf.end()); else throw conversion_error(); } @@ -131,18 +113,17 @@ namespace boost { namespace locale { namespace conv { namespace impl { buf.reserve(end - begin); const wchar_t* e = std::find(begin, end, L'\0'); const wchar_t* b = begin; + std::vector<char> tmp; for(;;) { - std::vector<char> tmp; wide_to_multibyte_non_zero(codepage, b, e, do_skip, tmp); - size_t osize = buf.size(); + const size_t osize = buf.size(); buf.resize(osize + tmp.size()); std::copy(tmp.begin(), tmp.end(), buf.begin() + osize); - if(e != end) { - buf.push_back('\0'); - b = e + 1; - e = std::find(b, end, L'0'); - } else + if(e == end) break; + buf.push_back('\0'); + b = e + 1; + e = std::find(b, end, L'0'); } } @@ -152,7 +133,7 @@ namespace boost { namespace locale { namespace conv { namespace impl { const CharType* begin = str; const CharType* end = str + len; while(begin != end) { - utf::code_point c = utf::utf_traits<CharType, 2>::template decode<const CharType*>(begin, end); + utf::code_point c = utf::utf_traits<CharType, 2>::decode(begin, end); if(c == utf::illegal || c == utf::incomplete) return false; } @@ -182,10 +163,10 @@ namespace boost { namespace locale { namespace conv { namespace impl { } } - class wconv_between : public converter_between { + class wconv_between final : public detail::narrow_converter { public: wconv_between() : how_(skip), to_code_page_(-1), from_code_page_(-1) {} - bool open(const char* to_charset, const char* from_charset, method_type how) override + bool open(const std::string& to_charset, const std::string& from_charset, method_type how) { how_ = how; to_code_page_ = util::encoding_to_windows_codepage(to_charset); @@ -196,17 +177,17 @@ namespace boost { namespace locale { namespace conv { namespace impl { } std::string convert(const char* begin, const char* end) override { - if(to_code_page_ == 65001 && from_code_page_ == 65001) + if(to_code_page_ == CP_UTF8 && from_code_page_ == CP_UTF8) return utf_to_utf<char>(begin, end, how_); std::string res; std::vector<wchar_t> tmp; // buffer for mb2w std::wstring tmps; // buffer for utf_to_utf - const wchar_t* wbegin = 0; - const wchar_t* wend = 0; + const wchar_t* wbegin = nullptr; + const wchar_t* wend = nullptr; - if(from_code_page_ == 65001) { + if(from_code_page_ == CP_UTF8) { tmps = utf_to_utf<wchar_t>(begin, end, how_); if(tmps.empty()) return res; @@ -216,19 +197,18 @@ namespace boost { namespace locale { namespace conv { namespace impl { multibyte_to_wide(from_code_page_, begin, end, how_ == skip, tmp); if(tmp.empty()) return res; - wbegin = &tmp[0]; + wbegin = tmp.data(); wend = wbegin + tmp.size(); } - if(to_code_page_ == 65001) { + if(to_code_page_ == CP_UTF8) return utf_to_utf<char>(wbegin, wend, how_); - } std::vector<char> ctmp; wide_to_multibyte(to_code_page_, wbegin, wend, how_ == skip, ctmp); if(ctmp.empty()) return res; - res.assign(&ctmp.front(), ctmp.size()); + res.assign(ctmp.data(), ctmp.size()); return res; } @@ -245,9 +225,9 @@ namespace boost { namespace locale { namespace conv { namespace impl { class wconv_from_utf; template<> - class wconv_to_utf<char, 1> : public converter_to_utf<char> { + class wconv_to_utf<char, 1> final : public detail::utf_encoder<char> { public: - bool open(const char* cs, method_type how) override { return cvt.open("UTF-8", cs, how); } + bool open(const std::string& cs, method_type how) { return cvt.open("UTF-8", cs, how); } std::string convert(const char* begin, const char* end) override { return cvt.convert(begin, end); } private: @@ -255,9 +235,9 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<> - class wconv_from_utf<char, 1> : public converter_from_utf<char> { + class wconv_from_utf<char, 1> final : public detail::utf_decoder<char> { public: - bool open(const char* cs, method_type how) override { return cvt.open(cs, "UTF-8", how); } + bool open(const std::string& cs, method_type how) { return cvt.open(cs, "UTF-8", how); } std::string convert(const char* begin, const char* end) override { return cvt.convert(begin, end); } private: @@ -265,15 +245,13 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<typename CharType> - class wconv_to_utf<CharType, 2> : public converter_to_utf<CharType> { + class wconv_to_utf<CharType, 2> final : public detail::utf_encoder<CharType> { public: - typedef CharType char_type; - - typedef std::basic_string<char_type> string_type; + using string_type = std::basic_string<CharType>; wconv_to_utf() : how_(skip), code_page_(-1) {} - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { how_ = how; code_page_ = util::encoding_to_windows_codepage(charset); @@ -282,14 +260,15 @@ namespace boost { namespace locale { namespace conv { namespace impl { string_type convert(const char* begin, const char* end) override { - if(code_page_ == 65001) { - return utf_to_utf<char_type>(begin, end, how_); - } + if(code_page_ == CP_UTF8) + return utf_to_utf<CharType>(begin, end, how_); std::vector<wchar_t> tmp; multibyte_to_wide(code_page_, begin, end, how_ == skip, tmp); string_type res; - if(!tmp.empty()) - res.assign(reinterpret_cast<char_type*>(&tmp.front()), tmp.size()); + if(!tmp.empty()) { + static_assert(sizeof(CharType) == sizeof(wchar_t), "Cast not possible"); + res.assign(reinterpret_cast<CharType*>(tmp.data()), tmp.size()); + } return res; } @@ -299,15 +278,11 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<typename CharType> - class wconv_from_utf<CharType, 2> : public converter_from_utf<CharType> { + class wconv_from_utf<CharType, 2> final : public detail::utf_decoder<CharType> { public: - typedef CharType char_type; - - typedef std::basic_string<char_type> string_type; - wconv_from_utf() : how_(skip), code_page_(-1) {} - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { how_ = how; code_page_ = util::encoding_to_windows_codepage(charset); @@ -316,24 +291,24 @@ namespace boost { namespace locale { namespace conv { namespace impl { std::string convert(const CharType* begin, const CharType* end) override { - if(code_page_ == 65001) { + if(code_page_ == CP_UTF8) return utf_to_utf<char>(begin, end, how_); - } - const wchar_t* wbegin = 0; - const wchar_t* wend = 0; + const wchar_t* wbegin; + const wchar_t* wend; std::vector<wchar_t> buffer; // if needed - if(begin == end) - return std::string(); if(validate_utf16(begin, end - begin)) { + static_assert(sizeof(CharType) == sizeof(wchar_t), "Cast not possible"); wbegin = reinterpret_cast<const wchar_t*>(begin); wend = reinterpret_cast<const wchar_t*>(end); } else { - if(how_ == stop) { + if(how_ == stop) throw conversion_error(); - } else { + else { clean_invalid_utf16(begin, end - begin, buffer); - if(!buffer.empty()) { - wbegin = &buffer[0]; + if(buffer.empty()) + wbegin = wend = nullptr; + else { + wbegin = buffer.data(); wend = wbegin + buffer.size(); } } @@ -345,7 +320,7 @@ namespace boost { namespace locale { namespace conv { namespace impl { wide_to_multibyte(code_page_, wbegin, wend, how_ == skip, ctmp); if(ctmp.empty()) return res; - res.assign(&ctmp.front(), ctmp.size()); + res.assign(ctmp.data(), ctmp.size()); return res; } @@ -355,15 +330,13 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<typename CharType> - class wconv_to_utf<CharType, 4> : public converter_to_utf<CharType> { + class wconv_to_utf<CharType, 4> final : public detail::utf_encoder<CharType> { public: - typedef CharType char_type; - - typedef std::basic_string<char_type> string_type; + using string_type = std::basic_string<CharType>; wconv_to_utf() : how_(skip), code_page_(-1) {} - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { how_ = how; code_page_ = util::encoding_to_windows_codepage(charset); @@ -372,16 +345,15 @@ namespace boost { namespace locale { namespace conv { namespace impl { string_type convert(const char* begin, const char* end) override { - if(code_page_ == 65001) { - return utf_to_utf<char_type>(begin, end, how_); - } + if(code_page_ == CP_UTF8) + return utf_to_utf<CharType>(begin, end, how_); std::vector<wchar_t> buf; multibyte_to_wide(code_page_, begin, end, how_ == skip, buf); if(buf.empty()) return string_type(); - return utf_to_utf<CharType>(&buf[0], &buf[0] + buf.size(), how_); + return utf_to_utf<CharType>(buf.data(), buf.data() + buf.size(), how_); } private: @@ -390,15 +362,11 @@ namespace boost { namespace locale { namespace conv { namespace impl { }; template<typename CharType> - class wconv_from_utf<CharType, 4> : public converter_from_utf<CharType> { + class wconv_from_utf<CharType, 4> final : public detail::utf_decoder<CharType> { public: - typedef CharType char_type; - - typedef std::basic_string<char_type> string_type; - wconv_from_utf() : how_(skip), code_page_(-1) {} - bool open(const char* charset, method_type how) override + bool open(const std::string& charset, method_type how) { how_ = how; code_page_ = util::encoding_to_windows_codepage(charset); @@ -407,9 +375,8 @@ namespace boost { namespace locale { namespace conv { namespace impl { std::string convert(const CharType* begin, const CharType* end) override { - if(code_page_ == 65001) { + if(code_page_ == CP_UTF8) return utf_to_utf<char>(begin, end, how_); - } std::wstring tmp = utf_to_utf<wchar_t>(begin, end, how_); std::vector<char> ctmp; @@ -417,7 +384,7 @@ namespace boost { namespace locale { namespace conv { namespace impl { std::string res; if(ctmp.empty()) return res; - res.assign(&ctmp.front(), ctmp.size()); + res.assign(ctmp.data(), ctmp.size()); return res; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp index a992048f75..a26dfc98cf 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/boundary.cpp @@ -7,12 +7,12 @@ #include <boost/locale/boundary.hpp> #include <boost/locale/generator.hpp> -#include "boost/locale//util/encoding.hpp" #include "boost/locale/icu/all_generator.hpp" #include "boost/locale/icu/cdata.hpp" #include "boost/locale/icu/icu_util.hpp" #include "boost/locale/icu/uconv.hpp" -#if BOOST_LOCALE_ICU_VERSION >= 306 +#include "boost/locale/util/encoding.hpp" +#if BOOST_LOCALE_ICU_VERSION >= 5502 # include <unicode/utext.h> #endif #include <memory> @@ -25,6 +25,16 @@ # pragma warning(disable : 4267) // 'argument' : conversion from 'size_t' #endif +#if BOOST_LOCALE_ICU_VERSION >= 5502 +namespace std { +template<> +struct default_delete<UText> { + using pointer = UText*; + void operator()(pointer ptr) { utext_close(ptr); } +}; +} // namespace std +#endif + namespace boost { namespace locale { namespace boundary { namespace impl_icu { @@ -45,12 +55,8 @@ namespace boost { namespace locale { int pos = 0; while((pos = it->next()) != icu::BreakIterator::DONE) { indx.push_back(break_info(pos)); - /// Character does not have any specific break types + // Character does not have any specific break types if(t != character && rbbi) { - // - // There is a collapse for MSVC: int32_t defined by both boost::cstdint and icu... - // So need to pick one ;( - // std::vector<int32_t> buffer; int32_t membuf[8] = {0}; // try not to use memory allocation if possible int32_t* buf = membuf; @@ -59,8 +65,8 @@ namespace boost { namespace locale { int n = rbbi->getRuleStatusVec(buf, 8, err); if(err == U_BUFFER_OVERFLOW_ERROR) { - buf = &buffer.front(); buffer.resize(n, 0); + buf = buffer.data(); n = rbbi->getRuleStatusVec(buf, buffer.size(), err); } @@ -97,9 +103,8 @@ namespace boost { namespace locale { case character: BOOST_UNREACHABLE_RETURN(0); } } - } else { - indx.back().rule |= character_any; // Baisc mark... for character - } + } else + indx.back().rule |= character_any; // Basic mark... for character } return indx; } @@ -127,52 +132,45 @@ namespace boost { namespace locale { const icu::Locale& loc, const std::string& encoding) { - index_type indx; std::unique_ptr<icu::BreakIterator> bi = get_iterator(t, loc); - -#if BOOST_LOCALE_ICU_VERSION >= 306 + // Versions prior to ICU 55.2 returned wrong splits when used with UText input +#if BOOST_LOCALE_ICU_VERSION >= 5502 UErrorCode err = U_ZERO_ERROR; BOOST_LOCALE_START_CONST_CONDITION if(sizeof(CharType) == 2 || (sizeof(CharType) == 1 && util::normalize_encoding(encoding) == "utf8")) { - UText* ut = 0; - try { - if(sizeof(CharType) == 1) - ut = utext_openUTF8(0, reinterpret_cast<const char*>(begin), end - begin, &err); - else // sizeof(CharType)==2 - ut = utext_openUChars(0, reinterpret_cast<const UChar*>(begin), end - begin, &err); - BOOST_LOCALE_END_CONST_CONDITION - - check_and_throw_icu_error(err); - err = U_ZERO_ERROR; - if(!ut) - throw std::runtime_error("Failed to create UText"); - bi->setText(ut, err); - check_and_throw_icu_error(err); - index_type res = map_direct(t, bi.get(), end - begin); - indx.swap(res); - } catch(...) { - if(ut) - utext_close(ut); - throw; + UText ut_stack = UTEXT_INITIALIZER; + std::unique_ptr<UText> ut; + if(sizeof(CharType) == 1) + ut.reset(utext_openUTF8(&ut_stack, reinterpret_cast<const char*>(begin), end - begin, &err)); + else { + static_assert(sizeof(UChar) == 2, "!"); + ut.reset(utext_openUChars(&ut_stack, reinterpret_cast<const UChar*>(begin), end - begin, &err)); } - if(ut) - utext_close(ut); + BOOST_LOCALE_END_CONST_CONDITION + + check_and_throw_icu_error(err); + err = U_ZERO_ERROR; + if(!ut) + throw std::runtime_error("Failed to create UText"); + bi->setText(ut.get(), err); + check_and_throw_icu_error(err); + return map_direct(t, bi.get(), end - begin); } else #endif { icu_std_converter<CharType> cvt(encoding); - icu::UnicodeString str = cvt.icu(begin, end); + const icu::UnicodeString str = cvt.icu(begin, end); bi->setText(str); - index_type indirect = map_direct(t, bi.get(), str.length()); - indx = indirect; + const index_type indirect = map_direct(t, bi.get(), str.length()); + index_type indx = indirect; for(size_t i = 1; i < indirect.size(); i++) { - size_t offset_inderect = indirect[i - 1].offset; - size_t diff = indirect[i].offset - offset_inderect; - size_t offset_direct = indx[i - 1].offset; - indx[i].offset = offset_direct + cvt.cut(str, begin, end, diff, offset_inderect, offset_direct); + const size_t offset_indirect = indirect[i - 1].offset; + const size_t diff = indirect[i].offset - offset_indirect; + const size_t offset_direct = indx[i - 1].offset; + indx[i].offset = offset_direct + cvt.cut(str, begin, end, diff, offset_indirect, offset_direct); } + return indx; } - return indx; } // do_map template<typename CharType> diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp index b62a542fb0..9e7de6db21 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/codecvt.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -9,11 +10,11 @@ #include <boost/locale/encoding_errors.hpp> #include <boost/locale/hold_ptr.hpp> #include <boost/locale/util.hpp> -#include "boost/locale/encoding/conv.hpp" #include "boost/locale/icu/all_generator.hpp" #include "boost/locale/icu/icu_util.hpp" #include "boost/locale/icu/uconv.hpp" #include "boost/locale/util/encoding.hpp" +#include "boost/locale/util/make_std_unique.hpp" #include <unicode/ucnv.h> #include <unicode/ucnv_err.h> @@ -24,49 +25,28 @@ namespace boost { namespace locale { namespace impl_icu { class uconv_converter : public util::base_converter { public: - uconv_converter(const std::string& encoding) : encoding_(encoding) - { - UErrorCode err = U_ZERO_ERROR; - - // No need to check err each time, this - // is how ICU works. - cvt_ = ucnv_open(encoding.c_str(), &err); - ucnv_setFromUCallBack(cvt_, UCNV_FROM_U_CALLBACK_STOP, 0, 0, 0, &err); - ucnv_setToUCallBack(cvt_, UCNV_TO_U_CALLBACK_STOP, 0, 0, 0, &err); - - if(!cvt_ || U_FAILURE(err)) { - if(cvt_) - ucnv_close(cvt_); - throw conv::invalid_charset_error(encoding); - } - - max_len_ = ucnv_getMaxCharSize(cvt_); - } - - ~uconv_converter() { ucnv_close(cvt_); } + uconv_converter(const std::string& encoding) : encoding_(encoding), cvt_(encoding, cpcvt_type::stop) {} bool is_thread_safe() const override { return false; } uconv_converter* clone() const override { return new uconv_converter(encoding_); } - uint32_t to_unicode(const char*& begin, const char* end) override + utf::code_point to_unicode(const char*& begin, const char* end) override { UErrorCode err = U_ZERO_ERROR; const char* tmp = begin; - UChar32 c = ucnv_getNextUChar(cvt_, &tmp, end, &err); - ucnv_reset(cvt_); - if(err == U_TRUNCATED_CHAR_FOUND) { + const UChar32 c = ucnv_getNextUChar(cvt_.cvt(), &tmp, end, &err); + ucnv_reset(cvt_.cvt()); + if(err == U_TRUNCATED_CHAR_FOUND) return incomplete; - } - if(U_FAILURE(err)) { + if(U_FAILURE(err)) return illegal; - } begin = tmp; return c; } - uint32_t from_unicode(uint32_t u, char* begin, const char* end) override + utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end) override { UChar code_point[2] = {0}; int len; @@ -82,8 +62,8 @@ namespace boost { namespace locale { namespace impl_icu { len = 2; } UErrorCode err = U_ZERO_ERROR; - int olen = ucnv_fromUChars(cvt_, begin, end - begin, code_point, len, &err); - ucnv_reset(cvt_); + const auto olen = ucnv_fromUChars(cvt_.cvt(), begin, end - begin, code_point, len, &err); + ucnv_reset(cvt_.cvt()); if(err == U_BUFFER_OVERFLOW_ERROR) return incomplete; if(U_FAILURE(err)) @@ -91,18 +71,17 @@ namespace boost { namespace locale { namespace impl_icu { return olen; } - int max_len() const override { return max_len_; } + int max_len() const override { return cvt_.max_char_size(); } private: std::string encoding_; - UConverter* cvt_; - int max_len_; + uconv cvt_; }; std::unique_ptr<util::base_converter> create_uconv_converter(const std::string& encoding) { try { - return std::unique_ptr<util::base_converter>(new uconv_converter(encoding)); + return make_std_unique<uconv_converter>(encoding); } catch(const std::exception& /*e*/) { return nullptr; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp index c199ba9312..8a20950cb7 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/collator.cpp @@ -102,10 +102,10 @@ namespace boost { namespace locale { namespace impl_icu { std::vector<uint8_t> tmp; tmp.resize(str.length() + 1u); icu::Collator* collate = get_collator(level); - const int len = collate->getSortKey(str, &tmp[0], tmp.size()); + const int len = collate->getSortKey(str, tmp.data(), tmp.size()); if(len > int(tmp.size())) { tmp.resize(len); - collate->getSortKey(str, &tmp[0], tmp.size()); + collate->getSortKey(str, tmp.data(), tmp.size()); } else tmp.resize(len); return tmp; @@ -121,7 +121,7 @@ namespace boost { namespace locale { namespace impl_icu { { std::vector<uint8_t> tmp = do_basic_transform(level, b, e); tmp.push_back(0); - return gnu_gettext::pj_winberger_hash_function(reinterpret_cast<char*>(&tmp.front())); + return gnu_gettext::pj_winberger_hash_function(reinterpret_cast<char*>(tmp.data())); } collate_impl(const cdata& d) : cvt_(d.encoding), locale_(d.locale), is_utf8_(d.utf8) {} diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp index 89609c127d..9f45db5cc1 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/conversion.cpp @@ -44,23 +44,22 @@ namespace boost { namespace locale { namespace impl_icu { template<typename CharType> class converter_impl : public converter<CharType> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; converter_impl(const cdata& d) : locale_(d.locale), encoding_(d.encoding) {} string_type convert(converter_base::conversion_type how, - const char_type* begin, - const char_type* end, + const CharType* begin, + const CharType* end, int flags = 0) const override { - icu_std_converter<char_type> cvt(encoding_); + icu_std_converter<CharType> cvt(encoding_); icu::UnicodeString str = cvt.icu(begin, end); switch(how) { case converter_base::normalization: normalize_string(str, flags); break; case converter_base::upper_case: str.toUpper(locale_); break; case converter_base::lower_case: str.toLower(locale_); break; - case converter_base::title_case: str.toTitle(0, locale_); break; + case converter_base::title_case: str.toTitle(nullptr, locale_); break; case converter_base::case_folding: str.foldCase(); break; } return cvt.std(str); @@ -85,7 +84,7 @@ namespace boost { namespace locale { namespace impl_icu { raii_casemap(const raii_casemap&) = delete; void operator=(const raii_casemap&) = delete; - raii_casemap(const std::string& locale_id) : map_(0) + raii_casemap(const std::string& locale_id) : map_(nullptr) { UErrorCode err = U_ZERO_ERROR; map_ = ucasemap_open(locale_id.c_str(), 0, &err); @@ -105,7 +104,7 @@ namespace boost { namespace locale { namespace impl_icu { std::vector<char> buf(max_converted_size); UErrorCode err = U_ZERO_ERROR; auto size = func(map_, - &buf.front(), + buf.data(), static_cast<size_type>(buf.size()), begin, static_cast<size_type>(end - begin), @@ -114,14 +113,14 @@ namespace boost { namespace locale { namespace impl_icu { err = U_ZERO_ERROR; buf.resize(size + 1); size = func(map_, - &buf.front(), + buf.data(), static_cast<size_type>(buf.size()), begin, static_cast<size_type>(end - begin), &err); } check_and_throw_icu_error(err); - return std::string(&buf.front(), size); + return std::string(buf.data(), size); } ~raii_casemap() { ucasemap_close(map_); } diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp index 450e7eadfa..c488390ad9 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/date_time.cpp @@ -25,9 +25,8 @@ namespace boost { namespace locale { namespace impl_icu { static void check_and_throw_dt(UErrorCode& e) { - if(U_FAILURE(e)) { + if(U_FAILURE(e)) throw date_time_error(u_errorName(e)); - } } using period::marks::period_mark; @@ -55,7 +54,7 @@ namespace boost { namespace locale { namespace impl_icu { case first_day_of_week: case invalid: break; } - throw std::invalid_argument("Invalid date_time period type"); + throw std::invalid_argument("Invalid date_time period type"); // LCOV_EXCL_LINE } class calendar_impl : public abstract_calendar { @@ -95,16 +94,16 @@ namespace boost { namespace locale { namespace impl_icu { guard l(lock_); v = calendar_->getFirstDayOfWeek(err); } else { - UCalendarDateFields uper = to_icu(p); + UCalendarDateFields field = to_icu(p); guard l(lock_); switch(type) { - case absolute_minimum: v = calendar_->getMinimum(uper); break; - case actual_minimum: v = calendar_->getActualMinimum(uper, err); break; - case greatest_minimum: v = calendar_->getGreatestMinimum(uper); break; - case current: v = calendar_->get(uper, err); break; - case least_maximum: v = calendar_->getLeastMaximum(uper); break; - case actual_maximum: v = calendar_->getActualMaximum(uper, err); break; - case absolute_maximum: v = calendar_->getMaximum(uper); break; + case absolute_minimum: v = calendar_->getMinimum(field); break; + case actual_minimum: v = calendar_->getActualMinimum(field, err); break; + case greatest_minimum: v = calendar_->getGreatestMinimum(field); break; + case current: v = calendar_->get(field, err); break; + case least_maximum: v = calendar_->getLeastMaximum(field); break; + case actual_maximum: v = calendar_->getActualMaximum(field, err); break; + case absolute_maximum: v = calendar_->getMaximum(field); break; } } check_and_throw_dt(err); @@ -153,11 +152,12 @@ namespace boost { namespace locale { namespace impl_icu { case is_gregorian: throw date_time_error("is_gregorian is not settable options for calendar"); case is_dst: throw date_time_error("is_dst is not settable options for calendar"); } + throw std::invalid_argument("Invalid option type"); // LCOV_EXCL_LINE } int get_option(calendar_option_type opt) const override { switch(opt) { - case is_gregorian: return icu_cast<const icu::GregorianCalendar>(calendar_.get()) != 0; + case is_gregorian: return icu_cast<const icu::GregorianCalendar>(calendar_.get()) != nullptr; case is_dst: { guard l(lock_); UErrorCode err = U_ZERO_ERROR; @@ -166,7 +166,7 @@ namespace boost { namespace locale { namespace impl_icu { return res; } } - return 0; + throw std::invalid_argument("Invalid option type"); // LCOV_EXCL_LINE } void adjust_value(period::marks::period_mark p, update_type u, int difference) override { @@ -179,15 +179,18 @@ namespace boost { namespace locale { namespace impl_icu { } int difference(const abstract_calendar& other, period::marks::period_mark m) const override { - UErrorCode err = U_ZERO_ERROR; + // era can't be queried via fieldDifference + if(BOOST_UNLIKELY(m == period::marks::era)) + return get_value(m, value_type::current) - other.get_value(m, value_type::current); + const double other_time_ms = other.get_time_ms(); // fieldDifference has side effect of moving calendar (WTF?) // So we clone it for performing this operation hold_ptr<icu::Calendar> self(calendar_->clone()); - int diff = self->fieldDifference(other_time_ms, to_icu(m), err); - + UErrorCode err = U_ZERO_ERROR; + const int diff = self->fieldDifference(other_time_ms, to_icu(m), err); check_and_throw_dt(err); return diff; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp index 6167852bb6..89763d39ba 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -// Copyright (c) 2021-2022 Alexander Grund +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -12,8 +12,13 @@ #include "boost/locale/icu/icu_util.hpp" #include "boost/locale/icu/time_zone.hpp" #include "boost/locale/icu/uconv.hpp" +#include "boost/locale/util/foreach_char.hpp" #include <limits> #include <memory> +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface... +#endif #include <unicode/datefmt.h> #include <unicode/decimfmt.h> #include <unicode/numfmt.h> @@ -21,6 +26,7 @@ #include <unicode/smpdtfmt.h> #ifdef BOOST_MSVC +# pragma warning(pop) # pragma warning(disable : 4244) // lose data #endif @@ -36,18 +42,16 @@ namespace boost { namespace locale { namespace impl_icu { precision += nf.getMaximumIntegerDigits(); #endif nf.setMaximumFractionDigits(precision); - if(how == std::ios_base::scientific || how == std::ios_base::fixed) { + if(how == std::ios_base::scientific || how == std::ios_base::fixed) nf.setMinimumFractionDigits(precision); - } else { + else nf.setMinimumFractionDigits(0); - } } } // namespace template<typename CharType> class number_format : public formatter<CharType> { public: - typedef CharType char_type; typedef std::basic_string<CharType> string_type; number_format(icu::NumberFormat& fmt, std::string codepage) : cvt_(codepage), icu_fmt_(fmt) {} @@ -123,7 +127,6 @@ namespace boost { namespace locale { namespace impl_icu { template<typename CharType> class date_format : public formatter<CharType> { public: - typedef CharType char_type; typedef std::basic_string<CharType> string_type; string_type format(double value, size_t& code_points) const override { return do_format(value, code_points); } @@ -171,7 +174,7 @@ namespace boost { namespace locale { namespace impl_icu { string_type do_format(double value, size_t& codepoints) const { - UDate date = value * 1000.0; /// UDate is time_t in milliseconds + UDate date = value * 1000.0; // UDate is time_t in milliseconds icu::UnicodeString tmp; icu_fmt_.format(date, tmp); codepoints = tmp.countChar32(); @@ -270,9 +273,9 @@ namespace boost { namespace locale { namespace impl_icu { escaped = false; } result += strftime_symbol_to_icu(c, cache); - } else if(c == '\'') { + } else if(c == '\'') result += "''"; - } else { + else { if(!escaped) { result += "'"; escaped = true; @@ -374,7 +377,7 @@ namespace boost { namespace locale { namespace impl_icu { case strftime: { using namespace flags; std::unique_ptr<icu::DateFormat> new_df; - icu::DateFormat* df = 0; + icu::DateFormat* df = nullptr; // try to use cached first { icu::SimpleDateFormat* sdf = cache.date_formatter(); @@ -389,7 +392,7 @@ namespace boost { namespace locale { namespace impl_icu { break; case strftime: { icu_std_converter<CharType> cvt_(encoding); - const std::basic_string<CharType>& f = info.date_time_pattern<CharType>(); + const std::basic_string<CharType> f = info.date_time_pattern<CharType>(); pattern = strftime_to_icu(cvt_.icu(f.c_str(), f.c_str() + f.size()), locale); } break; } @@ -418,7 +421,7 @@ namespace boost { namespace locale { namespace impl_icu { break; case strftime: { icu_std_converter<CharType> cvt_(encoding); - const std::basic_string<CharType>& f = info.date_time_pattern<CharType>(); + const std::basic_string<CharType> f = info.date_time_pattern<CharType>(); icu::UnicodeString pattern = strftime_to_icu(cvt_.icu(f.data(), f.data() + f.size()), locale); UErrorCode err = U_ZERO_ERROR; @@ -444,16 +447,9 @@ namespace boost { namespace locale { namespace impl_icu { return nullptr; // LCOV_EXCL_LINE } - template class formatter<char>; - template class formatter<wchar_t>; +#define BOOST_LOCALE_INSTANTIATE(CHAR) template class formatter<CHAR>; + BOOST_LOCALE_FOREACH_CHAR(BOOST_LOCALE_INSTANTIATE) -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - template class formatter<char16_t>; -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - template class formatter<char32_t>; -#endif }}} // namespace boost::locale::impl_icu // boostinspect:nominmax diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp b/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp index cc55e76e2e..110a031551 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/formatter.hpp @@ -8,7 +8,7 @@ #define BOOST_LOCALE_FORMATTER_HPP_INCLUDED #include <boost/locale/config.hpp> -#include <boost/cstdint.hpp> +#include <cstdint> #include <memory> #include <string> #include <unicode/locid.h> @@ -26,7 +26,6 @@ namespace boost { namespace locale { namespace impl_icu { template<typename CharType> class formatter : public base_formatter { public: - typedef CharType char_type; typedef std::basic_string<CharType> string_type; /// Format the value and return the number of Unicode code points diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp index acf1afccff..e5d5eb78ec 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -11,8 +12,7 @@ #include <boost/locale/util/locale_data.hpp> #include "boost/locale/icu/all_generator.hpp" #include "boost/locale/icu/cdata.hpp" -#include <algorithm> -#include <iterator> +#include "boost/locale/util/make_std_unique.hpp" #include <unicode/ucnv.h> @@ -85,9 +85,7 @@ namespace boost { namespace locale { namespace impl_icu { minf.country = country_; minf.variant = variant_; minf.encoding = data_.encoding; - std::copy(domains_.begin(), - domains_.end(), - std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); + minf.domains = gnu_gettext::messages_info::domains_type(domains_.begin(), domains_.end()); minf.paths = paths_; switch(type) { case char_facet_t::nochar: break; @@ -127,9 +125,9 @@ namespace boost { namespace locale { namespace impl_icu { bool use_ansi_encoding_; }; - localization_backend* create_localization_backend() + std::unique_ptr<localization_backend> create_localization_backend() { - return new icu_localization_backend(); + return make_std_unique<icu_localization_backend>(); } }}} // namespace boost::locale::impl_icu diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp index 3dc2ca53ea..8266856dc1 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_backend.hpp @@ -8,11 +8,12 @@ #define BOOST_LOCALE_IMPL_ICU_LOCALIZATION_BACKEND_HPP #include <boost/locale/config.hpp> +#include <memory> namespace boost { namespace locale { class localization_backend; namespace impl_icu { - localization_backend* create_localization_backend(); + std::unique_ptr<localization_backend> create_localization_backend(); } // namespace impl_icu }} // namespace boost::locale #endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp index 871e3f8488..70f4cefa36 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/icu_util.hpp @@ -9,9 +9,7 @@ #define BOOST_SRC_ICU_UTIL_HPP #include <boost/locale/config.hpp> -#ifdef BOOST_HAS_STDINT_H -# include <stdint.h> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings -#endif +#include <cstdint> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings #include <stdexcept> #include <string> #include <unicode/utypes.h> diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp index d3fdaaa2b8..963af7ba5b 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/numeric.cpp @@ -58,9 +58,8 @@ namespace boost { namespace locale { namespace impl_icu { if(!std::numeric_limits<ValueType>::is_integer) return false; - if(flg == flags::number && (ios.flags() & std::ios_base::basefield) != std::ios_base::dec) { + if(flg == flags::number && (ios.flags() & std::ios_base::basefield) != std::ios_base::dec) return true; - } return false; } } // namespace detail @@ -70,49 +69,48 @@ namespace boost { namespace locale { namespace impl_icu { public: typedef typename std::num_put<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; typedef formatter<CharType> formatter_type; num_format(const cdata& d, size_t refs = 0) : std::num_put<CharType>(refs), loc_(d.locale), enc_(d.encoding) {} protected: - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, double val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, double val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long double val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long double val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long long val) const override { return do_real_put(out, ios, fill, val); } private: template<typename ValueType> - iter_type do_real_put(iter_type out, std::ios_base& ios, char_type fill, ValueType val) const + iter_type do_real_put(iter_type out, std::ios_base& ios, CharType fill, ValueType val) const { if(detail::use_parent(ios, val)) - return std::num_put<char_type>::do_put(out, ios, fill, val); + return std::num_put<CharType>::do_put(out, ios, fill, val); const auto formatter = formatter_type::create(ios, loc_, enc_); if(!formatter) - return std::num_put<char_type>::do_put(out, ios, fill, val); + return std::num_put<CharType>::do_put(out, ios, fill, val); size_t code_points; typedef typename detail::icu_format_type<ValueType>::type icu_type; @@ -145,7 +143,7 @@ namespace boost { namespace locale { namespace impl_icu { icu::Locale loc_; std::string enc_; - }; /// num_format + }; // num_format template<typename CharType> class num_parse : public std::num_get<CharType> { @@ -155,7 +153,6 @@ namespace boost { namespace locale { namespace impl_icu { protected: typedef typename std::num_get<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; typedef formatter<CharType> formatter_type; typedef std::basic_istream<CharType> stream_type; @@ -240,14 +237,12 @@ namespace boost { namespace locale { namespace impl_icu { do_real_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, ValueType& val) const { stream_type* stream_ptr = dynamic_cast<stream_type*>(&ios); - if(!stream_ptr || detail::use_parent(ios, ValueType(0))) { + if(!stream_ptr || detail::use_parent(ios, ValueType(0))) return std::num_get<CharType>::do_get(in, end, ios, err, val); - } const auto formatter = formatter_type::create(ios, loc_, enc_); - if(!formatter) { + if(!formatter) return std::num_get<CharType>::do_get(in, end, ios, err, val); - } string_type tmp; tmp.reserve(64); @@ -256,23 +251,20 @@ namespace boost { namespace locale { namespace impl_icu { while(in != end && (((c = *in) <= 32 && (c > 0)) || c == 127)) // Assuming that ASCII is a subset ++in; - while(tmp.size() < 4096 && in != end && *in != '\n') { + while(tmp.size() < 4096 && in != end && *in != '\n') tmp += *in++; - } typedef typename detail::icu_format_type<ValueType>::type icu_type; icu_type value; size_t parsed_chars; - if((parsed_chars = formatter->parse(tmp, value)) == 0 || !is_losless_castable<ValueType>(value)) { + if((parsed_chars = formatter->parse(tmp, value)) == 0 || !is_losless_castable<ValueType>(value)) err |= std::ios_base::failbit; - } else { + else val = static_cast<ValueType>(value); - } - for(size_t n = tmp.size(); n > parsed_chars; n--) { + for(size_t n = tmp.size(); n > parsed_chars; n--) stream_ptr->putback(tmp[n - 1]); - } in = iter_type(*stream_ptr); @@ -314,9 +306,8 @@ namespace boost { namespace locale { namespace impl_icu { std::locale install_formatting_facets(const std::locale& in, const cdata& cd) { std::locale tmp = std::locale(in, new num_format<CharType>(cd)); - if(!std::has_facet<formatters_cache>(in)) { + if(!std::has_facet<formatters_cache>(in)) tmp = std::locale(tmp, new formatters_cache(cd.locale)); - } return tmp; } @@ -324,9 +315,8 @@ namespace boost { namespace locale { namespace impl_icu { std::locale install_parsing_facets(const std::locale& in, const cdata& cd) { std::locale tmp = std::locale(in, new num_parse<CharType>(cd)); - if(!std::has_facet<formatters_cache>(in)) { + if(!std::has_facet<formatters_cache>(in)) tmp = std::locale(tmp, new formatters_cache(cd.locale)); - } return tmp; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp b/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp index dc69f2dd90..2f11862a59 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.cpp @@ -45,12 +45,10 @@ namespace boost { namespace locale { namespace impl_icu { icu::TimeZone* get_time_zone(const std::string& time_zone) { - if(time_zone.empty()) { + if(time_zone.empty()) return icu::TimeZone::createDefault(); - } else { - icu::TimeZone* icu_tz = icu::TimeZone::createTimeZone(time_zone.c_str()); - return icu_tz; - } + else + return icu::TimeZone::createTimeZone(time_zone.c_str()); } #else @@ -83,7 +81,7 @@ namespace boost { namespace locale { namespace impl_icu { { if(d && readdir_r(d, &de, &read_result) == 0 && read_result != 0) return de.d_name; - return 0; + return nullptr; } private: @@ -95,10 +93,10 @@ namespace boost { namespace locale { namespace impl_icu { bool files_equal(const std::string& left, const std::string& right) { char l[256], r[256]; - std::ifstream ls(left.c_str()); + std::ifstream ls(left); if(!ls) return false; - std::ifstream rs(right.c_str()); + std::ifstream rs(right); if(!rs) return false; do { @@ -121,12 +119,11 @@ namespace boost { namespace locale { namespace impl_icu { if(!d.is_open()) return std::string(); - const char* name = 0; + const char* name = nullptr; while((name = d.next()) != 0) { std::string file_name = name; - if(file_name == "." || file_name == ".." || file_name == "posixrules" || file_name == "localtime") { + if(file_name == "." || file_name == ".." || file_name == "posixrules" || file_name == "localtime") continue; - } struct stat st; std::string path = dir + "/" + file_name; if(stat(path.c_str(), &st) == 0) { @@ -135,9 +132,8 @@ namespace boost { namespace locale { namespace impl_icu { if(!res.empty()) return file_name + "/" + res; } else { - if(size_t(st.st_size) == size && files_equal(path, ref)) { + if(size_t(st.st_size) == size && files_equal(path, ref)) return file_name; - } } } } @@ -194,9 +190,8 @@ namespace boost { namespace locale { namespace impl_icu { icu::TimeZone* get_time_zone(const std::string& time_zone) { - if(!time_zone.empty()) { + if(!time_zone.empty()) return icu::TimeZone::createTimeZone(time_zone.c_str()); - } hold_ptr<icu::TimeZone> tz(icu::TimeZone::createDefault()); icu::UnicodeString id; tz->getID(id); diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp b/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp index 132c5dbb64..87ab0c4416 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/time_zone.hpp @@ -8,9 +8,7 @@ #define BOOST_LOCALE_IMPL_ICU_GET_TIME_ZONE_HPP #include <boost/locale/config.hpp> -#ifdef BOOST_HAS_STDINT_H -# include <stdint.h> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings -#endif +#include <cstdint> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings #include <string> #include <unicode/timezone.h> diff --git a/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp b/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp index ac8278235b..7f3c88b5d2 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/icu/uconv.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2020-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -9,6 +10,7 @@ #include <boost/locale/encoding.hpp> #include "boost/locale/icu/icu_util.hpp" +#include <boost/core/exchange.hpp> #include <memory> #include <string> @@ -26,165 +28,158 @@ namespace boost { namespace locale { namespace impl_icu { - enum class cpcvt_type { skip, stop }; + class icu_handle { + UConverter* h_; + void close() + { + if(h_) + ucnv_close(h_); + } - template<typename CharType, int char_size = sizeof(CharType)> - class icu_std_converter { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + explicit icu_handle(UConverter* h = nullptr) : h_(h) {} - icu_std_converter(std::string charset, cpcvt_type cv = cpcvt_type::skip); - icu::UnicodeString icu(const char_type* begin, const char_type* end) const; - string_type std(const icu::UnicodeString& str) const; - size_t cut(const icu::UnicodeString& str, - const char_type* begin, - const char_type* end, - size_t n, - size_t from_u = 0, - size_t from_c = 0) const; + icu_handle(const icu_handle& rhs) = delete; + icu_handle(icu_handle&& rhs) noexcept : h_(exchange(rhs.h_, nullptr)) {} + + icu_handle& operator=(const icu_handle& rhs) = delete; + icu_handle& operator=(icu_handle&& rhs) noexcept + { + h_ = exchange(rhs.h_, nullptr); + return *this; + } + icu_handle& operator=(UConverter* h) + { + close(); + h_ = h; + return *this; + } + ~icu_handle() { close(); } + + operator UConverter*() const { return h_; } + explicit operator bool() const { return h_ != nullptr; } }; + enum class cpcvt_type { skip, stop }; + + struct uconv { + uconv(const uconv& other) = delete; + void operator=(const uconv& other) = delete; + + uconv(const std::string& charset, cpcvt_type cvt_type = cpcvt_type::skip) + { + UErrorCode err = U_ZERO_ERROR; + cvt_ = ucnv_open(charset.c_str(), &err); + if(!cvt_ || U_FAILURE(err)) + throw conv::invalid_charset_error(charset); + + if(cvt_type == cpcvt_type::skip) { + ucnv_setFromUCallBack(cvt_, UCNV_FROM_U_CALLBACK_SKIP, nullptr, nullptr, nullptr, &err); + ucnv_setToUCallBack(cvt_, UCNV_TO_U_CALLBACK_SKIP, nullptr, nullptr, nullptr, &err); + check_and_throw_icu_error(err); + } else { + ucnv_setFromUCallBack(cvt_, UCNV_FROM_U_CALLBACK_STOP, nullptr, nullptr, nullptr, &err); + ucnv_setToUCallBack(cvt_, UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr, nullptr, &err); + check_and_throw_icu_error(err); + } + } + + int max_char_size() const { return ucnv_getMaxCharSize(cvt_); } + + std::string go(const UChar* buf, int length, int max_size) const + { + std::string res; + res.resize(UCNV_GET_MAX_BYTES_FOR_STRING(length, max_size)); + char* ptr = reinterpret_cast<char*>(&res[0]); + UErrorCode err = U_ZERO_ERROR; + int n = ucnv_fromUChars(cvt_, ptr, res.size(), buf, length, &err); + check_and_throw_icu_error(err); + res.resize(n); + return res; + } + + size_t cut(size_t n, const char* begin, const char* end) const + { + const char* saved = begin; + while(n > 0 && begin < end) { + UErrorCode err = U_ZERO_ERROR; + ucnv_getNextUChar(cvt_, &begin, end, &err); + if(U_FAILURE(err)) + return 0; + n--; + } + return begin - saved; + } + + UConverter* cvt() const { return cvt_; } + + private: + icu_handle cvt_; + }; + + template<typename CharType, int char_size = sizeof(CharType)> + class icu_std_converter; + template<typename CharType> class icu_std_converter<CharType, 1> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; - icu::UnicodeString icu_checked(const char_type* vb, const char_type* ve) const + icu::UnicodeString icu_checked(const CharType* vb, const CharType* ve) const { return icu(vb, ve); // Already done } - icu::UnicodeString icu(const char_type* vb, const char_type* ve) const + icu::UnicodeString icu(const CharType* vb, const CharType* ve) const { const char* begin = reinterpret_cast<const char*>(vb); const char* end = reinterpret_cast<const char*>(ve); - uconv cvt(charset_, cvt_type_); UErrorCode err = U_ZERO_ERROR; - icu::UnicodeString tmp(begin, end - begin, cvt.cvt(), err); + icu::UnicodeString tmp(begin, end - begin, cvt_.cvt(), err); check_and_throw_icu_error(err); return tmp; } string_type std(const icu::UnicodeString& str) const { - uconv cvt(charset_, cvt_type_); - return cvt.go(str.getBuffer(), str.length(), max_len_); + return cvt_.go(str.getBuffer(), str.length(), max_len_); } - icu_std_converter(std::string charset, cpcvt_type cvt_type = cpcvt_type::skip) : - charset_(charset), cvt_type_(cvt_type) - { - uconv cvt(charset_, cvt_type); - max_len_ = cvt.max_char_size(); - } + icu_std_converter(const std::string& charset, cpcvt_type cvt_type = cpcvt_type::skip) : + cvt_(charset, cvt_type), max_len_(cvt_.max_char_size()) + {} size_t cut(const icu::UnicodeString& str, - const char_type* begin, - const char_type* end, + const CharType* begin, + const CharType* end, size_t n, size_t from_u = 0, size_t from_char = 0) const { size_t code_points = str.countChar32(from_u, n); - uconv cvt(charset_, cvt_type_); - return cvt.cut(code_points, begin + from_char, end); + return cvt_.cut(code_points, begin + from_char, end); } - struct uconv { - uconv(const uconv& other) = delete; - void operator=(const uconv& other) = delete; - - uconv(const std::string& charset, cpcvt_type cvt_type = cpcvt_type::skip) - { - UErrorCode err = U_ZERO_ERROR; - cvt_ = ucnv_open(charset.c_str(), &err); - if(!cvt_ || U_FAILURE(err)) { - if(cvt_) - ucnv_close(cvt_); - throw conv::invalid_charset_error(charset); - } - - try { - if(cvt_type == cpcvt_type::skip) { - ucnv_setFromUCallBack(cvt_, UCNV_FROM_U_CALLBACK_SKIP, 0, 0, 0, &err); - check_and_throw_icu_error(err); - - err = U_ZERO_ERROR; - ucnv_setToUCallBack(cvt_, UCNV_TO_U_CALLBACK_SKIP, 0, 0, 0, &err); - check_and_throw_icu_error(err); - } else { - ucnv_setFromUCallBack(cvt_, UCNV_FROM_U_CALLBACK_STOP, 0, 0, 0, &err); - check_and_throw_icu_error(err); - - err = U_ZERO_ERROR; - ucnv_setToUCallBack(cvt_, UCNV_TO_U_CALLBACK_STOP, 0, 0, 0, &err); - check_and_throw_icu_error(err); - } - } catch(...) { - ucnv_close(cvt_); - throw; - } - } - - int max_char_size() { return ucnv_getMaxCharSize(cvt_); } - - string_type go(const UChar* buf, int length, int max_size) - { - string_type res; - res.resize(UCNV_GET_MAX_BYTES_FOR_STRING(length, max_size)); - char* ptr = reinterpret_cast<char*>(&res[0]); - UErrorCode err = U_ZERO_ERROR; - int n = ucnv_fromUChars(cvt_, ptr, res.size(), buf, length, &err); - check_and_throw_icu_error(err); - res.resize(n); - return res; - } - - size_t cut(size_t n, const char_type* begin, const char_type* end) - { - const char_type* saved = begin; - while(n > 0 && begin < end) { - UErrorCode err = U_ZERO_ERROR; - ucnv_getNextUChar(cvt_, &begin, end, &err); - if(U_FAILURE(err)) - return 0; - n--; - } - return begin - saved; - } - - UConverter* cvt() { return cvt_; } - - ~uconv() { ucnv_close(cvt_); } - - private: - UConverter* cvt_; - }; - private: - int max_len_; - std::string charset_; - cpcvt_type cvt_type_; + uconv cvt_; + const int max_len_; }; template<typename CharType> class icu_std_converter<CharType, 2> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; - icu::UnicodeString icu_checked(const char_type* begin, const char_type* end) const + icu::UnicodeString icu_checked(const CharType* begin, const CharType* end) const { - icu::UnicodeString tmp(end - begin, 0, 0); // make inital capacity + icu::UnicodeString tmp(end - begin, 0, 0); // make initial capacity while(begin != end) { UChar cl = *begin++; if(U16_IS_SINGLE(cl)) tmp.append(static_cast<UChar32>(cl)); else if(U16_IS_LEAD(cl)) { - if(begin == end) { + if(begin == end) throw_if_needed(); - } else { + else { UChar ct = *begin++; if(!U16_IS_TRAIL(ct)) throw_if_needed(); @@ -203,8 +198,9 @@ namespace boost { namespace locale { namespace impl_icu { if(mode_ == cpcvt_type::stop) throw conv::conversion_error(); } - icu::UnicodeString icu(const char_type* vb, const char_type* ve) const + icu::UnicodeString icu(const CharType* vb, const CharType* ve) const { + static_assert(sizeof(CharType) == sizeof(UChar), "Size mismatch!"); const UChar* begin = reinterpret_cast<const UChar*>(vb); const UChar* end = reinterpret_cast<const UChar*>(ve); icu::UnicodeString tmp(begin, end - begin); @@ -213,12 +209,13 @@ namespace boost { namespace locale { namespace impl_icu { string_type std(const icu::UnicodeString& str) const { - const char_type* ptr = reinterpret_cast<const char_type*>(str.getBuffer()); + static_assert(sizeof(CharType) == sizeof(UChar), "Size mismatch!"); + const CharType* ptr = reinterpret_cast<const CharType*>(str.getBuffer()); return string_type(ptr, str.length()); } size_t cut(const icu::UnicodeString& /*str*/, - const char_type* /*begin*/, - const char_type* /*end*/, + const CharType* /*begin*/, + const CharType* /*end*/, size_t n, size_t /*from_u*/ = 0, size_t /*from_c*/ = 0) const @@ -235,18 +232,29 @@ namespace boost { namespace locale { namespace impl_icu { template<typename CharType> class icu_std_converter<CharType, 4> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; - icu::UnicodeString icu_checked(const char_type* begin, const char_type* end) const + icu::UnicodeString icu_checked(const CharType* begin, const CharType* end) const { - icu::UnicodeString tmp(end - begin, 0, 0); // make inital capacity + // Fast path checking if the full string is already valid + { + UErrorCode err = U_ZERO_ERROR; + static_assert(sizeof(CharType) == sizeof(UChar32), "Size mismatch!"); + u_strFromUTF32(nullptr, 0, nullptr, reinterpret_cast<const UChar32*>(begin), end - begin, &err); + if(err != U_INVALID_CHAR_FOUND) + return icu::UnicodeString::fromUTF32(reinterpret_cast<const UChar32*>(begin), end - begin); + } + // Any char is invalid + throw_if_needed(); + // If not thrown skip invalid chars + icu::UnicodeString tmp(end - begin, 0, 0); // make initial capacity while(begin != end) { - UChar32 c = static_cast<UChar32>(*begin++); - if(U_IS_UNICODE_CHAR(c)) + const UChar32 c = static_cast<UChar32>(*begin++); + // Maybe simply: UCHAR_MIN_VALUE <= c && c <= UCHAR_MAX_VALUE && !U_IS_SURROGATE(c) + UErrorCode err = U_ZERO_ERROR; + u_strFromUTF32(nullptr, 0, nullptr, &c, 1, &err); + if(err != U_INVALID_CHAR_FOUND) tmp.append(c); - else - throw_if_needed(); } return tmp; } @@ -256,9 +264,9 @@ namespace boost { namespace locale { namespace impl_icu { throw conv::conversion_error(); } - icu::UnicodeString icu(const char_type* begin, const char_type* end) const + icu::UnicodeString icu(const CharType* begin, const CharType* end) const { - icu::UnicodeString tmp(end - begin, 0, 0); // make inital capacity + icu::UnicodeString tmp(end - begin, 0, 0); // make initial capacity while(begin != end) { UChar32 c = static_cast<UChar32>(*begin++); tmp.append(c); @@ -283,8 +291,8 @@ namespace boost { namespace locale { namespace impl_icu { } size_t cut(const icu::UnicodeString& str, - const char_type* /*begin*/, - const char_type* /*end*/, + const CharType* /*begin*/, + const CharType* /*end*/, size_t n, size_t from_u = 0, size_t /*from_c*/ = 0) const diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp b/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp index 410d8bed45..e5c46ac248 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/posix/collate.cpp @@ -40,39 +40,37 @@ namespace boost { namespace locale { namespace impl_posix { template<typename CharType> class collator : public std::collate<CharType> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; collator(std::shared_ptr<locale_t> l, size_t refs = 0) : std::collate<CharType>(refs), lc_(std::move(l)) {} - int - do_compare(const char_type* lb, const char_type* le, const char_type* rb, const char_type* re) const override + int do_compare(const CharType* lb, const CharType* le, const CharType* rb, const CharType* re) const override { string_type left(lb, le - lb); string_type right(rb, re - rb); - int res = coll_traits<char_type>::coll(left.c_str(), right.c_str(), *lc_); + int res = coll_traits<CharType>::coll(left.c_str(), right.c_str(), *lc_); if(res < 0) return -1; if(res > 0) return 1; return 0; } - long do_hash(const char_type* b, const char_type* e) const override + long do_hash(const CharType* b, const CharType* e) const override { string_type s(do_transform(b, e)); const char* begin = reinterpret_cast<const char*>(s.c_str()); - const char* end = begin + s.size() * sizeof(char_type); + const char* end = begin + s.size() * sizeof(CharType); return gnu_gettext::pj_winberger_hash_function(begin, end); } - string_type do_transform(const char_type* b, const char_type* e) const override + string_type do_transform(const CharType* b, const CharType* e) const override { string_type s(b, e - b); - std::vector<char_type> buf((e - b) * 2 + 1); - size_t n = coll_traits<char_type>::xfrm(&buf.front(), s.c_str(), buf.size(), *lc_); + std::vector<CharType> buf((e - b) * 2 + 1); + size_t n = coll_traits<CharType>::xfrm(buf.data(), s.c_str(), buf.size(), *lc_); if(n > buf.size()) { buf.resize(n); - coll_traits<char_type>::xfrm(&buf.front(), s.c_str(), n, *lc_); + coll_traits<CharType>::xfrm(buf.data(), s.c_str(), n, *lc_); } - return string_type(&buf.front(), n); + return string_type(buf.data(), n); } private: diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp b/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp index 4dfa6babee..f769c7259e 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/posix/converter.cpp @@ -7,6 +7,7 @@ #include <boost/locale/conversion.hpp> #include <boost/locale/encoding.hpp> #include <boost/locale/generator.hpp> +#include "boost/locale/util/encoding.hpp" #include <cctype> #include <cstring> #include <langinfo.h> @@ -39,31 +40,28 @@ namespace boost { namespace locale { namespace impl_posix { template<typename CharType> class std_converter : public converter<CharType> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; - typedef std::ctype<char_type> ctype_type; + typedef std::basic_string<CharType> string_type; + typedef std::ctype<CharType> ctype_type; std_converter(std::shared_ptr<locale_t> lc, size_t refs = 0) : converter<CharType>(refs), lc_(std::move(lc)) {} string_type convert(converter_base::conversion_type how, - const char_type* begin, - const char_type* end, + const CharType* begin, + const CharType* end, int /*flags*/ = 0) const override { switch(how) { case converter_base::upper_case: { string_type res; res.reserve(end - begin); - while(begin != end) { - res += case_traits<char_type>::upper(*begin++, *lc_); - } + while(begin != end) + res += case_traits<CharType>::upper(*begin++, *lc_); return res; } case converter_base::lower_case: case converter_base::case_folding: { string_type res; res.reserve(end - begin); - while(begin != end) { - res += case_traits<char_type>::lower(*begin++, *lc_); - } + while(begin != end) + res += case_traits<CharType>::lower(*begin++, *lc_); return res; } case converter_base::normalization: @@ -86,22 +84,22 @@ namespace boost { namespace locale { namespace impl_posix { { switch(how) { case upper_case: { - std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8"); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(begin, end); std::wstring wres; wres.reserve(tmp.size()); - for(unsigned i = 0; i < tmp.size(); i++) - wres += towupper_l(tmp[i], *lc_); - return conv::from_utf<wchar_t>(wres, "UTF-8"); + for(const wchar_t c : tmp) + wres += towupper_l(c, *lc_); + return conv::utf_to_utf<char>(wres); } case lower_case: case case_folding: { - std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8"); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(begin, end); std::wstring wres; wres.reserve(tmp.size()); - for(unsigned i = 0; i < tmp.size(); i++) - wres += towlower_l(tmp[i], *lc_); - return conv::from_utf<wchar_t>(wres, "UTF-8"); + for(const wchar_t c : tmp) + wres += towlower_l(c, *lc_); + return conv::utf_to_utf<char>(wres); } case normalization: case title_case: break; @@ -118,13 +116,8 @@ namespace boost { namespace locale { namespace impl_posix { switch(type) { case char_facet_t::nochar: break; case char_facet_t::char_f: { - std::string encoding = nl_langinfo_l(CODESET, *lc); - for(unsigned i = 0; i < encoding.size(); i++) - if('A' <= encoding[i] && encoding[i] <= 'Z') - encoding[i] = encoding[i] - 'A' + 'a'; - if(encoding == "utf-8" || encoding == "utf8" || encoding == "utf_8") { + if(util::normalize_encoding(nl_langinfo_l(CODESET, *lc)) == "utf8") return std::locale(in, new utf8_converter(std::move(lc))); - } return std::locale(in, new std_converter<char>(std::move(lc))); } case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(std::move(lc))); diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp b/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp index 6c63a88810..031ce81463 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/posix/numeric.cpp @@ -11,6 +11,7 @@ #include <boost/locale/formatting.hpp> #include <boost/locale/generator.hpp> #include <boost/predef/os.h> +#include <algorithm> #include <cctype> #include <cerrno> #include <cstdlib> @@ -36,7 +37,6 @@ namespace boost { namespace locale { namespace impl_posix { public: typedef typename std::num_put<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; num_format(std::shared_ptr<locale_t> lc, size_t refs = 0) : util::base_num_format<CharType>(refs), lc_(std::move(lc)) @@ -46,7 +46,7 @@ namespace boost { namespace locale { namespace impl_posix { iter_type do_format_currency(bool intl, iter_type out, std::ios_base& /*ios*/, - char_type /*fill*/, + CharType /*fill*/, long double val) const override { char buf[4] = {}; @@ -57,33 +57,29 @@ namespace boost { namespace locale { namespace impl_posix { return write_it(out, buf, n); for(std::vector<char> tmp(sizeof(buf) * 2); tmp.size() <= 4098; tmp.resize(tmp.size() * 2)) { - n = strfmon_l(&tmp.front(), tmp.size(), *lc_, format, static_cast<double>(val)); + n = strfmon_l(tmp.data(), tmp.size(), *lc_, format, static_cast<double>(val)); if(n >= 0) - return write_it(out, &tmp.front(), n); + return write_it(out, tmp.data(), n); } return out; } std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out, const char* ptr, size_t n) const { - for(size_t i = 0; i < n; i++) - *out++ = *ptr++; - return out; + return std::copy_n(ptr, n, out); } std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out, const char* ptr, size_t n) const { - std::wstring tmp = conv::to_utf<wchar_t>(ptr, ptr + n, nl_langinfo_l(CODESET, *lc_)); - for(size_t i = 0; i < tmp.size(); i++) - *out++ = tmp[i]; - return out; + const std::wstring tmp = conv::to_utf<wchar_t>(ptr, ptr + n, nl_langinfo_l(CODESET, *lc_)); + return std::copy(tmp.begin(), tmp.end(), out); } private: std::shared_ptr<locale_t> lc_; - }; /// num_format + }; // num_format namespace { std::string do_ftime(const char* format, const struct tm* t, locale_t lc) @@ -119,8 +115,7 @@ namespace boost { namespace locale { namespace impl_posix { std::time_put<CharType>(refs), lc_(std::move(lc)) {} typedef typename std::time_put<CharType>::iter_type iter_type; - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; iter_type do_put(iter_type out, std::ios_base& /*ios*/, @@ -129,13 +124,11 @@ namespace boost { namespace locale { namespace impl_posix { char format, char modifier) const override { - char_type fmt[4] = {'%', - static_cast<char_type>(modifier != 0 ? modifier : format), - static_cast<char_type>(modifier == 0 ? '\0' : format)}; + CharType fmt[4] = {'%', + static_cast<CharType>(modifier != 0 ? modifier : format), + static_cast<CharType>(modifier == 0 ? '\0' : format)}; string_type res = do_ftime(fmt, tm, *lc_); - for(unsigned i = 0; i < res.size(); i++) - *out++ = res[i]; - return out; + return std::copy(res.begin(), res.end(), out); } private: diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp b/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp index df87fa14f7..14d864bbf9 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -20,6 +21,7 @@ #include "boost/locale/posix/all_generator.hpp" #include "boost/locale/util/gregorian.hpp" +#include "boost/locale/util/make_std_unique.hpp" namespace boost { namespace locale { namespace impl_posix { @@ -66,25 +68,19 @@ namespace boost { namespace locale { namespace impl_posix { if(real_id_.empty()) real_id_ = util::get_system_locale(); - locale_t tmp = newlocale(LC_ALL_MASK, real_id_.c_str(), 0); - - if(!tmp) { - tmp = newlocale(LC_ALL_MASK, "C", 0); - } - if(!tmp) { + locale_t tmp = newlocale(LC_ALL_MASK, real_id_.c_str(), nullptr); + if(!tmp) + tmp = newlocale(LC_ALL_MASK, "C", nullptr); + if(!tmp) throw std::runtime_error("newlocale failed"); - } - - locale_t* tmp_p = 0; + locale_t* tmp_p; try { - tmp_p = new locale_t(); + tmp_p = new locale_t(tmp); } catch(...) { freelocale(tmp); throw; } - - *tmp_p = tmp; lc_ = std::shared_ptr<locale_t>(tmp_p, free_locale_by_ptr); } @@ -148,9 +144,9 @@ namespace boost { namespace locale { namespace impl_posix { std::shared_ptr<locale_t> lc_; }; - localization_backend* create_localization_backend() + std::unique_ptr<localization_backend> create_localization_backend() { - return new posix_localization_backend(); + return make_std_unique<posix_localization_backend>(); } }}} // namespace boost::locale::impl_posix diff --git a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp b/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp index e172fe4103..925c9580d5 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/posix/posix_backend.hpp @@ -6,10 +6,14 @@ #ifndef BOOST_LOCALE_IMPL_POSIX_LOCALIZATION_BACKEND_HPP #define BOOST_LOCALE_IMPL_POSIX_LOCALIZATION_BACKEND_HPP + +#include <boost/locale/config.hpp> +#include <memory> + namespace boost { namespace locale { class localization_backend; namespace impl_posix { - localization_backend* create_localization_backend(); + std::unique_ptr<localization_backend> create_localization_backend(); } // namespace impl_posix }} // namespace boost::locale #endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp index 1970fec8bb..60f96feb7b 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/date_time.cpp @@ -6,6 +6,7 @@ #include <boost/locale/date_time.hpp> #include <boost/locale/formatting.hpp> +#include <boost/core/exchange.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/mutex.hpp> #include <cmath> @@ -66,12 +67,12 @@ namespace boost { namespace locale { return impl_->get_option(abstract_calendar::is_gregorian) != 0; } - std::string calendar::get_time_zone() const + const std::string& calendar::get_time_zone() const { return tz_; } - std::locale calendar::get_locale() const + const std::locale& calendar::get_locale() const { return locale_; } @@ -125,9 +126,8 @@ namespace boost { namespace locale { date_time::date_time(const date_time& other, const date_time_period_set& s) { impl_.reset(other.impl_->clone()); - for(unsigned i = 0; i < s.size(); i++) { + for(unsigned i = 0; i < s.size(); i++) impl_->set_value(s[i].type.mark(), s[i].value); - } impl_->normalize(); } @@ -154,16 +154,14 @@ namespace boost { namespace locale { impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) { impl_->set_timezone(time_zone::global()); - for(unsigned i = 0; i < s.size(); i++) { + for(unsigned i = 0; i < s.size(); i++) impl_->set_value(s[i].type.mark(), s[i].value); - } impl_->normalize(); } date_time::date_time(const date_time_period_set& s, const calendar& cal) : impl_(cal.impl_->clone()) { - for(unsigned i = 0; i < s.size(); i++) { + for(unsigned i = 0; i < s.size(); i++) impl_->set_value(s[i].type.mark(), s[i].value); - } impl_->normalize(); } @@ -268,33 +266,29 @@ namespace boost { namespace locale { date_time& date_time::operator+=(const date_time_period_set& v) { - for(unsigned i = 0; i < v.size(); i++) { + for(unsigned i = 0; i < v.size(); i++) *this += v[i]; - } return *this; } date_time& date_time::operator-=(const date_time_period_set& v) { - for(unsigned i = 0; i < v.size(); i++) { + for(unsigned i = 0; i < v.size(); i++) *this -= v[i]; - } return *this; } date_time& date_time::operator<<=(const date_time_period_set& v) { - for(unsigned i = 0; i < v.size(); i++) { + for(unsigned i = 0; i < v.size(); i++) *this <<= v[i]; - } return *this; } date_time& date_time::operator>>=(const date_time_period_set& v) { - for(unsigned i = 0; i < v.size(); i++) { + for(unsigned i = 0; i < v.size(); i++) *this >>= v[i]; - } return *this; } @@ -325,6 +319,11 @@ namespace boost { namespace locale { impl_->set_time(ptime); } + std::string date_time::timezone() const + { + return impl_->get_timezone(); + } + namespace { int compare(const posix_time& left, const posix_time& right) { @@ -370,7 +369,7 @@ namespace boost { namespace locale { return !(*this > other); } - void date_time::swap(date_time& other) + void date_time::swap(date_time& other) noexcept { impl_.swap(other.impl_); } @@ -409,15 +408,12 @@ namespace boost { namespace locale { std::string global() { boost::unique_lock<boost::mutex> lock(tz_mutex()); - std::string id = tz_id(); - return id; + return tz_id(); } std::string global(const std::string& new_id) { boost::unique_lock<boost::mutex> lock(tz_mutex()); - std::string id = tz_id(); - tz_id() = new_id; - return id; + return boost::exchange(tz_id(), new_id); } } // namespace time_zone diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp index 8d3f7406af..7ee809fe70 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/format.cpp @@ -7,11 +7,13 @@ #include <boost/locale/format.hpp> #include <boost/locale/generator.hpp> #include <boost/locale/info.hpp> -#include <cstdlib> +#include "boost/locale/util/numeric.hpp" +#include <algorithm> #include <iostream> #include <limits> namespace boost { namespace locale { namespace detail { + struct format_parser::data { unsigned position; std::streamsize precision; @@ -61,17 +63,11 @@ namespace boost { namespace locale { namespace detail { { if(key.empty()) return; - unsigned i; - for(i = 0; i < key.size(); i++) { - if(key[i] < '0' || '9' < key[i]) - break; - } - if(i == key.size()) { - d->position = atoi(key.c_str()) - 1; - return; - } - - if(key == "num" || key == "number") { + int position; + if(util::try_to_int(key, position) && position > 0) { + static_assert(sizeof(unsigned) <= sizeof(decltype(d->position)), "Possible lossy conversion"); + d->position = static_cast<unsigned>(position - 1); + } else if(key == "num" || key == "number") { as::number(ios_); if(value == "hex") @@ -88,9 +84,9 @@ namespace boost { namespace locale { namespace detail { as::currency_iso(ios_); else if(value == "nat" || value == "national") as::currency_national(ios_); - } else if(key == "per" || key == "percent") { + } else if(key == "per" || key == "percent") as::percent(ios_); - } else if(key == "date") { + else if(key == "date") { as::date(ios_); if(value == "s" || value == "short") as::date_short(ios_); @@ -125,11 +121,11 @@ namespace boost { namespace locale { namespace detail { as::date_full(ios_); as::time_full(ios_); } - } else if(key == "spell" || key == "spellout") { + } else if(key == "spell" || key == "spellout") as::spellout(ios_); - } else if(key == "ord" || key == "ordinal") { + else if(key == "ord" || key == "ordinal") as::ordinal(ios_); - } else if(key == "left" || key == "<") + else if(key == "left" || key == "<") ios_.setf(std::ios_base::left, std::ios_base::adjustfield); else if(key == "right" || key == ">") ios_.setf(std::ios_base::right, std::ios_base::adjustfield); @@ -139,23 +135,26 @@ namespace boost { namespace locale { namespace detail { as::local_time(ios_); else if(key == "timezone" || key == "tz") ios_info::get(ios_).time_zone(value); - else if(key == "w" || key == "width") - ios_.width(atoi(value.c_str())); - else if(key == "p" || key == "precision") - ios_.precision(atoi(value.c_str())); - else if(key == "locale") { + else if(key == "w" || key == "width") { + int v; + if(util::try_to_int(value, v)) + ios_.width(v); + } else if(key == "p" || key == "precision") { + int v; + if(util::try_to_int(value, v)) + ios_.precision(v); + } else if(key == "locale") { if(!d->restore_locale) { d->saved_locale = ios_.getloc(); d->restore_locale = true; } - std::string encoding = std::use_facet<info>(d->saved_locale).encoding(); generator gen; gen.categories(category_t::formatting); std::locale new_loc; if(value.find('.') == std::string::npos) - new_loc = gen(value + "." + encoding); + new_loc = gen(value + "." + std::use_facet<info>(d->saved_locale).encoding()); else new_loc = gen(value); diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp index 5c1e5e7ab5..489d1fd5a0 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/formatting.cpp @@ -12,22 +12,22 @@ namespace boost { namespace locale { - ios_info::string_set::string_set() : type(0), size(0), ptr(0) {} + ios_info::string_set::string_set() : type(nullptr), size(0), ptr(nullptr) {} ios_info::string_set::~string_set() { delete[] ptr; } ios_info::string_set::string_set(const string_set& other) { - if(other.ptr != 0) { + if(other.ptr != nullptr) { ptr = new char[other.size]; size = other.size; type = other.type; memcpy(ptr, other.ptr, size); } else { - ptr = 0; + ptr = nullptr; size = 0; - type = 0; + type = nullptr; } } diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp index fe4e20c3c8..baf424bea8 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/generator.cpp @@ -20,8 +20,7 @@ namespace boost { namespace locale { backend_manager(mgr) {} - typedef std::map<std::string, std::locale> cached_type; - mutable cached_type cached; + mutable std::map<std::string, std::locale> cached; mutable boost::mutex cached_lock; category_t cats; @@ -69,10 +68,9 @@ namespace boost { namespace locale { void generator::set_default_messages_domain(const std::string& domain) { - std::vector<std::string>::iterator p; - if((p = std::find(d->domains.begin(), d->domains.end(), domain)) != d->domains.end()) { + const auto p = std::find(d->domains.begin(), d->domains.end(), domain); + if(p != d->domains.end()) d->domains.erase(p); - } d->domains.insert(d->domains.begin(), domain); } @@ -104,12 +102,11 @@ namespace boost { namespace locale { { if(d->caching_enabled) { boost::unique_lock<boost::mutex> guard(d->cached_lock); - data::cached_type::const_iterator p = d->cached.find(id); - if(p != d->cached.end()) { + const auto p = d->cached.find(id); + if(p != d->cached.end()) return p->second; - } } - hold_ptr<localization_backend> backend(d->backend_manager.create()); + auto backend = d->backend_manager.create(); set_all_options(*backend, id); std::locale result = base; @@ -130,10 +127,9 @@ namespace boost { namespace locale { } if(d->caching_enabled) { boost::unique_lock<boost::mutex> guard(d->cached_lock); - data::cached_type::const_iterator p = d->cached.find(id); - if(p == d->cached.end()) { + const auto p = d->cached.find(id); + if(p == d->cached.end()) d->cached[id] = result; - } } return result; } @@ -160,12 +156,11 @@ namespace boost { namespace locale { void generator::set_all_options(localization_backend& backend, const std::string& id) const { backend.set_option("locale", id); - if(d->use_ansi_encoding) - backend.set_option("use_ansi_encoding", "true"); - for(size_t i = 0; i < d->domains.size(); i++) - backend.set_option("message_application", d->domains[i]); - for(size_t i = 0; i < d->paths.size(); i++) - backend.set_option("message_path", d->paths[i]); + backend.set_option("use_ansi_encoding", d->use_ansi_encoding ? "true" : "false"); + for(const std::string& domain : d->domains) + backend.set_option("message_application", domain); + for(const std::string& path : d->paths) + backend.set_option("message_path", path); } // Sanity check diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp index 764fe3c686..d34cb738be 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/iconv_codecvt.cpp @@ -12,27 +12,19 @@ #include <limits> #include <vector> #ifdef BOOST_LOCALE_WITH_ICONV +# include "boost/locale/util/encoding.hpp" # include "boost/locale/util/iconv.hpp" +# include "boost/locale/util/make_std_unique.hpp" #endif namespace boost { namespace locale { #ifdef BOOST_LOCALE_WITH_ICONV - static const char* utf32_encoding() - { - union { - char one; - uint32_t value; - } test; - test.value = 1; - return (test.one == 1) ? "UTF-32LE" : "UTF-32BE"; - } - class mb2_iconv_converter : public util::base_converter { public: mb2_iconv_converter(const std::string& encoding) : encoding_(encoding) { - iconv_handle d = iconv_open(utf32_encoding(), encoding.c_str()); + iconv_handle d(iconv_open(util::utf_name<uint32_t>(), encoding.c_str())); if(!d) throw std::runtime_error("Unsupported encoding" + encoding); @@ -68,7 +60,7 @@ namespace boost { namespace locale { mb2_iconv_converter* clone() const override { return new mb2_iconv_converter(*this); } - uint32_t to_unicode(const char*& begin, const char* end) override + utf::code_point to_unicode(const char*& begin, const char* end) override { if(begin == end) return incomplete; @@ -95,7 +87,7 @@ namespace boost { namespace locale { } else if(begin + 1 == end) return incomplete; - open(to_utf_, utf32_encoding(), encoding_.c_str()); + open(to_utf_, util::utf_name<uint32_t>(), encoding_.c_str()); // maybe illegal or may be double byte @@ -111,20 +103,19 @@ namespace boost { namespace locale { return illegal; } - uint32_t from_unicode(uint32_t cp, char* begin, const char* end) override + utf::len_or_error from_unicode(utf::code_point cp, char* begin, const char* end) override { if(cp == 0) { if(begin != end) { *begin = 0; return 1; - } else { + } else return incomplete; - } } - open(from_utf_, encoding_.c_str(), utf32_encoding()); + open(from_utf_, encoding_.c_str(), util::utf_name<utf::code_point>()); - const uint32_t inbuf[2] = {cp, 0}; + const utf::code_point inbuf[2] = {cp, 0}; size_t insize = sizeof(inbuf); char outseq[3] = {0}; size_t outsize = 3; @@ -133,13 +124,13 @@ namespace boost { namespace locale { if(insize != 0 || outsize > 1) return illegal; - size_t len = 2 - outsize; - size_t reminder = end - begin; + const size_t len = 2 - outsize; + const size_t reminder = end - begin; if(reminder < len) return incomplete; for(unsigned i = 0; i < len; i++) *begin++ = outseq[i]; - return static_cast<uint32_t>(len); + return static_cast<utf::code_point>(len); } int max_len() const override @@ -163,7 +154,7 @@ namespace boost { namespace locale { std::unique_ptr<util::base_converter> create_iconv_converter(const std::string& encoding) { try { - return std::unique_ptr<util::base_converter>(new mb2_iconv_converter(encoding)); + return make_std_unique<mb2_iconv_converter>(encoding); } catch(const std::exception&) { return nullptr; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp index 30d91d7454..95a64ff19a 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/ids.cpp @@ -10,81 +10,36 @@ #include <boost/locale/date_time_facet.hpp> #include <boost/locale/info.hpp> #include <boost/locale/message.hpp> +#include "boost/locale/util/foreach_char.hpp" #include <boost/core/ignore_unused.hpp> namespace boost { namespace locale { + namespace detail { + template<class Derived> + std::locale::id facet_id<Derived>::id; + } // namespace detail +#define BOOST_LOCALE_DEFINE_ID(CLASS) template struct detail::facet_id<CLASS> - std::locale::id info::id; - // Make sure we have the VTable here (Export/Import issues) - info::~info() = default; + BOOST_LOCALE_DEFINE_ID(info); + BOOST_LOCALE_DEFINE_ID(calendar_facet); - std::locale::id calendar_facet::id; - calendar_facet::~calendar_facet() = default; +#define BOOST_LOCALE_INSTANTIATE(CHARTYPE) \ + BOOST_LOCALE_DEFINE_ID(converter<CHARTYPE>); \ + BOOST_LOCALE_DEFINE_ID(message_format<CHARTYPE>); \ + BOOST_LOCALE_DEFINE_ID(boundary::boundary_indexing<CHARTYPE>); - abstract_calendar::~abstract_calendar() = default; - - std::locale::id converter<char>::id; - converter<char>::~converter() = default; - std::locale::id base_message_format<char>::id; - base_message_format<char>::~base_message_format() = default; - - std::locale::id converter<wchar_t>::id; - converter<wchar_t>::~converter() = default; - std::locale::id base_message_format<wchar_t>::id; - base_message_format<wchar_t>::~base_message_format() = default; - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - - std::locale::id converter<char16_t>::id; - converter<char16_t>::~converter() = default; - std::locale::id base_message_format<char16_t>::id; - base_message_format<char16_t>::~base_message_format() = default; - -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - - std::locale::id converter<char32_t>::id; - converter<char32_t>::~converter() = default; - std::locale::id base_message_format<char32_t>::id; - base_message_format<char32_t>::~base_message_format() = default; - -#endif - - namespace boundary { - - std::locale::id boundary_indexing<char>::id; - boundary_indexing<char>::~boundary_indexing() = default; - - std::locale::id boundary_indexing<wchar_t>::id; - boundary_indexing<wchar_t>::~boundary_indexing() = default; - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - std::locale::id boundary_indexing<char16_t>::id; - boundary_indexing<char16_t>::~boundary_indexing() = default; -#endif - -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - std::locale::id boundary_indexing<char32_t>::id; - boundary_indexing<char32_t>::~boundary_indexing() = default; -#endif - } // namespace boundary + BOOST_LOCALE_FOREACH_CHAR(BOOST_LOCALE_INSTANTIATE) +#undef BOOST_LOCALE_INSTANTIATE namespace { // Initialize each facet once to avoid issues where doing so - // in a multithreaded environment could cause problems (races) + // in a multi threaded environment could cause problems (races) struct init_all { init_all() { const std::locale& l = std::locale::classic(); - init_by<char>(l); - init_by<wchar_t>(l); -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - init_by<char16_t>(l); -#endif -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T - init_by<char32_t>(l); -#endif +#define BOOST_LOCALE_INIT_BY(CHAR) init_by<CHAR>(l); + BOOST_LOCALE_FOREACH_CHAR(BOOST_LOCALE_INIT_BY) init_facet<info>(l); init_facet<calendar_facet>(l); diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp index e15de171a6..951cb3beb4 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/localization_backend.cpp @@ -4,10 +4,10 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include <boost/locale/hold_ptr.hpp> #include <boost/locale/localization_backend.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/mutex.hpp> +#include <functional> #include <memory> #include <vector> @@ -28,19 +28,19 @@ #endif namespace boost { namespace locale { + static std::unique_ptr<localization_backend> clone(const localization_backend& backend) + { + return std::unique_ptr<localization_backend>(backend.clone()); + } + localization_backend::~localization_backend() = default; class localization_backend_manager::impl { public: impl(const impl& other) : default_backends_(other.default_backends_) { - for(all_backends_type::const_iterator p = other.all_backends_.begin(); p != other.all_backends_.end(); ++p) - { - all_backends_type::value_type v; - v.first = p->first; - v.second.reset(p->second->clone()); - all_backends_.push_back(v); - } + for(const auto& i : other.all_backends_) + all_backends_.push_back({i.first, clone(*i.second)}); } impl() : default_backends_(32, -1) {} @@ -48,39 +48,40 @@ namespace boost { namespace locale { localization_backend* create() const { - std::vector<std::shared_ptr<localization_backend>> backends; - for(unsigned i = 0; i < all_backends_.size(); i++) - backends.push_back(all_backends_[i].second); + std::vector<std::reference_wrapper<const localization_backend>> backends; + for(const auto& i : all_backends_) + backends.push_back(std::cref(*i.second)); return new actual_backend(backends, default_backends_); } - void adopt_backend(const std::string& name, localization_backend* backend_ptr) + + int find_backend(const std::string& name) const { - std::shared_ptr<localization_backend> sptr(backend_ptr); - if(all_backends_.empty()) { - all_backends_.push_back(std::make_pair(name, sptr)); - for(unsigned i = 0; i < default_backends_.size(); i++) - default_backends_[i] = 0; - } else { - for(unsigned i = 0; i < all_backends_.size(); i++) - if(all_backends_[i].first == name) - return; - all_backends_.push_back(std::make_pair(name, sptr)); + int id = 0; + for(const auto& i : all_backends_) { + if(i.first == name) + return id; + ++id; } + return -1; + } + + void add_backend(const std::string& name, std::unique_ptr<localization_backend> ptr) + { + if(all_backends_.empty()) + std::fill(default_backends_.begin(), default_backends_.end(), 0); + if(BOOST_LIKELY(find_backend(name) < 0)) + all_backends_.push_back(std::make_pair(name, std::move(ptr))); } void select(const std::string& backend_name, category_t category = all_categories) { - unsigned id; - for(id = 0; id < all_backends_.size(); ++id) { - if(all_backends_[id].first == backend_name) - break; - } - if(id == all_backends_.size()) - return; - category_t flag = category_first; - for(unsigned i = 0; i < default_backends_.size(); ++flag, ++i) { - if(category & flag) { - default_backends_[i] = id; + const int id = find_backend(backend_name); + if(id >= 0) { + category_t flag = category_first; + for(int& defBackend : default_backends_) { + if(category & flag) + defBackend = id; + ++flag; } } } @@ -88,42 +89,42 @@ namespace boost { namespace locale { void remove_all_backends() { all_backends_.clear(); - for(unsigned i = 0; i < default_backends_.size(); i++) { - default_backends_[i] = -1; - } + std::fill(default_backends_.begin(), default_backends_.end(), -1); } std::vector<std::string> get_all_backends() const { std::vector<std::string> res; - all_backends_type::const_iterator p; - for(p = all_backends_.begin(); p != all_backends_.end(); ++p) { - res.push_back(p->first); - } + for(const auto& i : all_backends_) + res.push_back(i.first); return res; } private: class actual_backend : public localization_backend { public: - actual_backend(const std::vector<std::shared_ptr<localization_backend>>& backends, + actual_backend(const std::vector<std::reference_wrapper<const localization_backend>>& backends, const std::vector<int>& index) : index_(index) { - backends_.resize(backends.size()); - for(unsigned i = 0; i < backends.size(); i++) { - backends_[i].reset(backends[i]->clone()); - } + for(const localization_backend& b : backends) + backends_.push_back(boost::locale::clone(b)); + } + actual_backend* clone() const override + { + std::vector<std::reference_wrapper<const localization_backend>> backends; + for(const auto& b : backends_) + backends.push_back(std::cref(*b)); + return new actual_backend(backends, index_); } - actual_backend* clone() const override { return new actual_backend(backends_, index_); } void set_option(const std::string& name, const std::string& value) override { - for(unsigned i = 0; i < backends_.size(); i++) - backends_[i]->set_option(name, value); + for(const auto& b : backends_) + b->set_option(name, value); } void clear_options() override { - for(unsigned i = 0; i < backends_.size(); i++) - backends_[i]->clear_options(); + for(const auto& b : backends_) + b->clear_options(); } std::locale install(const std::locale& l, category_t category, char_facet_t type) override { @@ -138,12 +139,11 @@ namespace boost { namespace locale { } private: - std::vector<std::shared_ptr<localization_backend>> backends_; + std::vector<std::unique_ptr<localization_backend>> backends_; std::vector<int> index_; }; - typedef std::vector<std::pair<std::string, std::shared_ptr<localization_backend>>> all_backends_type; - all_backends_type all_backends_; + std::vector<std::pair<std::string, std::unique_ptr<localization_backend>>> all_backends_; std::vector<int> default_backends_; }; @@ -161,23 +161,18 @@ namespace boost { namespace locale { return *this; } - std::unique_ptr<localization_backend> localization_backend_manager::get() const + localization_backend_manager::localization_backend_manager(localization_backend_manager&&) noexcept = default; + localization_backend_manager& + localization_backend_manager::operator=(localization_backend_manager&&) noexcept = default; + + std::unique_ptr<localization_backend> localization_backend_manager::create() const { return std::unique_ptr<localization_backend>(pimpl_->create()); } void localization_backend_manager::add_backend(const std::string& name, std::unique_ptr<localization_backend> backend) { - pimpl_->adopt_backend(name, backend.release()); - } - - localization_backend* localization_backend_manager::create() const - { - return pimpl_->create(); - } - void localization_backend_manager::adopt_backend(const std::string& name, localization_backend* backend) - { - pimpl_->adopt_backend(name, backend); + pimpl_->add_backend(name, std::move(backend)); } void localization_backend_manager::remove_all_backends() @@ -194,56 +189,49 @@ namespace boost { namespace locale { } namespace { - // prevent initialization order fiasco - boost::mutex& localization_backend_manager_mutex() + localization_backend_manager make_default_backend_mgr() { - static boost::mutex the_mutex; - return the_mutex; - } - // prevent initialization order fiasco - localization_backend_manager& localization_backend_manager_global() - { - static localization_backend_manager the_manager; - return the_manager; - } - - struct init { - init() - { - localization_backend_manager mgr; + localization_backend_manager mgr; #ifdef BOOST_LOCALE_WITH_ICU - mgr.adopt_backend("icu", impl_icu::create_localization_backend()); + mgr.add_backend("icu", impl_icu::create_localization_backend()); #endif #ifndef BOOST_LOCALE_NO_POSIX_BACKEND - mgr.adopt_backend("posix", impl_posix::create_localization_backend()); + mgr.add_backend("posix", impl_posix::create_localization_backend()); #endif #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND - mgr.adopt_backend("winapi", impl_win::create_localization_backend()); + mgr.add_backend("winapi", impl_win::create_localization_backend()); #endif #ifndef BOOST_LOCALE_NO_STD_BACKEND - mgr.adopt_backend("std", impl_std::create_localization_backend()); + mgr.add_backend("std", impl_std::create_localization_backend()); #endif - localization_backend_manager::global(mgr); - } - } do_init; + return mgr; + } + + boost::mutex& localization_backend_manager_mutex() + { + static boost::mutex the_mutex; + return the_mutex; + } + localization_backend_manager& localization_backend_manager_global() + { + static localization_backend_manager the_manager = make_default_backend_mgr(); + return the_manager; + } } // namespace localization_backend_manager localization_backend_manager::global() { boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex()); - localization_backend_manager mgr = localization_backend_manager_global(); - return mgr; + return localization_backend_manager_global(); } localization_backend_manager localization_backend_manager::global(const localization_backend_manager& in) { boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex()); - localization_backend_manager mgr = localization_backend_manager_global(); - localization_backend_manager_global() = in; - return mgr; + return exchange(localization_backend_manager_global(), in); } }} // namespace boost::locale diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp index 424e77a197..75dd905b09 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/message.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -15,154 +16,188 @@ # endif #endif -#include <boost/locale/encoding.hpp> #include <boost/locale/gnu_gettext.hpp> -#include <boost/locale/hold_ptr.hpp> + +#include <boost/locale/encoding.hpp> #include <boost/locale/message.hpp> #include "boost/locale/shared/mo_hash.hpp" #include "boost/locale/shared/mo_lambda.hpp" #include "boost/locale/util/encoding.hpp" -#include <boost/version.hpp> -#include <algorithm> +#include "boost/locale/util/foreach_char.hpp" +#include <boost/assert.hpp> +#include <boost/utility/string_view.hpp> #include <cstdio> -#include <cstring> -#include <iostream> #include <map> #include <memory> +#include <stdexcept> #include <unordered_map> #include <vector> namespace boost { namespace locale { namespace gnu_gettext { - class c_file { - c_file(const c_file&); - void operator=(const c_file&); + std::vector<std::string> messages_info::get_lang_folders() const + { + // List of fallbacks: en_US@euro, en@euro, en_US, en. + std::vector<std::string> result; + if(!language.empty()) { + if(!variant.empty() && !country.empty()) + result.push_back(language + "_" + country + "@" + variant); + + if(!variant.empty()) + result.push_back(language + "@" + variant); + if(!country.empty()) + result.push_back(language + "_" + country); + + result.push_back(language); + } + return result; + } + + std::vector<std::string> messages_info::get_catalog_paths() const + { + const auto lang_folders = get_lang_folders(); + std::vector<std::string> result; + result.reserve(lang_folders.size() * paths.size()); + for(const std::string& lang_folder : lang_folders) { + for(const std::string& search_path : paths) + result.push_back(search_path + "/" + lang_folder + "/" + locale_category); + } + return result; + } + + class c_file { public: - FILE* file; + FILE* handle; - c_file() : file(0) {} - ~c_file() { close(); } + c_file(const c_file&) = delete; + void operator=(const c_file&) = delete; - void close() + ~c_file() { - if(file) { - fclose(file); - file = 0; - } + if(handle) + fclose(handle); } #if defined(BOOST_WINDOWS) - bool open(const std::string& file_name, const std::string& encoding) + c_file(const std::string& file_name, const std::string& encoding) { - close(); - - // Under windows we have to use "_wfopen" to get - // access to path's with Unicode in them + // Under windows we have to use "_wfopen" to get access to path's with Unicode in them // // As not all standard C++ libraries support nonstandard std::istream::open(wchar_t const *) // we would use old and good stdio and _wfopen CRTL functions std::wstring wfile_name = conv::to_utf<wchar_t>(file_name, encoding); - file = _wfopen(wfile_name.c_str(), L"rb"); - - return file != 0; + handle = _wfopen(wfile_name.c_str(), L"rb"); } #else // POSIX systems do not have all this Wide API crap, as native codepages are UTF-8 // We do not use encoding as we use native file name encoding - bool open(const std::string& file_name, const std::string& /* encoding */) - { - close(); - - file = fopen(file_name.c_str(), "rb"); - - return file != 0; - } - + c_file(const std::string& file_name, const std::string& /* encoding */) : handle(fopen(file_name.c_str(), "rb")) + {} #endif }; + std::vector<char> read_file(FILE* file) + { + fseek(file, 0, SEEK_END); + const auto len = ftell(file); + if(BOOST_UNLIKELY(len < 0)) + throw std::runtime_error("Wrong file object"); // LCOV_EXCL_LINE + else { + fseek(file, 0, SEEK_SET); + std::vector<char> data(len); + if(BOOST_LIKELY(!data.empty()) && fread(data.data(), 1, data.size(), file) != data.size()) + throw std::runtime_error("Failed to read file"); // LCOV_EXCL_LINE + return data; + } + } + class mo_file { public: - typedef std::pair<const char*, const char*> pair_type; - - mo_file(std::vector<char>& file) : native_byteorder_(true), size_(0) + mo_file(std::vector<char> data) : data_(std::move(data)) { - load_file(file); - init(); - } + if(data_.size() < 4) + throw std::runtime_error("invalid 'mo' file format - the file is too short"); + uint32_t magic; + static_assert(sizeof(magic) == 4, "!"); + memcpy(&magic, data_.data(), sizeof(magic)); + if(magic == 0x950412de) + native_byteorder_ = true; + else if(magic == 0xde120495) + native_byteorder_ = false; + else + throw std::runtime_error("Invalid file format - invalid magic number"); - mo_file(FILE* file) : native_byteorder_(true), size_(0) - { - load_file(file); - init(); + // Read all format sizes + size_ = get(8); + keys_offset_ = get(12); + translations_offset_ = get(16); + hash_size_ = get(20); + hash_offset_ = get(24); } - pair_type find(const char* context_in, const char* key_in) const + string_view find(const char* context_in, const char* key_in) const { - pair_type null_pair((const char*)0, (const char*)0); - if(hash_size_ == 0) - return null_pair; - uint32_t hkey = 0; - if(context_in == 0) - hkey = pj_winberger_hash_function(key_in); - else { - pj_winberger_hash::state_type st = pj_winberger_hash::initial_state; + if(!has_hash()) + return {}; + + pj_winberger_hash::state_type st = pj_winberger_hash::initial_state; + if(context_in) { st = pj_winberger_hash::update_state(st, context_in); st = pj_winberger_hash::update_state(st, '\4'); // EOT - st = pj_winberger_hash::update_state(st, key_in); - hkey = st; } - uint32_t incr = 1 + hkey % (hash_size_ - 2); + st = pj_winberger_hash::update_state(st, key_in); + uint32_t hkey = st; + const uint32_t incr = 1 + hkey % (hash_size_ - 2); hkey %= hash_size_; - uint32_t orig = hkey; + const uint32_t orig_hkey = hkey; do { - uint32_t idx = get(hash_offset_ + 4 * hkey); - /// Not found + const uint32_t idx = get(hash_offset_ + 4 * hkey); + // Not found if(idx == 0) - return null_pair; - /// If equal values return translation + return {}; + // If equal values return translation if(key_equals(key(idx - 1), context_in, key_in)) return value(idx - 1); - /// Rehash + // Rehash hkey = (hkey + incr) % hash_size_; - } while(hkey != orig); - return null_pair; + } while(hkey != orig_hkey); + return {}; } static bool key_equals(const char* real_key, const char* cntx, const char* key) { - if(cntx == 0) + if(!cntx) return strcmp(real_key, key) == 0; else { - size_t real_len = strlen(real_key); - size_t cntx_len = strlen(cntx); - size_t key_len = strlen(key); - if(cntx_len + 1 + key_len != real_len) + const size_t real_key_len = strlen(real_key); + const size_t cntx_len = strlen(cntx); + const size_t key_len = strlen(key); + if(cntx_len + 1 + key_len != real_key_len) return false; return memcmp(real_key, cntx, cntx_len) == 0 && real_key[cntx_len] == '\4' && memcmp(real_key + cntx_len + 1, key, key_len) == 0; } } - const char* key(int id) const + const char* key(unsigned id) const { - uint32_t off = get(keys_offset_ + id * 8 + 4); - return data_ + off; + const uint32_t off = get(keys_offset_ + id * 8 + 4); + return data_.data() + off; } - pair_type value(int id) const + string_view value(unsigned id) const { - uint32_t len = get(translations_offset_ + id * 8); - uint32_t off = get(translations_offset_ + id * 8 + 4); - if(off >= file_size_ || off + len >= file_size_) + const uint32_t len = get(translations_offset_ + id * 8); + const uint32_t off = get(translations_offset_ + id * 8 + 4); + if(len > data_.size() || off > data_.size() - len) throw std::runtime_error("Bad mo-file format"); - return pair_type(&data_[off], &data_[off] + len); + return string_view(&data_[off], len); } bool has_hash() const { return hash_size_ != 0; } @@ -172,77 +207,16 @@ namespace boost { namespace locale { namespace gnu_gettext { bool empty() { return size_ == 0; } private: - void init() - { - // Read all format sizes - size_ = get(8); - keys_offset_ = get(12); - translations_offset_ = get(16); - hash_size_ = get(20); - hash_offset_ = get(24); - } - - void load_file(std::vector<char>& data) - { - vdata_.swap(data); - file_size_ = vdata_.size(); - data_ = &vdata_[0]; - if(file_size_ < 4) - throw std::runtime_error("invalid 'mo' file format - the file is too short"); - uint32_t magic = 0; - memcpy(&magic, data_, 4); - if(magic == 0x950412de) - native_byteorder_ = true; - else if(magic == 0xde120495) - native_byteorder_ = false; - else - throw std::runtime_error("Invalid file format - invalid magic number"); - } - - void load_file(FILE* file) - { - uint32_t magic = 0; - // if the size is wrong magic would be wrong - // ok to ignore fread result - size_t four_bytes = fread(&magic, 4, 1, file); - (void)four_bytes; // shut GCC - - if(magic == 0x950412de) - native_byteorder_ = true; - else if(magic == 0xde120495) - native_byteorder_ = false; - else - throw std::runtime_error("Invalid file format"); - - fseek(file, 0, SEEK_END); - long len = ftell(file); - if(len < 0) { - throw std::runtime_error("Wrong file object"); - } - fseek(file, 0, SEEK_SET); - vdata_.resize(len + 1, 0); // +1 to make sure the vector is not empty - if(fread(&vdata_.front(), 1, len, file) != unsigned(len)) - throw std::runtime_error("Failed to read file"); - data_ = &vdata_[0]; - file_size_ = len; - } - uint32_t get(unsigned offset) const { - uint32_t tmp; - if(offset > file_size_ - 4) { + if(offset > data_.size() - 4) throw std::runtime_error("Bad mo-file format"); - } - memcpy(&tmp, data_ + offset, 4); - convert(tmp); - return tmp; - } + uint32_t v; + memcpy(&v, &data_[offset], 4); + if(!native_byteorder_) + v = ((v & 0xFF) << 24) | ((v & 0xFF00) << 8) | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24); - void convert(uint32_t& v) const - { - if(native_byteorder_) - return; - v = ((v & 0xFF) << 24) | ((v & 0xFF00) << 8) | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24); + return v; } uint32_t keys_offset_; @@ -250,9 +224,7 @@ namespace boost { namespace locale { namespace gnu_gettext { uint32_t hash_size_; uint32_t hash_offset_; - const char* data_; - size_t file_size_; - std::vector<char> vdata_; + const std::vector<char> data_; bool native_byteorder_; size_t size_; }; @@ -260,76 +232,67 @@ namespace boost { namespace locale { namespace gnu_gettext { template<typename CharType> struct mo_file_use_traits { static constexpr bool in_use = false; - typedef CharType char_type; - typedef std::pair<const char_type*, const char_type*> pair_type; - static pair_type use(const mo_file& /*mo*/, const char_type* /*context*/, const char_type* /*key*/) + using string_view_type = basic_string_view<CharType>; + static string_view_type use(const mo_file&, const CharType*, const CharType*) { - return pair_type((const char_type*)(0), (const char_type*)(0)); + throw std::logic_error("Unexpected call"); // LCOV_EXCL_LINE } }; template<> struct mo_file_use_traits<char> { static constexpr bool in_use = true; - typedef char char_type; - typedef std::pair<const char_type*, const char_type*> pair_type; - static pair_type use(const mo_file& mo, const char* context, const char* key) { return mo.find(context, key); } + typedef char CharType; + using string_view_type = basic_string_view<CharType>; + static string_view_type use(const mo_file& mo, const char* context, const char* key) + { + return mo.find(context, key); + } }; template<typename CharType> - class converter { - public: - converter(std::string /*out_enc*/, std::string in_enc) : in_(in_enc) {} + class converter : conv::utf_encoder<CharType> { + using encoder = conv::utf_encoder<CharType>; - std::basic_string<CharType> operator()(const char* begin, const char* end) - { - return conv::to_utf<CharType>(begin, end, in_, conv::stop); - } + public: + converter(std::string /*out_enc*/, std::string in_enc) : encoder(in_enc, conv::stop) {} - private: - std::string in_; + using encoder::operator(); }; template<> - class converter<char> { + class converter<char> : conv::narrow_converter { public: - converter(std::string out_enc, std::string in_enc) : out_(out_enc), in_(in_enc) {} - - std::string operator()(const char* begin, const char* end) - { - return conv::between(begin, end, out_, in_, conv::stop); - } + converter(const std::string& out_enc, const std::string& in_enc) : narrow_converter(in_enc, out_enc) {} - private: - std::string out_, in_; + using narrow_converter::operator(); }; template<typename CharType> struct message_key { - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; - message_key(const string_type& c = string_type()) : c_context_(0), c_key_(0) + message_key(const string_type& c = string_type()) : c_context_(nullptr), c_key_(nullptr) { - size_t pos = c.find(char_type(4)); - if(pos == string_type::npos) { + const size_t pos = c.find(CharType(4)); + if(pos == string_type::npos) key_ = c; - } else { + else { context_ = c.substr(0, pos); key_ = c.substr(pos + 1); } } - message_key(const char_type* c, const char_type* k) : c_key_(k) + message_key(const CharType* c, const CharType* k) : c_key_(k) { - static const char_type empty = 0; - if(c != 0) + static const CharType empty = 0; + if(c != nullptr) c_context_ = c; else c_context_ = ∅ } bool operator<(const message_key& other) const { - int cc = compare(context(), other.context()); + const int cc = compare(context(), other.context()); if(cc != 0) return cc < 0; return compare(key(), other.key()) < 0; @@ -339,13 +302,13 @@ namespace boost { namespace locale { namespace gnu_gettext { return compare(context(), other.context()) == 0 && compare(key(), other.key()) == 0; } bool operator!=(const message_key& other) const { return !(*this == other); } - const char_type* context() const + const CharType* context() const { if(c_context_) return c_context_; return context_.c_str(); } - const char_type* key() const + const CharType* key() const { if(c_key_) return c_key_; @@ -353,12 +316,12 @@ namespace boost { namespace locale { namespace gnu_gettext { } private: - static int compare(const char_type* l, const char_type* r) + static int compare(const CharType* l, const CharType* r) { - typedef std::char_traits<char_type> traits_type; + typedef std::char_traits<CharType> traits_type; for(;;) { - char_type cl = *l++; - char_type cr = *r++; + const CharType cl = *l++; + const CharType cr = *r++; if(cl == 0 && cr == 0) return 0; if(traits_type::lt(cl, cr)) @@ -369,8 +332,8 @@ namespace boost { namespace locale { namespace gnu_gettext { } string_type context_; string_type key_; - const char_type* c_context_; - const char_type* c_key_; + const CharType* c_context_; + const CharType* c_key_; }; template<typename CharType> @@ -418,54 +381,57 @@ namespace boost { namespace locale { namespace gnu_gettext { return msg; if(detail::is_us_ascii_string(msg)) return msg; - std::string tmp = conv::between(msg, locale_encoding, key_encoding, conv::skip); - buffer.swap(tmp); + buffer = conv::between(msg, locale_encoding, key_encoding, conv::skip); return buffer.c_str(); } template<typename CharType> class mo_message : public message_format<CharType> { - typedef CharType char_type; typedef std::basic_string<CharType> string_type; typedef message_key<CharType> key_type; typedef std::unordered_map<key_type, string_type, hash_function<CharType>> catalog_type; - typedef std::vector<catalog_type> catalogs_set_type; - typedef std::map<std::string, int> domains_map_type; + struct domain_data_type { + std::unique_ptr<mo_file> mo_catalog; /// Message catalog (.mo file) if it can be directly used + catalog_type catalog; /// Converted message catalog when .mo file cannot be directly used + lambda::plural_expr plural_form; /// Expression to determine the plural form index + }; public: - typedef std::pair<const CharType*, const CharType*> pair_type; + using string_view_type = typename mo_file_use_traits<CharType>::string_view_type; - const char_type* get(int domain_id, const char_type* context, const char_type* in_id) const override + const CharType* get(int domain_id, const CharType* context, const CharType* in_id) const override { - return get_string(domain_id, context, in_id).first; + const auto result = get_string(domain_id, context, in_id); + return result.empty() ? nullptr : result.data(); } - const char_type* get(int domain_id, const char_type* context, const char_type* single_id, int n) const override + const CharType* + get(int domain_id, const CharType* context, const CharType* single_id, count_type n) const override { - pair_type ptr = get_string(domain_id, context, single_id); - if(!ptr.first) + auto result = get_string(domain_id, context, single_id); + if(result.empty()) return nullptr; - int form = 0; - if(plural_forms_.at(domain_id)) - form = (*plural_forms_[domain_id])(n); + + // domain_id is already checked by get_string -> Would return a null-pair + BOOST_ASSERT(domain_id >= 0 && static_cast<size_t>(domain_id) < domain_data_.size()); + lambda::expr::value_type plural_idx; + if(domain_data_[domain_id].plural_form) + plural_idx = domain_data_[domain_id].plural_form(n); else - form = n == 1 ? 0 : 1; // Fallback to English plural form + plural_idx = n == 1 ? 0 : 1; // Fallback to English plural form - const CharType* p = ptr.first; - for(int i = 0; p < ptr.second && i < form; i++) { - p = std::find(p, ptr.second, CharType(0)); - if(p == ptr.second) + for(decltype(plural_idx) i = 0; i < plural_idx; ++i) { + const auto pos = result.find(CharType(0)); + if(BOOST_UNLIKELY(pos == string_view_type::npos)) return nullptr; - ++p; + result.remove_prefix(pos + 1); } - if(p >= ptr.second) - return nullptr; - return p; + return result.empty() ? nullptr : result.data(); } int domain(const std::string& domain) const override { - domains_map_type::const_iterator p = domains_.find(domain); + const auto p = domains_.find(domain); if(p == domains_.end()) return -1; return p->second; @@ -473,61 +439,32 @@ namespace boost { namespace locale { namespace gnu_gettext { mo_message(const messages_info& inf) : key_conversion_required_(false) { - std::string language = inf.language; - std::string variant = inf.variant; - std::string country = inf.country; - std::string encoding = inf.encoding; - std::string lc_cat = inf.locale_category; const std::vector<messages_info::domain>& domains = inf.domains; - const std::vector<std::string>& search_paths = inf.paths; - - // List of fallbacks: en_US@euro, en@euro, en_US, en. - std::vector<std::string> paths; - - if(!variant.empty() && !country.empty()) - paths.push_back(language + "_" + country + "@" + variant); - - if(!variant.empty()) - paths.push_back(language + "@" + variant); - - if(!country.empty()) - paths.push_back(language + "_" + country); - - paths.push_back(language); - - catalogs_.resize(domains.size()); - mo_catalogs_.resize(domains.size()); - plural_forms_.resize(domains.size()); + domain_data_.resize(domains.size()); + const auto catalog_paths = inf.get_catalog_paths(); for(unsigned i = 0; i < domains.size(); i++) { - std::string domain = domains[i].name; - std::string key_encoding = domains[i].encoding; - domains_[domain] = i; - - bool found = false; - for(unsigned j = 0; !found && j < paths.size(); j++) { - for(unsigned k = 0; !found && k < search_paths.size(); k++) { - std::string full_path = search_paths[k] + "/" + paths[j] + "/" + lc_cat + "/" + domain + ".mo"; - found = load_file(full_path, encoding, key_encoding, i, inf.callback); - } + const auto& domain = domains[i]; + domains_[domain.name] = i; + const std::string filename = domain.name + ".mo"; + for(std::string path : catalog_paths) { + path += "/" + filename; + if(load_file(path, inf.encoding, domain.encoding, domain_data_[i], inf.callback)) + break; } } } - const char_type* convert(const char_type* msg, string_type& buffer) const override + const CharType* convert(const CharType* msg, string_type& buffer) const override { - return runtime_conversion<char_type>(msg, - buffer, - key_conversion_required_, - locale_encoding_, - key_encoding_); + return runtime_conversion<CharType>(msg, buffer, key_conversion_required_, locale_encoding_, key_encoding_); } private: bool load_file(const std::string& file_name, const std::string& locale_encoding, const std::string& key_encoding, - int idx, + domain_data_type& data, const messages_info::callback_type& callback) { locale_encoding_ = locale_encoding; @@ -536,44 +473,42 @@ namespace boost { namespace locale { namespace gnu_gettext { key_conversion_required_ = sizeof(CharType) == 1 && !util::are_encodings_equal(locale_encoding, key_encoding); - std::shared_ptr<mo_file> mo; - - if(callback) { - std::vector<char> vfile = callback(file_name, locale_encoding); - if(vfile.empty()) - return false; - mo.reset(new mo_file(vfile)); - } else { - c_file the_file; - the_file.open(file_name, locale_encoding); - if(!the_file.file) + std::unique_ptr<mo_file> mo; + + { + std::vector<char> file_data; + if(callback) + file_data = callback(file_name, locale_encoding); + else { + c_file the_file(file_name, locale_encoding); + if(!the_file.handle) + return false; + file_data = read_file(the_file.handle); + } + if(file_data.empty()) return false; - mo.reset(new mo_file(the_file.file)); + mo.reset(new mo_file(std::move(file_data))); } - std::string plural = extract(mo->value(0).first, "plural=", "\r\n;"); - - std::string mo_encoding = extract(mo->value(0).first, "charset=", " \r\n;"); + const std::string plural = extract(mo->value(0), "plural=", "\r\n;"); + const std::string mo_encoding = extract(mo->value(0), "charset=", " \r\n;"); if(mo_encoding.empty()) throw std::runtime_error("Invalid mo-format, encoding is not specified"); if(!plural.empty()) - plural_forms_[idx] = lambda::compile(plural.c_str()); + data.plural_form = lambda::compile(plural.c_str()); if(mo_useable_directly(mo_encoding, *mo)) - mo_catalogs_[idx] = mo; + data.mo_catalog = std::move(mo); else { converter<CharType> cvt_value(locale_encoding, mo_encoding); converter<CharType> cvt_key(key_encoding, mo_encoding); for(unsigned i = 0; i < mo->size(); i++) { const char* ckey = mo->key(i); - string_type skey = cvt_key(ckey, ckey + strlen(ckey)); - key_type key(skey); + const key_type key(cvt_key(ckey)); - mo_file::pair_type tmp = mo->value(i); - string_type value = cvt_value(tmp.first, tmp.second); - catalogs_[idx][key].swap(value); + data.catalog[key] = cvt_value(mo->value(i)); } } return true; @@ -594,85 +529,62 @@ namespace boost { namespace locale { namespace gnu_gettext { return false; if(!util::are_encodings_equal(mo_encoding, locale_encoding_)) return false; - if(util::are_encodings_equal(mo_encoding, key_encoding_)) { + if(util::are_encodings_equal(mo_encoding, key_encoding_)) return true; - } for(unsigned i = 0; i < mo.size(); i++) { - if(!detail::is_us_ascii_string(mo.key(i))) { + if(!detail::is_us_ascii_string(mo.key(i))) return false; - } } return true; } - static std::string extract(const std::string& meta, const std::string& key, const char* separator) + static std::string extract(boost::string_view meta, const std::string& key, const boost::string_view separators) { - size_t pos = meta.find(key); - if(pos == std::string::npos) + const size_t pos = meta.find(key); + if(pos == boost::string_view::npos) return ""; - pos += key.size(); /// size of charset= - size_t end_pos = meta.find_first_of(separator, pos); - return meta.substr(pos, end_pos - pos); + meta.remove_prefix(pos + key.size()); + const size_t end_pos = meta.find_first_of(separators); + return std::string(meta.substr(0, end_pos)); } - pair_type get_string(int domain_id, const char_type* context, const char_type* in_id) const + string_view_type get_string(int domain_id, const CharType* context, const CharType* in_id) const { - pair_type null_pair((const CharType*)0, (const CharType*)0); - if(domain_id < 0 || size_t(domain_id) >= catalogs_.size()) - return null_pair; + if(domain_id < 0 || static_cast<size_t>(domain_id) >= domain_data_.size()) + return {}; + const auto& data = domain_data_[domain_id]; + BOOST_LOCALE_START_CONST_CONDITION - if(mo_file_use_traits<char_type>::in_use && mo_catalogs_[domain_id]) { + if(mo_file_use_traits<CharType>::in_use && data.mo_catalog) { BOOST_LOCALE_END_CONST_CONDITION - return mo_file_use_traits<char_type>::use(*mo_catalogs_[domain_id], context, in_id); + return mo_file_use_traits<CharType>::use(*data.mo_catalog, context, in_id); } else { - key_type key(context, in_id); - const catalog_type& cat = catalogs_[domain_id]; - typename catalog_type::const_iterator p = cat.find(key); - if(p == cat.end()) { - return null_pair; - } - return pair_type(p->second.data(), p->second.data() + p->second.size()); + const key_type key(context, in_id); + const catalog_type& cat = data.catalog; + const auto p = cat.find(key); + if(p == cat.end()) + return {}; + return p->second; } } - catalogs_set_type catalogs_; - std::vector<std::shared_ptr<mo_file>> mo_catalogs_; - std::vector<std::shared_ptr<lambda::plural>> plural_forms_; - domains_map_type domains_; + std::map<std::string, unsigned> domains_; + std::vector<domain_data_type> domain_data_; std::string locale_encoding_; std::string key_encoding_; bool key_conversion_required_; }; - template<> - message_format<char>* create_messages_facet(const messages_info& info) - { - return new mo_message<char>(info); - } - - template<> - message_format<wchar_t>* create_messages_facet(const messages_info& info) - { - return new mo_message<wchar_t>(info); - } - -#ifdef BOOST_LOCALE_ENABLE_CHAR16_T - - template<> - message_format<char16_t>* create_messages_facet(const messages_info& info) + template<typename CharType, class /* enable_if */> + message_format<CharType>* create_messages_facet(const messages_info& info) { - return new mo_message<char16_t>(info); + return new mo_message<CharType>(info); } -#endif -#ifdef BOOST_LOCALE_ENABLE_CHAR32_T +#define BOOST_LOCALE_INSTANTIATE(CHARTYPE) \ + template BOOST_LOCALE_DECL message_format<CHARTYPE>* create_messages_facet(const messages_info& info); - template<> - message_format<char32_t>* create_messages_facet(const messages_info& info) - { - return new mo_message<char32_t>(info); - } -#endif + BOOST_LOCALE_FOREACH_CHAR(BOOST_LOCALE_INSTANTIATE) }}} // namespace boost::locale::gnu_gettext diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp index ad417641f9..702ea7aece 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_hash.hpp @@ -4,7 +4,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include <boost/cstdint.hpp> +#include <cstdint> namespace boost { namespace locale { namespace gnu_gettext { diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp index 90d0c232cb..a6d2eb6a44 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.cpp @@ -1,12 +1,18 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include "boost/locale/shared/mo_lambda.hpp" +#include <boost/assert.hpp> +#include <algorithm> #include <cstdlib> #include <cstring> +#include <functional> +#include <limits> +#include <stdexcept> #ifdef BOOST_MSVC # pragma warning(disable : 4512) // assignment operator could not be generated @@ -15,359 +21,283 @@ namespace boost { namespace locale { namespace gnu_gettext { namespace lambda { namespace { // anon - struct identity : public plural { - int operator()(int n) const override { return n; }; - identity* clone() const override { return new identity(); } + template<class TExp, typename... Ts> + expr_ptr make_expr(Ts... ts) + { + return expr_ptr(new TExp(std::forward<Ts>(ts)...)); + } + + struct identity final : expr { + value_type operator()(value_type n) const override { return n; } }; - struct unary : public plural { - unary(plural_ptr ptr) : op1(ptr) {} + using sub_expr_type = plural_expr; + + template<class Functor> + struct unary final : expr, Functor { + unary(expr_ptr p) : op1(std::move(p)) {} + value_type operator()(value_type n) const override { return Functor::operator()(op1(n)); } protected: - plural_ptr op1; + sub_expr_type op1; }; - struct binary : public plural { - binary(plural_ptr p1, plural_ptr p2) : op1(p1), op2(p2) {} + template<class Functor, bool returnZeroOnZero2ndArg = false> + struct binary final : expr, Functor { + binary(expr_ptr p1, expr_ptr p2) : op1(std::move(p1)), op2(std::move(p2)) {} + value_type operator()(value_type n) const override + { + const auto v1 = op1(n); + const auto v2 = op2(n); + BOOST_LOCALE_START_CONST_CONDITION + if(returnZeroOnZero2ndArg && v2 == 0) + return 0; + BOOST_LOCALE_END_CONST_CONDITION + return Functor::operator()(v1, v2); + } protected: - plural_ptr op1, op2; + sub_expr_type op1, op2; }; - struct number : public plural { - number(int v) : val(v) {} - int operator()(int /*n*/) const override { return val; } - number* clone() const override { return new number(val); } + struct number final : expr { + number(value_type v) : val(v) {} + value_type operator()(value_type /*n*/) const override { return val; } private: - int val; + value_type val; }; -#define UNOP(name, oper) \ - struct name : public unary { \ - name(plural_ptr op) : unary(op) {} \ - int operator()(int n) const override { return oper(*op1)(n); } \ - name* clone() const override \ - { \ - plural_ptr op1_copy(op1->clone()); \ - return new name(op1_copy); \ - } \ - }; - -#define BINOP(name, oper) \ - struct name : public binary { \ - name(plural_ptr p1, plural_ptr p2) : binary(p1, p2) {} \ - \ - int operator()(int n) const override { return (*op1)(n)oper(*op2)(n); } \ - name* clone() const override \ - { \ - plural_ptr op1_copy(op1->clone()); \ - plural_ptr op2_copy(op2->clone()); \ - return new name(op1_copy, op2_copy); \ - } \ - }; - -#define BINOPD(name, oper) \ - struct name : public binary { \ - name(plural_ptr p1, plural_ptr p2) : binary(p1, p2) {} \ - int operator()(int n) const override \ - { \ - int v1 = (*op1)(n); \ - int v2 = (*op2)(n); \ - return v2 == 0 ? 0 : v1 oper v2; \ - } \ - name* clone() const override \ - { \ - plural_ptr op1_copy(op1->clone()); \ - plural_ptr op2_copy(op2->clone()); \ - return new name(op1_copy, op2_copy); \ - } \ - }; - - enum { END = 0, SHL = 256, SHR, GTE, LTE, EQ, NEQ, AND, OR, NUM, VARIABLE }; - - UNOP(l_not, !) - UNOP(minus, -) - UNOP(bin_not, ~) - - BINOP(mul, *) - BINOPD(div, /) - BINOPD(mod, %) - static int level10[] = {3, '*', '/', '%'}; - - BINOP(add, +) - BINOP(sub, -) - static int level9[] = {2, '+', '-'}; - - BINOP(shl, <<) - BINOP(shr, >>) - static int level8[] = {2, SHL, SHR}; - - BINOP(gt, >) - BINOP(lt, <) - BINOP(gte, >=) - BINOP(lte, <=) - static int level7[] = {4, '<', '>', GTE, LTE}; - - BINOP(eq, ==) - BINOP(neq, !=) - static int level6[] = {2, EQ, NEQ}; - - BINOP(bin_and, &) - static int level5[] = {1, '&'}; - - BINOP(bin_xor, ^) - static int level4[] = {1, '^'}; - - BINOP(bin_or, |) - static int level3[] = {1, '|'}; - - BINOP(l_and, &&) - static int level2[] = {1, AND}; - - BINOP(l_or, ||) - static int level1[] = {1, OR}; - - struct conditional : public plural { - conditional(plural_ptr p1, plural_ptr p2, plural_ptr p3) : op1(p1), op2(p2), op3(p3) {} - int operator()(int n) const override { return (*op1)(n) ? (*op2)(n) : (*op3)(n); } - conditional* clone() const override - { - plural_ptr op1_copy(op1->clone()); - plural_ptr op2_copy(op2->clone()); - plural_ptr op3_copy(op3->clone()); - return new conditional(op1_copy, op2_copy, op3_copy); - } + struct conditional final : public expr { + conditional(expr_ptr p1, expr_ptr p2, expr_ptr p3) : + op1(std::move(p1)), op2(std::move(p2)), op3(std::move(p3)) + {} + value_type operator()(value_type n) const override { return op1(n) ? op2(n) : op3(n); } private: - plural_ptr op1, op2, op3; + sub_expr_type op1, op2, op3; }; - plural_ptr bin_factory(int value, plural_ptr left, plural_ptr right) + using token_t = int; + enum : token_t { END = 0, GTE = 256, LTE, EQ, NEQ, AND, OR, NUM, VARIABLE }; + + expr_ptr bin_factory(const token_t value, expr_ptr left, expr_ptr right) { +#define BINOP_CASE(match, cls) \ + case match: return make_expr<cls>(std::move(left), std::move(right)) + // Special cases: Avoid division by zero + using divides = binary<std::divides<expr::value_type>, true>; + using modulus = binary<std::modulus<expr::value_type>, true>; switch(value) { - case '/': return plural_ptr(new div(left, right)); - case '*': return plural_ptr(new mul(left, right)); - case '%': return plural_ptr(new mod(left, right)); - case '+': return plural_ptr(new add(left, right)); - case '-': return plural_ptr(new sub(left, right)); - case SHL: return plural_ptr(new shl(left, right)); - case SHR: return plural_ptr(new shr(left, right)); - case '>': return plural_ptr(new gt(left, right)); - case '<': return plural_ptr(new lt(left, right)); - case GTE: return plural_ptr(new gte(left, right)); - case LTE: return plural_ptr(new lte(left, right)); - case EQ: return plural_ptr(new eq(left, right)); - case NEQ: return plural_ptr(new neq(left, right)); - case '&': return plural_ptr(new bin_and(left, right)); - case '^': return plural_ptr(new bin_xor(left, right)); - case '|': return plural_ptr(new bin_or(left, right)); - case AND: return plural_ptr(new l_and(left, right)); - case OR: return plural_ptr(new l_or(left, right)); - default: return plural_ptr(); + BINOP_CASE('/', divides); + BINOP_CASE('*', binary<std::multiplies<expr::value_type>>); + BINOP_CASE('%', modulus); + BINOP_CASE('+', binary<std::plus<expr::value_type>>); + BINOP_CASE('-', binary<std::minus<expr::value_type>>); + BINOP_CASE('>', binary<std::greater<expr::value_type>>); + BINOP_CASE('<', binary<std::less<expr::value_type>>); + BINOP_CASE(GTE, binary<std::greater_equal<expr::value_type>>); + BINOP_CASE(LTE, binary<std::less_equal<expr::value_type>>); + BINOP_CASE(EQ, binary<std::equal_to<expr::value_type>>); + BINOP_CASE(NEQ, binary<std::not_equal_to<expr::value_type>>); + BINOP_CASE(AND, binary<std::logical_and<expr::value_type>>); + BINOP_CASE(OR, binary<std::logical_or<expr::value_type>>); + default: throw std::logic_error("Unexpected binary operator"); // LCOV_EXCL_LINE } +#undef BINOP_CASE } - static inline bool is_in(int v, int* p) + template<size_t size> + bool is_in(const token_t token, const token_t (&tokens)[size]) { - int len = *p; - p++; - while(len && *p != v) { - p++; - len--; + for(const auto el : tokens) { + if(token == el) + return true; } - return len != 0; + return false; } class tokenizer { public: - tokenizer(const char* s) + tokenizer(const char* s) : text_(s), next_tocken_(0), numeric_value_(0) { step(); } + token_t get(long long* val = nullptr) { - text = s; - pos = 0; + const token_t res = next(val); step(); - }; - int get(int* val = NULL) - { - int iv = int_value; - int res = next_tocken; - step(); - if(val && res == NUM) { - *val = iv; - } return res; - }; - int next(int* val = NULL) + } + token_t next(long long* val = nullptr) const { - if(val && next_tocken == NUM) { - *val = int_value; - return NUM; - } - return next_tocken; + if(val && next_tocken_ == NUM) + *val = numeric_value_; + return next_tocken_; } private: - const char* text; - size_t pos; - int next_tocken; - int int_value; - bool is_blank(char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } - bool isdigit(char c) { return '0' <= c && c <= '9'; } + const char* text_; + token_t next_tocken_; + long long numeric_value_; + + static constexpr bool is_blank(char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } + static constexpr bool is_digit(char c) { return '0' <= c && c <= '9'; } + template<size_t size> + static bool is(const char* s, const char (&search)[size]) + { + return strncmp(s, search, size - 1) == 0; + } void step() { - while(text[pos] && is_blank(text[pos])) - pos++; - const char* ptr = text + pos; - char* tmp_ptr; - if(strncmp(ptr, "<<", 2) == 0) { - pos += 2; - next_tocken = SHL; - } else if(strncmp(ptr, ">>", 2) == 0) { - pos += 2; - next_tocken = SHR; - } else if(strncmp(ptr, "&&", 2) == 0) { - pos += 2; - next_tocken = AND; - } else if(strncmp(ptr, "||", 2) == 0) { - pos += 2; - next_tocken = OR; - } else if(strncmp(ptr, "<=", 2) == 0) { - pos += 2; - next_tocken = LTE; - } else if(strncmp(ptr, ">=", 2) == 0) { - pos += 2; - next_tocken = GTE; - } else if(strncmp(ptr, "==", 2) == 0) { - pos += 2; - next_tocken = EQ; - } else if(strncmp(ptr, "!=", 2) == 0) { - pos += 2; - next_tocken = NEQ; - } else if(*ptr == 'n') { - pos++; - next_tocken = VARIABLE; - } else if(isdigit(*ptr)) { - int_value = strtol(text + pos, &tmp_ptr, 0); - pos = tmp_ptr - text; - next_tocken = NUM; - } else if(*ptr == '\0') { - next_tocken = 0; - } else { - next_tocken = *ptr; - pos++; + while(is_blank(*text_)) + text_++; + const char* text = text_; + if(is(text, "&&")) { + text_ += 2; + next_tocken_ = AND; + } else if(is(text, "||")) { + text_ += 2; + next_tocken_ = OR; + } else if(is(text, "<=")) { + text_ += 2; + next_tocken_ = LTE; + } else if(is(text, ">=")) { + text_ += 2; + next_tocken_ = GTE; + } else if(is(text, "==")) { + text_ += 2; + next_tocken_ = EQ; + } else if(is(text, "!=")) { + text_ += 2; + next_tocken_ = NEQ; + } else if(*text == 'n') { + text_++; + next_tocken_ = VARIABLE; + } else if(is_digit(*text)) { + char* tmp_ptr; + // strtoll not always available -> parse as unsigned long + const auto value = std::strtoul(text, &tmp_ptr, 10); + // Saturate in case long=long long + numeric_value_ = std::min<unsigned long long>(std::numeric_limits<long long>::max(), value); + text_ = tmp_ptr; + next_tocken_ = NUM; + } else if(*text == '\0') + next_tocken_ = END; + else { + next_tocken_ = *text; + text_++; } } }; -#define BINARY_EXPR(expr, hexpr, list) \ - plural_ptr expr() \ - { \ - plural_ptr op1, op2; \ - if((op1 = hexpr()).get() == 0) \ - return plural_ptr(); \ - while(is_in(t.next(), list)) { \ - int o = t.get(); \ - if((op2 = hexpr()).get() == 0) \ - return plural_ptr(); \ - op1 = bin_factory(o, op1, op2); \ - } \ - return op1; \ - } + constexpr token_t level6[] = {'*', '/', '%'}; + constexpr token_t level5[] = {'+', '-'}; + constexpr token_t level4[] = {'<', '>', GTE, LTE}; + constexpr token_t level3[] = {EQ, NEQ}; + constexpr token_t level2[] = {AND}; + constexpr token_t level1[] = {OR}; class parser { public: - parser(tokenizer& tin) : t(tin){}; + parser(const char* str) : t(str) {} - plural_ptr compile() + expr_ptr compile() { - plural_ptr res = cond_expr(); - if(res.get() && t.next() != END) { - return plural_ptr(); - }; + expr_ptr res = cond_expr(); + if(res && t.next() != END) + return expr_ptr(); return res; } private: - plural_ptr value_expr() + expr_ptr value_expr() { - plural_ptr op; + expr_ptr op; if(t.next() == '(') { t.get(); - if((op = cond_expr()).get() == 0) - return plural_ptr(); + if(!(op = cond_expr())) + return expr_ptr(); if(t.get() != ')') - return plural_ptr(); + return expr_ptr(); return op; } else if(t.next() == NUM) { - int value; + expr::value_type value; t.get(&value); - return plural_ptr(new number(value)); + return make_expr<number>(value); } else if(t.next() == VARIABLE) { t.get(); - return plural_ptr(new identity()); + return make_expr<identity>(); } - return plural_ptr(); - }; + return expr_ptr(); + } - plural_ptr un_expr() + expr_ptr unary_expr() { - plural_ptr op1; - static int level_unary[] = {3, '-', '!', '~'}; + constexpr token_t level_unary[] = {'!', '-'}; if(is_in(t.next(), level_unary)) { - int op = t.get(); - if((op1 = un_expr()).get() == 0) - return plural_ptr(); - switch(op) { - case '-': return plural_ptr(new minus(op1)); - case '!': return plural_ptr(new l_not(op1)); - case '~': return plural_ptr(new bin_not(op1)); - default: return plural_ptr(); + const token_t op = t.get(); + expr_ptr op1 = unary_expr(); + if(!op1) + return expr_ptr(); + if(BOOST_LIKELY(op == '!')) + return make_expr<unary<std::logical_not<expr::value_type>>>(std::move(op1)); + else { + BOOST_ASSERT(op == '-'); + return make_expr<unary<std::negate<expr::value_type>>>(std::move(op1)); } - } else { + } else return value_expr(); - } - }; + } + +#define BINARY_EXPR(lvl, nextLvl, list) \ + expr_ptr lvl() \ + { \ + expr_ptr op1 = nextLvl(); \ + if(!op1) \ + return expr_ptr(); \ + while(is_in(t.next(), list)) { \ + const token_t o = t.get(); \ + expr_ptr op2 = nextLvl(); \ + if(!op2) \ + return expr_ptr(); \ + op1 = bin_factory(o, std::move(op1), std::move(op2)); \ + } \ + return op1; \ + } - BINARY_EXPR(l10, un_expr, level10); - BINARY_EXPR(l9, l10, level9); - BINARY_EXPR(l8, l9, level8); - BINARY_EXPR(l7, l8, level7); - BINARY_EXPR(l6, l7, level6); + BINARY_EXPR(l6, unary_expr, level6); BINARY_EXPR(l5, l6, level5); BINARY_EXPR(l4, l5, level4); BINARY_EXPR(l3, l4, level3); BINARY_EXPR(l2, l3, level2); BINARY_EXPR(l1, l2, level1); +#undef BINARY_EXPR - plural_ptr cond_expr() + expr_ptr cond_expr() { - plural_ptr cond, case1, case2; - if((cond = l1()).get() == 0) - return plural_ptr(); - if(t.next() == '?') { - t.get(); - if((case1 = cond_expr()).get() == 0) - return plural_ptr(); - if(t.get() != ':') - return plural_ptr(); - if((case2 = cond_expr()).get() == 0) - return plural_ptr(); - } else { + expr_ptr cond; + if(!(cond = l1())) + return expr_ptr(); + if(t.next() != '?') return cond; - } - return plural_ptr(new conditional(cond, case1, case2)); + t.get(); + expr_ptr case1, case2; + if(!(case1 = cond_expr())) + return expr_ptr(); + if(t.get() != ':') + return expr_ptr(); + if(!(case2 = cond_expr())) + return expr_ptr(); + return make_expr<conditional>(std::move(cond), std::move(case1), std::move(case2)); } - tokenizer& t; + tokenizer t; }; } // namespace - plural_ptr compile(const char* str) + plural_expr compile(const char* str) { - tokenizer t(str); - parser p(t); - return p.compile(); + parser p(str); + return plural_expr(p.compile()); } }}}} // namespace boost::locale::gnu_gettext::lambda diff --git a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp index 71ae35a174..ff415175de 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/shared/mo_lambda.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2021-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -12,15 +13,24 @@ namespace boost { namespace locale { namespace gnu_gettext { namespace lambda { - struct plural { - virtual int operator()(int n) const = 0; - virtual plural* clone() const = 0; - virtual ~plural() = default; + struct BOOST_SYMBOL_VISIBLE expr { + using value_type = long long; + virtual value_type operator()(value_type n) const = 0; + virtual ~expr() = default; }; + using expr_ptr = std::unique_ptr<expr>; - typedef std::shared_ptr<plural> plural_ptr; + class plural_expr { + expr_ptr p_; - plural_ptr compile(const char* c_expression); + public: + plural_expr() = default; + explicit plural_expr(expr_ptr p) : p_(std::move(p)) {} + expr::value_type operator()(expr::value_type n) const { return (*p_)(n); } + explicit operator bool() const { return static_cast<bool>(p_); } + }; + + BOOST_LOCALE_DECL plural_expr compile(const char* c_expression); }}}} // namespace boost::locale::gnu_gettext::lambda diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp b/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp index 81e3102974..5dd020815b 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/all_generator.hpp @@ -12,32 +12,30 @@ #include <string> namespace boost { namespace locale { namespace impl_std { - enum class utf8_support { none, native, native_with_wide, from_wide }; - - std::locale create_convert(const std::locale& in, - const std::string& locale_name, - char_facet_t type, - utf8_support utf = utf8_support::none); - - std::locale create_collate(const std::locale& in, - const std::string& locale_name, - char_facet_t type, - utf8_support utf = utf8_support::none); - - std::locale create_formatting(const std::locale& in, - const std::string& locale_name, - char_facet_t type, - utf8_support utf = utf8_support::none); - - std::locale create_parsing(const std::locale& in, - const std::string& locale_name, - char_facet_t type, - utf8_support utf = utf8_support::none); - - std::locale create_codecvt(const std::locale& in, - const std::string& locale_name, - char_facet_t type, - utf8_support utf = utf8_support::none); + /// UTF-8 support of the standard library for the requested locale + enum class utf8_support { + /// No UTF-8 requested or required (e.g. other narrow encoding) + none, + /// UTF-8 encoding supported by the std-locale + native, + /// UTF-8 encoding has to be emulated using wchar_t + from_wide + }; + + std::locale + create_convert(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf); + + std::locale + create_collate(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf); + + std::locale + create_formatting(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf); + + std::locale + create_parsing(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf); + + std::locale + create_codecvt(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf); }}} // namespace boost::locale::impl_std diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp b/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp index e5f702afb0..95a5171fe3 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/codecvt.cpp @@ -12,15 +12,22 @@ namespace boost { namespace locale { namespace impl_std { template<typename CharType> std::locale codecvt_bychar(const std::locale& in, const std::string& locale_name) { - return std::locale(in, new std::codecvt_byname<CharType, char, std::mbstate_t>(locale_name.c_str())); + return std::locale(in, new std::codecvt_byname<CharType, char, std::mbstate_t>(locale_name)); } std::locale create_codecvt(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf) { +#if defined(BOOST_WINDOWS) + // This isn't fully correct: + // It will treat the 2-Byte wchar_t as UTF-16 encoded while it may be UCS-2 + // std::basic_filebuf explicitely disallows using suche multi-byte codecvts + // but it works in practice so far, so use it instead of failing for codepoints above U+FFFF + if(utf != utf8_support::none) + return util::create_utf8_codecvt(in, type); +#endif if(utf == utf8_support::from_wide) return util::create_utf8_codecvt(in, type); - switch(type) { case char_facet_t::nochar: break; case char_facet_t::char_f: return codecvt_bychar<char>(in, locale_name); diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp b/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp index ced58ec597..ee249bfa5f 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/collate.cpp @@ -6,20 +6,24 @@ #include <boost/locale/encoding.hpp> #include "boost/locale/std/all_generator.hpp" +#include <boost/assert.hpp> #include <ios> #include <locale> #include <string> +#include <type_traits> namespace boost { namespace locale { namespace impl_std { class utf8_collator_from_wide : public std::collate<char> { public: typedef std::collate<wchar_t> wfacet; - utf8_collator_from_wide(const std::locale& base, size_t refs = 0) : std::collate<char>(refs), base_(base) {} + utf8_collator_from_wide(const std::string& locale_name) : + base_(std::locale::classic(), new std::collate_byname<wchar_t>(locale_name)) + {} int do_compare(const char* lb, const char* le, const char* rb, const char* re) const override { - std::wstring l = conv::to_utf<wchar_t>(lb, le, "UTF-8"); - std::wstring r = conv::to_utf<wchar_t>(rb, re, "UTF-8"); + const std::wstring l = conv::utf_to_utf<wchar_t>(lb, le); + const std::wstring r = conv::utf_to_utf<wchar_t>(rb, re); return std::use_facet<wfacet>(base_).compare(l.c_str(), l.c_str() + l.size(), r.c_str(), @@ -27,33 +31,22 @@ namespace boost { namespace locale { namespace impl_std { } long do_hash(const char* b, const char* e) const override { - std::wstring tmp = conv::to_utf<wchar_t>(b, e, "UTF-8"); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(b, e); return std::use_facet<wfacet>(base_).hash(tmp.c_str(), tmp.c_str() + tmp.size()); } std::string do_transform(const char* b, const char* e) const override { - std::wstring tmp = conv::to_utf<wchar_t>(b, e, "UTF-8"); - std::wstring wkey = std::use_facet<wfacet>(base_).transform(tmp.c_str(), tmp.c_str() + tmp.size()); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(b, e); + const std::wstring wkey = std::use_facet<wfacet>(base_).transform(tmp.c_str(), tmp.c_str() + tmp.size()); + // wkey is only for lexicographical sorting, so may no be valid UTF + // --> Convert to char array in big endian order so sorting stays the same std::string key; - BOOST_LOCALE_START_CONST_CONDITION - if(sizeof(wchar_t) == 2) - key.reserve(wkey.size() * 2); - else - key.reserve(wkey.size() * 3); - for(unsigned i = 0; i < wkey.size(); i++) { - if(sizeof(wchar_t) == 2) { - uint16_t tv = static_cast<uint16_t>(wkey[i]); - key += char(tv >> 8); - key += char(tv & 0xFF); - } else { // 4 - uint32_t tv = static_cast<uint32_t>(wkey[i]); - // 21 bit - key += char((tv >> 16) & 0xFF); - key += char((tv >> 8) & 0xFF); - key += char(tv & 0xFF); - } + key.reserve(wkey.size() * sizeof(wchar_t)); + for(const wchar_t c : wkey) { + const auto tv = static_cast<std::make_unsigned<wchar_t>::type>(c); + for(unsigned i = 1; i <= sizeof(tv); ++i) + key += char((tv >> (sizeof(tv) - i) * 8) & 0xFF); } - BOOST_LOCALE_END_CONST_CONDITION return key; } @@ -61,29 +54,48 @@ namespace boost { namespace locale { namespace impl_std { std::locale base_; }; + // Workaround for a bug in the C++ or C standard library so far observed on the Appveyor VS2017 image + bool collation_works(const std::locale& l) + { + const auto& col = std::use_facet<std::collate<char>>(l); + const std::string a = "a"; + const std::string b = "b"; + try { + // On some broken system libs transform throws an exception + const auto ta = col.transform(a.c_str(), a.c_str() + a.size()); + const auto tb = col.transform(b.c_str(), b.c_str() + b.size()); + // This should always be true but on some broken system libs `l(a,b) == !l(b,a) == false` + return l(a, b) == !l(b, a) && (l(a, b) == (ta < tb)); + } catch(const std::exception&) { // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + std::locale create_collate(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf) { switch(type) { case char_facet_t::nochar: break; - case char_facet_t::char_f: { - if(utf == utf8_support::from_wide) { - std::locale base = - std::locale(std::locale::classic(), new std::collate_byname<wchar_t>(locale_name.c_str())); - return std::locale(in, new utf8_collator_from_wide(base)); - } else { - return std::locale(in, new std::collate_byname<char>(locale_name.c_str())); + case char_facet_t::char_f: + if(utf == utf8_support::from_wide) + return std::locale(in, new utf8_collator_from_wide(locale_name)); + else { + std::locale res = std::locale(in, new std::collate_byname<char>(locale_name)); + if(utf != utf8_support::none && !collation_works(res)) { + res = std::locale(res, new utf8_collator_from_wide(locale_name)); // LCOV_EXCL_LINE + } + BOOST_ASSERT_MSG(collation_works(res), "Broken collation"); + return res; } - } - case char_facet_t::wchar_f: return std::locale(in, new std::collate_byname<wchar_t>(locale_name.c_str())); + case char_facet_t::wchar_f: return std::locale(in, new std::collate_byname<wchar_t>(locale_name)); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - case char_facet_t::char16_f: return std::locale(in, new std::collate_byname<char16_t>(locale_name.c_str())); + case char_facet_t::char16_f: return std::locale(in, new std::collate_byname<char16_t>(locale_name)); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - case char_facet_t::char32_f: return std::locale(in, new std::collate_byname<char32_t>(locale_name.c_str())); + case char_facet_t::char32_f: return std::locale(in, new std::collate_byname<char32_t>(locale_name)); #endif } return in; diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp b/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp index a883ef7430..477c76f657 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/converter.cpp @@ -18,13 +18,15 @@ namespace boost { namespace locale { namespace impl_std { template<typename CharType> class std_converter : public converter<CharType> { public: - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; - typedef std::ctype<char_type> ctype_type; - std_converter(const std::locale& base, size_t refs = 0) : converter<CharType>(refs), base_(base) {} + typedef std::basic_string<CharType> string_type; + typedef std::ctype<CharType> ctype_type; + + std_converter(const std::string& locale_name) : + base_(std::locale::classic(), new std::ctype_byname<CharType>(locale_name)) + {} string_type convert(converter_base::conversion_type how, - const char_type* begin, - const char_type* end, + const CharType* begin, + const CharType* end, int /*flags*/ = 0) const override { switch(how) { @@ -33,8 +35,8 @@ namespace boost { namespace locale { namespace impl_std { case converter_base::case_folding: { const ctype_type& ct = std::use_facet<ctype_type>(base_); size_t len = end - begin; - std::vector<char_type> res(len + 1, 0); - char_type* lbegin = &res[0]; + std::vector<CharType> res(len + 1, 0); + CharType* lbegin = res.data(); std::copy(begin, end, lbegin); if(how == converter_base::upper_case) ct.toupper(lbegin, lbegin + len); @@ -54,9 +56,10 @@ namespace boost { namespace locale { namespace impl_std { class utf8_converter : public converter<char> { public: - typedef std::ctype<char> ctype_type; typedef std::ctype<wchar_t> wctype_type; - utf8_converter(const std::locale& base, size_t refs = 0) : converter<char>(refs), base_(base) {} + utf8_converter(const std::string& locale_name) : + base_(std::locale::classic(), new std::ctype_byname<wchar_t>(locale_name)) + {} std::string convert(converter_base::conversion_type how, const char* begin, const char* end, @@ -66,17 +69,15 @@ namespace boost { namespace locale { namespace impl_std { case upper_case: case lower_case: case case_folding: { - std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8"); + std::wstring tmp = conv::utf_to_utf<wchar_t>(begin, end); const wctype_type& ct = std::use_facet<wctype_type>(base_); - size_t len = tmp.size(); - std::vector<wchar_t> res(len + 1, 0); - wchar_t* lbegin = &res[0]; - std::copy(tmp.c_str(), tmp.c_str() + len, lbegin); + wchar_t* lbegin = &tmp.front(); + const size_t len = tmp.size(); if(how == upper_case) ct.toupper(lbegin, lbegin + len); else ct.tolower(lbegin, lbegin + len); - return conv::from_utf<wchar_t>(lbegin, lbegin + len, "UTF-8"); + return conv::utf_to_utf<char>(lbegin, lbegin + len); } case title_case: case normalization: break; @@ -93,29 +94,17 @@ namespace boost { namespace locale { namespace impl_std { { switch(type) { case char_facet_t::nochar: break; - case char_facet_t::char_f: { - if(utf == utf8_support::native_with_wide || utf == utf8_support::from_wide) { - std::locale base(std::locale::classic(), new std::ctype_byname<wchar_t>(locale_name.c_str())); - return std::locale(in, new utf8_converter(base)); - } - std::locale base(std::locale::classic(), new std::ctype_byname<char>(locale_name.c_str())); - return std::locale(in, new std_converter<char>(base)); - } - case char_facet_t::wchar_f: { - std::locale base(std::locale::classic(), new std::ctype_byname<wchar_t>(locale_name.c_str())); - return std::locale(in, new std_converter<wchar_t>(base)); - } + case char_facet_t::char_f: + if(utf != utf8_support::none) + return std::locale(in, new utf8_converter(locale_name)); + else + return std::locale(in, new std_converter<char>(locale_name)); + case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(locale_name)); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - case char_facet_t::char16_f: { - std::locale base(std::locale::classic(), new std::ctype_byname<char16_t>(locale_name.c_str())); - return std::locale(in, new std_converter<char16_t>(base)); - } + case char_facet_t::char16_f: return std::locale(in, new std_converter<char16_t>(locale_name)); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - case char_facet_t::char32_f: { - std::locale base(std::locale::classic(), new std::ctype_byname<char32_t>(locale_name.c_str())); - return std::locale(in, new std_converter<char32_t>(base)); - } + case char_facet_t::char32_f: return std::locale(in, new std_converter<char32_t>(locale_name)); #endif } return in; diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp b/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp index 2f93d2c88a..d8c7d5aff8 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/numeric.cpp @@ -7,6 +7,7 @@ #include <boost/locale/encoding.hpp> #include <boost/locale/formatting.hpp> #include <boost/locale/generator.hpp> +#include <algorithm> #include <cstdlib> #include <ios> #include <locale> @@ -17,12 +18,20 @@ #include "boost/locale/util/numeric.hpp" namespace boost { namespace locale { namespace impl_std { - + /// Forwarding time_put facet + /// Almost the same as `std::time_put_byname` but replaces the locale of the `ios_base` in `do_put` so that e.g. + /// weekday names are translated and formatting is as per the language of the base locale template<typename CharType> class time_put_from_base : public std::time_put<CharType> { public: - time_put_from_base(const std::locale& base, size_t refs = 0) : std::time_put<CharType>(refs), base_(base) {} - typedef typename std::time_put<CharType>::iter_type iter_type; + using iter_type = typename std::time_put<CharType>::iter_type; + + time_put_from_base(const std::locale& base) : + base_facet_(std::use_facet<std::time_put<CharType>>(base)), base_ios_(nullptr) + { + // Imbue the ios with the base locale so the facets `do_put` uses its formatting information + base_ios_.imbue(base); + } iter_type do_put(iter_type out, std::ios_base& /*ios*/, @@ -31,13 +40,12 @@ namespace boost { namespace locale { namespace impl_std { char format, char modifier) const override { - std::basic_stringstream<CharType> ss; - ss.imbue(base_); - return std::use_facet<std::time_put<CharType>>(base_).put(out, ss, fill, tm, format, modifier); + return base_facet_.put(out, base_ios_, fill, tm, format, modifier); } private: - std::locale base_; + const std::time_put<CharType>& base_facet_; + mutable std::basic_ios<CharType> base_ios_; }; class utf8_time_put_from_wide : public std::time_put<char> { @@ -54,12 +62,8 @@ namespace boost { namespace locale { namespace impl_std { wtmps.imbue(base_); std::use_facet<std::time_put<wchar_t>>(base_) .put(wtmps, wtmps, wchar_t(fill), tm, wchar_t(format), wchar_t(modifier)); - std::wstring wtmp = wtmps.str(); - std::string const tmp = conv::from_utf<wchar_t>(wtmp, "UTF-8"); - for(unsigned i = 0; i < tmp.size(); i++) { - *out++ = tmp[i]; - } - return out; + const std::string tmp = conv::utf_to_utf<char>(wtmps.str()); + return std::copy(tmp.begin(), tmp.end(), out); } private: @@ -73,8 +77,8 @@ namespace boost { namespace locale { namespace impl_std { typedef std::numpunct<wchar_t> wfacet_type; const wfacet_type& wfacet = std::use_facet<wfacet_type>(base); - truename_ = conv::from_utf<wchar_t>(wfacet.truename(), "UTF-8"); - falsename_ = conv::from_utf<wchar_t>(wfacet.falsename(), "UTF-8"); + truename_ = conv::utf_to_utf<char>(wfacet.truename()); + falsename_ = conv::utf_to_utf<char>(wfacet.falsename()); wchar_t tmp_decimal_point = wfacet.decimal_point(); wchar_t tmp_thousands_sep = wfacet.thousands_sep(); @@ -123,9 +127,9 @@ namespace boost { namespace locale { namespace impl_std { typedef std::moneypunct<wchar_t, Intl> wfacet_type; const wfacet_type& wfacet = std::use_facet<wfacet_type>(base); - curr_symbol_ = conv::from_utf<wchar_t>(wfacet.curr_symbol(), "UTF-8"); - positive_sign_ = conv::from_utf<wchar_t>(wfacet.positive_sign(), "UTF-8"); - negative_sign_ = conv::from_utf<wchar_t>(wfacet.negative_sign(), "UTF-8"); + curr_symbol_ = conv::utf_to_utf<char>(wfacet.curr_symbol()); + positive_sign_ = conv::utf_to_utf<char>(wfacet.positive_sign()); + negative_sign_ = conv::utf_to_utf<char>(wfacet.negative_sign()); frac_digits_ = wfacet.frac_digits(); pos_format_ = wfacet.pos_format(); neg_format_ = wfacet.neg_format(); @@ -184,7 +188,7 @@ namespace boost { namespace locale { namespace impl_std { class utf8_numpunct : public std::numpunct_byname<char> { public: typedef std::numpunct_byname<char> base_type; - utf8_numpunct(const char* name, size_t refs = 0) : std::numpunct_byname<char>(name, refs) {} + utf8_numpunct(const std::string& name, size_t refs = 0) : std::numpunct_byname<char>(name, refs) {} char do_thousands_sep() const override { unsigned char bs = base_type::do_thousands_sep(); @@ -209,7 +213,7 @@ namespace boost { namespace locale { namespace impl_std { class utf8_moneypunct : public std::moneypunct_byname<char, Intl> { public: typedef std::moneypunct_byname<char, Intl> base_type; - utf8_moneypunct(const char* name, size_t refs = 0) : std::moneypunct_byname<char, Intl>(name, refs) {} + utf8_moneypunct(const std::string& name, size_t refs = 0) : std::moneypunct_byname<char, Intl>(name, refs) {} char do_thousands_sep() const override { unsigned char bs = base_type::do_thousands_sep(); @@ -233,20 +237,19 @@ namespace boost { namespace locale { namespace impl_std { template<typename CharType> std::locale create_basic_parsing(const std::locale& in, const std::string& locale_name) { - std::locale tmp = std::locale(in, new std::numpunct_byname<CharType>(locale_name.c_str())); - tmp = std::locale(tmp, new std::moneypunct_byname<CharType, true>(locale_name.c_str())); - tmp = std::locale(tmp, new std::moneypunct_byname<CharType, false>(locale_name.c_str())); - tmp = std::locale(tmp, new std::ctype_byname<CharType>(locale_name.c_str())); - return tmp; + std::locale tmp = std::locale(in, new std::numpunct_byname<CharType>(locale_name)); + tmp = std::locale(tmp, new std::moneypunct_byname<CharType, true>(locale_name)); + tmp = std::locale(tmp, new std::moneypunct_byname<CharType, false>(locale_name)); + tmp = std::locale(tmp, new std::ctype_byname<CharType>(locale_name)); + return std::locale(tmp, new util::base_num_parse<CharType>()); } template<typename CharType> std::locale create_basic_formatting(const std::locale& in, const std::string& locale_name) { std::locale tmp = create_basic_parsing<CharType>(in, locale_name); - std::locale base(locale_name.c_str()); - tmp = std::locale(tmp, new time_put_from_base<CharType>(base)); - return tmp; + tmp = std::locale(tmp, new time_put_from_base<CharType>(std::locale(locale_name))); + return std::locale(tmp, new util::base_num_format<CharType>()); } std::locale @@ -254,59 +257,28 @@ namespace boost { namespace locale { namespace impl_std { { switch(type) { case char_facet_t::nochar: break; - case char_facet_t::char_f: { - switch(utf) { - case utf8_support::from_wide: { - std::locale base = std::locale(locale_name.c_str()); - - std::locale tmp = std::locale(in, new utf8_time_put_from_wide(base)); - tmp = std::locale(tmp, new utf8_numpunct_from_wide(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); - return std::locale(tmp, new util::base_num_format<char>()); - } - case utf8_support::native: { - std::locale base = std::locale(locale_name.c_str()); - - std::locale tmp = std::locale(in, new time_put_from_base<char>(base)); - tmp = std::locale(tmp, new utf8_numpunct(locale_name.c_str())); - tmp = std::locale(tmp, new utf8_moneypunct<true>(locale_name.c_str())); - tmp = std::locale(tmp, new utf8_moneypunct<false>(locale_name.c_str())); - return std::locale(tmp, new util::base_num_format<char>()); - } - case utf8_support::native_with_wide: { - std::locale base = std::locale(locale_name.c_str()); - - std::locale tmp = std::locale(in, new time_put_from_base<char>(base)); - tmp = std::locale(tmp, new utf8_numpunct_from_wide(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); - return std::locale(tmp, new util::base_num_format<char>()); - } - case utf8_support::none: break; - } - std::locale tmp = create_basic_formatting<char>(in, locale_name); - tmp = std::locale(tmp, new util::base_num_format<char>()); - return tmp; - } - case char_facet_t::wchar_f: { - std::locale tmp = create_basic_formatting<wchar_t>(in, locale_name); - tmp = std::locale(tmp, new util::base_num_format<wchar_t>()); - return tmp; - } + case char_facet_t::char_f: + if(utf != utf8_support::none) { + const std::locale base(locale_name); + std::time_put<char>* time_put; + if(utf == utf8_support::from_wide) + time_put = new utf8_time_put_from_wide(base); + else + time_put = new time_put_from_base<char>(base); + std::locale tmp(in, time_put); + // Fix possibly invalid UTF-8 + tmp = std::locale(tmp, new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp, new util::base_num_format<char>()); + } else + return create_basic_formatting<char>(in, locale_name); + case char_facet_t::wchar_f: return create_basic_formatting<wchar_t>(in, locale_name); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - case char_facet_t::char16_f: { - std::locale tmp = create_basic_formatting<char16_t>(in, locale_name); - tmp = std::locale(tmp, new util::base_num_format<char16_t>()); - return tmp; - } + case char_facet_t::char16_f: return create_basic_formatting<char16_t>(in, locale_name); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - case char_facet_t::char32_f: { - std::locale tmp = create_basic_formatting<char32_t>(in, locale_name); - tmp = std::locale(tmp, new util::base_num_format<char32_t>()); - return tmp; - } + case char_facet_t::char32_f: return create_basic_formatting<char32_t>(in, locale_name); #endif } return in; @@ -317,58 +289,22 @@ namespace boost { namespace locale { namespace impl_std { { switch(type) { case char_facet_t::nochar: break; - case char_facet_t::char_f: { - switch(utf) { - case utf8_support::from_wide: { - std::locale base = std::locale::classic(); - - base = std::locale(base, new std::numpunct_byname<wchar_t>(locale_name.c_str())); - base = std::locale(base, new std::moneypunct_byname<wchar_t, true>(locale_name.c_str())); - base = std::locale(base, new std::moneypunct_byname<wchar_t, false>(locale_name.c_str())); - - std::locale tmp = std::locale(in, new utf8_numpunct_from_wide(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); - return std::locale(tmp, new util::base_num_parse<char>()); - } - case utf8_support::native: { - std::locale tmp = std::locale(in, new utf8_numpunct(locale_name.c_str())); - tmp = std::locale(tmp, new utf8_moneypunct<true>(locale_name.c_str())); - tmp = std::locale(tmp, new utf8_moneypunct<false>(locale_name.c_str())); - return std::locale(tmp, new util::base_num_parse<char>()); - } - case utf8_support::native_with_wide: { - std::locale base = std::locale(locale_name.c_str()); - - std::locale tmp = std::locale(in, new utf8_numpunct_from_wide(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); - tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); - return std::locale(tmp, new util::base_num_parse<char>()); - } - case utf8_support::none: break; - } - std::locale tmp = create_basic_parsing<char>(in, locale_name); - tmp = std::locale(in, new util::base_num_parse<char>()); - return tmp; - } - case char_facet_t::wchar_f: { - std::locale tmp = create_basic_parsing<wchar_t>(in, locale_name); - tmp = std::locale(in, new util::base_num_parse<wchar_t>()); - return tmp; - } + case char_facet_t::char_f: + if(utf != utf8_support::none) { + const std::locale base(locale_name); + // Fix possibly invalid UTF-8 + std::locale tmp = std::locale(in, new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp, new util::base_num_parse<char>()); + } else + return create_basic_parsing<char>(in, locale_name); + case char_facet_t::wchar_f: return create_basic_parsing<wchar_t>(in, locale_name); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - case char_facet_t::char16_f: { - std::locale tmp = create_basic_parsing<char16_t>(in, locale_name); - tmp = std::locale(in, new util::base_num_parse<char16_t>()); - return tmp; - } + case char_facet_t::char16_f: return create_basic_parsing<char16_t>(in, locale_name); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - case char_facet_t::char32_f: { - std::locale tmp = create_basic_parsing<char32_t>(in, locale_name); - tmp = std::locale(in, new util::base_num_parse<char32_t>()); - return tmp; - } + case char_facet_t::char32_f: return create_basic_parsing<char32_t>(in, locale_name); #endif } return in; diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp b/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp index 05967eb4bc..7b70e8a9f8 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -9,21 +10,66 @@ #include <boost/locale/localization_backend.hpp> #include <boost/locale/util.hpp> #include <boost/locale/util/locale_data.hpp> +#include <boost/assert.hpp> +#include <boost/core/ignore_unused.hpp> #include <algorithm> #include <iterator> #include <vector> -#if defined(BOOST_WINDOWS) +#if BOOST_LOCALE_USE_WIN32_API # ifndef NOMINMAX # define NOMINMAX # endif -# include "boost/locale/encoding/conv.hpp" -# include "boost/locale/util/encoding.hpp" # include "boost/locale/win32/lcid.hpp" # include <windows.h> #endif #include "boost/locale/std/all_generator.hpp" +#include "boost/locale/util/encoding.hpp" #include "boost/locale/util/gregorian.hpp" +#include "boost/locale/util/make_std_unique.hpp" +#include "boost/locale/util/numeric.hpp" + +namespace { +struct windows_name { + std::string name, codepage; + explicit operator bool() const { return !name.empty() && !codepage.empty(); } +}; + +windows_name to_windows_name(const std::string& l) +{ +#if BOOST_LOCALE_USE_WIN32_API + windows_name res; + const unsigned lcid = boost::locale::impl_win::locale_to_lcid(l); + char win_lang[256]{}; + if(lcid == 0 || GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, win_lang, sizeof(win_lang)) == 0) + return res; + res.name = win_lang; + char win_country[256]{}; + if(GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, win_country, sizeof(win_country)) != 0) { + res.name += "_"; + res.name += win_country; + } + + char win_codepage[10]{}; + if(GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, win_codepage, sizeof(win_codepage)) != 0) + res.codepage = win_codepage; + return res; +#else + boost::ignore_unused(l); + return {}; +#endif +} + +bool loadable(const std::string& name) +{ + try { + std::locale l(name); + return true; + } catch(const std::exception&) { + return false; + } +} +} // namespace namespace boost { namespace locale { namespace impl_std { @@ -69,77 +115,54 @@ namespace boost { namespace locale { namespace impl_std { } in_use_id_ = lid; data_.parse(lid); - name_ = "C"; -#if defined(BOOST_WINDOWS) - const std::pair<std::string, int> wl_inf = to_windows_name(lid); - const std::string& win_name = wl_inf.first; - const int win_codepage = wl_inf.second; -#endif + const auto l_win = to_windows_name(lid); if(!data_.is_utf8()) { + utf_mode_ = utf8_support::none; if(loadable(lid)) name_ = lid; -#if defined(BOOST_WINDOWS) - else if(loadable(win_name) && win_codepage == util::encoding_to_windows_codepage(data_.encoding())) - name_ = win_name; -#endif - utf_mode_ = utf8_support::none; + else if(l_win && loadable(l_win.name)) { + if(util::are_encodings_equal(l_win.codepage, data_.encoding())) + name_ = l_win.name; + else { + int codepage_int; + if(util::try_to_int(l_win.codepage, codepage_int) + && codepage_int == util::encoding_to_windows_codepage(data_.encoding())) + { + name_ = l_win.name; + } else + name_ = "C"; + } + } else + name_ = "C"; } else { if(loadable(lid)) { name_ = lid; - utf_mode_ = utf8_support::native_with_wide; -#if defined(BOOST_WINDOWS) - // This isn't fully correct: - // It will treat the 2-Byte wchar_t as UTF-16 encoded while it may be UCS-2 - // std::basic_filebuf explicitely disallows using suche multi-byte codecvts - // but it works in practice so far, so use it instead of failing for codepoints above U+FFFF - utf_mode_ = utf8_support::from_wide; -#endif - } -#if defined(BOOST_WINDOWS) - else if(loadable(win_name)) - { - name_ = win_name; + utf_mode_ = utf8_support::native; + } else { + std::vector<std::string> alt_names; + if(l_win) + alt_names.push_back(l_win.name); + // Try different spellings + alt_names.push_back(util::locale_data(data_).encoding("UTF-8").to_string()); + alt_names.push_back(util::locale_data(data_).encoding("utf8", false).to_string()); + // Without encoding, let from_wide classes handle it + alt_names.push_back(util::locale_data(data_).encoding("").to_string()); + // Final try: Classic locale, but enable Unicode (if supported) + alt_names.push_back("C.UTF-8"); + alt_names.push_back("C.utf8"); + // If everything fails rely on the classic locale + alt_names.push_back("C"); + for(const std::string& name : alt_names) { + if(loadable(name)) { + name_ = name; + break; + } + } + BOOST_ASSERT(!name_.empty()); utf_mode_ = utf8_support::from_wide; } -#endif - else - utf_mode_ = utf8_support::none; - } - } - -#if defined(BOOST_WINDOWS) - std::pair<std::string, int> to_windows_name(const std::string& l) - { - std::pair<std::string, int> res("C", 0); - unsigned lcid = impl_win::locale_to_lcid(l); - char win_lang[256] = {0}; - char win_country[256] = {0}; - char win_codepage[10] = {0}; - if(GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, win_lang, sizeof(win_lang)) == 0) - return res; - std::string lc_name = win_lang; - if(GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, win_country, sizeof(win_country)) != 0) { - lc_name += "_"; - lc_name += win_country; - } - - res.first = lc_name; - - if(GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, win_codepage, sizeof(win_codepage)) != 0) - res.second = atoi(win_codepage); - return res; - } -#endif - - bool loadable(std::string name) - { - try { - std::locale l(name.c_str()); - return true; - } catch(const std::exception& /*e*/) { - return false; } } @@ -200,9 +223,9 @@ namespace boost { namespace locale { namespace impl_std { bool use_ansi_encoding_; }; - localization_backend* create_localization_backend() + std::unique_ptr<localization_backend> create_localization_backend() { - return new std_localization_backend(); + return make_std_unique<std_localization_backend>(); } }}} // namespace boost::locale::impl_std diff --git a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp b/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp index 76ddc051d0..4ce6b271e3 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/std/std_backend.hpp @@ -6,10 +6,14 @@ #ifndef BOOST_LOCALE_IMPL_STD_LOCALIZATION_BACKEND_HPP #define BOOST_LOCALE_IMPL_STD_LOCALIZATION_BACKEND_HPP + +#include <boost/locale/config.hpp> +#include <memory> + namespace boost { namespace locale { class localization_backend; namespace impl_std { - localization_backend* create_localization_backend(); + std::unique_ptr<localization_backend> create_localization_backend(); } // namespace impl_std }} // namespace boost::locale #endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp b/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp index 40759882f2..7ad9846d23 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/codecvt_converter.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -8,12 +9,14 @@ #include <boost/locale/generator.hpp> #include <boost/locale/utf8_codecvt.hpp> #include <boost/locale/util.hpp> +#include <boost/locale/util/string.hpp> +#include <boost/assert.hpp> #include <algorithm> #include <cstddef> #include <cstring> -#include "boost/locale/encoding/conv.hpp" #include "boost/locale/util/encoding.hpp" +#include "boost/locale/util/make_std_unique.hpp" #ifdef BOOST_MSVC # pragma warning(disable : 4244) // loose data @@ -31,11 +34,11 @@ namespace boost { namespace locale { namespace util { bool is_thread_safe() const override { return true; } - uint32_t to_unicode(const char*& begin, const char* end) override + utf::code_point to_unicode(const char*& begin, const char* end) override { const char* p = begin; - utf::code_point c = utf::utf_traits<char>::decode(p, end); + const utf::code_point c = utf::utf_traits<char>::decode(p, end); if(c == utf::illegal) return illegal; @@ -47,7 +50,7 @@ namespace boost { namespace locale { namespace util { return c; } - uint32_t from_unicode(uint32_t u, char* begin, const char* end) override + utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end) override { if(!utf::is_valid_codepoint(u)) return illegal; @@ -68,18 +71,18 @@ namespace boost { namespace locale { namespace util { { for(unsigned i = 0; i < 128; i++) to_unicode_tbl_[i] = i; + const conv::utf_encoder<wchar_t> to_utf(encoding, conv::skip); for(unsigned i = 128; i < 256; i++) { - char buf[2] = {char(i), 0}; + char buf[2] = {util::to_char(i), 0}; uint32_t uchar = utf::illegal; try { - std::wstring const tmp = conv::to_utf<wchar_t>(buf, buf + 1, encoding, conv::stop); - if(tmp.size() == 1) { + std::wstring const tmp = to_utf.convert(buf, buf + 1); + if(tmp.size() == 1) uchar = tmp[0]; - } else { + else uchar = utf::illegal; - } - } catch(const conv::conversion_error& /*e*/) { - uchar = utf::illegal; + } catch(const conv::conversion_error&) { // LCOV_EXCL_LINE + uchar = utf::illegal; // LCOV_EXCL_LINE } to_unicode_tbl_[i] = uchar; } @@ -95,14 +98,14 @@ namespace boost { namespace locale { namespace util { } } - uint32_t to_unicode(const char*& begin, const char* end) const + utf::code_point to_unicode(const char*& begin, const char* end) const { if(begin == end) return utf::incomplete; unsigned char c = *begin++; return to_unicode_tbl_[c]; } - uint32_t from_unicode(uint32_t u, char* begin, const char* end) const + utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end) const { if(begin == end) return utf::incomplete; @@ -116,12 +119,12 @@ namespace boost { namespace locale { namespace util { pos = (pos + 1) % hash_table_size; if(c == 0) return utf::illegal; - *begin = c; + *begin = to_char(c); return 1; } private: - uint32_t to_unicode_tbl_[256]; + utf::code_point to_unicode_tbl_[256]; unsigned char from_unicode_tbl_[hash_table_size]; }; @@ -134,8 +137,8 @@ namespace boost { namespace locale { namespace util { bool is_thread_safe() const override { return true; } base_converter* clone() const override { return new simple_converter(*this); } - uint32_t to_unicode(const char*& begin, const char* end) override { return cvt_.to_unicode(begin, end); } - uint32_t from_unicode(uint32_t u, char* begin, const char* end) override + utf::code_point to_unicode(const char*& begin, const char* end) override { return cvt_.to_unicode(begin, end); } + utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end) override { return cvt_.from_unicode(u, begin, end); } @@ -163,7 +166,7 @@ namespace boost { namespace locale { namespace util { return cvt_.to_unicode(begin, end); } - utf::code_point from_unicode(state_type&, utf::code_point u, char* begin, const char* end) const + utf::len_or_error from_unicode(state_type&, utf::code_point u, char* begin, const char* end) const { return cvt_.from_unicode(u, begin, end); } @@ -186,71 +189,68 @@ namespace boost { namespace locale { namespace util { } } // namespace - bool check_is_simple_encoding(const std::string& encoding) + std::vector<std::string> get_simple_encodings() { - std::string norm = util::normalize_encoding(encoding); - return std::binary_search<const char**>(simple_encoding_table, - simple_encoding_table - + sizeof(simple_encoding_table) / sizeof(const char*), - norm.c_str(), - compare_strings); + return std::vector<std::string>(simple_encoding_table, std::end(simple_encoding_table)); } - std::unique_ptr<base_converter> create_simple_converter(const std::string& encoding) + bool is_simple_encoding(const std::string& encoding) { - return std::unique_ptr<base_converter>(create_simple_converter_new_ptr(encoding)); + std::string norm = util::normalize_encoding(encoding); + return std::binary_search(simple_encoding_table, + std::end(simple_encoding_table), + norm.c_str(), + compare_strings); } - base_converter* create_simple_converter_new_ptr(const std::string& encoding) + + std::unique_ptr<base_converter> create_simple_converter(const std::string& encoding) { - if(check_is_simple_encoding(encoding)) - return new simple_converter(encoding); - return 0; + if(is_simple_encoding(encoding)) + return make_std_unique<simple_converter>(encoding); + return nullptr; } std::unique_ptr<base_converter> create_utf8_converter() { - return std::unique_ptr<base_converter>(create_utf8_converter_new_ptr()); + return make_std_unique<utf8_converter>(); } - base_converter* create_utf8_converter_new_ptr() - { - return new utf8_converter(); - } + // clang-format off + base_converter* create_simple_converter_new_ptr(const std::string& encoding){ return create_simple_converter(encoding).release(); } // LCOV_EXCL_LINE + base_converter* create_utf8_converter_new_ptr(){ return create_utf8_converter().release(); } // LCOV_EXCL_LINE + // clang-format on - template<typename CharType> - class code_converter : public generic_codecvt<CharType, code_converter<CharType>> { + template<typename CharType, bool ThreadSafe> + class code_converter : public generic_codecvt<CharType, code_converter<CharType, ThreadSafe>> { public: typedef std::unique_ptr<base_converter> base_converter_ptr; typedef base_converter_ptr state_type; code_converter(base_converter_ptr cvt, size_t refs = 0) : - generic_codecvt<CharType, code_converter<CharType>>(refs), cvt_(std::move(cvt)) - { - max_len_ = cvt_->max_len(); - thread_safe_ = cvt_->is_thread_safe(); - } + generic_codecvt<CharType, code_converter<CharType, ThreadSafe>>(refs), cvt_(std::move(cvt)) + {} - int max_encoding_length() const { return max_len_; } + int max_encoding_length() const { return cvt_->max_len(); } base_converter_ptr initial_state(generic_codecvt_base::initial_convertion_state /* unused */) const { base_converter_ptr r; - if(!thread_safe_) + if(!ThreadSafe) r.reset(cvt_->clone()); return r; } utf::code_point to_unicode(base_converter_ptr& ptr, const char*& begin, const char* end) const { - if(thread_safe_) + if(ThreadSafe) return cvt_->to_unicode(begin, end); else return ptr->to_unicode(begin, end); } - utf::code_point from_unicode(base_converter_ptr& ptr, utf::code_point u, char* begin, const char* end) const + utf::len_or_error from_unicode(base_converter_ptr& ptr, utf::code_point u, char* begin, const char* end) const { - if(thread_safe_) + if(ThreadSafe) return cvt_->from_unicode(u, begin, end); else return ptr->from_unicode(u, begin, end); @@ -258,23 +258,28 @@ namespace boost { namespace locale { namespace util { private: base_converter_ptr cvt_; - int max_len_; - bool thread_safe_; }; + template<typename CharType> + static std::locale do_create_codecvt(const std::locale& in, std::unique_ptr<base_converter> cvt) + { + return cvt->is_thread_safe() ? std::locale(in, new code_converter<CharType, true>(std::move(cvt))) : + std::locale(in, new code_converter<CharType, false>(std::move(cvt))); + } + std::locale create_codecvt(const std::locale& in, std::unique_ptr<base_converter> cvt, char_facet_t type) { if(!cvt) cvt.reset(new base_converter()); switch(type) { case char_facet_t::nochar: break; - case char_facet_t::char_f: return std::locale(in, new code_converter<char>(std::move(cvt))); - case char_facet_t::wchar_f: return std::locale(in, new code_converter<wchar_t>(std::move(cvt))); + case char_facet_t::char_f: return do_create_codecvt<char>(in, std::move(cvt)); + case char_facet_t::wchar_f: return do_create_codecvt<wchar_t>(in, std::move(cvt)); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T - case char_facet_t::char16_f: return std::locale(in, new code_converter<char16_t>(std::move(cvt))); + case char_facet_t::char16_f: return do_create_codecvt<char16_t>(in, std::move(cvt)); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T - case char_facet_t::char32_f: return std::locale(in, new code_converter<char32_t>(std::move(cvt))); + case char_facet_t::char32_f: return do_create_codecvt<char32_t>(in, std::move(cvt)); #endif } return in; @@ -298,14 +303,9 @@ namespace boost { namespace locale { namespace util { return in; } - /// This function installs codecvt that can be used for conversion between single byte - /// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points, - /// - /// Throws invalid_charset_error if the character set is not supported or isn't single byte character - /// set std::locale create_simple_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type) { - if(!check_is_simple_encoding(encoding)) + if(!is_simple_encoding(encoding)) throw boost::locale::conv::invalid_charset_error("Invalid simple encoding " + encoding); switch(type) { diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp b/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp index d4ede78b1b..74cf7705dc 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/default_locale.cpp @@ -5,7 +5,8 @@ // https://www.boost.org/LICENSE_1_0.txt #include <boost/locale/util.hpp> -#include <cstdlib> +#include <boost/locale/util/string.hpp> +#include <algorithm> #if BOOST_LOCALE_USE_WIN32_API # ifndef NOMINMAX @@ -27,7 +28,7 @@ static bool get_user_default_locale_info(LCTYPE lcType, char (&buf)[N]) namespace boost { namespace locale { namespace util { std::string get_system_locale(bool use_utf8_on_windows) { - const char* lang = 0; + const char* lang = nullptr; if(!lang || !*lang) lang = getenv("LC_ALL"); if(!lang || !*lang) @@ -54,7 +55,7 @@ namespace boost { namespace locale { namespace util { if(use_utf8_on_windows || !get_user_default_locale_info(LOCALE_IDEFAULTANSICODEPAGE, buf)) lc_name += ".UTF-8"; else { - if(atoi(buf) == 0) + if(std::find_if_not(buf, str_end(buf), is_numeric_ascii) != str_end(buf)) lc_name += ".UTF-8"; else lc_name.append(".windows-").append(buf); diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp b/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp index 232fdaf245..8a6bf183be 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/encoding.cpp @@ -7,7 +7,6 @@ #include "boost/locale/util/encoding.hpp" #include "boost/locale/util/string.hpp" -#include <boost/assert.hpp> #if BOOST_LOCALE_USE_WIN32_API # include "boost/locale/util/win_codepages.hpp" # ifndef NOMINMAX @@ -19,11 +18,11 @@ #include <cstring> namespace boost { namespace locale { namespace util { - static std::string do_normalize_encoding(const char* encoding, const size_t len) + std::string normalize_encoding(const string_view encoding) { std::string result; - result.reserve(len); - for(char c = *encoding; c != 0; c = *(++encoding)) { + result.reserve(encoding.length()); + for(char c : encoding) { if(is_lower_ascii(c) || is_numeric_ascii(c)) result += c; else if(is_upper_ascii(c)) @@ -32,24 +31,12 @@ namespace boost { namespace locale { namespace util { return result; } - std::string normalize_encoding(const std::string& encoding) - { - return do_normalize_encoding(encoding.c_str(), encoding.size()); - } - - std::string normalize_encoding(const char* encoding) - { - return do_normalize_encoding(encoding, std::strlen(encoding)); - } - #if BOOST_LOCALE_USE_WIN32_API static int normalized_encoding_to_windows_codepage(const std::string& encoding) { - constexpr size_t n = sizeof(all_windows_encodings) / sizeof(all_windows_encodings[0]); - windows_encoding* begin = all_windows_encodings; - windows_encoding* end = all_windows_encodings + n; + windows_encoding* end = std::end(all_windows_encodings); - windows_encoding* ptr = std::lower_bound(begin, end, encoding.c_str()); + windows_encoding* ptr = std::lower_bound(all_windows_encodings, end, encoding.c_str()); while(ptr != end && ptr->name == encoding) { if(ptr->was_tested) return ptr->codepage; @@ -64,12 +51,7 @@ namespace boost { namespace locale { namespace util { return -1; } - int encoding_to_windows_codepage(const char* encoding) - { - return normalized_encoding_to_windows_codepage(normalize_encoding(encoding)); - } - - int encoding_to_windows_codepage(const std::string& encoding) + int encoding_to_windows_codepage(const string_view encoding) { return normalized_encoding_to_windows_codepage(normalize_encoding(encoding)); } diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp index 958233fb35..7f2f6a8cd8 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/encoding.hpp @@ -9,8 +9,10 @@ #define BOOST_LOCALE_UTIL_ENCODING_HPP #include <boost/locale/config.hpp> +#include <boost/utility/string_view.hpp> #include <cstdint> #include <string> +#include <vector> namespace boost { namespace locale { namespace util { @@ -37,17 +39,23 @@ namespace boost { namespace locale { namespace util { } /// Make encoding lowercase and remove all non-alphanumeric characters - BOOST_LOCALE_DECL std::string normalize_encoding(const std::string& encoding); - BOOST_LOCALE_DECL std::string normalize_encoding(const char* encoding); + BOOST_LOCALE_DECL std::string normalize_encoding(string_view encoding); /// True if the normalized encodings are equal inline bool are_encodings_equal(const std::string& l, const std::string& r) { return normalize_encoding(l) == normalize_encoding(r); } + BOOST_LOCALE_DECL std::vector<std::string> get_simple_encodings(); + #if BOOST_LOCALE_USE_WIN32_API - int encoding_to_windows_codepage(const char* encoding); - int encoding_to_windows_codepage(const std::string& encoding); + int encoding_to_windows_codepage(string_view encoding); +#else + // Requires WinAPI -> Dummy returning invalid + inline int encoding_to_windows_codepage(string_view) // LCOV_EXCL_LINE + { + return -1; // LCOV_EXCL_LINE + } #endif }}} // namespace boost::locale::util diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp new file mode 100644 index 0000000000..df5857b9d9 --- /dev/null +++ b/contrib/restricted/boost/locale/src/boost/locale/util/foreach_char.hpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2023-2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_UTIL_FOREACH_CHAR_HPP +#define BOOST_LOCALE_UTIL_FOREACH_CHAR_HPP + +#include <boost/locale/config.hpp> + +#ifdef BOOST_LOCALE_ENABLE_CHAR16_T +# define BOOST_LOCALE_FOREACH_CHAR_I_CHAR16_T(F) F(char16_t) +#else +# define BOOST_LOCALE_FOREACH_CHAR_I_CHAR16_T(F) +#endif +#ifdef BOOST_LOCALE_ENABLE_CHAR32_T +# define BOOST_LOCALE_FOREACH_CHAR_I_CHAR32_T(F) F(char32_t) +#else +# define BOOST_LOCALE_FOREACH_CHAR_I_CHAR32_T(F) +#endif + +#define BOOST_LOCALE_FOREACH_CHAR(F) \ + F(char) \ + F(wchar_t) \ + BOOST_LOCALE_FOREACH_CHAR_I_CHAR16_T(F) \ + BOOST_LOCALE_FOREACH_CHAR_I_CHAR32_T(F) + +#endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp b/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp index 5c74b54eee..b0bc6e8a29 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/gregorian.cpp @@ -19,18 +19,22 @@ #include <memory> #include <string> +#define BOOST_LOCALE_CASE_INVALID(action) \ + BOOST_ASSERT_MSG(false, "Shouldn't use 'invalid' value."); \ + action + namespace boost { namespace locale { namespace util { namespace { - int is_leap(int year) + bool is_leap(int year) { if(year % 400 == 0) - return 1; + return true; if(year % 100 == 0) - return 0; + return false; if(year % 4 == 0) - return 1; - return 0; + return true; + return false; } int days_in_month(int year, int month) @@ -113,12 +117,9 @@ namespace boost { namespace locale { namespace util { "PH", "PK", "SG", "TH", "TT", "TW", "UM", "US", "UZ", "VI", "ZW"}; if(strcmp(terr, "MV") == 0) return 5; // fri - if(std::binary_search<const char* const*>(sat, sat + sizeof(sat) / (sizeof(sat[0])), terr, comparator)) + if(std::binary_search<const char* const*>(sat, std::end(sat), terr, comparator)) return 6; // sat - if(std::binary_search<const char* const*>(sunday, - sunday + sizeof(sunday) / (sizeof(sunday[0])), - terr, - comparator)) + if(std::binary_search<const char* const*>(sunday, std::end(sunday), terr, comparator)) return 0; // sun // default return 1; // mon @@ -130,7 +131,7 @@ namespace boost { namespace locale { namespace util { gregorian_calendar(const std::string& terr) { first_day_of_week_ = first_day_of_week(terr.c_str()); - time_ = std::time(0); + time_ = std::time(nullptr); is_local_ = true; tzoff_ = 0; from_time(time_); @@ -190,8 +191,10 @@ namespace boost { namespace locale { namespace util { int diff = 7 * (value - current_week); tm_updated_.tm_mday += diff; } break; - case period::marks::first_day_of_week: ///< For example Sunday in US, Monday in France - case invalid: return; + ///< For example Sunday in US, Monday in France + case period::marks::first_day_of_week: // LCOV_EXCL_LINE + throw std::invalid_argument("Can't change first day of week"); // LCOV_EXCL_LINE + case invalid: BOOST_LOCALE_CASE_INVALID(return ); // LCOV_EXCL_LINE } normalized_ = false; } @@ -209,19 +212,17 @@ namespace boost { namespace locale { namespace util { #ifndef BOOST_WINDOWS // windows does not handle negative time_t, under other plaforms // it may be actually valid value in 1969-12-31 23:59:59 - // so we check that a filed was updated - does not happen in case of error + // so we check that a field was updated - does not happen in case of error if(val.tm_wday == -1) #endif - { - throw date_time_error("boost::locale::gregorian_calendar: invalid time"); - } + throw date_time_error("boost::locale::gregorian_calendar: invalid time"); // LCOV_EXCL_LINE } } else { point = internal_timegm(&val); #ifdef BOOST_WINDOWS // Windows uses TLS, thread safe - std::tm* revert_point = 0; - if(point < 0 || (revert_point = gmtime(&point)) == 0) + std::tm* revert_point = nullptr; + if(point < 0 || (revert_point = gmtime(&point)) == nullptr) throw date_time_error("boost::locale::gregorian_calendar time is out of range"); val = *revert_point; #else @@ -250,11 +251,10 @@ namespace boost { namespace locale { namespace util { // adding something big dividable by 7 int start_of_period_in_weeks; - if(first_week_day < days_in_full_week) { + if(first_week_day < days_in_full_week) start_of_period_in_weeks = -first_week_day; - } else { + else start_of_period_in_weeks = 7 - first_week_day; - } int week_number_in_days = day - start_of_period_in_weeks; if(week_number_in_days < 0) return -1; @@ -293,7 +293,7 @@ namespace boost { namespace locale { namespace util { BOOST_LOCALE_END_CONST_CONDITION case current: return tm_.tm_year + 1900; }; - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case month: switch(v) { case absolute_minimum: @@ -304,7 +304,7 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 11; case current: return tm_.tm_mon; }; - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case day: switch(v) { case absolute_minimum: @@ -315,7 +315,7 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return days_in_month(tm_.tm_year + 1900, tm_.tm_mon + 1); case current: return tm_.tm_mday; }; - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case day_of_year: ///< The number of day in year, starting from 1 switch(v) { case absolute_minimum: @@ -326,7 +326,7 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return is_leap(tm_.tm_year + 1900) ? 366 : 365; case current: return tm_.tm_yday + 1; } - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case day_of_week: ///< Day of week, starting from Sunday, [1..7] switch(v) { case absolute_minimum: @@ -337,7 +337,7 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 7; case current: return tm_.tm_wday + 1; } - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, ///< [1..7] switch(v) { @@ -349,8 +349,8 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 7; case current: return (tm_.tm_wday - first_day_of_week_ + 7) % 7 + 1; } - break; - case hour: ///< 24 clock hour [0..23] + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case hour: ///< 24 clock hour [0..23] switch(v) { case absolute_minimum: case greatest_minimum: @@ -360,8 +360,8 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 23; case current: return tm_.tm_hour; } - break; - case hour_12: ///< 12 clock hour [0..11] + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case hour_12: ///< 12 clock hour [0..11] switch(v) { case absolute_minimum: case greatest_minimum: @@ -371,8 +371,8 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 11; case current: return tm_.tm_hour % 12; } - break; - case am_pm: ///< am or pm marker, [0..1] + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case am_pm: ///< am or pm marker, [0..1] switch(v) { case absolute_minimum: case greatest_minimum: @@ -382,8 +382,8 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 1; case current: return tm_.tm_hour >= 12 ? 1 : 0; } - break; - case minute: ///< minute [0..59] + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case minute: ///< minute [0..59] switch(v) { case absolute_minimum: case greatest_minimum: @@ -393,8 +393,8 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 59; case current: return tm_.tm_min; } - break; - case second: ///< second [0..59] + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case second: ///< second [0..59] switch(v) { case absolute_minimum: case greatest_minimum: @@ -404,7 +404,7 @@ namespace boost { namespace locale { namespace util { case actual_maximum: return 59; case current: return tm_.tm_sec; } - break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case period::marks::first_day_of_week: ///< For example Sunday in US, Monday in France return first_day_of_week_ + 1; @@ -422,13 +422,11 @@ namespace boost { namespace locale { namespace util { return get_week_number(end_of_year_days, dow_of_end_of_year); } case current: { - int val = get_week_number(tm_.tm_yday, tm_.tm_wday); - if(val < 0) - return 53; - return val; + const int val = get_week_number(tm_.tm_yday, tm_.tm_wday); + return (val < 0) ? 53 : val; } - } - break; + } // LCOV_EXCL_LINE + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case week_of_month: ///< The week number within current month switch(v) { case absolute_minimum: @@ -442,13 +440,11 @@ namespace boost { namespace locale { namespace util { return get_week_number(end_of_month_days, dow_of_end_of_month); } case current: { - int val = get_week_number(tm_.tm_mday, tm_.tm_wday); - if(val < 0) - return 5; - return val; + const int val = get_week_number(tm_.tm_mday, tm_.tm_wday); + return (val < 0) ? 5 : val; } - } - break; + } // LCOV_EXCL_LINE + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE case day_of_week_in_month: ///< Original number of the day of the week in month. switch(v) { case absolute_minimum: @@ -465,10 +461,10 @@ namespace boost { namespace locale { namespace util { return 5; case current: return (tm_.tm_mday - 1) / 7 + 1; } - break; - case invalid: BOOST_ASSERT_MSG(false, "Shouldn't use 'invalid' value."); break; + throw std::invalid_argument("Invalid abstract_calendar::value_type"); // LCOV_EXCL_LINE + case invalid: BOOST_LOCALE_CASE_INVALID(break); // LCOV_EXCL_LINE } - return 0; + throw std::invalid_argument("Invalid period_mark"); // LCOV_EXCL_LINE } /// Set current time point @@ -493,6 +489,7 @@ namespace boost { namespace locale { namespace util { case is_gregorian: throw date_time_error("is_gregorian is not settable options for calendar"); case is_dst: throw date_time_error("is_dst is not settable options for calendar"); } + throw std::invalid_argument("Invalid option type"); // LCOV_EXCL_LINE } /// Get option for calendar, currently only check if it is Gregorian calendar int get_option(calendar_option_type opt) const override @@ -501,69 +498,66 @@ namespace boost { namespace locale { namespace util { case is_gregorian: return 1; case is_dst: return tm_.tm_isdst == 1; } - return 0; + throw std::invalid_argument("Invalid option type"); // LCOV_EXCL_LINE } /// Adjust period's \a p value by \a difference items using a update_type \a u. /// Note: not all values are adjustable void adjust_value(period::marks::period_mark m, update_type u, int difference) override { - switch(u) { - case move: { - using namespace period::marks; - switch(m) { - case year: ///< Year, it is calendar specific - case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == - ///< -1. - tm_updated_.tm_year += difference; - break; - case month: tm_updated_.tm_mon += difference; break; - case day: - case day_of_year: - case day_of_week: ///< Day of week, starting from Sunday, [1..7] - case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday - ///< is 1, [1..7] - tm_updated_.tm_mday += difference; - break; - case hour: ///< 24 clock hour [0..23] - case hour_12: ///< 12 clock hour [0..11] - tm_updated_.tm_hour += difference; - break; - case am_pm: ///< am or pm marker, [0..1] - tm_updated_.tm_hour += 12 * difference; - break; - case minute: ///< minute [0..59] - tm_updated_.tm_min += difference; - break; - case second: tm_updated_.tm_sec += difference; break; - case week_of_year: ///< The week number in the year - case week_of_month: ///< The week number within current month - case day_of_week_in_month: ///< Original number of the day of the week in month. - tm_updated_.tm_mday += difference * 7; - break; - case era: - case period::marks::first_day_of_week: - case invalid: break; // Not adjustable and ignored - } - normalized_ = false; - normalize(); - } break; - case roll: { - const int cur_min = get_value(m, actual_minimum); - const int cur_max = get_value(m, actual_maximum); - BOOST_ASSERT(cur_max >= cur_min); - const int range = cur_max - cur_min + 1; - int value = get_value(m, current) - cur_min; - BOOST_ASSERT(value >= 0 && value < range); - BOOST_ASSERT_MSG(difference <= std::numeric_limits<int>::max(), "Input is to large"); - value = (value + difference) % range; - // If the sum above was negative the result of the modulo operation "can" be negative too. - if(value < 0) - value += range; - BOOST_ASSERT(value >= 0 && value < range); - set_value(m, value + cur_min); - normalize(); + if(u == move) { + using namespace period::marks; + switch(m) { + case year: ///< Year, it is calendar specific + case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1 + tm_updated_.tm_year += difference; + break; + case month: tm_updated_.tm_mon += difference; break; + case day: + case day_of_year: + case day_of_week: ///< starting from Sunday, [1..7] + case day_of_week_local: ///< Local DoW, e.g. in France Monday=1, in US Sunday=1, [1..7] + tm_updated_.tm_mday += difference; + break; + case hour: ///< 24 clock hour [0..23] + case hour_12: ///< 12 clock hour [0..11] + tm_updated_.tm_hour += difference; + break; + case am_pm: ///< am or pm marker, [0..1] + tm_updated_.tm_hour += 12 * difference; + break; + case minute: ///< minute [0..59] + tm_updated_.tm_min += difference; + break; + case second: tm_updated_.tm_sec += difference; break; + case week_of_year: ///< The week number in the year + case week_of_month: ///< The week number within current month + case day_of_week_in_month: ///< Original number of the day of the week in month. + tm_updated_.tm_mday += difference * 7; + break; + case era: throw std::invalid_argument("era not adjustable"); // LCOV_EXCL_LINE + case period::marks::first_day_of_week: // LCOV_EXCL_LINE + throw std::invalid_argument("Can't change first day of week"); // LCOV_EXCL_LINE + case invalid: BOOST_LOCALE_CASE_INVALID(return ); // LCOV_EXCL_LINE } + normalized_ = false; + normalize(); + } else { + BOOST_ASSERT(u == roll); + const int cur_min = get_value(m, actual_minimum); + const int cur_max = get_value(m, actual_maximum); + BOOST_ASSERT(cur_max >= cur_min); + const int range = cur_max - cur_min + 1; + int value = get_value(m, current) - cur_min; + BOOST_ASSERT(value >= 0 && value < range); + BOOST_ASSERT_MSG(difference <= std::numeric_limits<int>::max(), "Input is to large"); + value = (value + difference) % range; + // If the sum above was negative the result of the modulo operation "can" be negative too. + if(value < 0) + value += range; + BOOST_ASSERT(value >= 0 && value < range); + set_value(m, value + cur_min); + normalize(); } } @@ -619,9 +613,8 @@ namespace boost { namespace locale { namespace util { case day_of_week: case day_of_week_local: { int diff = other->tm_.tm_yday - tm_.tm_yday; - if(other->tm_.tm_year != tm_.tm_year) { + if(other->tm_.tm_year != tm_.tm_year) diff += days_from_0(other->tm_.tm_year + 1900) - days_from_0(tm_.tm_year + 1900); - } return get_diff(period::marks::day, diff, other) / factor; } case am_pm: return static_cast<int>((other->time_ - time_) / (3600 * 12)); @@ -629,10 +622,12 @@ namespace boost { namespace locale { namespace util { case hour_12: return static_cast<int>((other->time_ - time_) / 3600); case minute: return static_cast<int>((other->time_ - time_) / 60); case second: return static_cast<int>(other->time_ - time_); - case invalid: - case period::marks::first_day_of_week: break; // Not adjustable + case invalid: // LCOV_EXCL_LINE + BOOST_LOCALE_CASE_INVALID(return 0); // LCOV_EXCL_LINE + // Not adjustable + case period::marks::first_day_of_week: return 0; // LCOV_EXCL_LINE } - return 0; + throw std::invalid_argument("Invalid period_mark"); // LCOV_EXCL_LINE } /// Set time zone, empty - use system @@ -666,7 +661,7 @@ namespace boost { namespace locale { namespace util { void from_time(std::time_t point) { std::time_t real_point = point + tzoff_; - std::tm* t = 0; + std::tm* t; #ifdef BOOST_WINDOWS // Windows uses TLS, thread safe t = is_local_ ? localtime(&real_point) : gmtime(&real_point); @@ -674,9 +669,8 @@ namespace boost { namespace locale { namespace util { std::tm tmp_tm; t = is_local_ ? localtime_r(&real_point, &tmp_tm) : gmtime_r(&real_point, &tmp_tm); #endif - if(!t) { + if(!t) throw date_time_error("boost::locale::gregorian_calendar: invalid time point"); - } tm_ = *t; tm_updated_ = *t; normalized_ = true; diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp index 25701f7eca..ed8157ba97 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/iconv.hpp @@ -20,8 +20,12 @@ namespace boost { namespace locale { } public: - iconv_handle(iconv_t h = iconv_t(-1)) : h_(h) {} + explicit iconv_handle(iconv_t h = iconv_t(-1)) : h_(h) {} + + iconv_handle(const iconv_handle& rhs) = delete; iconv_handle(iconv_handle&& rhs) noexcept : h_(exchange(rhs.h_, iconv_t(-1))) {} + + iconv_handle& operator=(const iconv_handle& rhs) = delete; iconv_handle& operator=(iconv_handle&& rhs) noexcept { h_ = exchange(rhs.h_, iconv_t(-1)); diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp b/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp index 113d27fffc..f95d28a580 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/locale_data.cpp @@ -6,7 +6,6 @@ // https://www.boost.org/LICENSE_1_0.txt #include <boost/locale/util/locale_data.hpp> -#include "boost/locale/encoding/conv.hpp" #include "boost/locale/util/encoding.hpp" #include "boost/locale/util/string.hpp" #include <boost/assert.hpp> @@ -126,14 +125,7 @@ namespace boost { namespace locale { namespace util { if(tmp.empty()) return false; // No assumptions, but uppercase - for(char& c : tmp) { - if(util::is_lower_ascii(c)) - c += 'A' - 'a'; - } - encoding_ = tmp; - - utf8_ = util::normalize_encoding(encoding_) == "utf8"; - + encoding(std::move(tmp)); if(end >= input.size()) return true; else { @@ -157,4 +149,17 @@ namespace boost { namespace locale { namespace util { return true; } + locale_data& locale_data::encoding(std::string new_encoding, const bool uppercase) + { + if(uppercase) { + for(char& c : new_encoding) { + if(util::is_lower_ascii(c)) + c += 'A' - 'a'; + } + } + encoding_ = std::move(new_encoding); + utf8_ = util::normalize_encoding(encoding_) == "utf8"; + return *this; + } + }}} // namespace boost::locale::util diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp new file mode 100644 index 0000000000..d7492adc03 --- /dev/null +++ b/contrib/restricted/boost/locale/src/boost/locale/util/make_std_unique.hpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_LOCALE_MAKE_STD_UNIQUE_HPP +#define BOOST_LOCALE_MAKE_STD_UNIQUE_HPP + +#include <boost/locale/config.hpp> +#include <memory> +#include <type_traits> +#include <utility> + +namespace boost { namespace locale { + template<class T, class... Args> + std::unique_ptr<T> make_std_unique(Args&&... args) + { + static_assert(!std::is_array<T>::value, "Must not be an array"); + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + } +}} // namespace boost::locale + +#endif diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp index 5b4393d694..146309e357 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/numeric.hpp @@ -9,18 +9,36 @@ #include <boost/locale/formatting.hpp> #include <boost/locale/info.hpp> #include <boost/predef/os.h> +#include <algorithm> +#include <cerrno> #include <cstdlib> #include <ctime> #include <ios> +#include <limits> #include <locale> #include <sstream> #include <string> #include <vector> -#include "boost/locale/util/timezone.hpp" +#include "timezone.hpp" namespace boost { namespace locale { namespace util { + inline bool try_to_int(const std::string& s, int& res) + { + if(s.empty()) + return false; + errno = 0; + char* end_char{}; + const auto v = std::strtol(s.c_str(), &end_char, 10); + if(errno == ERANGE || end_char != s.c_str() + s.size()) + return false; + if(v < std::numeric_limits<int>::min() || v > std::numeric_limits<int>::max()) + return false; + res = v; + return true; + } + template<typename CharType> struct formatting_size_traits { static size_t size(const std::basic_string<CharType>& s, const std::locale& /*l*/) { return s.size(); } @@ -35,16 +53,10 @@ namespace boost { namespace locale { namespace util { if(!std::use_facet<info>(l).utf8()) return s.size(); // count code points, poor man's text size - size_t res = 0; - for(size_t i = 0; i < s.size(); i++) { - unsigned char c = s[i]; - if(c <= 127) - res++; - else if((c & 0xC0) == 0xC0) { // first UTF-8 byte - res++; - } - } - return res; + return std::count_if(s.begin(), s.end(), [](const unsigned char c) { + return (c <= 127) // ASCII + || ((c & 0xC0) == 0xC0); // first UTF-8 byte + }); } }; @@ -53,48 +65,47 @@ namespace boost { namespace locale { namespace util { public: typedef typename std::num_put<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; base_num_format(size_t refs = 0) : std::num_put<CharType>(refs) {} protected: - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, double val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, double val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long double val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long double val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long long val) const override { return do_real_put(out, ios, fill, val); } - iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long long val) const override + iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long long val) const override { return do_real_put(out, ios, fill, val); } private: template<typename ValueType> - iter_type do_real_put(iter_type out, std::ios_base& ios, char_type fill, ValueType val) const + iter_type do_real_put(iter_type out, std::ios_base& ios, CharType fill, ValueType val) const { - typedef std::num_put<char_type> super; + typedef std::num_put<CharType> super; ios_info& info = ios_info::get(ios); switch(info.display_flags()) { case flags::posix: { - typedef std::basic_ostringstream<char_type> sstream_type; + typedef std::basic_ostringstream<CharType> sstream_type; sstream_type ss; ss.imbue(std::locale::classic()); ss.flags(ios.flags()); @@ -112,7 +123,7 @@ namespace boost { namespace locale { namespace util { ios, fill, static_cast<std::time_t>(val), - info.date_time_pattern<char_type>()); + info.date_time_pattern<CharType>()); case flags::currency: { bool nat = info.currency_flags() == flags::currency_default || info.currency_flags() == flags::currency_national; @@ -129,7 +140,7 @@ namespace boost { namespace locale { namespace util { } virtual iter_type - do_format_currency(bool intl, iter_type out, std::ios_base& ios, char_type fill, long double val) const + do_format_currency(bool intl, iter_type out, std::ios_base& ios, CharType fill, long double val) const { if(intl) return format_currency<true>(out, ios, fill, val); @@ -138,34 +149,31 @@ namespace boost { namespace locale { namespace util { } template<bool intl> - iter_type format_currency(iter_type out, std::ios_base& ios, char_type fill, long double val) const + iter_type format_currency(iter_type out, std::ios_base& ios, CharType fill, long double val) const { std::locale loc = ios.getloc(); - int digits = std::use_facet<std::moneypunct<char_type, intl>>(loc).frac_digits(); + int digits = std::use_facet<std::moneypunct<CharType, intl>>(loc).frac_digits(); while(digits > 0) { val *= 10; digits--; } std::ios_base::fmtflags f = ios.flags(); ios.flags(f | std::ios_base::showbase); - out = std::use_facet<std::money_put<char_type>>(loc).put(out, intl, ios, fill, val); + out = std::use_facet<std::money_put<CharType>>(loc).put(out, intl, ios, fill, val); ios.flags(f); return out; } - iter_type format_time(iter_type out, std::ios_base& ios, char_type fill, std::time_t time, char c) const + iter_type format_time(iter_type out, std::ios_base& ios, CharType fill, std::time_t time, char c) const { string_type fmt; - fmt += char_type('%'); - fmt += char_type(c); + fmt += CharType('%'); + fmt += CharType(c); return format_time(out, ios, fill, time, fmt); } - iter_type format_time(iter_type out, - std::ios_base& ios, - char_type fill, - std::time_t time, - const string_type& format) const + iter_type + format_time(iter_type out, std::ios_base& ios, CharType fill, std::time_t time, const string_type& format) const { std::string tz = ios_info::get(ios).time_zone(); std::tm tm; @@ -174,7 +182,7 @@ namespace boost { namespace locale { namespace util { #endif if(tz.empty()) { #ifdef BOOST_WINDOWS - /// Windows uses TLS + // Windows uses TLS tm = *localtime(&time); #else localtime_r(&time, &tm); @@ -183,7 +191,7 @@ namespace boost { namespace locale { namespace util { int gmtoff = parse_tz(tz); time += gmtoff; #ifdef BOOST_WINDOWS - /// Windows uses TLS + // Windows uses TLS tm = *gmtime(&time); #else gmtime_r(&time, &tm); @@ -193,17 +201,17 @@ namespace boost { namespace locale { namespace util { // These have extra fields to specify timezone if(gmtoff != 0) { // bsd and apple want tm_zone be non-const - tm.tm_zone = &tmp_buf.front(); + tm.tm_zone = tmp_buf.data(); tm.tm_gmtoff = gmtoff; } #endif } - std::basic_ostringstream<char_type> tmp_out; - std::use_facet<std::time_put<char_type>>(ios.getloc()) + std::basic_ostringstream<CharType> tmp_out; + std::use_facet<std::time_put<CharType>>(ios.getloc()) .put(tmp_out, tmp_out, fill, &tm, format.c_str(), format.c_str() + format.size()); string_type str = tmp_out.str(); std::streamsize on_left = 0, on_right = 0; - std::streamsize points = formatting_size_traits<char_type>::size(str, ios.getloc()); + std::streamsize points = formatting_size_traits<CharType>::size(str, ios.getloc()); if(points < ios.width()) { std::streamsize n = ios.width() - points; @@ -228,7 +236,7 @@ namespace boost { namespace locale { namespace util { return out; } - }; /// num_format + }; // num_format template<typename CharType> class base_num_parse : public std::num_get<CharType> { @@ -238,7 +246,6 @@ namespace boost { namespace locale { namespace util { protected: typedef typename std::num_get<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; iter_type do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, long& val) const override @@ -317,7 +324,7 @@ namespace boost { namespace locale { namespace util { iter_type do_real_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, ValueType& val) const { - typedef std::num_get<char_type> super; + typedef std::num_get<CharType> super; ios_info& info = ios_info::get(ios); @@ -364,9 +371,9 @@ namespace boost { namespace locale { namespace util { long double& val) const { std::locale loc = ios.getloc(); - int digits = std::use_facet<std::moneypunct<char_type, intl>>(loc).frac_digits(); + int digits = std::use_facet<std::moneypunct<CharType, intl>>(loc).frac_digits(); long double rval; - in = std::use_facet<std::money_get<char_type>>(loc).get(in, end, intl, ios, err, rval); + in = std::use_facet<std::money_get<CharType>>(loc).get(in, end, intl, ios, err, rval); if(!(err & std::ios::failbit)) { while(digits > 0) { rval /= 10; diff --git a/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp b/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp index 684379d87b..617f40a977 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/util/timezone.hpp @@ -6,6 +6,7 @@ #ifndef BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP #define BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP +#include <boost/locale/util/string.hpp> #include <cstdlib> #include <cstring> #include <string> @@ -13,26 +14,23 @@ namespace boost { namespace locale { namespace util { inline int parse_tz(const std::string& tz) { - int gmtoff = 0; std::string ltz; - for(unsigned i = 0; i < tz.size(); i++) { - if('a' <= tz[i] && tz[i] <= 'z') - ltz += tz[i] - 'a' + 'A'; - else if(tz[i] == ' ') - ; - else - ltz += tz[i]; + for(const char c : tz) { + if(is_lower_ascii(c)) + ltz += c - 'a' + 'A'; + else if(c != ' ') + ltz += c; } if(ltz.compare(0, 3, "GMT") != 0 && ltz.compare(0, 3, "UTC") != 0) return 0; if(ltz.size() <= 3) return 0; + int gmtoff = 0; const char* begin = ltz.c_str() + 3; - char* end = 0; + char* end = const_cast<char*>(begin); int hours = strtol(begin, &end, 10); - if(end != begin) { + if(end != begin) gmtoff += hours * 3600; - } if(*end == ':') { begin = end + 1; int minutes = strtol(begin, &end, 10); diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp b/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp index a02d347779..aeda7ae602 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/api.hpp @@ -95,18 +95,17 @@ namespace boost { namespace locale { namespace impl_win { for(unsigned i = 0; gr[i]; i++) { if(gr[i] == L';') continue; - if(L'1' <= gr[i] && gr[i] <= L'9') { + if(L'1' <= gr[i] && gr[i] <= L'9') res.grouping += char(gr[i] - L'0'); - } else if(gr[i] == L'0') + else if(gr[i] == L'0') inf_group = true; } if(!inf_group) { BOOST_LOCALE_START_CONST_CONDITION - if(std::numeric_limits<char>::is_signed) { + if(std::numeric_limits<char>::is_signed) res.grouping += std::numeric_limits<char>::min(); - } else { + else res.grouping += std::numeric_limits<char>::max(); - } BOOST_LOCALE_END_CONST_CONDITION } return res; @@ -124,8 +123,8 @@ namespace boost { namespace locale { namespace impl_win { throw std::length_error("String to long for int type"); std::vector<wchar_t> buf(len + 1); int l2 = - LCMapStringW(l.lcid, flags, begin, static_cast<int>(end - begin), &buf.front(), static_cast<int>(buf.size())); - res.assign(&buf.front(), l2); + LCMapStringW(l.lcid, flags, begin, static_cast<int>(end - begin), buf.data(), static_cast<int>(buf.size())); + res.assign(buf.data(), l2); return res; } @@ -166,10 +165,10 @@ namespace boost { namespace locale { namespace impl_win { ss << std::setprecision(std::numeric_limits<double>::digits10 + 1) << value; std::wstring sval = ss.str(); - int len = GetCurrencyFormatW(l.lcid, 0, sval.c_str(), 0, 0, 0); + const auto len = GetCurrencyFormatW(l.lcid, 0, sval.c_str(), nullptr, nullptr, 0); std::vector<wchar_t> buf(len + 1); - GetCurrencyFormatW(l.lcid, 0, sval.c_str(), 0, &buf.front(), len); - return &buf.front(); + GetCurrencyFormatW(l.lcid, 0, sval.c_str(), nullptr, buf.data(), len); + return buf.data(); } //////////////////////////////////////////////////////////////////////// @@ -180,18 +179,18 @@ namespace boost { namespace locale { namespace impl_win { inline std::wstring wcs_format_date_l(const wchar_t* format, SYSTEMTIME const* tm, const winlocale& l) { - int len = GetDateFormatW(l.lcid, 0, tm, format, 0, 0); + const auto len = GetDateFormatW(l.lcid, 0, tm, format, nullptr, 0); std::vector<wchar_t> buf(len + 1); - GetDateFormatW(l.lcid, 0, tm, format, &buf.front(), len); - return &buf.front(); + GetDateFormatW(l.lcid, 0, tm, format, buf.data(), len); + return buf.data(); } inline std::wstring wcs_format_time_l(const wchar_t* format, SYSTEMTIME const* tm, const winlocale& l) { - int len = GetTimeFormatW(l.lcid, 0, tm, format, 0, 0); + const auto len = GetTimeFormatW(l.lcid, 0, tm, format, nullptr, 0); std::vector<wchar_t> buf(len + 1); - GetTimeFormatW(l.lcid, 0, tm, format, &buf.front(), len); - return &buf.front(); + GetTimeFormatW(l.lcid, 0, tm, format, buf.data(), len); + return buf.data(); } inline std::wstring wcsfold(const wchar_t* begin, const wchar_t* end) @@ -221,8 +220,8 @@ namespace boost { namespace locale { namespace impl_win { if(len == std::numeric_limits<int>::max()) throw std::length_error("String to long for int type"); std::vector<wchar_t> v(len + 1); - len = FoldStringW(flags, begin, static_cast<int>(end - begin), &v.front(), len + 1); - return std::wstring(&v.front(), len); + len = FoldStringW(flags, begin, static_cast<int>(end - begin), v.data(), len + 1); + return std::wstring(v.data(), len); } inline std::wstring wcsxfrm_l(collate_level level, const wchar_t* begin, const wchar_t* end, const winlocale& l) diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp b/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp index bd78c2116d..465676e437 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/collate.cpp @@ -20,32 +20,32 @@ namespace boost { namespace locale { namespace impl_win { int do_compare(collate_level level, const char* lb, const char* le, const char* rb, const char* re) const override { - std::wstring l = conv::to_utf<wchar_t>(lb, le, "UTF-8"); - std::wstring r = conv::to_utf<wchar_t>(rb, re, "UTF-8"); + const std::wstring l = conv::utf_to_utf<wchar_t>(lb, le); + const std::wstring r = conv::utf_to_utf<wchar_t>(rb, re); return wcscoll_l(level, l.c_str(), l.c_str() + l.size(), r.c_str(), r.c_str() + r.size(), lc_); } long do_hash(collate_level level, const char* b, const char* e) const override { - std::string key = do_transform(level, b, e); + const std::string key = do_transform(level, b, e); return gnu_gettext::pj_winberger_hash_function(key.c_str(), key.c_str() + key.size()); } std::string do_transform(collate_level level, const char* b, const char* e) const override { - std::wstring tmp = conv::to_utf<wchar_t>(b, e, "UTF-8"); - std::wstring wkey = wcsxfrm_l(level, tmp.c_str(), tmp.c_str() + tmp.size(), lc_); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(b, e); + const std::wstring wkey = wcsxfrm_l(level, tmp.c_str(), tmp.c_str() + tmp.size(), lc_); std::string key; BOOST_LOCALE_START_CONST_CONDITION if(sizeof(wchar_t) == 2) key.reserve(wkey.size() * 2); else key.reserve(wkey.size() * 3); - for(unsigned i = 0; i < wkey.size(); i++) { + for(const wchar_t c : wkey) { if(sizeof(wchar_t) == 2) { - uint16_t tv = static_cast<uint16_t>(wkey[i]); + const uint16_t tv = static_cast<uint16_t>(c); key += char(tv >> 8); key += char(tv & 0xFF); } else { // 4 - uint32_t tv = static_cast<uint32_t>(wkey[i]); + const uint32_t tv = static_cast<uint32_t>(c); // 21 bit key += char((tv >> 16) & 0xFF); key += char((tv >> 8) & 0xFF); diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp b/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp index 6911ab5996..ab0af493e4 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/converter.cpp @@ -43,7 +43,7 @@ namespace boost { namespace locale { namespace impl_win { std::string convert(converter_base::conversion_type how, const char* begin, const char* end, int flags = 0) const override { - std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8"); + const std::wstring tmp = conv::utf_to_utf<wchar_t>(begin, end); const wchar_t* wb = tmp.c_str(); const wchar_t* we = wb + tmp.size(); @@ -56,7 +56,7 @@ namespace boost { namespace locale { namespace impl_win { case normalization: res = wcsnormalize(static_cast<norm_type>(flags), wb, we); break; case title_case: break; } - return conv::from_utf(res, "UTF-8"); + return conv::utf_to_utf<char>(res); } private: diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp b/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp index f27cd099e5..1435455775 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/lcid.cpp @@ -46,9 +46,8 @@ namespace boost { namespace locale { namespace impl_win { unsigned lcid; ss >> lcid; - if(ss.fail() || !ss.eof()) { + if(ss.fail() || !ss.eof()) return FALSE; - } char iso_639_lang[16]; char iso_3166_country[16]; @@ -59,13 +58,12 @@ namespace boost { namespace locale { namespace impl_win { lc_name += "_"; lc_name += iso_3166_country; } - table_type::iterator p = tbl.find(lc_name); + const auto p = tbl.find(lc_name); if(p != tbl.end()) { if(p->second > lcid) p->second = lcid; - } else { + } else tbl[lc_name] = lcid; - } } catch(...) { tbl.clear(); return FALSE; @@ -89,27 +87,20 @@ namespace boost { namespace locale { namespace impl_win { unsigned locale_to_lcid(const std::string& locale_name) { - if(locale_name.empty()) { + if(locale_name.empty()) return LOCALE_USER_DEFAULT; - } boost::locale::util::locale_data d; d.parse(locale_name); std::string id = d.language(); - if(!d.country().empty()) { + if(!d.country().empty()) id += "_" + d.country(); - } - if(!d.variant().empty()) { + if(!d.variant().empty()) id += "@" + d.variant(); - } const table_type& tbl = get_ready_lcid_table(); - table_type::const_iterator p = tbl.find(id); - - unsigned lcid = 0; - if(p != tbl.end()) - lcid = p->second; - return lcid; + const auto p = tbl.find(id); + return (p != tbl.end()) ? p->second : 0; } }}} // namespace boost::locale::impl_win diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp b/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp index 2654be7ed4..edbb663e78 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/numeric.cpp @@ -10,6 +10,7 @@ #include <boost/locale/generator.hpp> #include "boost/locale/win32/all_generator.hpp" #include "boost/locale/win32/api.hpp" +#include <algorithm> #include <cctype> #include <cstdlib> #include <cstring> @@ -22,20 +23,15 @@ namespace boost { namespace locale { namespace impl_win { namespace { - std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out, const std::wstring& s) { - for(size_t i = 0; i < s.size(); i++) - *out++ = s[i]; - return out; + return std::copy(s.begin(), s.end(), out); } std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out, const std::wstring& s) { - std::string tmp = conv::from_utf(s, "UTF-8"); - for(size_t i = 0; i < tmp.size(); i++) - *out++ = tmp[i]; - return out; + const std::string tmp = conv::utf_to_utf<char>(s); + return std::copy(tmp.begin(), tmp.end(), out); } } // namespace @@ -44,7 +40,6 @@ namespace boost { namespace locale { namespace impl_win { public: typedef typename std::num_put<CharType>::iter_type iter_type; typedef std::basic_string<CharType> string_type; - typedef CharType char_type; num_format(const winlocale& lc, size_t refs = 0) : util::base_num_format<CharType>(refs), lc_(lc) {} @@ -52,19 +47,19 @@ namespace boost { namespace locale { namespace impl_win { iter_type do_format_currency(bool /*intl*/, iter_type out, std::ios_base& ios, - char_type fill, + CharType fill, long double val) const override { if(lc_.is_c()) { std::locale loc = ios.getloc(); - int digits = std::use_facet<std::moneypunct<char_type>>(loc).frac_digits(); + int digits = std::use_facet<std::moneypunct<CharType>>(loc).frac_digits(); while(digits > 0) { val *= 10; digits--; } std::ios_base::fmtflags f = ios.flags(); ios.flags(f | std::ios_base::showbase); - out = std::use_facet<std::money_put<char_type>>(loc).put(out, false, ios, fill, val); + out = std::use_facet<std::money_put<CharType>>(loc).put(out, false, ios, fill, val); ios.flags(f); return out; } else { @@ -76,7 +71,7 @@ namespace boost { namespace locale { namespace impl_win { private: winlocale lc_; - }; /// num_format + }; // num_format template<typename CharType> class time_put_win : public std::time_put<CharType> { @@ -84,8 +79,7 @@ namespace boost { namespace locale { namespace impl_win { time_put_win(const winlocale& lc, size_t refs = 0) : std::time_put<CharType>(refs), lc_(lc) {} typedef typename std::time_put<CharType>::iter_type iter_type; - typedef CharType char_type; - typedef std::basic_string<char_type> string_type; + typedef std::basic_string<CharType> string_type; iter_type do_put(iter_type out, std::ios_base& /*ios*/, @@ -125,7 +119,7 @@ namespace boost { namespace locale { namespace impl_win { void to_str(std::wstring& s1, std::wstring& s2) { s2.swap(s1); } - void to_str(std::wstring& s1, std::string& s2) { s2 = conv::from_utf(s1, "UTF-8"); } + void to_str(std::wstring& s1, std::string& s2) { s2 = conv::utf_to_utf<char>(s1); } CharType do_decimal_point() const override { return *decimal_point_.c_str(); } CharType do_thousands_sep() const override { return *thousands_sep_.c_str(); } std::string do_grouping() const override { return grouping_; } diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp b/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp index c1a8107423..aa694648d8 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2022-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -11,6 +12,7 @@ #include <boost/locale/util.hpp> #include <boost/locale/util/locale_data.hpp> #include "boost/locale/util/gregorian.hpp" +#include "boost/locale/util/make_std_unique.hpp" #include "boost/locale/win32/all_generator.hpp" #include "boost/locale/win32/api.hpp" #include <algorithm> @@ -51,19 +53,16 @@ namespace boost { namespace locale { namespace impl_win { if(!invalid_) return; invalid_ = false; - if(locale_id_.empty()) { + if(locale_id_.empty()) real_id_ = util::get_system_locale(true); // always UTF-8 - lc_ = winlocale(real_id_); - } else { - lc_ = winlocale(locale_id_); + else real_id_ = locale_id_; - } util::locale_data d; d.parse(real_id_); - if(!d.is_utf8()) { - lc_ = winlocale(); - // Make it C as non-UTF8 locales are not supported - } + if(!d.is_utf8()) + lc_ = winlocale(); // Make it C as non-UTF8 locales are not supported + else + lc_ = winlocale(real_id_); } std::locale install(const std::locale& base, category_t category, char_facet_t type) override @@ -126,9 +125,9 @@ namespace boost { namespace locale { namespace impl_win { winlocale lc_; }; - localization_backend* create_localization_backend() + std::unique_ptr<localization_backend> create_localization_backend() { - return new winapi_localization_backend(); + return make_std_unique<winapi_localization_backend>(); } }}} // namespace boost::locale::impl_win diff --git a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp b/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp index 57fa5c2919..8980535e74 100644 --- a/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp +++ b/contrib/restricted/boost/locale/src/boost/locale/win32/win_backend.hpp @@ -6,10 +6,14 @@ #ifndef BOOST_LOCALE_IMPL_WIN32_LOCALIZATION_BACKEND_HPP #define BOOST_LOCALE_IMPL_WIN32_LOCALIZATION_BACKEND_HPP + +#include <boost/locale/config.hpp> +#include <memory> + namespace boost { namespace locale { class localization_backend; namespace impl_win { - localization_backend* create_localization_backend(); + std::unique_ptr<localization_backend> create_localization_backend(); } // namespace impl_win }} // namespace boost::locale #endif diff --git a/contrib/restricted/boost/locale/ya.make b/contrib/restricted/boost/locale/ya.make index 1e440342d3..4243abc00d 100644 --- a/contrib/restricted/boost/locale/ya.make +++ b/contrib/restricted/boost/locale/ya.make @@ -6,9 +6,9 @@ LICENSE(BSL-1.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(1.82.0) +VERSION(1.83.0) -ORIGINAL_SOURCE(https://github.com/boostorg/locale/archive/boost-1.82.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/boostorg/locale/archive/boost-1.83.0.tar.gz) PEERDIR( contrib/libs/icu @@ -18,6 +18,7 @@ PEERDIR( contrib/restricted/boost/iterator contrib/restricted/boost/predef contrib/restricted/boost/thread + contrib/restricted/boost/utility ) ADDINCL( diff --git a/contrib/restricted/boost/utility/include/boost/utility/string_view.hpp b/contrib/restricted/boost/utility/include/boost/utility/string_view.hpp new file mode 100644 index 0000000000..3d195b6e87 --- /dev/null +++ b/contrib/restricted/boost/utility/include/boost/utility/string_view.hpp @@ -0,0 +1,694 @@ +/* + Copyright (c) Marshall Clow 2012-2015. + Copyright (c) Beman Dawes 2015 + Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com) + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + Updated July 2015 to reflect the Library Fundamentals TS + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html +*/ + +#ifndef BOOST_STRING_VIEW_HPP +#define BOOST_STRING_VIEW_HPP + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/io/ostream_put.hpp> +#include <boost/utility/string_view_fwd.hpp> +#include <boost/throw_exception.hpp> +#include <boost/assert.hpp> + +#include <cstddef> +#include <stdexcept> +#include <algorithm> +#include <iterator> +#include <string> +#include <cstring> +#include <iosfwd> + +#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406) +// GCC 4.6 cannot handle a defaulted function with noexcept specifier +#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS +#endif + +namespace boost { + + namespace detail { + // A helper functor because sometimes we don't have lambdas + template <typename charT, typename traits> + class string_view_traits_eq { + public: + string_view_traits_eq ( charT ch ) : ch_(ch) {} + bool operator()( charT val ) const { return traits::eq (ch_, val); } + charT ch_; + }; + } + + template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp + class basic_string_view { + public: + // types + typedef traits traits_type; + typedef charT value_type; + typedef charT* pointer; + typedef const charT* const_pointer; + typedef charT& reference; + typedef const charT& const_reference; + typedef const_pointer const_iterator; // impl-defined + typedef const_iterator iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); + + // construct/copy + BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT + : ptr_(NULL), len_(0) {} + + // by defaulting these functions, basic_string_ref becomes + // trivially copy/move constructible. + BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + : ptr_(rhs.ptr_), len_(rhs.len_) {} +#endif + + basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + { + ptr_ = rhs.ptr_; + len_ = rhs.len_; + return *this; + } +#endif + + template<typename Allocator> + basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT + : ptr_(str.data()), len_(str.length()) {} + +// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +// // Constructing a string_view from a temporary string is a bad idea +// template<typename Allocator> +// basic_string_view( std::basic_string<charT, traits, Allocator>&&) +// = delete; +// #endif + + BOOST_CONSTEXPR basic_string_view(const charT* str) + : ptr_(str), len_(traits::length(str)) {} + + BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len) + : ptr_(str), len_(len) {} + + // iterators + BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; } + BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; } + BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; } + BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; } + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } + + // capacity + BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; } + BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; } + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return ~static_cast<size_type>(0) / (sizeof(value_type) * 2u); } + BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; } + + // element access + BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; } + + BOOST_CONSTEXPR const_reference at(size_type pos) const { + return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos]; + } + + BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; } + BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; } + BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; } + + // modifiers + void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension + + BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) { + BOOST_ASSERT(n <= size()); + // This check is deprecated and is left for backward compatibility. It will be removed in the future. + if ( n > len_ ) + n = len_; + ptr_ += n; + len_ -= n; + } + + BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) { + BOOST_ASSERT(n <= size()); + // This check is deprecated and is left for backward compatibility. It will be removed in the future. + if ( n > len_ ) + n = len_; + len_ -= n; + } + + BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT { + std::swap(ptr_, s.ptr_); + std::swap(len_, s.len_); + } + + // basic_string_view string operations +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + template<typename Allocator> + explicit operator std::basic_string<charT, traits, Allocator>() const { + return std::basic_string<charT, traits, Allocator>(begin(), end()); + } +#endif + +#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS + template<typename Allocator = std::allocator<charT> > + std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const { + return std::basic_string<charT, traits, Allocator>(begin(), end(), a); + } +#else + std::basic_string<charT, traits> to_string() const { + return std::basic_string<charT, traits>(begin(), end()); + } + + template<typename Allocator> + std::basic_string<charT, traits, Allocator> to_string(const Allocator& a) const { + return std::basic_string<charT, traits, Allocator>(begin(), end(), a); + } +#endif + + size_type copy(charT* s, size_type n, size_type pos=0) const { + if (pos > size()) + BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" )); + size_type rlen = (std::min)(n, len_ - pos); + traits_type::copy(s, data() + pos, rlen); + return rlen; + } + + BOOST_CXX14_CONSTEXPR basic_string_view substr() const { + return basic_string_view(data(), size()); + } + + BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const { + if ( pos > size()) + BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) ); + return basic_string_view(data() + pos, (std::min)(size() - pos, n)); + } + + BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT { + const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_)); + return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x) + const { + return substr(pos1, n1).compare(x); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, + basic_string_view x, size_type pos2, size_type n2) const { + return substr(pos1, n1).compare(x.substr(pos2, n2)); + } + + BOOST_CXX14_CONSTEXPR int compare(const charT* x) const { + return compare(basic_string_view(x)); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const { + return substr(pos1, n1).compare(basic_string_view(x)); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, + const charT* x, size_type n2) const { + return substr(pos1, n1).compare(basic_string_view(x, n2)); + } + + // Searches + BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension + return !empty() && traits::eq(c, front()); + } + + BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension + return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0; + } + + BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension + return !empty() && traits::eq(c, back()); + } + + BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension + return len_ >= x.len_ && + traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0; + } + + BOOST_CXX14_CONSTEXPR bool contains(basic_string_view s) const BOOST_NOEXCEPT { + return find(s) != npos; + } + + BOOST_CXX14_CONSTEXPR bool contains(charT c) const BOOST_NOEXCEPT { + return find(c) != npos; + } + + BOOST_CXX14_CONSTEXPR bool contains(const charT* s) const BOOST_NOEXCEPT { + return find(s) != npos; + } + + // find + BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos > size()) + return npos; + if (s.empty()) + return pos; + if (s.size() > size() - pos) + return npos; + const charT* cur = ptr_ + pos; + const charT* last = cend() - s.size() + 1; + for (; cur != last ; ++cur) { + cur = traits::find(cur, last - cur, s[0]); + if (!cur) + return npos; + if (traits::compare(cur, s.cbegin(), s.size()) == 0) + return cur - ptr_; + } + return npos; + } + BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos > size()) + return npos; + const charT* ret_ptr = traits::find(ptr_ + pos, len_ - pos, c); + if (ret_ptr) + return ret_ptr - ptr_; + return npos; + } + BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find(basic_string_view(s), pos); } + + // rfind + BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (len_ < s.len_) + return npos; + if (pos > len_ - s.len_) + pos = len_ - s.len_; + if (s.len_ == 0u) // an empty string is always found + return pos; + for (const charT* cur = ptr_ + pos; ; --cur) { + if (traits::compare(cur, s.ptr_, s.len_) == 0) + return cur - ptr_; + if (cur == ptr_) + return npos; + }; + } + BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return rfind(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return rfind(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return rfind(basic_string_view(s), pos); } + + // find_first_of + BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos >= len_ || s.len_ == 0) + return npos; + const_iterator iter = std::find_first_of + (this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT + { return find(c, pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_first_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_of(basic_string_view(s), pos); } + + // find_last_of + BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (s.len_ == 0u) + return npos; + if (pos >= len_) + pos = 0; + else + pos = len_ - (pos+1); + const_reverse_iterator iter = std::find_first_of + ( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter); + } + BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(s), pos); } + + // find_first_not_of + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos >= len_) + return npos; + if (s.len_ == 0) + return pos; + const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(s), pos); } + + // find_last_not_of + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (pos >= len_) + pos = len_ - 1; + if (s.len_ == 0u) + return pos; + pos = len_ - (pos+1); + const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(s), pos); } + + private: + template <typename r_iter> + size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT { + // Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw. + return len_ - 1 - std::distance ( first, last ); + } + + template <typename Iterator> + Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT { + for (; first != last ; ++first) + if ( 0 == traits::find(s.ptr_, s.len_, *first)) + return first; + return last; + } + + const charT *ptr_; + std::size_t len_; + }; + + +// Comparison operators +// Equality + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + if (x.size () != y.size ()) return false; + return x.compare(y) == 0; + } + +// Inequality + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + if ( x.size () != y.size ()) return true; + return x.compare(y) != 0; + } + +// Less than + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return x.compare(y) < 0; + } + +// Greater than + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return x.compare(y) > 0; + } + +// Less than or equal to + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return x.compare(y) <= 0; + } + +// Greater than or equal to + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return x.compare(y) >= 0; + } + +// "sufficient additional overloads of comparison functions" + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x == basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) == y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x == basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) == y; + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x != basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) != y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x != basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) != y; + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x < basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) < y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x < basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) < y; + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x > basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) > y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x > basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) > y; + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x <= basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) <= y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x <= basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) <= y; + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x, + const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT { + return x >= basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits, typename Allocator> + inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string<charT, traits, Allocator> & x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) >= y; + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x, + const charT * y) BOOST_NOEXCEPT { + return x >= basic_string_view<charT, traits>(y); + } + + template<typename charT, typename traits> + inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x, + basic_string_view<charT, traits> y) BOOST_NOEXCEPT { + return basic_string_view<charT, traits>(x) >= y; + } + + // Inserter + template<class charT, class traits> + inline std::basic_ostream<charT, traits>& + operator<<(std::basic_ostream<charT, traits>& os, + const basic_string_view<charT,traits>& str) { + return boost::io::ostream_put(os, str.data(), str.size()); + } + +#if 0 + // numeric conversions + // + // These are short-term implementations. + // In a production environment, I would rather avoid the copying. + // + inline int stoi (string_view str, size_t* idx=0, int base=10) { + return std::stoi ( std::string(str), idx, base ); + } + + inline long stol (string_view str, size_t* idx=0, int base=10) { + return std::stol ( std::string(str), idx, base ); + } + + inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) { + return std::stoul ( std::string(str), idx, base ); + } + + inline long long stoll (string_view str, size_t* idx=0, int base=10) { + return std::stoll ( std::string(str), idx, base ); + } + + inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) { + return std::stoull ( std::string(str), idx, base ); + } + + inline float stof (string_view str, size_t* idx=0) { + return std::stof ( std::string(str), idx ); + } + + inline double stod (string_view str, size_t* idx=0) { + return std::stod ( std::string(str), idx ); + } + + inline long double stold (string_view str, size_t* idx=0) { + return std::stold ( std::string(str), idx ); + } + + inline int stoi (wstring_view str, size_t* idx=0, int base=10) { + return std::stoi ( std::wstring(str), idx, base ); + } + + inline long stol (wstring_view str, size_t* idx=0, int base=10) { + return std::stol ( std::wstring(str), idx, base ); + } + + inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) { + return std::stoul ( std::wstring(str), idx, base ); + } + + inline long long stoll (wstring_view str, size_t* idx=0, int base=10) { + return std::stoll ( std::wstring(str), idx, base ); + } + + inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) { + return std::stoull ( std::wstring(str), idx, base ); + } + + inline float stof (wstring_view str, size_t* idx=0) { + return std::stof ( std::wstring(str), idx ); + } + + inline double stod (wstring_view str, size_t* idx=0) { + return std::stod ( std::wstring(str), idx ); + } + + inline long double stold (wstring_view str, size_t* idx=0) { + return std::stold ( std::wstring(str), idx ); + } +#endif + + // Forward declaration of Boost.ContainerHash function + template <class It> std::size_t hash_range(It, It); + + template <class charT, class traits> + std::size_t hash_value(basic_string_view<charT, traits> s) { + return boost::hash_range(s.begin(), s.end()); + } +} + +#if 0 +namespace std { + // Hashing + template<> struct hash<boost::string_view>; + template<> struct hash<boost::u16string_view>; + template<> struct hash<boost::u32string_view>; + template<> struct hash<boost::wstring_view>; +} +#endif + +#endif diff --git a/contrib/restricted/boost/utility/include/boost/utility/string_view_fwd.hpp b/contrib/restricted/boost/utility/include/boost/utility/string_view_fwd.hpp new file mode 100644 index 0000000000..dbda0de46a --- /dev/null +++ b/contrib/restricted/boost/utility/include/boost/utility/string_view_fwd.hpp @@ -0,0 +1,39 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + Updated July 2015 to reflect the Library Fundamentals TS + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html + +*/ + +#ifndef BOOST_STRING_VIEW_FWD_HPP +#define BOOST_STRING_VIEW_FWD_HPP + +#include <boost/config.hpp> +#include <string> + +namespace boost { + + template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view; + typedef basic_string_view<char, std::char_traits<char> > string_view; + typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view; + +#ifndef BOOST_NO_CXX11_CHAR16_T + typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view; +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view; +#endif + +} + +#endif |