xgboost
charconv.h
Go to the documentation of this file.
1 
8 #ifndef XGBOOST_COMMON_CHARCONV_H_
9 #define XGBOOST_COMMON_CHARCONV_H_
10 
11 #include <cstddef>
12 #include <system_error>
13 #include <iterator>
14 #include <limits>
15 
16 #include "xgboost/logging.h"
17 
18 namespace xgboost {
19 
20 struct to_chars_result { // NOLINT
21  char* ptr;
22  std::errc ec;
23 };
24 
25 struct from_chars_result { // NOLINT
26  const char *ptr;
27  std::errc ec;
28 };
29 
30 namespace detail {
31 int32_t ToCharsFloatImpl(float f, char * const result);
32 to_chars_result ToCharsUnsignedImpl(char *first, char *last,
33  uint64_t const value);
34 from_chars_result FromCharFloatImpl(const char *buffer, const int len,
35  float *result);
36 } // namespace detail
37 
38 template <typename T>
40 
41 template <> struct NumericLimits<float> {
42  // Unlike std::numeric_limit<float>::max_digits10, which represents the **minimum**
43  // length of base10 digits that are necessary to uniquely represent all distinct values.
44  // This value is used to represent the maximum length. As sign bit occupies 1 character:
45  // sign + len(str(2^24)) + decimal point + `E` + sign + len(str(2^8)) + '\0'
46  static constexpr size_t kToCharsSize = 16;
47 };
48 
49 template <> struct NumericLimits<int64_t> {
50  // From llvm libcxx: numeric_limits::digits10 returns value less on 1 than desired for
51  // unsigned numbers. For example, for 1-byte unsigned value digits10 is 2 (999 can not
52  // be represented), so we need +1 here.
53  static constexpr size_t kToCharsSize =
54  std::numeric_limits<int64_t>::digits10 +
55  3; // +1 for minus, +1 for digits10, +1 for '\0' just to be safe.
56 };
57 
58 inline to_chars_result to_chars(char *first, char *last, float value) { // NOLINT
59  if (XGBOOST_EXPECT(!(static_cast<size_t>(last - first) >=
61  false)) {
62  return {first, std::errc::value_too_large};
63  }
64  auto index = detail::ToCharsFloatImpl(value, first);
65  to_chars_result ret;
66  ret.ptr = first + index;
67 
68  if (XGBOOST_EXPECT(ret.ptr < last, true)) {
69  ret.ec = std::errc();
70  } else {
71  ret.ec = std::errc::value_too_large;
72  ret.ptr = last;
73  }
74  return ret;
75 }
76 
77 inline to_chars_result to_chars(char *first, char *last, int64_t value) { // NOLINT
78  if (XGBOOST_EXPECT(first == last, false)) {
79  return {first, std::errc::value_too_large};
80  }
81  // first write '-' and convert to unsigned, then write the rest.
82  if (value == 0) {
83  *first = '0';
84  return {std::next(first), std::errc()};
85  }
86  uint64_t unsigned_value = value;
87  if (value < 0) {
88  *first = '-';
89  std::advance(first, 1);
90  unsigned_value = uint64_t(~value) + uint64_t(1);
91  }
92  return detail::ToCharsUnsignedImpl(first, last, unsigned_value);
93 }
94 
95 inline from_chars_result from_chars(const char *buffer, const char *end, // NOLINT
96  float &value) { // NOLINT
97  from_chars_result res =
98  detail::FromCharFloatImpl(buffer, std::distance(buffer, end), &value);
99  return res;
100 }
101 } // namespace xgboost
102 
103 #endif // XGBOOST_COMMON_CHARCONV_H_
std::errc ec
Definition: charconv.h:27
to_chars_result to_chars(char *first, char *last, float value)
Definition: charconv.h:58
Definition: charconv.h:20
Definition: charconv.h:25
std::errc ec
Definition: charconv.h:22
const char * ptr
Definition: charconv.h:26
from_chars_result FromCharFloatImpl(const char *buffer, const int len, float *result)
namespace of xgboost
Definition: base.h:102
to_chars_result ToCharsUnsignedImpl(char *first, char *last, uint64_t const value)
Definition: charconv.h:39
#define XGBOOST_EXPECT(cond, ret)
Definition: base.h:75
int32_t ToCharsFloatImpl(float f, char *const result)
char * ptr
Definition: charconv.h:21
from_chars_result from_chars(const char *buffer, const char *end, float &value)
Definition: charconv.h:95