text:
#ifndef BOOST_PP_IS_ITERATING
    ///////////////////////////////////////////////////////////////////////////////
    /// \file make_expr.hpp
    /// Definition of the \c make_expr() and \c unpack_expr() utilities for
    /// building Proto expression nodes from child nodes or from a Fusion
    /// sequence of child nodes, respectively.
    //
    //  Copyright 2008 Eric Niebler. Distributed under the Boost
    //  Software License, Version 1.0. (See accompanying file
    //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    #ifndef BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005
    #define BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005

    #include <boost/config.hpp>
    #include <boost/detail/workaround.hpp>
    #include <boost/preprocessor/cat.hpp>
    #include <boost/preprocessor/arithmetic/inc.hpp>
    #include <boost/preprocessor/arithmetic/dec.hpp>
    #include <boost/preprocessor/arithmetic/sub.hpp>
    #include <boost/preprocessor/punctuation/comma_if.hpp>
    #include <boost/preprocessor/iteration/iterate.hpp>
    #include <boost/preprocessor/facilities/intercept.hpp>
    #include <boost/preprocessor/repetition/enum.hpp>
    #include <boost/preprocessor/repetition/enum_params.hpp>
    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
    #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
    #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
    #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
    #include <boost/preprocessor/repetition/repeat.hpp>
    #include <boost/ref.hpp>
    #include <boost/mpl/if.hpp>
    #include <boost/mpl/assert.hpp>
    #include <boost/mpl/eval_if.hpp>
    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits/is_same.hpp>
    #include <boost/type_traits/add_const.hpp>
    #include <boost/type_traits/add_reference.hpp>
    #include <boost/type_traits/remove_cv.hpp>
    #include <boost/proto/proto_fwd.hpp>
    #include <boost/proto/traits.hpp>
    #include <boost/proto/domain.hpp>
    #include <boost/proto/generate.hpp>
    #include <boost/fusion/include/begin.hpp>
    #include <boost/fusion/include/next.hpp>
    #include <boost/fusion/include/value_of.hpp>
    #include <boost/fusion/include/size.hpp>
    #include <boost/proto/detail/poly_function.hpp>
    #include <boost/proto/detail/deprecated.hpp>

    #ifdef _MSC_VER
    # pragma warning(push)
    # pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
    #endif

    namespace boost
    {
        /// INTERNAL ONLY
        ///
        namespace fusion
        {
            /// INTERNAL ONLY
            ///
            template<typename Function>
            class unfused_generic;
        }
    }

    namespace boost { namespace proto
    {
    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_AS_CHILD_TYPE(Z, N, DATA)                                                   \
        typename boost::proto::detail::protoify<                                                    \
            BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N)                                        \
          , BOOST_PP_TUPLE_ELEM(3, 2, DATA)                                                         \
        >::result_type                                                                              \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_AS_CHILD(Z, N, DATA)                                                        \
        boost::proto::detail::protoify<                                                             \
            BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N)                                        \
          , BOOST_PP_TUPLE_ELEM(3, 2, DATA)                                                         \
        >()(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, DATA), N))                                       \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_NEXT_ITERATOR_TYPE(Z, N, DATA)                                       \
        typedef typename fusion::result_of::next<                                                   \
            BOOST_PP_CAT(fusion_iterator, N)>::type                                                 \
                BOOST_PP_CAT(fusion_iterator, BOOST_PP_INC(N));                                     \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_ITERATORS_TYPE(N)                                                    \
        typedef                                                                                \
            typename fusion::result_of::begin<Sequence const>::type                                 \
        fusion_iterator0;                                                                           \
        BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_PROTO_FUSION_NEXT_ITERATOR_TYPE, fusion_iterator)    \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_AT_TYPE(Z, N, DATA)                                                  \
        typename add_const<                                                                         \
            typename fusion::result_of::value_of<                                                   \
                BOOST_PP_CAT(fusion_iterator, N)                                                    \
            >::type                                                                                \
        >::type                                                                                \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_NEXT_ITERATOR(Z, N, DATA)                                            \
        BOOST_PP_CAT(fusion_iterator, BOOST_PP_INC(N)) BOOST_PP_CAT(it, BOOST_PP_INC(N)) =          \
            fusion::next(BOOST_PP_CAT(it, N));                                                      \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_ITERATORS(N)                                                         \
        fusion_iterator0 it0 = fusion::begin(sequence);                                             \
        BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_PROTO_FUSION_NEXT_ITERATOR, fusion_iterator)         \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_AT(Z, N, DATA)                                                       \
        *BOOST_PP_CAT(it, N)                                                                        \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_AS_CHILD_AT_TYPE(Z, N, DATA)                                         \
        typename detail::protoify<                                                                  \
            BOOST_PROTO_FUSION_AT_TYPE(Z, N, DATA)                                                  \
          , Domain                                                                                \
        >::result_type                                                                              \
        /**/

    /// INTERNAL ONLY
    ///
    #define BOOST_PROTO_FUSION_AS_CHILD_AT(Z, N, DATA)                                              \
        detail::protoify<                                                                           \
            BOOST_PROTO_FUSION_AT_TYPE(Z, N, DATA)                                                  \
          , Domain                                                                                \
        >()(BOOST_PROTO_FUSION_AT(Z, N, DATA))                                                      \
        /**/

        namespace detail
        {
            template<typename T, typename Domain>
            struct protoify
              : Domain::template as_expr<T>
            {};

            template<typename T, typename Domain>
            struct protoify<T &, Domain>
              : Domain::template as_child<T>
            {};

            template<typename T, typename Domain>
            struct protoify<boost::reference_wrapper<T>, Domain>
              : Domain::template as_child<T>
            {};

            template<typename T, typename Domain>
            struct protoify<boost::reference_wrapper<T> const, Domain>
              : Domain::template as_child<T>
            {};

            template<typename Tag, typename Domain, typename Sequence, std::size_t Size>
            struct unpack_expr_
            {};

            template<typename Domain, typename Sequence>
            struct unpack_expr_<tag::terminal, Domain, Sequence, 1u>
            {
                typedef
                    typename add_const<
                        typename fusion::result_of::value_of<
                            typename fusion::result_of::begin<Sequence>::type
                        >::type
                    >::type
                terminal_type;

                typedef
                    typename proto::detail::protoify<
                        terminal_type
                      , Domain
                    >::result_type
                type;

                static type const call(Sequence const &sequence)
                {
                    return proto::detail::protoify<terminal_type, Domain>()(fusion::at_c<0>(sequence));
                }
            };

            template<typename Sequence>
            struct unpack_expr_<tag::terminal, deduce_domain, Sequence, 1u>
              : unpack_expr_<tag::terminal, default_domain, Sequence, 1u>
            {};

            template<
                typename Tag
              , typename Domain
                BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
                    BOOST_PROTO_MAX_ARITY
                  , typename A
                  , = void BOOST_PP_INTERCEPT
                )
              , typename _ = void
            >
            struct make_expr_
            {};

            template<typename Domain, typename A>
            struct make_expr_<tag::terminal, Domain, A
                BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, void BOOST_PP_INTERCEPT)>
            {
                typedef typename proto::detail::protoify<A, Domain>::result_type result_type;

                result_type operator()(typename add_reference<A>::type a) const
                {
                    return proto::detail::protoify<A, Domain>()(a);
                }
            };

            template<typename A>
            struct make_expr_<tag::terminal, deduce_domain, A
                BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, void BOOST_PP_INTERCEPT)>
              : make_expr_<tag::terminal, default_domain, A>
            {};

        #define BOOST_PP_ITERATION_PARAMS_1                                                         \
            (4, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/make_expr.hpp>, 1))                         \
            /**/

        #include BOOST_PP_ITERATE()
        }

        namespace result_of
        {
            /// \brief Metafunction that computes the return type of the
            /// \c make_expr() function, with a domain deduced from the
            /// domains of the children.
            ///
            /// Use the <tt>result_of::make_expr\<\></tt> metafunction to
            /// compute the return type of the \c make_expr() function.
            ///
            /// In this specialization, the domain is deduced from the
            /// domains of the child types. (If
            /// <tt>is_domain\<A0\>::value</tt> is \c true, then another
            /// specialization is selected.)
            template<
                typename Tag
              , BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
              , typename Void1  // = void
              , typename Void2  // = void
            >
            struct make_expr
            {
                /// Same as <tt>result_of::make_expr\<Tag, D, A0, ... AN\>::type</tt>
                /// where \c D is the deduced domain, which is calculated as follows:
                ///
                /// For each \c x in <tt>[0,N)</tt> (proceeding in order beginning with
                /// <tt>x=0</tt>), if <tt>domain_of\<Ax\>::type</tt> is not
                /// \c default_domain, then \c D is <tt>domain_of\<Ax\>::type</tt>.
                /// Otherwise, \c D is \c default_domain.
                typedef
                    typename detail::make_expr_<
                        Tag
                      , deduce_domain
                        BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
                    >::result_type
                type;
            };

            /// \brief Metafunction that computes the return type of the
            /// \c make_expr() function, within the specified domain.
            ///
            /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
            /// the return type of the \c make_expr() function.
            template<
                typename Tag
              , typename Domain
                BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
            >
            struct make_expr<
                Tag
              , Domain
                BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
              , typename Domain::proto_is_domain_
            >
            {
                /// If \c Tag is <tt>tag::terminal</tt>, then \c type is a
                /// typedef for <tt>boost::result_of\<Domain(expr\<tag::terminal,
                /// term\<A0\> \>)\>::type</tt>.
                ///
                /// Otherwise, \c type is a typedef for <tt>boost::result_of\<Domain(expr\<Tag,
                /// listN\< as_child\<A0\>::type, ... as_child\<AN\>::type\>)
                /// \>::type</tt>, where \c N is the number of non-void template
                /// arguments, and <tt>as_child\<A\>::type</tt> is evaluated as
                /// follows:
                ///
                /// \li If <tt>is_expr\<A\>::value</tt> is \c true, then the
                /// child type is \c A.
                /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
                /// and <tt>is_expr\<B\>::value</tt> is \c true, then the
                /// child type is <tt>B &</tt>.
                /// \li If <tt>is_expr\<A\>::value</tt> is \c false, then the
                /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<A\> \>
                /// )\>::type</tt>.
                /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
                /// and <tt>is_expr\<B\>::value</tt> is \c false, then the
                /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<B &\> \>
                /// )\>::type</tt>.
                typedef
                    typename detail::make_expr_<
                        Tag
                      , Domain
                        BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
                    >::result_type
                type;
            };

            /// \brief Metafunction that computes the return type of the
            /// \c unpack_expr() function, with a domain deduced from the
            /// domains of the children.
            ///
            /// Use the <tt>result_of::unpack_expr\<\></tt> metafunction to
            /// compute the return type of the \c unpack_expr() function.
            ///
            /// \c Sequence is a Fusion Forward Sequence.
            ///
            /// In this specialization, the domain is deduced from the
            /// domains of the child types. (If
            /// <tt>is_domain\<Sequence>::value</tt> is \c true, then another
            /// specialization is selected.)
            template<
                typename Tag
              , typename Sequence
              , typename Void1  // = void
              , typename Void2  // = void
            >
            struct unpack_expr
            {
                /// Let \c S be the type of a Fusion Random Access Sequence
                /// equivalent to \c Sequence. Then \c type is the
                /// same as <tt>result_of::make_expr\<Tag,
                /// fusion::result_of::value_at_c\<S, 0\>::type, ...
                /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
                /// where \c N is the size of \c S.
                typedef
                    typename detail::unpack_expr_<
                        Tag
                      , deduce_domain
                      , Sequence
                      , fusion::result_of::size<Sequence>::type::value
                    >::type
                type;
            };

            /// \brief Metafunction that computes the return type of the
            /// \c unpack_expr() function, within the specified domain.
            ///
            /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
            /// the return type of the \c make_expr() function.
            template<typename Tag, typename Domain, typename Sequence>
            struct unpack_expr<Tag, Domain, Sequence, typename Domain::proto_is_domain_>
            {
                /// Let \c S be the type of a Fusion Random Access Sequence
                /// equivalent to \c Sequence. Then \c type is the
                /// same as <tt>result_of::make_expr\<Tag, Domain,
                /// fusion::result_of::value_at_c\<S, 0\>::type, ...
                /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
                /// where \c N is the size of \c S.
                typedef
                    typename detail::unpack_expr_<
                        Tag
                      , Domain
                      , Sequence
                      , fusion::result_of::size<Sequence>::type::value
                    >::type
                type;
            };
        }

        namespace functional
        {
            /// \brief A callable function object equivalent to the
            /// \c proto::make_expr() function.
            ///
            /// In all cases, <tt>functional::make_expr\<Tag, Domain\>()(a0, ... aN)</tt>
            /// is equivalent to <tt>proto::make_expr\<Tag, Domain\>(a0, ... aN)</tt>.
            ///
            /// <tt>functional::make_expr\<Tag\>()(a0, ... aN)</tt>
            /// is equivalent to <tt>proto::make_expr\<Tag\>(a0, ... aN)</tt>.
            template<typename Tag, typename Domain  /* = deduce_domain*/>
            struct make_expr
            {
                BOOST_PROTO_CALLABLE()
                BOOST_PROTO_POLY_FUNCTION()

                template<typename Sig>
                struct result;

                template<typename This, typename A0>
                struct result<This(A0)>
                {
                    typedef
                        typename result_of::make_expr<
                            Tag
                          , Domain
                          , A0
                        >::type
                    type;
                };

                /// Construct an expression node with tag type \c Tag
                /// and in the domain \c Domain.
                ///
                /// \return <tt>proto::make_expr\<Tag, Domain\>(a0,...aN)</tt>
                template<typename A0>
                typename result_of::make_expr<
                    Tag
                  , Domain
                  , A0 const
                >::type const
                operator ()(A0 const &a0) const
                {
                    return proto::detail::make_expr_<
                        Tag
                      , Domain
                      , A0 const
                    >()(a0);
                }

                // Additional overloads generated by the preprocessor ...

            #define BOOST_PP_ITERATION_PARAMS_1                                                     \
                (4, (2, BOOST_PROTO_MAX_ARITY, <boost/proto/make_expr.hpp>, 2))                     \
                /**/

            #include BOOST_PP_ITERATE()

                /// INTERNAL ONLY
                ///
                template<
                    BOOST_PP_ENUM_BINARY_PARAMS(
                        BOOST_PROTO_MAX_ARITY
                      , typename A
                      , = void BOOST_PP_INTERCEPT
                    )
                >
                struct impl
                  : detail::make_expr_<
                      Tag
                    , Domain
                      BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
                    >
                {};
            };

            /// \brief A callable function object equivalent to the
            /// \c proto::unpack_expr() function.
            ///
            /// In all cases, <tt>functional::unpack_expr\<Tag, Domain\>()(seq)</tt>
            /// is equivalent to <tt>proto::unpack_expr\<Tag, Domain\>(seq)</tt>.
            ///
            /// <tt>functional::unpack_expr\<Tag\>()(seq)</tt>
            /// is equivalent to <tt>proto::unpack_expr\<Tag\>(seq)</tt>.
            template<typename Tag, typename Domain /* = deduce_domain*/>
            struct unpack_expr
            {
                BOOST_PROTO_CALLABLE()

                template<typename Sig>
                struct result
                {};

                template<typename This, typename Sequence>
                struct result<This(Sequence)>
                {
                    typedef
                        typename result_of::unpack_expr<
                            Tag
                          , Domain
                          , typename remove_reference<Sequence>::type
                        >::type
                    type;
                };

                /// Construct an expression node with tag type \c Tag
                /// and in the domain \c Domain.
                ///
                /// \param sequence A Fusion Forward Sequence
                /// \return <tt>proto::unpack_expr\<Tag, Domain\>(sequence)</tt>
                template<typename Sequence>
                typename result_of::unpack_expr<Tag, Domain, Sequence const>::type const
                operator ()(Sequence const &sequence) const
                {
                    return proto::detail::unpack_expr_<
                        Tag
                      , Domain
                      , Sequence const
                      , fusion::result_of::size<Sequence>::type::value
                    >::call(sequence);
                }
            };

            /// INTERNAL ONLY
            ///
            template<typename Tag, typename Domain>
            struct unfused_expr_fun
            {
                BOOST_PROTO_CALLABLE()

                template<typename Sig>
                struct result;

                template<typename This, typename Sequence>
                struct result<This(Sequence)>
                {
                    typedef
                        typename result_of::unpack_expr<
                            Tag
                          , Domain
                          , typename remove_reference<Sequence>::type
                        >::type
                    type;
                };

                template<typename Sequence>
                typename proto::result_of::unpack_expr<Tag, Domain, Sequence const>::type const
                operator ()(Sequence const &sequence) const
                {
                    return proto::detail::unpack_expr_<
                        Tag
                      , Domain
                      , Sequence const
                      , fusion::result_of::size<Sequence>::type::value
                    >::call(sequence);
                }
            };

            /// INTERNAL ONLY
            ///
            template<typename Tag, typename Domain>
            struct unfused_expr
              : fusion::unfused_generic<unfused_expr_fun<Tag, Domain> >
            {
                BOOST_PROTO_CALLABLE()
            };

        } // namespace functional

        /// \brief Construct an expression of the requested tag type
        /// with a domain and with the specified arguments as children.
        ///
        /// This function template may be invoked either with or without
        /// specifying a \c Domain argument. If no domain is specified,
        /// the domain is deduced by examining in order the domains of
        /// the given arguments and taking the first that is not
        /// \c default_domain, if any such domain exists, or
        /// \c default_domain otherwise.
        ///
        /// Let \c wrap_(x) be defined such that:
        /// \li If \c x is a <tt>boost::reference_wrapper\<\></tt>,
        /// \c wrap_(x) is equivalent to <tt>as_child\<Domain\>(x.get())</tt>.
        /// \li Otherwise, \c wrap_(x) is equivalent to
        /// <tt>as_expr\<Domain\>(x)</tt>.
        ///
        /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
        /// <tt>expr\<Tag, listN\<C0,...CN\> \>::make(c0,...cN)</tt>
        /// where \c Bx is the type of \c bx.
        ///
        /// \return <tt>Domain()(make_\<Tag\>(wrap_(a0),...wrap_(aN)))</tt>.
        template<typename Tag, typename A0>
        typename lazy_disable_if<
            is_domain<A0>
          , result_of::make_expr<
                Tag
              , A0 const
            >
        >::type const
        make_expr(A0 const &a0)
        {
            return proto::detail::make_expr_<
                Tag
              , deduce_domain
              , A0 const
            >()(a0);
        }

        /// \overload
        ///
        template<typename Tag, typename Domain, typename C0>
        typename result_of::make_expr<
            Tag
          , Domain
          , C0 const
        >::type const
        make_expr(C0 const &c0)
        {
            return proto::detail::make_expr_<
                Tag
              , Domain
              , C0 const
            >()(c0);
        }

        // Additional overloads generated by the preprocessor...

    #define BOOST_PP_ITERATION_PARAMS_1                                                             \
        (4, (2, BOOST_PROTO_MAX_ARITY, <boost/proto/make_expr.hpp>, 3))                             \
        /**/

    #include BOOST_PP_ITERATE()

        /// \brief Construct an expression of the requested tag type
        /// with a domain and with childres from the specified Fusion
        /// Forward Sequence.
        ///
        /// This function template may be invoked either with or without
        /// specifying a \c Domain argument. If no domain is specified,
        /// the domain is deduced by examining in order the domains of the
        /// elements of \c sequence and taking the first that is not
        /// \c default_domain, if any such domain exists, or
        /// \c default_domain otherwise.
        ///
        /// Let \c s be a Fusion Random Access Sequence equivalent to \c sequence.
        /// Let <tt>wrap_\<N\>(s)</tt>, where \c s has type \c S, be defined
        /// such that:
        /// \li If <tt>fusion::result_of::value_at_c\<S,N\>::type</tt> is a reference,
        /// <tt>wrap_\<N\>(s)</tt> is equivalent to
        /// <tt>as_child\<Domain\>(fusion::at_c\<N\>(s))</tt>.
        /// \li Otherwise, <tt>wrap_\<N\>(s)</tt> is equivalent to
        /// <tt>as_expr\<Domain\>(fusion::at_c\<N\>(s))</tt>.
        ///
        /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
        /// <tt>expr\<Tag, listN\<B0,...BN\> \>::make(b0,...bN)</tt>
        /// where \c Bx is the type of \c bx.
        ///
        /// \param sequence a Fusion Forward Sequence.
        /// \return <tt>Domain()(make_\<Tag\>(wrap_\<0\>(s),...wrap_\<N-1\>(s)))</tt>,
        /// where N is the size of \c Sequence.
        template<typename Tag, typename Sequence>
        typename lazy_disable_if<
            is_domain<Sequence>
          , result_of::unpack_expr<Tag, Sequence const>
        >::type const
        unpack_expr(Sequence const &sequence)
        {
            return proto::detail::unpack_expr_<
                Tag
              , deduce_domain
              , Sequence const
              , fusion::result_of::size<Sequence>::type::value
            >::call(sequence);
        }

        /// \overload
        ///
        template<typename Tag, typename Domain, typename Sequence2>
        typename result_of::unpack_expr<Tag, Domain, Sequence2 const>::type const
        unpack_expr(Sequence2 const &sequence2)
        {
            return proto::detail::unpack_expr_<
                Tag
              , Domain
              , Sequence2 const
              , fusion::result_of::size<Sequence2>::type::value
            >::call(sequence2);
        }

        /// INTERNAL ONLY
        ///
        template<typename Tag, typename Domain>
        struct is_callable<functional::make_expr<Tag, Domain> >
          : mpl::true_
        {};

        /// INTERNAL ONLY
        ///
        template<typename Tag, typename Domain>
        struct is_callable<functional::unpack_expr<Tag, Domain> >
          : mpl::true_
        {};

        /// INTERNAL ONLY
        ///
        template<typename Tag, typename Domain>
        struct is_callable<functional::unfused_expr<Tag, Domain> >
          : mpl::true_
        {};

    }}

    #ifdef _MSC_VER
    # pragma warning(pop)
    #endif

    #undef BOOST_PROTO_FUSION_AT
    #undef BOOST_PROTO_FUSION_AT_TYPE
    #undef BOOST_PROTO_FUSION_AS_CHILD_AT
    #undef BOOST_PROTO_FUSION_AS_CHILD_AT_TYPE
    #undef BOOST_PROTO_FUSION_NEXT_ITERATOR
    #undef BOOST_PROTO_FUSION_NEXT_ITERATOR_TYPE
    #undef BOOST_PROTO_FUSION_ITERATORS
    #undef BOOST_PROTO_FUSION_ITERATORS_TYPE

    #endif // BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005

#elif BOOST_PP_ITERATION_FLAGS() == 1

    #define N BOOST_PP_ITERATION()
    #define M BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N)

        template<typename Tag, typename Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
        struct make_expr_<Tag, Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
            BOOST_PP_ENUM_TRAILING_PARAMS(M, void BOOST_PP_INTERCEPT), void>
        {
            typedef
                BOOST_PP_CAT(list, N)<
                    BOOST_PP_ENUM(N, BOOST_PROTO_AS_CHILD_TYPE, (A, ~, Domain))
                >
            proto_args;

            typedef typename base_expr<Domain, Tag, proto_args>::type expr_type;
            typedef typename Domain::proto_generator proto_generator;
            typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;

            result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, typename add_reference<A, >::type a)) const
            {
                expr_type const that = {
                    BOOST_PP_ENUM(N, BOOST_PROTO_AS_CHILD, (A, a, Domain))
                };
                return proto_generator()(that);
            }
        };

        template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
        struct make_expr_<Tag, deduce_domain BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
            BOOST_PP_ENUM_TRAILING_PARAMS(M, void BOOST_PP_INTERCEPT), void>
          : make_expr_<
                Tag
              , typename BOOST_PP_CAT(deduce_domain, N)<BOOST_PP_ENUM_PARAMS(N, A)>::type
                BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
            >
        {};

        template<typename Tag, typename Domain, typename Sequence>
        struct unpack_expr_<Tag, Domain, Sequence, N>
        {
            BOOST_PROTO_FUSION_ITERATORS_TYPE(N)

            typedef
                BOOST_PP_CAT(list, N)<
                    BOOST_PP_ENUM(N, BOOST_PROTO_FUSION_AS_CHILD_AT_TYPE, ~)
                >
            proto_args;

            typedef typename base_expr<Domain, Tag, proto_args>::type expr_type;
            typedef typename Domain::proto_generator proto_generator;
            typedef typename proto_generator::template result<proto_generator(expr_type)>::type type;

            static type const call(Sequence const &sequence)
            {
                BOOST_PROTO_FUSION_ITERATORS(N)
                expr_type const that = {
                    BOOST_PP_ENUM(N, BOOST_PROTO_FUSION_AS_CHILD_AT, ~)
                };
                return proto_generator()(that);
            }
        };

        template<typename Tag, typename Sequence>
        struct unpack_expr_<Tag, deduce_domain, Sequence, N>
        {
            BOOST_PROTO_FUSION_ITERATORS_TYPE(N)

            typedef
                unpack_expr_<
                    Tag
                  , typename BOOST_PP_CAT(deduce_domain, N)<
                        BOOST_PP_ENUM(N, BOOST_PROTO_FUSION_AT_TYPE, ~)
                    >::type
                  , Sequence
                  , N
                >
            other;

            typedef typename other::type type;

            static type const call(Sequence const &sequence)
            {
                return other::call(sequence);
            }
        };

    #undef N
    #undef M

#elif BOOST_PP_ITERATION_FLAGS() == 2

    #define N BOOST_PP_ITERATION()

        template<typename This BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
        struct result<This(BOOST_PP_ENUM_PARAMS(N, A))>
        {
            typedef
                typename result_of::make_expr<
                    Tag
                  , Domain
                    BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
                >::type
            type;
        };

        /// \overload
        ///
        template<BOOST_PP_ENUM_PARAMS(N, typename A)>
        typename result_of::make_expr<
            Tag
          , Domain
            BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
        >::type const
        operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a)) const
        {
            return proto::detail::make_expr_<
                Tag
              , Domain
                BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
            >()(BOOST_PP_ENUM_PARAMS(N, a));
        }

    #undef N

#elif BOOST_PP_ITERATION_FLAGS() == 3

    #define N BOOST_PP_ITERATION()

        /// \overload
        ///
        template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
        typename lazy_disable_if<
            is_domain<A0>
          , result_of::make_expr<
                Tag
                BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
            >
        >::type const
        make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a))
        {
            return proto::detail::make_expr_<
                Tag
              , deduce_domain
                BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
            >()(BOOST_PP_ENUM_PARAMS(N, a));
        }

        /// \overload
        ///
        template<typename Tag, typename Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, typename C)>
        typename result_of::make_expr<
            Tag
          , Domain
            BOOST_PP_ENUM_TRAILING_PARAMS(N, const C)
        >::type const
        make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const C, &c))
        {
            return proto::detail::make_expr_<
                Tag
              , Domain
                BOOST_PP_ENUM_TRAILING_PARAMS(N, const C)
            >()(BOOST_PP_ENUM_PARAMS(N, c));
        }

    #undef N

#endif // BOOST_PP_IS_ITERATING

max_stars_repo_name: RaptDept/slimtune

max_issues_repo_name: RaptDept/slimtune

max_forks_repo_name: RaptDept/slimtune


text:
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

#include "WebProxyAdapter.h"

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>

namespace base64 = boost::beast::detail::base64;
using boost::log::trivial::trace;
using boost::log::trivial::debug;
using boost::log::trivial::info;
using boost::log::trivial::warning;
using boost::log::trivial::error;
using boost::log::trivial::fatal;

namespace aws {
    namespace iot {
        namespace securedtunneling {

            constexpr int BUFFER_SIZE_IN_BYTES = 10*1000; // 10 KB
            constexpr int HTTP_VERSION = 11; // HTTP/1.1
            WebProxyAdapter::WebProxyAdapter(logger* log,
                                                 const LocalproxyConfig &localproxy_config):
                    log(log), localproxy_config(localproxy_config) { }

            void WebProxyAdapter::async_connect(BoostCallbackFunc on_tcp_tunnel_callback,
                                                  const shared_ptr<WebSocketStream> &wss,
                                                  const tcp::endpoint &web_proxy_endpoint) {
                on_tcp_tunnel = std::make_unique<BoostCallbackFunc>(std::move(on_tcp_tunnel_callback));
                websocket_stream = wss.get();
                BOOST_LOG_SEV(*log, trace) << "Establishing TCP connection with the Web Proxy";
                websocket_stream->get_tcp_socket().async_connect(web_proxy_endpoint, [this](error_code const &ec) {
                    if (ec) {
                        BOOST_LOG_SEV(*log, error) << (boost::format("Could not connect to Web Proxy: %1%") % ec.message()).str();
                        (*on_tcp_tunnel)(WebProxyAdapterErrc::TcpConnectError);
                    } else {
                        BOOST_LOG_SEV(*log, debug) << "Connected successfully with Web Proxy";
                        websocket_stream->lowest_layer().set_option(tcp::no_delay(true));
                        if (localproxy_config.is_web_proxy_using_tls) {
                            async_ssl_handshake();
                        } else {
                            on_tcp_connect();
                        }
                    }
                });
            }

            void WebProxyAdapter::async_ssl_handshake() {
                if (!localproxy_config.no_ssl_host_verify) {
                    websocket_stream->get_web_proxy_ssl_stream()->set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert);
                    websocket_stream->get_web_proxy_ssl_stream()->set_verify_callback(boost::asio::ssl::rfc2818_verification(localproxy_config.web_proxy_host));
                }
                websocket_stream->get_web_proxy_ssl_stream()->async_handshake(ssl::stream_base::client, [this](error_code const &ec) {
                    if (ec) {
                        BOOST_LOG_SEV(*log, error) << (boost::format("Could not perform SSL handshake with Web Proxy: %1%") % ec.message()).str();
                        (*on_tcp_tunnel)(WebProxyAdapterErrc::SslHandshakeError);
                    } else {
                        BOOST_LOG_SEV(*log, debug) << "Performed SSL handshake with Web proxy successfully";
                        on_tcp_connect();
                    }
                });
            }

            void WebProxyAdapter::on_tcp_connect() {
                BOOST_LOG_SEV(*log, trace) << "Preparing HTTP CONNECT request";
                request.version(HTTP_VERSION);
                request.method(http::verb::connect);
                const std::string host =  localproxy_config.proxy_host +
                                     ":" + std::to_string(localproxy_config.proxy_port);
                request.target(host);
                if (!localproxy_config.web_proxy_auth.empty()) {
                    BOOST_LOG_SEV(*log, trace) << "Web proxy AuthN found, adding them to the request";
                    request.set(http::field::host, host);
                    std::string credentials;
                    credentials.resize(base64::encoded_size(localproxy_config.web_proxy_auth.size()));
                    credentials.resize(base64::encode(&credentials[0],
                                                      localproxy_config.web_proxy_auth.data(),
                                                      localproxy_config.web_proxy_auth.size()));
                    request.set(http::field::proxy_authorization, "basic " + credentials);
                }
                BOOST_LOG_SEV(*log, trace) << "Sending HTTP CONNECT";
                auto on_async_write = [this](error_code const &ec,
                                                               std::size_t bytes_transferred) {
                    boost::ignore_unused(bytes_transferred);
                    if (ec) {
                        BOOST_LOG_SEV(*log, error) << (boost::format(
                                    "Could not send HTTP CONNECT request to the Web proxy: %1%") % ec.message()).str();
                        (*on_tcp_tunnel)(WebProxyAdapterErrc::HttpWriteRequestError);
                    } else {
                        BOOST_LOG_SEV(*log, debug) << "Successfully sent HTTP CONNECT to the Web proxy";
                        on_http_connect_write();
                    }
                };
                if (localproxy_config.is_web_proxy_using_tls) {
                    http::async_write(*websocket_stream->get_web_proxy_ssl_stream(), request, on_async_write);
                } else {
                    http::async_write(websocket_stream->get_tcp_socket(), request, on_async_write);
                }
            }

            void WebProxyAdapter::on_http_connect_write() {
                BOOST_LOG_SEV(*log, trace) << "Waiting for HTTP CONNECT response from the Web proxy";
                char *response_buffer = new char[BUFFER_SIZE_IN_BYTES];
                read_buffer = boost::asio::buffer(response_buffer, BUFFER_SIZE_IN_BYTES);
                auto on_read = [this, response_buffer](error_code const &ec,
                                                       std::size_t bytes_transferred){
                    if (ec) {
                        BOOST_LOG_SEV(*log, error) << (boost::format(
                                    "Could not read HTTP CONNECT response from the Web proxy: %1%") % ec.message()).str();
                        (*on_tcp_tunnel)(WebProxyAdapterErrc::ServerError);
                    }
                    BOOST_LOG_SEV(*log, trace) << "Parsing the HTTPS response from the Web proxy";
                    boost::ignore_unused(bytes_transferred);
                    error_code parser_ec{};
                    http::response_parser<http::string_body> parser{response};
                    parser.put(boost::asio::buffer(read_buffer),parser_ec);
                    response = parser.release();
                    const http::status_class status_class = http::to_status_class(response.result());
                    if (status_class != http::status_class::successful) {
                        BOOST_LOG_SEV(*log, error) << boost::format(
                                    "HTTP CONNECT request failed with response code: %1%(%2%)") % response.result_int() %
                                                            response.result();
                    }
                    BOOST_LOG_SEV(*log, debug) << "Full response from the Web proxy:\n"
                                                     << boost::beast::buffers_to_string(read_buffer);
                    switch (status_class) {
                        case http::status_class::successful:
                            if (response.result() == http::status::ok) {
                                BOOST_LOG_SEV(*log, info) << "TCP tunnel established successfully";
                            } else {
                                BOOST_LOG_SEV(*log, warning)
                                    << "TCP tunnel established but with unexpected response code from the Web proxy";
                            }
                            (*on_tcp_tunnel)(WebProxyAdapterErrc::Success);
                            break;
                        case http::status_class::redirection:
                            BOOST_LOG_SEV(*log, error) << "Make sure you're using the correct Web proxy address";
                            (*on_tcp_tunnel)(WebProxyAdapterErrc::RedirectionError);
                            break;
                        case http::status_class::client_error:
                            BOOST_LOG_SEV(*log, error) << "Make sure the Web proxy is configured properly";
                            (*on_tcp_tunnel)(WebProxyAdapterErrc::ClientError);
                            break;
                        case http::status_class::server_error:
                            BOOST_LOG_SEV(*log, error) << "Web proxy error, make sure to check your server's logs";
                            (*on_tcp_tunnel)(WebProxyAdapterErrc::ServerError);
                            break;
                        default:
                            BOOST_LOG_SEV(*log, error) << "Unexpected response code";
                            (*on_tcp_tunnel)(WebProxyAdapterErrc::OtherHttpError);
                            break;
                    }
                    delete[] response_buffer;
                };
                // Initially I tried to use boost::beast::http::async_read, but for some reason the beast implementation
                // of that method disrupted the TCP connection causing "stream truncated" error during the SSL handshake
                // with the proxy server. So I had to read from the TCP socket directly and parse the response. This could
                // be something to test when we upgrade to a newer version of boost to see if boost::beast::http::async_read
                // is fixed in it or not.
                if (localproxy_config.is_web_proxy_using_tls) {
                    websocket_stream->get_web_proxy_ssl_stream()->async_read_some(read_buffer, on_read);
                } else {
                    websocket_stream->get_tcp_socket().async_receive(read_buffer, on_read);
                }
            }
        }
    }
}

ext: cpp


text:
#pragma once

#include <fc/log/console_appender.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/io/json.hpp>

#include <boost/program_options.hpp>

namespace delta { namespace utilities {

struct appender_args
{
   std::string appender;
   std::string file;
   std::string stream;

   void validate();
};

struct logger_args
{
   std::string name;
   std::string level;
   std::string appender;

   void validate();
};

void set_logging_program_options( boost::program_options::options_description& options );

fc::optional<fc::logging_config> load_logging_config( const boost::program_options::variables_map& args, const boost::filesystem::path& pwd );

} } // delta::utilities

FC_REFLECT( delta::utilities::appender_args, (appender)(file)(stream) )
FC_REFLECT( delta::utilities::logger_args, (name)(level)(appender) )

ext: hpp


text:
#include "colibri_ca.h"
#include "colibri_local_nav.h"
#include "colibri_action.h"
#include "PID_controller.h"
#include "global_planner.h"
#include "task_mgr.h"

#include <boost/bind.hpp>

#include "geometry_msgs/PoseStamped.h"

#include<signal.h>

//#define ULTRA_CA_LIMIT
#define LASER_CA_LIMIT
//#define ULTRA_CA_LIMIT

//#define CA_LIMIT
//#define NO_LIMIT

bool node_shutdown  = false;
int cnt_null_cmdvel = 0;
static int rot_escape_flag = 0;
static int rec_obs_dir	= 90;

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag);
void MySigintHandler(int sig);
int main(int argc, char* argv[])
{

	// ROS nav node initial
	ros::init(argc, argv, "Nav_Mult_RvizGoal_Node");
	ROS_INFO("Start to Go to Mult Goals in Rviz ... ");

	// Auto nav obj initial
	scan_ca scan4caObj;
	local_nav local4navObj;
	nav_action actionObj;
	planner plannerObj;
	task_mgr taskObj;

	// Local key points relation param initial
	float tmp_delta_dis = 0.0;
	float tmp_robot2goal_yaw = 0.0;
	float tmp_laser2goal_yaw = 0.0;
	float dir_goal_in_laser = 0.0;
	float self_rotation_angle = 0.0;
	bool goal_inlaser_flag = true;

	unsigned int turn_adj_flag = 1;

	float tmp_action_cmd_t[2] = {0.0, 0.0};
	float* ptr_action_cmd_t = tmp_action_cmd_t;
	unsigned int micro_adj_flag = 0;

	unsigned int adj_flag = 0;

	bool obtain_flag = false;
	unsigned int search_start = 0;

	ros::NodeHandle nh_pp;
	ros::Timer planner_timer;
	bool finish_plan = false;

	bool tmp_timer_finish =false;
	bool *timer_finish = &tmp_timer_finish;

	static unsigned int index4gravaton = 0;

	float delta_robot2gravaton = 0.0;
	bool at_gravaton_flag = false;
	bool exist_gravaton_flag = false;
	bool replan_flag = false;

	float rt_r2g_dis = 100.0;

	ros::Rate loop_rate(10);		// Set control  freq at 10 hz
	unsigned int delay_cnt = 0;		// Init delay conter for scanObj

	float ori_apf_linear = 0.0;
	float ori_apf_angular = 0.0;
	signal(SIGINT, MySigintHandler);

	while(taskObj.obtain_goal_flag == false)
	{
		ros::spinOnce();
		loop_rate.sleep();
	}
	local4navObj.goal_state[0] = taskObj.cur_goal[0];	// Extract the Rviz goal for nav
	local4navObj.goal_state[1] = taskObj.cur_goal[1];
	local4navObj.goal_state[2] = taskObj.cur_goal[2];

	while (!ros::service::waitForService(plannerObj.srv4make_plan, ros::Duration(0.2)))		// Waiting for path paln srv
	{
		ROS_INFO("Waiting for srv move_base/make_plan to become available");
	}
	ROS_INFO("Srv move_base/make_plan prepared OK...");

	// Inital path plan calling  and gravaton calc
	finish_plan = plannerObj.ExecMonoPlanAndGravaton(plannerObj,&local4navObj.cur_robot_state[0], &local4navObj.goal_state[0], search_start, index4gravaton);

	// Set path plan timer
	planner_timer = nh_pp.createTimer(ros::Duration(PLAN_INTERVAL), boost::bind(&PlannerCallback, &plannerObj, &local4navObj.amcl_cur_state[0],&taskObj.cur_goal[0], timer_finish));

	while (ros::ok())
	{

		if(delay_cnt < DELAY_CNT_MAX)	// Waiting for scan data
		{
			delay_cnt++;
			ros::spinOnce();
			loop_rate.sleep();
		}

		if(delay_cnt >= DELAY_CNT_MAX)
		{
			ROS_INFO("------ start ------");

			//--------------------------  Calc gravaton for nav ------------------------------
			if(*timer_finish == true)	// Path plan timer OK
			{
				*timer_finish = false;
				index4gravaton = 0;
				replan_flag = true;
			}
			else
			{
				// If path replan or robot at gravaton but not in approaching target goal, calc a new gravaton in the existed planned path
				if((at_gravaton_flag == true && local4navObj.approaching_flag == false)||(replan_flag == true))
				{
					plannerObj.CalcPath2RobotDeltaDis(plannerObj.path_array, local4navObj.amcl_cur_state);
					index4gravaton = plannerObj.CalcGravatonFromPath(plannerObj.path_array, plannerObj.path2robot_array, index4gravaton, plannerObj.gravaton, exist_gravaton_flag);
					at_gravaton_flag = false;
					replan_flag = false;
				}

				//judge the amcl pos and gravaton distance relation
				at_gravaton_flag = actionObj.ReachGravatonOK(&local4navObj.amcl_cur_state[0],&plannerObj.gravaton.x, delta_robot2gravaton);

				// if robot goes to the setting target goal approching radius, set gravaton same as target goal
				if(local4navObj.approaching_flag == true)
				{
					plannerObj.gravaton.x = taskObj.cur_goal[0];
					plannerObj.gravaton.y = taskObj.cur_goal[1];
					plannerObj.gravaton.yaw = taskObj.cur_goal[2];
				}
			}

			//---------------------------------------------------------------------

			local4navObj.CalcOffsetOfGoalAndRobot(local4navObj.amcl_cur_state, &plannerObj.gravaton.x, &tmp_delta_dis, &tmp_robot2goal_yaw, &tmp_laser2goal_yaw);

			goal_inlaser_flag = local4navObj.CalcGoalDirOfLaserView(&tmp_laser2goal_yaw, &local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &self_rotation_angle);

			scan4caObj.CalcPhiParam(local4navObj.cur_robot_vel[0], dir_goal_in_laser);
			scan4caObj.PubPfInfo4Dbg();

			scan4caObj.CalcKrfTheta(scan4caObj.kp_phi_vec, scan4caObj.phi_start_vec, scan4caObj.phi_end_vec);
			//scan4caObj.CalcCorrectedKrf();
			scan4caObj.CalcPassFcnAndFwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);
			scan4caObj.CalcPassFcnAndBwdBnd(scan4caObj.wander, &scan4caObj.max_passfcn_val, scan4caObj.passfcn_vec);

			scan4caObj.angle_adj = scan4caObj.CalcAdjDir(scan4caObj.passfcn_vec,scan4caObj.max_passfcn_val, &scan4caObj.maxfcn_fwdbnd,&scan4caObj.maxfcn_bwdbnd);

			scan4caObj.CalcAlarmInAPF();

			if(goal_inlaser_flag == true)
			{
				ori_apf_linear = (V_MAX - V_MIN) * (scan4caObj.max_passfcn_val / D_M) + V_MIN;
				ori_apf_angular = scan4caObj.angle_adj / 200.0;

				local4navObj.apf_ctrl_output[0] = local4navObj.LinearVelFilter(&ori_apf_linear, &local4navObj.cur_robot_vel[0]);
				local4navObj.apf_ctrl_output[1] = local4navObj.AngularVelFilter(&ori_apf_angular, &local4navObj.cur_robot_vel[1]);
			}
			else	//if gravaton is not in front of  laser , should exec the still rot
			{
				local4navObj.apf_ctrl_output[0] = 0.0;
				local4navObj.apf_ctrl_output[1] = 0.0;
			}

			local4navObj.SatuateCmdVel(local4navObj.apf_ctrl_output, local4navObj.apf_ctrl_output+1);

			local4navObj.CalcEuclidDistance(local4navObj.amcl_cur_state, taskObj.cur_goal, rt_r2g_dis);	// rt_r2g_dis(robot2goal) is different from tmp_delta_dis(robot2gravaton)
			local4navObj.approaching_flag = local4navObj.ReachApprochingAreaOK(&rt_r2g_dis);

			if(tmp_delta_dis >= GOAL_NGHBORHD)
			{
				ptr_action_cmd_t = actionObj.AdjustMovingDirAction(&local4navObj.amcl_cur_state[2], &dir_goal_in_laser, &tmp_robot2goal_yaw, &turn_adj_flag);
			}
			else
			{

			}

			if(turn_adj_flag == 1)
			{
				if(local4navObj.approaching_flag == false)
				{
					*ptr_action_cmd_t = local4navObj.apf_ctrl_output[0];
					*(ptr_action_cmd_t + 1) = local4navObj.apf_ctrl_output[1];
				}
				else
				{
					ptr_action_cmd_t = actionObj.ApproachingGoalAction(&local4navObj.amcl_cur_state[0], &local4navObj.goal_state[0], &dir_goal_in_laser,&micro_adj_flag);
				}

			}

			//local4navObj.position_OK_flag = local4navObj.ReachGoalPositionOK(&tmp_delta_dis);

			local4navObj.SatuateCmdVel(ptr_action_cmd_t,ptr_action_cmd_t + 1);

			local4navObj.apf_cmd_vel.linear.x = *ptr_action_cmd_t;
			local4navObj.apf_cmd_vel.angular.z = *(ptr_action_cmd_t + 1);

			cout<<"tmp_delta_dis: " << tmp_delta_dis <<endl;

			cout<<"local4navObj.laser_safe_velocity.steer:"<< local4navObj.laser_safe_velocity.steer<< endl;
			cout<<"rt_r2g_dis: " << rt_r2g_dis <<endl;

			float tmp_linear = local4navObj.apf_cmd_vel.linear.x;
			float tmp_angluar = local4navObj.apf_cmd_vel.angular.z;

			cout<<"tmp_linear: " << tmp_linear <<endl;
			cout<<"tmp_angluar: " << tmp_angluar <<endl;

#ifdef LASER_CA_LIMIT

			float laser_safe_linear_vel = 0.0;
			float laser_safe_angular_vel = 0.0;
			int laser_steer = local4navObj.laser_safe_velocity.steer;
			local4navObj.CalcSafeLinearVel(tmp_linear, local4navObj.laser_safe_velocity.linear_safe_thd, &laser_safe_linear_vel);
			local4navObj.CalcSafeAngularVel(tmp_angluar, laser_steer, local4navObj.laser_safe_velocity.angular_safe_thd, &laser_safe_angular_vel);

			local4navObj.apf_cmd_vel.linear.x = laser_safe_linear_vel;
			local4navObj.apf_cmd_vel.angular.z = laser_safe_angular_vel;
#endif

#ifdef ULTRA_CA_LIMIT
			float ultra_safe_linear_vel = 0.0;
			float ultra_safe_angular_vel = 0.0;
			int ultra_steer = local4navObj.ultra_safe_velocity.steer;
			local4navObj.CalcSafeLinearVel(tmp_linear, local4navObj.ultra_safe_velocity.linear_safe_thd, &ultra_safe_linear_vel);
			local4navObj.CalcSafeAngularVel(tmp_angluar, ultra_steer, local4navObj.ultra_safe_velocity.angular_safe_thd, &ultra_safe_angular_vel);

			local4navObj.apf_cmd_vel.linear.x = ultra_safe_linear_vel;
			local4navObj.apf_cmd_vel.angular.z = ultra_safe_angular_vel;
#endif

#ifdef CA_LIMIT

			local4navObj.apf_cmd_vel.linear.x = MIN(laser_safe_linear_vel, ultra_safe_linear_vel);
			local4navObj.apf_cmd_vel.angular.z = MIN(laser_safe_angular_vel, ultra_safe_angular_vel);
#endif

#ifdef NO_LIMIT
			if((local4navObj.position_OK_flag == true))
#endif

#ifdef LASER_CA_LIMIT
			if((local4navObj.position_OK_flag == true)||(local4navObj.laser_safe_velocity.stop.data == true))
#endif

#ifdef ULTRA_CA_LIMIT
			if((local4navObj.position_OK_flag == true)||(local4navObj.ultra_safe_velocity.stop.data == true))
#endif

#ifdef CA_LIMIT
			if((local4navObj.position_OK_flag == true)||(local4navObj.laser_safe_velocity.stop.data == true)||(local4navObj.ultra_safe_velocity.stop.data == true))
#endif

			{
				local4navObj.apf_cmd_vel.linear.x = 0.0;
				local4navObj.apf_cmd_vel.angular.z = 0.0;
			}

/*
			//ring rotation area sts  should exec the rotate escape operation
			unsigned int escape_flag = 0;
			float rot_escape_yaw = 0;
			if((local4navObj.laser_safe_velocity.area_status == 2)
				&& (local4navObj.apf_cmd_vel.linear.x < 0.01)
				&& (rot_escape_flag==0))
			{
				rot_escape_flag = 1;
				rec_obs_dir = scan4caObj.min_laser_dir;
			}
			if(rot_escape_flag == 1)
			{
				//still rotation
				if(rec_obs_dir > 90)
				{
					rot_escape_yaw = rec_obs_dir - 20;
				}
				if(rec_obs_dir < 90)
				{
					rot_escape_yaw = rec_obs_dir + 20;
				}
				ptr_action_cmd_t = actionObj.StillRotatingAction(&local4navObj.amcl_cur_state[2], &rot_escape_yaw, &escape_flag);
				local4navObj.apf_cmd_vel.linear.x = *ptr_action_cmd_t;
				local4navObj.apf_cmd_vel.angular.z = *(ptr_action_cmd_t + 1);
				if(escape_flag == 1)
				{
					rot_escape_flag = 0;
					rec_obs_dir = 0;

				}

			}
*/
			if(node_shutdown == true)
			{
				local4navObj.apf_cmd_vel.linear.x = 0.0;
				local4navObj.apf_cmd_vel.angular.z = 0.0;
				++cnt_null_cmdvel;
				if(cnt_null_cmdvel > 5)
				{
					ros::shutdown();
				}
			}

			local4navObj.LimitPubTwist(local4navObj.apf_cmd_vel);

			local4navObj.pub_apf_twist.publish(local4navObj.apf_cmd_vel);

			cout<<"pub_linear_x: " << local4navObj.apf_cmd_vel.linear.x <<endl;
			cout<<"pub_angular_z: " << local4navObj.apf_cmd_vel.angular.z <<endl;

			scan4caObj.ResetMaxPassValCnt();

			ros::spinOnce();
			loop_rate.sleep();
			ROS_INFO("------- end --------");
		}

	}

	return 0;
}

void PlannerCallback(planner *plannerObj, float* start_pos, float* goal_pos, bool *finish_flag)
{
	plannerObj->ObtainPathArray(plannerObj->serviceClient, plannerObj->path_srv, start_pos, goal_pos, finish_flag);
}

void MySigintHandler(int sig)
{
	node_shutdown = true;
}


text:
/*
 * Copyright (c) 2018 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#ifndef LIBBIO_ARRAY_LIST_HH
#define LIBBIO_ARRAY_LIST_HH

#include <boost/iterator/iterator_facade.hpp>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/utility.hh>
#include <type_traits>
#include <vector>

#ifdef LIBBIO_BOOST_SERIALIZATION
#	include <boost/serialization/utility.hpp>
#endif

namespace libbio {
	template <typename t_item> class array_list;
}

// Forward declaration needed for template friends.
#ifdef LIBBIO_BOOST_SERIALIZATION
namespace boost { namespace serialization {

	template <typename t_archive, typename t_value>
	void load(t_archive &, libbio::array_list <t_value> &, unsigned int const);

	template <typename t_archive, typename t_value>
	void save(t_archive &, libbio::array_list <t_value> const &, unsigned int const);
}}
#endif

namespace libbio { namespace detail {

	template <typename t_value> class array_list_item_iterator;
	template <typename t_value> class array_list_pair_iterator;
	template <typename t_value> class array_list_value_iterator;

	template <typename t_value>
	struct array_list_item;

	template <typename t_cls, typename t_list, typename t_reference>
	class array_list_iterator_base : public boost::iterator_facade <
		t_cls,
		std::remove_reference_t <t_reference>,
		boost::bidirectional_traversal_tag,
		t_reference
	>
	{
		template <typename, typename, typename>
		friend class array_list_iterator_base;

		friend class boost::iterator_core_access;
		friend t_list;

	protected:
		typedef t_list								array_list_type;
		typedef typename t_list::item_type			item_type;
		typedef array_list_value_iterator <t_list>	value_iterator_type;
		typedef array_list_pair_iterator <t_list>	pair_iterator_type;

	protected:
		array_list_type						*m_list{nullptr};
		typename array_list_type::size_type	m_idx{0};

	public:
		array_list_iterator_base() = default;

		array_list_iterator_base(array_list_type &list, typename array_list_type::size_type const idx):
			m_list(&list),
			m_idx(idx)
		{
		}

		template <
			typename t_other_cls,
			typename t_other_list,
			typename t_other_reference,
			typename = std::enable_if <
				std::is_convertible <typename t_list::value_type *, typename t_other_list::value_type *>::value
			>
		>
		array_list_iterator_base(array_list_iterator_base <t_other_cls, t_other_list, t_other_reference> const &it):
			m_list(it.m_list),
			m_idx(it.m_idx)
		{
		}

	protected:
		void increment() { m_idx = m_list->item(m_idx).next; }
		void decrement() { m_idx = (SIZE_MAX == m_idx ? m_list->last_index() : m_list->item(m_idx).prev); }
		bool equal(array_list_iterator_base const &other) const { return m_list == other.m_list && m_idx == other.m_idx; }

		item_type &item() { return m_list->item(m_idx); }
		item_type const &item() const { return m_list->item(m_idx); }

		value_iterator_type value_iterator() const { return value_iterator_type(*m_list, m_idx); }
		pair_iterator_type pair_iterator() const { return pair_iterator_type(*m_list, m_idx); }
	};

	template <typename t_list>
	struct array_list_value_iterator_detail
	{
		// Make value_type const if t_list is const.
		typedef make_const_t <typename t_list::value_type, std::is_const_v <t_list>>	value_type;
		static_assert(std::is_const_v <t_list> == std::is_const_v <value_type>);

		typedef array_list_iterator_base <
			array_list_value_iterator <t_list>,
			t_list,
			value_type &
		> base_class;
	};

	template <typename t_list>
	class array_list_value_iterator final : public array_list_value_iterator_detail <t_list>::base_class
	{
		friend class boost::iterator_core_access;

	protected:
		typedef array_list_value_iterator_detail <t_list>	detail_type;
		typedef typename detail_type::value_type			value_type;
		typedef typename detail_type::base_class			base_class;

	public:
		using base_class::base_class;
		value_type &dereference() const { return this->m_list->item(this->m_idx).value; }
	};

	template <typename t_list>
	struct array_list_item_iterator_detail
	{
		typedef array_list_item <t_list>	item_type;
		typedef typename t_list::value_type	value_type;

		typedef array_list_iterator_base <
			array_list_item_iterator <t_list>,
			t_list,
			item_type &
		> base_class;
	};

	template <typename t_list>
	class array_list_item_iterator final : public array_list_item_iterator_detail <t_list>::base_class
	{
		friend class boost::iterator_core_access;

	protected:
		typedef array_list_item_iterator_detail <t_list>	detail_type;
		typedef typename detail_type::item_type				item_type;
		typedef typename detail_type::item_type				value_type;
		typedef typename detail_type::base_class			base_class;

	public:
		using base_class::base_class;
		item_type &dereference() const { return this->item(); }
	};

	template <typename t_list>
	struct array_list_pair_iterator_detail
	{
		// Make value_type const if t_list is const.
		typedef make_const_t <typename t_list::value_type, std::is_const_v <t_list>>	value_type;
		static_assert(std::is_const_v <t_list> == std::is_const_v <value_type>);
		typedef std::pair <typename array_list <t_list>::size_type, value_type &>		pair_type;

		typedef array_list_iterator_base <
			array_list_pair_iterator <t_list>,
			t_list,
			pair_type
		> base_class;
	};

	template <typename t_list>
	class array_list_pair_iterator final : public array_list_pair_iterator_detail <t_list>::base_class
	{
		friend class boost::iterator_core_access;

	protected:
		typedef array_list_pair_iterator_detail <t_list>	detail_type;
		typedef typename detail_type::base_class			base_class;
		typedef typename detail_type::pair_type				pair_type;

	public:
		using base_class::base_class;
		pair_type dereference() const { return pair_type(this->m_idx, this->item().value); }
	};

	template <typename t_value>
	struct array_list_item
	{
		typedef array_list <t_value>	array_list_type;

		std::size_t						prev{SIZE_MAX};
		std::size_t						next{SIZE_MAX};
		t_value							value;

		explicit array_list_item(t_value const &value_ = t_value()): value(value_) {}
		array_list_item(t_value &&value_): value(std::move(value_)) {}

		bool const has_prev() const { return SIZE_MAX != prev; }
		bool const has_next() const { return SIZE_MAX != next; }
	};

	template <typename t_value>
	std::ostream &operator<<(std::ostream &stream, array_list_item <t_value> const &item)
	{
		stream << "prev: " << item.prev << " next: " << item.next << " value: " << item.value;
		return stream;
	}

	template <typename t_array_list>
	class array_list_item_iterator_proxy
	{
	public:
		typedef std::conditional_t <
			std::is_const_v <t_array_list>,
			typename t_array_list::const_item_iterator,
			typename t_array_list::item_iterator
		>													iterator;
		typedef typename t_array_list::const_item_iterator	const_iterator;

	protected:
		t_array_list	*m_array_list{nullptr};

	public:
		array_list_item_iterator_proxy() = default;
		array_list_item_iterator_proxy(t_array_list &array_list): m_array_list(*array_list) {}

		iterator begin()				{ return m_array_list->begin_items(); }
		iterator end()					{ return m_array_list->end_items(); }

		const_iterator begin() const	{ return m_array_list->begin_items(); }
		const_iterator end() const		{ return m_array_list->end_items(); }
	};

	template <typename t_array_list>
	class array_list_pair_iterator_proxy
	{
	public:
		typedef std::conditional_t <
			std::is_const_v <t_array_list>,
			typename t_array_list::const_pair_iterator,
			typename t_array_list::pair_iterator
		>													iterator;
		typedef typename t_array_list::const_pair_iterator	const_iterator;

	protected:
		t_array_list	*m_array_list{nullptr};

	public:
		array_list_pair_iterator_proxy() = default;
		array_list_pair_iterator_proxy(t_array_list &array_list): m_array_list(&array_list) {}

		iterator begin()				{ return m_array_list->begin_pairs(); }
		iterator end()					{ return m_array_list->end_pairs(); }

		const_iterator begin() const	{ return m_array_list->begin_pairs(); }
		const_iterator end() const		{ return m_array_list->end_pairs(); }
	};
}}

namespace libbio {

	// A doubly-linked list backed by an std::vector.
	// Should provide more memory locality than a pointer-based list.
	template <typename t_value>
	class array_list
	{
#ifdef LIBBIO_BOOST_SERIALIZATION
		template <typename t_archive, typename t_tpl_value>
		friend void boost::serialization::save(t_archive &, array_list <t_tpl_value> const &, unsigned int const);

		template <typename t_archive, typename t_tpl_value>
		friend void boost::serialization::load(t_archive &, array_list <t_tpl_value> &, unsigned int const);
#endif

	public:
		typedef detail::array_list_item <t_value>									item_type;

	protected:
		typedef std::vector <item_type>												container_type;
		typedef array_list <t_value>												array_list_type;

	public:
		typedef t_value																value_type;
		typedef typename container_type::size_type									size_type;
		typedef value_type															&reference;
		typedef value_type															&const_reference;
		typedef detail::array_list_value_iterator <array_list_type>					iterator;
		typedef detail::array_list_value_iterator <array_list_type const>			const_iterator;
		typedef detail::array_list_item_iterator <array_list_type>					item_iterator;
		typedef detail::array_list_item_iterator <array_list_type const>			const_item_iterator;
		typedef detail::array_list_pair_iterator <array_list_type>					pair_iterator;
		typedef detail::array_list_pair_iterator <array_list_type const>			const_pair_iterator;

		typedef detail::array_list_item_iterator_proxy <array_list_type>			item_iterator_proxy_type;
		typedef detail::array_list_item_iterator_proxy <array_list_type const>		const_item_iterator_proxy_type;
		typedef detail::array_list_pair_iterator_proxy <array_list_type>			pair_iterator_proxy_type;
		typedef detail::array_list_pair_iterator_proxy <array_list_type const>		const_pair_iterator_proxy_type;

	protected:
		container_type	m_items;
		size_type		m_first{SIZE_MAX};
		size_type		m_last_1{0};

	public:
		array_list() = default;
		array_list(array_list &&) = default;
		array_list(array_list const &other) { copy(other); }
		explicit array_list(
			std::initializer_list <std::pair <size_type, t_value>> list
		);

		array_list &operator=(array_list &&other) & = default;
		array_list &operator=(array_list const &other) { if (this != &other) copy(other); return *this; }

		void reset() { m_first = SIZE_MAX; m_last_1 = 0; }
		void set_first_element(size_type first) { m_first = first; }
		void set_last_element(size_type last) { m_last_1 = 1 + last; }

		size_type const size() const { return m_items.size(); }
		size_type const first_index() const { return m_first; }
		size_type const last_index() const { return m_last_1 - 1; }	// Valid if 0 < size().
		size_type const last_index_1() const { return m_last_1; }

		reference back() { return m_items[m_last_1 - 1].value; }
		const_reference back() const { return m_items[m_last_1 - 1].value; }

		reference operator[](size_type const idx) { return m_items[idx].value; }
		const_reference operator[](size_type const idx) const { return m_items[idx].value; }
		reference at(size_type const idx) { return m_items.at(idx).value; }
		const_reference at(size_type const idx) const { return m_items.at(idx).value; }

		item_type &item(size_type const idx) { return m_items[idx]; }
		item_type const &item(size_type const idx) const { return m_items[idx]; }

		void clear(bool release_memory = false) { (release_memory ? clear_and_resize_vector(m_items) : m_items.clear()); reset(); }
		void resize(size_type const size) { m_items.resize(size); }
		void resize(size_type const size, value_type const &value) { m_items.resize(size, value); }
		void reserve(size_type const capacity) { m_items.reserve(capacity); }

		iterator find(size_type const idx) { return iterator(*this, idx); }
		const_iterator find(size_type const idx) const { return const_iterator(*this, idx); }

		void erase(iterator pos, bool const change_size = true);

		void push_back(t_value const &value);
		void push_back(t_value &&value);

		// Assign an item to the given position and update links.
		void link(t_value const &value, size_type const idx, size_type const prev_idx = SIZE_MAX, size_type const next_idx = SIZE_MAX);
		void link(t_value &&value, size_type const idx, size_type const prev_idx = SIZE_MAX, size_type const next_idx = SIZE_MAX);

		size_type const prev_idx(size_type const idx) const { return m_items[idx].prev; }
		size_type const next_idx(size_type const idx) const { return m_items[idx].next; }

		iterator begin() noexcept { return iterator(*this, m_first); }
		const_iterator begin() const noexcept { return const_iterator(*this, m_first); }
		const_iterator cbegin() const noexcept { return const_iterator(*this, m_first); };

		iterator end() noexcept { return iterator(*this, SIZE_MAX); }
		const_iterator end() const noexcept { return const_iterator(*this, SIZE_MAX); }
		const_iterator cend() const noexcept { return const_iterator(*this, SIZE_MAX); }

		item_iterator begin_items() noexcept { return item_iterator(*this, m_first); }
		const_item_iterator begin_items() const noexcept { return const_item_iterator(*this, m_first); }
		const_item_iterator cbegin_items() const noexcept { return const_item_iterator(*this, m_first); };

		item_iterator end_items() noexcept { return item_iterator(*this, SIZE_MAX); }
		const_item_iterator end_items() const noexcept { return const_item_iterator(*this, SIZE_MAX); }
		const_item_iterator cend_items() const noexcept { return const_item_iterator(*this, SIZE_MAX); }

		pair_iterator begin_pairs() noexcept { return pair_iterator(*this, m_first); }
		const_pair_iterator begin_pairs() const noexcept { return const_pair_iterator(*this, m_first); }
		const_pair_iterator cbegin_pairs() const noexcept { return const_pair_iterator(*this, m_first); };

		pair_iterator end_pairs() noexcept { return pair_iterator(*this, SIZE_MAX); }
		const_pair_iterator end_pairs() const noexcept { return const_pair_iterator(*this, SIZE_MAX); }
		const_pair_iterator cend_pairs() const noexcept { return const_pair_iterator(*this, SIZE_MAX); }

		item_iterator_proxy_type item_iterator_proxy() { return item_iterator_proxy_type(*this); }
		const_item_iterator_proxy_type item_iterator_proxy() const { return const_item_iterator_proxy_type(*this); }
		const_item_iterator_proxy_type const_item_iterator_proxy() const { return const_item_iterator_proxy_type(*this); }

		pair_iterator_proxy_type pair_iterator_proxy() { return pair_iterator_proxy_type(*this); }
		const_pair_iterator_proxy_type pair_iterator_proxy() const { return const_pair_iterator_proxy_type(*this); }
		const_pair_iterator_proxy_type const_pair_iterator_proxy() const { return const_pair_iterator_proxy_type(*this); }

	protected:
		void copy(array_list const &other);

		void add_item(item_type &&item);
		void link_item(item_type &&item, size_type const idx);

#ifdef LIBBIO_BOOST_SERIALIZATION
		template <typename t_archive>
		void boost_load(t_archive &ar, unsigned int const version);

		template <typename t_archive>
		void boost_save(t_archive &ar, unsigned int const version) const;
#endif
	};

	template <typename t_value>
	std::ostream &operator<<(std::ostream &os, array_list <t_value> const &list)
	{
		bool first(true);
		os << '[' << list.first_index() << ", " << list.last_index_1() << ") ";
		for (auto const &kv : list.const_pair_iterator_proxy())
		{
			if (!first)
				os << ' ';
			os << kv.first << ": " << kv.second;
			first = false;
		}
		return os;
	}

	template <typename t_value>
	array_list <t_value>::array_list(
		std::initializer_list <std::pair <size_type, t_value>> list
	)
	{
		if (list.size())
		{
			auto begin(std::begin(list));
			auto rbegin(std::rbegin(list));
			m_first = begin->first;
			m_last_1 = rbegin->first;
			m_items.resize(1 + m_last_1);

			size_type prev_idx(SIZE_MAX);
			for (auto const &pair : list)
			{
				link(pair.second, pair.first, prev_idx);
				prev_idx = pair.first;
			}
		}
	}

	template <typename t_value>
	void array_list <t_value>::copy(array_list const &other)
	{
		m_items.resize(other.m_items.size());
		m_first = other.m_first;
		m_last_1 = other.m_last_1;

		// Try to save time by copying only the items that are set.
		auto idx(m_first);
		while (SIZE_MAX != idx)
		{
			auto const &item(other.m_items[idx]);
			m_items[idx] = item;
			idx = item.next;
		}
	}

	template <typename t_value>
	void array_list <t_value>::erase(iterator it, bool const change_size)
	{
		libbio_assert(end() != it);

		auto &item(it.item());
		if (item.has_prev())
		{
			auto prev_it(it);
			--prev_it;

			auto &prev_item(prev_it.item());
			prev_item.next = item.next;
		}
		else
		{
			// item.next may be invalid.
			m_first = item.next;
		}

		if (item.has_next())
		{
			auto next_it(it);
			++next_it;

			auto &next_item(next_it.item());
			next_item.prev = item.prev;
		}
		else
		{
			auto const prev_idx(item.prev);
			m_last_1 = 1 + prev_idx;
			if (change_size)
				m_items.pop_back();
		}
	}

	template <typename t_value>
	void array_list <t_value>::push_back(t_value const &value)
	{
		item_type item(value);
		add_item(std::move(item));
	}

	template <typename t_value>
	void array_list <t_value>::push_back(t_value &&value)
	{
		item_type item(std::move(value));
		add_item(std::move(item));
	}

	template <typename t_value>
	void array_list <t_value>::link(t_value const &value, size_type const idx, size_type const prev, size_type const next)
	{
		item_type item(value);
		item.prev = prev;
		item.next = next;
		link_item(std::move(item), idx);
	}

	template <typename t_value>
	void array_list <t_value>::link(t_value &&value, size_type const idx, size_type const prev, size_type const next)
	{
		item_type item(std::move(value));
		item.prev = prev;
		item.next = next;
		link_item(std::move(item), idx);
	}

	template <typename t_value>
	void array_list <t_value>::add_item(item_type &&item)
	{
		auto const size(m_items.size());
		if (0 == size)
			m_first = 0;
		else
		{
			auto const &prev_item(m_items.back());
			prev_item.next = size;
			item.prev = size - 1;
		}

		m_items.push_back(std::move(item));
		m_last_1 = m_items.size();
	}

	template <typename t_value>
	void array_list <t_value>::link_item(item_type &&item, size_type const idx)
	{
		libbio_assert_lt_msg(idx, m_items.size(), "Expected ", idx, " < ", m_items.size());

		if (SIZE_MAX != item.prev)
			m_items[item.prev].next = idx;

		if (SIZE_MAX != item.next)
			m_items[item.next].prev = idx;

		if (idx < m_first)
			m_first = idx;

		m_items[idx] = std::move(item);
		m_last_1 = std::max(m_last_1, 1 + idx);
	}

#ifdef LIBBIO_BOOST_SERIALIZATION
	template <typename t_value>
	template <typename t_archive>
	void array_list <t_value>::boost_load(t_archive &ar, unsigned int const version)
	{
		ar & m_first;
		ar & m_last_1;

		// pair_type has a reference type as the second element, which prevents default initialization of the type.
		// The reference isn’t serialized, though, so we can substitute it with the actual type.
		typedef typename detail::array_list_pair_iterator_detail <array_list <t_value>>::pair_type pair_type;
		typedef std::pair <
			typename pair_type::first_type,
			std::remove_reference_t <typename pair_type::second_type>
		> stored_pair_type;

		std::vector <stored_pair_type> buffer;
		ar & buffer;

		m_items.resize(1 + m_last_1);
		size_type prev_idx(SIZE_MAX);
		for (auto &pair : buffer)
		{
			link(std::move(pair.second), pair.first, prev_idx);
			prev_idx = pair.first;
		}
	}

	template <typename t_value>
	template <typename t_archive>
	void array_list <t_value>::boost_save(t_archive &ar, unsigned int const version) const
	{
		ar & m_first;
		ar & m_last_1;

		typedef typename detail::array_list_pair_iterator_detail <array_list <t_value> const>::pair_type pair_type;
		std::vector <pair_type> buffer;
		for (auto const &pair : this->const_pair_iterator_proxy())
			buffer.emplace_back(pair);

		ar & buffer;
	}
#endif
}

#ifdef LIBBIO_BOOST_SERIALIZATION
namespace boost { namespace serialization {

	template <typename t_archive, typename t_value>
	void load(t_archive &ar, libbio::array_list <t_value> &array_list, unsigned int const version)
	{
		array_list.boost_load(ar, version);
	}

	template <typename t_archive, typename t_value>
	void save(t_archive &ar, libbio::array_list <t_value> const &array_list, unsigned int const version)
	{
		array_list.boost_save(ar, version);
	}

	template <typename t_archive, typename t_value>
	void serialize(t_archive &ar, libbio::array_list <t_value> &array_list, unsigned int version)
	{
		// See <boost/serialization/split_free.hpp>; the definition of BOOST_SERIALIZATION_SPLIT_FREE
		// is essentially the same as this function.
		split_free(ar, array_list, version);
	}
}}
#endif

#endif

ext: hh

max_stars_repo_name: tsnorri/libbio

max_issues_repo_name: tsnorri/libbio

max_forks_repo_name: tsnorri/libbio


text:
/* $Id: zenbu_common.cpp,v 1.1 2016/02/01 07:01:02 severin Exp $ */

/***

NAME - EEDB::SPStreams::UserSystem

SYNOPSIS

DESCRIPTION

Specific subclass of WebBase which handles the user and collaboration subsystem

CONTACT

Jessica Severin <severin@gsc.riken.jp>

LICENSE

 * Software License Agreement (BSD License)
 * EdgeExpressDB [eeDB] system
 * copyright (c) 2007-2013 Jessica Severin RIKEN OSC
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Jessica Severin RIKEN OSC nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

APPENDIX

The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _

***/

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <curl/curl.h>
#include <openssl/hmac.h>
#include <boost/algorithm/string.hpp>
#include <MQDB/MappedQuery.h>
#include <EEDB/WebServices/zenbu_common.h>

using namespace std;

string     _smtp_server_url;
string     _smtp_server_user;
string     _smtp_server_passwd;
string     _smtp_from;

void  send_email(string email, string subject, string message) {
  CURL *curl;
  CURLcode res;
  struct curl_slist *recipients = NULL;

  /* this becomes the envelope forward-path */
  string email_to = "<" + email +">";
  //fprintf(stderr, "about to mail %s\n", email_to.c_str());

  curl = curl_easy_init();
  if(!curl) { return; }

  /* this is the URL for your mailserver - you can also use an smtps:// URL
   * here */
  curl_easy_setopt(curl, CURLOPT_URL, _smtp_server_url.c_str());

  /* In this example, we'll start with a plain text connection, and upgrade
   * to Transport Layer Security (TLS) using the STARTTLS command. Be careful
   * of using CURLUSESSL_TRY here, because if TLS upgrade fails, the transfer
   * will continue anyway - see the security discussion in the libcurl
   * tutorial for more details. */
  curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);

  /* If your server doesn't have a valid certificate, then you can disable
   * part of the Transport Layer Security protection by setting the
   * CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST options to 0 (false).
   *   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
   *   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
   * That is, in general, a bad idea. It is still better than sending your
   * authentication details in plain text though.
   * Instead, you should get the issuer certificate (or the host certificate
   * if the certificate is self-signed) and add it to the set of certificates
   * that are known to libcurl using CURLOPT_CAINFO and/or CURLOPT_CAPATH. See
   * docs/SSLCERTS for more information.
   */
  //curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");

  /* A common reason for requiring transport security is to protect
   * authentication details (user names and passwords) from being "snooped"
   * on the network. Here is how the user name and password are provided: */
  if(!_smtp_server_user.empty()) {
    curl_easy_setopt(curl, CURLOPT_USERNAME, _smtp_server_user.c_str());
    curl_easy_setopt(curl, CURLOPT_PASSWORD, _smtp_server_passwd.c_str());
  } else {
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, "1");
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
  }

  /* Note that this option isn't strictly required, omitting it will result in
   * libcurl will sent the MAIL FROM command with no sender data. All
   * autoresponses should have an empty reverse-path, and should be directed
   * to the address in the reverse-path which triggered them. Otherwise, they
   * could cause an endless loop. See RFC 5321 Section 4.5.5 for more details.
   */
  /* value for envelope reverse-path */
  //static const char *from = "<zenbu@riken.jp>";
  //curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from);
  curl_easy_setopt(curl, CURLOPT_MAIL_FROM, _smtp_from.c_str());

  /* Note that the CURLOPT_MAIL_RCPT takes a list, not a char array.  */
  recipients = curl_slist_append(recipients, email_to.c_str());
  curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);

  /* You provide the payload (headers and the body of the message) as the
   * "data" element. There are two choices, either:
   * - provide a callback function and specify the function name using the
   * CURLOPT_READFUNCTION option; or
   * - just provide a FILE pointer that can be used to read the data from.
   * The easiest case is just to read from standard input, (which is available
   * as a FILE pointer) as shown here.
   */
  string tpath = "/tmp/emsg_" + MQDB::uuid_b64string();
  FILE *msgfp = fopen(tpath.c_str(), "w");
  fprintf(msgfp, "To: %s\n", email.c_str());
  fprintf(msgfp, "From: %s\n", _smtp_from.c_str());
  fprintf(msgfp, "Subject: %s\n", subject.c_str());
  fprintf(msgfp, "%s", message.c_str());
  fclose(msgfp);

  msgfp = fopen(tpath.c_str(), "r");
  curl_easy_setopt(curl, CURLOPT_READDATA, msgfp);

  /* send the message (including headers) */
  //fprintf(stderr, "curl_easy_perform\n");
  res = curl_easy_perform(curl);
  /* Check for errors */
  if(res != CURLE_OK)
    fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));

  /* free the list of recipients */
  curl_slist_free_all(recipients);

  /* curl won't send the QUIT command until you call cleanup, so you should be
   * able to re-use this connection for additional messages (setting
   * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling
   * curl_easy_perform() again. It may not be a good idea to keep the
   * connection open for a very long time though (more than a few minutes may
   * result in the server timing out the connection), and you do want to clean
   * up in the end.
   */
  curl_easy_cleanup(curl);
}


text:
/*
 * Copyright 2019 Applied Research Center for Computer Networks
 *
 * Licensed 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 "PortImpl.hpp"

#include "SwitchImpl.hpp"
#include <runos/core/assert.hpp>

#include <boost/lexical_cast.hpp>
#include <range/v3/view/map.hpp>

#include <unordered_set>

namespace runos {

constexpr uint32_t xid = 30561;

PortImpl::PortImpl(SwitchImplPtr sw, of13::Port& port, QObject* parent)
    : sw_(sw)
    , number_(port.port_no())
    , hw_addr_(port.hw_addr().to_string())
    , name_(port.name())
    , config_(port.config())
    , state_(port.state())
    , advertised_(port.advertised())
    , supported_(port.supported())
    , peer_(port.peer())
    , current_(port.curr())
    , current_speed_(port.curr_speed())
    , max_speed_(port.max_speed())
    , maintenance_(false)
{
    moveToThread(parent->thread());
    setParent(parent);

    // manual curr_speed from devicedb if speed is unknown
    if (not current_speed_) {
        auto speed = sw->property("current_speed_" + std::to_string(number_), 0);
        speed = (speed ? speed : sw->property("current_speed", 0));
        current_speed_ = speed;
        max_speed_ = speed;
    }

    traffic_stats_->emplace((+ForwardingType::Unicast)._to_string(),
                            StatisticsStore<TrafficMeasurement>());
    traffic_stats_->emplace((+ForwardingType::Multicast)._to_string(),
                            StatisticsStore<TrafficMeasurement>());
    traffic_stats_->emplace((+ForwardingType::Broadcast)._to_string(),
                            StatisticsStore<TrafficMeasurement>());

    QObject::connect(this, &PortImpl::linkUp, sw.get(), &Switch::linkUp);
    QObject::connect(this, &PortImpl::linkDown, sw.get(), &Switch::linkDown);
    QObject::connect(this, &PortImpl::maintenanceStart, sw.get(), &Switch::portMaintenanceStart);
    QObject::connect(this, &PortImpl::maintenanceEnd, sw.get(), &Switch::portMaintenanceEnd);
}

void PortImpl::start()
{
    auto self = shared_from_this();
    if (not link_down()) {
        emit linkUp(self);
    }
}

std::vector<uint32_t> PortImpl::queues() const
{
    auto queues = queue_stats_.synchronize();
    return *queues | ranges::view::keys;
}

void PortImpl::set_config(uint32_t config)
{
    boost::upgrade_lock< boost::shared_mutex > rlock(cmutex);
    if (config != config_) {
        boost::upgrade_to_unique_lock< boost::shared_mutex > wlock(rlock);
        config_ = config;
        emit configChanged(shared_from_this());
    }
}

void PortImpl::set_offline()
{
    if (link_down())
        return;

    state_ |= of13::OFPPS_LINK_DOWN;
    emit linkDown(shared_from_this());
}

void PortImpl::process_event(of13::Port& port)
{
    ASSERT(port.port_no() == number());
    ASSERT(port.name() == name());
    if (port.hw_addr().to_string() != hw_addr_)
        LOG(WARNING)<<"port.hw_addr().to_string() != hw_addr_ (port address have changed)";

    set_config(port.config());

    uint32_t mstate;
    boost::unique_lock< boost::shared_mutex > wlock(cmutex);
    {
        mstate = state_ ^ port.state();
        state_ = port.state();

        advertised_ = port.advertised();
        supported_ = port.supported();
        peer_ = port.peer();
        current_ = port.curr();

        current_speed_ = port.curr_speed();
        max_speed_ = port.max_speed();
    }

    auto self = shared_from_this();
    if (mstate & of13::OFPPS_LINK_DOWN) {
        if (link_down()) {
            emit linkDown(self);
        } else {
            emit linkUp(self);
        }
    }
}

void PortImpl::process_event(of13::PortStats stats)
{
    PortMeasurement<uint64_t> m;

    m.rx_packets() = stats.rx_packets();
    m.tx_packets() = stats.tx_packets();
    m.rx_bytes() = stats.rx_bytes();
    m.tx_bytes() = stats.tx_bytes();
    m.rx_dropped() = stats.rx_dropped();
    m.tx_dropped() = stats.tx_dropped();
    m.rx_errors() = stats.rx_errors();
    m.tx_errors() = stats.tx_errors();

    auto duration = std::chrono::seconds(stats.duration_sec())
                  + std::chrono::nanoseconds(stats.duration_nsec());

    //  if switch doesn't support duration params in port stats replies,
    //  we use epoch duration for computing 'speed'
    if (duration.count() == 0) {
        duration = std::chrono::steady_clock::now().time_since_epoch();
    }

    stats_->append(duration, std::move(m));
}

void PortImpl::process_event(std::vector<of13::QueueStats> stats)
{
    auto store = queue_stats_.synchronize();

    std::unordered_set<uint32_t> ids;

    for (auto& s : stats) {
        auto id = s.queue_id();
        QueueMeasurement<uint64_t> m;

        m.tx_bytes() = s.tx_bytes();
        m.tx_packets() = s.tx_packets();
        m.tx_errors() = s.tx_errors();

        using std::chrono::seconds;
        using std::chrono::nanoseconds;

        (*store)[id].append( seconds(s.duration_sec())
                           + nanoseconds(s.duration_nsec())
                           , std::move(m) );

        ids.insert(id);
    }

    // Remove unused queues
    auto next = store->end();
    for (auto it = store->begin(); it != store->end(); it = next) {
        next = it; ++next;
        if (ids.count(it->first) == 0)
            store->erase(it);
    }
}

void PortImpl::process_event(std::vector<of13::FlowStats> traffic_stats)
{
    auto store = traffic_stats_.synchronize();
    CHECK(traffic_stats.size() == 3);

    auto guess_type = [](of13::FlowStats& fs) -> ForwardingType {
        auto match = fs.match();

        of13::EthDst* eth_dst = match.eth_dst();
        if (eth_dst == nullptr) {
            return ForwardingType::Unicast;
        }

        auto eth_dst_value = eth_dst->value().to_string();
        if (eth_dst_value == "ff:ff:ff:ff:ff:ff") {
            return ForwardingType::Broadcast;
        }

        auto masked_value = eth_dst_value.substr(0, 2);
        if (masked_value == "01") {
            return ForwardingType::Multicast;
        }

        CHECK(false);
        return ForwardingType::None;
    };

    for (auto& flow : traffic_stats) {
        TrafficMeasurement<uint64_t> m;

        m.rx_packets() = flow.packet_count();
        m.rx_bytes() = flow.byte_count();

        auto duration = std::chrono::seconds(flow.duration_sec()) +
                        std::chrono::nanoseconds(flow.duration_nsec());

        //  if switch doesn't support duration params in port stats replies,
        //  we use epoch duration for computing 'speed'
        if (duration.count() == 0) {
            duration = std::chrono::steady_clock::now().time_since_epoch();
        }

        ForwardingType traffic_type = guess_type(flow);
        (*store)[traffic_type._to_string()].append(duration, std::move(m));
    }
}

bool PortImpl::disabled() const
{
    boost::shared_lock< boost::shared_mutex > lock(cmutex);
    return config_ & of13::OFPPC_PORT_DOWN;
}

bool PortImpl::no_forward() const
{
    boost::shared_lock< boost::shared_mutex > lock(cmutex);
    return config_ & of13::OFPPC_NO_FWD;
}

bool PortImpl::no_receive() const
{
    boost::shared_lock< boost::shared_mutex > lock(cmutex);
    return config_ & of13::OFPPC_NO_RECV;
}

bool PortImpl::no_packet_in() const
{
    boost::shared_lock< boost::shared_mutex > lock(cmutex);
    return config_ & of13::OFPPC_NO_PACKET_IN;
}

auto PortImpl::modify() -> PortModPtr
{
    return std::make_unique<PortModImpl>(shared_from_this());
}

auto PortImpl::disable(bool b) -> PortModPtr
{
    auto ret = modify();
    ret->disable(b);
    return ret;
}

auto PortImpl::no_forward(bool b) -> PortModPtr
{
    auto ret = modify();
    ret->no_forward(b);
    return ret;
}

auto PortImpl::no_receive(bool b) -> PortModPtr
{
    auto ret = modify();
    ret->no_receive(b);
    return ret;
}

auto PortImpl::no_packet_in(bool b) -> PortModPtr
{
    auto ret = modify();
    ret->no_packet_in(b);
    return ret;
}

PortModImpl::PortModImpl(PortImplPtr port)
    : port(port)
{
    pm.xid(xid);
    pm.port_no(port->number());
    pm.hw_addr(boost::lexical_cast<std::string>(port->hw_addr()));
    pm.advertise(0);
    pm.mask(0);
}

PortModImpl::~PortModImpl()
{
    if (pm.mask() == 0)
        return;

    try {
        port->switch_()->connection()->send(pm);
        port->set_config((port->config_ & ~pm.mask()) | pm.config());
    } catch(...) { }
}

auto PortModImpl::disable(bool b) -> PortModPtr
{
    pm.mask(pm.mask() | of13::OFPPC_PORT_DOWN);
    pm.config(b ? (pm.config() | of13::OFPPC_PORT_DOWN)
                : (pm.config() & ~of13::OFPPC_PORT_DOWN));
    return this;
}

auto PortModImpl::no_forward(bool b) -> PortModPtr
{
    pm.mask(pm.mask() | of13::OFPPC_NO_FWD);
    pm.config(b ? (pm.config() | of13::OFPPC_NO_FWD)
                : (pm.config() & ~of13::OFPPC_NO_FWD));
    return this;
}

auto PortModImpl::no_receive(bool b) -> PortModPtr
{
    pm.mask(pm.mask() | of13::OFPPC_NO_RECV);
    pm.config(b ? (pm.config() | of13::OFPPC_NO_RECV)
                : (pm.config() & ~of13::OFPPC_NO_RECV));
    return this;
}

auto PortModImpl::no_packet_in(bool b) -> PortModPtr
{
    pm.mask(pm.mask() | of13::OFPPC_NO_PACKET_IN);
    pm.config(b ? (pm.config() | of13::OFPPC_NO_PACKET_IN)
                : (pm.config() & ~of13::OFPPC_NO_PACKET_IN));
    return this;
}

} // namespace runos

ext: cc

max_stars_repo_name: estepanov-lvk/runos

max_issues_repo_name: estepanov-lvk/runos

max_forks_repo_name: estepanov-lvk/runos


text:
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include "NetworkQuantizationScheme.hpp"

#include <armnn/Tensor.hpp>
#include <armnn/TypesUtils.hpp>
#include <armnn/ILayerVisitor.hpp>

#include <utility>
#include <limits>

#include <boost/assert.hpp>

namespace armnn
{

template<typename srcType>
void QuantizeConstant(const srcType* src, uint8_t* dst, size_t numElements, float& scale, int& offset)
{
    BOOST_ASSERT(src);
    BOOST_ASSERT(dst);

    float min = std::numeric_limits<srcType>::max();
    float max = std::numeric_limits<srcType>::lowest();
    for (size_t i = 0; i < numElements; ++i)
    {
        min = std::min(min, src[i]);
        max = std::max(max, src[i]);
    }

    QAsymm8QuantizationScheme quantizationScheme;
    OffsetScalePair qParams = quantizationScheme.ComputeScheme(min, max);
    scale = qParams.first;
    offset = qParams.second;

    for (size_t i = 0; i < numElements; ++i)
    {
        dst[i] = armnn::Quantize<uint8_t>(src[i], scale, offset);
    }
}

ConstTensor CreateQuantizedConst(const ConstTensor& tensor, std::vector<uint8_t>& backing);

template <typename LayerContainer>
void VisitLayers(const LayerContainer& layerContainer, ILayerVisitor& visitor)
{
    visitor.StartVisit();
    for (auto layer : layerContainer)
    {
        layer->Accept(visitor);
    }
    visitor.FinishVisit();
}

} // namespace armnn

max_stars_repo_name: VinayKarnam/armnn

max_issues_repo_name: VinayKarnam/armnn

max_forks_repo_name: VinayKarnam/armnn


text:
#include "program_options.hpp"
#include "trade_stream_maker.hpp"
#include "wscc_trade_stream.hpp"

#include <boost/program_options.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace profitview
{

struct ProgramArgs
{
    std::string exchange;
    std::vector<std::string> symbols;

    void addOptions(boost::program_options::options_description& options)
    {
        namespace po = boost::program_options;
        // clang-format off
        options.add_options()
            ("exchange", po::value(&exchange)->required(), "Crypto Exchange to execute on.")
            ("symbols", po::value(&symbols)->multitoken()->required(), "Symbols for cypto assets to trade.");
        // clang-format on
    }
};

}    // namespace profitview

int main(int argc, char* argv[])
{
    using namespace profitview;
    ProgramArgs options;
    auto const result = profitview::parseProgramOptions(argc, argv, options);
    if (result)
        return result.value();

    auto stream {TradeStreamMaker::register_stream<WSCcTradeStream>("WSCcStream")};
    stream->subscribe(options.exchange, options.symbols);

    std::cout << "Press enter to quit" << std::endl;
    std::cin.get();
}