RESTinio
pcre2_regex_engine.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
9 #pragma once
10 
11 #include <array>
12 
13 #include <pcre2.h>
14 
16 
17 #include <restinio/exception.hpp>
18 
19 namespace restinio
20 {
21 
22 namespace router
23 {
24 
25 namespace pcre2_details
26 {
27 
28 //
29 // match_results_t
30 //
31 
33 template < typename Traits >
34 struct match_results_t final
35 {
37  {
38  m_match_data = pcre2_match_data_create( Traits::max_capture_groups, nullptr );
39  }
40 
42  {
43  if( nullptr != m_match_data )
44  pcre2_match_data_free( m_match_data );
45  }
46 
47  match_results_t( const match_results_t & ) = delete;
51 
53  {
55  PCRE2_SIZE begin,
56  PCRE2_SIZE end )
57  : m_begin{ begin }
58  , m_end{ end }
59  {}
60 
61  PCRE2_SIZE m_begin;
62  PCRE2_SIZE m_end;
63  };
64 
66  operator [] ( std::size_t i ) const
67  {
68  PCRE2_SIZE * submatches = pcre2_get_ovector_pointer( m_match_data );
69 
71  submatches[ 2 * i ],
72  submatches[ 1 + 2 * i ] };
73  }
74 
75  std::size_t size() const { return m_size; }
76 
77  std::size_t m_size{ 0 };
78  pcre2_match_data * m_match_data;
79 };
80 
81 //
82 // regex_t
83 //
84 
86 class regex_t final
87 {
88  public:
89  regex_t() = default;
90  regex_t( string_view_t r, int options )
91  {
92  compile( r, options );
93  }
94 
95  regex_t( const regex_t & ) = delete;
96  regex_t & operator = ( const regex_t & ) = delete;
97 
98  regex_t( regex_t && rw ) noexcept
99  : m_route_regex{ rw.m_route_regex }
100  {
101  rw.m_route_regex = nullptr;
102  }
103 
104  regex_t & operator = ( regex_t && rw ) noexcept
105  {
106  if( this != &rw )
107  {
108  m_route_regex = rw.m_route_regex;
109  rw.m_route_regex = nullptr;
110  }
111 
112  return *this;
113  }
114 
116  {
117  if( nullptr != m_route_regex )
118  {
119  pcre2_code_free( m_route_regex );
120  }
121  }
122 
123  const pcre2_code *
124  pcre2_regex() const
125  {
126  return m_route_regex;
127  }
128 
129  private:
130  pcre2_code * m_route_regex{ nullptr };
131 
132  void
133  compile( string_view_t r, int options )
134  {
135  PCRE2_SIZE erroroffset;
136  int errorcode;
137 
138  m_route_regex = pcre2_compile(
139  reinterpret_cast< const unsigned char*>( r.data() ),
140  r.size(),
141  static_cast<unsigned int>(options),
142  &errorcode,
143  &erroroffset,
144  nullptr );
145 
146  if( nullptr == m_route_regex )
147  {
148  std::array< unsigned char, 256 > buffer;
149  (void)pcre2_get_error_message( errorcode, buffer.data(), buffer.size() );
150  throw exception_t{
151  fmt::format(
152  "unable to compile regex \"{}\": {}",
153  r,
154  reinterpret_cast< const char * >( buffer.data() ) ) };
155  }
156  }
157 };
158 
159 } /* namespace pcre2_details */
160 
161 //
162 // pcre_traits_t
163 //
164 
166 template < std::size_t Max_Capture_Groups = 20, int Compile_Options = 0, int Match_Options = 0 >
168 {
169  static constexpr std::size_t max_capture_groups = Max_Capture_Groups;
170  static constexpr int compile_options = Compile_Options;
171  static constexpr int match_options = Match_Options;
172 };
173 
174 //
175 // pcre2_regex_engine_t
176 //
177 
179 template < typename Traits = pcre2_traits_t<> >
181 {
185 
186  // Max itemes that can be captured be pcre engine.
187  static constexpr std::size_t
189  {
190  return Traits::max_capture_groups;
191  }
192 
194  static auto
197  string_view_t r,
199  bool is_case_sensative )
200  {
201  int options = Traits::compile_options;
202 
203  if( !is_case_sensative )
204  {
205  options |= PCRE2_CASELESS;
206  }
207 
208  return compiled_regex_t{ r, options };
209  }
210 
212  static auto
214  string_view_t target_path,
215  const compiled_regex_t & r,
216  match_results_t & match_results )
217  {
218  const int rc =
219  pcre2_match(
220  r.pcre2_regex(),
221  reinterpret_cast< const unsigned char* >( target_path.data() ),
222  target_path.size(),
223  0, // startoffset
224  Traits::match_options,
225  match_results.m_match_data,
226  nullptr );
227 
228  if( rc > 0 )
229  {
230  match_results.m_size = static_cast<std::size_t>(rc);
231  return true;
232  }
233  else if( rc == 0 )
234  {
235  // This should not happen,
236  // because the number of groups is checked when creating route matcher.
237  throw exception_t{ "unexpected: not enough submatch vector size" };
238  }
239  if( PCRE2_ERROR_NOMATCH != rc )
240  {
241  throw exception_t{ fmt::format("pcre2 error: {}", rc ) };
242  }
243  // else PCRE2_ERROR_NOMATCH -- no match for this route
244 
245  return false;
246  }
247 
249  static auto
251  {
252  return static_cast< std::size_t >( m.m_begin );
253  }
254 
256  static auto
258  {
259  return static_cast< std::size_t >( m.m_end );
260  }
261 };
262 
263 } /* namespace router */
264 
265 } /* namespace restinio */
restinio::router::pcre2_details::match_results_t::m_match_data
pcre2_match_data * m_match_data
Definition: pcre2_regex_engine.hpp:78
restinio::router::pcre2_regex_engine_t::submatch_end_pos
static auto submatch_end_pos(const matched_item_descriptor_t &m)
Get the end of a submatch.
Definition: pcre2_regex_engine.hpp:257
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::router::pcre2_details::regex_t::m_route_regex
pcre2_code * m_route_regex
Definition: pcre2_regex_engine.hpp:130
restinio::router::pcre2_details::match_results_t::matched_item_descriptor_t::matched_item_descriptor_t
matched_item_descriptor_t(PCRE2_SIZE begin, PCRE2_SIZE end)
Definition: pcre2_regex_engine.hpp:54
restinio::router::pcre2_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: pcre2_regex_engine.hpp:195
restinio::router::pcre2_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: pcre2_regex_engine.hpp:213
restinio::router::pcre2_regex_engine_t
Regex engine implementation for PCRE2.
Definition: pcre2_regex_engine.hpp:181
restinio::router::pcre2_details::match_results_t::~match_results_t
~match_results_t()
Definition: pcre2_regex_engine.hpp:41
restinio::router::pcre2_regex_engine_t::submatch_begin_pos
static auto submatch_begin_pos(const matched_item_descriptor_t &m)
Get the beginning of a submatch.
Definition: pcre2_regex_engine.hpp:250
restinio::router::pcre2_details::match_results_t::size
std::size_t size() const
Definition: pcre2_regex_engine.hpp:75
restinio::router::pcre2_details::regex_t::regex_t
regex_t()=default
restinio::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
restinio::router::pcre2_details::match_results_t::matched_item_descriptor_t::m_begin
PCRE2_SIZE m_begin
Definition: pcre2_regex_engine.hpp:61
restinio::router::pcre2_traits_t::max_capture_groups
static constexpr std::size_t max_capture_groups
Definition: pcre2_regex_engine.hpp:169
restinio::router::pcre2_details::match_results_t::matched_item_descriptor_t
Definition: pcre2_regex_engine.hpp:53
restinio::router::pcre2_details::regex_t::~regex_t
~regex_t()
Definition: pcre2_regex_engine.hpp:115
restinio::router::pcre2_traits_t
PCRE traits.
Definition: pcre2_regex_engine.hpp:168
restinio::router::pcre2_details::regex_t::regex_t
regex_t(regex_t &&rw) noexcept
Definition: pcre2_regex_engine.hpp:98
restinio::router::pcre2_details::regex_t::pcre2_regex
const pcre2_code * pcre2_regex() const
Definition: pcre2_regex_engine.hpp:124
restinio::router::pcre2_regex_engine_t::matched_item_descriptor_t
typename match_results_t::matched_item_descriptor_t matched_item_descriptor_t
Definition: pcre2_regex_engine.hpp:184
restinio::router::pcre2_traits_t::match_options
static constexpr int match_options
Definition: pcre2_regex_engine.hpp:171
include_fmtlib.hpp
A special wrapper around fmtlib include files.
restinio::router::pcre2_details::match_results_t
A wrapper class for working with pcre match results.
Definition: pcre2_regex_engine.hpp:35
restinio::router::pcre2_details::match_results_t::m_size
std::size_t m_size
Definition: pcre2_regex_engine.hpp:77
restinio::router::pcre2_details::match_results_t::match_results_t
match_results_t(const match_results_t &)=delete
restinio
Definition: asio_include.hpp:21
restinio::router::pcre2_details::match_results_t::match_results_t
match_results_t()
Definition: pcre2_regex_engine.hpp:36
exception.hpp
restinio::router::pcre2_details::regex_t::operator=
regex_t & operator=(const regex_t &)=delete
restinio::router::pcre2_details::regex_t
A wrapper for using pcre regexes in express_router.
Definition: pcre2_regex_engine.hpp:87
restinio::router::pcre2_details::match_results_t::match_results_t
match_results_t(match_results_t &&)=delete
restinio::router::pcre2_details::match_results_t::matched_item_descriptor_t::m_end
PCRE2_SIZE m_end
Definition: pcre2_regex_engine.hpp:62
restinio::router::pcre2_details::regex_t::regex_t
regex_t(const regex_t &)=delete
restinio::router::pcre2_details::match_results_t::operator=
match_results_t & operator=(const match_results_t &)=delete
restinio::router::pcre2_traits_t::compile_options
static constexpr int compile_options
Definition: pcre2_regex_engine.hpp:170
restinio::router::pcre2_details::regex_t::compile
void compile(string_view_t r, int options)
Definition: pcre2_regex_engine.hpp:133
restinio::router::pcre2_details::match_results_t::operator[]
matched_item_descriptor_t operator[](std::size_t i) const
Definition: pcre2_regex_engine.hpp:66
restinio::router::pcre2_details::regex_t::regex_t
regex_t(string_view_t r, int options)
Definition: pcre2_regex_engine.hpp:90
restinio::router::pcre2_regex_engine_t::max_capture_groups
static constexpr std::size_t max_capture_groups()
Definition: pcre2_regex_engine.hpp:188