diff --git a/src/io_port.h b/src/io_port.h index bebf521d..15c124ea 100644 --- a/src/io_port.h +++ b/src/io_port.h @@ -40,7 +40,6 @@ SOFTWARE. #include "platform.h" #include "nullptr.h" -#include "parameter_type.h" namespace etl { @@ -48,353 +47,222 @@ namespace etl /// Read write port. //*************************************************************************** template - class io_port_rw + class io_port_rw : public std::iterator { - private: - - typedef volatile T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - public: - class iterator : public std::iterator - { - typedef io_port_rw iop_t; - - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - iop_t& operator *() - { - return *p_iop; - } - - const iop_t& operator *() const - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; - + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; + /// Read. - operator T() volatile const + operator T() const { - return *reinterpret_cast(ADDRESS); + return *reinterpret_cast(ADDRESS); } /// Read. - T value() volatile const + T read() const { - return *reinterpret_cast(ADDRESS); + return *reinterpret_cast(ADDRESS); } /// Write. - io_port_rw& operator =(parameter_t value_) + void write(T value_) { - *reinterpret_cast(ADDRESS) = value_; + *reinterpret_cast(ADDRESS) = value_; + } + + /// Write. + io_port_rw& operator =(T value_) + { + *reinterpret_cast(ADDRESS) = value_; return *this; } - /// Get the IO port address. - pointer_t get_address() + /// Read / Write + reference operator *() { - return reinterpret_cast(ADDRESS); + return *reinterpret_cast(ADDRESS); } - /// Get the iterator. - iterator get_iterator() + /// Read + const_reference operator *() const { - return iterator(*this); + return *reinterpret_cast(ADDRESS); } + + /// Increment + io_port_rw& operator ++() + { + return *this; + } + + /// Increment + io_port_rw operator ++(int) + { + return *this; + } + + /// Get the IO port address. + pointer get_address() + { + return reinterpret_cast(ADDRESS); + } + + /// Get the IO port address. + const_pointer get_address() const + { + return reinterpret_cast(ADDRESS); + } + + private: + + /// Disabled. + io_port_rw& operator =(const io_port_rw&); }; //*************************************************************************** /// Read only port. //*************************************************************************** template - class io_port_ro + class io_port_ro : public std::iterator { - private: - - typedef volatile const T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - - /// Write disabled. - void operator =(parameter_t value); - public: - class iterator : public std::iterator - { - typedef io_port_ro iop_t; - - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - const iop_t& operator *() const - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; /// Read. - operator T() volatile const + operator T() const { - return *reinterpret_cast(ADDRESS); + return *reinterpret_cast(ADDRESS); } /// Read. - T value() volatile const + T read() const { - return *reinterpret_cast(ADDRESS); + return *reinterpret_cast(ADDRESS); + } + + /// Read + const_reference operator *() const + { + return *reinterpret_cast(ADDRESS); + } + + /// Increment + io_port_ro& operator ++() + { + return *this; + } + + /// Increment + io_port_ro operator ++(int) + { + return *this; } /// Get the IO port address. - pointer_t get_address() + pointer get_address() { - return reinterpret_cast(ADDRESS); + return reinterpret_cast(ADDRESS); } - /// Get the iterator. - iterator get_iterator() + /// Get the IO port address. + const_pointer get_address() const { - return iterator(*this); + return reinterpret_cast(ADDRESS); } + + private: + + /// Write disabled. + void operator =(T value); + + /// Disabled. + io_port_ro& operator =(const io_port_ro&); }; //*************************************************************************** /// Write only port. //*************************************************************************** template - class io_port_wo + class io_port_wo : public std::iterator { - private: - - typedef T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - - /// Read disabled. - operator T() volatile const; - public: - class iterator : public std::iterator - { - typedef io_port_wo iop_t; - - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - iop_t& operator *() - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; /// Write. - void operator =(parameter_t value) + void operator =(T value) { - *reinterpret_cast(ADDRESS) = value; + *reinterpret_cast(ADDRESS) = value; + } + + /// Write. + void write(T value_) + { + *reinterpret_cast(ADDRESS) = value_; + } + + /// Write + io_port_wo& operator *() + { + return *this; + } + + /// Increment + io_port_wo& operator ++() + { + return *this; + } + + /// Increment + io_port_wo operator ++(int) + { + return *this; } /// Get the IO port address. - pointer_t get_address() + pointer get_address() { - return reinterpret_cast(ADDRESS); + return reinterpret_cast(ADDRESS); } - /// Get the iterator. - iterator get_iterator() + /// Get the IO port address. + const_pointer get_address() const { - return iterator(*this); + return reinterpret_cast(ADDRESS); } + + private: + + /// Read disabled. + operator T() const; + + /// Disabled. + io_port_wo& operator =(const io_port_wo&); }; //*************************************************************************** /// Write only port with shadow register. //*************************************************************************** template - class io_port_wos + class io_port_wos : public std::iterator { - private: - - typedef T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - public: - class iterator : public std::iterator - { - typedef io_port_wos iop_t; - - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - iop_t& operator *() - { - return *p_iop; - } - - const iop_t& operator *() const - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; /// Read. operator T() const @@ -409,27 +277,55 @@ namespace etl } /// Write. - io_port_wos& operator =(parameter_t value_) + void write(T value_) { shadow_value = value_; - *reinterpret_cast(ADDRESS) = shadow_value; + *reinterpret_cast(ADDRESS) = shadow_value; + } + + /// Write. + io_port_wos& operator =(T value_) + { + shadow_value = value_; + *reinterpret_cast(ADDRESS) = shadow_value; + return *this; + } + + /// Read / Write + io_port_wos& operator *() + { + return *this; + } + + /// Read + const_reference operator *() const + { + return shadow_value; + } + + /// Increment + io_port_wos& operator ++() + { + return *this; + } + + /// Increment + io_port_wos operator ++(int) + { return *this; } /// Get the IO port address. - pointer_t get_address() + pointer get_address() { - return reinterpret_cast(ADDRESS); - } - - /// Get the iterator. - iterator get_iterator() - { - return iterator(*this); + return reinterpret_cast(ADDRESS); } private: + /// Disabled. + io_port_wos& operator =(const io_port_wos&); + T shadow_value; }; @@ -438,125 +334,110 @@ namespace etl /// Specialisation for dynamic addresses. //*************************************************************************** template - class io_port_rw + class io_port_rw : public std::iterator { - private: - - typedef volatile T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - public: - class iterator : public std::iterator - { - typedef io_port_rw iop_t; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - iop_t& operator *() - { - return *p_iop; - } - - const iop_t& operator *() const - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; - - - // Default constructor. + /// Default constructor. io_port_rw() : address(nullptr) { } - // Constructor. + /// Constructor. io_port_rw(uint8_t* address_) - : address(reinterpret_cast(address_)) + : address(reinterpret_cast(address_)) { } + /// Copy Constructor. + io_port_rw(const io_port_rw& other_) + : address(reinterpret_cast(other_.address)) + { + } + + /// Assignment. + io_port_rw& operator =(const io_port_rw& other_) + { + address = other_.address; + return *this; + } + /// Set the IO port address. void set_address(uintptr_t address_) { - address = reinterpret_cast(address_); + address = reinterpret_cast(address_); } /// Get the IO port address. - pointer_t get_address() + pointer get_address() { return address; } - /// Get the iterator. - iterator get_iterator() + /// Get the IO port address. + const_pointer get_address() const { - return iterator(*this); + return address; } /// Read. - operator T() volatile const + operator T() const { return *address; } /// Read. - T value() volatile const + T value() const { return *address; } /// Write. - io_port_rw& operator =(parameter_t value_) + void write(T value_) + { + *address = value_; + } + + /// Write. + io_port_rw& operator =(T value_) { *address = value_; return *this; } + /// Read / Write + reference operator *() + { + return *address; + } + + /// Read + const_reference operator *() const + { + return *address; + } + + /// Increment + io_port_rw& operator ++() + { + return *this; + } + + /// Increment + io_port_rw operator ++(int) + { + return *this; + } + private: - pointer_t address; + pointer address; }; //*************************************************************************** @@ -564,115 +445,88 @@ namespace etl /// Specialisation for dynamic addresses. //*************************************************************************** template - class io_port_ro + class io_port_ro : public std::iterator { - private: - - typedef volatile const T* pointer_t; - public: - class iterator : public std::iterator - { - typedef io_port_ro iop_t; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - const iop_t& operator *() const - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; - - // Default constructor. + /// Default constructor. io_port_ro() : address(nullptr) { } - // Constructor. + /// Constructor. io_port_ro(void* address_) - : address(reinterpret_cast(address_)) + : address(reinterpret_cast(address_)) { } + /// Copy Constructor. + io_port_ro(const io_port_ro& other_) + : address(reinterpret_cast(other_.address)) + { + } + + /// Assignment. + io_port_ro& operator =(const io_port_ro& other_) + { + address = other_.address; + return *this; + } + + /// Set the IO port address. void set_address(uintptr_t address_) { - address = reinterpret_cast(address_); + address = reinterpret_cast(address_); } /// Get the IO port address. - pointer_t get_address() + const_pointer get_address() const { return address; } - /// Get the iterator. - iterator get_iterator() - { - return iterator(*this); - } - /// Read. - operator T() volatile const + operator T() const { return *address; } /// Read. - T value() volatile const + T value() const { return *address; } + /// Read + const_reference operator *() const + { + return *address; + } + + /// Increment + io_port_ro& operator ++() + { + return *this; + } + + /// Increment + io_port_ro operator ++(int) + { + return *this; + } + private: - typedef typename etl::parameter_type::type parameter_t; - /// Write disabled. - void operator =(parameter_t value); + void operator =(T value); - pointer_t address; + pointer address; }; //*************************************************************************** @@ -680,110 +534,94 @@ namespace etl /// Specialisation for dynamic addresses. //*************************************************************************** template - class io_port_wo + class io_port_wo : public std::iterator { - private: - - typedef T* pointer_t; - public: - class iterator : public std::iterator - { - typedef io_port_wo iop_t; + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; - public: - - iterator(iop_t& iop) - : p_iop(&iop) - { - } - - iterator(const iterator& other) - : p_iop(other.p_iop) - { - } - - iterator& operator =(const iterator& other) - { - p_iop = other.p_iop; - return *this; - } - - iop_t& operator *() - { - return *p_iop; - } - - iterator& operator ++() - { - return *this; - } - - iterator operator ++(int) - { - return *this; - } - - iterator& operator --() - { - return *this; - } - - iterator operator --(int) - { - return *this; - } - - private: - - iop_t* p_iop; - }; - - typedef typename etl::parameter_type::type parameter_t; - - // Default constructor. + /// Default constructor. io_port_wo() : address(nullptr) { } - // Constructor. + /// Constructor. io_port_wo(void* address_) - : address(reinterpret_cast(address_)) + : address(reinterpret_cast(address_)) { } + /// Copy Constructor. + io_port_wo(const io_port_wo& other_) + : address(reinterpret_cast(other_.address)) + { + } + + /// Assignment. + io_port_wo& operator =(const io_port_wo& other_) + { + address = other_.address; + return *this; + } + /// Set the IO port address. void set_address(uintptr_t address_) { - address = reinterpret_cast(address_); + address = reinterpret_cast(address_); } /// Get the IO port address. - pointer_t get_address() + pointer get_address() { return address; } - /// Get the iterator. - iterator get_iterator() + /// Get the IO port address. + const_pointer get_address() const { - return iterator(*this); + return address; } /// Write. - void operator =(parameter_t value) + void write(T value_) + { + *address = value_; + } + + /// Write. + void operator =(T value) { *address = value; } + /// Write + io_port_wo& operator *() + { + return *this; + } + + /// Increment + io_port_wo& operator ++() + { + return *this; + } + + /// Write + io_port_wo operator ++(int) + { + return *this; + } + private: /// Read disabled. - operator T() volatile const; + operator T() const; - pointer_t address; + pointer address; }; //*************************************************************************** @@ -791,15 +629,15 @@ namespace etl /// Specialisation for dynamic addresses. //*************************************************************************** template - class io_port_wos + class io_port_wos : public std::iterator { - private: - - typedef T* pointer_t; - typedef typename etl::parameter_type::type parameter_t; - public: + typedef volatile T* pointer; + typedef volatile const T* const_pointer; + typedef volatile T& reference; + typedef volatile const T& const_reference; + class iterator : public std::iterator { typedef io_port_wos iop_t; @@ -856,27 +694,48 @@ namespace etl iop_t* p_iop; }; - - // Default constructor. + + /// Default constructor. io_port_wos() : address(nullptr) { } - // Constructor. + /// Constructor. io_port_wos(void* address_) - : address(reinterpret_cast(address_)) + : address(reinterpret_cast(address_)) { } + /// Copy Constructor. + io_port_wos(const io_port_wos& other_) + : shadow_value(other_.shadow_value), + address(reinterpret_cast(other_.address)) + { + } + + /// Assignment. + io_port_wos& operator =(const io_port_wos& other_) + { + shadow_value = other_.shadow_value; + address = other_.address; + return *this; + } + /// Set the IO port address. void set_address(uintptr_t address_) { - address = reinterpret_cast(address_); + address = reinterpret_cast(address_); } /// Get the IO port address. - pointer_t get_address() + pointer get_address() + { + return address; + } + + /// Get the IO port address. + const_pointer get_address() const { return address; } @@ -900,17 +759,48 @@ namespace etl } /// Write. - io_port_wos& operator =(parameter_t value_) + void write(T value_) + { + shadow_value = value_; + *address = shadow_value; + } + + /// Write. + io_port_wos& operator =(T value_) { shadow_value = value_; *address = shadow_value; return *this; } + /// Read / Write + io_port_wos& operator *() + { + return *this; + } + + /// Read + const_reference operator *() const + { + return shadow_value; + } + + /// Increment + io_port_wos& operator ++() + { + return *this; + } + + /// Increment + io_port_wos operator ++(int) + { + return *this; + } + private: - T shadow_value; - pointer_t address; + T shadow_value; + pointer address; }; } diff --git a/src/largest.h b/src/largest.h index bb82dc28..616594f7 100644 --- a/src/largest.h +++ b/src/largest.h @@ -76,39 +76,15 @@ namespace etl typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void> struct largest_type { - private: - - // Declaration. - template - struct choose_type; - - // Specialisation for 'true'. - // Defines 'type' as 'TrueType'. - template - struct choose_type - { - typedef TrueType type; - }; - - // Specialisation for 'false'. - // Defines 'type' as 'FalseType'. - template - struct choose_type - { - typedef FalseType type; - }; - - public: - // Define 'largest_other' as 'largest_type' with all but the first parameter. typedef typename largest_type::type largest_other; // Set 'type' to be the largest of the first parameter and any of the others. // This is recursive. - typedef typename choose_type<(sizeof(T1) > sizeof(largest_other)), // Boolean - T1, // TrueType - largest_other> // FalseType - ::type type; // The largest type of the two. + typedef typename etl::conditional<(sizeof(T1) > sizeof(largest_other)), // Boolean + T1, // TrueType + largest_other> // FalseType + ::type type; // The largest type of the two. // The size of the largest type. enum @@ -139,53 +115,40 @@ namespace etl ///\ingroup largest //*************************************************************************** template + typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, + typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, + typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void> struct largest_alignment { - private: + // Define 'largest_other' as 'largest_type' with all but the first parameter. + typedef typename largest_alignment::type largest_other; - // Determine the largest size. - template - struct max_size - { - enum - { - value = (size1 > size2) ? size1 : size2 - }; - }; + // Set 'type' to be the largest of the first parameter and any of the others. + // This is recursive. + typedef typename etl::conditional<(etl::alignment_of::value > etl::alignment_of::value), // Boolean + T1, // TrueType + largest_other> // FalseType + ::type type; // The largest type of the two. - // All of the alignments. + // The largest alignment. enum { - t1 = etl::alignment_of::value, - t2 = etl::alignment_of::value, - t3 = etl::alignment_of::value, - t4 = etl::alignment_of::value, - t5 = etl::alignment_of::value, - t6 = etl::alignment_of::value, - t7 = etl::alignment_of::value, - t8 = etl::alignment_of::value, - t9 = etl::alignment_of::value, - t10 = etl::alignment_of::value, - t11 = etl::alignment_of::value, - t12 = etl::alignment_of::value, - t13 = etl::alignment_of::value, - t14 = etl::alignment_of::value, - t15 = etl::alignment_of::value, - t16 = etl::alignment_of::value + value = etl::alignment_of::value }; + }; - public: + //*************************************************************************** + // Specialisation for one template parameter. + //*************************************************************************** + template + struct largest_alignment + { + typedef T1 type; - // The largest of all of them. enum { - value = max_size - ::value>::value>::value>::value>::value>::value>::value>::value> - ::value>::value>::value>::value>::value>::value>::value + value = etl::alignment_of::value }; }; diff --git a/src/largest_generator.h b/src/largest_generator.h index 202fde53..b701a70c 100644 --- a/src/largest_generator.h +++ b/src/largest_generator.h @@ -93,30 +93,6 @@ namespace etl cog.outl("typename T%s = void>" % int(NTypes)) cog.outl("struct largest_type") cog.outl("{") - cog.outl("private:") - cog.outl("") - cog.outl(" // Declaration.") - cog.outl(" template ") - cog.outl(" struct choose_type;") - cog.outl("") - cog.outl(" // Specialisation for 'true'.") - cog.outl(" // Defines 'type' as 'TrueType'.") - cog.outl(" template ") - cog.outl(" struct choose_type") - 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 ") - cog.outl(" struct choose_type") - cog.outl(" {") - cog.outl(" typedef FalseType type;") - cog.outl(" };") - cog.outl("") - cog.outl("public:") - 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)): @@ -128,10 +104,10 @@ namespace etl 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 choose_type<(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(" 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") @@ -175,49 +151,50 @@ namespace etl cog.out("typename T%s = void, " % n) if n % 4 == 0: cog.outl("") - cog.out(" ") - cog.outl("typename T%s = void>" % NTypes) + cog.out(" ") + cog.outl("typename T%s = void>" % int(NTypes)) cog.outl("struct largest_alignment") cog.outl("{") - cog.outl("private:") + 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(" // Determine the largest size.") - cog.outl(" template ") - cog.outl(" struct max_size") - cog.outl(" {") - cog.outl(" enum") - cog.outl(" {") - cog.outl(" value = (size1 > size2) ? size1 : size2") - cog.outl(" };") - 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::value > etl::alignment_of::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(" // All of the alignments.") + cog.outl(" // The largest alignment.") cog.outl(" enum") cog.outl(" {") - for n in range(1, int(NTypes)): - cog.outl(" t%s = etl::alignment_of::value," %(n, n)) - cog.outl(" t%s = etl::alignment_of::value" % (NTypes, NTypes)) + cog.outl(" value = etl::alignment_of::value") cog.outl(" };") + cog.outl("};") cog.outl("") - cog.outl("public:") + cog.outl("//***************************************************************************") + cog.outl("// Specialisation for one template parameter.") + cog.outl("//***************************************************************************") + cog.outl("template ") + cog.out("struct largest_alignment") + cog.outl("{") + cog.outl(" typedef T1 type;") cog.outl("") - cog.outl(" // The largest of all of them.") cog.outl(" enum") cog.outl(" {") - cog.out(" value = ") - for n in range(1, int(NTypes)): - cog.out("max_size" % int(NTypes)) - cog.out(" ") - for n in range(1, int(NTypes) - 1): - cog.out("::value>") - if n % 8 == 0: - cog.outl("") - cog.out(" ") - cog.outl("::value") + cog.outl(" value = etl::alignment_of::value") cog.outl(" };") cog.outl("};") ]]]*/ diff --git a/src/message_router.h b/src/message_router.h index 397086cd..4c8744c2 100644 --- a/src/message_router.h +++ b/src/message_router.h @@ -38,12 +38,12 @@ SOFTWARE. // 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= message_router_generator.h +// python -m cogapp -d -e -omessage_router.h -DHandlers= message_router_generator.h // Where is the 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 +// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h // // See generate.bat //*************************************************************************** @@ -60,6 +60,7 @@ SOFTWARE. #include "error_handler.h" #include "exception.h" #include "largest.h" +#include "nullptr.h" #undef ETL_FILE #define ETL_FILE "35" @@ -126,6 +127,12 @@ namespace etl return (message_router_id == MESSAGE_BUS); } + //******************************************** + void set_successor(imessage_router& successor_) + { + successor = &successor_; + } + enum { NULL_MESSAGE_ROUTER = 255, @@ -136,11 +143,21 @@ namespace etl protected: - imessage_router(etl::message_router_id_t id) - : message_router_id(id) + imessage_router(etl::message_router_id_t id_) + : successor(nullptr), + message_router_id(id_) { } + imessage_router(etl::message_router_id_t id_, + imessage_router& successor_) + : successor(&successor_), + message_router_id(id_) + { + } + + etl::imessage_router* successor; + private: // Disabled. @@ -191,7 +208,7 @@ namespace etl /// Send a message to a router. /// Sets the 'sender' to etl::null_message_router type. //*************************************************************************** - inline static void send_message(etl::imessage_router& destination, + inline static void send_message(etl::imessage_router& destination, const etl::imessage& message) { destination.receive(message); @@ -200,20 +217,20 @@ namespace etl //*************************************************************************** /// Send a message to a router. //*************************************************************************** - inline static void send_message(etl::imessage_router& source, - etl::imessage_router& destination, + inline static void send_message(etl::imessage_router& source, + etl::imessage_router& destination, const etl::imessage& message) { destination.receive(source, message); } - + //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** template class message_router : public imessage_router { @@ -293,10 +310,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -328,7 +352,18 @@ namespace etl case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T16::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -339,8 +374,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: return true; break; default: return false; break; @@ -351,10 +386,10 @@ namespace etl //*************************************************************************** // Specialisation for 15 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -434,10 +469,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -468,7 +510,18 @@ namespace etl case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -479,8 +532,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: return true; break; default: return false; break; @@ -491,10 +544,10 @@ namespace etl //*************************************************************************** // Specialisation for 14 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -573,10 +626,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -606,7 +666,18 @@ namespace etl case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -617,8 +688,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: return true; break; default: return false; break; @@ -629,10 +700,10 @@ namespace etl //*************************************************************************** // Specialisation for 13 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -710,10 +781,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -742,7 +820,18 @@ namespace etl case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -753,8 +842,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: return true; break; default: return false; break; @@ -765,9 +854,9 @@ namespace etl //*************************************************************************** // Specialisation for 12 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -844,10 +933,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -875,7 +971,18 @@ namespace etl case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -886,8 +993,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: return true; break; default: return false; break; @@ -898,9 +1005,9 @@ namespace etl //*************************************************************************** // Specialisation for 11 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -976,10 +1083,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1006,7 +1120,18 @@ namespace etl case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1017,8 +1142,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: return true; break; default: return false; break; @@ -1029,9 +1154,9 @@ namespace etl //*************************************************************************** // Specialisation for 10 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1106,10 +1231,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1135,7 +1267,18 @@ namespace etl case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1146,8 +1289,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: return true; break; default: return false; break; @@ -1158,9 +1301,9 @@ namespace etl //*************************************************************************** // Specialisation for 9 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1234,10 +1377,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1262,7 +1412,18 @@ namespace etl case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1273,8 +1434,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: return true; break; default: return false; break; @@ -1285,8 +1446,8 @@ namespace etl //*************************************************************************** // Specialisation for 8 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1359,10 +1520,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1386,7 +1554,18 @@ namespace etl case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1397,8 +1576,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + return true; break; default: return false; break; @@ -1409,8 +1588,8 @@ namespace etl //*************************************************************************** // Specialisation for 7 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1482,10 +1661,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1508,7 +1694,18 @@ namespace etl case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1519,7 +1716,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: return true; break; default: return false; break; @@ -1530,8 +1727,8 @@ namespace etl //*************************************************************************** // Specialisation for 6 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1602,10 +1799,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1627,7 +1831,18 @@ namespace etl case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1638,7 +1853,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: return true; break; default: return false; break; @@ -1649,8 +1864,8 @@ namespace etl //*************************************************************************** // Specialisation for 5 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1720,10 +1935,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1744,7 +1966,18 @@ namespace etl case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1755,7 +1988,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: return true; break; default: return false; break; @@ -1766,7 +1999,7 @@ namespace etl //*************************************************************************** // Specialisation for 4 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1835,10 +2068,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1858,7 +2098,18 @@ namespace etl case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1869,7 +2120,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: return true; break; default: return false; break; @@ -1880,7 +2131,7 @@ namespace etl //*************************************************************************** // Specialisation for 3 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1948,10 +2199,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -1970,7 +2228,18 @@ namespace etl case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1981,7 +2250,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: + case T1::ID: case T2::ID: case T3::ID: return true; break; default: return false; break; @@ -1992,7 +2261,7 @@ namespace etl //*************************************************************************** // Specialisation for 2 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -2059,10 +2328,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -2080,7 +2356,18 @@ namespace etl { case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -2091,7 +2378,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: + case T1::ID: case T2::ID: return true; break; default: return false; break; @@ -2102,7 +2389,7 @@ namespace etl //*************************************************************************** // Specialisation for 1 message type. //*************************************************************************** - template class message_router : public imessage_router @@ -2168,10 +2455,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + 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)); + 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)); } //********************************************** @@ -2188,7 +2482,18 @@ namespace etl switch (id) { case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -2199,7 +2504,7 @@ namespace etl { switch (id) { - case T1::ID: + case T1::ID: return true; break; default: return false; break; diff --git a/src/message_router_generator.h b/src/message_router_generator.h index 054cd5fb..8353ee48 100644 --- a/src/message_router_generator.h +++ b/src/message_router_generator.h @@ -72,6 +72,7 @@ cog.outl("//******************************************************************** #include "error_handler.h" #include "exception.h" #include "largest.h" +#include "nullptr.h" #undef ETL_FILE #define ETL_FILE "35" @@ -138,6 +139,12 @@ namespace etl return (message_router_id == MESSAGE_BUS); } + //******************************************** + void set_successor(imessage_router& successor_) + { + successor = &successor_; + } + enum { NULL_MESSAGE_ROUTER = 255, @@ -148,11 +155,21 @@ namespace etl protected: - imessage_router(etl::message_router_id_t id) - : message_router_id(id) + imessage_router(etl::message_router_id_t id_) + : successor(nullptr), + message_router_id(id_) { } + imessage_router(etl::message_router_id_t id_, + imessage_router& successor_) + : successor(&successor_), + message_router_id(id_) + { + } + + etl::imessage_router* successor; + private: // Disabled. @@ -313,10 +330,17 @@ namespace etl cog.outl(" };") cog.outl("") cog.outl(" //**********************************************") - cog.outl(" message_router(etl::message_router_id_t id)") - cog.outl(" : imessage_router(id)") + 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(" 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(" //**********************************************") @@ -336,9 +360,18 @@ namespace etl cog.out(" case T%d::ID:" % n) cog.out(" static_cast(this)->on_receive(source, static_cast(msg));" % n) cog.outl(" break;") - cog.out(" default:") - cog.out(" static_cast(this)->on_receive_unknown(source, msg);") - cog.outl(" break;") + cog.outl(" default:") + cog.outl(" {") + cog.outl(" if (successor != nullptr)") + cog.outl(" {") + cog.outl(" successor->receive(source, msg);") + cog.outl(" }") + cog.outl(" else") + cog.outl(" {") + cog.outl(" static_cast(this)->on_receive_unknown(source, msg);") + cog.outl(" }") + cog.outl(" break;") + cog.outl(" }") cog.outl(" }") cog.outl(" }") cog.outl("") @@ -469,10 +502,17 @@ namespace etl cog.outl(" };") cog.outl("") cog.outl(" //**********************************************") - cog.outl(" message_router(etl::message_router_id_t id)") - cog.outl(" : imessage_router(id)") + 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(" 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(" //**********************************************") @@ -492,9 +532,18 @@ namespace etl cog.out(" case T%d::ID:" % t) cog.out(" static_cast(this)->on_receive(source, static_cast(msg));" % t) cog.outl(" break;") - cog.out(" default:") - cog.out(" static_cast(this)->on_receive_unknown(source, msg);") - cog.outl(" break;") + cog.outl(" default:") + cog.outl(" {") + cog.outl(" if (successor != nullptr)") + cog.outl(" {") + cog.outl(" successor->receive(source, msg);") + cog.outl(" }") + cog.outl(" else") + cog.outl(" {") + cog.outl(" static_cast(this)->on_receive_unknown(source, msg);") + cog.outl(" }") + cog.outl(" break;") + cog.outl(" }") cog.outl(" }") cog.outl(" }") cog.outl("") diff --git a/src/power.h b/src/power.h index 76f1f5c7..dd2435d3 100644 --- a/src/power.h +++ b/src/power.h @@ -65,11 +65,6 @@ namespace etl static const uint64_t value = 1; }; - //*************************************************************************** - /// Declaration of static 'value' for power. - //*************************************************************************** - template const uint64_t power::value; - //*************************************************************************** ///\ingroup power /// Calculates the rounded up power of 2. diff --git a/src/type_traits.h b/src/type_traits.h index 083df234..350c8129 100644 --- a/src/type_traits.h +++ b/src/type_traits.h @@ -54,10 +54,10 @@ SOFTWARE. #define __ETL_TYPE_TRAITS__ #include -#include #include "platform.h" #include "nullptr.h" +#include "static_assert.h" #if (ETL_CPP11_SUPPORTED) #include @@ -318,6 +318,25 @@ namespace etl template struct conditional { typedef T type; }; template struct conditional { typedef F type; }; + /// conditional_integral_constant + ///\ingroup type_traits + template + struct conditional_integral_constant; + + template + struct conditional_integral_constant + { + STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); + static const T value = TRUE_VALUE; + }; + + template + struct conditional_integral_constant + { + STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); + static const T value = FALSE_VALUE; + }; + /// make_signed ///\ingroup type_traits template struct make_signed { typedef T type; }; @@ -417,10 +436,10 @@ namespace etl /// is_base_of ///\ingroup type_traits - template::value || etl::is_fundamental::value)> - struct is_base_of + template::value || etl::is_fundamental::value)> + struct is_base_of { private: @@ -441,7 +460,7 @@ namespace etl { static const bool value = false; }; - + /// Alignment templates. /// These require compiler specific intrinsics. ///\ingroup type_traits @@ -465,14 +484,14 @@ namespace etl ///\ingroup types //*************************************************************************** template struct is_one_of { - static const bool value = + static const bool value = etl::is_same::value || etl::is_same::value || etl::is_same::value || diff --git a/src/type_traits_generator.h b/src/type_traits_generator.h index 0a1471d5..ef409202 100644 --- a/src/type_traits_generator.h +++ b/src/type_traits_generator.h @@ -69,6 +69,7 @@ cog.outl("//******************************************************************** #include "platform.h" #include "nullptr.h" +#include "static_assert.h" #if (ETL_CPP11_SUPPORTED) #include @@ -329,6 +330,22 @@ namespace etl template struct conditional { typedef T type; }; template struct conditional { typedef F type; }; + /// conditional_integral_constant + ///\ingroup type_traits + template + struct conditional_integral_constant + { + STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); + static const T value = TRUE_VALUE; + }; + + template + struct conditional_integral_constant + { + STATIC_ASSERT(etl::is_integral::value, "Not an integral type"); + static const T value = FALSE_VALUE; + }; + /// make_signed ///\ingroup type_traits template struct make_signed { typedef T type; }; diff --git a/test/test_io_port.cpp b/test/test_io_port.cpp index d1cb8d9c..798e147d 100644 --- a/test/test_io_port.cpp +++ b/test/test_io_port.cpp @@ -41,6 +41,11 @@ SOFTWARE. #pragma warning(disable:4101) // Unused variable. #endif +uint8_t rw = 0x12; +uint8_t ro = 0x34; +uint8_t wo = 0x56; +uint8_t wos = 0x78; + namespace { template @@ -123,8 +128,8 @@ namespace CHECK_EQUAL(0xDE, port.control2); port.control2.set_address(0x1000); - uint8_t* address = port.control2.get_address(); - CHECK_EQUAL(reinterpret_cast(0x1000), address); + volatile uint8_t* address = port.control2.get_address(); + CHECK_EQUAL(reinterpret_cast(0x1000), address); } //************************************************************************* @@ -144,9 +149,7 @@ namespace std::array result; // Read from RW IOP. - etl::io_port_rw::iterator itr_rw = iop_rw.get_iterator(); - - std::copy_n(itr_rw, result.size(), result.begin()); + std::copy_n(iop_rw, result.size(), result.begin()); compare.fill(0x12); for (size_t i = 0; i < compare.size(); ++i) @@ -156,14 +159,12 @@ namespace // Write to RW IOP. compare.fill(0x34); - std::copy_n(compare.begin(), compare.size(), itr_rw); + std::copy_n(compare.begin(), compare.size(), iop_rw); CHECK_EQUAL(compare[0], iop_rw); // Read from RO IOP. - etl::io_port_ro::iterator itr_ro = iop_ro.get_iterator(); - - std::copy_n(itr_ro, result.size(), result.begin()); + std::copy_n(iop_ro, result.size(), result.begin()); compare.fill(0x34); for (size_t i = 0; i < compare.size(); ++i) @@ -172,19 +173,15 @@ namespace } // Write to WO IOP. - etl::io_port_wo::iterator itr_wo = iop_wo.get_iterator(); - compare.fill(0x56); - std::copy_n(compare.begin(), compare.size(), itr_wo); + std::copy_n(compare.begin(), compare.size(), iop_wo); CHECK_EQUAL(compare[0], memory_wo); // Read from WOS IOP. - etl::io_port_wos::iterator itr_wos = iop_wos.get_iterator(); + iop_wos = 0x78; - *itr_wos = 0x78; - - std::copy_n(itr_wos, result.size(), result.begin()); + std::copy_n(iop_wos, result.size(), result.begin()); compare.fill(0x78); for (size_t i = 0; i < compare.size(); ++i) @@ -194,10 +191,32 @@ namespace // Write to WOS IOP. compare.fill(0x90); - std::copy_n(compare.begin(), compare.size(), itr_wos); + std::copy_n(compare.begin(), compare.size(), iop_wos.get_iterator()); CHECK_EQUAL(compare[0], iop_wos); } + + TEST(compile) + { + // etl::io_port_rw p_rw; + // etl::io_port_ro p_ro; + // etl::io_port_wo p_wo; + // etl::io_port_wos p_wos; + + // uint8_t c; + + // *p_rw = 1; + // c = *p_rw; + + // *p_ro = 1; + // c = *p_ro; + + // *p_wo = 1; + // c = *p_wo; + + // *p_wos = 1; + // c = *p_wos; + } }; } diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index c15408fb..45598673 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -417,5 +417,62 @@ namespace CHECK_EQUAL(4, r1.callback_count); queue.pop(); } + + //========================================================================= + TEST(message_router_successor) + { + Router1 r1; + Router2 r2; + + r2.set_successor(r1); + + etl::send_message(r2, message1); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(0, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message2); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message3); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message4); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(1, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + } }; } diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 33092988..cd57f45d 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -716,4 +716,14 @@ namespace CHECK((std::is_same::const_pointer_const>::value)); } }; + + //************************************************************************* + TEST(conditional_integral_constant) + { + int v1 = etl::conditional_integral_constant::value; + int v2 = etl::conditional_integral_constant::value; + + CHECK_EQUAL(1, v1); + CHECK_EQUAL(2, v2); + } }