20 #include <fmt/format.h> 22 #include <restinio/exception.hpp> 23 #include <restinio/string_view.hpp> 43 result.reserve( group.size() + group.size() / 2 );
45 for(
const char c : group )
47 if(
'=' == c ||
'!' == c ||
':' == c ||
48 '$' == c ||
'/' == c ||
'(' == c ||
')' == c )
66 result.reserve( group.size() + group.size() / 2 );
68 for(
const char c : group )
70 if(
'.' == c ||
'+' == c ||
'*' == c ||
71 '?' == c ||
'=' == c ||
'^' == c ||
72 ':' == c ||
'$' == c ||
'{' == c ||
73 '}' == c ||
'(' == c ||
')' == c ||
74 '[' == c ||
']' == c ||
'|' == c ||
75 '\\' == c ||
'/' == c )
104 return std::move(
this->sensitive( s ) );
123 return std::move(
this->strict( p ) );
142 return std::move(
this->ending( p ) );
154 m_delimiter = std::move( p );
161 return std::move(
this->delimiter( std::move( p ) ) );
173 std::string result{ std::move( d ) };
176 result = delimiter();
184 m_delimiters = std::move( p );
191 return std::move(
this->delimiters( std::move( p ) ) );
203 m_ends_with = std::move( p );
210 return std::move(
this->ends_with( std::move( p ) ) );
224 for(
const auto & e : m_ends_with )
228 result += impl::escape_string( e ) +
"|";
279 template <
typename Route_Param_Appender >
292 template <
typename Route_Param_Appender >
310 template <
typename Container >
332 throw exception_t{
"unable to insert data into names buffer" };
357 R"((\\.)|(?:\:(\w+)(?:\(((?:\\.|[^\\()])+)\))?|\(((?:\\.|[^\\()])+)\))([+*?])?)";
370 template <
typename Route_Param_Appender >
382 param_appender_sequence_t< Route_Param_Appender > & param_appender_sequence,
383 names_buffer_appender_t & names_buffer_appender )
const = 0;
403 template <
typename Route_Param_Appender >
435 template <
typename Route_Param_Appender >
448 template <
typename Route_Param_Appender,
typename Name >
457 const std::string & prefix,
458 std::string delimiter,
462 std::string pattern )
475 param_appender_sequence_t< Route_Param_Appender > & param_appender_sequence,
476 names_buffer_appender_t & names_buffer_appender )
const override 529 template <
typename Route_Param_Appender,
typename Name >
564 auto pos = strv.find(
'(' );
565 if( std::string::npos != pos )
569 "non-escaped bracket '(' at pos {}: may be unmatched group start",
573 pos = strv.find(
')' );
574 if( std::string::npos != pos )
578 "non-escaped bracket ')' at pos {}: may be unmatched group finish",
582 return std::string{ strv.data(), strv.size() };
590 template <
typename Route_Param_Appender,
typename MATCH >
597 token_list_t< Route_Param_Appender > & result )
674 template <
typename Route_Param_Appender >
748 template <
typename Route_Param_Appender,
typename Regex_Engine >
758 using regex_t =
typename Regex_Engine::compiled_regex_t;
778 template <
typename Route_Param_Appender,
typename Regex_Engine >
782 const token_list_t< Route_Param_Appender > & tokens,
788 result.m_named_params_buffer = std::make_shared< std::string >();
789 names_buffer_appender_t
790 names_buffer_appender{ path.size(), *result.m_named_params_buffer };
793 auto & param_appender_sequence = result.m_param_appender_sequence;
797 std::size_t captured_groups_count = 1 ;
799 for(
const auto & t : tokens )
801 const auto appended_token_type =
802 t->append_self_to( route, param_appender_sequence, names_buffer_appender );
804 if( token_type_t::capturing_token == appended_token_type )
805 ++captured_groups_count;
808 if( Regex_Engine::max_capture_groups() < captured_groups_count )
813 "too many parameter to capture from route: {}, while {} is the maximum",
814 captured_groups_count,
815 Regex_Engine::max_capture_groups() ) };
818 const auto & delimiter = escape_string( options.delimiter() );
819 const auto & ends_with = options.make_ends_with();
825 route +=
"(?:" + delimiter +
")?";
828 if( ends_with ==
"$" )
831 route +=
"(?=" + ends_with +
")";
835 if( !options.strict() )
836 route +=
"(?:" + delimiter +
"(?=" + ends_with +
"))?";
838 if( !tokens.empty() &&
839 !tokens.back()->is_end_delimited( options.delimiters() ) )
840 route +=
"(?=" + delimiter +
"|" + ends_with +
")";
843 result.m_regex = Regex_Engine::compile_regex(
"^" + route, options.sensitive() );
845 catch(
const std::exception & ex )
848 fmt::format(
"unable to process route \"{}\": {}", path, ex.what() ) };
861 template <
typename Route_Param_Appender,
typename Regex_Engine >
867 return impl::tokens2regexp< Route_Param_Appender, Regex_Engine >(
869 impl::parse< Route_Param_Appender >( path, options ),
std::string make_delimiter(std::string d) const
Token for paramater (named/indexed).
void handle_param_token(const options_t &options, const MATCH &match, std::string &path, bool &path_escaped, token_list_t< Route_Param_Appender > &result)
Handling of a parameterized token.
options_t & ends_with(std::vector< std::string > p) &
std::shared_ptr< std::string > m_named_params_buffer
Char buffer for holding named paramaters.
route_regex_matcher_data_t & operator=(route_regex_matcher_data_t &&)=delete
virtual bool is_end_delimited(const std::string &) const noexcept
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > ¶m_appender_sequence, names_buffer_appender_t &names_buffer_appender) const =0
bool m_ending
When false the path will match at the beginning.
parameter_token_t(Name name, const std::string &prefix, std::string delimiter, bool optional, bool repeat, bool partial, std::string pattern)
param_appender_sequence_t< Route_Param_Appender > m_param_appender_sequence
Appenders for captured values (names/indexed groups).
constexpr std::size_t group_modifier_idx
route_regex_matcher_data_t(const route_regex_matcher_data_t &)=delete
options_t & sensitive(bool s) &
const std::string & delimiter() const
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > &, names_buffer_appender_t &) const override
options_t & delimiters(std::string p) &
token_t(const token_t &)=delete
bool m_sensitive
When true the route will be case sensitive.
constexpr std::size_t group_group_idx
options_t & strict(bool p) &
const std::string m_escaped_prefix
bool m_strict
When false the trailing slash is optional.
parameter_token_t(const parameter_token_t &)=delete
auto escape_string(const std::string &group)
Excape regex control chars.
options_t && ends_with(std::vector< std::string > p) &&
token_list_t< Route_Param_Appender > parse(string_view_t route_sv, const options_t &options)
Parse a string for the raw tokens.
const std::string m_delimiter
auto escape_group(const std::string &group)
Escapes not allowed symbols in a sub-match group assigned to a parameter.
std::string make_ends_with() const
std::size_t append_name(std::size_t i) const
A stub for indexed paramaters.
const std::string m_pattern
const std::string & delimiters() const
plain_string_token_t(const std::string &path)
options_t && ending(bool p) &&
options_t & delimiter(std::string p) &
constexpr auto path_regex_str
The main path matching expression.
param_appender_t< Route_Param_Appender > make_param_setter(std::size_t)
Create default appender indexed parameter.
options_t && strict(bool p) &&
route_regex_matcher_data_t()=default
const std::vector< std::string > & ends_with() const
token_unique_ptr_t< Route_Param_Appender > create_token(std::string path)
Options for matching routes.
Appender for names to a given buffered string.
constexpr std::size_t group_name_idx
Resulting regex and param extraction for a specific route.
string_view_t append_name(const std::string &name)
Appends a given name to buffer, and returns a string view object within the context of a buffer...
std::string m_delimiters
Path delimiters.
Base class for token variants.
auto tokens2regexp(string_view_t path, const token_list_t< Route_Param_Appender > &tokens, const options_t &options)
Makes route regex matcher out of path tokens.
token_t(token_t &&)=delete
options_t && delimiter(std::string p) &&
virtual ~token_t()=default
options_t & ending(bool p) &
token_unique_ptr_t< Route_Param_Appender > create_token(Name name, std::string prefix, std::string delimiter, bool optional, bool repeat, bool partial, std::string pattern)
Creates tokent for specific parameter.
options_t && sensitive(bool s) &&
std::vector< std::string > m_ends_with
Path delimiter.
route_regex_matcher_data_t(route_regex_matcher_data_t &&)=default
auto path2regex(string_view_t path, const options_t &options)
The main path matching regexp.
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > ¶m_appender_sequence, names_buffer_appender_t &names_buffer_appender) const override
options_t && delimiters(std::string p) &&
std::string m_delimiter
Path delimiter.
virtual bool is_end_delimited(const std::string &delimiters) const noexcept override
string_view_buffer_storage_appender_t(std::size_t reserve_size, Container &buffer)
const std::string m_escaped_path
Already escaped piece of the route.
std::string check_no_unescaped_brackets(string_view_t strv, std::size_t base_pos)
Checks that string doesn't contain non-excaped brackets.
route_regex_matcher_data_t & operator=(const route_regex_matcher_data_t &)=delete
parameter_token_t(parameter_token_t &&)=delete
constexpr std::size_t group_escaped_idx
Indexes for different groups in matched result (used when extracting tokens from initial route)...
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 std::size_t group_capture_idx