Embedded Template Library 1.0
Loading...
Searching...
No Matches
message_packet.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2020 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_MESSAGE_PACKET_INCLUDED
30#define ETL_MESSAGE_PACKET_INCLUDED
31
32#include "platform.h"
33
34#include "alignment.h"
35#include "error_handler.h"
36#include "largest.h"
37#include "message.h"
38#include "static_assert.h"
39#include "type_list.h"
40#include "utility.h"
42#include <stdint.h>
43
44namespace etl
45{
46#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
47 //***************************************************************************
48 // The definition for all message types.
49 //***************************************************************************
50 template <typename... TMessageTypes>
51 class message_packet
52 {
53 private:
54
55 template <typename T>
56 static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
57
58 template <typename T>
59 static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<T>>, TMessageTypes...>;
60
61 template <typename T>
62 static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
63
64 public:
65
66 using message_types = etl::type_list<TMessageTypes...>;
67
68 //********************************************
70 constexpr message_packet() noexcept
71 : valid(false)
72 {
73 }
75
76 //********************************************
78 //********************************************
80 template <typename T, typename = typename etl::enable_if< IsIMessage<T> || IsInMessageList<T>, int>::type>
81 explicit message_packet(T&& msg)
82 : valid(true)
83 {
84 if constexpr (IsIMessage<T>)
85 {
86 if (accepts(msg))
87 {
88 add_new_message(etl::forward<T>(msg));
89 valid = true;
90 }
91 else
92 {
93 valid = false;
94 }
95
96 ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
97 }
98 else if constexpr (IsInMessageList<T>)
99 {
100 add_new_message_type<T>(etl::forward<T>(msg));
101 }
102 else
103 {
104 ETL_STATIC_ASSERT(IsInMessageList<T>, "Message not in packet type list");
105 }
106 }
107 #include "private/diagnostic_pop.h"
108
109 //**********************************************
110 message_packet(const message_packet& other)
111 {
112 valid = other.is_valid();
113
114 if (valid)
115 {
116 add_new_message(other.get());
117 }
118 }
119
120 #if ETL_USING_CPP11
121 //**********************************************
122 message_packet(message_packet&& other)
123 {
124 valid = other.is_valid();
125
126 if (valid)
127 {
128 add_new_message(etl::move(other.get()));
129 }
130 }
131 #endif
132
133 //**********************************************
134 void copy(const message_packet& other)
135 {
136 valid = other.is_valid();
137
138 if (valid)
139 {
140 add_new_message(other.get());
141 }
142 }
143
144 //**********************************************
145 void copy(message_packet&& other)
146 {
147 valid = other.is_valid();
148
149 if (valid)
150 {
151 add_new_message(etl::move(other.get()));
152 }
153 }
154
155 //**********************************************
157 message_packet& operator=(const message_packet& rhs)
158 {
159 delete_current_message();
160 valid = rhs.is_valid();
161 if (valid)
162 {
163 add_new_message(rhs.get());
164 }
165
166 return *this;
167 }
168 #include "private/diagnostic_pop.h"
169
170 //**********************************************
172 message_packet& operator=(message_packet&& rhs)
173 {
174 delete_current_message();
175 valid = rhs.is_valid();
176 if (valid)
177 {
178 add_new_message(etl::move(rhs.get()));
179 }
180
181 return *this;
182 }
183 #include "private/diagnostic_pop.h"
184
185 //********************************************
186 ~message_packet()
187 {
188 delete_current_message();
189 }
190
191 //********************************************
192 etl::imessage& get() ETL_NOEXCEPT
193 {
194 return *static_cast<etl::imessage*>(data);
195 }
196
197 //********************************************
198 const etl::imessage& get() const ETL_NOEXCEPT
199 {
200 return *static_cast<const etl::imessage*>(data);
201 }
202
203 //********************************************
204 bool is_valid() const
205 {
206 return valid;
207 }
208
209 //**********************************************
210 static ETL_CONSTEXPR bool accepts(etl::message_id_t id)
211 {
212 return (accepts_message<TMessageTypes::ID>(id) || ...);
213 }
214
215 //**********************************************
216 static ETL_CONSTEXPR bool accepts(const etl::imessage& msg)
217 {
218 return accepts(msg.get_message_id());
219 }
220
221 //**********************************************
222 template <etl::message_id_t Id>
223 static ETL_CONSTEXPR bool accepts()
224 {
225 return (accepts_message<TMessageTypes::ID, Id>() || ...);
226 }
227
228 //**********************************************
229 template <typename TMessage>
230 static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
231 {
232 return accepts<TMessage::ID>();
233 }
234
235 enum
236 {
237 SIZE = etl::largest<TMessageTypes...>::size,
238 ALIGNMENT = etl::largest<TMessageTypes...>::alignment
239 };
240
241 private:
242
243 //**********************************************
244 template <etl::message_id_t Id1, etl::message_id_t Id2>
245 static bool accepts_message()
246 {
247 return Id1 == Id2;
248 }
249
250 //**********************************************
251 template <etl::message_id_t Id1>
252 static bool accepts_message(etl::message_id_t id2)
253 {
254 return Id1 == id2;
255 }
256
257 //********************************************
259 void delete_current_message()
260 {
261 if (valid)
262 {
263 etl::imessage* pmsg = static_cast<etl::imessage*>(data);
264
265 #if ETL_HAS_VIRTUAL_MESSAGES
266 pmsg->~imessage();
267 #else
268 delete_message(pmsg);
269 #endif
270 }
271 }
272 #include "private/diagnostic_pop.h"
273
274 #if !ETL_HAS_VIRTUAL_MESSAGES
275 //********************************************
276 void delete_message(etl::imessage* pmsg)
277 {
278 (delete_message_type<TMessageTypes>(pmsg) || ...);
279 }
280
281 //********************************************
282 template <typename TType>
283 bool delete_message_type(etl::imessage* pmsg)
284 {
285 if (TType::ID == pmsg->get_message_id())
286 {
287 TType* p = static_cast<TType*>(pmsg);
288 p->~TType();
289 return true;
290 }
291 else
292 {
293 return false;
294 }
295 }
296 #endif
297
298 //********************************************
299 void add_new_message(const etl::imessage& msg)
300 {
301 (add_new_message_type<TMessageTypes>(msg) || ...);
302 }
303
304 //********************************************
305 void add_new_message(etl::imessage&& msg)
306 {
307 (add_new_message_type<TMessageTypes>(etl::move(msg)) || ...);
308 }
309
311 //********************************************
313 //********************************************
314 template <typename TMessage>
315 etl::enable_if_t< etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<TMessage>>, TMessageTypes...>, void>
316 add_new_message_type(TMessage&& msg)
317 {
318 void* p = data;
319 new (p) etl::remove_reference_t<TMessage>((etl::forward<TMessage>(msg)));
320 }
321 #include "private/diagnostic_pop.h"
322
324 //********************************************
325 template <typename TType>
326 bool add_new_message_type(const etl::imessage& msg)
327 {
328 if (TType::ID == msg.get_message_id())
329 {
330 void* p = data;
331 new (p) TType(static_cast<const TType&>(msg));
332 return true;
333 }
334 else
335 {
336 return false;
337 }
338 }
339 #include "private/diagnostic_pop.h"
340
342 //********************************************
343 template <typename TType>
344 bool add_new_message_type(etl::imessage&& msg)
345 {
346 if (TType::ID == msg.get_message_id())
347 {
348 void* p = data;
349 new (p) TType(static_cast<TType&&>(msg));
350 return true;
351 }
352 else
353 {
354 return false;
355 }
356 }
357 #include "private/diagnostic_pop.h"
358
360 bool valid;
361 };
362
363 //***************************************************************************
364 // The definition for no message types.
365 //***************************************************************************
366 template <>
367 class message_packet<>
369 private:
370
371 template <typename T>
372 static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<>>;
373
374 template <typename T>
375 static constexpr bool IsInMessageList = false;
376
377 template <typename T>
378 static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
379
380 public:
381
382 using message_types = etl::type_list<>;
383
384 //********************************************
386 constexpr message_packet() noexcept {}
387 #include "private/diagnostic_pop.h"
388
389 //**********************************************
390 message_packet(const message_packet& /*other*/) {}
391
392 #if ETL_USING_CPP11
393 //**********************************************
394 message_packet(message_packet&& /*other*/) {}
395 #endif
396
397 //**********************************************
398 void copy(const message_packet& /*other*/) {}
399
400 //**********************************************
401 void copy(message_packet&& /*other*/) {}
402
403 //**********************************************
405 message_packet& operator=(const message_packet& /*rhs*/)
406 {
407 return *this;
408 }
409 #include "private/diagnostic_pop.h"
410
411 //**********************************************
413 message_packet& operator=(message_packet&& /*rhs*/)
414 {
415 return *this;
416 }
417 #include "private/diagnostic_pop.h"
418
419 //********************************************
420 ~message_packet() {}
421
422 //********************************************
423 bool is_valid() const
424 {
425 return false;
426 }
427
428 //**********************************************
429 static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/)
430 {
431 return false;
432 }
433
434 //**********************************************
435 static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/)
436 {
437 return false;
438 }
439
440 //**********************************************
441 template <etl::message_id_t Id>
442 static ETL_CONSTEXPR bool accepts()
443 {
444 return false;
445 }
446
447 //**********************************************
448 template <typename TMessage>
449 static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
450 {
451 return false;
452 }
453
454 enum
455 {
456 SIZE = 0,
457 ALIGNMENT = 1
458 };
459 };
460
461 //***************************************************************************
464 template <typename TList>
465 struct message_packet_from_type_list;
466
467 template <typename... TTypes>
468 struct message_packet_from_type_list<etl::type_list<TTypes...>>
469 {
470 using type = etl::message_packet<TTypes...>;
471 };
472
473 template <typename TTypeList>
474 using message_packet_from_type_list_t = typename message_packet_from_type_list<TTypeList>::type;
475
476#else
477 #include "private/message_packet_cpp03.h"
478#endif
479} // namespace etl
480
481#endif
Definition message.h:75
Definition message_packet.h:42
Definition message.h:56
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition largest.h:45
bitset_ext
Definition absolute.h:40
uint_least8_t message_id_t
Allow alternative type for message id.
Definition message_types.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
Definition alignment.h:253