15 #include <restinio/impl/to_lower_lut.hpp> 16 #include <restinio/impl/overflow_controlled_integer_accumulator.hpp> 18 #include <restinio/utils/tuple_algorithms.hpp> 19 #include <restinio/utils/metaprogramming.hpp> 21 #include <restinio/string_view.hpp> 22 #include <restinio/compiler_features.hpp> 24 #include <restinio/exception.hpp> 25 #include <restinio/optional.hpp> 26 #include <restinio/expected.hpp> 102 std::size_t position,
178 template<
typename T >
181 using result_type = T;
182 using wrapped_type = result_type;
243 template<
typename T >
249 template<
typename T >
252 template<
typename T,
typename...
Args >
297 template<
typename T, std::size_t S >
325 "index in the result std::array is out of range, " 347 template<
typename T, std::size_t S >
353 template<
typename Char,
typename...
Args >
399 template<
typename K,
typename V,
typename...
Args >
434 using wrapped_type = result_type;
498 underlying_int_t min,
499 underlying_int_t max )
noexcept 516 constexpr static auto 526 constexpr static auto 617 constexpr char SP =
' ';
634 inline constexpr bool 668 inline constexpr bool 671 return (
ch >=
'0' &&
ch <=
'9');
701 inline constexpr bool 704 return (
ch >=
'0' &&
ch <=
'9') ||
705 (
ch >=
'A' &&
ch <=
'F') ||
706 (
ch >=
'a' &&
ch <=
'f');
943 template<
typename Result_Type >
946 using result_type = Result_Type;
950 template<
typename T,
typename =
meta::
void_t<> >
953 template<
typename T >
969 template<
typename T >
997 template<
typename Result_Type >
1000 using result_type = Result_Type;
1004 template<
typename T,
typename =
meta::
void_t<> >
1007 template<
typename T >
1023 template<
typename T >
1046 template<
typename Result_Type >
1109 template<
typename Result_Type >
1143 template<
typename Producer,
typename Transformer >
1146 static_assert( is_producer_v<Producer>,
1147 "Producer should be a producer type" );
1148 static_assert( is_transformer_v<Transformer>,
1149 "Transformer should be a transformer type" );
1160 using expected_result_t =
typename Transformer::result_type;
1178 template<
typename Producer,
typename Transformer >
1183 Producer, Transformer >;
1186 traits_checker::is_valid_transformation_result_type,
1187 "transformation result should be either T or " 1188 "expected_t<T, error_reson_t>, not expected_t<T, parse_error_t>" );
1194 using result_type =
typename Transformer::result_type;
1197 Producer && producer,
1198 Transformer && transformer )
1228 template<
typename P,
typename T >
1271 template<
typename T,
typename =
meta::
void_t<> >
1274 template<
typename T >
1289 template<
typename T >
1347 template<
typename T,
typename =
meta::
void_t<> >
1350 template<
typename T >
1366 template<
typename T >
1397 template<
typename T,
typename =
meta::
void_t<> >
1400 template<
typename T >
1419 template<
typename T >
1472 template<
typename P,
typename C >
1475 static_assert( is_producer_v<P>,
"P should be a producer type" );
1476 static_assert( is_consumer_v<C>,
"C should be a consumer type" );
1508 template<
typename P,
typename C >
1535 "Producer should be a producer type" );
1634 typename Subitems_Tuple >
1641 Subitems_Tuple && subitems )
1715 typename Subitems_Tuple >
1722 Subitems_Tuple && subitems )
1778 typename Subitems_Tuple >
1785 Subitems_Tuple && subitems )
1846 typename Subitems_Tuple >
1853 Subitems_Tuple && subitems )
1907 typename Subitems_Tuple >
1914 Subitems_Tuple && subitems )
1960 typename Subitems_Tuple >
1966 using base_type_t::base_type_t;
2007 typename Target_Type,
2008 typename Subitems_Tuple >
2017 Subitems_Tuple && subitems )
2059 typename Subitems_Tuple >
2069 std::size_t min_occurences,
2070 std::size_t max_occurences,
2071 Subitems_Tuple && subitems )
2129 template<
typename Predicate >
2132 ,
protected Predicate
2135 template<
typename... Args >
2434 template<
typename T,
typename Value_Accumulator >
2498 template<
typename T,
typename Value_Accumulator >
2506 const auto ch_to_digit = [](
char ch ) -> std::pair<
bool, T> {
2507 if( ch >=
'0' && ch <=
'9' )
2508 return std::make_pair(
true,
static_cast<T>(ch -
'0') );
2509 else if( ch >=
'A' && ch <=
'F' )
2510 return std::make_pair(
true,
static_cast<T>(10 + (ch -
'A')) );
2511 else if( ch >=
'a' && ch <=
'f' )
2512 return std::make_pair(
true,
static_cast<T>(10 + (ch -
'a')) );
2514 return std::make_pair(
false,
static_cast<T>(0) );
2517 source_t::content_consumer_t consumer{ from };
2519 digits_to_consume_t::underlying_int_t symbols_processed{};
2521 for(
auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
2523 const auto d = ch_to_digit( ch.m_ch );
2526 acc.next_digit( d.second );
2528 if( acc.overflow_detected() )
2529 return make_unexpected( parse_error_t{
2530 consumer.started_at(),
2531 error_reason_t::illegal_value_found
2534 ++symbols_processed;
2535 if( symbols_processed == digits_limit.max() )
2545 if( symbols_processed < digits_limit.min() )
2547 return make_unexpected( parse_error_t{
2548 from.current_position(),
2549 error_reason_t::pattern_not_found
2569 template<
typename T >
2597 template<
typename T >
2631 template<
typename T >
2635 "T is expected to be unsigned type" );
2662 template<
typename T >
2696 template<
typename T >
2700 "decimal_number_producer_t can be used only for signed types" );
2706 try_parse_result_type
2767 return static_cast<
T >( -(*
r) );
2809 template<
typename T >
2844 template<
typename Target_Type,
typename Value >
2846 consume( Target_Type &, Value && )
const noexcept {}
2871 template<
typename Target_Type,
typename Value >
2890 template<
typename Result_Type >
2909 template<
typename Result_Arg >
2915 template<
typename Target_Type,
typename Value >
2938 template<
typename C >
2946 template<
typename Target_Type,
typename Value >
2967 template<
typename F,
typename C >
2970 using pointer_t = F C::*;
2997 template<
typename P,
typename F,
typename C >
3040 template<
typename Input_Type >
3041 struct to_lower_transformer_t;
3061 [](
unsigned char ch ) ->
char {
3076 struct to_lower_transformer_t<
char >
3077 :
public transformer_tag<
char >
3079 using input_type =
char;
3083 transform( input_type && input )
const noexcept 3085 return restinio::impl::to_lower_case(input);
3095 template< std::size_t S >
3096 struct to_lower_transformer_t< std::array<
char, S > >
3097 :
public transformer_tag< std::array<
char, S > >
3108 [](
unsigned char ch ) ->
char {
3144 template<
typename T >
3154 template<
typename Input >
3172 template<
typename Output_Type,
typename Converter >
3178 template<
typename Convert_Arg >
3192 template<
typename Input >
3204 "the return value of converter should be either Output_Type or " 3205 "expected_t<Output_Type, error_reason_t>" );
3224 template<
typename Result_Type >
3227 using type = Result_Type;
3241 template<
typename Result_Type >
3242 using conversion_result_type_detector_t =
3261 template<
typename Converter >
3274 template<
typename Convert_Arg >
3310 template<
typename It >
3315 assert( begin != end );
3317 source_t::content_consumer_t consumer{ from };
3319 for(
auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
3321 if( ch.m_ch != *begin )
3322 return make_unexpected( parse_error_t{
3323 consumer.started_at(),
3324 error_reason_t::pattern_not_found
3326 if( ++begin == end )
3331 return make_unexpected( parse_error_t{
3332 consumer.started_at(),
3333 error_reason_t::unexpected_eof
3353 template< std::size_t Size >
3357 static_assert( 1u < Size,
"Size is expected to greater that 1" );
3396 if( m_fragment.empty() )
3397 throw exception_t(
"'fragment' value for exact_fragment_producer_t " 3398 "can't be empty!" );
3416 template<
typename It >
3421 assert( begin != end );
3423 source_t::content_consumer_t consumer{ from };
3425 for(
auto ch = from.getch(); !ch.m_eof; ch = from.getch() )
3427 if( restinio::impl::to_lower_case(ch.m_ch) != *begin )
3428 return make_unexpected( parse_error_t{
3429 consumer.started_at(),
3430 error_reason_t::pattern_not_found
3432 if( ++begin == end )
3437 return make_unexpected( parse_error_t{
3438 consumer.started_at(),
3439 error_reason_t::unexpected_eof
3461 template< std::size_t Size >
3465 static_assert( 1u < Size,
"Size is expected to greater that 1" );
3478 [](
const char src ) {
3512 if( m_fragment.empty() )
3513 throw exception_t(
"'fragment' value for exact_fragment_producer_t " 3514 "can't be empty!" );
3517 for(
auto & ch : m_fragment )
3518 ch = restinio::impl::to_lower_case( ch );
3556 static_assert( 0 !=
sizeof...(
clauses),
3557 "list of clauses can't be empty" );
3559 "all arguments for produce() should be clauses" );
3592 template<
typename...
Clauses >
3597 static_assert( 0 !=
sizeof...(
clauses),
3598 "list of clauses can't be empty" );
3600 "all arguments for alternatives() should be clauses" );
3631 template<
typename...
Clauses >
3636 static_assert( 0 !=
sizeof...(
clauses),
3637 "list of clauses can't be empty" );
3639 "all arguments for maybe() should be clauses" );
3673 template<
typename...
Clauses >
3678 static_assert( 0 !=
sizeof...(
clauses),
3679 "list of clauses can't be empty" );
3681 "all arguments for not_clause() should be clauses" );
3715 template<
typename...
Clauses >
3720 static_assert( 0 !=
sizeof...(
clauses),
3721 "list of clauses can't be empty" );
3723 "all arguments for sequence() should be clauses" );
3755 template<
typename...
Clauses >
3760 static_assert( 0 !=
sizeof...(
clauses),
3761 "list of clauses can't be empty" );
3763 "all arguments for sequence() should be clauses" );
3818 template<
typename...
Clauses >
3823 static_assert( 0 !=
sizeof...(
clauses),
3824 "list of clauses can't be empty" );
3826 "all arguments for force_only_this_alternative() should " 3889 static_assert( 0 !=
sizeof...(
clauses),
3890 "list of clauses can't be empty" );
3892 "all arguments for repeat() should be clauses" );
4215 template<
typename T >
4254 template<
typename T >
4276 template<
typename T >
4304 template<
typename T >
4346 template<
typename T >
4384 template<
typename T >
4390 "decimal_number_p() can be used only for signed numeric types" );
4437 template<
typename T >
4443 "decimal_number_p() can be used only for signed numeric types" );
4513 template<
typename F >
4632 template<
typename T >
4661 template<
typename T >
5047 "Producer should be a value producer type" );
5127 constexpr char hex_digits[] =
"0123456789abcdef";
5170 result +=
"unexpected EOF at ";
Subitems_Tuple m_subitems
hexadecimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &)
Unexpected end of input is encontered when some character expected.
A producer for the case when a decimal digit is expected in the input stream.
RESTINIO_NODISCARD expected_t< T, parse_error_t > try_parse_hexdigits_with_digits_limit(source_t &from, digits_to_consume_t digits_limit, Value_Accumulator acc) noexcept
Helper function for parsing integers in hexadecimal form.
void consume(Target_Type &dest, Value &&src) const noexcept(noexcept(m_consumer(dest, std::forward< Value >(src))))
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse_caseless_exact_fragment(source_t &from, It begin, It end)
A helper template for the detection of type to be produced as conversion procedure.
error_reason_t
Reason of parsing error.
alternatives_clause_t(Subitems_Tuple &&subitems)
RESTINIO_NODISCARD expected_t< T, parse_error_t > try_parse(source_t &from) const noexcept
RESTINIO_NODISCARD auto try_parse(source_t &from) const noexcept
repeat_clause_t(std::size_t min_occurences, std::size_t max_occurences, Subitems_Tuple &&subitems)
A producer for the case when a particual character is expected in the input stream.
digits_to_consume_t m_digits_limit
A producer for the case when any character except the specific sentinel character is expected in the ...
A producer for the case when a symbol should belong to specified range.
constexpr digits_to_consume_t(underlying_int_t total) noexcept
Entity is a producer of values.
RESTINIO_NODISCARD std::string make_error_description(const parse_error_t &error, string_view_t from)
Make textual description of error returned by try_parse function.
std::size_t m_position
Position in the input stream.
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
underlying_int_t m_max
Maximal number of digits to consume.
Required pattern is not found in the input.
A special wrapper for std::array type to be used inside a producer during the parsing.
caseless_exact_fixed_size_fragment_producer_t(const char(&f)[Size])
One character extracted from the input stream.
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse(source_t &from)
std::size_t m_max_occurences
constexpr digits_to_consume_t(underlying_int_t min, underlying_int_t max) noexcept
static RESTINIO_NODISCARD try_parse_result_type try_parse_with_this_first_symbol(source_t &from, char first_symbol, Digits_Limit_Maker &&digits_limit_maker) noexcept
constexpr bool is_clause_v
A meta-value to check whether T is a consumer type.
Entity is a transformer of a value from one type to another.
void consume(Target_Type &dest, Value &&) const
None of alternatives was found in the input.
Entity is a transformer-proxy. It can't be used directly, only for binding a producer and transformer...
RESTINIO_NODISCARD expected_t< T, parse_error_t > try_parse(source_t &from) const noexcept
static constexpr entity_type_t entity_type
RESTINIO_NODISCARD expected_t< T, parse_error_t > try_parse(source_t &from) const noexcept
Unexpected character is found in the input.
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse(source_t &from)
A producer for the case when a hexadecimal digit is expected in the input stream. ...
A consumer for the case when a specific value should be used as the result instead of the value produ...
just_result_consumer_t(Result_Arg &&result) noexcept(noexcept(Result_Type{std::forward< Result_Arg >(result)}))
exact_fragment_producer_t(std::string fragment)
Subitems_Tuple m_subitems
not_clause_t(Subitems_Tuple &&subitems)
Subitems_Tuple m_subitems
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &target)
static void as_result(wrapped_type &to, result_type &&what)
constexpr std::size_t N
A special marker that means infinite repetitions.
symbol_from_range_producer_t(char left, char right)
maybe_clause_t(Subitems_Tuple &&subitems)
Subitems_Tuple m_subitems
and_clause_t(Subitems_Tuple &&subitems)
consume_value_clause_t(P &&producer, C &&consumer)
caseless_symbol_producer_t(char expected)
void consume(Target_Type &dest, Value &&src) const
Subitems_Tuple m_subitems
Entity is a consumer of values. It requires a value on the input and doesn't produces anything...
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
constexpr bool is_transformer_proxy_v
A meta-value to check whether T is a transformer-proxy type.
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse(source_t &from)
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &target)
std::array< T, S > m_array
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &target)
any_symbol_if_not_producer_t(char sentinel)
caseless_exact_fragment_producer_t(std::string fragment)
A special consumer that simply throws any value away.
constexpr bool is_transformer_v
A meta-value to check whether T is a transformer type.
Illegal value was found in the input.
const string_view_t m_data
The content to be used as "input stream".
digits_to_consume_t m_digits_limit
std::size_t m_min_occurences
Entity is a clause. It doesn't produces anything.
There are some unconsumed non-whitespace characters in the input after the completion of parsing...
RESTINIO_NODISCARD expected_t< Target_Type, parse_error_t > try_parse(source_t &from)
exact_fixed_size_fragment_producer_t(const char(&f)[Size])
produce_t(Subitems_Tuple &&subitems)
constexpr char HTAB
A constant for Horizontal Tab value.
A failure of parsing an alternative marked as "force only this alternative".
Subitems_Tuple m_subitems
digits_to_consume_t m_digits_limit
caseless_particular_symbol_predicate_t(char v) noexcept
non_negative_decimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
void consume(Target_Type &, Value &&) const noexcept
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse_exact_fragment(source_t &from, It begin, It end)
A template for consumers that store a value to the specified field of a target object.
A consumer for the case when the current value should be returned as the result for the producer at o...
A special base class to be used with clauses.
symbol_producer_template_t(Args &&... args)
void commit() noexcept
Consume all acquired content.
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
static void to_container(wrapped_type &, value_type &&) noexcept
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &dest)
A special base class to be used with producers.
custom_consumer_t(C &&consumer)
symbol_producer_t(char expected)
source_t(string_view_t data) noexcept
Initializing constructor.
std::array< char, Size-1u > m_fragment
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
underlying_int_t m_min
Minimal number of digits to consume.
static RESTINIO_NODISCARD result_type && unwrap_value(wrapped_type &v)
RESTINIO_NODISCARD static constexpr auto from_one_to_max() noexcept
void consume(C &to, F &&value) const noexcept(noexcept(to.*m_ptr=std::move(value)))
string_view_t::size_type m_index
The current position in the input stream.
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &target)
static constexpr entity_type_t entity_type
constexpr bool is_consumer_v
A meta-value to check whether T is a consumer type.
parse_error_t(std::size_t position, error_reason_t reason) noexcept
Initializing constructor.
field_setter_consumer_t(pointer_t ptr) noexcept
RESTINIO_NODISCARD expected_t< T, parse_error_t > try_parse(source_t &from) const noexcept
Result_Type make_copy_of_result() const noexcept(noexcept(Result_Type{m_result}))
std::array< char, Size-1u > m_fragment
static void as_result(wrapped_type &, result_type &&) noexcept
decimal_number_producer_with_digits_limit_t(digits_to_consume_t digits_limit)
RESTINIO_NODISCARD expected_t< bool, parse_error_t > try_parse(source_t &from)
A producer for the case when a particual character is expected in the input stream.
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &)
RESTINIO_NODISCARD error_reason_t reason() const noexcept
Get the reason of the error.
constexpr char SP
A constant for SPACE value.
RESTINIO_NODISCARD optional_t< parse_error_t > try_process(source_t &from, Target_Type &target)
RESTINIO_NODISCARD expected_t< char, parse_error_t > try_parse(source_t &from) const noexcept
A template for consumers that are released by lambda/functional objects.
A special type to be used in the case where there is no need to store produced value.
entity_type_t
A marker for distinguish different kind of entities in parser.
RESTINIO_NODISCARD bool operator()(const char actual) const noexcept
error_reason_t m_reason
The reason of the error.
A metafunction for detection of actual result_value_wrapper type for T.
Subitems_Tuple m_subitems
RESTINIO_NODISCARD constexpr bool operator()(const char) const noexcept
sequence_clause_t(Subitems_Tuple &&subitems)
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container ¶ms, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
constexpr bool is_producer_v
A meta-value to check whether T is a producer type.