vendor Catch2 and ETL
This commit is contained in:
@ -0,0 +1,853 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -ofsm.h -DHandlers=<n> fsm_generator.h
|
||||
// Where <n> is the number of messages to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 events...
|
||||
// python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h
|
||||
//
|
||||
// See generate.bat
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef ETL_FSM_INCLUDED
|
||||
#define ETL_FSM_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "array.h"
|
||||
#include "nullptr.h"
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "user_type.h"
|
||||
#include "message_router.h"
|
||||
#include "integral_limits.h"
|
||||
#include "largest.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
class fsm;
|
||||
class hfsm;
|
||||
|
||||
/// Allow alternative type for state id.
|
||||
#if !defined(ETL_FSM_STATE_ID_TYPE)
|
||||
typedef uint_least8_t fsm_state_id_t;
|
||||
#else
|
||||
typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
|
||||
#endif
|
||||
|
||||
// For internal FSM use.
|
||||
typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
class fsm_state;
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("template <typename, typename, etl::fsm_state_id_t,")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename, ")
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename>")
|
||||
cog.outl("class fsm_state;")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Base exception class for FSM.
|
||||
//***************************************************************************
|
||||
class fsm_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: etl::exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for null state pointer.
|
||||
//***************************************************************************
|
||||
class fsm_null_state_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_null_state_exception(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FSM_FILE_ID"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for invalid state id.
|
||||
//***************************************************************************
|
||||
class fsm_state_id_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_state_id_exception(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FSM_FILE_ID"B"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for incompatible state list.
|
||||
//***************************************************************************
|
||||
class fsm_state_list_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_state_list_exception(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FSM_FILE_ID"C"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for incompatible order state list.
|
||||
//***************************************************************************
|
||||
class fsm_state_list_order_exception : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
|
||||
fsm_state_list_order_exception(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list order", ETL_FSM_FILE_ID"D"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for forbidden state changes.
|
||||
//***************************************************************************
|
||||
class fsm_state_composite_state_change_forbidden : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Exception for message received but not started.
|
||||
//***************************************************************************
|
||||
class fsm_not_started : public etl::fsm_exception
|
||||
{
|
||||
public:
|
||||
fsm_not_started(string_type file_name_, numeric_type line_number_)
|
||||
: etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace private_fsm
|
||||
{
|
||||
template <typename T = void>
|
||||
class ifsm_state_helper
|
||||
{
|
||||
public:
|
||||
|
||||
// Pass this whenever no state change is desired.
|
||||
// The highest unsigned value of fsm_state_id_t.
|
||||
static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
|
||||
|
||||
// Pass this when this event also needs to be passed to the parent.
|
||||
static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
|
||||
|
||||
// Pass this when this event should trigger a self transition.
|
||||
static ETL_CONSTANT fsm_state_id_t Self_Transition = No_State_Change - 2U;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
|
||||
|
||||
template <typename T>
|
||||
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Pass_To_Parent;
|
||||
|
||||
template <typename T>
|
||||
ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Interface class for FSM states.
|
||||
//***************************************************************************
|
||||
class ifsm_state : public private_fsm::ifsm_state_helper<>
|
||||
{
|
||||
public:
|
||||
|
||||
/// Allows ifsm_state functions to be private.
|
||||
friend class etl::fsm;
|
||||
friend class etl::hfsm;
|
||||
|
||||
using private_fsm::ifsm_state_helper<>::No_State_Change;
|
||||
using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
|
||||
using private_fsm::ifsm_state_helper<>::Self_Transition;
|
||||
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
template <typename, typename, etl::fsm_state_id_t, typename...>
|
||||
friend class fsm_state;
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl(" template <typename, typename, etl::fsm_state_id_t,")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename, ")
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename>")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
friend class etl::fsm_state;
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
/// Gets the id for this state.
|
||||
//*******************************************
|
||||
etl::fsm_state_id_t get_state_id() const
|
||||
{
|
||||
return state_id;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Adds a child to this state.
|
||||
/// Only of use when part of an HFSM.
|
||||
//*******************************************
|
||||
void add_child_state(etl::ifsm_state& state)
|
||||
{
|
||||
ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
state.p_parent = this;
|
||||
|
||||
if (p_default_child == ETL_NULLPTR)
|
||||
{
|
||||
p_active_child = &state;
|
||||
p_default_child = &state;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Adds a list of child states.
|
||||
/// Only of use when part of an HFSM.
|
||||
//*******************************************
|
||||
template <typename TSize>
|
||||
void set_child_states(etl::ifsm_state** state_list, TSize size)
|
||||
{
|
||||
p_active_child = ETL_NULLPTR;
|
||||
p_default_child = ETL_NULLPTR;
|
||||
|
||||
for (TSize i = 0; i < size; ++i)
|
||||
{
|
||||
ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
add_child_state(*state_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
ifsm_state(etl::fsm_state_id_t state_id_)
|
||||
: state_id(state_id_),
|
||||
p_context(ETL_NULLPTR),
|
||||
p_parent(ETL_NULLPTR),
|
||||
p_active_child(ETL_NULLPTR),
|
||||
p_default_child(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Destructor.
|
||||
//*******************************************
|
||||
virtual ~ifsm_state()
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
etl::fsm& get_fsm_context() const
|
||||
{
|
||||
return *p_context;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
|
||||
|
||||
virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
|
||||
virtual void on_exit_state() {} // By default, do nothing.
|
||||
|
||||
//*******************************************
|
||||
void set_fsm_context(etl::fsm& context)
|
||||
{
|
||||
p_context = &context;
|
||||
}
|
||||
|
||||
// The state id.
|
||||
const etl::fsm_state_id_t state_id;
|
||||
|
||||
// A pointer to the FSM context.
|
||||
etl::fsm* p_context;
|
||||
|
||||
// A pointer to the parent.
|
||||
ifsm_state* p_parent;
|
||||
|
||||
// A pointer to the active child.
|
||||
ifsm_state* p_active_child;
|
||||
|
||||
// A pointer to the default active child.
|
||||
ifsm_state* p_default_child;
|
||||
|
||||
// Disabled.
|
||||
ifsm_state(const ifsm_state&);
|
||||
ifsm_state& operator =(const ifsm_state&);
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The FSM class.
|
||||
//***************************************************************************
|
||||
class fsm : public etl::imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
friend class etl::hfsm;
|
||||
using imessage_router::receive;
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
fsm(etl::message_router_id_t id)
|
||||
: imessage_router(id)
|
||||
, p_state(ETL_NULLPTR)
|
||||
, state_list(ETL_NULLPTR)
|
||||
, number_of_states(0U)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Set the states for the FSM
|
||||
//*******************************************
|
||||
template <typename TSize>
|
||||
void set_states(etl::ifsm_state** p_states, TSize size)
|
||||
{
|
||||
state_list = p_states;
|
||||
number_of_states = etl::fsm_state_id_t(size);
|
||||
|
||||
ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
|
||||
ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
|
||||
|
||||
for (etl::fsm_state_id_t i = 0; i < size; ++i)
|
||||
{
|
||||
ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
|
||||
state_list[i]->set_fsm_context(*this);
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Starts the FSM.
|
||||
/// Can only be called once.
|
||||
/// Subsequent calls will do nothing.
|
||||
///\param call_on_enter_state If true will call on_enter_state() for the first state. Default = true.
|
||||
//*******************************************
|
||||
virtual void start(bool call_on_enter_state = true)
|
||||
{
|
||||
// Can only be started once.
|
||||
if (p_state == ETL_NULLPTR)
|
||||
{
|
||||
p_state = state_list[0];
|
||||
ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
|
||||
if (call_on_enter_state)
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id;
|
||||
etl::ifsm_state* p_last_state;
|
||||
|
||||
do
|
||||
{
|
||||
p_last_state = p_state;
|
||||
next_state_id = p_state->on_enter_state();
|
||||
if (next_state_id != ifsm_state::No_State_Change)
|
||||
{
|
||||
ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_state = state_list[next_state_id];
|
||||
}
|
||||
} while (p_last_state != p_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Top level message handler for the FSM.
|
||||
//*******************************************
|
||||
void receive(const etl::imessage& message) ETL_OVERRIDE
|
||||
{
|
||||
if (is_started())
|
||||
{
|
||||
etl::fsm_state_id_t next_state_id = p_state->process_event(message);
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
etl::ifsm_state* p_next_state = state_list[next_state_id];
|
||||
|
||||
do
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state = p_next_state;
|
||||
|
||||
next_state_id = p_state->on_enter_state();
|
||||
|
||||
if (have_changed_state(next_state_id))
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
|
||||
p_next_state = state_list[next_state_id];
|
||||
}
|
||||
} while (p_next_state != p_state); // Have we changed state again?
|
||||
}
|
||||
else if (is_self_transition(next_state_id))
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
p_state->on_enter_state();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
|
||||
}
|
||||
}
|
||||
|
||||
using imessage_router::accepts;
|
||||
|
||||
//*******************************************
|
||||
/// Does this FSM accept the message id?
|
||||
/// Yes, it accepts everything!
|
||||
//*******************************************
|
||||
bool accepts(etl::message_id_t) const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets the current state id.
|
||||
//*******************************************
|
||||
etl::fsm_state_id_t get_state_id() const
|
||||
{
|
||||
ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return p_state->get_state_id();
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets a reference to the current state interface.
|
||||
//*******************************************
|
||||
ifsm_state& get_state()
|
||||
{
|
||||
ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return *p_state;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Gets a const reference to the current state interface.
|
||||
//*******************************************
|
||||
const ifsm_state& get_state() const
|
||||
{
|
||||
ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
|
||||
return *p_state;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Checks if the FSM has been started.
|
||||
//*******************************************
|
||||
bool is_started() const
|
||||
{
|
||||
return p_state != ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Reset the FSM to pre-started state.
|
||||
///\param call_on_exit_state If true will call on_exit_state() for the current state. Default = false.
|
||||
//*******************************************
|
||||
virtual void reset(bool call_on_exit_state = false)
|
||||
{
|
||||
if ((p_state != ETL_NULLPTR) && call_on_exit_state)
|
||||
{
|
||||
p_state->on_exit_state();
|
||||
}
|
||||
|
||||
p_state = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_producer() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_consumer() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//********************************************
|
||||
bool have_changed_state(etl::fsm_state_id_t next_state_id) const
|
||||
{
|
||||
return (next_state_id != p_state->get_state_id()) &&
|
||||
(next_state_id != ifsm_state::No_State_Change) &&
|
||||
(next_state_id != ifsm_state::Self_Transition);
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_self_transition(etl::fsm_state_id_t next_state_id) const
|
||||
{
|
||||
return (next_state_id == ifsm_state::Self_Transition);
|
||||
}
|
||||
|
||||
etl::ifsm_state* p_state; ///< A pointer to the current state.
|
||||
etl::ifsm_state** state_list; ///< The list of added states.
|
||||
etl::fsm_state_id_t number_of_states; ///< The number of states.
|
||||
};
|
||||
|
||||
//*************************************************************************************************
|
||||
// For C++17 and above.
|
||||
//*************************************************************************************************
|
||||
#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
|
||||
//***************************************************************************
|
||||
// The definition for all types.
|
||||
//***************************************************************************
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
class fsm_state : public ifsm_state
|
||||
{
|
||||
public:
|
||||
|
||||
static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
|
||||
|
||||
fsm_state()
|
||||
: ifsm_state(STATE_ID)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~fsm_state()
|
||||
{
|
||||
}
|
||||
|
||||
TContext& get_fsm_context() const
|
||||
{
|
||||
return static_cast<TContext&>(ifsm_state::get_fsm_context());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//********************************************
|
||||
struct result_t
|
||||
{
|
||||
bool was_handled;
|
||||
etl::fsm_state_id_t state_id;
|
||||
};
|
||||
|
||||
//********************************************
|
||||
etl::fsm_state_id_t process_event(const etl::imessage& message)
|
||||
{
|
||||
etl::fsm_state_id_t new_state_id;
|
||||
|
||||
const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
|
||||
|
||||
if (!was_handled || (new_state_id == Pass_To_Parent))
|
||||
{
|
||||
new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
|
||||
}
|
||||
|
||||
return new_state_id;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
|
||||
{
|
||||
if (TMessage::ID == msg.get_message_id())
|
||||
{
|
||||
new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Definition of STATE_ID
|
||||
template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
|
||||
ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
|
||||
|
||||
#else
|
||||
//*************************************************************************************************
|
||||
// For C++14 and below.
|
||||
//*************************************************************************************************
|
||||
/*[[[cog
|
||||
import cog
|
||||
################################################
|
||||
# The first definition for all of the events.
|
||||
################################################
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The definition for all %s message types." % Handlers)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % Handlers)
|
||||
cog.outl("class fsm_state : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
|
||||
cog.outl("")
|
||||
cog.outl(" fsm_state()")
|
||||
cog.outl(" : ifsm_state(STATE_ID)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("protected:")
|
||||
cog.outl("")
|
||||
cog.outl(" ~fsm_state()")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" TContext& get_fsm_context() const")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("private:")
|
||||
cog.outl("")
|
||||
cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" etl::fsm_state_id_t new_state_id;")
|
||||
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (event_id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, int(Handlers) + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
|
||||
####################################
|
||||
# All of the other specialisations.
|
||||
####################################
|
||||
for n in range(int(Handlers) - 1, 0, -1):
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
if n == 1:
|
||||
cog.outl("// Specialisation for %d message type." % n)
|
||||
else:
|
||||
cog.outl("// Specialisation for %d message types." % n)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
for t in range(1, n):
|
||||
cog.out("typename T%d, " % t)
|
||||
if t % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%d>" % n)
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("T%d, " % t)
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
for t in range(n + 1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void> : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
|
||||
cog.outl("")
|
||||
cog.outl(" fsm_state()")
|
||||
cog.outl(" : ifsm_state(STATE_ID)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("protected:")
|
||||
cog.outl("")
|
||||
cog.outl(" ~fsm_state()")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" TContext& get_fsm_context() const")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("private:")
|
||||
cog.outl("")
|
||||
cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" etl::fsm_state_id_t new_state_id;")
|
||||
cog.outl(" etl::message_id_t event_id = message.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (event_id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, n + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T%d&>(message));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.out(" default:")
|
||||
cog.out(" new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
####################################
|
||||
# Specialisation for zero messages.
|
||||
####################################
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// Specialisation for 0 message types.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>")
|
||||
cog.out("class fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
for t in range(1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void> : public ifsm_state")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;")
|
||||
cog.outl("")
|
||||
cog.outl(" fsm_state()")
|
||||
cog.outl(" : ifsm_state(STATE_ID)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("protected:")
|
||||
cog.outl("")
|
||||
cog.outl(" ~fsm_state()")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" TContext& get_fsm_context() const")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return static_cast<TContext&>(ifsm_state::get_fsm_context());")
|
||||
cog.outl(" }")
|
||||
cog.outl("private:")
|
||||
cog.outl("")
|
||||
cog.outl(" etl::fsm_state_id_t process_event(const etl::imessage& message)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
|
||||
cog.outl("")
|
||||
cog.outl("template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, ")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("typename T%s, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s>" % Handlers)
|
||||
cog.out("ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::STATE_ID;" % Handlers)
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "private/minmax_pop.h"
|
||||
|
||||
#endif
|
@ -0,0 +1,9 @@
|
||||
python -m cogapp -d -e -o../fsm.h -DHandlers=16 fsm_generator.h
|
||||
python -m cogapp -d -e -o../message_router.h -DHandlers=16 message_router_generator.h
|
||||
python -m cogapp -d -e -o../largest.h -DNTypes=16 largest_generator.h
|
||||
python -m cogapp -d -e -o../smallest.h -DNTypes=16 smallest_generator.h
|
||||
python -m cogapp -d -e -o../type_traits.h -DIsOneOf=16 type_traits_generator.h
|
||||
python -m cogapp -d -e -o../type_lookup.h -DNTypes=16 type_lookup_generator.h
|
||||
python -m cogapp -d -e -o../type_select.h -DNTypes=16 type_select_generator.h
|
||||
python -m cogapp -d -e -o../message_packet.h -DHandlers=16 message_packet_generator.h
|
||||
python -m cogapp -d -e -o../variant_pool.h -DNTypes=16 variant_pool_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../fsm.h -DHandlers=16 fsm_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../largest.h -DNTypes=16 largest_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../message_packet.h -DHandlers=16 message_packet_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../message_router.h -DHandlers=16 message_router_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../smallest.h -DNTypes=16 smallest_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../type_lookup.h -DNTypes=16 type_lookup_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../type_select.h -DNTypes=16 type_select_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../type_traits.h -DIsOneOf=16 type_traits_generator.h
|
@ -0,0 +1 @@
|
||||
python -m cogapp -d -e -o../variant_pool.h -DNTypes=16 variant_pool_generator.h
|
@ -0,0 +1,452 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2014 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -olargest.h -DNTypes=<n> largest_generator.h
|
||||
// Where <n> is the number of types to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 types...
|
||||
// python -m cogapp -d -e -olargest.h -DNTypes=16 largest_generator.h
|
||||
//
|
||||
// See generate.bat
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef ETL_LARGEST_INCLUDED
|
||||
#define ETL_LARGEST_INCLUDED
|
||||
|
||||
///\defgroup largest largest
|
||||
///\ingroup utilities
|
||||
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
#include "smallest.h"
|
||||
#include "static_assert.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP11 && !defined(ETL_LARGEST_TYPE_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
/// Template to determine the largest type and size.
|
||||
/// Defines 'value_type' which is the type of the largest parameter.
|
||||
/// Defines 'size' which is the size of the largest parameter.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T1, typename... TRest>
|
||||
class largest_type
|
||||
{
|
||||
private:
|
||||
|
||||
// Define 'largest_other' as 'largest_type' with all but the first parameter.
|
||||
using largest_other = typename largest_type<TRest...>::type;
|
||||
|
||||
public:
|
||||
|
||||
// Set 'type' to be the largest of the first parameter and any of the others.
|
||||
// This is recursive.
|
||||
using type = typename etl::conditional<(etl::size_of<T1>::value > etl::size_of<largest_other>::value), // Boolean
|
||||
T1, // TrueType
|
||||
largest_other> // FalseType
|
||||
::type; // The largest type of the two.
|
||||
|
||||
// The size of the largest type.
|
||||
enum
|
||||
{
|
||||
size = etl::size_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for one template parameter.
|
||||
//***************************************************************************
|
||||
template <typename T1>
|
||||
class largest_type<T1>
|
||||
{
|
||||
public:
|
||||
|
||||
using type = T1;
|
||||
|
||||
enum
|
||||
{
|
||||
size = etl::size_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename... T>
|
||||
using largest_type_t = typename largest_type<T...>::type;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename... T>
|
||||
constexpr size_t largest_type_v = largest_type<T...>::size;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("/// Template to determine the largest type and size.")
|
||||
cog.outl("/// Supports up to %s types." % NTypes)
|
||||
cog.outl("/// Defines 'value_type' which is the type of the largest parameter.")
|
||||
cog.outl("/// Defines 'size' which is the size of the largest parameter.")
|
||||
cog.outl("///\\ingroup largest")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.out("template <typename T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % int(NTypes))
|
||||
cog.outl("struct largest_type")
|
||||
cog.outl("{")
|
||||
cog.outl(" // Define 'largest_other' as 'largest_type' with all but the first parameter. ")
|
||||
cog.out(" typedef typename largest_type<")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::type largest_other;" % int(NTypes))
|
||||
cog.outl("")
|
||||
cog.outl(" // Set 'type' to be the largest of the first parameter and any of the others.")
|
||||
cog.outl(" // This is recursive.")
|
||||
cog.outl(" typedef typename etl::conditional<(sizeof(T1) > sizeof(largest_other)), // Boolean")
|
||||
cog.outl(" T1, // TrueType")
|
||||
cog.outl(" largest_other> // FalseType")
|
||||
cog.outl(" ::type type; // The largest type of the two.")
|
||||
cog.outl("")
|
||||
cog.outl(" // The size of the largest type.")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" size = sizeof(type)")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// Specialisation for one template parameter.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T1>")
|
||||
cog.out("struct largest_type<T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("void, ")
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void>")
|
||||
cog.outl("{")
|
||||
cog.outl(" typedef T1 type;")
|
||||
cog.outl("")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" size = sizeof(type)")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11 && !defined(ETL_LARGEST_ALIGNMENT_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
/// Template to determine the largest alignment.
|
||||
/// Defines <b>value</b> which is the largest alignment of all the parameters.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T1, typename... TRest>
|
||||
struct largest_alignment
|
||||
{
|
||||
// Define 'largest_other' as 'largest_type' with all but the first parameter.
|
||||
using largest_other = typename largest_alignment<TRest...>::type;
|
||||
|
||||
// Set 'type' to be the largest of the first parameter and any of the others.
|
||||
// This is recursive.
|
||||
using type = typename etl::conditional<(etl::alignment_of<T1>::value > etl::alignment_of<largest_other>::value), // Boolean
|
||||
T1, // TrueType
|
||||
largest_other> // FalseType
|
||||
::type; // The largest type of the two.
|
||||
|
||||
// The largest alignment.
|
||||
enum
|
||||
{
|
||||
value = etl::alignment_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for one template parameter.
|
||||
//***************************************************************************
|
||||
template <typename T1>
|
||||
struct largest_alignment<T1>
|
||||
{
|
||||
typedef T1 type;
|
||||
|
||||
enum
|
||||
{
|
||||
value = etl::alignment_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename... T>
|
||||
inline constexpr size_t largest_alignment_v = largest_alignment<T...>::value;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("/// Template to determine the largest alignment.")
|
||||
cog.outl("/// Supports up to %s types." % int(NTypes))
|
||||
cog.outl("/// Defines <b>value</b> which is the largest alignment of all the parameters.")
|
||||
cog.outl("///\\ingroup largest")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.out("template <typename T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % int(NTypes))
|
||||
cog.outl("struct largest_alignment")
|
||||
cog.outl("{")
|
||||
cog.outl(" // Define 'largest_other' as 'largest_type' with all but the first parameter. ")
|
||||
cog.out(" typedef typename largest_alignment<")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::type largest_other;" % int(NTypes))
|
||||
cog.outl("")
|
||||
cog.outl(" // Set 'type' to be the largest of the first parameter and any of the others.")
|
||||
cog.outl(" // This is recursive.")
|
||||
cog.outl(" typedef typename etl::conditional<(etl::alignment_of<T1>::value > etl::alignment_of<largest_other>::value), // Boolean")
|
||||
cog.outl(" T1, // TrueType")
|
||||
cog.outl(" largest_other> // FalseType")
|
||||
cog.outl(" ::type type; // The largest type of the two.")
|
||||
cog.outl("")
|
||||
cog.outl(" // The largest alignment.")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" value = etl::alignment_of<type>::value")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// Specialisation for one template parameter.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T1>")
|
||||
cog.out("struct largest_alignment<T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("void, ")
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void>")
|
||||
cog.outl("{")
|
||||
cog.outl(" typedef T1 type;")
|
||||
cog.outl("")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" value = etl::alignment_of<type>::value")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Defines a type that is as larger or larger than the specified type.
|
||||
/// Will return the specified type is there is not a larger type.
|
||||
///\\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct larger_int_type
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
|
||||
|
||||
typedef typename etl::smallest_int_for_bits<etl::integral_limits<typename etl::make_signed<T>::type>::bits + 1>::type type;
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
using larger_int_type_t = typename larger_int_type<T>::type;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Defines a type that is as larger or larger than the specified type.
|
||||
/// Will return the specified type is there is not a larger type.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct larger_uint_type
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
|
||||
|
||||
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<typename etl::make_unsigned<T>::type>::bits + 1>::type type;
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
using larger_uint_type_t = typename larger_uint_type<T>::type;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Defines a type that is as larger or larger than the specified type.
|
||||
/// Will return the specified type is there is not a larger type.
|
||||
/// The returned type will be of the same sign.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T, bool IS_SIGNED = etl::is_signed<T>::value>
|
||||
struct larger_type;
|
||||
|
||||
template <typename T>
|
||||
struct larger_type<T, false>
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
|
||||
|
||||
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<T>::bits + 1>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct larger_type<T, true>
|
||||
{
|
||||
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
|
||||
|
||||
typedef typename etl::smallest_int_for_bits<etl::integral_limits<T>::bits + 1>::type type;
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename T>
|
||||
using larger_type_t = typename larger_type<T>::type;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11 && !defined(ETL_LARGEST_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
/// Template to determine the largest type, size and alignment.
|
||||
/// Defines <b>value</b> which is the largest type, size and alignment of all the parameters.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename... T>
|
||||
struct largest
|
||||
{
|
||||
using type = typename etl::largest_type<T...>::type;
|
||||
|
||||
enum
|
||||
{
|
||||
size = etl::largest_type<T...>::size,
|
||||
alignment = etl::largest_alignment<T...>::value
|
||||
};
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename... T>
|
||||
using largest_t = typename largest<T...>::type;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename... T>
|
||||
inline constexpr size_t largest_size = largest<T...>::size;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("/// Template to determine the largest type, size and alignment.")
|
||||
cog.outl("/// Supports up to %s types." % NTypes)
|
||||
cog.outl("/// Defines <b>value</b> which is the largest type, size and alignment of all the parameters.")
|
||||
cog.outl("///\\ingroup largest")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.out("template <typename T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % NTypes)
|
||||
cog.outl("struct largest")
|
||||
cog.outl("{")
|
||||
cog.out(" typedef typename etl::largest_type<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::type type;" % NTypes)
|
||||
cog.outl("")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.out(" size = etl::largest_type<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::size," % NTypes)
|
||||
cog.out(" alignment = etl::largest_alignment<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value" % NTypes)
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,898 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h
|
||||
// Where <n> is the maximum number of messages to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 messages...
|
||||
// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h
|
||||
//
|
||||
// See generate.bat
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef ETL_MESSAGE_ROUTER_INCLUDED
|
||||
#define ETL_MESSAGE_ROUTER_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "message.h"
|
||||
#include "shared_message.h"
|
||||
#if ETL_HAS_VIRTUAL_MESSAGES
|
||||
#include "message_packet.h"
|
||||
#endif
|
||||
#include "message_types.h"
|
||||
#include "alignment.h"
|
||||
#include "error_handler.h"
|
||||
#include "exception.h"
|
||||
#include "largest.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "successor.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Base exception class for message router
|
||||
//***************************************************************************
|
||||
class message_router_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
|
||||
: etl::exception(reason_, file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Router id is out of the legal range.
|
||||
//***************************************************************************
|
||||
class message_router_illegal_id : public etl::message_router_exception
|
||||
{
|
||||
public:
|
||||
|
||||
message_router_illegal_id(string_type file_name_, numeric_type line_number_)
|
||||
: message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_MESSAGE_ROUTER_FILE_ID"A"), file_name_, line_number_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Forward declare null message router functionality.
|
||||
//***************************************************************************
|
||||
class imessage_router;
|
||||
|
||||
etl::imessage_router& get_null_message_router();
|
||||
|
||||
//***************************************************************************
|
||||
/// This is the base of all message routers.
|
||||
//***************************************************************************
|
||||
class imessage_router : public etl::successor<imessage_router>
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~imessage_router() {}
|
||||
virtual void receive(const etl::imessage&) = 0;
|
||||
virtual bool accepts(etl::message_id_t) const = 0;
|
||||
virtual bool is_null_router() const = 0;
|
||||
virtual bool is_producer() const = 0;
|
||||
virtual bool is_consumer() const = 0;
|
||||
|
||||
//********************************************
|
||||
virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message)
|
||||
{
|
||||
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
|
||||
{
|
||||
receive(message);
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
virtual void receive(etl::shared_message shared_msg)
|
||||
{
|
||||
receive(shared_msg.get_message());
|
||||
}
|
||||
|
||||
//********************************************
|
||||
virtual void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
|
||||
{
|
||||
if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
|
||||
{
|
||||
receive(shared_msg);
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool accepts(const etl::imessage& msg) const
|
||||
{
|
||||
return accepts(msg.get_message_id());
|
||||
}
|
||||
|
||||
//********************************************
|
||||
etl::message_router_id_t get_message_router_id() const
|
||||
{
|
||||
return message_router_id;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
NULL_MESSAGE_ROUTER = 255,
|
||||
MESSAGE_BUS = 254,
|
||||
ALL_MESSAGE_ROUTERS = 253,
|
||||
MESSAGE_BROKER = 252,
|
||||
MESSAGE_ROUTER = 251,
|
||||
MAX_MESSAGE_ROUTER = 249
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
imessage_router(etl::message_router_id_t id_)
|
||||
: message_router_id(id_)
|
||||
{
|
||||
}
|
||||
|
||||
imessage_router(etl::message_router_id_t id_, imessage_router& successor_)
|
||||
: successor(successor_)
|
||||
, message_router_id(id_)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Disabled.
|
||||
imessage_router(const imessage_router&);
|
||||
imessage_router& operator =(const imessage_router&);
|
||||
|
||||
etl::message_router_id_t message_router_id;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// This router can be used as a sink for messages or a 'null source' router.
|
||||
//***************************************************************************
|
||||
class null_message_router : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
//********************************************
|
||||
null_message_router()
|
||||
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
|
||||
{
|
||||
}
|
||||
|
||||
//********************************************
|
||||
null_message_router(etl::imessage_router& successor_)
|
||||
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
|
||||
{
|
||||
}
|
||||
|
||||
//********************************************
|
||||
using etl::imessage_router::receive;
|
||||
|
||||
void receive(const etl::imessage& msg) ETL_OVERRIDE
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
using etl::imessage_router::accepts;
|
||||
|
||||
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
return get_successor().accepts(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_producer() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_consumer() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
static null_message_router& instance()
|
||||
{
|
||||
static null_message_router nmr;
|
||||
return nmr;
|
||||
}
|
||||
};
|
||||
|
||||
//***********************************************
|
||||
/// null message router functionality.
|
||||
inline etl::imessage_router& get_null_message_router()
|
||||
{
|
||||
return etl::null_message_router::instance();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// This router can be used as a producer-only of messages, such an interrupt routine.
|
||||
//***************************************************************************
|
||||
class message_producer : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
//********************************************
|
||||
message_producer()
|
||||
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
|
||||
{
|
||||
}
|
||||
|
||||
//********************************************
|
||||
message_producer(etl::imessage_router& successor_)
|
||||
: imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
|
||||
{
|
||||
}
|
||||
|
||||
//********************************************
|
||||
message_producer(etl::message_router_id_t id_)
|
||||
: imessage_router(id_)
|
||||
{
|
||||
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
|
||||
}
|
||||
|
||||
//********************************************
|
||||
message_producer(etl::message_router_id_t id_, etl::imessage_router& successor_)
|
||||
: imessage_router(id_, successor_)
|
||||
{
|
||||
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
|
||||
}
|
||||
|
||||
//********************************************
|
||||
using etl::imessage_router::receive;
|
||||
|
||||
void receive(const etl::imessage& msg) ETL_OVERRIDE
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
using etl::imessage_router::accepts;
|
||||
|
||||
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
return get_successor().accepts(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_producer() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_consumer() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Is T ultimately derived from etl::imessage_router?
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct is_message_router : public etl::bool_constant<etl::is_base_of<etl::imessage_router, typename etl::remove_cvref<T>::type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a message to a router.
|
||||
//***************************************************************************
|
||||
template <typename TRouter, typename TMessage>
|
||||
static
|
||||
typename etl::enable_if<etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
|
||||
send_message(TRouter& destination,
|
||||
const TMessage& message)
|
||||
{
|
||||
destination.receive(message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a shared message to a router.
|
||||
//***************************************************************************
|
||||
template <typename TRouter>
|
||||
static
|
||||
typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type
|
||||
send_message(TRouter& destination,
|
||||
etl::shared_message message)
|
||||
{
|
||||
destination.receive(message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a message to a router with a particular id.
|
||||
//***************************************************************************
|
||||
template <typename TRouter, typename TMessage>
|
||||
static
|
||||
typename etl::enable_if<etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
|
||||
send_message(TRouter& destination,
|
||||
etl::message_router_id_t id,
|
||||
const TMessage& message)
|
||||
{
|
||||
destination.receive(id, message);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Send a shared message to a router with a particular id.
|
||||
//***************************************************************************
|
||||
template <typename TRouter>
|
||||
static
|
||||
typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type
|
||||
send_message(TRouter& destination,
|
||||
etl::message_router_id_t id,
|
||||
etl::shared_message message)
|
||||
{
|
||||
destination.receive(id, message);
|
||||
}
|
||||
|
||||
//*************************************************************************************************
|
||||
// For C++17 and above.
|
||||
//*************************************************************************************************
|
||||
#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
// The definition for all message types.
|
||||
//***************************************************************************
|
||||
template <typename TDerived, typename... TMessageTypes>
|
||||
class message_router : public imessage_router
|
||||
{
|
||||
public:
|
||||
|
||||
#if ETL_HAS_VIRTUAL_MESSAGES
|
||||
typedef etl::message_packet<TMessageTypes...> message_packet;
|
||||
#endif
|
||||
|
||||
//**********************************************
|
||||
message_router()
|
||||
: imessage_router(etl::imessage_router::MESSAGE_ROUTER)
|
||||
{
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
message_router(etl::imessage_router& successor_)
|
||||
: imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
|
||||
{
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
message_router(etl::message_router_id_t id_)
|
||||
: imessage_router(id_)
|
||||
{
|
||||
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
|
||||
: imessage_router(id_, successor_)
|
||||
{
|
||||
ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
using etl::imessage_router::receive;
|
||||
|
||||
void receive(const etl::imessage& msg) ETL_OVERRIDE
|
||||
{
|
||||
const bool was_handled = (receive_message_type<TMessageTypes>(msg) || ...);
|
||||
|
||||
if (!was_handled)
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TMessage, typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value, int>::type = 0>
|
||||
void receive(const TMessage& msg)
|
||||
{
|
||||
if constexpr (etl::is_one_of<TMessage, TMessageTypes...>::value)
|
||||
{
|
||||
static_cast<TDerived*>(this)->on_receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
get_successor().receive(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cast<TDerived*>(this)->on_receive_unknown(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**********************************************
|
||||
using imessage_router::accepts;
|
||||
|
||||
bool accepts(etl::message_id_t id) const ETL_OVERRIDE
|
||||
{
|
||||
return (accepts_type<TMessageTypes>(id) || ...);
|
||||
}
|
||||
|
||||
//********************************************
|
||||
ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_producer() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
bool is_consumer() const ETL_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
bool receive_message_type(const etl::imessage& msg)
|
||||
{
|
||||
if (TMessage::ID == msg.get_message_id())
|
||||
{
|
||||
static_cast<TDerived*>(this)->on_receive(static_cast<const TMessage&>(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************
|
||||
template <typename TMessage>
|
||||
bool accepts_type(etl::message_id_t id) const
|
||||
{
|
||||
if (TMessage::ID == id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_successor())
|
||||
{
|
||||
return get_successor().accepts(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#else
|
||||
//*************************************************************************************************
|
||||
// For C++14 and below.
|
||||
//*************************************************************************************************
|
||||
/*[[[cog
|
||||
import cog
|
||||
################################################
|
||||
# The first definition for all of the messages.
|
||||
################################################
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// The definition for all %s message types." % Handlers)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TDerived,")
|
||||
cog.out(" ")
|
||||
cog.out("typename T1, ")
|
||||
for n in range(2, int(Handlers)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % int(Handlers))
|
||||
cog.out("class message_router")
|
||||
cog.outl(" : public imessage_router")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
|
||||
cog.out(" typedef etl::message_packet<")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl(" T%s> message_packet;" % int(Handlers))
|
||||
cog.outl("#endif")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::message_router_id_t id_)")
|
||||
cog.outl(" : imessage_router(id_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)")
|
||||
cog.outl(" : imessage_router(id_, successor_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router()")
|
||||
cog.outl(" : imessage_router(etl::imessage_router::MESSAGE_ROUTER)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::imessage_router& successor_)")
|
||||
cog.outl(" : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" using etl::imessage_router::receive;")
|
||||
cog.outl("")
|
||||
cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" const etl::message_id_t id = msg.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
for n in range(1, int(Handlers) + 1):
|
||||
cog.out(" case T%d::ID:" % n)
|
||||
cog.out(" static_cast<TDerived*>(this)->on_receive(static_cast<const T%d&>(msg));" % n)
|
||||
cog.outl(" break;")
|
||||
cog.outl(" default:")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" get_successor().receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive_unknown(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" template <typename TMessage>")
|
||||
cog.out(" typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value && etl::is_one_of<TMessage, ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::value, void>::type" % int(Handlers))
|
||||
cog.outl(" receive(const TMessage& msg)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" template <typename TMessage>")
|
||||
cog.out(" typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value && !etl::is_one_of<TMessage, ")
|
||||
for n in range(1, int(Handlers)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::value, void>::type" % int(Handlers))
|
||||
cog.outl(" receive(const TMessage& msg)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" get_successor().receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive_unknown(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" using imessage_router::accepts;")
|
||||
cog.outl("")
|
||||
cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(Handlers) + 1):
|
||||
cog.out("case T%d::ID: " % n)
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" default:")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return get_successor().accepts(id);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return false;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return false;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" bool is_producer() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" bool is_consumer() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
|
||||
####################################
|
||||
# All of the other specialisations.
|
||||
####################################
|
||||
for n in range(int(Handlers) - 1, 0, -1):
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
if n == 1:
|
||||
cog.outl("// Specialisation for %d message type." % n)
|
||||
else:
|
||||
cog.outl("// Specialisation for %d message types." % n)
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename TDerived, ")
|
||||
cog.out(" ")
|
||||
for t in range(1, n):
|
||||
cog.out("typename T%d, " % t)
|
||||
if t % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%d>" % n)
|
||||
cog.out("class message_router<TDerived, ")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("T%d, " % t)
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
for t in range(n + 1, int(Handlers)):
|
||||
cog.out("void, ")
|
||||
if t % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void>")
|
||||
cog.outl(" : public imessage_router")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl("#if ETL_HAS_VIRTUAL_MESSAGES")
|
||||
cog.out(" typedef etl::message_packet<")
|
||||
for t in range(1, n):
|
||||
cog.out("T%s, " % t)
|
||||
cog.outl(" T%s> message_packet;" % n)
|
||||
cog.outl("#endif")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::message_router_id_t id_)")
|
||||
cog.outl(" : imessage_router(id_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)")
|
||||
cog.outl(" : imessage_router(id_, successor_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router()")
|
||||
cog.outl(" : imessage_router(etl::imessage_router::MESSAGE_ROUTER)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" message_router(etl::imessage_router& successor_)")
|
||||
cog.outl(" : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" using etl::imessage_router::receive;")
|
||||
cog.outl("")
|
||||
cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" const size_t id = msg.get_message_id();")
|
||||
cog.outl("")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
for t in range(1, n + 1):
|
||||
cog.out(" case T%d::ID:" % t)
|
||||
cog.out(" static_cast<TDerived*>(this)->on_receive(static_cast<const T%d&>(msg));" % t)
|
||||
cog.outl(" break;")
|
||||
cog.outl(" default:")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" get_successor().receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive_unknown(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" break;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" template <typename TMessage>")
|
||||
cog.out(" typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value && etl::is_one_of<TMessage, ")
|
||||
for t in range(1, n):
|
||||
cog.out("T%s, " % t)
|
||||
cog.outl("T%s>::value, void>::type" % n)
|
||||
cog.outl(" receive(const TMessage& msg)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" template <typename TMessage>")
|
||||
cog.out(" typename etl::enable_if<etl::is_base_of<imessage, TMessage>::value && !etl::is_one_of<TMessage, ")
|
||||
for t in range(1, n):
|
||||
cog.out("T%s, " % t)
|
||||
cog.outl("T%s>::value, void>::type" % n)
|
||||
cog.outl(" receive(const TMessage& msg)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" get_successor().receive(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" static_cast<TDerived*>(this)->on_receive_unknown(msg);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl("")
|
||||
cog.outl(" //**********************************************")
|
||||
cog.outl(" using imessage_router::accepts;")
|
||||
cog.outl("")
|
||||
cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" switch (id)")
|
||||
cog.outl(" {")
|
||||
cog.out(" ")
|
||||
for t in range(1, n + 1):
|
||||
cog.out("case T%d::ID: " % t)
|
||||
if t % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" default:")
|
||||
cog.outl(" {")
|
||||
cog.outl(" if (has_successor())")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return get_successor().accepts(id);")
|
||||
cog.outl(" }")
|
||||
cog.outl(" else")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return false;")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return false;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" bool is_producer() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //********************************************")
|
||||
cog.outl(" bool is_consumer() const ETL_OVERRIDE")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return true;")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,432 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2014 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -osmallest.h -DNTypes=<n> smallest_generator.h
|
||||
// Where <n> is the number of types to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 types...
|
||||
// python -m cogapp -d -e -osmallest.h -DNTypes=16 smallest_generator.h
|
||||
//
|
||||
// See generate.bat
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef ETL_SMALLEST_INCLUDED
|
||||
#define ETL_SMALLEST_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "integral_limits.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
///\defgroup smallest smallest
|
||||
///\ingroup utilities
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP11 && !defined(ETL_SMALLEST_TYPE_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
/// Template to determine the largest type and size.
|
||||
/// Defines 'value_type' which is the type of the largest parameter.
|
||||
/// Defines 'size' which is the size of the largest parameter.
|
||||
///\ingroup largest
|
||||
//***************************************************************************
|
||||
template <typename T1, typename... TRest>
|
||||
class smallest_type
|
||||
{
|
||||
private:
|
||||
|
||||
// Define 'smallest_other' as 'smallest_type' with all but the first parameter.
|
||||
using smallest_other = typename smallest_type<TRest...>::type;
|
||||
|
||||
public:
|
||||
|
||||
// Set 'type' to be the smallest of the first parameter and any of the others.
|
||||
// This is recursive.
|
||||
using type = typename etl::conditional<(etl::size_of<T1>::value < etl::size_of<smallest_other>::value), // Boolean
|
||||
T1, // TrueType
|
||||
smallest_other> // FalseType
|
||||
::type; // The smallest type of the two.
|
||||
|
||||
// The size of the smallest type.
|
||||
enum
|
||||
{
|
||||
size = etl::size_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Specialisation for one template parameter.
|
||||
//***************************************************************************
|
||||
template <typename T1>
|
||||
class smallest_type<T1>
|
||||
{
|
||||
public:
|
||||
|
||||
using type = T1;
|
||||
|
||||
enum
|
||||
{
|
||||
size = etl::size_of<type>::value
|
||||
};
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <typename... T>
|
||||
using smallest_type_t = typename smallest_type<T...>::type;
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename... T>
|
||||
constexpr size_t smallest_type_v = smallest_type<T...>::size;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("/// Template to determine the smallest type and size.")
|
||||
cog.outl("/// Supports up to %s types." % NTypes)
|
||||
cog.outl("/// Defines 'value_type' which is the type of the smallest parameter.")
|
||||
cog.outl("/// Defines 'size' which is the size of the smallest parameter.")
|
||||
cog.outl("///\\ingroup smallest")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.out("template <typename T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("typename T%s = void, " % n)
|
||||
if n % 4 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s = void>" % int(NTypes))
|
||||
cog.outl("struct smallest_type")
|
||||
cog.outl("{")
|
||||
cog.outl("private:")
|
||||
cog.outl("")
|
||||
cog.outl(" // Declaration.")
|
||||
cog.outl(" template <bool Boolean, typename TrueType, typename FalseType>")
|
||||
cog.outl(" struct choose_type;")
|
||||
cog.outl("")
|
||||
cog.outl(" // Specialisation for 'true'.")
|
||||
cog.outl(" // Defines 'type' as 'TrueType'.")
|
||||
cog.outl(" template <typename TrueType, typename FalseType>")
|
||||
cog.outl(" struct choose_type<true, TrueType, FalseType>")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef TrueType type;")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" // Specialisation for 'false'. ")
|
||||
cog.outl(" // Defines 'type' as 'FalseType'.")
|
||||
cog.outl(" template <typename TrueType, typename FalseType>")
|
||||
cog.outl(" struct choose_type<false, TrueType, FalseType>")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef FalseType type;")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" // Define 'smallest_other' as 'smallest_type' with all but the first parameter. ")
|
||||
cog.out(" typedef typename smallest_type<")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::type smallest_other;" % int(NTypes))
|
||||
cog.outl("")
|
||||
cog.outl(" // Set 'type' to be the smallest of the first parameter and any of the others.")
|
||||
cog.outl(" // This is recursive.")
|
||||
cog.outl(" typedef typename choose_type<(sizeof(T1) < sizeof(smallest_other)), // Boolean")
|
||||
cog.outl(" T1, // TrueType")
|
||||
cog.outl(" smallest_other> // FalseType")
|
||||
cog.outl(" ::type type; // The smallest type of the two.")
|
||||
cog.outl("")
|
||||
cog.outl(" // The size of the smallest type.")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" size = sizeof(type)")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// Specialisation for one template parameter.")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T1>")
|
||||
cog.out("struct smallest_type<T1, ")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.out("void, ")
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("void>")
|
||||
cog.outl("{")
|
||||
cog.outl(" typedef T1 type;")
|
||||
cog.outl("")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" size = sizeof(type)")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
|
||||
namespace private_smallest
|
||||
{
|
||||
//*************************************************************************
|
||||
// Determine the type to hold the number of bits based on the index.
|
||||
//*************************************************************************
|
||||
template <int index>
|
||||
struct best_fit_uint_type;
|
||||
|
||||
//*************************************************************************
|
||||
// Less than or equal to 8 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_uint_type<0>
|
||||
{
|
||||
typedef uint_least8_t type;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
// 9 to 16 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_uint_type<1>
|
||||
{
|
||||
typedef uint_least16_t type;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
// 17 to 31 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_uint_type<2>
|
||||
{
|
||||
typedef uint_least32_t type;
|
||||
};
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
//*************************************************************************
|
||||
// Greater than 32 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_uint_type<3>
|
||||
{
|
||||
typedef uint_least64_t type;
|
||||
};
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
// Determine the type to hold the number of bits based on the index.
|
||||
//*************************************************************************
|
||||
template <int index>
|
||||
struct best_fit_int_type;
|
||||
|
||||
//*************************************************************************
|
||||
// Less than or equal to 8 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_int_type<0>
|
||||
{
|
||||
typedef int_least8_t type;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
// 9 to 16 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_int_type<1>
|
||||
{
|
||||
typedef int_least16_t type;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
// 17 to 31 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_int_type<2>
|
||||
{
|
||||
typedef int_least32_t type;
|
||||
};
|
||||
|
||||
#if ETL_USING_64BIT_TYPES
|
||||
//*************************************************************************
|
||||
// Greater than 32 bits.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
struct best_fit_int_type<3>
|
||||
{
|
||||
typedef int_least64_t type;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Template to determine the smallest unsigned int type that can contain a
|
||||
/// value with the specified number of bits.
|
||||
/// Defines 'type' which is the type of the smallest unsigned integer.
|
||||
///\ingroup smallest
|
||||
//***************************************************************************
|
||||
template <size_t NBITS>
|
||||
struct smallest_uint_for_bits
|
||||
{
|
||||
private:
|
||||
|
||||
// Determines the index of the best unsigned type for the required number of bits.
|
||||
static ETL_CONSTANT int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
|
||||
((NBITS > 16) ? 1 : 0) +
|
||||
((NBITS > 32) ? 1 : 0);
|
||||
|
||||
public:
|
||||
|
||||
typedef typename private_smallest::best_fit_uint_type<TYPE_INDEX>::type type;
|
||||
};
|
||||
|
||||
template <size_t NBITS>
|
||||
ETL_CONSTANT int smallest_uint_for_bits<NBITS>::TYPE_INDEX;
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <size_t NBITS>
|
||||
using smallest_uint_for_bits_t = typename smallest_uint_for_bits<NBITS>::type;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Template to determine the smallest signed int type that can contain a
|
||||
/// value with the specified number of bits.
|
||||
/// Defines 'type' which is the type of the smallest signed integer.
|
||||
///\ingroup smallest
|
||||
//***************************************************************************
|
||||
template <size_t NBITS>
|
||||
struct smallest_int_for_bits
|
||||
{
|
||||
private:
|
||||
|
||||
// Determines the index of the best unsigned type for the required number of bits.
|
||||
static ETL_CONSTANT int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
|
||||
((NBITS > 16) ? 1 : 0) +
|
||||
((NBITS > 32) ? 1 : 0);
|
||||
|
||||
public:
|
||||
|
||||
typedef typename private_smallest::best_fit_int_type<TYPE_INDEX>::type type;
|
||||
};
|
||||
|
||||
template <size_t NBITS>
|
||||
ETL_CONSTANT int smallest_int_for_bits<NBITS>::TYPE_INDEX;
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <size_t NBITS>
|
||||
using smallest_int_for_bits_t = typename smallest_int_for_bits<NBITS>::type;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Template to determine the smallest unsigned int type that can contain the
|
||||
/// specified unsigned value.
|
||||
/// Defines 'type' which is the type of the smallest unsigned integer.
|
||||
///\ingroup smallest
|
||||
//***************************************************************************
|
||||
template <uintmax_t VALUE>
|
||||
struct smallest_uint_for_value
|
||||
{
|
||||
private:
|
||||
|
||||
// Determines the index of the best unsigned type for the required value.
|
||||
static ETL_CONSTANT int TYPE_INDEX = ((VALUE > UINT_LEAST8_MAX) ? 1 : 0) +
|
||||
((VALUE > UINT16_MAX) ? 1 : 0) +
|
||||
((VALUE > UINT32_MAX) ? 1 : 0);
|
||||
|
||||
public:
|
||||
|
||||
typedef typename private_smallest::best_fit_uint_type<TYPE_INDEX>::type type;
|
||||
};
|
||||
|
||||
template <uintmax_t VALUE>
|
||||
ETL_CONSTANT int smallest_uint_for_value<VALUE>::TYPE_INDEX;
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <uintmax_t VALUE>
|
||||
using smallest_uint_for_value_t = typename smallest_uint_for_value<VALUE>::type;
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Template to determine the smallest int type that can contain the
|
||||
/// specified signed value.
|
||||
/// Defines 'type' which is the type of the smallest signed integer.
|
||||
///\ingroup smallest
|
||||
//***************************************************************************
|
||||
template <intmax_t VALUE>
|
||||
struct smallest_int_for_value
|
||||
{
|
||||
private:
|
||||
|
||||
// Determines the index of the best signed type for the required value.
|
||||
static ETL_CONSTANT int TYPE_INDEX = (((VALUE > intmax_t(INT_LEAST8_MAX)) || (VALUE < intmax_t(INT_LEAST8_MIN))) ? 1 : 0) +
|
||||
(((VALUE > intmax_t(INT16_MAX)) || (VALUE < intmax_t(INT16_MIN))) ? 1 : 0) +
|
||||
(((VALUE > intmax_t(INT32_MAX)) || (VALUE < intmax_t(INT32_MIN))) ? 1 : 0);
|
||||
|
||||
public:
|
||||
|
||||
typedef typename private_smallest::best_fit_int_type<TYPE_INDEX>::type type;
|
||||
};
|
||||
|
||||
template <intmax_t VALUE>
|
||||
ETL_CONSTANT int smallest_int_for_value<VALUE>::TYPE_INDEX;
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
template <intmax_t VALUE>
|
||||
using smallest_int_for_value_t = typename smallest_int_for_value<VALUE>::type;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,337 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_TYPE_LOOKUP_INCLUDED
|
||||
#define ETL_TYPE_LOOKUP_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "type_traits.h"
|
||||
#include "static_assert.h"
|
||||
#include "integral_limits.h"
|
||||
#include "null_type.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// The type/id pair type to use for type/id lookup template parameters.
|
||||
//***************************************************************************
|
||||
template <typename T, int ID_>
|
||||
struct type_id_pair
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
enum
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The type/type pair type to use for type/type lookup template parameters.
|
||||
//***************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
struct type_type_pair
|
||||
{
|
||||
typedef T1 type1;
|
||||
typedef T2 type2;
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP11 && !defined(ETL_TYPE_SELECT_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
// type_id_lookup
|
||||
//***************************************************************************
|
||||
template <typename... TTypes>
|
||||
struct type_id_lookup
|
||||
{
|
||||
private:
|
||||
|
||||
// The type for no match.
|
||||
struct nulltype {};
|
||||
|
||||
// For N type pairs.
|
||||
template <size_t ID, typename T1, typename... TRest>
|
||||
struct type_from_id_helper
|
||||
{
|
||||
using type = typename etl::conditional<ID == T1::ID,
|
||||
typename T1::type,
|
||||
typename type_from_id_helper<ID, TRest...>::type>::type;
|
||||
};
|
||||
|
||||
// Specialisation for 1 type pair.
|
||||
template <size_t ID, typename T1>
|
||||
struct type_from_id_helper<ID, T1>
|
||||
{
|
||||
using type = typename etl::conditional<ID == T1::ID,
|
||||
typename T1::type,
|
||||
nulltype>::type;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//************************************
|
||||
// type_from_id
|
||||
//************************************
|
||||
template <int ID>
|
||||
struct type_from_id
|
||||
{
|
||||
using type = typename type_from_id_helper<ID, TTypes...>::type;
|
||||
|
||||
static_assert(!(etl::is_same<nulltype, type>::value), "Invalid id");
|
||||
};
|
||||
|
||||
template <int ID>
|
||||
using type_from_id_t = typename type_from_id<ID>::type;
|
||||
|
||||
private:
|
||||
|
||||
static constexpr size_t UNKNOWN = etl::integral_limits<size_t>::max;
|
||||
|
||||
// For N type pairs.
|
||||
template <typename T, typename T1, typename... TRest>
|
||||
struct id_from_type_helper
|
||||
{
|
||||
static constexpr size_t value = etl::is_same<T, typename T1::type>::value ? size_t(T1::ID) : id_from_type_helper<T, TRest...>::value;
|
||||
};
|
||||
|
||||
// Specialisation for 1 type pair.
|
||||
template <typename T, typename T1>
|
||||
struct id_from_type_helper<T, T1>
|
||||
{
|
||||
static constexpr size_t value = etl::is_same<T, typename T1::type>::value ? size_t(T1::ID) : UNKNOWN;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//************************************
|
||||
// id_from_type
|
||||
//************************************
|
||||
template <typename T>
|
||||
struct id_from_type
|
||||
{
|
||||
static constexpr size_t value = id_from_type_helper<T, TTypes...>::value;
|
||||
|
||||
static_assert(value != UNKNOWN, "Invalid type");
|
||||
};
|
||||
|
||||
#if ETL_USING_CPP17
|
||||
template <typename T>
|
||||
static constexpr size_t id_from_type_v = id_from_type<T>::value;
|
||||
#endif
|
||||
|
||||
//************************************
|
||||
template <typename T>
|
||||
static unsigned int get_id_from_type(const T&)
|
||||
{
|
||||
return get_id_from_type<T>();
|
||||
}
|
||||
|
||||
//************************************
|
||||
template <typename T>
|
||||
static unsigned int get_id_from_type()
|
||||
{
|
||||
return id_from_type<T>::value;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// type_type_lookup
|
||||
//***************************************************************************
|
||||
template <typename... TTypes>
|
||||
class type_type_lookup
|
||||
{
|
||||
private:
|
||||
|
||||
// The type for no match.
|
||||
struct nulltype {};
|
||||
|
||||
template <typename T, typename T1, typename... TRest>
|
||||
struct type_from_type_helper
|
||||
{
|
||||
using type = typename etl::conditional<etl::is_same<T, typename T1::type1>::value,
|
||||
typename T1::type2,
|
||||
typename type_from_type_helper<T, TRest...>::type>::type;
|
||||
};
|
||||
|
||||
template <typename T, typename T1>
|
||||
struct type_from_type_helper<T, T1>
|
||||
{
|
||||
using type = typename etl::conditional<etl::is_same<T, typename T1::type1>::value,
|
||||
typename T1::type2,
|
||||
nulltype>::type;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template <typename T>
|
||||
class type_from_type
|
||||
{
|
||||
public:
|
||||
|
||||
// The matched type or nulltype
|
||||
using type = typename type_from_type_helper<T, TTypes...>::type;
|
||||
|
||||
static_assert(!etl::is_same<type, nulltype>::value, "Type match not found");
|
||||
};
|
||||
|
||||
// Template alias.
|
||||
template <typename T>
|
||||
using type_from_type_t = typename type_from_type<T>::type;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// For %s types." % int(NTypes))
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T1,")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.outl(" typename T%s = etl::type_id_pair<etl::null_type<0>, -%s>," %(n, n))
|
||||
cog.outl(" typename T%s = etl::type_id_pair<etl::null_type<0>, -%s> >" %(NTypes, NTypes))
|
||||
cog.outl("struct type_id_lookup")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" //************************************")
|
||||
cog.outl(" template <int ID>")
|
||||
cog.outl(" struct type_from_id")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef ")
|
||||
for n in range(1, int(NTypes) + 1):
|
||||
cog.outl(" typename etl::conditional<ID == T%s::ID, typename T%s::type," %(n, n))
|
||||
cog.out(" etl::null_type<0> >")
|
||||
for n in range(1, int(NTypes) + 1):
|
||||
if n == int(NTypes):
|
||||
cog.outl("::type type;")
|
||||
else:
|
||||
cog.out("::type>")
|
||||
if n % 4 == 0:
|
||||
if n != int(NTypes):
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("")
|
||||
cog.outl(" ETL_STATIC_ASSERT(!(etl::is_same<etl::null_type<0>, type>::value), \"Invalid id\");")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" //************************************")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" UNKNOWN = UINT_MAX")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" template <typename T>")
|
||||
cog.outl(" struct id_from_type")
|
||||
cog.outl(" {")
|
||||
cog.outl(" enum")
|
||||
cog.outl(" {")
|
||||
cog.outl(" value =")
|
||||
for n in range(1, int(NTypes) + 1) :
|
||||
cog.outl(" (unsigned int) etl::is_same<T, typename T%s::type>::value ? (unsigned int)T%s::ID :" % (n, n))
|
||||
cog.outl(" (unsigned int) UNKNOWN")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" ETL_STATIC_ASSERT(((unsigned int)value != (unsigned int)UNKNOWN), \"Invalid type\");")
|
||||
cog.outl(" };")
|
||||
cog.outl("")
|
||||
cog.outl(" //************************************")
|
||||
cog.outl(" template <typename T>")
|
||||
cog.outl(" static unsigned int get_id_from_type(const T&)")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return get_id_from_type<T>();")
|
||||
cog.outl(" }")
|
||||
cog.outl("")
|
||||
cog.outl(" //************************************")
|
||||
cog.outl(" template <typename T>")
|
||||
cog.outl(" static unsigned int get_id_from_type()")
|
||||
cog.outl(" {")
|
||||
cog.outl(" return id_from_type<T>::value;")
|
||||
cog.outl(" }")
|
||||
cog.outl("};")
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// For %s types." % int(NTypes))
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T1,")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.outl(" typename T%s = etl::type_type_pair<etl::null_type<0>, etl::null_type<0> >," %n)
|
||||
cog.outl(" typename T%s = etl::type_type_pair<etl::null_type<0>, etl::null_type<0> > >" %NTypes)
|
||||
cog.outl("struct type_type_lookup")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" //************************************")
|
||||
cog.outl(" template <typename T>")
|
||||
cog.outl(" struct type_from_type")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef ")
|
||||
for n in range(1, int(NTypes) + 1):
|
||||
cog.outl(" typename etl::conditional<etl::is_same<T, typename T%s::type1>::value, typename T%s::type2," %(n, n))
|
||||
cog.out(" etl::null_type<0> >")
|
||||
for n in range(1, int(NTypes) + 1):
|
||||
if n == int(NTypes):
|
||||
cog.outl("::type type;")
|
||||
else:
|
||||
cog.out("::type>")
|
||||
if n % 8 == 0:
|
||||
if n != int(NTypes):
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("")
|
||||
cog.outl(" ETL_STATIC_ASSERT(!(etl::is_same<etl::null_type<0>, type>::value), \"Invalid type\");")
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,177 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2018 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_TYPE_SELECT_INCLUDED
|
||||
#define ETL_TYPE_SELECT_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
#include "null_type.h"
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP11 && !defined(ETL_TYPE_SELECT_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
// Variadic version.
|
||||
//***************************************************************************
|
||||
template <typename... TTypes>
|
||||
struct type_select
|
||||
{
|
||||
private:
|
||||
|
||||
//***********************************
|
||||
template <size_t ID, size_t N, typename T1, typename... TRest>
|
||||
struct type_select_helper
|
||||
{
|
||||
using type = typename etl::conditional<ID == N,
|
||||
T1,
|
||||
typename type_select_helper<ID, N + 1, TRest...>::type>::type;
|
||||
};
|
||||
|
||||
//***********************************
|
||||
template <size_t ID, size_t N, typename T1>
|
||||
struct type_select_helper<ID, N, T1>
|
||||
{
|
||||
using type = T1;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template <size_t ID>
|
||||
struct select
|
||||
{
|
||||
static_assert(ID < sizeof...(TTypes), "Illegal type_select::select index");
|
||||
|
||||
using type = typename type_select_helper<ID, 0, TTypes...>::type;
|
||||
};
|
||||
|
||||
template <size_t ID>
|
||||
using select_t = typename select<ID>::type;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
// Select type alias
|
||||
//***************************************************************************
|
||||
template <size_t N, typename... TTypes>
|
||||
using type_select_t = typename etl::type_select<TTypes...>:: template select_t<N>;
|
||||
|
||||
#else
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// For %s types." % int(NTypes))
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("template <typename T0,")
|
||||
for n in range(1, int(NTypes) - 1):
|
||||
cog.outl(" typename T%s = void," % n)
|
||||
cog.outl(" typename T%s = void>" %(int(NTypes) - 1))
|
||||
cog.outl("struct type_select")
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl("")
|
||||
cog.outl(" template <size_t ID>")
|
||||
cog.outl(" struct select")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef typename etl::conditional<ID == 0, T0,")
|
||||
for n in range(1, int(NTypes)) :
|
||||
cog.outl(" typename etl::conditional<ID == %s, T%s," % (n, n))
|
||||
cog.outl(" etl::null_type<0> >")
|
||||
cog.out(" ")
|
||||
for n in range(1, int(NTypes)) :
|
||||
cog.out("::type>")
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("::type type;")
|
||||
cog.outl("");
|
||||
cog.outl(" ETL_STATIC_ASSERT(ID < %s, \"Invalid ID\");" % int(NTypes));
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
|
||||
for s in range(int(NTypes) - 1, 0, -1):
|
||||
cog.outl("")
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// For %s types." % int(s))
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.out("template <")
|
||||
for n in range(0, s - 1):
|
||||
cog.outl("typename T%s, " % n)
|
||||
cog.out(" ")
|
||||
cog.outl("typename T%s>" % (s - 1))
|
||||
cog.out("struct type_select<")
|
||||
for n in range(0, s - 1):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>" % (s - 1))
|
||||
cog.outl("{")
|
||||
cog.outl("public:")
|
||||
cog.outl(" template <size_t ID>")
|
||||
cog.outl(" struct select")
|
||||
cog.outl(" {")
|
||||
cog.outl(" typedef typename etl::conditional<ID == 0, T0,")
|
||||
for n in range(1, s) :
|
||||
cog.outl(" typename etl::conditional<ID == %s, T%s," % (n, n))
|
||||
cog.outl(" etl::null_type<0> >")
|
||||
cog.out(" ")
|
||||
for n in range(1, s) :
|
||||
cog.out("::type>")
|
||||
if n % 8 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("::type type;")
|
||||
cog.outl("");
|
||||
cog.outl(" ETL_STATIC_ASSERT(ID < %s, \"Invalid ID\");" % s);
|
||||
cog.outl(" };")
|
||||
cog.outl("};")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,620 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#if 0")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("#endif")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("//***************************************************************************")
|
||||
cog.outl("// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.")
|
||||
cog.outl("//***************************************************************************")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//***************************************************************************
|
||||
// To generate to header file, run this at the command line.
|
||||
// Note: You will need Python and COG installed.
|
||||
//
|
||||
// python -m cogapp -d -e -ovariant_pool.h -DNTypes=<n> variant_pool_generator.h
|
||||
// Where <n> is the number of types to support.
|
||||
//
|
||||
// e.g.
|
||||
// To generate handlers for up to 16 types...
|
||||
// python -m cogapp -d -e -ovariant_pool.h -DNTypes=16 variant_pool_generator.h
|
||||
//
|
||||
// See generate.bat
|
||||
//***************************************************************************
|
||||
|
||||
#ifndef ETL_VARIANT_POOL_INCLUDED
|
||||
#define ETL_VARIANT_POOL_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "pool.h"
|
||||
#include "type_traits.h"
|
||||
#include "static_assert.h"
|
||||
#include "largest.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
#if ETL_USING_CPP11 && !defined(ETL_VARIANT_POOL_FORCE_CPP03_IMPLEMENTATION)
|
||||
//***************************************************************************
|
||||
template <size_t MAX_SIZE_, typename ... Ts>
|
||||
class variant_pool
|
||||
: public etl::generic_pool<etl::largest<Ts...>::size,
|
||||
etl::largest<Ts...>::alignment,
|
||||
MAX_SIZE_>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef etl::generic_pool<etl::largest<Ts...>::size,
|
||||
etl::largest<Ts...>::alignment,
|
||||
MAX_SIZE_> base_t;
|
||||
|
||||
static const size_t MAX_SIZE = MAX_SIZE_;
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
variant_pool()
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object from a type. Variadic parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename... Args>
|
||||
T* create(Args&&... args)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_one_of<T, Ts...>::value), "Unsupported type");
|
||||
|
||||
return base_t::template create<T>(etl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_one_of<T, Ts...>::value || etl::is_base_of_any<T, Ts...>::value), "Invalid type");
|
||||
|
||||
base_t::destroy(p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the variant_pool.
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
variant_pool(const variant_pool&) ETL_DELETE;
|
||||
variant_pool& operator =(const variant_pool&) ETL_DELETE;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
template <typename ... Ts>
|
||||
class variant_pool_ext
|
||||
: public etl::generic_pool_ext<etl::largest<Ts...>::size,
|
||||
etl::largest<Ts...>::alignment>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef etl::generic_pool_ext<etl::largest<Ts...>::size,
|
||||
etl::largest<Ts...>::alignment> base_t;
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
variant_pool_ext(typename base_t::element* buffer, size_t size)
|
||||
: base_t(buffer, size)
|
||||
{
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object from a type. Variadic parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename... Args>
|
||||
T* create(Args&&... args)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_one_of<T, Ts...>::value), "Unsupported type");
|
||||
|
||||
return base_t::template create<T>(etl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p)
|
||||
{
|
||||
ETL_STATIC_ASSERT((etl::is_one_of<T, Ts...>::value || etl::is_base_of_any<T, Ts...>::value), "Invalid type");
|
||||
|
||||
base_t::destroy(p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the variant_pool.
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return base_t::max_size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
variant_pool_ext(const variant_pool_ext&) ETL_DELETE;
|
||||
variant_pool_ext& operator =(const variant_pool_ext&) ETL_DELETE;
|
||||
};
|
||||
#else
|
||||
//***************************************************************************
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("template <size_t MAX_SIZE_,")
|
||||
cog.outl(" typename T1,")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.outl(" typename T%s = void," % n)
|
||||
cog.outl(" typename T%s = void>" % int(NTypes))
|
||||
cog.outl("class variant_pool")
|
||||
cog.out(" : public etl::generic_pool<")
|
||||
cog.out("etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::size," % int(NTypes))
|
||||
cog.out(" etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::alignment," % int(NTypes))
|
||||
cog.outl(" MAX_SIZE_>")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
{
|
||||
public:
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("typedef etl::generic_pool<")
|
||||
cog.out("etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::size," % int(NTypes))
|
||||
cog.out(" etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::alignment," % int(NTypes))
|
||||
cog.outl(" MAX_SIZE_> base_t;")
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
static const size_t MAX_SIZE = MAX_SIZE_;
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
variant_pool()
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Creates the object. Default constructor.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
T* create()
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. One parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1>
|
||||
T* create(const TP1& p1)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Two parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2>
|
||||
T* create(const TP1& p1, const TP2& p2)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Three parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2, typename TP3>
|
||||
T* create(const TP1& p1, const TP2& p2, const TP3& p3)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2, p3);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Four parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2, typename TP3, typename TP4>
|
||||
T* create(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2, p3, p4);
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Creates the object from a type. Variadic parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename... Args>
|
||||
T* create(Args&&... args)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(etl::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value ||" % int(NTypes))
|
||||
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.outl(" etl::is_base_of<T, T%s>::value ||" % n)
|
||||
cog.outl(" etl::is_base_of<T, T%s>::value), \"Invalid type\");" % int(NTypes))
|
||||
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
base_t::destroy(p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the variant_pool.
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return MAX_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
variant_pool(const variant_pool&) ETL_DELETE;
|
||||
variant_pool& operator =(const variant_pool&) ETL_DELETE;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.outl("template <typename T1,")
|
||||
for n in range(2, int(NTypes)):
|
||||
cog.outl(" typename T%s = void," % n)
|
||||
cog.outl(" typename T%s = void>" % int(NTypes))
|
||||
cog.outl("class variant_pool_ext")
|
||||
cog.out(" : public etl::generic_pool_ext<")
|
||||
cog.out("etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::size," % int(NTypes))
|
||||
cog.out(" etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::alignment>" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
{
|
||||
public:
|
||||
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("typedef etl::generic_pool_ext<")
|
||||
cog.out("etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::size," % int(NTypes))
|
||||
cog.out(" etl::largest<")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
cog.outl("T%s>::alignment> base_t;" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
variant_pool_ext(typename base_t::element* buffer, size_t size)
|
||||
: base_t(buffer, size)
|
||||
{
|
||||
}
|
||||
|
||||
#if ETL_CPP11_NOT_SUPPORTED || ETL_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Creates the object. Default constructor.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
T* create()
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. One parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1>
|
||||
T* create(const TP1& p1)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Two parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2>
|
||||
T* create(const TP1& p1, const TP2& p2)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Three parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2, typename TP3>
|
||||
T* create(const TP1& p1, const TP2& p2, const TP3& p3)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2, p3);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Creates the object. Four parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename TP1, typename TP2, typename TP3, typename TP4>
|
||||
T* create(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(p1, p2, p3, p4);
|
||||
}
|
||||
#else
|
||||
//*************************************************************************
|
||||
/// Creates the object from a type. Variadic parameter constructor.
|
||||
//*************************************************************************
|
||||
template <typename T, typename... Args>
|
||||
T* create(Args&&... args)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value), \"Unsupported type\");" % int(NTypes))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
return base_t::template create<T>(etl::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Destroys the object.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
void destroy(const T* const p)
|
||||
{
|
||||
/*[[[cog
|
||||
import cog
|
||||
cog.out("ETL_STATIC_ASSERT((etl::is_one_of<T, ")
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.out("T%s, " % n)
|
||||
if n % 16 == 0:
|
||||
cog.outl("")
|
||||
cog.out(" ")
|
||||
cog.outl("T%s>::value ||" % int(NTypes))
|
||||
|
||||
for n in range(1, int(NTypes)):
|
||||
cog.outl(" etl::is_base_of<T, T%s>::value ||" % n)
|
||||
cog.outl(" etl::is_base_of<T, T%s>::value), \"Invalid type\");" % int(NTypes))
|
||||
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
base_t::destroy(p);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the maximum number of items in the variant_pool.
|
||||
//*************************************************************************
|
||||
size_t max_size() const
|
||||
{
|
||||
return base_t::max_size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
variant_pool_ext(const variant_pool_ext&) ETL_DELETE;
|
||||
variant_pool_ext& operator =(const variant_pool_ext&) ETL_DELETE;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user