Project

General

Profile

CppHelperClasses » handler_helpers.hpp

automate handler setting of the plugin structure according to mod_blank::handlers typelist - hazzadous, 2009-04-08 00:42

 
/**
* The following are some structures used to decide at compile-time which handlers in
* the lighttpd plugin structure to be set, based on a list of handler interface types
* i.e. calling a handlers_setter< list< UriRawHandler, UriCleanHandler > >( p ) object
* will set p->handle_uri_raw and p->handle_uri_clean hooks.
* A list of handler types supported:
* - UriRawHandler
* - UriCleanHandler
* - DocRootHandler
* - PhysicalHandler
* - StartBackendHandler
*/

#ifndef _LIGHTTPD_HANDLER_HELPERS_HPP_
#define _LIGHTTPD_HANDLER_HELPERS_HPP_

#include <boost/mpl/empty.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>

// Forward declarations for handlers_setter to use
template < typename PluginType, typename Handler, typename HandlerList >
struct handlers_setter_impl;
struct handlers_setter_end;

template < typename PluginType, typename HandlerList >
struct handlers_setter_choose
{
typedef handlers_setter_impl< PluginType,
typename boost::mpl::front< HandlerList >::type,
typename boost::mpl::pop_front< HandlerList >::type > type;
};

// calling handlers_setters type will set the hooks in p to
// the appropriate functions according to HandlerList
template < typename PluginType, typename HandlerList = typename PluginType::handlers >
struct handlers_setter
{
typedef typename boost::mpl::empty< HandlerList >::type is_empty;
typedef boost::mpl::identity< handlers_setter_end > handlers_setter_choose_end;
typedef typename boost::mpl::eval_if< is_empty,
handlers_setter_choose_end,
handlers_setter_choose< PluginType, HandlerList > >::type type;
};

/**
* handlers_setter_base will decide which our next setter will be
*/
template < typename PluginType, typename HandlerList >
struct handlers_setter_base
{
typedef typename handlers_setter< PluginType, HandlerList >::type next;
};

/**
* When we reach handlers_setter_end, we are at the end of the HandlerList
*/
struct handlers_setter_end
{
static void set( plugin& p ){}
};

/**
* Here we can partial specialize for Handler such that the right
* hook will be set.
*/
template < typename PluginType, typename Handler, typename HandlerList >
struct handlers_setter_impl : handlers_setter_base< PluginType, HandlerList > {};

// Macro for defining interfaces for handler classes, wrapper functions for
// the calls to the appropriate handlers in class( p_d ) and metafunction
// specializations of the handlers_setter_impl type.
#define MAKE_HANDLER( TypedefHandle, handler_name ) \
struct TypedefHandle { handler_t handler_name( connection& ); }; \
template < typename PluginType, typename HandlerList > \
struct handlers_setter_impl< PluginType, TypedefHandle, HandlerList > \
: handlers_setter_base< PluginType, HandlerList > \
{ \
typedef handlers_setter_base< PluginType, HandlerList > super_type; \
static handler_t handler_wrapper( server* srv, connection* con, void* p ) \
{ \
PluginType* P = reinterpret_cast< PluginType* >( p ); \
return P->handler_name( *con ); \
} \
static void set( plugin& p ) \
{ \
p.handler_name = &handler_wrapper; \
super_type::next::set( p ); \
} \
};

#endif // _LIGHTTPD_HANDLER_HELPERS_HPP_

(1-1/10)