RESTinio
path2regex.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  Utility for converting express.js style routes to regexp.
7 
8  Code adopted from https://github.com/pillarjs/path-to-regexp.
9 */
10 #pragma once
11 
12 #include <cassert>
13 #include <regex>
14 #include <string>
15 #include <vector>
16 #include <memory>
17 #include <functional>
18 #include <iterator>
19 
20 #include <restinio/impl/include_fmtlib.hpp>
21 
22 #include <restinio/exception.hpp>
23 #include <restinio/string_view.hpp>
24 
25 namespace restinio
26 {
27 
28 namespace path2regex
29 {
30 
31 namespace impl
32 {
33 
34 //
35 // escape_group()
36 //
37 
38 //! Escapes not allowed symbols in a sub-match group assigned to a parameter.
39 inline auto
40 escape_group( const std::string & group )
41 {
42  std::string result;
43  result.reserve( group.size() + group.size() / 2 );
44 
45  for( const char c : group )
46  {
47  if( '=' == c || '!' == c || ':' == c ||
48  '$' == c || '/' == c || '(' == c || ')' == c )
49  result+= '\\';
50 
51  result+= c;
52  }
53 
54  return result;
55 }
56 
57 //
58 // escape_string()
59 //
60 
61 //! Excape regex control chars.
62 inline auto
63 escape_string( const std::string & group )
64 {
65  std::string result;
66  result.reserve( group.size() + group.size() / 2 );
67 
68  for( const char c : group )
69  {
70  if( '.' == c || '+' == c || '*' == c ||
71  '?' == c || '=' == c || '^' == c ||
72  ':' == c || '$' == c || '{' == c ||
73  '}' == c || '(' == c || ')' == c ||
74  '[' == c || ']' == c || '|' == c ||
75  '\\' == c || '/' == c )
76  result+= '\\';
77 
78  result+= c;
79  }
80 
81  return result;
82 }
83 
84 } /* namespace impl */
85 
86 //
87 // options_t
88 //
89 
90 //! Options for matching routes.
91 class options_t
92 {
93  public:
94  options_t &
95  sensitive( bool s ) &
96  {
97  m_sensitive = s;
98  return *this;
99  }
100 
101  options_t &&
102  sensitive( bool s ) &&
103  {
104  return std::move( this->sensitive( s ) );
105  }
106 
107  bool
108  sensitive() const
109  {
110  return m_sensitive;
111  }
112 
113  options_t &
114  strict( bool p ) &
115  {
116  m_strict = p;
117  return *this;
118  }
119 
120  options_t &&
121  strict( bool p ) &&
122  {
123  return std::move( this->strict( p ) );
124  }
125 
126  bool
127  strict() const
128  {
129  return m_strict;
130  }
131 
132  options_t &
133  ending( bool p ) &
134  {
135  m_ending = p;
136  return *this;
137  }
138 
139  options_t &&
140  ending( bool p ) &&
141  {
142  return std::move( this->ending( p ) );
143  }
144 
145  bool
146  ending() const
147  {
148  return m_ending;
149  }
150 
151  options_t &
152  delimiter( std::string p ) &
153  {
154  m_delimiter = std::move( p );
155  return *this;
156  }
157 
158  options_t &&
159  delimiter( std::string p ) &&
160  {
161  return std::move( this->delimiter( std::move( p ) ) );
162  }
163 
164  const std::string &
165  delimiter() const
166  {
167  return m_delimiter;
168  }
169 
170  std::string
172  {
173  std::string result{ std::move( d ) };
174 
175  if( result.empty() )
176  result = delimiter();
177 
178  return result;
179  }
180 
181  options_t &
182  delimiters( std::string p ) &
183  {
184  m_delimiters = std::move( p );
185  return *this;
186  }
187 
188  options_t &&
189  delimiters( std::string p ) &&
190  {
191  return std::move( this->delimiters( std::move( p ) ) );
192  }
193 
194  const std::string &
195  delimiters() const
196  {
197  return m_delimiters;
198  }
199 
200  options_t &
201  ends_with( std::vector< std::string > p ) &
202  {
203  m_ends_with = std::move( p );
204  return *this;
205  }
206 
207  options_t &&
208  ends_with( std::vector< std::string > p ) &&
209  {
210  return std::move( this->ends_with( std::move( p ) ) );
211  }
212 
213  const std::vector< std::string > &
214  ends_with() const
215  {
216  return m_ends_with;
217  }
218 
219  std::string
221  {
222  std::string result;
223 
224  for( const auto & e : m_ends_with )
225  {
226  if( !e.empty() )
227  {
228  result += impl::escape_string( e ) + "|";
229  }
230  }
231 
232  result += "$";
233 
234  return result;
235  }
236 
237  private:
238  //! When true the route will be case sensitive.
239  bool m_sensitive{ false };
240 
241  //! When false the trailing slash is optional.
242  bool m_strict{ false };
243 
244  //! When false the path will match at the beginning.
245  bool m_ending{ true };
246 
247  //! Path delimiter.
249 
250  //! Path delimiters.
252 
253  //! Path delimiter.
255 };
256 
257 //
258 // param_appender_t
259 //
260 
261 //! Appends sub-match as a request parameter to specified container.
262 template < typename Route_Param_Appender >
263 using param_appender_t =
265 
266 //
267 // param_appender_sequence_t
268 //
269 
270 //! A sequence of appenders for submatches.
271 template < typename Route_Param_Appender >
273 
274 //
275 // make_param_setter
276 //
277 
278 //! Create default appender for named parameter.
279 template < typename Route_Param_Appender >
282 {
283  return
284  [ key ](
288  };
289 }
290 
291 //! Create default appender indexed parameter.
292 template < typename Route_Param_Appender >
295 {
296  return
299  };
300 }
301 
302 namespace impl
303 {
304 
305 //
306 // string_view_buffer_storage_appender_t
307 //
308 
309 //! Appender for names to a given buffered string.
310 template < typename Container >
312 {
313  public:
314  string_view_buffer_storage_appender_t( std::size_t reserve_size, Container & buffer )
315  : m_buffer{ buffer }
316  {
319  }
320 
321  //! Appends a given name to buffer,
322  //! and returns a string view object within the context of a buffer.
325  {
326  const auto n = name.size();
327  if( m_buffer.capacity() - m_buffer.size() < n )
328  {
329  // This actually should never happen,
330  // because buffer is set to the size
331  // of a whole route-path that itself contains all the names.
332  throw exception_t{ "unable to insert data into names buffer" };
333  }
334 
335  // Remember where previous names finishes.
336  const auto prev_size = m_buffer.size();
337 
338  std::copy( name.data(), name.data() + n, std::back_inserter( m_buffer ) );
339  return string_view_t{ m_buffer.data() + prev_size, n };
340  }
341 
342  //! A stub for indexed paramaters.
343  std::size_t
345  {
346  return i;
347  }
348 
349  private:
350  Container & m_buffer;
351 };
352 
354 
355 //! The main path matching expression.
356 constexpr auto path_regex_str =
357  R"((\\.)|(?:\:(\w+)(?:\(((?:\\.|[^\\()])+)\))?|\(((?:\\.|[^\\()])+)\))([+*?])?)";
358 
359 enum class token_type_t : std::uint8_t
360 {
361  plain_string,
363 };
364 
365 //
366 // token_t
367 //
368 
369 //! Base class for token variants.
370 template < typename Route_Param_Appender >
371 class token_t
372 {
373  public:
374  token_t() = default;
375  token_t( const token_t & ) = delete;
376  token_t( token_t && ) = delete;
377  virtual ~token_t() = default;
378 
379  virtual token_type_t
381  std::string & route,
382  param_appender_sequence_t< Route_Param_Appender > & param_appender_sequence,
383  names_buffer_appender_t & names_buffer_appender ) const = 0;
384 
385  virtual bool
386  is_end_delimited( const std::string & ) const noexcept
387  {
388  return false;
389  }
390 };
391 
392 template < typename Route_Param_Appender >
394 
395 template < typename Route_Param_Appender >
397 
398 //
399 // plain_string_token_t
400 //
401 
402 //! Plain str token.
403 template < typename Route_Param_Appender >
404 class plain_string_token_t final : public token_t< Route_Param_Appender >
405 {
406  public:
407  plain_string_token_t( const std::string & path )
409  , m_last_char{ path.back() }
410  {}
411 
412  virtual token_type_t
414  std::string & route,
416  names_buffer_appender_t & ) const override
417  {
419 
420  return token_type_t::plain_string;
421  }
422 
423  virtual bool
424  is_end_delimited( const std::string & delimiters ) const noexcept override
425  {
426  return std::string::npos != delimiters.find( m_last_char );
427  }
428 
429  private:
430  //! Already escaped piece of the route.
432  const char m_last_char;
433 };
434 
435 template < typename Route_Param_Appender >
438 {
440  return std::make_unique< token_t >( std::move( path ) );
441 }
442 
443 //
444 // parameter_token_t
445 //
446 
447 //! Token for paramater (named/indexed).
448 template < typename Route_Param_Appender, typename Name >
449 class parameter_token_t final : public token_t< Route_Param_Appender >
450 {
451  public:
452  parameter_token_t( const parameter_token_t & ) = delete;
453  parameter_token_t( parameter_token_t && ) = delete;
454 
456  Name name,
457  const std::string & prefix,
458  std::string delimiter,
459  bool optional,
460  bool repeat,
461  bool partial,
462  std::string pattern )
463  : m_name{ std::move( name ) }
465  , m_delimiter{ std::move( delimiter ) }
466  , m_optional{ optional }
467  , m_repeat{ repeat }
468  , m_partial{ partial }
469  , m_pattern{ std::move( pattern ) }
470  {}
471 
472  virtual token_type_t
474  std::string & route,
475  param_appender_sequence_t< Route_Param_Appender > & param_appender_sequence,
476  names_buffer_appender_t & names_buffer_appender ) const override
477  {
478  // Basic capturing pattern.
479  auto capture = "(?:" + m_pattern + ")";
480 
481  if( m_repeat )
482  {
483  // Add * as the parameter can be repeeated.
484  capture += "(?:" + m_escaped_prefix + capture + ")*";
485  }
486 
487  if( m_optional )
488  {
489  // Optional param goes in ()?.
490  if( !m_partial )
491  {
492  capture = "(?:" + m_escaped_prefix + "(" + capture + "))?";
493  }
494  else
495  {
496  capture = m_escaped_prefix + "(" + capture + ")?";
497  }
498  }
499  else
500  {
501  // Mandatory param goes in ().
502  capture = m_escaped_prefix + "(" + capture + ")";
503  }
504 
505  route += capture;
506 
510 
512  }
513 
514  private:
515  const Name m_name;
518  const bool m_optional;
519  const bool m_repeat;
520  const bool m_partial;
522 };
523 
524 //
525 // create_token()
526 //
527 
528 //! Creates tokent for specific parameter.
529 template < typename Route_Param_Appender, typename Name >
532  Name name,
533  std::string prefix,
535  bool optional,
536  bool repeat,
537  bool partial,
538  std::string pattern )
539 {
541  std::move( name ),
542  std::move( prefix ),
543  std::move( delimiter ),
544  optional,
545  repeat,
546  partial,
547  std::move( pattern ) );
548 }
549 
550 //! Indexes for different groups in matched result
551 //! (used when extracting tokens from initial route).
552 //! \{
553 constexpr std::size_t group_escaped_idx = 1;
554 constexpr std::size_t group_name_idx = 2;
555 constexpr std::size_t group_capture_idx = 3;
556 constexpr std::size_t group_group_idx = 4;
558 //! \}
559 
560 //! Checks that string doesn't contain non-excaped brackets
561 inline std::string
563 {
564  auto pos = strv.find( '(' );
565  if( std::string::npos != pos )
566  {
567  throw exception_t{
568  fmt::format(
569  RESTINIO_FMT_FORMAT_STRING(
570  "non-escaped bracket '(' at pos {}: may be unmatched group start" ),
571  base_pos + pos ) };
572  }
573 
574  pos = strv.find( ')' );
575  if( std::string::npos != pos )
576  {
577  throw exception_t{
578  fmt::format(
579  RESTINIO_FMT_FORMAT_STRING(
580  "non-escaped bracket ')' at pos {}: may be unmatched group finish" ),
581  base_pos + pos ) };
582  }
583 
584  return std::string{ strv.data(), strv.size() };
585 }
586 
587 //
588 // handle_param_token()
589 //
590 
591 //! Handling of a parameterized token.
592 template < typename Route_Param_Appender, typename MATCH >
593 inline void
595  const options_t & options,
596  const MATCH & match,
597  std::string & path,
598  bool & path_escaped,
599  token_list_t< Route_Param_Appender > & result )
600 {
601  std::string prefix{ "" }; // prev in js code.
602  if( !path_escaped && !path.empty() )
603  {
604  const auto k = path.size() - 1;
605 
606  if( std::string::npos != options.delimiters().find( path[k] ) )
607  {
608  prefix = path.substr( k, 1 );
609  path = path.substr( 0, k );
610  }
611  }
612 
613  // Push the current path onto the tokens.
614  if( !path.empty() )
615  {
617  path_escaped = false;
618  }
619 
620  const auto next = match.suffix().str().substr( 0, 1 );
621 
624 
625  const bool partial = !prefix.empty() && !next.empty() && prefix != next;
626 
627  const bool optional = modifier == "?" || modifier == "*";
628  const bool repeat = modifier == "+" || modifier == "*";
630 
631  auto create_pattern = [ delimiter ]( auto pattern ){
632  if( !pattern.empty() )
633  {
635  }
636  else
637  {
638  pattern = "[^" + escape_string( delimiter ) + "]+?";
639  }
640  return pattern;
641  };
642 
643  if( !name.empty() )
644  {
645  // Named parameter.
648  name,
649  std::move( prefix ),
650  std::move( delimiter ),
651  optional,
652  repeat,
653  partial,
655  }
656  else
657  {
658  // Indexed parameter.
661  std::size_t{ 0 }, // just to have a variable of this type.
662  std::move( prefix ),
663  std::move( delimiter ),
664  optional,
665  repeat,
666  partial,
668  }
669 }
670 
671 //
672 // parse()
673 //
674 
675 //! Parse a string for the raw tokens.
676 template < typename Route_Param_Appender >
679 {
681 
682  std::string path{};
684  bool path_escaped = false;
685 
687  route_sv.data(),
688  route_sv.data() + route_sv.size(),
690  };
692 
693  if( token_it == token_end )
694  {
695  // Path is a single token.
697  }
698 
699  while( token_it != token_end )
700  {
701  const auto & match = *token_it;
702 
703  assert( 6 == match.size() );
704 
705  const string_view_t prefix{
706  match.prefix().first,
707  static_cast<std::size_t>( match.prefix().length() ) };
708 
710  static_cast<std::size_t>(match.position()) - prefix.size() );
711 
712  const auto escaped = match[ group_escaped_idx ].str();
713  if( !escaped.empty() )
714  {
715  assert( 2 == escaped.size() );
716  path += escaped[ 1 ];
717  path_escaped = true;
718  }
719  else
720  {
722  }
723 
724  auto next_it = token_it;
725  std::advance( next_it, 1 );
726 
727  if( next_it == token_end )
728  {
729  const std::string suffix{ match.suffix() };
730  path +=
732  suffix,
733  static_cast<std::size_t>(match.position() + match.length()) );
734  }
735 
736  token_it = next_it;
737  }
738 
739  if( !path.empty() )
741 
742  return result;
743 }
744 
745 //
746 // route_regex_matcher_data_t
747 //
748 
749 //! Resulting regex and param extraction for a specific route.
750 template < typename Route_Param_Appender, typename Regex_Engine >
752 {
753  route_regex_matcher_data_t() = default;
756 
759 
760  using regex_t = typename Regex_Engine::compiled_regex_t;
761 
762  regex_t m_regex;
763 
764  //! Char buffer for holding named paramaters.
765  /*!
766  In order to store named parameters 'names' in a continous block of memory
767  and use them in param_appender_sequence items as string_view.
768  */
770 
771  //! Appenders for captured values (names/indexed groups).
773 };
774 
775 //
776 // tokens2regexp()
777 //
778 
779 //! Makes route regex matcher out of path tokens.
780 template < typename Route_Param_Appender, typename Regex_Engine >
781 auto
783  string_view_t path,
784  const token_list_t< Route_Param_Appender > & tokens,
785  const options_t & options )
786 {
787  route_regex_matcher_data_t< Route_Param_Appender, Regex_Engine > result;
788  try
789  {
790  result.m_named_params_buffer = std::make_shared< std::string >();
791  names_buffer_appender_t
792  names_buffer_appender{ path.size(), *result.m_named_params_buffer };
793 
794  std::string route;
795  auto & param_appender_sequence = result.m_param_appender_sequence;
796 
797  // The number of capture groups in resultin regex
798  // 1 is for match of a route itself.
799  std::size_t captured_groups_count = 1 ;
800 
801  for( const auto & t : tokens )
802  {
803  const auto appended_token_type =
804  t->append_self_to( route, param_appender_sequence, names_buffer_appender );
805 
806  if( token_type_t::capturing_token == appended_token_type )
807  ++captured_groups_count;
808  }
809 
810  if( Regex_Engine::max_capture_groups() < captured_groups_count )
811  {
812  // This number of captures is not possible with this engine.
813  throw exception_t{
814  fmt::format(
815  RESTINIO_FMT_FORMAT_STRING(
816  "too many parameter to capture from route: {}, while {} "
817  "is the maximum" ),
818  captured_groups_count,
819  Regex_Engine::max_capture_groups() ) };
820  }
821 
822  const auto & delimiter = escape_string( options.delimiter() );
823  const auto & ends_with = options.make_ends_with();
824 
825  if( options.ending() )
826  {
827  if( !options.strict() )
828  {
829  route += "(?:" + delimiter + ")?";
830  }
831 
832  if( ends_with == "$" )
833  route += '$';
834  else
835  route += "(?=" + ends_with + ")";
836  }
837  else
838  {
839  if( !options.strict() )
840  route += "(?:" + delimiter + "(?=" + ends_with + "))?";
841 
842  if( !tokens.empty() &&
843  !tokens.back()->is_end_delimited( options.delimiters() ) )
844  route += "(?=" + delimiter + "|" + ends_with + ")";
845  }
846 
847  result.m_regex = Regex_Engine::compile_regex( "^" + route, options.sensitive() );
848  }
849  catch( const std::exception & ex )
850  {
851  throw exception_t{
852  fmt::format(
853  RESTINIO_FMT_FORMAT_STRING( "unable to process route \"{}\": {}" ),
854  fmtlib_tools::streamed( path ), ex.what() ) };
855  }
856 
857  return result;
858 }
859 
860 } /* namespace impl */
861 
862 //
863 // path2regex()
864 //
865 
866 //! The main path matching regexp.
867 template < typename Route_Param_Appender, typename Regex_Engine >
868 inline auto
870  string_view_t path,
871  const options_t & options )
872 {
873  return impl::tokens2regexp< Route_Param_Appender, Regex_Engine >(
874  path,
875  impl::parse< Route_Param_Appender >( path, options ),
876  options );
877 }
878 
879 } /* namespace path2regex */
880 
881 } /* namespace restinio */
std::string make_delimiter(std::string d) const
Definition: path2regex.hpp:171
Token for paramater (named/indexed).
Definition: path2regex.hpp:449
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.
Definition: path2regex.hpp:594
options_t & ends_with(std::vector< std::string > p) &
Definition: path2regex.hpp:201
std::shared_ptr< std::string > m_named_params_buffer
Char buffer for holding named paramaters.
Definition: path2regex.hpp:769
route_regex_matcher_data_t & operator=(route_regex_matcher_data_t &&)=delete
virtual bool is_end_delimited(const std::string &) const noexcept
Definition: path2regex.hpp:386
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > &param_appender_sequence, names_buffer_appender_t &names_buffer_appender) const =0
bool m_ending
When false the path will match at the beginning.
Definition: path2regex.hpp:245
parameter_token_t(Name name, const std::string &prefix, std::string delimiter, bool optional, bool repeat, bool partial, std::string pattern)
Definition: path2regex.hpp:455
param_appender_sequence_t< Route_Param_Appender > m_param_appender_sequence
Appenders for captured values (names/indexed groups).
Definition: path2regex.hpp:772
constexpr std::size_t group_modifier_idx
Definition: path2regex.hpp:557
route_regex_matcher_data_t(const route_regex_matcher_data_t &)=delete
options_t & sensitive(bool s) &
Definition: path2regex.hpp:95
const std::string & delimiter() const
Definition: path2regex.hpp:165
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > &, names_buffer_appender_t &) const override
Definition: path2regex.hpp:413
options_t & delimiters(std::string p) &
Definition: path2regex.hpp:182
token_t(const token_t &)=delete
bool m_sensitive
When true the route will be case sensitive.
Definition: path2regex.hpp:239
constexpr std::size_t group_group_idx
Definition: path2regex.hpp:556
options_t & strict(bool p) &
Definition: path2regex.hpp:114
bool m_strict
When false the trailing slash is optional.
Definition: path2regex.hpp:242
parameter_token_t(const parameter_token_t &)=delete
auto escape_string(const std::string &group)
Excape regex control chars.
Definition: path2regex.hpp:63
options_t && ends_with(std::vector< std::string > p) &&
Definition: path2regex.hpp:208
token_list_t< Route_Param_Appender > parse(string_view_t route_sv, const options_t &options)
Parse a string for the raw tokens.
Definition: path2regex.hpp:678
auto escape_group(const std::string &group)
Escapes not allowed symbols in a sub-match group assigned to a parameter.
Definition: path2regex.hpp:40
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
std::string make_ends_with() const
Definition: path2regex.hpp:220
std::size_t append_name(std::size_t i) const
A stub for indexed paramaters.
Definition: path2regex.hpp:344
const std::string & delimiters() const
Definition: path2regex.hpp:195
options_t && ending(bool p) &&
Definition: path2regex.hpp:140
options_t & delimiter(std::string p) &
Definition: path2regex.hpp:152
constexpr auto path_regex_str
The main path matching expression.
Definition: path2regex.hpp:356
param_appender_t< Route_Param_Appender > make_param_setter(std::size_t)
Create default appender indexed parameter.
Definition: path2regex.hpp:294
options_t && strict(bool p) &&
Definition: path2regex.hpp:121
const std::vector< std::string > & ends_with() const
Definition: path2regex.hpp:214
token_unique_ptr_t< Route_Param_Appender > create_token(std::string path)
Definition: path2regex.hpp:437
Options for matching routes.
Definition: path2regex.hpp:91
Appender for names to a given buffered string.
Definition: path2regex.hpp:311
constexpr std::size_t group_name_idx
Definition: path2regex.hpp:554
Resulting regex and param extraction for a specific route.
Definition: path2regex.hpp:751
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...
Definition: path2regex.hpp:324
std::string m_delimiters
Path delimiters.
Definition: path2regex.hpp:251
Base class for token variants.
Definition: path2regex.hpp:371
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.
Definition: path2regex.hpp:782
options_t && delimiter(std::string p) &&
Definition: path2regex.hpp:159
options_t & ending(bool p) &
Definition: path2regex.hpp:133
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.
Definition: path2regex.hpp:531
options_t && sensitive(bool s) &&
Definition: path2regex.hpp:102
std::vector< std::string > m_ends_with
Path delimiter.
Definition: path2regex.hpp:254
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.
Definition: path2regex.hpp:869
virtual token_type_t append_self_to(std::string &route, param_appender_sequence_t< Route_Param_Appender > &param_appender_sequence, names_buffer_appender_t &names_buffer_appender) const override
Definition: path2regex.hpp:473
options_t && delimiters(std::string p) &&
Definition: path2regex.hpp:189
std::string m_delimiter
Path delimiter.
Definition: path2regex.hpp:248
virtual bool is_end_delimited(const std::string &delimiters) const noexcept override
Definition: path2regex.hpp:424
string_view_buffer_storage_appender_t(std::size_t reserve_size, Container &buffer)
Definition: path2regex.hpp:314
const std::string m_escaped_path
Already escaped piece of the route.
Definition: path2regex.hpp:431
std::string check_no_unescaped_brackets(string_view_t strv, std::size_t base_pos)
Checks that string doesn&#39;t contain non-excaped brackets.
Definition: path2regex.hpp:562
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)...
Definition: path2regex.hpp:553
constexpr std::size_t group_capture_idx
Definition: path2regex.hpp:555