1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Merge pull request #51 from EricMCornelius/master

Use type_traits to enable Packet& sniff_loop callback variant in C++11
This commit is contained in:
Matias Fontanini
2015-03-06 09:42:25 -08:00
2 changed files with 128 additions and 83 deletions

View File

@@ -30,6 +30,10 @@
#ifndef TINS_INTERNALS_H #ifndef TINS_INTERNALS_H
#define TINS_INTERNALS_H #define TINS_INTERNALS_H
#if TINS_IS_CXX11
#include <type_traits>
#endif
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
@@ -200,6 +204,39 @@ template<>
struct is_unsigned_integral<uint64_t> { struct is_unsigned_integral<uint64_t> {
static const bool value = true; static const bool value = true;
}; };
#if TINS_IS_CXX11
// Part of C++14 standard library
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
template <class T, class P, class=void>
struct accepts_type : std::false_type { };
template <class T, class P>
struct accepts_type<T, P, enable_if_t<
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
>> : std::true_type { };
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
return f(std::move(p));
}
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(p);
}
template <class Functor, class Packet>
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
return f(*p.pdu());
}
#endif
} // namespace Internals } // namespace Internals
} // namespace Tins } // namespace Tins
/** /**

View File

@@ -139,6 +139,9 @@ namespace Tins {
* \code * \code
* bool(PDU&); * bool(PDU&);
* bool(const PDU&); * bool(const PDU&);
* bool(const Packet&);
* bool(Packet&&);
* bool(Packet);
* \endcode * \endcode
* *
* This functor will be called using the each of the sniffed packets * This functor will be called using the each of the sniffed packets
@@ -391,7 +394,7 @@ namespace Tins {
/** /**
* \brief Iterates over packets sniffed by a BaseSniffer. * \brief Iterates over packets sniffed by a BaseSniffer.
*/ */
class SnifferIterator : public std::iterator<std::forward_iterator_tag, PDU> { class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
public: public:
/** /**
* Constructs a SnifferIterator. * Constructs a SnifferIterator.
@@ -425,15 +428,15 @@ namespace Tins {
* Dereferences the iterator. * Dereferences the iterator.
* \return reference to the current packet. * \return reference to the current packet.
*/ */
PDU &operator*() { Packet &operator*() {
return *pkt.pdu(); return pkt;
} }
/** /**
* Dereferences the iterator. * Dereferences the iterator.
* \return pointer to the current packet. * \return pointer to the current packet.
*/ */
PDU *operator->() { Packet *operator->() {
return &(**this); return &(**this);
} }
@@ -578,8 +581,13 @@ namespace Tins {
for(iterator it = begin(); it != end(); ++it) { for(iterator it = begin(); it != end(); ++it) {
try { try {
// If the functor returns false, we're done // If the functor returns false, we're done
if(!function(*it)) #if TINS_IS_CXX11
if (!Tins::Internals::invoke_loop_cb(function, *it))
return; return;
#else
if(!function(*it->pdu()))
return;
#endif
} }
catch(malformed_packet&) { } catch(malformed_packet&) { }
catch(pdu_not_found&) { } catch(pdu_not_found&) { }