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
13#include <restinio/impl/include_fmtlib.hpp>
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{
35 struct matched_item_descriptor_t final
36 {
37 matched_item_descriptor_t(
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
48 matched_item_descriptor_t
49 operator [] ( std::size_t i ) const
50 {
51 if( m_submatches[ 2 * i ] >= 0 )
52 {
53 // Submatch has non-empty value.
54 return matched_item_descriptor_t{
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
103 ~regex_t()
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 >
150 struct pcre_traits_t
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<> >
163 struct pcre_regex_engine_t
164{
165 using compiled_regex_t = pcre_details::regex_t;
166 using match_results_t = pcre_details::match_results_t< Traits >;
167 using matched_item_descriptor_t = typename match_results_t::matched_item_descriptor_t;
168
169 // Max itemes that can be captured be pcre engine.
170 static constexpr std::size_t
171 max_capture_groups()
172 {
173 return Traits::max_capture_groups;
174 }
175
177 static auto
178 compile_regex(
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
196 try_match(
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
234 submatch_begin_pos( const matched_item_descriptor_t & m )
235 {
236 return static_cast< std::size_t >( m.m_begin );
237 }
238
240 static auto
241 submatch_end_pos( const matched_item_descriptor_t & m )
242 {
243 return static_cast< std::size_t >( m.m_end );
244 }
245};
246
247} /* namespace router */
248
249} /* namespace restinio */
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::router::pcre_details::regex_t
A wrapper for using pcre regexes in express_router.
Definition: pcre_regex_engine.hpp:75
restinio::router::pcre_details::regex_t::regex_t
regex_t(const regex_t &)=delete
restinio::router::pcre_details::regex_t::operator=
regex_t & operator=(const regex_t &)=delete
restinio::router::pcre_details::regex_t::~regex_t
~regex_t()
Definition: pcre_regex_engine.hpp:103
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::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::regex_t::regex_t
regex_t(regex_t &&rw) noexcept
Definition: pcre_regex_engine.hpp:86
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::regex_t::regex_t
regex_t()=default
exception.hpp
include_fmtlib.hpp
A special wrapper around fmtlib include files.
restinio
Definition: asio_include.hpp:21
restinio::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
restinio::router::pcre_details::match_results_t::matched_item_descriptor_t
Definition: pcre_regex_engine.hpp:36
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_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_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
A wrapper class for working with pcre match results.
Definition: pcre_regex_engine.hpp:34
restinio::router::pcre_details::match_results_t::size
std::size_t size() const
Definition: pcre_regex_engine.hpp:63
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_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::m_size
std::size_t m_size
Definition: pcre_regex_engine.hpp:65
restinio::router::pcre_regex_engine_t
Regex engine implementation for PCRE.
Definition: pcre_regex_engine.hpp:164
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_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_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_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_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_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_traits_t
PCRE traits.
Definition: pcre_regex_engine.hpp:151
restinio::router::pcre_traits_t::max_capture_groups
static constexpr std::size_t max_capture_groups
Definition: pcre_regex_engine.hpp:152
restinio::router::pcre_traits_t::match_options
static constexpr int match_options
Definition: pcre_regex_engine.hpp:154
restinio::router::pcre_traits_t::compile_options
static constexpr int compile_options
Definition: pcre_regex_engine.hpp:153