Commit 2cfa6ee6 authored by Dominik Charousset's avatar Dominik Charousset

Add parse function for floating points

parent 27bf1b1e
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <type_traits>
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/parser/add_ascii.hpp" #include "caf/detail/parser/add_ascii.hpp"
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include "caf/detail/parser/state.hpp" #include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/optional.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
CAF_PUSH_UNUSED_LABEL_WARNING CAF_PUSH_UNUSED_LABEL_WARNING
...@@ -44,7 +46,7 @@ namespace parser { ...@@ -44,7 +46,7 @@ namespace parser {
/// @param start_value Allows another parser to pre-initialize this parser with /// @param start_value Allows another parser to pre-initialize this parser with
/// the pre-decimal value. /// the pre-decimal value.
template <class Iterator, class Sentinel, class Consumer, class ValueType> template <class Iterator, class Sentinel, class Consumer, class ValueType>
void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer, void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer,
optional<ValueType> start_value, optional<ValueType> start_value,
bool negative = false) { bool negative = false) {
// Any exponent larger than 511 always overflows. // Any exponent larger than 511 always overflows.
...@@ -184,8 +186,9 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer, ...@@ -184,8 +186,9 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer,
} }
template <class Iterator, class Sentinel, class Consumer> template <class Iterator, class Sentinel, class Consumer>
void read_floating_point(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
using value_type = typename Consumer::value_type; using consumer_type = typename std::decay<Consumer>::type;
using value_type = typename consumer_type::value_type;
return read_floating_point(ps, consumer, optional<value_type>{}); return read_floating_point(ps, consumer, optional<value_type>{});
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "caf/detail/parse.hpp" #include "caf/detail/parse.hpp"
#include "caf/detail/consumer.hpp" #include "caf/detail/consumer.hpp"
#include "caf/detail/parser/read_floating_point.hpp"
#include "caf/detail/parser/read_signed_integer.hpp" #include "caf/detail/parser/read_signed_integer.hpp"
#include "caf/detail/parser/read_unsigned_integer.hpp" #include "caf/detail/parser/read_unsigned_integer.hpp"
...@@ -46,5 +47,9 @@ PARSE_IMPL(uint32_t, unsigned_integer) ...@@ -46,5 +47,9 @@ PARSE_IMPL(uint32_t, unsigned_integer)
PARSE_IMPL(uint64_t, unsigned_integer) PARSE_IMPL(uint64_t, unsigned_integer)
PARSE_IMPL(float, floating_point)
PARSE_IMPL(double, floating_point)
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
...@@ -41,45 +41,57 @@ expected<T> read(string_view str) { ...@@ -41,45 +41,57 @@ expected<T> read(string_view str) {
} // namespace } // namespace
#define CHECK_INT(type, value) CAF_CHECK_EQUAL(read<type>(#value), type(value)) #define CHECK_NUMBER(type, value) \
CAF_CHECK_EQUAL(read<type>(#value), type(value))
#define CHECK_INT_3(type, value, cpp_value) \ #define CHECK_NUMBER_3(type, value, cpp_value) \
CAF_CHECK_EQUAL(read<type>(#value), type(cpp_value)) CAF_CHECK_EQUAL(read<type>(#value), type(cpp_value))
#define CHECK_INVALID(type, str, code) CAF_CHECK_EQUAL(read<type>(str), code) #define CHECK_INVALID(type, str, code) CAF_CHECK_EQUAL(read<type>(str), code)
CAF_TEST(valid signed integers) { CAF_TEST(valid signed integers) {
CHECK_INT(int8_t, -128); CHECK_NUMBER(int8_t, -128);
CHECK_INT(int8_t, 127); CHECK_NUMBER(int8_t, 127);
CHECK_INT(int8_t, +127); CHECK_NUMBER(int8_t, +127);
CHECK_INT(int16_t, -32768); CHECK_NUMBER(int16_t, -32768);
CHECK_INT(int16_t, 32767); CHECK_NUMBER(int16_t, 32767);
CHECK_INT(int16_t, +32767); CHECK_NUMBER(int16_t, +32767);
CHECK_INT(int32_t, -2147483648); CHECK_NUMBER(int32_t, -2147483648);
CHECK_INT(int32_t, 2147483647); CHECK_NUMBER(int32_t, 2147483647);
CHECK_INT(int32_t, +2147483647); CHECK_NUMBER(int32_t, +2147483647);
CHECK_INT(int64_t, -9223372036854775807); CHECK_NUMBER(int64_t, -9223372036854775807);
CHECK_INT(int64_t, 9223372036854775807); CHECK_NUMBER(int64_t, 9223372036854775807);
CHECK_INT(int64_t, +9223372036854775807); CHECK_NUMBER(int64_t, +9223372036854775807);
}
CAF_TEST(invalid signed integers) {
CHECK_INVALID(int8_t, "--1", pec::unexpected_character);
CHECK_INVALID(int8_t, "++1", pec::unexpected_character);
CHECK_INVALID(int8_t, "-129", pec::integer_underflow);
CHECK_INVALID(int8_t, "128", pec::integer_overflow);
CHECK_INVALID(int8_t, "~1", pec::unexpected_character);
CHECK_INVALID(int8_t, "1!", pec::trailing_character);
CHECK_INVALID(int8_t, "+", pec::unexpected_eof);
CHECK_INVALID(int8_t, "-", pec::unexpected_eof);
} }
CAF_TEST(valid unsigned integers) { CAF_TEST(valid unsigned integers) {
CHECK_INT(uint8_t, 0); CHECK_NUMBER(uint8_t, 0);
CHECK_INT(uint8_t, +0); CHECK_NUMBER(uint8_t, +0);
CHECK_INT(uint8_t, 255); CHECK_NUMBER(uint8_t, 255);
CHECK_INT(uint8_t, +255); CHECK_NUMBER(uint8_t, +255);
CHECK_INT(uint16_t, 0); CHECK_NUMBER(uint16_t, 0);
CHECK_INT(uint16_t, +0); CHECK_NUMBER(uint16_t, +0);
CHECK_INT(uint16_t, 65535); CHECK_NUMBER(uint16_t, 65535);
CHECK_INT(uint16_t, +65535); CHECK_NUMBER(uint16_t, +65535);
CHECK_INT(uint32_t, 0); CHECK_NUMBER(uint32_t, 0);
CHECK_INT(uint32_t, +0); CHECK_NUMBER(uint32_t, +0);
CHECK_INT(uint32_t, 4294967295); CHECK_NUMBER(uint32_t, 4294967295);
CHECK_INT(uint32_t, +4294967295); CHECK_NUMBER(uint32_t, +4294967295);
CHECK_INT(uint64_t, 0); CHECK_NUMBER(uint64_t, 0);
CHECK_INT(uint64_t, +0); CHECK_NUMBER(uint64_t, +0);
CHECK_INT_3(uint64_t, 18446744073709551615, 18446744073709551615ULL); CHECK_NUMBER_3(uint64_t, 18446744073709551615, 18446744073709551615ULL);
CHECK_INT_3(uint64_t, +18446744073709551615, 18446744073709551615ULL); CHECK_NUMBER_3(uint64_t, +18446744073709551615, 18446744073709551615ULL);
} }
CAF_TEST(invalid unsigned integers) { CAF_TEST(invalid unsigned integers) {
...@@ -88,4 +100,23 @@ CAF_TEST(invalid unsigned integers) { ...@@ -88,4 +100,23 @@ CAF_TEST(invalid unsigned integers) {
CHECK_INVALID(uint8_t, "256", pec::integer_overflow); CHECK_INVALID(uint8_t, "256", pec::integer_overflow);
CHECK_INVALID(uint8_t, "~1", pec::unexpected_character); CHECK_INVALID(uint8_t, "~1", pec::unexpected_character);
CHECK_INVALID(uint8_t, "1!", pec::trailing_character); CHECK_INVALID(uint8_t, "1!", pec::trailing_character);
CHECK_INVALID(uint8_t, "+", pec::unexpected_eof);
}
CAF_TEST(valid floating point numbers) {
CHECK_NUMBER(float, 1);
CHECK_NUMBER(double, 1);
CHECK_NUMBER(double, 0.01e10);
CHECK_NUMBER(double, 10e-10);
CHECK_NUMBER(double, -10e-10);
}
CAF_TEST(invalid floating point numbers) {
CHECK_INVALID(float, "1..", pec::trailing_character);
CHECK_INVALID(double, "..1", pec::unexpected_character);
CHECK_INVALID(double, "+", pec::unexpected_eof);
CHECK_INVALID(double, "-", pec::unexpected_eof);
CHECK_INVALID(double, "1e", pec::unexpected_eof);
CHECK_INVALID(double, "--0.01e10", pec::unexpected_character);
CHECK_INVALID(double, "++10e-10", pec::unexpected_character);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment