diff --git a/include/stdex/compat.hpp b/include/stdex/compat.hpp index 9b98e1c93..4d5c6dfd3 100644 --- a/include/stdex/compat.hpp +++ b/include/stdex/compat.hpp @@ -10,7 +10,10 @@ #include "windows.h" #include #include +#else +#include #endif +#include #include #ifndef _In_ @@ -223,3 +226,108 @@ size_t _countof(const T (&arr)[N]) #define lockf64 lockf #define ftruncate64 ftruncate #endif + +#ifndef _WIN32 +// On Windows, wchar_t is UTF-16. On POSIX it is UTF32, and we are left out of UTF16 support in std C++. + +namespace std +{ + /// + /// This is a poor man's instantiation of a `std::ctype`. + /// + template <> + class ctype : public locale::facet, public ctype_base + { + public: + typedef char16_t char_type; + + explicit ctype(size_t refs = 0) : + locale::facet(refs), + m_ctypew(std::use_facet>(std::locale())) + {} + + bool is(mask m, char_type c) const + { + return do_is(m, c); + } + + const char_type* is(const char_type* low, const char_type* high, mask* vec) const + { + return do_is(low, high, vec); + } + + const char_type* scan_is(mask m, const char_type* low, const char_type* high) const + { + return do_scan_is(m, low, high); + } + + const char_type* scan_not(mask m, const char_type* low, const char_type* high) const + { + return do_scan_not(m, low, high); + } + + char_type toupper(char_type c) const + { + return do_toupper(c); + } + + const char_type* toupper(char_type* low, const char_type* high) const + { + return do_toupper(low, high); + } + + char_type tolower(char_type c) const + { + return do_tolower(c); + } + + const char_type* tolower(char_type* low, const char_type* high) const + { + return do_tolower(low, high); + } + + char_type widen(char c) const + { + return do_widen(c); + } + + const char* widen(const char* low, const char* high, char_type* to) const + { + return do_widen(low, high, to); + } + + char narrow(char_type c, char dfault) const + { + return do_narrow(c, dfault); + } + + const char_type* narrow(const char_type* low, const char_type* high, char dfault, char* to) const + { + return do_narrow(low, high, dfault, to); + } + + static inline locale::id id; + + protected: + const std::ctype &m_ctypew; + + bool do_is(mask m, char_type c) const { return m_ctypew.is(m, c); } + + const char_type* do_is(const char_type* low, const char_type* high, mask* vec) const; + const char_type* do_scan_is(mask m, const char_type* low, const char_type* high) const; + const char_type* do_scan_not(mask m, const char_type* low, const char_type* high) const; + + char_type do_toupper(char_type c) const { return m_ctypew.toupper(c); } + + const char_type* do_toupper(char_type* low, const char_type* high) const; + + char_type do_tolower(char_type c) const { return m_ctypew.tolower(c); } + + const char_type* do_tolower(char_type* low, const char_type* high) const; + char_type do_widen(char) const; + const char* do_widen(const char* low, const char* high, char_type* dest) const; + char do_narrow(char_type, char dfault) const; + const char_type* do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const; + }; +} +#endif