RESTinio
pcre_regex_engine.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
9 #pragma once
10 
11 #include <pcre.h>
12 
14 
15 #include <restinio/exception.hpp>
16 
17 namespace restinio
18 {
19 
20 namespace router
21 {
22 
23 namespace pcre_details
24 {
25 
26 
27 //
28 // match_results_t
29 //
30 
32 template < typename Traits >
33 struct match_results_t final
34 {
36  {
38  int begin,
39  int end )
40  : m_begin{ begin }
41  , m_end{ end }
42  {}
43 
44  int m_begin;
45  int m_end;
46  };
47 
49  operator [] ( std::size_t i ) const
50  {
51  if( m_submatches[ 2 * i ] >= 0 )
52  {
53  // Submatch has non-empty value.
55  m_submatches[ 2 * i ],
56  m_submatches[ 1 + 2 * i ] };
57  }
58 
59  // This submatch group is empty.
60  return matched_item_descriptor_t{ 0, 0 };
61  }
62 
63  std::size_t size() const { return m_size; }
64 
65  std::size_t m_size{ 0 };
66  std::array< int, 3 * Traits::max_capture_groups > m_submatches;
67 };
68 
69 //
70 // regex_t
71 //
72 
74 class regex_t final
75 {
76  public:
77  regex_t() = default;
78  regex_t( string_view_t r, int options )
79  {
80  compile( r, options );
81  }
82 
83  regex_t( const regex_t & ) = delete;
84  regex_t & operator = ( const regex_t & ) = delete;
85 
86  regex_t( regex_t && rw ) noexcept
87  : m_route_regex{ rw.m_route_regex }
88  {
89  rw.m_route_regex = nullptr;
90  }
91 
92  regex_t & operator = ( regex_t && rw ) noexcept
93  {
94  if( this != &rw )
95  {
96  m_route_regex = rw.m_route_regex;
97  rw.m_route_regex = nullptr;
98  }
99 
100  return *this;
101  }
102 
104  {
105  if( nullptr != m_route_regex )
106  {
107  pcre_free( m_route_regex );
108  }
109  }
110 
111  const pcre *
112  pcre_regex() const
113  {
114  return m_route_regex;
115  }
116 
117  private:
118  pcre * m_route_regex{ nullptr };
119 
120  void
121  compile( string_view_t r, int options )
122  {
123  const char* compile_error;
124  int eoffset;
125 
126  // We need zero-terminated string.
127  const std::string route{ r.data(), r.size() };
128 
129  m_route_regex = pcre_compile( route.c_str(), options, &compile_error, &eoffset, nullptr );
130 
131  if( nullptr == m_route_regex )
132  {
133  throw exception_t{
134  fmt::format(
135  "unable to compile regex \"{}\": {}",
136  route,
137  compile_error ) };
138  }
139  }
140 };
141 
142 } /* namespace pcre_details */
143 
144 //
145 // pcre_traits_t
146 //
147 
149 template < std::size_t Max_Capture_Groups = 20, int Compile_Options = 0, int Match_Options = 0 >
151 {
152  static constexpr std::size_t max_capture_groups = Max_Capture_Groups;
153  static constexpr int compile_options = Compile_Options;
154  static constexpr int match_options = Match_Options;
155 };
156 
157 //
158 // pcre_regex_engine_t
159 //
160 
162 template < typename Traits = pcre_traits_t<> >
164 {
168 
169  // Max itemes that can be captured be pcre engine.
170  static constexpr std::size_t
172  {
173  return Traits::max_capture_groups;
174  }
175 
177  static auto
180  string_view_t r,
182  bool is_case_sensative )
183  {
184  int options = Traits::compile_options;
185 
186  if( !is_case_sensative )
187  {
188  options |= PCRE_CASELESS;
189  }
190 
191  return compiled_regex_t{ r, options };
192  }
193 
195  static auto
197  string_view_t target_path,
198  const compiled_regex_t & r,
199  match_results_t & match_results )
200  {
201  const int rc =
202  pcre_exec(
203  r.pcre_regex(),
204  nullptr,
205  target_path.data(),
206  static_cast< int >( target_path.size() ),
207  0, // startoffset
208  Traits::match_options,
209  match_results.m_submatches.data(),
210  static_cast< int >( match_results.m_submatches.size() ) );
211 
212  if( rc > 0 )
213  {
214  match_results.m_size = static_cast<std::size_t>(rc);
215  return true;
216  }
217  else if( rc == 0 )
218  {
219  // This should not happen,
220  // because the number of groups is checked when creating route matcher.
221  throw exception_t{ "unexpected: not enough submatch vector size" };
222  }
223  if( PCRE_ERROR_NOMATCH != rc )
224  {
225  throw exception_t{ fmt::format("pcre error: {}", rc ) };
226  }
227  // else PCRE_ERROR_NOMATCH -- no match for this route
228 
229  return false;
230  }
231 
233  static auto
235  {
236  return static_cast< std::size_t >( m.m_begin );
237  }
238 
240  static auto
242  {
243  return static_cast< std::size_t >( m.m_end );
244  }
245 };
246 
247 } /* namespace router */
248 
249 } /* namespace restinio */
restinio::router::pcre_details::regex_t
A wrapper for using pcre regexes in express_router.
Definition: pcre_regex_engine.hpp:75
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::router::pcre_regex_engine_t::submatch_begin_pos
static auto submatch_begin_pos(const matched_item_descriptor_t &m)
Get the beginning of a submatch.
Definition: pcre_regex_engine.hpp:234
restinio::router::pcre_details::match_results_t::matched_item_descriptor_t::m_begin
int m_begin
Definition: pcre_regex_engine.hpp:44
restinio::router::pcre_regex_engine_t::compile_regex
static auto compile_regex(string_view_t r, bool is_case_sensative)
Create compiled regex object for a given route.
Definition: pcre_regex_engine.hpp:178
restinio::router::pcre_traits_t::match_options
static constexpr int match_options
Definition: pcre_regex_engine.hpp:154
restinio::router::pcre_details::match_results_t::m_submatches
std::array< int, 3 *Traits::max_capture_groups > m_submatches
Definition: pcre_regex_engine.hpp:66
restinio::router::pcre_details::match_results_t::matched_item_descriptor_t
Definition: pcre_regex_engine.hpp:36
restinio::router::pcre_regex_engine_t::matched_item_descriptor_t
typename match_results_t::matched_item_descriptor_t matched_item_descriptor_t
Definition: pcre_regex_engine.hpp:167
restinio::router::pcre_details::match_results_t
A wrapper class for working with pcre match results.
Definition: pcre_regex_engine.hpp:34
restinio::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
restinio::router::pcre_details::regex_t::regex_t
regex_t(regex_t &&rw) noexcept
Definition: pcre_regex_engine.hpp:86
restinio::router::pcre_regex_engine_t::max_capture_groups
static constexpr std::size_t max_capture_groups()
Definition: pcre_regex_engine.hpp:171
restinio::router::pcre_details::regex_t::compile
void compile(string_view_t r, int options)
Definition: pcre_regex_engine.hpp:121
restinio::router::pcre_details::regex_t::pcre_regex
const pcre * pcre_regex() const
Definition: pcre_regex_engine.hpp:112
restinio::router::pcre_details::match_results_t::operator[]
matched_item_descriptor_t operator[](std::size_t i) const
Definition: pcre_regex_engine.hpp:49
restinio::router::pcre_regex_engine_t::submatch_end_pos
static auto submatch_end_pos(const matched_item_descriptor_t &m)
Get the end of a submatch.
Definition: pcre_regex_engine.hpp:241
restinio::router::pcre_details::regex_t::regex_t
regex_t()=default
include_fmtlib.hpp
A special wrapper around fmtlib include files.
restinio::router::pcre_details::regex_t::m_route_regex
pcre * m_route_regex
Definition: pcre_regex_engine.hpp:118
restinio::router::pcre_details::regex_t::regex_t
regex_t(const regex_t &)=delete
restinio::router::pcre_details::match_results_t::matched_item_descriptor_t::m_end
int m_end
Definition: pcre_regex_engine.hpp:45
restinio::router::pcre_details::match_results_t::matched_item_descriptor_t::matched_item_descriptor_t
matched_item_descriptor_t(int begin, int end)
Definition: pcre_regex_engine.hpp:37
restinio::router::pcre_regex_engine_t
Regex engine implementation for PCRE.
Definition: pcre_regex_engine.hpp:164
restinio::router::pcre_details::match_results_t::m_size
std::size_t m_size
Definition: pcre_regex_engine.hpp:65
restinio::router::pcre_traits_t::max_capture_groups
static constexpr std::size_t max_capture_groups
Definition: pcre_regex_engine.hpp:152
restinio
Definition: asio_include.hpp:21
restinio::router::pcre_details::regex_t::~regex_t
~regex_t()
Definition: pcre_regex_engine.hpp:103
restinio::router::pcre_traits_t
PCRE traits.
Definition: pcre_regex_engine.hpp:151
exception.hpp
restinio::router::pcre_regex_engine_t::try_match
static auto try_match(string_view_t target_path, const compiled_regex_t &r, match_results_t &match_results)
Wrapper function for matching logic invokation.
Definition: pcre_regex_engine.hpp:196
restinio::router::pcre_details::regex_t::regex_t
regex_t(string_view_t r, int options)
Definition: pcre_regex_engine.hpp:78
restinio::router::pcre_details::match_results_t::size
std::size_t size() const
Definition: pcre_regex_engine.hpp:63
restinio::router::pcre_details::regex_t::operator=
regex_t & operator=(const regex_t &)=delete
restinio::router::pcre_traits_t::compile_options
static constexpr int compile_options
Definition: pcre_regex_engine.hpp:153