Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
b901e279
Commit
b901e279
authored
May 14, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a parser for producing numbers or timespans
parent
f5109d55
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
257 additions
and
4 deletions
+257
-4
libcaf_core/caf/detail/parser/ec.hpp
libcaf_core/caf/detail/parser/ec.hpp
+4
-4
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
+116
-0
libcaf_core/test/read_number_or_timespan.cpp
libcaf_core/test/read_number_or_timespan.cpp
+137
-0
No files found.
libcaf_core/caf/detail/parser/ec.hpp
View file @
b901e279
...
@@ -33,10 +33,10 @@ enum class ec : uint8_t {
...
@@ -33,10 +33,10 @@ enum class ec : uint8_t {
unexpected_eof
,
unexpected_eof
,
/// Parser stopped after reading an unexpected character.
/// Parser stopped after reading an unexpected character.
unexpected_character
,
unexpected_character
,
///
Cannot construct a negative caf::duration
.
///
Parsed integer exceeds the number of available bits of a `timespan`
.
negative_duration
,
timespan_overflow
,
///
Cannot construct a caf::duration with a value exceeding uint32_t
.
///
Tried constructing a `timespan` with from a floating point number
.
duration_overflow
,
fractional_timespan
,
/// Too many characters for an atom.
/// Too many characters for an atom.
too_many_characters
,
too_many_characters
,
/// Unrecognized character after escaping `\`.
/// Unrecognized character after escaping `\`.
...
...
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
0 → 100644
View file @
b901e279
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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/none.hpp"
#include "caf/optional.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/read_number.hpp"
#include "caf/detail/parser/state.hpp"
namespace
caf
{
namespace
detail
{
namespace
parser
{
/// Reads a number or a duration, i.e., on success produces an `int64_t`, a
/// `double`, or a `timespan`.
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_number_or_timespan
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
using
namespace
std
::
chrono
;
struct
interim_consumer
{
variant
<
none_t
,
int64_t
,
double
>
interim
;
void
value
(
int64_t
x
)
{
interim
=
x
;
}
void
value
(
double
x
)
{
interim
=
x
;
}
};
optional
<
timespan
>
res
;
interim_consumer
ic
;
auto
has_int
=
[
&
]
{
return
holds_alternative
<
int64_t
>
(
ic
.
interim
);
};
auto
has_dbl
=
[
&
]
{
return
holds_alternative
<
double
>
(
ic
.
interim
);
};
auto
get_int
=
[
&
]
{
return
get
<
int64_t
>
(
ic
.
interim
);
};
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
{
if
(
res
!=
none
)
{
consumer
.
value
(
*
res
);
}
else
if
(
!
holds_alternative
<
none_t
>
(
ic
.
interim
))
{
if
(
has_int
())
consumer
.
value
(
get_int
());
else
consumer
.
value
(
get
<
double
>
(
ic
.
interim
));
}
}
});
start
();
state
(
init
)
{
invoke_fsm
(
read_number
(
ps
,
ic
),
has_number
)
}
term_state
(
has_number
)
{
checked_epsilon
(
has_int
(),
has_integer
)
checked_epsilon
(
has_dbl
(),
has_double
)
}
term_state
(
has_double
)
{
invalid_input
(
is_char
<
'u'
>
,
ec
::
fractional_timespan
)
invalid_input
(
is_char
<
'n'
>
,
ec
::
fractional_timespan
)
invalid_input
(
is_char
<
'm'
>
,
ec
::
fractional_timespan
)
invalid_input
(
is_char
<
's'
>
,
ec
::
fractional_timespan
)
}
term_state
(
has_integer
)
{
input
(
is_char
<
'u'
>
,
have_u
)
input
(
is_char
<
'n'
>
,
have_n
)
input
(
is_char
<
'm'
>
,
have_m
)
action
(
is_char
<
's'
>
,
done
,
res
=
seconds
(
get_int
()))
}
state
(
have_u
)
{
action
(
is_char
<
's'
>
,
done
,
res
=
microseconds
(
get_int
()))
}
state
(
have_n
)
{
action
(
is_char
<
's'
>
,
done
,
res
=
nanoseconds
(
get_int
()))
}
state
(
have_m
)
{
input
(
is_char
<
'i'
>
,
have_mi
)
action
(
is_char
<
's'
>
,
done
,
res
=
milliseconds
(
get_int
()))
}
state
(
have_mi
)
{
action
(
is_char
<
'n'
>
,
done
,
res
=
minutes
(
get_int
()))
}
term_state
(
done
)
{
// nop
}
fin
();
}
}
// namespace parser
}
// namespace detail
}
// namespace caf
libcaf_core/test/read_number_or_timespan.cpp
0 → 100644
View file @
b901e279
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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. *
******************************************************************************/
#define CAF_SUITE read_number_or_timespan
#include <string>
#include "caf/test/unit_test.hpp"
#include "caf/variant.hpp"
#include "caf/detail/parser/read_number_or_timespan.hpp"
using
namespace
caf
;
using
namespace
std
::
chrono
;
using
detail
::
parser
::
ec
;
namespace
{
struct
number_or_timespan_parser_consumer
{
variant
<
int64_t
,
double
,
timespan
>
x
;
template
<
class
T
>
void
value
(
T
y
)
{
x
=
y
;
}
};
struct
res_t
{
variant
<
ec
,
double
,
int64_t
,
timespan
>
val
;
template
<
class
T
>
res_t
(
T
&&
x
)
:
val
(
std
::
forward
<
T
>
(
x
))
{
// nop
}
};
std
::
string
to_string
(
const
res_t
&
x
)
{
return
deep_to_string
(
x
.
val
);
}
bool
operator
==
(
const
res_t
&
x
,
const
res_t
&
y
)
{
if
(
x
.
val
.
index
()
!=
y
.
val
.
index
())
return
false
;
// Implements a safe equal comparison for double.
caf
::
test
::
equal_to
f
;
using
caf
::
get
;
using
caf
::
holds_alternative
;
if
(
holds_alternative
<
ec
>
(
x
.
val
))
return
f
(
get
<
ec
>
(
x
.
val
),
get
<
ec
>
(
y
.
val
));
if
(
holds_alternative
<
double
>
(
x
.
val
))
return
f
(
get
<
double
>
(
x
.
val
),
get
<
double
>
(
y
.
val
));
if
(
holds_alternative
<
int64_t
>
(
x
.
val
))
return
f
(
get
<
int64_t
>
(
x
.
val
),
get
<
int64_t
>
(
y
.
val
));
return
f
(
get
<
timespan
>
(
x
.
val
),
get
<
timespan
>
(
y
.
val
));
}
struct
number_or_timespan_parser
{
res_t
operator
()(
std
::
string
str
)
{
detail
::
parser
::
state
<
std
::
string
::
iterator
>
res
;
number_or_timespan_parser_consumer
f
;
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_number_or_timespan
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
};
struct
fixture
{
number_or_timespan_parser
p
;
};
template
<
class
T
>
typename
std
::
enable_if
<
std
::
is_integral
<
T
>::
value
,
res_t
>::
type
res
(
T
x
)
{
return
{
static_cast
<
int64_t
>
(
x
)};
}
template
<
class
T
>
typename
std
::
enable_if
<
std
::
is_floating_point
<
T
>::
value
,
res_t
>::
type
res
(
T
x
)
{
return
{
static_cast
<
double
>
(
x
)};
}
template
<
class
Rep
,
class
Period
>
res_t
res
(
std
::
chrono
::
duration
<
Rep
,
Period
>
x
)
{
return
std
::
chrono
::
duration_cast
<
timespan
>
(
x
);
}
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
read_number_or_timespan_tests
,
fixture
)
CAF_TEST
(
valid
numbers
and
timespans
)
{
CAF_CHECK_EQUAL
(
p
(
"123"
),
res
(
123
));
CAF_CHECK_EQUAL
(
p
(
"123.456"
),
res
(
123.456
));
CAF_CHECK_EQUAL
(
p
(
"123s"
),
res
(
seconds
(
123
)));
CAF_CHECK_EQUAL
(
p
(
"123ns"
),
res
(
nanoseconds
(
123
)));
CAF_CHECK_EQUAL
(
p
(
"123ms"
),
res
(
milliseconds
(
123
)));
CAF_CHECK_EQUAL
(
p
(
"123us"
),
res
(
microseconds
(
123
)));
CAF_CHECK_EQUAL
(
p
(
"123min"
),
res
(
minutes
(
123
)));
}
CAF_TEST
(
invalid
timespans
)
{
CAF_CHECK_EQUAL
(
p
(
"12.3s"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3m"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ms"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3mi"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3min"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"123ss"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"123m"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123mi"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123u"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123n"
),
ec
::
unexpected_eof
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment