Skip to content

Commit

Permalink
Fix building on Mac and Linux due to deprecated C++ std api
Browse files Browse the repository at this point in the history
  • Loading branch information
DecoyRS committed Dec 15, 2023
1 parent ecca9dc commit 059e117
Showing 1 changed file with 57 additions and 1 deletion.
58 changes: 57 additions & 1 deletion rd-cpp/src/rd_core_cpp/src/main/std/to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
#include <atomic>
#include <future>
#include <locale>
#if defined(_MSC_VER) || defined(__APPLE__)
#include <codecvt>
#else
#include <limits>
#include <iconv.h>
#endif

#include <thirdparty.hpp>

Expand All @@ -29,12 +34,63 @@ inline std::string to_string(const char* val)
return val;
}

#if defined(_MSC_VER) || defined(__APPLE__)
template<class I, class E, class S>
struct codecvt : std::codecvt<I, E, S>
{
~codecvt()
{ }
};

inline std::string to_string(std::wstring const& val)
{
using convert_type = std::codecvt_utf8<wchar_t>;
#if defined(__APPLE__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
using convert_type = codecvt<wchar_t, char, std::mbstate_t>;
std::wstring_convert<convert_type> 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<iconv_t>::max() == icvt) {
return conv_error;
}

// I hope this does not modify the incoming buffer
wchar_t* non_const_in = const_cast<wchar_t*>(wstr.c_str());
char* iconv_in = reinterpret_cast<char*>(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<char[]>(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<size_t>(-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)
{
Expand Down

0 comments on commit 059e117

Please sign in to comment.