diff --git a/include/ircd/locale.h b/include/ircd/locale.h index 9554e0a5f..1612815ae 100644 --- a/include/ircd/locale.h +++ b/include/ircd/locale.h @@ -32,6 +32,7 @@ namespace locale { // On newer platforms (gcc-5 etc) these conversions are standard C++. // On older platforms the definition file may use boost::locale. size_t convert(const char16_t *const &, char *const &buf, const size_t &max); +size_t convert(const char *const &, char16_t *const &buf, const size_t &max); // uint8_t = max*2 std::string convert(const char16_t *const &); std::string convert(const std::u16string &); std::u16string convert(const char *const &); diff --git a/ircd/locale.cc b/ircd/locale.cc index 5f6e226dc..23a1be25a 100644 --- a/ircd/locale.cc +++ b/ircd/locale.cc @@ -112,3 +112,39 @@ ircd::locale::convert(const char16_t *const &str, return rb_strlcpy(buf, s.c_str(), max); } #endif + +#ifdef HAVE_CODECVT +size_t +ircd::locale::convert(const char *const &str, + char16_t *const &buf, + const size_t &max) +{ + static std::wstring_convert, char16_t> converter; + + if(unlikely(!max)) + return 0; + + //TODO: optimize + const auto s(converter.from_bytes(str)); + const auto cpsz(std::min(s.size(), size_t(max - 1))); + memcpy(buf, s.data(), cpsz * 2); + buf[cpsz] = char16_t(0); + return cpsz; +} +#else +size_t +ircd::locale::convert(const char *const &str, + char16_t *const &buf, + const size_t &max) +{ + if(unlikely(!max)) + return 0; + + //TODO: optimize + const auto s(boost::locale::conv::utf_to_utf(str)); + const auto cpsz(std::min(s.size(), size_t(max - 1))); + memcpy(buf, s.data(), cpsz * 2); + buf[cpsz] = char16_t(0); + return cpsz; +} +#endif