Commit 3237a7d8 authored by Dominik Charousset's avatar Dominik Charousset

Add parser for timespan

parent dc8113b5
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/read_number.hpp" #include "caf/detail/parser/read_number.hpp"
#include "caf/detail/parser/read_timespan.hpp"
#include "caf/detail/parser/state.hpp" #include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
...@@ -57,23 +58,19 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps, ...@@ -57,23 +58,19 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps,
interim = x; interim = x;
} }
}; };
optional<timespan> res;
interim_consumer ic; interim_consumer ic;
auto has_int = [&] { return holds_alternative<int64_t>(ic.interim); }; auto has_int = [&] { return holds_alternative<int64_t>(ic.interim); };
auto has_dbl = [&] { return holds_alternative<double>(ic.interim); }; auto has_dbl = [&] { return holds_alternative<double>(ic.interim); };
auto get_int = [&] { return get<int64_t>(ic.interim); }; auto get_int = [&] { return get<int64_t>(ic.interim); };
auto g = make_scope_guard([&] { auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character) { if (ps.code <= pec::trailing_character) {
if (res != none) { if (has_dbl())
consumer.value(*res); consumer.value(get<double>(ic.interim));
} else if (!holds_alternative<none_t>(ic.interim)) { else if (has_int())
if (has_int()) consumer.value(get_int());
consumer.value(get_int());
else
consumer.value(get<double>(ic.interim));
}
} }
}); });
// clang-format off
start(); start();
state(init) { state(init) {
fsm_epsilon(read_number(ps, ic), has_number) fsm_epsilon(read_number(ps, ic), has_number)
...@@ -83,31 +80,17 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps, ...@@ -83,31 +80,17 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps,
epsilon_if(has_dbl(), has_double) epsilon_if(has_dbl(), has_double)
} }
term_state(has_double) { term_state(has_double) {
error_transition(pec::fractional_timespan, "unms") error_transition(pec::fractional_timespan, "unmsh")
} }
term_state(has_integer) { term_state(has_integer) {
transition(have_u, 'u') fsm_epsilon(read_timespan(ps, consumer, get_int()),
transition(have_n, 'n') done, "unmsh", g.disable())
transition(have_m, 'm')
transition(done, 's', res = seconds(get_int()))
}
state(have_u) {
transition(done, 's', res = microseconds(get_int()))
}
state(have_n) {
transition(done, 's', res = nanoseconds(get_int()))
}
state(have_m) {
transition(have_mi, 'i')
transition(done, 's', res = milliseconds(get_int()))
}
state(have_mi) {
transition(done, 'n', res = minutes(get_int()))
} }
term_state(done) { term_state(done) {
// nop // nop
} }
fin(); fin();
// clang-format on
} }
} // namespace parser } // namespace parser
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <chrono>
#include <cstdint>
#include <string>
#include "caf/config.hpp"
#include "caf/detail/parser/read_signed_integer.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/optional.hpp"
#include "caf/pec.hpp"
#include "caf/timestamp.hpp"
CAF_PUSH_UNUSED_LABEL_WARNING
#include "caf/detail/parser/fsm.hpp"
namespace caf {
namespace detail {
namespace parser {
/// Reads a timespan.
template <class Iterator, class Sentinel, class Consumer>
void read_timespan(state<Iterator, Sentinel>& ps, Consumer& consumer,
optional<int64_t> num = none) {
using namespace std::chrono;
struct interim_consumer {
using value_type = int64_t;
void value(int64_t y) {
x = y;
}
int64_t x = 0;
};
interim_consumer ic;
timespan result;
auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character)
consumer.value(result);
});
// clang-format off
start();
state(init) {
epsilon_if(num, has_integer, any_char, ic.x = *num)
fsm_epsilon(read_signed_integer(ps, ic), has_integer)
}
state(has_integer) {
transition(have_u, 'u')
transition(have_n, 'n')
transition(have_m, 'm')
transition(done, 's', result = seconds(ic.x))
transition(done, 'h', result = hours(ic.x))
}
state(have_u) {
transition(done, 's', result = microseconds(ic.x))
}
state(have_n) {
transition(done, 's', result = nanoseconds(ic.x))
}
state(have_m) {
transition(have_mi, 'i')
transition(done, 's', result = milliseconds(ic.x))
}
state(have_mi) {
transition(done, 'n', result = minutes(ic.x))
}
term_state(done) {
// nop
}
fin();
// clang-format on
}
} // namespace parser
} // namespace detail
} // namespace caf
#include "caf/detail/parser/fsm_undef.hpp"
CAF_POP_WARNINGS
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE read_timespan
#include "caf/detail/parser/read_timespan.hpp"
#include "caf/test/dsl.hpp"
#include <chrono>
using namespace caf;
namespace {
using std::chrono::duration_cast;
timespan operator"" _ns(unsigned long long x) {
return duration_cast<timespan>(std::chrono::nanoseconds(x));
}
timespan operator"" _us(unsigned long long x) {
return duration_cast<timespan>(std::chrono::microseconds(x));
}
timespan operator"" _ms(unsigned long long x) {
return duration_cast<timespan>(std::chrono::milliseconds(x));
}
timespan operator"" _s(unsigned long long x) {
return duration_cast<timespan>(std::chrono::seconds(x));
}
timespan operator"" _h(unsigned long long x) {
return duration_cast<timespan>(std::chrono::hours(x));
}
struct timespan_consumer {
using value_type = timespan;
void value(timespan y) {
x = y;
}
timespan x;
};
optional<timespan> read(string_view str) {
timespan_consumer consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()};
detail::parser::read_timespan(ps, consumer);
if (ps.code != pec::success)
return none;
return consumer.x;
}
} // namespace
CAF_TEST(todo) {
CAF_CHECK_EQUAL(read("12ns"), 12_ns);
CAF_CHECK_EQUAL(read("34us"), 34_us);
CAF_CHECK_EQUAL(read("56ms"), 56_ms);
CAF_CHECK_EQUAL(read("78s"), 78_s);
CAF_CHECK_EQUAL(read("60min"), 1_h);
CAF_CHECK_EQUAL(read("90h"), 90_h);
}
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