#ifndef XGBOOST_COMMON_CHARCONV_H_
#define XGBOOST_COMMON_CHARCONV_H_
#include <cstddef>
#include <system_error>
#include <iterator>
#include <limits>
#include "xgboost/logging.h"
namespace xgboost {
struct to_chars_result { char* ptr;
std::errc ec;
};
struct from_chars_result { const char *ptr;
std::errc ec;
};
namespace detail {
int32_t ToCharsFloatImpl(float f, char * const result);
to_chars_result ToCharsUnsignedImpl(char *first, char *last,
uint64_t const value);
from_chars_result FromCharFloatImpl(const char *buffer, const int len,
float *result);
}
template <typename T>
struct NumericLimits;
template <> struct NumericLimits<float> {
static constexpr size_t kToCharsSize = 16;
};
template <> struct NumericLimits<int64_t> {
static constexpr size_t kToCharsSize =
std::numeric_limits<int64_t>::digits10 +
3; };
inline to_chars_result to_chars(char *first, char *last, float value) { if (XGBOOST_EXPECT(!(static_cast<size_t>(last - first) >=
NumericLimits<float>::kToCharsSize),
false)) {
return {first, std::errc::value_too_large};
}
auto index = detail::ToCharsFloatImpl(value, first);
to_chars_result ret;
ret.ptr = first + index;
if (XGBOOST_EXPECT(ret.ptr < last, true)) {
ret.ec = std::errc();
} else {
ret.ec = std::errc::value_too_large;
ret.ptr = last;
}
return ret;
}
inline to_chars_result to_chars(char *first, char *last, int64_t value) { if (XGBOOST_EXPECT(first == last, false)) {
return {first, std::errc::value_too_large};
}
if (value == 0) {
*first = '0';
return {std::next(first), std::errc()};
}
uint64_t unsigned_value = value;
if (value < 0) {
*first = '-';
std::advance(first, 1);
unsigned_value = static_cast<uint64_t>(~value) + static_cast<uint64_t>(1);
}
return detail::ToCharsUnsignedImpl(first, last, unsigned_value);
}
inline from_chars_result from_chars(const char *buffer, const char *end, float &value) { from_chars_result res =
detail::FromCharFloatImpl(buffer, std::distance(buffer, end), &value);
return res;
}
}
#endif