17 return std::unexpected(
21 std::size_t index = value.front() ==
'-' ? 1 : 0;
22 if (index == value.size()) {
23 return std::unexpected(
27 bool saw_digit =
false;
28 bool saw_decimal =
false;
29 bool fractional_digit =
false;
30 for (; index < value.size(); ++index) {
31 const char ch = value[index];
32 if (ch >=
'0' && ch <=
'9') {
34 fractional_digit = fractional_digit || saw_decimal;
37 if (ch ==
'.' && !saw_decimal && saw_digit) {
41 return std::unexpected(
44 if (!saw_digit || (saw_decimal && !fractional_digit)) {
45 return std::unexpected(
57 return std::unexpected(
Error{
61 const bool negative = wire_.front() ==
'-';
62 const std::size_t first = negative ? 1 : 0;
63 const std::size_t decimal = wire_.find(
'.', first);
64 const std::size_t whole_end = decimal == std::string::npos ? wire_.size() : decimal;
65 const std::size_t fractional_start =
66 decimal == std::string::npos ? wire_.size() : decimal + 1;
67 const std::size_t fractional_size = wire_.size() - fractional_start;
69 if (fractional_size > scale) {
70 for (std::size_t i = fractional_start + scale; i < wire_.size(); ++i) {
71 if (wire_[i] !=
'0') {
73 "fixed-point conversion would lose precision",
80 const std::uint64_t positive_limit =
81 negative ? std::uint64_t{std::numeric_limits<std::int64_t>::max()} + 1U
82 : std::uint64_t{std::numeric_limits<std::int64_t>::max()};
83 std::uint64_t magnitude = 0;
84 const auto append_digit = [&](
char ch) ->
bool {
85 const std::uint64_t digit =
static_cast<std::uint64_t
>(ch -
'0');
86 if (magnitude > (positive_limit - digit) / 10U) {
89 magnitude = magnitude * 10U + digit;
93 for (std::size_t i = first; i < whole_end; ++i) {
94 if (!append_digit(wire_[i])) {
95 return overflow_error();
98 for (std::uint8_t i = 0; i < scale; ++i) {
99 const char digit = i < fractional_size ? wire_[fractional_start + i] :
'0';
100 if (!append_digit(digit)) {
101 return overflow_error();
105 if (negative && magnitude == positive_limit) {
106 return std::numeric_limits<std::int64_t>::min();
108 const std::int64_t signed_value =
static_cast<std::int64_t
>(magnitude);
109 return negative ? -signed_value : signed_value;