30#ifndef ETL_TO_ARITHMETIC_INCLUDED
31#define ETL_TO_ARITHMETIC_INCLUDED
69 ETL_ENUM_TYPE(Valid,
"Valid")
70 ETL_ENUM_TYPE(Invalid_Radix,
"Invalid Radix")
71 ETL_ENUM_TYPE(Invalid_Format,
"Invalid Format")
72 ETL_ENUM_TYPE(Invalid_Float,
"Invalid Float")
73 ETL_ENUM_TYPE(Signed_To_Unsigned,
"Signed To Unsigned")
74 ETL_ENUM_TYPE(Overflow,
"Overflow")
81 template<
typename TValue>
105 : conversion_value(
other.conversion_value)
106 , conversion_status(
other.conversion_status)
117 return (conversion_status.
error() == error_type::Valid);
138 return conversion_value;
175 conversion_value =
value_;
193 value_type conversion_value;
194 unexpected_type conversion_status;
197 namespace private_to_arithmetic
199 template <
typename T =
void>
202 static ETL_CONSTANT
char Positive_Char =
'+';
203 static ETL_CONSTANT
char Negative_Char =
'-';
204 static ETL_CONSTANT
char Radix_Point1_Char =
'.';
205 static ETL_CONSTANT
char Radix_Point2_Char =
',';
206 static ETL_CONSTANT
char Exponential_Char =
'e';
209 template <
typename T>
210 ETL_CONSTANT
char char_statics<T>::Positive_Char;
212 template <
typename T>
213 ETL_CONSTANT
char char_statics<T>::Negative_Char;
215 template <
typename T>
216 ETL_CONSTANT
char char_statics<T>::Radix_Point1_Char;
218 template <
typename T>
219 ETL_CONSTANT
char char_statics<T>::Radix_Point2_Char;
221 template <
typename T>
222 ETL_CONSTANT
char char_statics<T>::Exponential_Char;
224 struct char_constant : char_statics<>
232 bool is_valid(
char c, etl::radix::value_type radix)
236 case etl::radix::binary:
238 return (c >=
'0') && (c <=
'1');
242 case etl::radix::octal:
244 return (c >=
'0') && (c <=
'7');
248 case etl::radix::decimal:
250 return (c >=
'0') && (c <=
'9');
254 case etl::radix::hexadecimal:
256 return ((c >=
'0') && (c <=
'9')) || ((c >=
'a') && (c <=
'f'));
272 char digit_value(
char c, etl::radix::value_type radix)
276 case etl::radix::binary:
277 case etl::radix::octal:
278 case etl::radix::decimal:
284 case etl::radix::hexadecimal:
286 if ((c >=
'0') && (c <=
'9'))
292 return (c -
'a') + 10;
309 char to_lower(
char c)
311 if ((c >=
'A') && (c <=
'Z'))
320 template <
typename TChar>
323 char convert(TChar c)
325 return to_lower(
static_cast<char>(c));
332 template <
typename TChar>
340 const char c = convert(view[0]);
341 const bool has_positive_prefix = (c == char_constant::Positive_Char);
342 const bool has_negative_prefix = (c == char_constant::Negative_Char);
345 if (has_positive_prefix || has_negative_prefix)
347 view.remove_prefix(1);
348 return has_negative_prefix;
361 bool is_valid_radix(
const etl::radix::value_type radix)
363 return (radix == etl::radix::binary) ||
364 (radix == etl::radix::octal) ||
365 (radix == etl::radix::decimal) ||
366 (radix == etl::radix::hexadecimal);
372 template <
typename TValue>
373 struct integral_accumulator
377 integral_accumulator(etl::radix::value_type radix_, TValue maximum_)
381 , conversion_status(to_arithmetic_status::Valid)
388 bool add(
const char c)
390 bool is_success =
false;
391 bool is_not_overflow =
false;
393 const bool is_valid_char = is_valid(c, radix);
397 TValue old_value = integral_value;
398 integral_value *= radix;
401 is_not_overflow = ((integral_value / radix) == old_value);
405 const char digit = digit_value(c, radix);
408 is_not_overflow = ((maximum - digit) >= integral_value);
410 if ((maximum - digit) >= integral_value)
412 integral_value += digit;
419 if (is_valid_char ==
false)
421 conversion_status = to_arithmetic_status::Invalid_Format;
423 else if (is_not_overflow ==
false)
425 conversion_status = to_arithmetic_status::Overflow;
434 bool has_value()
const
436 return conversion_status == to_arithmetic_status::Valid;
444 return integral_value;
450 to_arithmetic_status status()
const
452 return conversion_status;
457 etl::radix::value_type radix;
459 TValue integral_value;
460 to_arithmetic_status conversion_status;
466 struct floating_point_accumulator
470 floating_point_accumulator()
472 , floating_point_value(0)
473 , is_negative_mantissa(false)
474 , is_negative_exponent(false)
475 , expecting_sign(true)
477 , state(Parsing_Integral)
478 , conversion_status(to_arithmetic_status::Valid)
487 bool is_success =
true;
492 case Parsing_Integral:
494 if (expecting_sign && ((c == char_constant::Positive_Char) || (c == char_constant::Negative_Char)))
496 is_negative_mantissa = (c == char_constant::Negative_Char);
497 expecting_sign =
false;
500 else if ((c == char_constant::Radix_Point1_Char) || (c == char_constant::Radix_Point2_Char))
502 expecting_sign =
false;
503 state = Parsing_Fractional;
506 else if (c == char_constant::Exponential_Char)
508 expecting_sign =
true;
509 state = Parsing_Exponential;
511 else if (is_valid(c, etl::radix::decimal))
513 const char digit = digit_value(c, etl::radix::decimal);
514 floating_point_value *= 10;
515 is_negative_mantissa ? floating_point_value -= digit : floating_point_value += digit;
516 conversion_status = to_arithmetic_status::Valid;
517 expecting_sign =
false;
521 conversion_status = to_arithmetic_status::Invalid_Format;
528 case Parsing_Fractional:
531 if ((c == char_constant::Radix_Point1_Char) || (c == char_constant::Radix_Point2_Char))
533 conversion_status = to_arithmetic_status::Invalid_Format;
537 else if (c == char_constant::Exponential_Char)
539 expecting_sign =
true;
540 state = Parsing_Exponential;
542 else if (is_valid(c, etl::radix::decimal))
544 const char digit = digit_value(c, etl::radix::decimal);
546 long double fraction = digit / divisor;
547 is_negative_mantissa ? floating_point_value -= fraction : floating_point_value += fraction;
548 conversion_status = to_arithmetic_status::Valid;
552 conversion_status = to_arithmetic_status::Invalid_Format;
559 case Parsing_Exponential:
561 if (expecting_sign && ((c == char_constant::Positive_Char) || (c == char_constant::Negative_Char)))
563 is_negative_exponent = (c == char_constant::Negative_Char);
564 expecting_sign =
false;
567 else if ((c == char_constant::Radix_Point1_Char) || (c == char_constant::Radix_Point2_Char) || (c == char_constant::Exponential_Char))
569 conversion_status = to_arithmetic_status::Invalid_Format;
572 else if (is_valid(c, etl::radix::decimal))
574 const char digit = digit_value(c, etl::radix::decimal);
575 exponent_value *= etl::radix::decimal;
576 is_negative_exponent ? exponent_value -= digit : exponent_value += digit;
580 conversion_status = to_arithmetic_status::Invalid_Format;
600 bool has_value()
const
602 return (conversion_status == to_arithmetic_status::Valid);
608 long double value()
const
610 return floating_point_value;
616 to_arithmetic_status status()
const
618 return conversion_status;
626 return exponent_value;
639 long double floating_point_value;
640 bool is_negative_mantissa;
641 bool is_negative_exponent;
645 to_arithmetic_status conversion_status;
651 template <
size_t Bits>
652 struct accumulator_type_select;
655 struct accumulator_type_select<8U>
657 typedef uint32_t type;
661 struct accumulator_type_select<16U>
663 typedef uint32_t type;
667 struct accumulator_type_select<32U>
669 typedef uint32_t type;
672#if ETL_USING_64BIT_TYPES
674 struct accumulator_type_select<64U>
676 typedef uint64_t type;
683 template <
typename TChar,
typename TAccumulatorType>
687 const etl::radix::value_type radix,
688 const TAccumulatorType maximum)
696 integral_accumulator<TAccumulatorType> accumulator(radix, maximum);
698 while ((itr != itr_end) && accumulator.add(convert(*itr)))
704 if (accumulator.has_value())
706 accumulator_result = accumulator.value();
710 accumulator_result = unexpected_type(accumulator.status());
713 return accumulator_result;
720 template <
typename TValue,
typename TChar>
725 const etl::radix::value_type
radix)
727 using namespace etl::private_to_arithmetic;
730 typedef typename result_type::unexpected_type unexpected_type;
734 if (is_valid_radix(
radix))
737 const bool is_negative = check_and_remove_sign_prefix(
view);
741 result = unexpected_type(to_arithmetic_status::Invalid_Format);
748 result = unexpected_type(to_arithmetic_status::Signed_To_Unsigned);
780 result = unexpected_type(to_arithmetic_status::Invalid_Radix);
789 template <
typename TValue,
typename TChar>
801 template <
typename TValue,
typename TChar>
813 template <
typename TValue,
typename TChar>
825 template <
typename TValue,
typename TChar>
837 template <
typename TValue,
typename TChar>
849 template <
typename TValue,
typename TChar>
861 template <
typename TValue,
typename TChar>
873 template <
typename TValue,
typename TChar>
885 template <
typename TValue,
typename TChar>
891 using namespace etl::private_to_arithmetic;
894 typedef typename result_type::unexpected_type unexpected_type;
900 result = unexpected_type(to_arithmetic_status::Invalid_Format);
904 floating_point_accumulator accumulator;
909 while ((itr != itr_end) && accumulator.add(convert(*itr)))
915 result = unexpected_type(accumulator.status());
917 if (result.has_value())
919 TValue value =
static_cast<TValue>(accumulator.value());
920 int exponent = accumulator.exponent();
922 value *=
pow(
static_cast<TValue>(10.0),
static_cast<TValue>(exponent));
925 if (etl::is_infinity(value))
927 result = unexpected_type(to_arithmetic_status::Overflow);
929 else if (etl::is_nan(value))
931 result = unexpected_type(to_arithmetic_status::Invalid_Float);
946 template <
typename TValue,
typename TChar>
958 template <
typename TValue,
typename TChar>
970 template <
typename TValue,
typename TChar>
986 if (
lhs.has_value() &&
rhs.has_value())
988 return (
lhs.value() ==
rhs.value());
992 return (
lhs.status() ==
rhs.status());
999template <
typename T,
typename U>
1008template <
typename T,
typename U>
1017template <
typename T>
1026template <
typename T,
typename U>
1035template <
typename T,
typename U>
Status values for to_arithmetic.
Definition to_arithmetic.h:83
ETL_CONSTEXPR14 to_arithmetic_result(const to_arithmetic_result &other)
Copy constructor.
Definition to_arithmetic.h:104
ETL_CONSTEXPR14 to_arithmetic_result & operator=(value_type value_)
Assignment from a value.
Definition to_arithmetic.h:173
ETL_NODISCARD ETL_CONSTEXPR14 error_type error() const
Definition to_arithmetic.h:164
ETL_NODISCARD ETL_CONSTEXPR14 value_type value() const
Definition to_arithmetic.h:136
ETL_CONSTEXPR14 to_arithmetic_result()
Default constructor.
Definition to_arithmetic.h:94
ETL_NODISCARD ETL_CONSTEXPR14 bool has_value() const
Returns true if the result has a valid value.
Definition to_arithmetic.h:115
const TError & error() const
Get the error.
Definition expected.h:200
Definition integral_limits.h:516
is_unsigned
Definition type_traits_generator.h:1016
make_unsigned
Definition type_traits_generator.h:1176
bitset_ext
Definition absolute.h:38
ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< TValue >::value, etl::to_arithmetic_result< TValue > >::type to_arithmetic(etl::basic_string_view< TChar > view, const etl::radix::value_type radix)
Text to integral from view and radix value type.
Definition to_arithmetic.h:724
pair holds two objects of arbitrary type
Definition utility.h:164
Status values for to_arithmetic.
Definition to_arithmetic.h:57
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:984
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:1018