diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index 6bbb3e52..fe728495 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -62,6 +62,244 @@ SOFTWARE. namespace etl { +#if ETL_CPP17_SUPPORTED && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03) + //*************************************************************************** + // The definition for all message types. + //*************************************************************************** + template + class message_packet + { + public: + + //******************************************** + message_packet() + : valid(false) + { + } + + //******************************************** + explicit message_packet(const etl::imessage& msg) + : valid(true) + { + add_new_message(msg); + } + + //******************************************** + explicit message_packet(etl::imessage&& msg) + : valid(true) + { + add_new_message(etl::move(msg)); + } + + //********************************************** + message_packet(const message_packet& other) + : valid(other.is_valid()) + { + if (valid) + { + add_new_message(other.get()); + } + } + + //********************************************** + message_packet(message_packet&& other) + : valid(other.is_valid()) + { + if (valid) + { + add_new_message(etl::move(other.get())); + } + } + + //********************************************** + message_packet& operator =(const message_packet& rhs) + { + delete_current_message(); + valid = rhs.is_valid(); + if (valid) + { + add_new_message(rhs.get()); + } + + return *this; + } + + //********************************************** + message_packet& operator =(message_packet&& rhs) + { + delete_current_message(); + valid = rhs.is_valid(); + if (valid) + { + add_new_message(etl::move(rhs.get())); + } + + return *this; + } + + //******************************************** + ~message_packet() + { + delete_current_message(); + } + + //******************************************** + etl::imessage& get() ETL_NOEXCEPT + { + return *static_cast(data); + } + + //******************************************** + const etl::imessage& get() const ETL_NOEXCEPT + { + return *static_cast(data); + } + + //******************************************** + bool is_valid() const + { + return valid; + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(etl::message_id_t id) + { + return (accepts_message(id) || ...); + } + + //********************************************** + static ETL_CONSTEXPR bool accepts(const etl::imessage& msg) + { + return accepts(msg.get_message_id()); + } + + //********************************************** + template + static ETL_CONSTEXPR bool accepts() + { + return (accepts_message() || ...); + } + + //********************************************** + template + static ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + accepts() + { + return accepts(TMessage::ID); + } + + enum + { + SIZE = etl::largest::size, + ALIGNMENT = etl::largest::alignment + }; + + private: + + //********************************************** + template + static ETL_CONSTEXPR bool accepts_message() + { + return Id1 == Id2; + } + + //********************************************** + template + static ETL_CONSTEXPR bool accepts_message(etl::message_id_t id2) + { + return Id1 == id2; + } + + //******************************************** + void delete_current_message() + { + if (valid) + { + etl::imessage* pmsg = static_cast(data); + +#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); +#else + if (!(delete_current_message_type(pmsg->get_message_id()) || ...)) + { + ETL_ALWAYS_ASSERT(ETL_ERROR(unhandled_message_exception)); + } +#endif + } + } + + //******************************************** + void add_new_message(const etl::imessage& msg) + { + if (!(add_new_message_type(msg) || ...)) + { + ETL_ALWAYS_ASSERT(ETL_ERROR(unhandled_message_exception)); + } + } + + //******************************************** + void add_new_message(etl::imessage&& msg) + { + if (!(add_new_message_type(etl::move(msg)) || ...)) + { + ETL_ALWAYS_ASSERT(ETL_ERROR(unhandled_message_exception)); + } + } + + typename etl::aligned_storage::type data; + bool valid; + + private: + + //******************************************** + template + bool delete_current_message_type(etl::message_id_t Id) + { + if (TMessage::ID == Id) + { + static_cast(data)->~TMessage(); + return true; + } + else + { + return false; + } + } + + //******************************************** + template + bool add_new_message_type(const etl::imessage& msg) + { + if (TMessage::ID == msg.get_message_id()) + { + void* p = data; + new (p) TMessage(static_cast(msg)); + return true; + } + else + { + return false; + } + } + + //******************************************** + template + bool add_new_message_type(etl::imessage&& msg) + { + if (TMessage::ID == msg.get_message_id()) + { + void* p = data; + new (p) TMessage(static_cast(msg)); + return true; + } + else + { + return false; + } + } + }; +#else //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** @@ -206,7 +444,7 @@ namespace etl enum { - SIZE = etl::largest::size, + Size = etl::largest::size, ALIGNMENT = etl::largest::alignment }; @@ -306,7 +544,7 @@ namespace etl } #endif - typename etl::aligned_storage::type data; + typename etl::aligned_storage::type data; bool valid; }; @@ -454,7 +692,7 @@ namespace etl enum { - SIZE = etl::largest::size, + Size = etl::largest::size, ALIGNMENT = etl::largest::alignment }; @@ -551,7 +789,7 @@ namespace etl } #endif - typename etl::aligned_storage::type data; + typename etl::aligned_storage::type data; bool valid; }; @@ -699,7 +937,7 @@ namespace etl enum { - SIZE = etl::largest::size, + Size = etl::largest::size, ALIGNMENT = etl::largest::alignment }; @@ -793,7 +1031,7 @@ namespace etl } #endif - typename etl::aligned_storage::type data; + typename etl::aligned_storage::type data; bool valid; }; @@ -941,7 +1179,7 @@ namespace etl enum { - SIZE = etl::largest::size, + Size = etl::largest::size, ALIGNMENT = etl::largest::alignment }; @@ -1032,7 +1270,7 @@ namespace etl } #endif - typename etl::aligned_storage::type data; + typename etl::aligned_storage::type data; bool valid; }; @@ -1179,7 +1417,7 @@ namespace etl enum { - SIZE = etl::largest::size, + Size = etl::largest::size, ALIGNMENT = etl::largest::alignment }; @@ -1267,7 +1505,7 @@ namespace etl } #endif - typename etl::aligned_storage::type data; + typename etl::aligned_storage::type data; bool valid; }; @@ -3638,6 +3876,7 @@ namespace etl typename etl::aligned_storage::type data; bool valid; }; +#endif } #endif