21#include <system_error>
25#include "absl/base/attributes.h"
26#include "absl/log/check.h"
27#include "absl/status/statusor.h"
28#include "absl/strings/charconv.h"
29#include "absl/strings/escaping.h"
30#include "absl/strings/str_format.h"
31#include "absl/strings/string_view.h"
41template <
typename T,
typename =
void>
42struct std_to_chars_has_overload : std::false_type {};
45struct std_to_chars_has_overload<
46 T,
std::void_t<decltype(std::to_chars(
47 std::declval<char*>(), std::declval<char*>(), std::declval<T>()))>>
52inline constexpr bool std_to_chars_has_overload_v =
53 std_to_chars_has_overload<T>::value;
68using RoundTripDoubleBuffer = std::array<char, 32>;
76 typename Double = double,
77 typename std::enable_if_t<std_to_chars_has_overload_v<Double>,
bool> =
true>
78absl::string_view RoundTripDoubleToBuffer(
const Double
value,
79 RoundTripDoubleBuffer& buffer) {
81 std::to_chars(buffer.data(), buffer.data() + buffer.size(),
value);
82 CHECK(result.ec == std::errc()) << std::make_error_code(result.ec).message();
83 return absl::string_view(buffer.data(), result.ptr - buffer.data());
90template <
typename Double = double,
91 typename std::enable_if_t<!std_to_chars_has_overload_v<Double>,
93absl::string_view RoundTripDoubleToBuffer(
const Double
value,
94 RoundTripDoubleBuffer& buffer) {
98 absl::SNPrintF(buffer.data(), buffer.size(),
"%.*g",
99 std::numeric_limits<double>::max_digits10,
value);
100 CHECK_GT(written, 0);
101 CHECK_LT(written, buffer.size());
102 return absl::string_view(buffer.data(), written);
108 std_to_chars_has_overload_v<double>;
112 RoundTripDoubleBuffer buffer;
113 out << RoundTripDoubleToBuffer(format.value_, buffer);
118 RoundTripDoubleBuffer buffer;
119 return std::string(RoundTripDoubleToBuffer(
value, buffer));
123 const absl::string_view str_value) {
124 const char*
const begin = str_value.data();
125 const char*
const end = begin + str_value.size();
127 const auto result = absl::from_chars(begin,
end, ret);
128 if (result.ec == std::errc()) {
129 if (result.ptr !=
end) {
131 <<
'"' << absl::CEscape(str_value)
132 <<
"\" has unexpected suffix starting at index "
133 << (result.ptr - begin);
138 case std::errc::invalid_argument:
140 <<
'"' << absl::CEscape(str_value) <<
"\" is not a valid double";
141 case std::errc::result_out_of_range:
143 <<
'"' << absl::CEscape(str_value)
144 <<
"\" does not fit in a double precision float";
147 <<
"parsing of \"" << absl::CEscape(str_value)
148 <<
"\" failed with an unexpected error: "
149 << std::make_error_code(result.ec).message();
In SWIG mode, we don't want anything besides these top-level includes.
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
ABSL_CONST_INIT const bool kStdToCharsDoubleIsSupported
StatusBuilder InternalErrorBuilder()
StatusBuilder InvalidArgumentErrorBuilder()
std::optional< int64_t > end