diff options
Diffstat (limited to 'src/test-helper.cpp')
-rw-r--r-- | src/test-helper.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/test-helper.cpp b/src/test-helper.cpp new file mode 100644 index 0000000..d441895 --- /dev/null +++ b/src/test-helper.cpp @@ -0,0 +1,131 @@ +#include "test-helper.h" + +#include <array> +#include <chrono> +#include <codecvt> +#include <deque> +#include <exception> +#include <limits> +#include <list> +#include <locale> +#include <ostream> +#include <random> +#include <string> +#include <tuple> +#include <type_traits> +#include <vector> + +// output operators must be in same namespace as the type itself +namespace std { + +#ifdef __cpp_char8_t + std::ostream& operator<<(std::ostream& os, std::basic_string<utf8_t> const& s) + { + os << "["; + for (auto& c: s) + os << " " << std::to_string(static_cast<uint8_t>(c)); + os << "]"; + + return os; + } +#endif + + std::ostream& operator<<(std::ostream& os, std::basic_string<char16_t> const& s) + { + os << "["; + for (auto& c: s) + os << " " << std::to_string(static_cast<uint16_t>(c)); + os << "]"; + + return os; + } + + std::ostream& operator<<(std::ostream& os, std::basic_string<char32_t> const& s) + { + os << "["; + for (auto& c: s) + os << " " << std::to_string(static_cast<uint32_t>(c)); + os << "]"; + + return os; + } + +} // namespace std + +namespace { + + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + template<class Facet> + struct deletable_facet : Facet + { + template<class ...Args> + deletable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {} + ~deletable_facet() {} + }; + + // char8_t instead of char doesn't work w/ clang++-13 + C++20 (yet?) + std::wstring_convert<deletable_facet<std::codecvt<char16_t, char, std::mbstate_t>>, char16_t> conv16; + std::wstring_convert<deletable_facet<std::codecvt<char32_t, char, std::mbstate_t>>, char32_t> conv32; + +} // namespace + +template<> +std::basic_string<utf8_t> std_convert<utf8_t, utf8_t>(const std::basic_string<utf8_t>& s) +{ + std::string a{s.begin(), s.end()}; + a = conv32.to_bytes(conv32.from_bytes(a)); + return std::basic_string<utf8_t>{a.begin(), a.end()}; +} + +template<> +std::basic_string<char16_t> std_convert<utf8_t, char16_t>(const std::basic_string<utf8_t>& s) +{ + std::string a{s.begin(), s.end()}; + return conv16.from_bytes(a); +} + +template<> +std::basic_string<char32_t> std_convert<utf8_t, char32_t>(const std::basic_string<utf8_t>& s) +{ + std::string a{s.begin(), s.end()}; + return conv32.from_bytes(a); +} + +template<> +std::basic_string<utf8_t> std_convert<char16_t, utf8_t>(const std::basic_string<char16_t>& s) +{ + auto result{conv16.to_bytes(s)}; + return std::basic_string<utf8_t>(result.begin(), result.end()); +} + +template<> +std::basic_string<char16_t> std_convert<char16_t, char16_t>(const std::basic_string<char16_t>& s) +{ + return conv16.from_bytes(conv16.to_bytes(s)); +} + +template<> +std::basic_string<char32_t> std_convert<char16_t, char32_t>(const std::basic_string<char16_t>& s) +{ + return conv32.from_bytes(conv16.to_bytes(s)); +} + +template<> +std::basic_string<utf8_t> std_convert<char32_t, utf8_t>(const std::basic_string<char32_t>& s) +{ + auto result{conv32.to_bytes(s)}; + return std::basic_string<utf8_t>(result.begin(), result.end()); +} + +template<> +std::basic_string<char16_t> std_convert<char32_t, char16_t>(const std::basic_string<char32_t>& s) +{ + return conv16.from_bytes(conv32.to_bytes(s)); +} + +template<> +std::basic_string<char32_t> std_convert<char32_t, char32_t>(const std::basic_string<char32_t>& s) +{ + return conv32.from_bytes(conv32.to_bytes(s)); +} + |