<commit_before>// Copyright (c) 2004 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef OPERATOR_040729_HPP
#define OPERATOR_040729_HPP

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_traits/is_same.hpp>
#include <luabind/detail/other.hpp>
#include <luabind/raw_policy.hpp>

#if defined(__GNUC__) && __GNUC__ < 3
# define LUABIND_NO_STRINGSTREAM
#else
# if defined(BOOST_NO_STRINGSTREAM)
#  define LUABIND_NO_STRINGSTREAM
# endif
#endif

#ifdef LUABIND_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif

namespace luabind { namespace detail {

    template<class W, class T> struct unwrap_parameter_type;
    template<class Derived> struct operator_ {};

    struct operator_void_return {};

#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    template<class T>
    inline T const& operator,(T const& x, operator_void_return)
    {
        return x;
    }
#endif

}} // namespace luabind

namespace luabind { namespace operators {

   #define BOOST_PP_ITERATION_PARAMS_1 (3, \
       (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>))
   #include BOOST_PP_ITERATE()

}} // namespace luabind::operators

#include <boost/preprocessor/iteration/local.hpp>

namespace luabind {

    template<class Derived>
    struct self_base
    {
        operators::call_operator0<Derived> operator()() const
        {
            return 0;
        }

#define BOOST_PP_LOCAL_MACRO(n) \
        template<BOOST_PP_ENUM_PARAMS(n, class A)> \
        BOOST_PP_CAT(operators::call_operator, n)< \
            Derived \
            BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \
        >\
        operator()( \
            BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \
        ) const \
        { \
            return 0; \
        }

#define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY)
#include BOOST_PP_LOCAL_ITERATE()

    };

    struct self_type : self_base<self_type>
    {
    };

    struct const_self_type : self_base<const_self_type>
    {
    };

namespace detail {

    template<class W, class T>
    struct unwrap_parameter_type
    {
        typedef typename boost::mpl::eval_if<
            boost::is_same<T, self_type>
          , boost::mpl::identity<W&>
          , boost::mpl::eval_if<
                boost::is_same<T, const_self_type>
              , boost::mpl::identity<W const&>
              , unwrap_other<T>
            >
        >::type type;
    };

    template<class Derived, class A, class B>
    struct binary_operator
        : operator_<binary_operator<Derived, A, B> >
    {
        binary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;
            typedef typename unwrap_parameter_type<T, B>::type arg1;

            static void execute(lua_State* L, arg0 _0, arg1 _1)
            {
                Derived::template apply<arg0, arg1, Policies>::execute(
                    L, _0, _1);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Derived, class A>
    struct unary_operator
        : operator_<unary_operator<Derived, A> >
    {
        unary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;

            static void execute(lua_State* L, arg0 _0)
            {
                Derived::template apply<arg0, Policies>::execute(L, _0);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Policies>
    inline void operator_result(lua_State* L, operator_void_return, Policies*)
    {
    }

    namespace mpl = boost::mpl;

    template<class T, class Policies>
    inline void operator_result(lua_State* L, T const& x, Policies*)
    {
        typedef typename find_conversion_policy<
            0
          , Policies
        >::type cv_policy;

        typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv;

        cv.apply(L, x);
    }

}} // namespace detail::luabind

namespace luabind {

#define LUABIND_BINARY_OPERATOR(name_, op) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T0, class T1, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T0 _0, T1 _1) \
                { \
                    detail::operator_result(L, _0 op _1, (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , U \
      , T \
    > \
    inline operator op(self_base<U>, T const&) \
    { \
        return 0; \
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , T \
      , U \
    > \
    inline operator op(T const&, self_base<U>) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , self_type \
    > \
    inline operator op(self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , const_self_type \
    > \
    inline operator op(self_type, const_self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , self_type \
    > \
    inline operator op(const_self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , const_self_type \
    > \
    inline operator op(const_self_type, const_self_type) \
    { \
        return 0; \
    }

    LUABIND_BINARY_OPERATOR(add, +)
    LUABIND_BINARY_OPERATOR(sub, -)
    LUABIND_BINARY_OPERATOR(mul, *)
    LUABIND_BINARY_OPERATOR(div, /)
    LUABIND_BINARY_OPERATOR(pow, ^)
    LUABIND_BINARY_OPERATOR(lt, <)
    LUABIND_BINARY_OPERATOR(le, <=)
    LUABIND_BINARY_OPERATOR(eq, ==)

#undef LUABIND_UNARY_OPERATOR

#define LUABIND_UNARY_OPERATOR(name_, op, fn) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T x) \
                { \
                    detail::operator_result(L, op(x), (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T> \
    detail::unary_operator< \
        operators::name_ \
      , T \
    > \
    inline fn(self_base<T>) \
    { \
        return 0; \
    }

    template<class T>
    std::string tostring_operator(T const& x)
    {
#ifdef LUABIND_NO_STRINGSTREAM
        std::strstream s;
        s << x << std::ends;
#else
        std::stringstream s;
        s << x;
#endif
        return s.str();
    }

    LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring)
    LUABIND_UNARY_OPERATOR(unm, -, operator-)

#undef LUABIND_BINARY_OPERATOR

    namespace {

        LUABIND_ANONYMOUS_FIX self_type self;
        LUABIND_ANONYMOUS_FIX const_self_type const_self;

    } // namespace unnamed

} // namespace luabind

#endif // OPERATOR_040729_HPP
<commit_msg>fix header compile of operator.hpp<commit_after>// Copyright (c) 2004 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef OPERATOR_040729_HPP
#define OPERATOR_040729_HPP

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_traits/is_same.hpp>
#include <luabind/detail/other.hpp>
#include <luabind/raw_policy.hpp>

#if defined(__GNUC__) && __GNUC__ < 3
# define LUABIND_NO_STRINGSTREAM
#else
# if defined(BOOST_NO_STRINGSTREAM)
#  define LUABIND_NO_STRINGSTREAM
# endif
#endif

#ifdef LUABIND_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif

namespace luabind { namespace detail {

    template<class W, class T> struct unwrap_parameter_type;
    template<class Derived> struct operator_ {};

    struct operator_void_return {};

#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    template<class T>
    inline T const& operator,(T const& x, operator_void_return)
    {
        return x;
    }
#endif

}} // namespace luabind

#include <boost/preprocessor/iteration/iterate.hpp>

namespace luabind { namespace operators {

   #define BOOST_PP_ITERATION_PARAMS_1 (3, \
       (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>))
   #include BOOST_PP_ITERATE()

}} // namespace luabind::operators

#include <boost/preprocessor/iteration/local.hpp>

namespace luabind {

    template<class Derived>
    struct self_base
    {
        operators::call_operator0<Derived> operator()() const
        {
            return 0;
        }

#define BOOST_PP_LOCAL_MACRO(n) \
        template<BOOST_PP_ENUM_PARAMS(n, class A)> \
        BOOST_PP_CAT(operators::call_operator, n)< \
            Derived \
            BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \
        >\
        operator()( \
            BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \
        ) const \
        { \
            return 0; \
        }

#define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY)
#include BOOST_PP_LOCAL_ITERATE()

    };

    struct self_type : self_base<self_type>
    {
    };

    struct const_self_type : self_base<const_self_type>
    {
    };

namespace detail {

    template<class W, class T>
    struct unwrap_parameter_type
    {
        typedef typename boost::mpl::eval_if<
            boost::is_same<T, self_type>
          , boost::mpl::identity<W&>
          , boost::mpl::eval_if<
                boost::is_same<T, const_self_type>
              , boost::mpl::identity<W const&>
              , unwrap_other<T>
            >
        >::type type;
    };

    template<class Derived, class A, class B>
    struct binary_operator
        : operator_<binary_operator<Derived, A, B> >
    {
        binary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;
            typedef typename unwrap_parameter_type<T, B>::type arg1;

            static void execute(lua_State* L, arg0 _0, arg1 _1)
            {
                Derived::template apply<arg0, arg1, Policies>::execute(
                    L, _0, _1);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Derived, class A>
    struct unary_operator
        : operator_<unary_operator<Derived, A> >
    {
        unary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;

            static void execute(lua_State* L, arg0 _0)
            {
                Derived::template apply<arg0, Policies>::execute(L, _0);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Policies>
    inline void operator_result(lua_State* L, operator_void_return, Policies*)
    {
    }

    namespace mpl = boost::mpl;

    template<class T, class Policies>
    inline void operator_result(lua_State* L, T const& x, Policies*)
    {
        typedef typename find_conversion_policy<
            0
          , Policies
        >::type cv_policy;

        typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv;

        cv.apply(L, x);
    }

}} // namespace detail::luabind

namespace luabind {

#define LUABIND_BINARY_OPERATOR(name_, op) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T0, class T1, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T0 _0, T1 _1) \
                { \
                    detail::operator_result(L, _0 op _1, (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , U \
      , T \
    > \
    inline operator op(self_base<U>, T const&) \
    { \
        return 0; \
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , T \
      , U \
    > \
    inline operator op(T const&, self_base<U>) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , self_type \
    > \
    inline operator op(self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , const_self_type \
    > \
    inline operator op(self_type, const_self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , self_type \
    > \
    inline operator op(const_self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , const_self_type \
    > \
    inline operator op(const_self_type, const_self_type) \
    { \
        return 0; \
    }

    LUABIND_BINARY_OPERATOR(add, +)
    LUABIND_BINARY_OPERATOR(sub, -)
    LUABIND_BINARY_OPERATOR(mul, *)
    LUABIND_BINARY_OPERATOR(div, /)
    LUABIND_BINARY_OPERATOR(pow, ^)
    LUABIND_BINARY_OPERATOR(lt, <)
    LUABIND_BINARY_OPERATOR(le, <=)
    LUABIND_BINARY_OPERATOR(eq, ==)

#undef LUABIND_UNARY_OPERATOR

#define LUABIND_UNARY_OPERATOR(name_, op, fn) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T x) \
                { \
                    detail::operator_result(L, op(x), (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T> \
    detail::unary_operator< \
        operators::name_ \
      , T \
    > \
    inline fn(self_base<T>) \
    { \
        return 0; \
    }

    template<class T>
    std::string tostring_operator(T const& x)
    {
#ifdef LUABIND_NO_STRINGSTREAM
        std::strstream s;
        s << x << std::ends;
#else
        std::stringstream s;
        s << x;
#endif
        return s.str();
    }

    LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring)
    LUABIND_UNARY_OPERATOR(unm, -, operator-)

#undef LUABIND_BINARY_OPERATOR

    namespace {

        LUABIND_ANONYMOUS_FIX self_type self;
        LUABIND_ANONYMOUS_FIX const_self_type const_self;

    } // namespace unnamed

} // namespace luabind

#endif // OPERATOR_040729_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2004 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef OPERATOR_040729_HPP
#define OPERATOR_040729_HPP

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_traits/is_same.hpp>
#include <luabind/detail/other.hpp>
#include <luabind/raw_policy.hpp>

#if defined(__GNUC__) && __GNUC__ < 3
# define LUABIND_NO_STRINGSTREAM
#else
# if defined(BOOST_NO_STRINGSTREAM)
#  define LUABIND_NO_STRINGSTREAM
# endif
#endif

#ifdef LUABIND_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif

namespace luabind { namespace detail {

    template<class W, class T> struct unwrap_parameter_type;
    template<class Derived> struct operator_ {};

    struct operator_void_return {};

#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    template<class T>
    inline T const& operator,(T const& x, operator_void_return)
    {
        return x;
    }
#endif

}} // namespace luabind

#include <boost/preprocessor/iteration/iterate.hpp>

namespace luabind { namespace operators {

   #define BOOST_PP_ITERATION_PARAMS_1 (3, \
       (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>))
   #include BOOST_PP_ITERATE()

}} // namespace luabind::operators

#include <boost/preprocessor/iteration/local.hpp>

namespace luabind {

    template<class Derived>
    struct self_base
    {
        operators::call_operator0<Derived> operator()() const
        {
            return 0;
        }

#define BOOST_PP_LOCAL_MACRO(n) \
        template<BOOST_PP_ENUM_PARAMS(n, class A)> \
        BOOST_PP_CAT(operators::call_operator, n)< \
            Derived \
            BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \
        >\
        operator()( \
            BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \
        ) const \
        { \
            return 0; \
        }

#define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY)
#include BOOST_PP_LOCAL_ITERATE()

    };

    struct self_type : self_base<self_type>
    {
    };

    struct const_self_type : self_base<const_self_type>
    {
    };

namespace detail {

    template<class W, class T>
    struct unwrap_parameter_type
    {
        typedef typename boost::mpl::eval_if<
            boost::is_same<T, self_type>
          , boost::mpl::identity<W&>
          , boost::mpl::eval_if<
                boost::is_same<T, const_self_type>
              , boost::mpl::identity<W const&>
              , unwrap_other<T>
            >
        >::type type;
    };

    template<class Derived, class A, class B>
    struct binary_operator
        : operator_<binary_operator<Derived, A, B> >
    {
        binary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;
            typedef typename unwrap_parameter_type<T, B>::type arg1;

            static void execute(lua_State* L, arg0 _0, arg1 _1)
            {
                Derived::template apply<arg0, arg1, Policies>::execute(
                    L, _0, _1);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Derived, class A>
    struct unary_operator
        : operator_<unary_operator<Derived, A> >
    {
        unary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;

            static void execute(lua_State* L, arg0 _0)
            {
                Derived::template apply<arg0, Policies>::execute(L, _0);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Policies>
    inline void operator_result(lua_State*, operator_void_return, Policies*)
    {
    }

    namespace mpl = boost::mpl;

    template<class T, class Policies>
    inline void operator_result(lua_State* L, T const& x, Policies*)
    {
        typedef typename find_conversion_policy<
            0
          , Policies
        >::type cv_policy;

        typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv;

        cv.apply(L, x);
    }

}} // namespace detail::luabind

namespace luabind {

#define LUABIND_BINARY_OPERATOR(name_, op) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T0, class T1, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T0 _0, T1 _1) \
                { \
                    detail::operator_result(L, _0 op _1, (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , U \
      , T \
    > \
    inline operator op(self_base<U>, T const&) \
    { \
        return 0; \
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , T \
      , U \
    > \
    inline operator op(T const&, self_base<U>) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , self_type \
    > \
    inline operator op(self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , const_self_type \
    > \
    inline operator op(self_type, const_self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , self_type \
    > \
    inline operator op(const_self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , const_self_type \
    > \
    inline operator op(const_self_type, const_self_type) \
    { \
        return 0; \
    }

    LUABIND_BINARY_OPERATOR(add, +)
    LUABIND_BINARY_OPERATOR(sub, -)
    LUABIND_BINARY_OPERATOR(mul, *)
    LUABIND_BINARY_OPERATOR(div, /)
    LUABIND_BINARY_OPERATOR(pow, ^)
    LUABIND_BINARY_OPERATOR(lt, <)
    LUABIND_BINARY_OPERATOR(le, <=)
    LUABIND_BINARY_OPERATOR(eq, ==)

#undef LUABIND_UNARY_OPERATOR

#define LUABIND_UNARY_OPERATOR(name_, op, fn) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T x) \
                { \
                    detail::operator_result(L, op(x), (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T> \
    detail::unary_operator< \
        operators::name_ \
      , T \
    > \
    inline fn(self_base<T>) \
    { \
        return 0; \
    }

    template<class T>
    std::string tostring_operator(T const& x)
    {
#ifdef LUABIND_NO_STRINGSTREAM
        std::strstream s;
        s << x << std::ends;
#else
        std::stringstream s;
        s << x;
#endif
        return s.str();
    }

    LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring)
    LUABIND_UNARY_OPERATOR(unm, -, operator-)

#undef LUABIND_BINARY_OPERATOR

    namespace {

        LUABIND_ANONYMOUS_FIX self_type self;
        LUABIND_ANONYMOUS_FIX const_self_type const_self;

    } // namespace unnamed

} // namespace luabind

#endif // OPERATOR_040729_HPP

<commit_msg>Don't leave our macros defined when they're for internal use.<commit_after>// Copyright (c) 2004 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef OPERATOR_040729_HPP
#define OPERATOR_040729_HPP

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/apply_wrap.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_traits/is_same.hpp>
#include <luabind/detail/other.hpp>
#include <luabind/raw_policy.hpp>

#if defined(__GNUC__) && __GNUC__ < 3
# define LUABIND_NO_STRINGSTREAM
#else
# if defined(BOOST_NO_STRINGSTREAM)
#  define LUABIND_NO_STRINGSTREAM
# endif
#endif

#ifdef LUABIND_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif

namespace luabind { namespace detail {

    template<class W, class T> struct unwrap_parameter_type;
    template<class Derived> struct operator_ {};

    struct operator_void_return {};

#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    template<class T>
    inline T const& operator,(T const& x, operator_void_return)
    {
        return x;
    }
#endif

}} // namespace luabind

#include <boost/preprocessor/iteration/iterate.hpp>

namespace luabind { namespace operators {

   #define BOOST_PP_ITERATION_PARAMS_1 (3, \
       (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>))
   #include BOOST_PP_ITERATE()

}} // namespace luabind::operators

#include <boost/preprocessor/iteration/local.hpp>

namespace luabind {

    template<class Derived>
    struct self_base
    {
        operators::call_operator0<Derived> operator()() const
        {
            return 0;
        }

#define BOOST_PP_LOCAL_MACRO(n) \
        template<BOOST_PP_ENUM_PARAMS(n, class A)> \
        BOOST_PP_CAT(operators::call_operator, n)< \
            Derived \
            BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \
        >\
        operator()( \
            BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \
        ) const \
        { \
            return 0; \
        }

#define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY)
#include BOOST_PP_LOCAL_ITERATE()

    };

    struct self_type : self_base<self_type>
    {
    };

    struct const_self_type : self_base<const_self_type>
    {
    };

namespace detail {

    template<class W, class T>
    struct unwrap_parameter_type
    {
        typedef typename boost::mpl::eval_if<
            boost::is_same<T, self_type>
          , boost::mpl::identity<W&>
          , boost::mpl::eval_if<
                boost::is_same<T, const_self_type>
              , boost::mpl::identity<W const&>
              , unwrap_other<T>
            >
        >::type type;
    };

    template<class Derived, class A, class B>
    struct binary_operator
        : operator_<binary_operator<Derived, A, B> >
    {
        binary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;
            typedef typename unwrap_parameter_type<T, B>::type arg1;

            static void execute(lua_State* L, arg0 _0, arg1 _1)
            {
                Derived::template apply<arg0, arg1, Policies>::execute(
                    L, _0, _1);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Derived, class A>
    struct unary_operator
        : operator_<unary_operator<Derived, A> >
    {
        unary_operator(int) {}

        template<class T, class Policies>
        struct apply
        {
            typedef typename unwrap_parameter_type<T, A>::type arg0;

            static void execute(lua_State* L, arg0 _0)
            {
                Derived::template apply<arg0, Policies>::execute(L, _0);
            }
        };

        static char const* name()
        {
            return Derived::name();
        }
    };

    template<class Policies>
    inline void operator_result(lua_State*, operator_void_return, Policies*)
    {
    }

    namespace mpl = boost::mpl;

    template<class T, class Policies>
    inline void operator_result(lua_State* L, T const& x, Policies*)
    {
        typedef typename find_conversion_policy<
            0
          , Policies
        >::type cv_policy;

        typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv;

        cv.apply(L, x);
    }

}} // namespace detail::luabind

namespace luabind {

#define LUABIND_BINARY_OPERATOR(name_, op) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T0, class T1, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T0 _0, T1 _1) \
                { \
                    detail::operator_result(L, _0 op _1, (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , U \
      , T \
    > \
    inline operator op(self_base<U>, T const&) \
    { \
        return 0; \
    } \
    \
    template<class T, class U> \
    detail::binary_operator< \
        operators::name_ \
      , T \
      , U \
    > \
    inline operator op(T const&, self_base<U>) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , self_type \
    > \
    inline operator op(self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , self_type \
      , const_self_type \
    > \
    inline operator op(self_type, const_self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , self_type \
    > \
    inline operator op(const_self_type, self_type) \
    { \
        return 0; \
    } \
    \
    detail::binary_operator< \
        operators::name_ \
      , const_self_type \
      , const_self_type \
    > \
    inline operator op(const_self_type, const_self_type) \
    { \
        return 0; \
    }

    LUABIND_BINARY_OPERATOR(add, +)
    LUABIND_BINARY_OPERATOR(sub, -)
    LUABIND_BINARY_OPERATOR(mul, *)
    LUABIND_BINARY_OPERATOR(div, /)
    LUABIND_BINARY_OPERATOR(pow, ^)
    LUABIND_BINARY_OPERATOR(lt, <)
    LUABIND_BINARY_OPERATOR(le, <=)
    LUABIND_BINARY_OPERATOR(eq, ==)

#undef LUABIND_BINARY_OPERATOR

#define LUABIND_UNARY_OPERATOR(name_, op, fn) \
    namespace operators { \
\
        struct name_ \
        { \
            template<class T, class Policies> \
            struct apply \
            { \
                static void execute(lua_State* L, T x) \
                { \
                    detail::operator_result(L, op(x), (Policies*)0); \
                } \
            }; \
\
            static char const* name() \
            { \
                return "__" # name_; \
            } \
        }; \
\
    } \
    \
    template<class T> \
    detail::unary_operator< \
        operators::name_ \
      , T \
    > \
    inline fn(self_base<T>) \
    { \
        return 0; \
    }

    template<class T>
    std::string tostring_operator(T const& x)
    {
#ifdef LUABIND_NO_STRINGSTREAM
        std::strstream s;
        s << x << std::ends;
#else
        std::stringstream s;
        s << x;
#endif
        return s.str();
    }

    LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring)
    LUABIND_UNARY_OPERATOR(unm, -, operator-)

#undef LUABIND_UNARY_OPERATOR

    namespace {

        LUABIND_ANONYMOUS_FIX self_type self;
        LUABIND_ANONYMOUS_FIX const_self_type const_self;

    } // namespace unnamed

} // namespace luabind

#endif // OPERATOR_040729_HPP

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <utility>

#include "components/command_line.hpp"
#include "utils.hpp"

enum {
    /*
     * Same order as they are initialized
     * in main(). Perhaps we should have a
     * getter funtion instead?
     *
     * These (or well, only main) are used in
     * validate_arguments() to get the group of
     * main arguments so that we can find if any of
     * those are passed.
     *
     * I'm a bit unsure if it's worth the time to
     * implement a better way to do this. This will work
     * as long as they are in the same order as they are
     * initialized in in main().
     */
    main,
    excl,
    exact,
    misc
};

enum { /* magic padding numbers */
    padding_margin = 4,
    desc_align_magic = 7
};

cliparser::cli_type cliparser::make(const string &&progname, const groups &&groups)
{
    return std::make_unique<cliparser>(
        "Usage: " + progname + " option... download_path", std::forward<decltype(groups)>(groups)
    );
}

void cliparser::usage() const
{
    std::cout << synopsis_ << "\n\n";

    size_t maxlen = 0;

    /*
     * Get the length of the longest string in the flag column
     * which is used to align the description fields.
     */
    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            size_t len = opt.flag_long.length() + opt.flag.length() +
                         opt.token.length() + padding_margin;

            maxlen = std::max(len, maxlen);
        }
    }

    /*
     * Print each option group, its options, the options'
     * descriptions, token and possible values for said token (if any).
     */
    for (const auto &group : valid_groups_) {
        std::cout << group.name << " arguments"
                  << (group.synopsis.empty() ? ":" : " - " + group.synopsis + ":")
                  << '\n';

        for (const auto &opt : group.options) {
            /* Padding between flags and description. */
            size_t pad = maxlen - opt.flag_long.length() - opt.token.length();

            std::cout << "  " << opt.flag << ", " << opt.flag_long;

            if (!opt.token.empty()) {
                std::cout << ' ' << opt.token;
                pad--;
            }

            /*
             * Print the list with accepted values.
             * This line is printed below the description.
             */
            if (!opt.values.empty()) {
                std::cout << std::setw(pad + opt.desc.length())
                          << opt.desc << '\n';

                pad += opt.flag_long.length() + opt.token.length() + desc_align_magic;

                std::cout << string(pad, ' ') << opt.token << " is one of: "
                          << utils::vector_to_string(opt.values);
            } else {
                std::cout << std::setw(pad + opt.desc.length()) << opt.desc;
            }

            std::cout << '\n';
        }

        std::cout << std::endl;
    }
}

string cliparser::get(string opt) const
{
    if (has(std::forward<string>(opt)))
        return passed_opts_.find(opt)->second;

    return "";
}

vector<string> cliparser::get_many(const string &&opt) const
{
    vector<string> values;

    if (has(opt)) {
        auto range = passed_opts_.equal_range(opt);

        /* Can't we just return {range.first, range.second} somehow? */
        for (auto &opt = range.first; opt != range.second; opt++)
            values.push_back(opt->second);
    }

    return values;
}

void cliparser::process_arguments(const vector<string> &args)
{
    for (size_t i = 0; i < args.size(); i++) {
        const string_view &arg = args[i];
        const string_view &next_arg = args.size() > i + 1 ? args[i + 1] : "";

        parse(arg, next_arg);
    }
}

void cliparser::validate_arguments() const
{
    if (!has(0))
        throw argument_error("you must specify a download path");

    if (positional_args_.size() > 1)
        throw argument_error("only one positional argument is allowed");

    vector<string> passed_opts, required_opts;

    for (const auto &opt : passed_opts_) {
        /* We don't want the value, only the flag. */
        passed_opts.emplace_back(opt.first);
    }

    for (const auto &opt : valid_groups_[main].options)
        required_opts.emplace_back(opt.flag_long.substr(2));

    /* Has any required arguments been passed? */
    const bool req_match = utils::any_intersection(passed_opts, required_opts);
    const bool ident_passed = std::find(passed_opts.cbegin(), passed_opts.cend(), "ident")
        != passed_opts.cend();

    if (ident_passed && passed_opts.size() > 1)
        throw argument_error("ident flag is exclusive and may not be passed with another flag");
    else if (!req_match)
        throw argument_error("at least one main argument must be specified");
}

auto cliparser::check_value(const string_view &flag, const string_view &value, const vector<string> &values)
{

    if (value.empty())
        throw value_error("missing value for " + string(flag.data()));

    if (!values.empty() && std::find(values.cbegin(), values.cend(), value) == values.cend()) {
        throw value_error(
            "invalid value '" + string(value.data()) + "' for argument " + string(flag.data()) +
            "; valid options are: " + utils::vector_to_string(values)
        );
    }

    return value;
}

void cliparser::parse(const string_view &input, const string_view &input_next)
{
    if (skipnext_) {
        /* The next input is a value, which we've already used. */
        skipnext_ = false;
        return;
    }

    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            if (is(input, opt.flag, opt.flag_long)) {
                if (opt.token.empty()) {
                    /* The option is only a flag. */
                    passed_opts_.emplace(opt.flag_long.substr(2), "");
                } else {
                    /*
                     * The option should have an accompanied value.
                     * And may be that it must be an element in opt.values.
                     */
                    const auto value = check_value(input, input_next, opt.values);
                    skipnext_ = (value == input_next);
                    passed_opts_.emplace(opt.flag_long.substr(2), value);
                }

                return;
            }
        }
    }

    if (input[0] == '-')
        throw argument_error("unrecognized option " + string(input.data()));

    positional_args_.emplace_back(input);
}
<commit_msg>command_line: remove rogue newline<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <utility>

#include "components/command_line.hpp"
#include "utils.hpp"

enum {
    /*
     * Same order as they are initialized
     * in main(). Perhaps we should have a
     * getter funtion instead?
     *
     * These (or well, only main) are used in
     * validate_arguments() to get the group of
     * main arguments so that we can find if any of
     * those are passed.
     *
     * I'm a bit unsure if it's worth the time to
     * implement a better way to do this. This will work
     * as long as they are in the same order as they are
     * initialized in in main().
     */
    main,
    excl,
    exact,
    misc
};

enum { /* magic padding numbers */
    padding_margin = 4,
    desc_align_magic = 7
};

cliparser::cli_type cliparser::make(const string &&progname, const groups &&groups)
{
    return std::make_unique<cliparser>(
        "Usage: " + progname + " option... download_path", std::forward<decltype(groups)>(groups)
    );
}

void cliparser::usage() const
{
    std::cout << synopsis_ << "\n\n";

    size_t maxlen = 0;

    /*
     * Get the length of the longest string in the flag column
     * which is used to align the description fields.
     */
    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            size_t len = opt.flag_long.length() + opt.flag.length() +
                         opt.token.length() + padding_margin;

            maxlen = std::max(len, maxlen);
        }
    }

    /*
     * Print each option group, its options, the options'
     * descriptions, token and possible values for said token (if any).
     */
    for (const auto &group : valid_groups_) {
        std::cout << group.name << " arguments"
                  << (group.synopsis.empty() ? ":" : " - " + group.synopsis + ":")
                  << '\n';

        for (const auto &opt : group.options) {
            /* Padding between flags and description. */
            size_t pad = maxlen - opt.flag_long.length() - opt.token.length();

            std::cout << "  " << opt.flag << ", " << opt.flag_long;

            if (!opt.token.empty()) {
                std::cout << ' ' << opt.token;
                pad--;
            }

            /*
             * Print the list with accepted values.
             * This line is printed below the description.
             */
            if (!opt.values.empty()) {
                std::cout << std::setw(pad + opt.desc.length())
                          << opt.desc << '\n';

                pad += opt.flag_long.length() + opt.token.length() + desc_align_magic;

                std::cout << string(pad, ' ') << opt.token << " is one of: "
                          << utils::vector_to_string(opt.values);
            } else {
                std::cout << std::setw(pad + opt.desc.length()) << opt.desc;
            }

            std::cout << '\n';
        }

        std::cout << std::endl;
    }
}

string cliparser::get(string opt) const
{
    if (has(std::forward<string>(opt)))
        return passed_opts_.find(opt)->second;

    return "";
}

vector<string> cliparser::get_many(const string &&opt) const
{
    vector<string> values;

    if (has(opt)) {
        auto range = passed_opts_.equal_range(opt);

        /* Can't we just return {range.first, range.second} somehow? */
        for (auto &opt = range.first; opt != range.second; opt++)
            values.push_back(opt->second);
    }

    return values;
}

void cliparser::process_arguments(const vector<string> &args)
{
    for (size_t i = 0; i < args.size(); i++) {
        const string_view &arg = args[i];
        const string_view &next_arg = args.size() > i + 1 ? args[i + 1] : "";

        parse(arg, next_arg);
    }
}

void cliparser::validate_arguments() const
{
    if (!has(0))
        throw argument_error("you must specify a download path");

    if (positional_args_.size() > 1)
        throw argument_error("only one positional argument is allowed");

    vector<string> passed_opts, required_opts;

    for (const auto &opt : passed_opts_) {
        /* We don't want the value, only the flag. */
        passed_opts.emplace_back(opt.first);
    }

    for (const auto &opt : valid_groups_[main].options)
        required_opts.emplace_back(opt.flag_long.substr(2));

    /* Has any required arguments been passed? */
    const bool req_match = utils::any_intersection(passed_opts, required_opts);
    const bool ident_passed = std::find(passed_opts.cbegin(), passed_opts.cend(), "ident")
        != passed_opts.cend();

    if (ident_passed && passed_opts.size() > 1)
        throw argument_error("ident flag is exclusive and may not be passed with another flag");
    else if (!req_match)
        throw argument_error("at least one main argument must be specified");
}

auto cliparser::check_value(const string_view &flag, const string_view &value, const vector<string> &values)
{
    if (value.empty())
        throw value_error("missing value for " + string(flag.data()));

    if (!values.empty() && std::find(values.cbegin(), values.cend(), value) == values.cend()) {
        throw value_error(
            "invalid value '" + string(value.data()) + "' for argument " + string(flag.data()) +
            "; valid options are: " + utils::vector_to_string(values)
        );
    }

    return value;
}

void cliparser::parse(const string_view &input, const string_view &input_next)
{
    if (skipnext_) {
        /* The next input is a value, which we've already used. */
        skipnext_ = false;
        return;
    }

    for (const auto &group : valid_groups_) {
        for (const auto &opt : group.options) {
            if (is(input, opt.flag, opt.flag_long)) {
                if (opt.token.empty()) {
                    /* The option is only a flag. */
                    passed_opts_.emplace(opt.flag_long.substr(2), "");
                } else {
                    /*
                     * The option should have an accompanied value.
                     * And may be that it must be an element in opt.values.
                     */
                    const auto value = check_value(input, input_next, opt.values);
                    skipnext_ = (value == input_next);
                    passed_opts_.emplace(opt.flag_long.substr(2), value);
                }

                return;
            }
        }
    }

    if (input[0] == '-')
        throw argument_error("unrecognized option " + string(input.data()));

    positional_args_.emplace_back(input);
}
<|endoftext|>


<commit_before>#pragma once

#include "fwd.hpp"
#include <configure/log.hpp>

#include <string>
#include <typeinfo>
#include <type_traits>
#include <stdexcept>

namespace configure { namespace lua {

	template<typename T>
	struct Converter
	{
		typedef T& extract_type;

		static std::string const& type_name()
		{
			static std::string name = std::string("typeid-") + typeid(T).name();
			return name;
		}

		static extract_type extract(lua_State* state, int index)
		{

			T* value = extract_ptr(state, index);
			if (value == nullptr)
			{
				std::string err = "Expected value of type '"
					+ type_name()
					+ "', got '" + luaL_tolstring(state, index, nullptr) + "'";
				throw std::runtime_error(err);
			}
			return *value;
		}

		static T* extract_ptr(lua_State* state, int index)
		{
			void* mem = luaL_testudata(state, index, type_name().c_str());
			return ((T*) mem);
		}

		static bool push_metatable(lua_State* state)
		{
			std::string name = type_name();
			if (!luaL_newmetatable(state, name.c_str()))
				return false;
			if (!std::is_trivially_destructible<T>::value)
			{
				lua_pushstring(state, "__gc");
				lua_pushcfunction(state, &_call_destructor);
				lua_settable(state, -3);
			}
			return true;
		}
		static bool push_metatable(lua_State* state, std::string const& friendly_name)
		{
			bool is_new = push_metatable(state);
			if (is_new && !friendly_name.empty())
			{
				lua_pushvalue(state, -1);
				lua_setglobal(state, friendly_name.c_str());
			}
			return is_new;
		}

		static int _call_destructor(lua_State* L)
		{
			if (T* object = reinterpret_cast<T*>(lua_touserdata(L, 1)))
				object->~T();
			return 0;
		}

		template<typename... Args>
		static T& push(lua_State* state, Args&&... args)
		{
			void* mem = lua_newuserdata(state, sizeof(T));
			T* data = new (mem) T(std::forward<Args>(args)...);
			push_metatable(state);
			lua_setmetatable(state, -2);
			return *data;
		}
	};

	template<typename T> struct Converter<T*> : Converter<T> {};
	template<typename T> struct Converter<T&> : Converter<T> {};
	template<typename T> struct Converter<T const> : Converter<T> {};

	template<>
	struct Converter<std::string>
	{
		typedef std::string extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tostring(state, index); }

		static void push(lua_State* state, std::string const& value)
		{ lua_pushstring(state, value.c_str()); }
	};

	template<>
	struct Converter<char const*> : Converter<std::string>
	{
		static void push(lua_State* state, char const* value)
		{ lua_pushstring(state, value); }
	};

	template<unsigned size>
	struct Converter<const char[size]> : Converter<char const*> {};

	template<>
	struct Converter<int32_t>
	{
		typedef int32_t extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tointeger(state, index); }

		static void push(lua_State* state, extract_type value)
		{ lua_pushinteger(state, value); }
	};

	template<>
	struct Converter<int64_t>
	{
		typedef int extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tointeger(state, index); }

		static void push(lua_State* state, extract_type value)
		{ lua_pushinteger(state, value); }
	};

	template<>
	struct Converter<double>
	{
		typedef double extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tonumber(state, index); }

		static void push(lua_State* state, double value)
		{ lua_pushnumber(state, value); }
	};

	template<>
	struct Converter<bool>
	{
		typedef bool extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_toboolean(state, index) != 0; }

		static void push(lua_State* state, bool value)
		{ lua_pushboolean(state, value); }
	};

}}
<commit_msg>Add missing include.<commit_after>#pragma once

#include "fwd.hpp"
#include <configure/log.hpp>

#include <string>
#include <typeinfo>
#include <type_traits>
#include <stdexcept>
#include <cstdint>

namespace configure { namespace lua {

	template<typename T>
	struct Converter
	{
		typedef T& extract_type;

		static std::string const& type_name()
		{
			static std::string name = std::string("typeid-") + typeid(T).name();
			return name;
		}

		static extract_type extract(lua_State* state, int index)
		{

			T* value = extract_ptr(state, index);
			if (value == nullptr)
			{
				std::string err = "Expected value of type '"
					+ type_name()
					+ "', got '" + luaL_tolstring(state, index, nullptr) + "'";
				throw std::runtime_error(err);
			}
			return *value;
		}

		static T* extract_ptr(lua_State* state, int index)
		{
			void* mem = luaL_testudata(state, index, type_name().c_str());
			return ((T*) mem);
		}

		static bool push_metatable(lua_State* state)
		{
			std::string name = type_name();
			if (!luaL_newmetatable(state, name.c_str()))
				return false;
			if (!std::is_trivially_destructible<T>::value)
			{
				lua_pushstring(state, "__gc");
				lua_pushcfunction(state, &_call_destructor);
				lua_settable(state, -3);
			}
			return true;
		}
		static bool push_metatable(lua_State* state, std::string const& friendly_name)
		{
			bool is_new = push_metatable(state);
			if (is_new && !friendly_name.empty())
			{
				lua_pushvalue(state, -1);
				lua_setglobal(state, friendly_name.c_str());
			}
			return is_new;
		}

		static int _call_destructor(lua_State* L)
		{
			if (T* object = reinterpret_cast<T*>(lua_touserdata(L, 1)))
				object->~T();
			return 0;
		}

		template<typename... Args>
		static T& push(lua_State* state, Args&&... args)
		{
			void* mem = lua_newuserdata(state, sizeof(T));
			T* data = new (mem) T(std::forward<Args>(args)...);
			push_metatable(state);
			lua_setmetatable(state, -2);
			return *data;
		}
	};

	template<typename T> struct Converter<T*> : Converter<T> {};
	template<typename T> struct Converter<T&> : Converter<T> {};
	template<typename T> struct Converter<T const> : Converter<T> {};

	template<>
	struct Converter<std::string>
	{
		typedef std::string extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tostring(state, index); }

		static void push(lua_State* state, std::string const& value)
		{ lua_pushstring(state, value.c_str()); }
	};

	template<>
	struct Converter<char const*> : Converter<std::string>
	{
		static void push(lua_State* state, char const* value)
		{ lua_pushstring(state, value); }
	};

	template<unsigned size>
	struct Converter<const char[size]> : Converter<char const*> {};

	template<>
	struct Converter<int32_t>
	{
		typedef int32_t extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tointeger(state, index); }

		static void push(lua_State* state, extract_type value)
		{ lua_pushinteger(state, value); }
	};

	template<>
	struct Converter<int64_t>
	{
		typedef int extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tointeger(state, index); }

		static void push(lua_State* state, extract_type value)
		{ lua_pushinteger(state, value); }
	};

	template<>
	struct Converter<double>
	{
		typedef double extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_tonumber(state, index); }

		static void push(lua_State* state, double value)
		{ lua_pushnumber(state, value); }
	};

	template<>
	struct Converter<bool>
	{
		typedef bool extract_type;
		static extract_type extract(lua_State* state, int index)
		{ return lua_toboolean(state, index) != 0; }

		static void push(lua_State* state, bool value)
		{ lua_pushboolean(state, value); }
	};

}}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ExpirationTest.h"

#include <integration/common/IntegrationCommon.h>

CPPUNIT_TEST_SUITE_REGISTRATION( integration::expiration::ExpirationTest );

#include <sstream>

#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/exceptions/ActiveMQException.h>
#include <activemq/concurrent/Thread.h>
#include <activemq/connector/stomp/StompConnector.h>
#include <activemq/util/SimpleProperties.h>
#include <activemq/transport/TransportFactory.h>
#include <activemq/util/Guid.h>
#include <activemq/util/SimpleProperties.h>
#include <activemq/util/StringTokenizer.h>
#include <activemq/connector/ConnectorFactoryMap.h>
#include <activemq/network/SocketFactory.h>
#include <activemq/transport/TransportFactory.h>
#include <activemq/network/Socket.h>
#include <activemq/exceptions/NullPointerException.h>
#include <activemq/core/ActiveMQConnection.h>
#include <activemq/core/ActiveMQConsumer.h>
#include <activemq/core/ActiveMQProducer.h>
#include <activemq/util/StringTokenizer.h>
#include <activemq/util/Boolean.h>

#include <cms/Connection.h>
#include <cms/MessageConsumer.h>
#include <cms/MessageProducer.h>
#include <cms/MessageListener.h>
#include <cms/Startable.h>
#include <cms/Closeable.h>
#include <cms/MessageListener.h>
#include <cms/ExceptionListener.h>
#include <cms/Topic.h>
#include <cms/Queue.h>
#include <cms/TemporaryTopic.h>
#include <cms/TemporaryQueue.h>
#include <cms/Session.h>
#include <cms/BytesMessage.h>
#include <cms/TextMessage.h>
#include <cms/MapMessage.h>
#include <cms/Session.h>

using namespace activemq::connector::stomp;
using namespace activemq::transport;
using namespace activemq::util;
using namespace std;
using namespace cms;
using namespace activemq;
using namespace activemq::core;
using namespace activemq::util;
using namespace activemq::connector;
using namespace activemq::exceptions;
using namespace activemq::network;
using namespace activemq::transport;
using namespace activemq::concurrent;

using namespace std;
using namespace integration;
using namespace integration::expiration;
using namespace integration::common;

class Producer : public Runnable {
private:

    Connection* connection;
    Session* session;
    Topic* destination;
    MessageProducer* producer;
    int numMessages;
    long long timeToLive;
    bool disableTimeStamps;

public:

    Producer( int numMessages, long long timeToLive ){
        connection = NULL;
        session = NULL;
        destination = NULL;
        producer = NULL;
        this->numMessages = numMessages;
        this->timeToLive = timeToLive;
        this->disableTimeStamps = false;
    }

    virtual ~Producer(){
        cleanup();
    }

    virtual bool getDisableTimeStamps() const {
        return disableTimeStamps;
    }

    virtual void setDisableTimeStamps( bool value ) {
        this->disableTimeStamps = value;
    }

    virtual void run() {
        try {
            // Create a ConnectionFactory
            ActiveMQConnectionFactory* connectionFactory = new
                ActiveMQConnectionFactory("tcp://localhost:61613");

            // Create a Connection
            connection = connectionFactory->createConnection();
            connection->start();

            string sss=connection->getClientId();
            cout << sss << endl;

            session = connection->createSession( Session::AUTO_ACKNOWLEDGE);
            destination = session->createTopic( "expirationTopic" );

            producer = session->createProducer( destination );
            producer->setDeliveryMode( DeliveryMode::PERSISTANT );
            producer->setDisableMessageTimeStamp( disableTimeStamps );

            //unsigned long ttt=getcurt();
            producer->setTimeToLive( 1);

            // Create the Thread Id String
            string threadIdStr = Integer::toString( Thread::getId() );

            // Create a messages
            string text = (string)"Hello world! from thread " + threadIdStr;

            for( int ix=0; ix<numMessages; ++ix ){
                TextMessage* message = session->createTextMessage( text );
                producer->send( message );
                delete message;
           }

       }catch ( CMSException& e ) {
           e.printStackTrace();
       }
   }

private:

    void cleanup(){

        // Destroy resources.
        try{
            if( destination != NULL ) delete destination;
        }catch ( CMSException& e ) {}
        destination = NULL;

        try{
            if( producer != NULL ) delete producer;
        }catch ( CMSException& e ) {}
        producer = NULL;

        // Close open resources.
        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch ( CMSException& e ) {}

        try{
            if( session != NULL ) delete session;
        }catch ( CMSException& e ) {}
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch ( CMSException& e ) {}
        connection = NULL;
    }
};

class Consumer : public MessageListener, public Runnable {

private:

    Connection* connection;
    Session* session;
    Topic* destination;
    MessageConsumer* consumer;
    long waitMillis;
    int numReceived;

public:

    Consumer( long waitMillis ){
        connection = NULL;
        session = NULL;
        destination = NULL;
        consumer = NULL;
        this->waitMillis = waitMillis;
        numReceived = 0;
    }

    virtual ~Consumer(){
        cleanup();
    }

    virtual int getNumReceived() const{
        return numReceived;
    }

    virtual void run() {

        try {

            string user,passwd,sID;
            user="default";
            passwd="";
            sID="lsgID";

            // Create a ConnectionFactory
            ActiveMQConnectionFactory* connectionFactory =
               new ActiveMQConnectionFactory("tcp://localhost:61613",user,passwd,sID);

            // Create a Connection
            connection = connectionFactory->createConnection();
            delete connectionFactory;
            connection->start();

            // Create a Session
            session = connection->createSession( Session::AUTO_ACKNOWLEDGE);

            // Create the destination (Topic or Queue)
            destination = session->createTopic( "expirationTopic?consumer.retroactive=true");

            consumer = session->createConsumer( destination );

            consumer->setMessageListener( this );

            // Sleep while asynchronous messages come in.
            Thread::sleep( waitMillis );

        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

    virtual void onMessage( const Message* message ){

        try
        {
            const TextMessage* textMessage =
                dynamic_cast< const TextMessage* >( message );
            string text = textMessage->getText();
            numReceived++;
        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

private:

    void cleanup(){

        // Destroy resources.
        try{
            if( destination != NULL ) delete destination;
        }catch (CMSException& e) {}
        destination = NULL;

        try{
            if( consumer != NULL ) delete consumer;
        }catch (CMSException& e) {}
        consumer = NULL;

        // Close open resources.
        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch (CMSException& e) {}

        try{
            if( session != NULL ) delete session;
        }catch (CMSException& e) {}
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch (CMSException& e) {}
        connection = NULL;
    }
};

void ExpirationTest::testExpired()
{
    Producer producer( 1, 1 );
    Thread producerThread( &producer );
    producerThread.start();
    producerThread.join();

    Thread::sleep( 100 );

    Consumer consumer( 2000 );
    Thread consumerThread( &consumer );
    consumerThread.start();
    consumerThread.join();

    Thread::sleep( 100 );

    CPPUNIT_ASSERT( consumer.getNumReceived() == 0 );
}

void ExpirationTest::testNotExpired()
{
    Producer producer( 2, 2000 );
    producer.setDisableTimeStamps( true );
    Thread producerThread( &producer );
    producerThread.start();
    producerThread.join();

    Consumer consumer( 3000 );
    Thread consumerThread( &consumer );
    consumerThread.start();
    consumerThread.join();

    Thread::sleep( 50 );

    CPPUNIT_ASSERT( consumer.getNumReceived() == 2 );
}

<commit_msg>tweak to expiration test to allow multiple successive runs without collision with previous runs<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ExpirationTest.h"

#include <integration/common/IntegrationCommon.h>

CPPUNIT_TEST_SUITE_REGISTRATION( integration::expiration::ExpirationTest );

#include <sstream>

#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/exceptions/ActiveMQException.h>
#include <activemq/concurrent/Thread.h>
#include <activemq/connector/stomp/StompConnector.h>
#include <activemq/util/SimpleProperties.h>
#include <activemq/transport/TransportFactory.h>
#include <activemq/util/Guid.h>
#include <activemq/util/SimpleProperties.h>
#include <activemq/util/StringTokenizer.h>
#include <activemq/connector/ConnectorFactoryMap.h>
#include <activemq/network/SocketFactory.h>
#include <activemq/transport/TransportFactory.h>
#include <activemq/network/Socket.h>
#include <activemq/exceptions/NullPointerException.h>
#include <activemq/core/ActiveMQConnection.h>
#include <activemq/core/ActiveMQConsumer.h>
#include <activemq/core/ActiveMQProducer.h>
#include <activemq/util/StringTokenizer.h>
#include <activemq/util/Boolean.h>

#include <cms/Connection.h>
#include <cms/MessageConsumer.h>
#include <cms/MessageProducer.h>
#include <cms/MessageListener.h>
#include <cms/Startable.h>
#include <cms/Closeable.h>
#include <cms/MessageListener.h>
#include <cms/ExceptionListener.h>
#include <cms/Topic.h>
#include <cms/Queue.h>
#include <cms/TemporaryTopic.h>
#include <cms/TemporaryQueue.h>
#include <cms/Session.h>
#include <cms/BytesMessage.h>
#include <cms/TextMessage.h>
#include <cms/MapMessage.h>
#include <cms/Session.h>

using namespace activemq::connector::stomp;
using namespace activemq::transport;
using namespace activemq::util;
using namespace std;
using namespace cms;
using namespace activemq;
using namespace activemq::core;
using namespace activemq::util;
using namespace activemq::connector;
using namespace activemq::exceptions;
using namespace activemq::network;
using namespace activemq::transport;
using namespace activemq::concurrent;

using namespace std;
using namespace integration;
using namespace integration::expiration;
using namespace integration::common;

std::string messageTag = Guid().createGUID();

class Producer : public Runnable {
private:

    Connection* connection;
    Session* session;
    Topic* destination;
    MessageProducer* producer;
    int numMessages;
    long long timeToLive;
    bool disableTimeStamps;

public:

    Producer( int numMessages, long long timeToLive ){
        connection = NULL;
        session = NULL;
        destination = NULL;
        producer = NULL;
        this->numMessages = numMessages;
        this->timeToLive = timeToLive;
        this->disableTimeStamps = false;
    }

    virtual ~Producer(){
        cleanup();
    }

    virtual bool getDisableTimeStamps() const {
        return disableTimeStamps;
    }

    virtual void setDisableTimeStamps( bool value ) {
        this->disableTimeStamps = value;
    }

    virtual void run() {
        try {
            // Create a ConnectionFactory
            ActiveMQConnectionFactory* connectionFactory = new
                ActiveMQConnectionFactory("tcp://localhost:61613");

            // Create a Connection
            connection = connectionFactory->createConnection();
            connection->start();

            string sss=connection->getClientId();
            cout << sss << endl;

            session = connection->createSession( Session::AUTO_ACKNOWLEDGE);
            destination = session->createTopic( "expirationTopic" );

            producer = session->createProducer( destination );
            producer->setDeliveryMode( DeliveryMode::PERSISTANT );
            producer->setDisableMessageTimeStamp( disableTimeStamps );

            //unsigned long ttt=getcurt();
            producer->setTimeToLive( 1);

            // Create the Thread Id String
            string threadIdStr = Integer::toString( Thread::getId() );

            // Create a messages
            string text = (string)"Hello world! from thread " + threadIdStr;

            for( int ix=0; ix<numMessages; ++ix ){
                TextMessage* message = session->createTextMessage( text );
                message->setStringProperty( "messageTag", messageTag );
                producer->send( message );
                delete message;
           }

       }catch ( CMSException& e ) {
           e.printStackTrace();
       }
   }

private:

    void cleanup(){

        // Destroy resources.
        try{
            if( destination != NULL ) delete destination;
        }catch ( CMSException& e ) {}
        destination = NULL;

        try{
            if( producer != NULL ) delete producer;
        }catch ( CMSException& e ) {}
        producer = NULL;

        // Close open resources.
        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch ( CMSException& e ) {}

        try{
            if( session != NULL ) delete session;
        }catch ( CMSException& e ) {}
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch ( CMSException& e ) {}
        connection = NULL;
    }
};

class Consumer : public MessageListener, public Runnable {

private:

    Connection* connection;
    Session* session;
    Topic* destination;
    MessageConsumer* consumer;
    long waitMillis;
    int numReceived;

public:

    Consumer( long waitMillis ){
        connection = NULL;
        session = NULL;
        destination = NULL;
        consumer = NULL;
        this->waitMillis = waitMillis;
        numReceived = 0;
    }

    virtual ~Consumer(){
        cleanup();
    }

    virtual int getNumReceived() const{
        return numReceived;
    }

    virtual void run() {

        try {

            string user,passwd,sID;
            user="default";
            passwd="";
            sID="lsgID";

            // Create a ConnectionFactory
            ActiveMQConnectionFactory* connectionFactory =
               new ActiveMQConnectionFactory("tcp://localhost:61613",user,passwd,sID);

            // Create a Connection
            connection = connectionFactory->createConnection();
            delete connectionFactory;
            connection->start();

            // Create a Session
            session = connection->createSession( Session::AUTO_ACKNOWLEDGE);

            // Create the destination (Topic or Queue)
            destination = session->createTopic( "expirationTopic?consumer.retroactive=true");

            consumer = session->createConsumer( destination );

            consumer->setMessageListener( this );

            // Sleep while asynchronous messages come in.
            Thread::sleep( waitMillis );

        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

    virtual void onMessage( const Message* message ){

        try
        {
            if( !message->propertyExists( "messageTag" ) ||
                message->getStringProperty("messageTag") != messageTag ){
                return;
            }

            const TextMessage* textMessage =
                dynamic_cast< const TextMessage* >( message );
            string text = textMessage->getText();
            numReceived++;
        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

private:

    void cleanup(){

        // Destroy resources.
        try{
            if( destination != NULL ) delete destination;
        }catch (CMSException& e) {}
        destination = NULL;

        try{
            if( consumer != NULL ) delete consumer;
        }catch (CMSException& e) {}
        consumer = NULL;

        // Close open resources.
        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch (CMSException& e) {}

        try{
            if( session != NULL ) delete session;
        }catch (CMSException& e) {}
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch (CMSException& e) {}
        connection = NULL;
    }
};

void ExpirationTest::testExpired()
{
    Producer producer( 1, 1 );
    Thread producerThread( &producer );
    producerThread.start();
    producerThread.join();

    Thread::sleep( 100 );

    Consumer consumer( 2000 );
    Thread consumerThread( &consumer );
    consumerThread.start();
    consumerThread.join();

    Thread::sleep( 100 );

    CPPUNIT_ASSERT( consumer.getNumReceived() == 0 );
}

void ExpirationTest::testNotExpired()
{
    Producer producer( 2, 2000 );
    producer.setDisableTimeStamps( true );
    Thread producerThread( &producer );
    producerThread.start();
    producerThread.join();

    Consumer consumer( 3000 );
    Thread consumerThread( &consumer );
    consumerThread.start();
    consumerThread.join();

    Thread::sleep( 50 );

    CPPUNIT_ASSERT( consumer.getNumReceived() == 2 );
}

<|endoftext|>


<commit_before>#include <pwd.h>
#include <grp.h>
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = directoryName;
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true; // there's an -a flag
			else if (flags.at(i).at(k) == 'l')
				isL = true; // there's an -l flag
			else if (flags.at(i).at(k) == 'R')
				isR = true; // there's an -R flag
		}

	}

	dirent *direntp;
	if (isL) { //run -l flag

		struct stat current;

		struct passwd *x;
		struct group *y;
		while ((direntp = readdir(dirp))) {

			//cout << "direntp: " << direntp->d_name << endl;
			char curdir[1000];
			strcpy(curdir, directoryName);
			strcat(curdir, "/");
			strcat(curdir, direntp->d_name);

			//cout << curdir << endl;
			if (-1 == (stat(/*toCur*/curdir, &current))) {

				perror("stat failed");
				return -1;
			}
			if (direntp->d_name[0] == '.' && !isA) // if there's no -a flag, don't print files
															   // starting with .
				continue;
			else {

				if (current.st_mode & S_IFDIR)
					cout << "d";

				if (current.st_mode & S_IFLNK)
					cout << "l";

				if (!(current.st_mode & S_IFDIR) && !(current.st_mode & S_IFLNK))
					cout << "-";

				if (current.st_mode & S_IRUSR)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWUSR)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXUSR)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IRGRP)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWGRP)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXGRP)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IROTH)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWOTH)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXOTH)
					cout << "x";
				else
					cout << "-";

				cout << " ";

				cout << current.st_nlink << " ";

				if ((x = getpwuid(current.st_uid)) != NULL)
					cout << x->pw_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}

				if ((y = getgrgid(current.st_gid)) != NULL)
					cout << y->gr_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}
				cout << current.st_size << " ";

				char buff[20];
				struct tm * timeinfo;
				timeinfo = localtime(&(current.st_mtime));
				strftime(buff, 20, "%b %d %H:%M", timeinfo);
				printf("%s",buff);

				cout << " " << direntp->d_name;
				if (isR)
					lsWithFlags(curdir, flags);
			}
			cout << endl;

		}
		closedir(dirp);

	}

	else if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
		closedir(dirp);
	}
	return 0;
}

int main(int argc, char* argv[]) {

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		string toInsert = "./";
		for (int i = 1; i < argc; ++i) {

			if (argv[i][0] == '-') {

				flags.push_back(argv[i]);
			} else {

				directories.push_back(argv[i]);
			}
		}

		for (unsigned i = 0; i < directories.size(); ++i) {

			directories.at(i).insert(0, toInsert);
		}
		if (flags.size() == 0) {

			for (unsigned i = 0; i < directories.size(); ++i) {

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());

				ls(directoryName);

				delete [] directoryName;
			}
		}
		else if (directories.size() == 0) {

			lsWithFlags(".", flags);
		}
		else {
			//cout << "directories: ";
			//for (unsigned i = 0; i < directories.size(); ++i)
				//cout << directories.at(i) << " ";
			//cout << endl;

			if (directories.size() == 1) {

				char* directoryName = new char[directories.at(0).size() + 1];
				strcpy(directoryName, directories.at(0).c_str());

				lsWithFlags(directoryName, flags);

				delete [] directoryName;
			}

			else {
				for (unsigned int i = 0; i < directories.size(); ++i) {
					//cout << 145 << endl;

					char* directoryName = new char[directories.at(i).size() + 1];
					strcpy(directoryName, directories.at(i).c_str());

					lsWithFlags(directoryName, flags);
					delete [] directoryName;
				}
			}
		}
	}

}

<commit_msg>added -l protection functionality<commit_after>#include <pwd.h>
#include <grp.h>
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = directoryName;
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true; // there's an -a flag
			else if (flags.at(i).at(k) == 'l')
				isL = true; // there's an -l flag
			else if (flags.at(i).at(k) == 'R')
				isR = true; // there's an -R flag
		}

	}

	dirent *direntp;
	if (isL) { //run -l flag

		struct stat current;

		struct passwd *x;
		struct group *y;
		while ((direntp = readdir(dirp))) {

			//cout << "direntp: " << direntp->d_name << endl;
			char curdir[1000];
			strcpy(curdir, directoryName);
			strcat(curdir, "/");
			strcat(curdir, direntp->d_name);

			//cout << curdir << endl;
			if (-1 == (stat(/*toCur*/curdir, &current))) {

				perror("stat failed");
				return -1;
			}
			if (direntp->d_name[0] == '.' && !isA) // if there's no -a flag, don't print files
															   // starting with .
				continue;
			else {

				if (current.st_mode & S_IFDIR)
					cout << "d";

				if (current.st_mode & S_IFLNK)
					cout << "l";

				if (!(current.st_mode & S_IFDIR) && !(current.st_mode & S_IFLNK))
					cout << "-";

				if (current.st_mode & S_IRUSR)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWUSR)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXUSR)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IRGRP)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWGRP)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXGRP)
					cout << "x";
				else
					cout << "-";

				if (current.st_mode & S_IROTH)
					cout << "r";
				else
					cout << "-";

				if (current.st_mode & S_IWOTH)
					cout << "w";
				else
					cout << "-";

				if (current.st_mode & S_IXOTH)
					cout << "x";
				else
					cout << "-";

				cout << " ";

				cout << current.st_nlink << " ";

				if ((x = getpwuid(current.st_uid)) != NULL)
					cout << x->pw_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}

				if ((y = getgrgid(current.st_gid)) != NULL)
					cout << y->gr_name << " ";
				else {
					cerr << "error: " << errno << endl;
					exit(0);
				}
				cout << current.st_size << " ";

				char buff[20];
				struct tm * timeinfo;
				timeinfo = localtime(&(current.st_mtime));
				strftime(buff, 20, "%b %d %H:%M", timeinfo);
				printf("%s",buff);

				cout << " " << direntp->d_name;
				if (isR)
					lsWithFlags(curdir, flags);
			}
			cout << endl;

		}
		closedir(dirp);

	}

	else if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
		closedir(dirp);
	}
	return 0;
}

int main(int argc, char* argv[]) {

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		string toInsert = "./";
		for (int i = 1; i < argc; ++i) {

			if (argv[i][0] == '-') {

				flags.push_back(argv[i]);
			} else {

				directories.push_back(argv[i]);
			}
		}

		for (unsigned i = 0; i < directories.size(); ++i) {

			directories.at(i).insert(0, toInsert);
		}
		if (flags.size() == 0) {

			for (unsigned i = 0; i < directories.size(); ++i) {

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());

				ls(directoryName);

				delete [] directoryName;
			}
		}
		else if (directories.size() == 0) {

			lsWithFlags(".", flags);
		}
		else {
			//cout << "directories: ";
			//for (unsigned i = 0; i < directories.size(); ++i)
				//cout << directories.at(i) << " ";
			//cout << endl;

			if (directories.size() == 1) {

				char* directoryName = new char[directories.at(0).size() + 1];
				strcpy(directoryName, directories.at(0).c_str());

				lsWithFlags(directoryName, flags);

				delete [] directoryName;
			}

			else {
				for (unsigned int i = 0; i < directories.size(); ++i) {
					//cout << 145 << endl;

					char* directoryName = new char[directories.at(i).size() + 1];
					strcpy(directoryName, directories.at(i).c_str());
					cout << directoryName << ":" << endl;
					lsWithFlags(directoryName, flags);
					delete [] directoryName;
					cout << endl;
				}
			}
		}
	}

}

<|endoftext|>


<commit_before><commit_msg>Take into account merge of branch 'asl/hydro_porting_741' in GUI module.<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
 * thrill/data/fetching_block_queue.hpp
 *
 * Part of Project Thrill.
 *
 * Copyright (C) 2015 Tobias Sturm <mail@tobiassturm.de>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef THRILL_DATA_PREFETCHING_BLOCK_QUEUE_HEADER
#define THRILL_DATA_PREFETCHING_BLOCK_QUEUE_HEADER

#include <thrill/common/concurrent_bounded_queue.hpp>

namespace thrill {
namespace data {

//! \addtogroup data Data Subsystem
//! \{

class PrefetchingBlockQueue final
{
protected:
    mutable std::mutex mutex_;
    std::queue<Block> unpinned_queue_;
    std::queue<Block> pinned_queue_;
    std::condition_variable cv_;
    std::atomic<size_t> currently_fetching_ = { 0 };
    const size_t desired_;
public:

    PrefetchingBlockQueue(size_t desired_prefetched) : desired_(desired_prefetched) {}

    //we cannod move since callbacks would break (?)
    PrefetchingBlockQueue(PrefetchingBlockQueue&& other) = delete;

    //! If pinned_queue_ holds less than the desired_ number of blocks
    //! MaybePrefetch starts the pin process for the required amount of
    //! blocks (or unpinned_queue_ is empty). currently_fetching_
    //! is used to prevent too many pin calls by two consecutove calls to
    //! MaybePrefetch. MaybePrefetch notifies the condition variable cv_
    void MaybePrefetch() {
        while(currently_fetching_ + pinned_queue_.size() < desired_ && !unpinned_queue_.empty()) {
            //block is valid (not end-of-x block)
            if (unpinned_queue_.front().byte_block_) {
                currently_fetching_++;
                // we have a block which is not swapped in
                //copy block since http://stackoverflow.com/a/14763579/359326
                unpinned_queue_.front().byte_block_->Prefetch([&, block = unpinned_queue_.pop()](){
                    currently_fetching_--;
                    pinned_queue_.push(block);
                    cv_.notify_one();
                });
            } else { // for end-of-x blocks or already in memory
                pinned_queue_.push_back(unpinned_queue_.front());
                unpinned_queue_.pop();
                cv_.notify_one();
            }
        }
    }

    //! Pushes a copy of source onto back of the queue.
    void push(const Block& source) {
        std::unique_lock<std::mutex> lock(other.mutex_);
        unpinned_queue_.push(source);
        MaybePrefetch();
    }

    //! Pushes given element into the queue by utilizing element's move
    //! constructor
    void push(Block&& source) {
        std::unique_lock<std::mutex> lock(other.mutex_);
        unpinned_queue_.push(std::move(source));
        MaybePrefetch();
    }

    //! Pushes a new element into the queue. The element is constructed with
    //! given arguments.
    template <typename ... Arguments>
    void emplace(Arguments&& ... args) {
        std::unique_lock<std::mutex> lock(mutex_);
        unpinned_queue_.emplace(args ...);
        MaybePrefetch();
    }

    //! Returns: true if queue has no items; false otherwise.
    bool empty() const {
        std::unique_lock<std::mutex> lock(mutex_);
        return unpinned_queue_.empty() && pinned_queue_.empty();
    }

    //! Clears the queue.
    void clear() {
        std::unique_lock<std::mutex> lock(mutex_);
        unpinned_queue_.clear();
        pinned_queue_.clear();
    }

    //! If a fetched Block is available, pops it from the queue, move it to destination,
    //! destroying the original position. Otherwise does nothing.
    bool try_pop(Block& destination) {
        std::unique_lock<std::mutex> lock(mutex_);
        if (pinned_queue_.empty())
            return false;

        destination = std::move(pinned_queue_.front());
        pinned_queue_.pop();
        return true;
    }

    //! If value is available, pops it from the queue, move it to
    //! destination. If no item is in the queue, wait until there is one.
    void pop(Block& destination) {
        std::unique_lock<std::mutex> lock(mutex_);
        cv_.wait(lock, [=]() { return !queue_.empty(); });
        destination = std::move(queue_.front());
        queue_.pop();
    }

    //! return number of items available in the queue (tbb says "can return
    //! negative size", due to pending pop()s, but we ignore that here).
    //! \returns number of blocks (includes pinned, unpinned and currently fetching)
    size_t size() {
        std::unique_lock<std::mutex> lock(mutex_);
        return pinned_queue_.size() + unpinned_queue_.size() + currently_fetching_;
    }
};

} // namespace data
} // namespace thrill

#endif // !THRILL_DATA_PREFETCHING_BLOCK_QUEUE_HEADER

/******************************************************************************/
<commit_msg>idea with prefetching block queue was a bad idea - incorpate that into BlockQueue directly<commit_after><|endoftext|>