RESTinio
method_matcher.hpp
Go to the documentation of this file.
1/*
2 * RESTinio
3 */
4
12#pragma once
13
15
16#include <initializer_list>
17#include <vector>
18
19namespace restinio
20{
21
22namespace router
23{
24
25//
26// method_matcher_t
27//
39{
40 method_matcher_t( const method_matcher_t & ) = default;
42 operator=( const method_matcher_t & ) = default;
43
46 operator=( method_matcher_t && ) = default;
47
48 method_matcher_t() = default;
49 virtual ~method_matcher_t() = default;
50
52
57 virtual bool
58 match( const http_method_id_t & method ) const noexcept = 0;
59};
60
61namespace impl
62{
63
64//
65// allocated_matcher_proxy_t
66//
79template< typename Matcher >
81{
82 std::unique_ptr< Matcher > m_matcher;
83
84public :
85 template< typename... Args >
86 allocated_matcher_proxy_t( Args && ...args )
87 : m_matcher{ std::make_unique<Matcher>( std::forward<Args>(args)... ) }
88 {}
89
91 bool
92 match( const http_method_id_t & method ) const noexcept override
93 {
94 return m_matcher->match( method );
95 }
96};
97
98//
99// simple_matcher_t
100//
111{
113
114public :
116 : m_method{ std::move(method) }
117 {}
118
120 bool
121 match( const http_method_id_t & method ) const noexcept override
122 {
123 return m_method == method;
124 }
125};
126
127//
128// fixed_size_any_of_matcher_t
129//
138template< std::size_t Size >
140{
141 std::array< http_method_id_t, Size > m_methods;
142
143public :
152 std::initializer_list< http_method_id_t > values )
153 {
154 assert( Size == values.size() );
155
156 std::copy( values.begin(), values.end(), m_methods.begin() );
157 }
158
160 bool
161 match( const http_method_id_t & method ) const noexcept override
162 {
163 for( const auto & m : m_methods )
164 if( m == method )
165 return true;
166
167 return false;
168 }
169};
170
171//
172// fixed_size_none_of_matcher_t
173//
182template< std::size_t Size >
184 : public fixed_size_any_of_matcher_t<Size>
185{
187
188public :
189 using base_type_t::base_type_t;
190
192 bool
193 match( const http_method_id_t & method ) const noexcept override
194 {
195 return !base_type_t::match( method );
196 }
197};
198
199//
200// buffered_matcher_holder_t
201//
225{
227 static constexpr std::size_t buffer_size =
229
231 static constexpr std::size_t alignment =
232 std::max( {
233 alignof(simple_matcher_t),
237
240
245 using pfn_move_t = method_matcher_t* (*)(void* object, void* buffer);
246
248
253
255 alignas(alignment) std::array<char, buffer_size> m_buffer;
256
258
261 pfn_move_t m_mover{ nullptr };
262
263 void
265 {
267 }
268
269 void
271 {
272 if( other.m_matcher )
273 {
274 m_matcher = other.m_mover( other.m_matcher, m_buffer.data() );
275 m_mover = other.m_mover;
276
277 other.m_matcher = nullptr;
278 other.m_mover = nullptr;
279 }
280 }
281
282public :
284
286 {
287 cleanup();
288 }
289
291 const buffered_matcher_holder_t & ) = delete;
292
295 const buffered_matcher_holder_t & ) = delete;
296
298 buffered_matcher_holder_t && other ) noexcept
299 {
300 move_from( other );
301 }
302
305 {
306 if( this != &other )
307 {
308 cleanup();
309 move_from( other );
310 }
311
312 return *this;
313 }
314
327 template< typename Target_Type, typename... Args >
328 void
329 assign( Args &&... args )
330 {
331 static_assert( alignof(Target_Type) <= alignment,
332 "Target_Type should have appropriate alignment" );
333
334 cleanup();
335
336 if( sizeof(Target_Type) <= buffer_size )
337 {
338 m_matcher = new(m_buffer.data()) Target_Type{ std::forward<Args>(args)... };
339 m_mover = [](void * raw_what, void * dest_storage) -> method_matcher_t * {
340 auto * what = reinterpret_cast<Target_Type *>(raw_what);
341 return new(dest_storage) Target_Type{ std::move(*what) };
342 };
343 }
344 else
345 {
346 using actual_type = allocated_matcher_proxy_t<Target_Type>;
347 m_matcher = new(m_buffer.data()) actual_type{ std::forward<Args>(args)... };
348 m_mover = [](void * raw_what, void * dest_storage) -> method_matcher_t * {
349 auto * what = reinterpret_cast<actual_type *>(raw_what);
350 return new(dest_storage) actual_type{ std::move(*what) };
351 };
352 }
353 }
354
358 get() const noexcept { return m_matcher; }
359
363 operator->() const noexcept { return m_matcher; }
364
368 operator*() const noexcept { return *m_matcher; }
369
370 friend void
372 {
373 holder.assign< simple_matcher_t >( std::move(method) );
374 }
375
376 template< typename Arg >
377 friend void
378 assign( buffered_matcher_holder_t & holder, Arg && method_matcher )
379 {
380 using pure_method_matcher_type = std::decay_t<Arg>;
381
382 static_assert( std::is_base_of<
383 method_matcher_t, pure_method_matcher_type >::value,
384 "Arg should be derived from method_matcher_t" );
385
386 holder.assign< pure_method_matcher_type >(
387 std::forward<Arg>(method_matcher) );
388 }
389};
390
391} /* namespace impl */
392
393//
394// any_of_methods
395//
414template< typename... Args >
416impl::fixed_size_any_of_matcher_t< sizeof...(Args) >
417any_of_methods( Args && ...args )
418{
419 return { std::initializer_list<http_method_id_t>{ std::forward<Args>(args)... } };
420}
421
422//
423// none_of_methods
424//
446template< typename... Args >
448impl::fixed_size_none_of_matcher_t< sizeof...(Args) >
449none_of_methods( Args && ...args )
450{
451 return { std::initializer_list<http_method_id_t>{ std::forward<Args>(args)... } };
452}
453
454//
455// dynamic_any_of_methods_matcher_t
456//
476{
477 std::vector< http_method_id_t > m_methods;
478
479public:
481
483 bool
484 match( const http_method_id_t & method ) const noexcept override
485 {
486 for( const auto & m : m_methods )
487 if( m == method )
488 return true;
489
490 return false;
491 }
492
495 {
496 m_methods.emplace_back( std::move(method) );
497 return *this;
498 }
499
501 std::size_t
502 size() const noexcept
503 {
504 return m_methods.size();
505 }
506
508 bool
509 empty() const noexcept
510 {
511 return m_methods.empty();
512 }
513};
514
515//
516// dynamic_none_of_methods_matcher_t
517//
537{
538 std::vector< http_method_id_t > m_methods;
539
540public:
542
544 bool
545 match( const http_method_id_t & method ) const noexcept override
546 {
547 for( const auto & m : m_methods )
548 if( m == method )
549 return false;
550
551 return true;
552 }
553
556 {
557 m_methods.emplace_back( std::move(method) );
558 return *this;
559 }
560
562 std::size_t
563 size() const noexcept
564 {
565 return m_methods.size();
566 }
567
569 bool
570 empty() const noexcept
571 {
572 return m_methods.empty();
573 }
574};
575
576} /* namespace router */
577
578} /* namespace restinio */
579
A type for representation of HTTP method ID.
An implementation of method_matcher that allows a method if it's found in a dynamic list of allowed m...
dynamic_any_of_methods_matcher_t & add(http_method_id_t method)
RESTINIO_NODISCARD std::size_t size() const noexcept
RESTINIO_NODISCARD bool empty() const noexcept
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
An implementation of method_matcher that allows a method if it isn't found in a dynamic list of disab...
RESTINIO_NODISCARD bool empty() const noexcept
RESTINIO_NODISCARD std::size_t size() const noexcept
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
dynamic_none_of_methods_matcher_t & add(http_method_id_t method)
A proxy for actual method_matcher that will be allocated in dynamic memory.
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
A special class that allows to hold a copy of small-size method_matchers or a pointer to dynamically ...
std::array< char, buffer_size > m_buffer
The internal buffer.
friend void assign(buffered_matcher_holder_t &holder, Arg &&method_matcher)
pfn_move_t m_mover
An actual move-function.
friend void assign(buffered_matcher_holder_t &holder, http_method_id_t method)
RESTINIO_NODISCARD method_matcher_t & operator*() const noexcept
Get a reference to actual matcher inside the holder.
void move_from(buffered_matcher_holder_t &other)
buffered_matcher_holder_t & operator=(buffered_matcher_holder_t &&other) noexcept
RESTINIO_NODISCARD method_matcher_t * operator->() const noexcept
Get the pointer to actual matcher inside the holder.
buffered_matcher_holder_t & operator=(const buffered_matcher_holder_t &)=delete
method_matcher_t *(*)(void *object, void *buffer) pfn_move_t
A type of free function to be used to move a value of an object to the specified buffer.
void assign(Args &&... args)
Creates an instance of Target_Type and initializes it with arguments Args.
RESTINIO_NODISCARD method_matcher_t * get() const noexcept
Get the pointer to actual matcher inside the holder.
buffered_matcher_holder_t(buffered_matcher_holder_t &&other) noexcept
static constexpr std::size_t alignment
Alignment to be used by the internal buffer.
static constexpr std::size_t buffer_size
The size of the internal buffer.
method_matcher_t * m_matcher
A pointer to actual matcher allocated inside the internall buffer.
buffered_matcher_holder_t(const buffered_matcher_holder_t &)=delete
A matcher that finds a value in the vector of allowed values of fixed size.
fixed_size_any_of_matcher_t(std::initializer_list< http_method_id_t > values)
Initializing constructor.
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
std::array< http_method_id_t, Size > m_methods
A matcher that finds a value in the vector of disabled values of fixed size.
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
A simple method_matcher that compares just one user-specified value.
RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept override
Is the specified method can be applied to a route?
#define RESTINIO_NODISCARD
RESTINIO_NODISCARD impl::fixed_size_any_of_matcher_t< sizeof...(Args) > any_of_methods(Args &&...args)
A factory function that creates a method_matcher that allows a method if it's found in the list of al...
RESTINIO_NODISCARD impl::fixed_size_none_of_matcher_t< sizeof...(Args) > none_of_methods(Args &&...args)
A factory function that creates a method_matcher that allows a method if it isn't found in the list o...
STL namespace.
An interface of method_matcher.
method_matcher_t(method_matcher_t &&)=default
method_matcher_t & operator=(const method_matcher_t &)=default
method_matcher_t & operator=(method_matcher_t &&)=default
method_matcher_t(const method_matcher_t &)=default
virtual RESTINIO_NODISCARD bool match(const http_method_id_t &method) const noexcept=0
Is the specified method can be applied to a route?
#define const
Definition: zconf.h:230