<commit_before>/**
 * This file defines facilities to perform concept-based overloading.
 */

#ifndef DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP
#define DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP

#include <duck/detail/mpl_extensions.hpp>

#include <boost/mpl/and.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/copy_if.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/quote.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>

namespace duck {

// Note to self: Storing the visited concepts in a list ordered by concept
//               specificity could make things much more efficient.

/**
 * Tag to signal the failure of a concept-based overload resolution.
 *
 * @note It is important that this stays an incomplete type.
 */
struct concept_based_overload_resolution_failed;

//! Compile-time data structure storing state during an overload resolution.
template <typename Family, typename VisitedConcepts = boost::mpl::vector<> >
struct overload_resolution {
    typedef VisitedConcepts visited_concepts;
    typedef Family family;

    typedef overload_resolution type; // to make it a metafunction
};

//! Metafunction returning whether a `Type` is a model of a given `Concept`.
template <typename Concept, typename Type>
struct models
    : boost::mpl::apply<Concept, Type>
{ };

/**
 * Trait that must be specialized by new concepts to specify a partial order
 * between concepts.
 *
 * @note `is_more_specific_than<A, B>` is conceptually equivalent to `A < B`
 *       where the `<` operator is a partial order meaning `A` is less
 *       specific than `B`.
 */
template <typename A, typename B>
struct is_more_specific_than;

/**
 * Specialization of the `is_more_specific_than` trait for the trivial case
 * where both concepts are the same, i.e. `is_more_specific_than<A, A>`. In
 * this trivial case, the trait is obviously false.
 */
template <typename Concept>
struct is_more_specific_than<Concept, Concept>
    : boost::mpl::false_
{ };

/**
 * Metafunction class returning the result of calling the function overloaded
 * by `Family` at the current stage of the overload resolution.
 *
 * @note This metafunction class may be specialized by each family of
 *       overload, or the family may define a
 *       `perform_overload<OverloadResolution>` nested metafunction class
 *       accepting arguments to perform the overload.
 */
template <typename Family, typename OverloadResolution>
struct perform_overload {
    template <typename ...Args>
    struct apply
        : boost::mpl::apply<
            typename Family::template perform_overload<OverloadResolution>,
            Args...
        >
    { };
};

namespace concept_overload_detail {
/**
 * Add a `Concept` to the list of concepts visited during the current
 * overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct mark_as_visited
    : overload_resolution<
        typename OverloadResolution::family,
        typename boost::mpl::push_front<
            typename OverloadResolution::visited_concepts, Concept
        >::type
    >
{ };

/**
 * Metafunction returning whether a `Concept` has already been visited during
 * the current overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct has_visited
    : boost::mpl::contains<
        typename OverloadResolution::visited_concepts, Concept
    >
{ };

/**
 * Metafunction returning whether a `Concept` is the most specific that was
 * visited so far during an overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct is_most_specific_so_far
    : boost::mpl::none_of<
        typename OverloadResolution::visited_concepts,
        is_more_specific_than<Concept, boost::mpl::_1>
    >
{ };

/**
 * Metafunction returning whether a `Concept` is the best match for a `Type`
 * so far during an overload resolution.
 */
template <typename Type, typename Concept, typename OverloadResolution>
struct is_best_match_so_far
    : boost::mpl::and_<
        boost::mpl::not_<has_visited<Concept, OverloadResolution> >,
        is_most_specific_so_far<Concept, OverloadResolution>,
        models<Concept, Type>
    >
{ };

/**
 * Metafunction class returning whether a `Concept` is the most specific
 * concept modeled by a `Type` for which an overload exists according to
 * the family present in `OverloadResolution`.
 */
template <typename Type, typename Concept, typename OverloadResolution>
class clause_passes {
    template <typename ...Args>
    struct result_of_calling_the_function_with
        : boost::mpl::apply<
            perform_overload<
                typename OverloadResolution::family,
                typename mark_as_visited<Concept, OverloadResolution>::type
            >,
            Args...
        >
    { };

    template <typename ...Args>
    struct there_are_no_better_overloads
        : boost::is_same<
            typename result_of_calling_the_function_with<Args...>::type,
            concept_based_overload_resolution_failed
        >
    { };

public:
    template <typename ...Args>
    struct apply
        : boost::mpl::and_<
            is_best_match_so_far<Type, Concept, OverloadResolution>,
            there_are_no_better_overloads<Args...>
        >
    { };
};

//! Requires a `Type` to be a model of a `Concept` in a `require` clause.
template <typename Concept, typename Type> struct model_of {
    typedef Concept concept;
    typedef Type model;
};

template <typename T>
struct is_model_of_clause
    : boost::mpl::false_
{ };

template <typename Concept, typename Type>
struct is_model_of_clause<model_of<Concept, Type> >
    : boost::mpl::true_
{ };

//! Provides the current `OverloadResolution` state to a `require` clause.
template <typename Family>
struct overload_resolution_state {
    typedef overload_resolution<Family> type;
};

template <typename ...Args>
struct overload_resolution_state<overload_resolution<Args...> > {
    typedef overload_resolution<Args...> type;
};

template <typename T>
struct is_overload_resolution_state
    : boost::mpl::false_
{ };

template <typename OverloadResolution>
struct is_overload_resolution_state<
                            overload_resolution_state<OverloadResolution> >
    : boost::mpl::true_
{ };

/**
 * Provides the template parameters to pass to the next function that will be
 * tried in the same overload family.
 *
 * @note The overload information is handled by the library and must not be
 *       passed here.
 */
template <typename ...Params> struct template_parameters;

template <typename T>
struct is_template_parameters
    : boost::mpl::false_
{ };

template <typename ...Params>
struct is_template_parameters<template_parameters<Params...> >
    : boost::mpl::true_
{ };

template <typename ...Blob>
struct requires_impl {
    template <typename F, typename Pack> struct apply_pack;
    template <typename F, template <typename ...> class Pack, typename ...Args>
    struct apply_pack<F, Pack<Args...> >
        : boost::mpl::apply<F, Args...>
    { };

    typedef typename boost::mpl::back<
                boost::mpl::vector<Blob...>
            >::type return_type;

    typedef typename boost::mpl::pop_back<
                boost::mpl::vector<Blob...>
            >::type arguments;

    // Gather all the model_of clauses
    typedef typename boost::mpl::copy_if<
                arguments, boost::mpl::quote1<is_model_of_clause>
            >::type clauses;

    // Gather the template parameters to be passed to subsequent overloads
    typedef typename boost::mpl::deref<typename boost::mpl::find_if<
                arguments, boost::mpl::quote1<is_template_parameters>
            >::type>::type template_parameters;

    // Fetch the current overload resolution state
    typedef typename boost::mpl::deref<typename boost::mpl::find_if<
                arguments, boost::mpl::quote1<is_overload_resolution_state>
            >::type>::type::type current_state;

    struct clause_is_respected {
        template <typename Clause>
        struct apply
            : apply_pack<
                clause_passes<
                    typename Clause::model,
                    typename Clause::concept,
                    current_state
                >,
                template_parameters
            >
        { };
    };

    typedef typename boost::mpl::all_of<
                clauses, clause_is_respected
            >::type type;
    static bool const value = type::value;
};
} // end namespace concept_overload_detail

// Named parameters for `requires`
using concept_overload_detail::model_of;
using concept_overload_detail::overload_resolution_state;
using concept_overload_detail::template_parameters;

/**
 * Metafunction to perform concept-based overloading.
 *
 * Examples of usage:
 *
 *      typename requires<
 *                  model_of<SomeConcept, SomeType>,
 *                  model_of<SomeOtherConcept, SomeOtherType>,
 *
 *                  overload_resolution_state<State>,
 *                  template_parameters<SomeType, SomeOtherType>,
 *                  return_type
 *      >::type
 */
template <typename ...Args>
struct requires
    : boost::enable_if<
        concept_overload_detail::requires_impl<Args...>,
        typename concept_overload_detail::requires_impl<Args...>::return_type
    >
{ };

/**
 * Macro to enable concept overloading on a family of overloads.
 *
 * @param FUNCTION The name of the function that is overloaded using concepts.
 * @param CALL An expression calling the function. This expression can use
 *        the templates parameters provided in `__VA_ARGS__`.
 * @param ... A list of `typename T` template parameters that will be usable
 *            within the `CALL` expression. The `State` parameter is always
 *            available within the `CALL` expression and it represents the
 *            current state of the overload resolution.
 *
 * Once instantiated, this macro will create a type named `FUNCTION` inside a
 * `tag` namespace. This type should be used as the default overload
 * resolution state for overloads within this family.
 */
#define DUCK_ENABLE_CONCEPT_OVERLOADING(FUNCTION, CALL, .../*typenames*/)   \
    ::duck::concept_based_overload_resolution_failed FUNCTION(...);         \
    namespace tag {                                                         \
        /* We can't call the structure FUNCTION because it would clash */   \
        /* with the CALL expansion. */                                      \
        struct BOOST_PP_CAT(FUNCTION, _tag) {                               \
            template <typename State>                                       \
            struct perform_overload {                                       \
                template <__VA_ARGS__>                                      \
                struct apply {                                              \
                    typedef decltype(CALL) type;                            \
                };                                                          \
            };                                                              \
        };                                                                  \
        /* Now we can make the alias */                                     \
        typedef BOOST_PP_CAT(FUNCTION, _tag) FUNCTION;                      \
    }                                                                       \
/**/

} // end namespace duck

#endif // !DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP
<commit_msg>Transform a compile-time error into a link-time error on GCC until it accepts incomplete types in decltype.<commit_after>/**
 * This file defines facilities to perform concept-based overloading.
 */

#ifndef DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP
#define DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP

#include <duck/detail/mpl_extensions.hpp>

#include <boost/config.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/copy_if.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/quote.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>

namespace duck {

// Note to self: Storing the visited concepts in a list ordered by concept
//               specificity could make things much more efficient.

/**
 * Tag to signal the failure of a concept-based overload resolution.
 *
 * @note It is important that this stays an incomplete type.
 */
struct concept_based_overload_resolution_failed
#if defined(BOOST_NO_CXX11_DECLTYPE_N3276)
{
    // On GCC, incomplete types can't appear inside decltype.
    // Instead of failing on valid decltypes, we will trigger a link time
    // error when `concept_based_overload_resolution_failed` is used.
    ~concept_based_overload_resolution_failed();
}
#endif
;

//! Compile-time data structure storing state during an overload resolution.
template <typename Family, typename VisitedConcepts = boost::mpl::vector<> >
struct overload_resolution {
    typedef VisitedConcepts visited_concepts;
    typedef Family family;

    typedef overload_resolution type; // to make it a metafunction
};

//! Metafunction returning whether a `Type` is a model of a given `Concept`.
template <typename Concept, typename Type>
struct models
    : boost::mpl::apply<Concept, Type>
{ };

/**
 * Trait that must be specialized by new concepts to specify a partial order
 * between concepts.
 *
 * @note `is_more_specific_than<A, B>` is conceptually equivalent to `A < B`
 *       where the `<` operator is a partial order meaning `A` is less
 *       specific than `B`.
 */
template <typename A, typename B>
struct is_more_specific_than;

/**
 * Specialization of the `is_more_specific_than` trait for the trivial case
 * where both concepts are the same, i.e. `is_more_specific_than<A, A>`. In
 * this trivial case, the trait is obviously false.
 */
template <typename Concept>
struct is_more_specific_than<Concept, Concept>
    : boost::mpl::false_
{ };

/**
 * Metafunction class returning the result of calling the function overloaded
 * by `Family` at the current stage of the overload resolution.
 *
 * @note This metafunction class may be specialized by each family of
 *       overload, or the family may define a
 *       `perform_overload<OverloadResolution>` nested metafunction class
 *       accepting arguments to perform the overload.
 */
template <typename Family, typename OverloadResolution>
struct perform_overload {
    template <typename ...Args>
    struct apply
        : boost::mpl::apply<
            typename Family::template perform_overload<OverloadResolution>,
            Args...
        >
    { };
};

namespace concept_overload_detail {
/**
 * Add a `Concept` to the list of concepts visited during the current
 * overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct mark_as_visited
    : overload_resolution<
        typename OverloadResolution::family,
        typename boost::mpl::push_front<
            typename OverloadResolution::visited_concepts, Concept
        >::type
    >
{ };

/**
 * Metafunction returning whether a `Concept` has already been visited during
 * the current overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct has_visited
    : boost::mpl::contains<
        typename OverloadResolution::visited_concepts, Concept
    >
{ };

/**
 * Metafunction returning whether a `Concept` is the most specific that was
 * visited so far during an overload resolution.
 */
template <typename Concept, typename OverloadResolution>
struct is_most_specific_so_far
    : boost::mpl::none_of<
        typename OverloadResolution::visited_concepts,
        is_more_specific_than<Concept, boost::mpl::_1>
    >
{ };

/**
 * Metafunction returning whether a `Concept` is the best match for a `Type`
 * so far during an overload resolution.
 */
template <typename Type, typename Concept, typename OverloadResolution>
struct is_best_match_so_far
    : boost::mpl::and_<
        boost::mpl::not_<has_visited<Concept, OverloadResolution> >,
        is_most_specific_so_far<Concept, OverloadResolution>,
        models<Concept, Type>
    >
{ };

/**
 * Metafunction class returning whether a `Concept` is the most specific
 * concept modeled by a `Type` for which an overload exists according to
 * the family present in `OverloadResolution`.
 */
template <typename Type, typename Concept, typename OverloadResolution>
class clause_passes {
    template <typename ...Args>
    struct result_of_calling_the_function_with
        : boost::mpl::apply<
            perform_overload<
                typename OverloadResolution::family,
                typename mark_as_visited<Concept, OverloadResolution>::type
            >,
            Args...
        >
    { };

    template <typename ...Args>
    struct there_are_no_better_overloads
        : boost::is_same<
            typename result_of_calling_the_function_with<Args...>::type,
            concept_based_overload_resolution_failed
        >
    { };

public:
    template <typename ...Args>
    struct apply
        : boost::mpl::and_<
            is_best_match_so_far<Type, Concept, OverloadResolution>,
            there_are_no_better_overloads<Args...>
        >
    { };
};

//! Requires a `Type` to be a model of a `Concept` in a `require` clause.
template <typename Concept, typename Type> struct model_of {
    typedef Concept concept;
    typedef Type model;
};

template <typename T>
struct is_model_of_clause
    : boost::mpl::false_
{ };

template <typename Concept, typename Type>
struct is_model_of_clause<model_of<Concept, Type> >
    : boost::mpl::true_
{ };

//! Provides the current `OverloadResolution` state to a `require` clause.
template <typename Family>
struct overload_resolution_state {
    typedef overload_resolution<Family> type;
};

template <typename ...Args>
struct overload_resolution_state<overload_resolution<Args...> > {
    typedef overload_resolution<Args...> type;
};

template <typename T>
struct is_overload_resolution_state
    : boost::mpl::false_
{ };

template <typename OverloadResolution>
struct is_overload_resolution_state<
                            overload_resolution_state<OverloadResolution> >
    : boost::mpl::true_
{ };

/**
 * Provides the template parameters to pass to the next function that will be
 * tried in the same overload family.
 *
 * @note The overload information is handled by the library and must not be
 *       passed here.
 */
template <typename ...Params> struct template_parameters;

template <typename T>
struct is_template_parameters
    : boost::mpl::false_
{ };

template <typename ...Params>
struct is_template_parameters<template_parameters<Params...> >
    : boost::mpl::true_
{ };

template <typename ...Blob>
struct requires_impl {
    template <typename F, typename Pack> struct apply_pack;
    template <typename F, template <typename ...> class Pack, typename ...Args>
    struct apply_pack<F, Pack<Args...> >
        : boost::mpl::apply<F, Args...>
    { };

    typedef typename boost::mpl::back<
                boost::mpl::vector<Blob...>
            >::type return_type;

    typedef typename boost::mpl::pop_back<
                boost::mpl::vector<Blob...>
            >::type arguments;

    // Gather all the model_of clauses
    typedef typename boost::mpl::copy_if<
                arguments, boost::mpl::quote1<is_model_of_clause>
            >::type clauses;

    // Gather the template parameters to be passed to subsequent overloads
    typedef typename boost::mpl::deref<typename boost::mpl::find_if<
                arguments, boost::mpl::quote1<is_template_parameters>
            >::type>::type template_parameters;

    // Fetch the current overload resolution state
    typedef typename boost::mpl::deref<typename boost::mpl::find_if<
                arguments, boost::mpl::quote1<is_overload_resolution_state>
            >::type>::type::type current_state;

    struct clause_is_respected {
        template <typename Clause>
        struct apply
            : apply_pack<
                clause_passes<
                    typename Clause::model,
                    typename Clause::concept,
                    current_state
                >,
                template_parameters
            >
        { };
    };

    typedef typename boost::mpl::all_of<
                clauses, clause_is_respected
            >::type type;
    static bool const value = type::value;
};
} // end namespace concept_overload_detail

// Named parameters for `requires`
using concept_overload_detail::model_of;
using concept_overload_detail::overload_resolution_state;
using concept_overload_detail::template_parameters;

/**
 * Metafunction to perform concept-based overloading.
 *
 * Examples of usage:
 *
 *      typename requires<
 *                  model_of<SomeConcept, SomeType>,
 *                  model_of<SomeOtherConcept, SomeOtherType>,
 *
 *                  overload_resolution_state<State>,
 *                  template_parameters<SomeType, SomeOtherType>,
 *                  return_type
 *      >::type
 */
template <typename ...Args>
struct requires
    : boost::enable_if<
        concept_overload_detail::requires_impl<Args...>,
        typename concept_overload_detail::requires_impl<Args...>::return_type
    >
{ };

/**
 * Macro to enable concept overloading on a family of overloads.
 *
 * @param FUNCTION The name of the function that is overloaded using concepts.
 * @param CALL An expression calling the function. This expression can use
 *        the templates parameters provided in `__VA_ARGS__`.
 * @param ... A list of `typename T` template parameters that will be usable
 *            within the `CALL` expression. The `State` parameter is always
 *            available within the `CALL` expression and it represents the
 *            current state of the overload resolution.
 *
 * Once instantiated, this macro will create a type named `FUNCTION` inside a
 * `tag` namespace. This type should be used as the default overload
 * resolution state for overloads within this family.
 */
#define DUCK_ENABLE_CONCEPT_OVERLOADING(FUNCTION, CALL, .../*typenames*/)   \
    ::duck::concept_based_overload_resolution_failed FUNCTION(...);         \
    namespace tag {                                                         \
        /* We can't call the structure FUNCTION because it would clash */   \
        /* with the CALL expansion. */                                      \
        struct BOOST_PP_CAT(FUNCTION, _tag) {                               \
            template <typename State>                                       \
            struct perform_overload {                                       \
                template <__VA_ARGS__>                                      \
                struct apply {                                              \
                    typedef decltype(CALL) type;                            \
                };                                                          \
            };                                                              \
        };                                                                  \
        /* Now we can make the alias */                                     \
        typedef BOOST_PP_CAT(FUNCTION, _tag) FUNCTION;                      \
    }                                                                       \
/**/

} // end namespace duck

#endif // !DUCK_SANDBOX_CONCEPT_OVERLOAD_HPP
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014-2015 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPP_UTILS_TMP_HPP
#define CPP_UTILS_TMP_HPP

namespace cpp {

namespace static_if_detail {

struct identity {
    template<typename T>
    T operator()(T&& x) const {
        return std::forward<T>(x);
    }
};

template<bool Cond>
struct statement {
    template<typename F>
    void then(const F& f){
        f(identity());
    }

    template<typename F>
    void else_(const F&){}
};

template<>
struct statement<false> {
    template<typename F>
    void then(const F&){}

    template<typename F>
    void else_(const F& f){
        f(identity());
    }
};

} //end of namespace static_if_detail

template<bool Cond, typename F>
static_if_detail::statement<Cond> static_if(F const& f){
    static_if_detail::statement<Cond> if_;
    if_.then(f);
    return if_;
}

} //end of namespace cpp

#endif //CPP_UTILS_TMP_HPP
<commit_msg>Fix header guard<commit_after>//=======================================================================
// Copyright (c) 2013-2014-2015 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPP_STATIC_IF_HPP
#define CPP_STATIC_IF_HPP

namespace cpp {

namespace static_if_detail {

struct identity {
    template<typename T>
    T operator()(T&& x) const {
        return std::forward<T>(x);
    }
};

template<bool Cond>
struct statement {
    template<typename F>
    void then(const F& f){
        f(identity());
    }

    template<typename F>
    void else_(const F&){}
};

template<>
struct statement<false> {
    template<typename F>
    void then(const F&){}

    template<typename F>
    void else_(const F& f){
        f(identity());
    }
};

} //end of namespace static_if_detail

template<bool Cond, typename F>
static_if_detail::statement<Cond> static_if(F const& f){
    static_if_detail::statement<Cond> if_;
    if_.then(f);
    return if_;
}

} //end of namespace cpp

#endif //CPP_STATIC_IF_HPP
<|endoftext|>


<commit_before>
#include "FlareTradeRouteInfo.h"
#include "../../Flare.h"
#include "../../Game/FlareGameTools.h"
#include "../../Game/FlareCompany.h"
#include "../../Game/FlareTradeRoute.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"
#include "../../Game/FlareGame.h"

#define LOCTEXT_NAMESPACE "FlareTradeRouteInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareTradeRouteInfo::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Build structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	[
		SNew(SBox)
		.WidthOverride(Theme.ContentWidth)
		.HAlign(HAlign_Fill)
		[
			SNew(SVerticalBox)

			// Trade routes title
			+ SVerticalBox::Slot()
			.Padding(Theme.TitlePadding)
			.AutoHeight()
			[
				SNew(STextBlock)
				.Text(LOCTEXT("Trade routes", "Trade routes"))
				.TextStyle(&Theme.SubTitleFont)
			]

			// New trade route button
			+ SVerticalBox::Slot()
			.AutoHeight()
			.Padding(Theme.ContentPadding)
			.HAlign(HAlign_Left)
			[
				SNew(SFlareButton)
				.Width(8)
				.Text(LOCTEXT("NewTradeRouteButton", "Add new trade route"))
				.HelpText(LOCTEXT("NewTradeRouteInfo", "Create a new trade route and edit it. You need an available fleet to create a new trade route."))
				.Icon(FFlareStyleSet::GetIcon("New"))
				.OnClicked(this, &SFlareTradeRouteInfo::OnNewTradeRouteClicked)
				.IsDisabled(this, &SFlareTradeRouteInfo::IsNewTradeRouteDisabled)
			]

			// Trade route list
			+ SVerticalBox::Slot()
			.HAlign(HAlign_Left)
			.AutoHeight()
			[
				SNew(SScrollBox)
				.Style(&Theme.ScrollBoxStyle)
				.ScrollBarStyle(&Theme.ScrollBarStyle)
				+ SScrollBox::Slot()
				[
					SAssignNew(TradeRouteList, SVerticalBox)
				]
			]
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareTradeRouteInfo::UpdateTradeRouteList()
{
	Clear();
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TArray<UFlareTradeRoute*>& TradeRoutes = MenuManager->GetPC()->GetCompany()->GetCompanyTradeRoutes();

	for (int RouteIndex = 0; RouteIndex < TradeRoutes.Num(); RouteIndex++)
	{
		UFlareTradeRoute* TradeRoute = TradeRoutes[RouteIndex];

		// Add line
		TradeRouteList->AddSlot()
		.AutoHeight()
		.HAlign(HAlign_Right)
		.Padding(Theme.ContentPadding)
		[
			SNew(SVerticalBox)

			// Buttons
			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SHorizontalBox)

				// Inspect
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Width(6)
					.Text(this, &SFlareTradeRouteInfo::GetTradeRouteName, TradeRoute)
					.HelpText(FText(LOCTEXT("InspectHelp", "Edit this trade route")))
					.OnClicked(this, &SFlareTradeRouteInfo::OnInspectTradeRouteClicked, TradeRoute)
				]

				// Pause
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Transparent(true)
					.Text(FText())
					.HelpText(LOCTEXT("PauseTradeRouteHelp", "Pause or restart this trade route"))
					.Icon(this, &SFlareTradeRouteInfo::GetTogglePauseTradeRouteIcon, TradeRoute)
					.OnClicked(this, &SFlareTradeRouteInfo::OnTogglePauseTradeRoute, TradeRoute)
					.Width(1)
				]

				// Remove
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Transparent(true)
					.Text(FText())
					.HelpText(LOCTEXT("RemoveTradeRouteHelp", "Remove this trade route"))
					.Icon(FFlareStyleSet::GetIcon("Stop"))
					.OnClicked(this, &SFlareTradeRouteInfo::OnDeleteTradeRoute, TradeRoute)
					.Width(1)
				]
			]

			// Infos
			+ SVerticalBox::Slot()
			.AutoHeight()
			.Padding(Theme.SmallContentPadding)
			[
				SNew(SRichTextBlock)
				.TextStyle(&Theme.TextFont)
				.Text(this, &SFlareTradeRouteInfo::GetDetailText, TradeRoute)
				.WrapTextAt(Theme.ContentWidth / 2)
				.DecoratorStyleSet(&FFlareStyleSet::Get())
			]
		];
	}
}

void SFlareTradeRouteInfo::Clear()
{
	TradeRouteList->ClearChildren();
}

FText SFlareTradeRouteInfo::GetDetailText(UFlareTradeRoute* TradeRoute) const
{
	FCHECK(TradeRoute);
	const FFlareTradeRouteSave* TradeRouteData = TradeRoute->Save();
	FCHECK(TradeRouteData);

	// Get data
	int32 TotalOperations = TradeRouteData->StatsOperationSuccessCount + TradeRouteData->StatsOperationFailCount;
	int32 SuccessPercentage = (TotalOperations > 0) ? (FMath::RoundToInt(100.0f * TradeRouteData->StatsOperationSuccessCount / float(TotalOperations))) : 0;
	int32 CreditsGain = (TradeRouteData->StatsDays > 0) ? (FMath::RoundToInt(0.01f * float(TradeRouteData->StatsMoneySell - TradeRouteData->StatsMoneyBuy) / float(TradeRouteData->StatsDays))) : 0;

	// Format result
	if (CreditsGain > 0)
	{
		return UFlareGameTools::AddLeadingSpace(FText::Format(LOCTEXT("TradeRouteDetailsGain", "<TradeText>{0} credits per day, {1}% OK</>"),
			FText::AsNumber(CreditsGain),
			FText::AsNumber(SuccessPercentage)),
			3);
	}
	else
	{
		return UFlareGameTools::AddLeadingSpace(FText::Format(LOCTEXT("TradeRouteDetailsLoss", "<WarningText>{0} credits per day</>, {1}% OK"),
			FText::AsNumber(CreditsGain),
			FText::AsNumber(SuccessPercentage)),
			3);
	}
}

bool SFlareTradeRouteInfo::IsNewTradeRouteDisabled() const
{
	int32 FleetCount = 0;
	TArray<UFlareFleet*>& Fleets = MenuManager->GetGame()->GetPC()->GetCompany()->GetCompanyFleets();

	for (int FleetIndex = 0; FleetIndex < Fleets.Num(); FleetIndex++)
	{
		if (!Fleets[FleetIndex]->GetCurrentTradeRoute() && Fleets[FleetIndex] != MenuManager->GetPC()->GetPlayerFleet())
		{
			FleetCount++;
		}
	}

	return (FleetCount == 0);
}

void SFlareTradeRouteInfo::OnNewTradeRouteClicked()
{
	UFlareTradeRoute* TradeRoute = MenuManager->GetPC()->GetCompany()->CreateTradeRoute(LOCTEXT("UntitledRoute", "Untitled Route"));
	FCHECK(TradeRoute);

	FFlareMenuParameterData Data;
	Data.Route = TradeRoute;
	MenuManager->OpenMenu(EFlareMenu::MENU_TradeRoute, Data);
}

void SFlareTradeRouteInfo::OnInspectTradeRouteClicked(UFlareTradeRoute* TradeRoute)
{
	FFlareMenuParameterData Data;
	Data.Route = TradeRoute;
	MenuManager->OpenMenu(EFlareMenu::MENU_TradeRoute, Data);
}

void SFlareTradeRouteInfo::OnDeleteTradeRoute(UFlareTradeRoute* TradeRoute)
{
	MenuManager->Confirm(LOCTEXT("AreYouSure", "ARE YOU SURE ?"),
		LOCTEXT("ConfirmDeleteTR", "Do you really want to remove this trade route ?"),
		FSimpleDelegate::CreateSP(this, &SFlareTradeRouteInfo::OnDeleteTradeRouteConfirmed, TradeRoute));
}

void SFlareTradeRouteInfo::OnDeleteTradeRouteConfirmed(UFlareTradeRoute* TradeRoute)
{
	FCHECK(TradeRoute);
	TradeRoute->Dissolve();
	UpdateTradeRouteList();
}

FText SFlareTradeRouteInfo::GetTradeRouteName(UFlareTradeRoute* TradeRoute) const
{
	return FText::Format(LOCTEXT("TradeRouteNameFormat", "{0}{1}"),
		TradeRoute->GetTradeRouteName(),
		(TradeRoute->IsPaused() ? UFlareGameTools::AddLeadingSpace(LOCTEXT("FleetTradeRoutePausedFormat", "(Paused)")) : FText()));
}

const FSlateBrush* SFlareTradeRouteInfo::GetTogglePauseTradeRouteIcon(UFlareTradeRoute* TradeRoute) const
{
	if (TradeRoute->IsPaused())
	{
		return FFlareStyleSet::GetIcon("Load");
	}
	else
	{
		return FFlareStyleSet::GetIcon("Pause");
	}
}

void SFlareTradeRouteInfo::OnTogglePauseTradeRoute(UFlareTradeRoute* TradeRoute)
{
	TradeRoute->SetPaused(!TradeRoute->IsPaused());
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Fix build<commit_after>
#include "FlareTradeRouteInfo.h"
#include "../../Flare.h"
#include "../../Game/FlareGameTools.h"
#include "../../Game/FlareCompany.h"
#include "../../Game/FlareGameTools.h"
#include "../../Game/FlareTradeRoute.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"
#include "../../Game/FlareGame.h"

#define LOCTEXT_NAMESPACE "FlareTradeRouteInfo"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareTradeRouteInfo::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	// Build structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	[
		SNew(SBox)
		.WidthOverride(Theme.ContentWidth)
		.HAlign(HAlign_Fill)
		[
			SNew(SVerticalBox)

			// Trade routes title
			+ SVerticalBox::Slot()
			.Padding(Theme.TitlePadding)
			.AutoHeight()
			[
				SNew(STextBlock)
				.Text(LOCTEXT("Trade routes", "Trade routes"))
				.TextStyle(&Theme.SubTitleFont)
			]

			// New trade route button
			+ SVerticalBox::Slot()
			.AutoHeight()
			.Padding(Theme.ContentPadding)
			.HAlign(HAlign_Left)
			[
				SNew(SFlareButton)
				.Width(8)
				.Text(LOCTEXT("NewTradeRouteButton", "Add new trade route"))
				.HelpText(LOCTEXT("NewTradeRouteInfo", "Create a new trade route and edit it. You need an available fleet to create a new trade route."))
				.Icon(FFlareStyleSet::GetIcon("New"))
				.OnClicked(this, &SFlareTradeRouteInfo::OnNewTradeRouteClicked)
				.IsDisabled(this, &SFlareTradeRouteInfo::IsNewTradeRouteDisabled)
			]

			// Trade route list
			+ SVerticalBox::Slot()
			.HAlign(HAlign_Left)
			.AutoHeight()
			[
				SNew(SScrollBox)
				.Style(&Theme.ScrollBoxStyle)
				.ScrollBarStyle(&Theme.ScrollBarStyle)
				+ SScrollBox::Slot()
				[
					SAssignNew(TradeRouteList, SVerticalBox)
				]
			]
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareTradeRouteInfo::UpdateTradeRouteList()
{
	Clear();
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TArray<UFlareTradeRoute*>& TradeRoutes = MenuManager->GetPC()->GetCompany()->GetCompanyTradeRoutes();

	for (int RouteIndex = 0; RouteIndex < TradeRoutes.Num(); RouteIndex++)
	{
		UFlareTradeRoute* TradeRoute = TradeRoutes[RouteIndex];

		// Add line
		TradeRouteList->AddSlot()
		.AutoHeight()
		.HAlign(HAlign_Right)
		.Padding(Theme.ContentPadding)
		[
			SNew(SVerticalBox)

			// Buttons
			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SHorizontalBox)

				// Inspect
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Width(6)
					.Text(this, &SFlareTradeRouteInfo::GetTradeRouteName, TradeRoute)
					.HelpText(FText(LOCTEXT("InspectHelp", "Edit this trade route")))
					.OnClicked(this, &SFlareTradeRouteInfo::OnInspectTradeRouteClicked, TradeRoute)
				]

				// Pause
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Transparent(true)
					.Text(FText())
					.HelpText(LOCTEXT("PauseTradeRouteHelp", "Pause or restart this trade route"))
					.Icon(this, &SFlareTradeRouteInfo::GetTogglePauseTradeRouteIcon, TradeRoute)
					.OnClicked(this, &SFlareTradeRouteInfo::OnTogglePauseTradeRoute, TradeRoute)
					.Width(1)
				]

				// Remove
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SFlareButton)
					.Transparent(true)
					.Text(FText())
					.HelpText(LOCTEXT("RemoveTradeRouteHelp", "Remove this trade route"))
					.Icon(FFlareStyleSet::GetIcon("Stop"))
					.OnClicked(this, &SFlareTradeRouteInfo::OnDeleteTradeRoute, TradeRoute)
					.Width(1)
				]
			]

			// Infos
			+ SVerticalBox::Slot()
			.AutoHeight()
			.Padding(Theme.SmallContentPadding)
			[
				SNew(SRichTextBlock)
				.TextStyle(&Theme.TextFont)
				.Text(this, &SFlareTradeRouteInfo::GetDetailText, TradeRoute)
				.WrapTextAt(Theme.ContentWidth / 2)
				.DecoratorStyleSet(&FFlareStyleSet::Get())
			]
		];
	}
}

void SFlareTradeRouteInfo::Clear()
{
	TradeRouteList->ClearChildren();
}

FText SFlareTradeRouteInfo::GetDetailText(UFlareTradeRoute* TradeRoute) const
{
	FCHECK(TradeRoute);
	const FFlareTradeRouteSave* TradeRouteData = TradeRoute->Save();
	FCHECK(TradeRouteData);

	// Get data
	int32 TotalOperations = TradeRouteData->StatsOperationSuccessCount + TradeRouteData->StatsOperationFailCount;
	int32 SuccessPercentage = (TotalOperations > 0) ? (FMath::RoundToInt(100.0f * TradeRouteData->StatsOperationSuccessCount / float(TotalOperations))) : 0;
	int32 CreditsGain = (TradeRouteData->StatsDays > 0) ? (FMath::RoundToInt(0.01f * float(TradeRouteData->StatsMoneySell - TradeRouteData->StatsMoneyBuy) / float(TradeRouteData->StatsDays))) : 0;

	// Format result
	if (CreditsGain > 0)
	{
		return UFlareGameTools::AddLeadingSpace(FText::Format(LOCTEXT("TradeRouteDetailsGain", "<TradeText>{0} credits per day, {1}% OK</>"),
			FText::AsNumber(CreditsGain),
			FText::AsNumber(SuccessPercentage)),
			3);
	}
	else
	{
		return UFlareGameTools::AddLeadingSpace(FText::Format(LOCTEXT("TradeRouteDetailsLoss", "<WarningText>{0} credits per day</>, {1}% OK"),
			FText::AsNumber(CreditsGain),
			FText::AsNumber(SuccessPercentage)),
			3);
	}
}

bool SFlareTradeRouteInfo::IsNewTradeRouteDisabled() const
{
	int32 FleetCount = 0;
	TArray<UFlareFleet*>& Fleets = MenuManager->GetGame()->GetPC()->GetCompany()->GetCompanyFleets();

	for (int FleetIndex = 0; FleetIndex < Fleets.Num(); FleetIndex++)
	{
		if (!Fleets[FleetIndex]->GetCurrentTradeRoute() && Fleets[FleetIndex] != MenuManager->GetPC()->GetPlayerFleet())
		{
			FleetCount++;
		}
	}

	return (FleetCount == 0);
}

void SFlareTradeRouteInfo::OnNewTradeRouteClicked()
{
	UFlareTradeRoute* TradeRoute = MenuManager->GetPC()->GetCompany()->CreateTradeRoute(LOCTEXT("UntitledRoute", "Untitled Route"));
	FCHECK(TradeRoute);

	FFlareMenuParameterData Data;
	Data.Route = TradeRoute;
	MenuManager->OpenMenu(EFlareMenu::MENU_TradeRoute, Data);
}

void SFlareTradeRouteInfo::OnInspectTradeRouteClicked(UFlareTradeRoute* TradeRoute)
{
	FFlareMenuParameterData Data;
	Data.Route = TradeRoute;
	MenuManager->OpenMenu(EFlareMenu::MENU_TradeRoute, Data);
}

void SFlareTradeRouteInfo::OnDeleteTradeRoute(UFlareTradeRoute* TradeRoute)
{
	MenuManager->Confirm(LOCTEXT("AreYouSure", "ARE YOU SURE ?"),
		LOCTEXT("ConfirmDeleteTR", "Do you really want to remove this trade route ?"),
		FSimpleDelegate::CreateSP(this, &SFlareTradeRouteInfo::OnDeleteTradeRouteConfirmed, TradeRoute));
}

void SFlareTradeRouteInfo::OnDeleteTradeRouteConfirmed(UFlareTradeRoute* TradeRoute)
{
	FCHECK(TradeRoute);
	TradeRoute->Dissolve();
	UpdateTradeRouteList();
}

FText SFlareTradeRouteInfo::GetTradeRouteName(UFlareTradeRoute* TradeRoute) const
{
	return FText::Format(LOCTEXT("TradeRouteNameFormat", "{0}{1}"),
		TradeRoute->GetTradeRouteName(),
		(TradeRoute->IsPaused() ? UFlareGameTools::AddLeadingSpace(LOCTEXT("FleetTradeRoutePausedFormat", "(Paused)")) : FText()));
}

const FSlateBrush* SFlareTradeRouteInfo::GetTogglePauseTradeRouteIcon(UFlareTradeRoute* TradeRoute) const
{
	if (TradeRoute->IsPaused())
	{
		return FFlareStyleSet::GetIcon("Load");
	}
	else
	{
		return FFlareStyleSet::GetIcon("Pause");
	}
}

void SFlareTradeRouteInfo::OnTogglePauseTradeRoute(UFlareTradeRoute* TradeRoute)
{
	TradeRoute->SetPaused(!TradeRoute->IsPaused());
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>
#include <algorithm>
#include <io/uri.hpp>

using namespace Arabica::io;

namespace {
  const std::string ZERO = "0";
  const std::string PORT_EIGHTY = "80";
  const std::string PORT_443 = "443";

  const std::string SCHEME_HTTP = "http";
  const std::string SCHEME_HTTPS = "https";
  const std::string SCHEME_FILE = "file";

  const std::string COLON = ":";
  const char FORWARD_SLASH = '/';

  const std::string& wellKnownPort(const std::string& scheme)
  {
    if(scheme.empty())
      return ZERO;

    if(scheme == SCHEME_HTTP)
      return PORT_EIGHTY;
    if(scheme == SCHEME_HTTPS)
      return PORT_443;

    return ZERO;
  } // wellKnownPort
} // namespace

URI::URI(const std::string& uri) :
  is_absolute_(false)
{
  parse(uri);
} // URI

URI::URI(const URI& base, const std::string& relativeUrl) :
  scheme_(base.scheme_),
  host_(base.host_),
  path_(base.path_),
  port_(base.port_),
  is_absolute_(base.is_absolute_)
{
  if(!relativeUrl.empty())
  {
    URI relUrl(relativeUrl);
    absolutise(relUrl);
  } // if ...
} // URI

const std::string& URI::port() const
{
  if(port_.empty())
    return wellKnownPort(scheme_);
  return port_;
} // port()

std::string URI::as_string() const
{
  std::string str;
  if(!scheme_.empty())
    str.append(scheme_).append(COLON);
  if(is_absolute_)
    str.append("//");
  if(!host_.empty())
  {
    str.append(host_);
    if(!port_.empty())
      str.append(COLON).append(port_);
  }
  str.append(path_);
  return str;
} // as_string

void fixSlashes(std::string& path)
{
  for(int i = path.find('\\'); i != std::string::npos; i = path.find('\\', i))
    path[i] = FORWARD_SLASH;
} // fixSlashes

void URI::parse(const std::string& uri)
{
  parse_uri(uri);

  is_absolute_ = (!scheme_.empty() && !host_.empty()) ||
    (((scheme_ == SCHEME_FILE) && (!path_.empty())) &&
     ((path_[0] == FORWARD_SLASH) || (path_[1] == ':')));
} // parse

void URI::parse_uri(const std::string& uri)
{
  // I'd like to use something a bit stronger - http://code.google.com/p/uri-grammar/
  // but that would put a Boost Spirit dependence right in the core, which I'm not prepared to do at the moment

  int d = uri.find_first_of(COLON);
  if(d == std::string::npos)
  {
    path_ = uri;
    fixSlashes(path_);
    return;
  } // if ...

  if(d == 1)
  {
    // looks like a windows file path
    path_ = uri;
    fixSlashes(path_);
    scheme_ = SCHEME_FILE;
    return;
  } // if ...

  scheme_ = uri.substr(0, d);

  std::string::const_iterator u = uri.begin() + d;
  std::string::const_iterator ue = uri.end();

  ++u;
  if(*u == FORWARD_SLASH && *(u+1) == FORWARD_SLASH)
  {
    u += 2;
    u = parseAuthority(u, ue);
  } // if ...

  path_.append(u, ue);
} // parse

std::string::const_iterator URI::parseAuthority(const std::string::const_iterator& u,
						const std::string::const_iterator& ue)
{
  std::string::const_iterator slash = std::find(u, ue, FORWARD_SLASH);
  if(slash == ue)
  {
    // ah, this is easy
    host_.append(u, ue);
    return ue;
  } // if(slash == we)

  std::string::const_iterator colon = std::find(u, slash, ':');
  host_.append(u, colon);

  if(colon != slash)
    port_.append(colon+1, slash);

  return slash;
} // parseAuthority

bool compatible_schemes(const std::string& scheme,
			const std::string& relative)
{
  if(scheme.empty() && (relative == "file"))
    return true;
  if(relative.empty())
    return true;
  return (scheme == relative);
} // compatible_schemes

void URI::absolutise(URI& relative)
{
  if((relative.is_absolute()) ||
     !compatible_schemes(scheme_, relative.scheme()))
  {
    swap(relative);
    return;
  }

  if(relative.path_[0] == FORWARD_SLASH)
    path_ = relative.path_;
  else
    combinePath(relative.path_);
} // absolutise

void URI::combinePath(const std::string& relPath)
{
  if(*(path_.rbegin()) != FORWARD_SLASH)
    path_.erase(path_.rfind(FORWARD_SLASH)+1);

  std::string::size_type from = path_.length() - 1;
  path_.append(relPath);

  int dots = path_.find("/../", from);
  while(dots != std::string::npos)
  {
    int preceding_slash = (dots > 0) ? path_.rfind(FORWARD_SLASH, dots-1) : 0;
    path_.erase(preceding_slash, dots+3-preceding_slash);
    dots = path_.find("/../", preceding_slash);
  } // while

  int dot = path_.find("/./");
  while(dot != std::string::npos)
  {
    path_.erase(dot, 2);
    dot = path_.find("/./", dot);
  }
} // combinePath

<commit_msg>use size_t not int<commit_after>
#include <algorithm>
#include <io/uri.hpp>

using namespace Arabica::io;

namespace {
  const std::string ZERO = "0";
  const std::string PORT_EIGHTY = "80";
  const std::string PORT_443 = "443";

  const std::string SCHEME_HTTP = "http";
  const std::string SCHEME_HTTPS = "https";
  const std::string SCHEME_FILE = "file";

  const std::string COLON = ":";
  const char FORWARD_SLASH = '/';

  const std::string& wellKnownPort(const std::string& scheme)
  {
    if(scheme.empty())
      return ZERO;

    if(scheme == SCHEME_HTTP)
      return PORT_EIGHTY;
    if(scheme == SCHEME_HTTPS)
      return PORT_443;

    return ZERO;
  } // wellKnownPort
} // namespace

URI::URI(const std::string& uri) :
  is_absolute_(false)
{
  parse(uri);
} // URI

URI::URI(const URI& base, const std::string& relativeUrl) :
  scheme_(base.scheme_),
  host_(base.host_),
  path_(base.path_),
  port_(base.port_),
  is_absolute_(base.is_absolute_)
{
  if(!relativeUrl.empty())
  {
    URI relUrl(relativeUrl);
    absolutise(relUrl);
  } // if ...
} // URI

const std::string& URI::port() const
{
  if(port_.empty())
    return wellKnownPort(scheme_);
  return port_;
} // port()

std::string URI::as_string() const
{
  std::string str;
  if(!scheme_.empty())
    str.append(scheme_).append(COLON);
  if(is_absolute_)
    str.append("//");
  if(!host_.empty())
  {
    str.append(host_);
    if(!port_.empty())
      str.append(COLON).append(port_);
  }
  str.append(path_);
  return str;
} // as_string

void fixSlashes(std::string& path)
{
  for(size_t i = path.find('\\'); i != std::string::npos; i = path.find('\\', i))
    path[i] = FORWARD_SLASH;
} // fixSlashes

void URI::parse(const std::string& uri)
{
  parse_uri(uri);

  is_absolute_ = (!scheme_.empty() && !host_.empty()) ||
    (((scheme_ == SCHEME_FILE) && (!path_.empty())) &&
     ((path_[0] == FORWARD_SLASH) || (path_[1] == ':')));
} // parse

void URI::parse_uri(const std::string& uri)
{
  // I'd like to use something a bit stronger - http://code.google.com/p/uri-grammar/
  // but that would put a Boost Spirit dependence right in the core, which I'm not prepared to do at the moment

  size_t d = uri.find_first_of(COLON);
  if(d == std::string::npos)
  {
    path_ = uri;
    fixSlashes(path_);
    return;
  } // if ...

  if(d == 1)
  {
    // looks like a windows file path
    path_ = uri;
    fixSlashes(path_);
    scheme_ = SCHEME_FILE;
    return;
  } // if ...

  scheme_ = uri.substr(0, d);

  std::string::const_iterator u = uri.begin() + d;
  std::string::const_iterator ue = uri.end();

  ++u;
  if(*u == FORWARD_SLASH && *(u+1) == FORWARD_SLASH)
  {
    u += 2;
    u = parseAuthority(u, ue);
  } // if ...

  path_.append(u, ue);
} // parse

std::string::const_iterator URI::parseAuthority(const std::string::const_iterator& u,
						const std::string::const_iterator& ue)
{
  std::string::const_iterator slash = std::find(u, ue, FORWARD_SLASH);
  if(slash == ue)
  {
    // ah, this is easy
    host_.append(u, ue);
    return ue;
  } // if(slash == we)

  std::string::const_iterator colon = std::find(u, slash, ':');
  host_.append(u, colon);

  if(colon != slash)
    port_.append(colon+1, slash);

  return slash;
} // parseAuthority

bool compatible_schemes(const std::string& scheme,
			const std::string& relative)
{
  if(scheme.empty() && (relative == "file"))
    return true;
  if(relative.empty())
    return true;
  return (scheme == relative);
} // compatible_schemes

void URI::absolutise(URI& relative)
{
  if((relative.is_absolute()) ||
     !compatible_schemes(scheme_, relative.scheme()))
  {
    swap(relative);
    return;
  }

  if(relative.path_[0] == FORWARD_SLASH)
    path_ = relative.path_;
  else
    combinePath(relative.path_);
} // absolutise

void URI::combinePath(const std::string& relPath)
{
  if(*(path_.rbegin()) != FORWARD_SLASH)
    path_.erase(path_.rfind(FORWARD_SLASH)+1);

  std::string::size_type from = path_.length() - 1;
  path_.append(relPath);

  size_t dots = path_.find("/../", from);
  while(dots != std::string::npos)
  {
    int preceding_slash = (dots > 0) ? path_.rfind(FORWARD_SLASH, dots-1) : 0;
    path_.erase(preceding_slash, dots+3-preceding_slash);
    dots = path_.find("/../", preceding_slash);
  } // while

  size_t dot = path_.find("/./");
  while(dot != std::string::npos)
  {
    path_.erase(dot, 2);
    dot = path_.find("/./", dot);
  }
} // combinePath

<|endoftext|>


<commit_before>// Copyright 2008, Google Inc.
// 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 Google Inc. 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 AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER OR CONTRIBUTORS 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.

#include "base/platform_thread.h"

#if defined(OS_POSIX)
#include <errno.h>
#include <sched.h>
#endif

#if defined(OS_MACOSX)
#include <mach/mach.h>
#elif defined(OS_LINUX)
#include <sys/types.h>
#include <unistd.h>
#endif

// static
PlatformThread PlatformThread::Current() {
  PlatformThread thread;

#if defined(OS_WIN)
  thread.thread_ = GetCurrentThread();
#elif defined(OS_POSIX)
  thread.thread_ = pthread_self();
#endif

  return thread;
}

// static
void PlatformThread::YieldCurrentThread() {
#if defined(OS_WIN)
  ::Sleep(0);
#elif defined(OS_POSIX)
  sched_yield();
#endif
}

// static
void PlatformThread::Sleep(int duration_ms) {
#if defined(OS_WIN)
  ::Sleep(duration_ms);
#elif defined (OS_POSIX)
  struct timespec sleep_time, remaining;
  // Contains the portion of duration_ms >= 1 sec.
  sleep_time.tv_sec = duration_ms / 1000;
  duration_ms -= sleep_time.tv_sec * 1000;
  // Contains the portion of duration_ms < 1 sec.
  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.
  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) {
    sleep_time = remaining;
  }
#endif
}

// static
int PlatformThread::CurrentId() {
#if defined(OS_WIN)
  return GetCurrentThreadId();
#elif defined(OS_MACOSX)
  return mach_thread_self();
#elif defined(OS_LINUX)
  return gettid();
#endif
}

bool PlatformThread::operator==(const PlatformThread& other_thread) {
#if defined(OS_WIN)
  return thread_ == other_thread.thread_;
#elif defined(OS_POSIX)
  return pthread_equal(thread_, other_thread.thread_);
#endif
}
<commit_msg>Use syscall instead since gettid doesn't seem to exist.<commit_after>// Copyright 2008, Google Inc.
// 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 Google Inc. 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 AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER OR CONTRIBUTORS 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.

#include "base/platform_thread.h"

#if defined(OS_POSIX)
#include <errno.h>
#include <sched.h>
#endif

#if defined(OS_MACOSX)
#include <mach/mach.h>
#elif defined(OS_LINUX)
#include <sys/syscall.h>
#include <unistd.h>
#endif

// static
PlatformThread PlatformThread::Current() {
  PlatformThread thread;

#if defined(OS_WIN)
  thread.thread_ = GetCurrentThread();
#elif defined(OS_POSIX)
  thread.thread_ = pthread_self();
#endif

  return thread;
}

// static
void PlatformThread::YieldCurrentThread() {
#if defined(OS_WIN)
  ::Sleep(0);
#elif defined(OS_POSIX)
  sched_yield();
#endif
}

// static
void PlatformThread::Sleep(int duration_ms) {
#if defined(OS_WIN)
  ::Sleep(duration_ms);
#elif defined (OS_POSIX)
  struct timespec sleep_time, remaining;
  // Contains the portion of duration_ms >= 1 sec.
  sleep_time.tv_sec = duration_ms / 1000;
  duration_ms -= sleep_time.tv_sec * 1000;
  // Contains the portion of duration_ms < 1 sec.
  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.
  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) {
    sleep_time = remaining;
  }
#endif
}

// static
int PlatformThread::CurrentId() {
#if defined(OS_WIN)
  return GetCurrentThreadId();
#elif defined(OS_MACOSX)
  return mach_thread_self();
#elif defined(OS_LINUX)
  return syscall(__NR_gettid);
#endif
}

bool PlatformThread::operator==(const PlatformThread& other_thread) {
#if defined(OS_WIN)
  return thread_ == other_thread.thread_;
#elif defined(OS_POSIX)
  return pthread_equal(thread_, other_thread.thread_);
#endif
}
<|endoftext|>


<commit_before>#include "audiere.h"
#include "internal.h"
#include "repeatable.h"
#include "utility.h"

namespace audiere {

  ADR_EXPORT(OutputStream*, AdrOpenSound)(
    AudioDevice* device,
    SampleSource* source,
    bool streaming)
  {
    if (!device || !source) {
      return 0;
    }

    // If the stream is not seekable, we cannot know how big of a buffer
    // to allocate, so try to stream it.  Also, if the user wants to stream
    // then let him.  ;)
    if (!source->isSeekable() && streaming) {
      return device->openStream(source);
    }

    int stream_length = source->getLength();
    int channel_count, sample_rate;
    SampleFormat sample_format;
    source->getFormat(channel_count, sample_rate, sample_format);

    int stream_length_bytes =
      stream_length * channel_count * GetSampleSize(sample_format);
    u8* buffer = new u8[stream_length_bytes];
    source->setPosition(0);  // in case the source has been read from already
    source->read(stream_length, buffer);

    OutputStream* stream = device->openBuffer(
      buffer, stream_length,
      channel_count, sample_rate, sample_format);

    delete[] buffer;
    return stream;
  }

}
<commit_msg>oops, fix opening sounds...  dumb mistake on my part<commit_after>#include "audiere.h"
#include "internal.h"
#include "repeatable.h"
#include "utility.h"

namespace audiere {

  ADR_EXPORT(OutputStream*, AdrOpenSound)(
    AudioDevice* device,
    SampleSource* source,
    bool streaming)
  {
    if (!device || !source) {
      return 0;
    }

    // If the stream is not seekable, we cannot know how big of a buffer
    // to allocate, so try to stream it.  Also, if the user wants to stream
    // then let him.  ;)
    if (!source->isSeekable() || streaming) {
      return device->openStream(source);
    }

    int stream_length = source->getLength();
    int channel_count, sample_rate;
    SampleFormat sample_format;
    source->getFormat(channel_count, sample_rate, sample_format);

    int stream_length_bytes =
      stream_length * channel_count * GetSampleSize(sample_format);
    u8* buffer = new u8[stream_length_bytes];
    source->setPosition(0);  // in case the source has been read from already
    source->read(stream_length, buffer);

    OutputStream* stream = device->openBuffer(
      buffer, stream_length,
      channel_count, sample_rate, sample_format);

    delete[] buffer;
    return stream;
  }

}
<|endoftext|>


<commit_before>// @(#)root/tree:$Name$:$Id$
// Author: Rene Brun   11/02/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// A TEventList object is a list of selected events (entries) in a TTree//
//                                                                      //
// A TEventList is automatically generated by TTree::Draw: example      //
//      tree->Draw(">>elist1","x<0 && y> 0");                           //
//         In this example, a TEventList object named "elist1" will be  //
//         generated. (Previous contents are overwritten).              //
//      tree->Draw(">>+elist1","x<0 && y> 0");                          //
//         In this example, selected entries are added to the list.     //
//                                                                      //
// The TEventList object is added to the list of objects in the current //
// directory.                                                           //
// Use TTree:SetEventList(TEventList *list) to inform TTree that you    //
// want to use the list as input. The following code gets a pointer to  //
// the TEventList object created in the above commands:                 //
//     TEventList *list = (TEventList*)gDirectory->Get("elist1");       //
//                                                                      //
// Use function Enter to enter an element in the list                   //
// The function Add may be used to merge two lists.                     //
// The function Subtract may be used to subtract two lists.             //
// The function Reset may be used to reset a list.                      //
// Use TEventList::Print(option) to print the contents.                 //
//      (option "all" prints all the list entries).                     //
//   Operators + and - correspond to functions Add and Subtract.        //
// A TEventList object can be saved on a file via the Write function.   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TEventList.h"
#include "TTree.h"
#include "TFile.h"
#include "TMath.h"

ClassImp(TEventList)

//______________________________________________________________________________
TEventList::TEventList(): TNamed()
{
//*-*-*-*-*-*Default constructor for a EventList*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ==================================

   fN          = 0;
   fSize       = 100;
   fDelta      = 100;
   fList       = 0;
   fDirectory  = 0;
}

//______________________________________________________________________________
TEventList::TEventList(const char *name, const char *title, Int_t initsize, Int_t delta)
    :TNamed(name,title)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a EventList*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =================
//
//  This Eventlist is added to the list of objects in current directory

   fN = 0;
   if (initsize > 100) fSize  = initsize;
   else                fSize  = 100;
   if (delta > 100)    fDelta = delta;
   else                fDelta = 100;
   fList       = 0;
   fDirectory  = gDirectory;
   gDirectory->Append(this);
}

//______________________________________________________________________________
TEventList::TEventList(const TEventList &list)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Copy constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ================

   fN     = list.fN;
   fSize  = list.fSize;
   fDelta = list.fDelta;
   fList  = new Int_t[fSize];
   for (Int_t i=0; i<fN; i++)
      fList[i] = list.fList[i];
}

//______________________________________________________________________________
TEventList::~TEventList()
{
//*-*-*-*-*-*Default destructor for a EventList*-*-*-*-*-*-*-*-*-*-*-*
//*-*        =================================

   delete [] fList;
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fDirectory  = 0;
}

//______________________________________________________________________________
void TEventList::Add(const TEventList *alist)
{
//          Merge contents of alist with this list.
//   Both alist and this list are assumed to be sorted prior to this call

   Int_t i;
   Int_t an = alist->GetN();
   if (!an) return;
   Int_t *alst = alist->GetList();
   if (!fList) {
      fList = new Int_t[an];
      for (i=0;i<an;i++) fList[i] = alst[i];
      fN = an;
      fSize = an;
      return;
   }
   Int_t newsize = fN + an;
   Int_t *newlist = new Int_t[newsize];
   Int_t newpos, alpos;
   newpos = alpos = 0;
   for (i=0;i<fN;i++) {
      while (alpos < an && fList[i] > alst[alpos]) {
         newlist[newpos] = alst[alpos];
         newpos++;
         alpos++;
      }
      if (fList[i] == alst[alpos]) alpos++;
      newlist[newpos] = fList[i];
      newpos++;
   }
   while (alpos < an) {
      newlist[newpos] = alst[alpos];
      newpos++;
      alpos++;
   }
   delete [] fList;
   fN    = newpos;
   fSize = newsize;
   fList = newlist;
}

//______________________________________________________________________________
Bool_t TEventList::Contains(Int_t entry)
{
//          Return TRUE if list contains entry.

   if (GetIndex(entry) < 0) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
void TEventList::Enter(Int_t entry)
{
//          Enter element entry into the list

   if (!fList) {
      fList = new Int_t[fSize];
      fList[0] = entry;
      fN = 1;
      return;
   }
   if (fN >= fSize) Resize();
   fList[fN] = entry;
   fN++;
}

//______________________________________________________________________________
Int_t TEventList::GetEntry(Int_t index) const
{
//       Return value of entry at index in the list.
//       Return -1 if index is not in the list range

   if (!fList)   return -1;
   if (index < 0 || index >= fN)   return -1;
   return fList[index];
}

//______________________________________________________________________________
Int_t TEventList::GetIndex(Int_t entry) const
{
   // Return index in the list of element with value entry
   // array is supposed  to be sorted prior to this call.
   // If match is found, function returns position of element.
   // If no match found, function returns -1.

   Int_t nabove, nbelow, middle;
   nabove = fN+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      if (entry == fList[middle-1]) return middle-1;
      if (entry  < fList[middle-1]) nabove = middle;
      else                          nbelow = middle;
   }
   return -1;
}

//______________________________________________________________________________
void TEventList::Print(Option_t *option)
{
//          Print contents of this list

   printf("EventList:%s/%s, number of entries =%d, size=%d\n",GetName(),GetTitle(),fN,fSize);
   if (!strstr(option,"all")) return;
   Int_t i;
   Int_t nbuf = 0;
   char element[10];
   char *line = new char[100];
   sprintf(line,"%-5d ",0);
   for (i=0;i<fN;i++) {
      nbuf++;
      if (nbuf > 10) {
         printf("%s\n",line);
         sprintf(line,"%-5d ",i);
         nbuf = 1;
      }
      sprintf(element,"%-7d ",fList[i]);
      strcat(line,element);
   }
   if (nbuf) printf("%s\n",line);
   delete [] line;
}

//______________________________________________________________________________
void TEventList::Reset(Option_t *)
{
//          Reset number of entries in event list

   fN = 0;
}

//______________________________________________________________________________
void TEventList::Resize(Int_t delta)
{
//          Resize list by delta entries

   if (!delta) delta = fDelta;
   fSize += delta;
   Int_t *newlist = new Int_t[fSize];
   for (Int_t i=0;i<fN;i++) newlist[i] = fList[i];
   delete [] fList;
   fList = newlist;
}

//______________________________________________________________________________
void TEventList::SetDirectory(TDirectory *dir)
{
   // Remove reference to this EventList from current directory and add
   // reference to new directory dir. dir can be 0 in which case the list
   // does not belong to any directory.

   if (fDirectory == dir) return;
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fDirectory = dir;
   if (fDirectory) fDirectory->GetList()->Add(this);
}

//______________________________________________________________________________
void TEventList::SetName(const char *name)
{
// Change the name of this TEventList
//

//  TEventLists are named objects in a THashList.
//  We must update the hashlist if we change the name
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fName = name;
   if (fDirectory) fDirectory->GetList()->Add(this);
}

//______________________________________________________________________________
void TEventList::Sort()
{
//          Sort list entries in increasing order

   Int_t *index   = new Int_t[fN];
   Int_t *newlist = new Int_t[fSize];
   Int_t i,ind;
   TMath::Sort(fN,fList,index); //sort in decreasing order
   for (i=0;i<fN;i++) {
      ind = index[fN-i-1];
      newlist[i] = fList[ind];
   }
   for (i=fN;i<fSize;i++) {
      newlist[i] = 0;
   }
   delete [] index;
   delete [] fList;
   fList = newlist;
}

//______________________________________________________________________________
void TEventList::Streamer(TBuffer &b)
{
   // Stream an object of class TEventList.

   UInt_t R__s, R__c;
   if (b.IsReading()) {
      b.ReadVersion(&R__s, &R__c);
      TNamed::Streamer(b);
      b >> fN;
      b >> fSize;
      b >> fDelta;
      if (fN) {
         fList = new Int_t[fSize];
         b.ReadFastArray(fList,fN);
      }
      fDirectory = gDirectory;
      gDirectory->Append(this);
      b.CheckByteCount(R__s, R__c, TEventList::IsA());
   } else {
      R__c = b.WriteVersion(TEventList::IsA(), kTRUE);
      TNamed::Streamer(b);
      b << fN;
      b << fSize;
      b << fDelta;
      if (fN) {
         b.WriteFastArray(fList,fN);
      }
      b.SetByteCount(R__c, kTRUE);
   }
}

//______________________________________________________________________________
void TEventList::Subtract(const TEventList *alist)
{
   // Remove elements from this list that are present in alist.

   if (!alist) return;
   if (!fList) return;

   Int_t *newlist = new Int_t[fN];
   Int_t newpos = 0;
   Int_t i;
   for (i=0;i<fN;i++) {
      if (alist->GetIndex(fList[i]) < 0) {
         newlist[newpos] = fList[i];
         newpos++;
      }
   }
   delete [] fList;
   fN    = newpos;
   fList = newlist;
}

//______________________________________________________________________________
TEventList& TEventList::operator=(const TEventList &list)
{
   if (this != &list) {
      TNamed::operator=(list);
      if (fSize < list.fSize) {
         delete [] fList;
         fList  = new Int_t[list.fSize];
      }
      fN     = list.fN;
      fSize  = list.fSize;
      fDelta = list.fDelta;
      for (Int_t i=0; i<fN; i++)
         fList[i] = list.fList[i];
   }
   return *this;
}

//______________________________________________________________________________
TEventList operator+(const TEventList &list1, const TEventList &list2)
{
   TEventList newlist = list1;
   newlist.Add(&list2);
   return newlist;
}

//______________________________________________________________________________
TEventList operator-(const TEventList &list1, const TEventList &list2)
{
   TEventList newlist = list1;
   newlist.Subtract(&list2);
   return newlist;
}

<commit_msg>Implement a suggestion by Walter Mueller to optimize the resizing of the list. The mod is in the Enter function.<commit_after>// @(#)root/tree:$Name:  $:$Id: TEventList.cxx,v 1.1.1.1 2000/05/16 17:00:45 rdm Exp $
// Author: Rene Brun   11/02/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// A TEventList object is a list of selected events (entries) in a TTree//
//                                                                      //
// A TEventList is automatically generated by TTree::Draw: example      //
//      tree->Draw(">>elist1","x<0 && y> 0");                           //
//         In this example, a TEventList object named "elist1" will be  //
//         generated. (Previous contents are overwritten).              //
//      tree->Draw(">>+elist1","x<0 && y> 0");                          //
//         In this example, selected entries are added to the list.     //
//                                                                      //
// The TEventList object is added to the list of objects in the current //
// directory.                                                           //
// Use TTree:SetEventList(TEventList *list) to inform TTree that you    //
// want to use the list as input. The following code gets a pointer to  //
// the TEventList object created in the above commands:                 //
//     TEventList *list = (TEventList*)gDirectory->Get("elist1");       //
//                                                                      //
// Use function Enter to enter an element in the list                   //
// The function Add may be used to merge two lists.                     //
// The function Subtract may be used to subtract two lists.             //
// The function Reset may be used to reset a list.                      //
// Use TEventList::Print(option) to print the contents.                 //
//      (option "all" prints all the list entries).                     //
//   Operators + and - correspond to functions Add and Subtract.        //
// A TEventList object can be saved on a file via the Write function.   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TEventList.h"
#include "TTree.h"
#include "TFile.h"
#include "TMath.h"

ClassImp(TEventList)

//______________________________________________________________________________
TEventList::TEventList(): TNamed()
{
//*-*-*-*-*-*Default constructor for a EventList*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*        ==================================

   fN          = 0;
   fSize       = 100;
   fDelta      = 100;
   fList       = 0;
   fDirectory  = 0;
}

//______________________________________________________________________________
TEventList::TEventList(const char *name, const char *title, Int_t initsize, Int_t delta)
    :TNamed(name,title)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a EventList*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      =================
//
//  This Eventlist is added to the list of objects in current directory

   fN = 0;
   if (initsize > 100) fSize  = initsize;
   else                fSize  = 100;
   if (delta > 100)    fDelta = delta;
   else                fDelta = 100;
   fList       = 0;
   fDirectory  = gDirectory;
   gDirectory->Append(this);
}

//______________________________________________________________________________
TEventList::TEventList(const TEventList &list)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Copy constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                      ================

   fN     = list.fN;
   fSize  = list.fSize;
   fDelta = list.fDelta;
   fList  = new Int_t[fSize];
   for (Int_t i=0; i<fN; i++)
      fList[i] = list.fList[i];
}

//______________________________________________________________________________
TEventList::~TEventList()
{
//*-*-*-*-*-*Default destructor for a EventList*-*-*-*-*-*-*-*-*-*-*-*
//*-*        =================================

   delete [] fList;
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fDirectory  = 0;
}

//______________________________________________________________________________
void TEventList::Add(const TEventList *alist)
{
//          Merge contents of alist with this list.
//   Both alist and this list are assumed to be sorted prior to this call

   Int_t i;
   Int_t an = alist->GetN();
   if (!an) return;
   Int_t *alst = alist->GetList();
   if (!fList) {
      fList = new Int_t[an];
      for (i=0;i<an;i++) fList[i] = alst[i];
      fN = an;
      fSize = an;
      return;
   }
   Int_t newsize = fN + an;
   Int_t *newlist = new Int_t[newsize];
   Int_t newpos, alpos;
   newpos = alpos = 0;
   for (i=0;i<fN;i++) {
      while (alpos < an && fList[i] > alst[alpos]) {
         newlist[newpos] = alst[alpos];
         newpos++;
         alpos++;
      }
      if (fList[i] == alst[alpos]) alpos++;
      newlist[newpos] = fList[i];
      newpos++;
   }
   while (alpos < an) {
      newlist[newpos] = alst[alpos];
      newpos++;
      alpos++;
   }
   delete [] fList;
   fN    = newpos;
   fSize = newsize;
   fList = newlist;
}

//______________________________________________________________________________
Bool_t TEventList::Contains(Int_t entry)
{
//          Return TRUE if list contains entry.

   if (GetIndex(entry) < 0) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
void TEventList::Enter(Int_t entry)
{
//          Enter element entry into the list

   if (!fList) {
      fList = new Int_t[fSize];
      fList[0] = entry;
      fN = 1;
      return;
   }
   if (fN >= fSize) {
      Int_t newsize = TMath::Max(2*fSize,fN+fDelta);
      Resize(newsize-fSize);
   }
   fList[fN] = entry;
   fN++;
}

//______________________________________________________________________________
Int_t TEventList::GetEntry(Int_t index) const
{
//       Return value of entry at index in the list.
//       Return -1 if index is not in the list range

   if (!fList)   return -1;
   if (index < 0 || index >= fN)   return -1;
   return fList[index];
}

//______________________________________________________________________________
Int_t TEventList::GetIndex(Int_t entry) const
{
   // Return index in the list of element with value entry
   // array is supposed  to be sorted prior to this call.
   // If match is found, function returns position of element.
   // If no match found, function returns -1.

   Int_t nabove, nbelow, middle;
   nabove = fN+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      if (entry == fList[middle-1]) return middle-1;
      if (entry  < fList[middle-1]) nabove = middle;
      else                          nbelow = middle;
   }
   return -1;
}

//______________________________________________________________________________
void TEventList::Print(Option_t *option)
{
//          Print contents of this list

   printf("EventList:%s/%s, number of entries =%d, size=%d\n",GetName(),GetTitle(),fN,fSize);
   if (!strstr(option,"all")) return;
   Int_t i;
   Int_t nbuf = 0;
   char element[10];
   char *line = new char[100];
   sprintf(line,"%-5d ",0);
   for (i=0;i<fN;i++) {
      nbuf++;
      if (nbuf > 10) {
         printf("%s\n",line);
         sprintf(line,"%-5d ",i);
         nbuf = 1;
      }
      sprintf(element,"%-7d ",fList[i]);
      strcat(line,element);
   }
   if (nbuf) printf("%s\n",line);
   delete [] line;
}

//______________________________________________________________________________
void TEventList::Reset(Option_t *)
{
//          Reset number of entries in event list

   fN = 0;
}

//______________________________________________________________________________
void TEventList::Resize(Int_t delta)
{
//          Resize list by delta entries

   if (!delta) delta = fDelta;
   fSize += delta;
   Int_t *newlist = new Int_t[fSize];
   for (Int_t i=0;i<fN;i++) newlist[i] = fList[i];
   delete [] fList;
   fList = newlist;
}

//______________________________________________________________________________
void TEventList::SetDirectory(TDirectory *dir)
{
   // Remove reference to this EventList from current directory and add
   // reference to new directory dir. dir can be 0 in which case the list
   // does not belong to any directory.

   if (fDirectory == dir) return;
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fDirectory = dir;
   if (fDirectory) fDirectory->GetList()->Add(this);
}

//______________________________________________________________________________
void TEventList::SetName(const char *name)
{
// Change the name of this TEventList
//

//  TEventLists are named objects in a THashList.
//  We must update the hashlist if we change the name
   if (fDirectory) fDirectory->GetList()->Remove(this);
   fName = name;
   if (fDirectory) fDirectory->GetList()->Add(this);
}

//______________________________________________________________________________
void TEventList::Sort()
{
//          Sort list entries in increasing order

   Int_t *index   = new Int_t[fN];
   Int_t *newlist = new Int_t[fSize];
   Int_t i,ind;
   TMath::Sort(fN,fList,index); //sort in decreasing order
   for (i=0;i<fN;i++) {
      ind = index[fN-i-1];
      newlist[i] = fList[ind];
   }
   for (i=fN;i<fSize;i++) {
      newlist[i] = 0;
   }
   delete [] index;
   delete [] fList;
   fList = newlist;
}

//______________________________________________________________________________
void TEventList::Streamer(TBuffer &b)
{
   // Stream an object of class TEventList.

   UInt_t R__s, R__c;
   if (b.IsReading()) {
      b.ReadVersion(&R__s, &R__c);
      TNamed::Streamer(b);
      b >> fN;
      b >> fSize;
      b >> fDelta;
      if (fN) {
         fList = new Int_t[fSize];
         b.ReadFastArray(fList,fN);
      }
      fDirectory = gDirectory;
      gDirectory->Append(this);
      b.CheckByteCount(R__s, R__c, TEventList::IsA());
   } else {
      R__c = b.WriteVersion(TEventList::IsA(), kTRUE);
      TNamed::Streamer(b);
      b << fN;
      b << fSize;
      b << fDelta;
      if (fN) {
         b.WriteFastArray(fList,fN);
      }
      b.SetByteCount(R__c, kTRUE);
   }
}

//______________________________________________________________________________
void TEventList::Subtract(const TEventList *alist)
{
   // Remove elements from this list that are present in alist.

   if (!alist) return;
   if (!fList) return;

   Int_t *newlist = new Int_t[fN];
   Int_t newpos = 0;
   Int_t i;
   for (i=0;i<fN;i++) {
      if (alist->GetIndex(fList[i]) < 0) {
         newlist[newpos] = fList[i];
         newpos++;
      }
   }
   delete [] fList;
   fN    = newpos;
   fList = newlist;
}

//______________________________________________________________________________
TEventList& TEventList::operator=(const TEventList &list)
{
   if (this != &list) {
      TNamed::operator=(list);
      if (fSize < list.fSize) {
         delete [] fList;
         fList  = new Int_t[list.fSize];
      }
      fN     = list.fN;
      fSize  = list.fSize;
      fDelta = list.fDelta;
      for (Int_t i=0; i<fN; i++)
         fList[i] = list.fList[i];
   }
   return *this;
}

//______________________________________________________________________________
TEventList operator+(const TEventList &list1, const TEventList &list2)
{
   TEventList newlist = list1;
   newlist.Add(&list2);
   return newlist;
}

//______________________________________________________________________________
TEventList operator-(const TEventList &list1, const TEventList &list2)
{
   TEventList newlist = list1;
   newlist.Subtract(&list2);
   return newlist;
}

<|endoftext|>