#ifndef BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915
#define BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915

//          Copyright Dean Michael Berris 2010.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <boost/network/traits/string.hpp>
#include <boost/variant/variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/network/support/is_pod.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>

/**
 *
 *  To create your own string directive, you can use the preprocessor macro
 *  BOOST_NETWORK_STRING_DIRECTIVE which takes three parameters: the name of
 *  the directive, a name for the variable to use in the directive visitor,
 *  and the body to be implemented in the visitor. An example directive for
 *  setting the source of a message would look something like this given the
 *  BOOST_NETWORK_STRING_DIRECTIVE macro:
 *
 *      BOOST_NETWORK_STRING_DIRECTIVE(source, source_,
 *          message.source(source_)
 *          , message.source=source_);
 *
 */

#ifndef BOOST_NETWORK_STRING_DIRECTIVE
#define BOOST_NETWORK_STRING_DIRECTIVE(name, value, body, pod_body)         \
  template <class ValueType>                                                \
  struct name##_directive {                                                 \
    ValueType const& value;                                                 \
    explicit name##_directive(ValueType const& value_) : value(value_) {}   \
    name##_directive(name##_directive const& other) : value(other.value) {} \
    template <class Tag, template <class> class Message>                    \
    typename enable_if<is_pod<Tag>, void>::type operator()(                 \
        Message<Tag>& message) const {                                      \
      pod_body;                                                             \
    }                                                                       \
    template <class Tag, template <class> class Message>                    \
    typename enable_if<mpl::not_<is_pod<Tag> >, void>::type operator()(     \
        Message<Tag>& message) const {                                      \
      body;                                                                 \
    }                                                                       \
  };                                                                        \
                                                                            \
  template <class T>                                                        \
  inline name##_directive<T> name(T const& input) {                         \
    return name##_directive<T>(input);                                      \
  }
#endif /* BOOST_NETWORK_STRING_DIRECTIVE */

#endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 \
          */
