From 059e117b13fe0834250bca33f16677ff13649d77 Mon Sep 17 00:00:00 2001 From: Alexander Pirogov Date: Fri, 15 Dec 2023 15:08:51 +0200 Subject: [PATCH] Fix building on Mac and Linux due to deprecated C++ std api --- .../src/rd_core_cpp/src/main/std/to_string.h | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/rd-cpp/src/rd_core_cpp/src/main/std/to_string.h b/rd-cpp/src/rd_core_cpp/src/main/std/to_string.h index fd8b6725f..e24c220e2 100644 --- a/rd-cpp/src/rd_core_cpp/src/main/std/to_string.h +++ b/rd-cpp/src/rd_core_cpp/src/main/std/to_string.h @@ -9,7 +9,12 @@ #include #include #include +#if defined(_MSC_VER) || defined(__APPLE__) #include +#else +#include +#include +#endif #include @@ -29,12 +34,63 @@ inline std::string to_string(const char* val) return val; } +#if defined(_MSC_VER) || defined(__APPLE__) +template +struct codecvt : std::codecvt +{ + ~codecvt() + { } +}; + inline std::string to_string(std::wstring const& val) { - using convert_type = std::codecvt_utf8; +#if defined(__APPLE__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + using convert_type = codecvt; std::wstring_convert converter; return converter.to_bytes(val); +#if defined(__APPLE__) +#pragma clang diagnostic pop +#endif +} +#else +const std::string conv_error("Conversion Error"); +inline std::string to_string(const std::wstring& wstr) { + std::string result; + if (wstr.empty()) { + return result; + } + // Order of arguments is to, from + auto icvt = iconv_open("UTF-8", "WCHAR_T"); + // CentOS is not happy with -1 + if (std::numeric_limits::max() == icvt) { + return conv_error; + } + + // I hope this does not modify the incoming buffer + wchar_t* non_const_in = const_cast(wstr.c_str()); + char* iconv_in = reinterpret_cast(non_const_in); + size_t iconv_in_bytes = wstr.length() * sizeof(wchar_t); + // Temp buffer, assume every code point converts into 3 bytes, this should be enough + // We do not convert terminating zeros + const size_t buffer_len = wstr.length() * 3; + auto buffer = std::make_unique(buffer_len); + + char* iconv_out = buffer.get(); + size_t iconv_out_bytes = buffer_len; + auto ret = iconv(icvt, &iconv_in, &iconv_in_bytes, &iconv_out, &iconv_out_bytes); + if (static_cast(-1) == ret) { + result = conv_error; + } else { + size_t converted_len = buffer_len - iconv_out_bytes; + result.assign(buffer.get(), converted_len); + } + iconv_close(icvt); + return result; } +#endif inline std::string to_string(std::thread::id const& id) {