summaryrefslogtreecommitdiffhomepage
path: root/src/test-helper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test-helper.cpp')
-rw-r--r--src/test-helper.cpp131
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));
+}
+