diff --git a/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp b/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp new file mode 100644 index 00000000..2fb61c92 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/FunctionInterruptSimulation.cpp @@ -0,0 +1,149 @@ +#include + +#include "etl/delegate.h" +#include "etl/delegate_service.h" + +enum VectorId +{ + TIM1_CC_IRQ_HANDLER = 42, + TIM2_IRQ_HANDLER = 43, + TIM3_IRQ_HANDLER = 44, + USART1_IRQ_HANDLER = 52, + USART2_IRQ_HANDLER = 53, + VECTOR_ID_END, + VECTOR_ID_OFFSET = TIM1_CC_IRQ_HANDLER, + VECTOR_ID_RANGE = VECTOR_ID_END - VECTOR_ID_OFFSET +}; + +typedef etl::delegate_service InterruptVectors; + +// Ensure that the callback service is initialised before use. +InterruptVectors& GetInterruptVectorsInstance() +{ + static InterruptVectors interruptVectors; + + return interruptVectors; +} + +extern "C" +{ + InterruptVectors& interruptVectors = GetInterruptVectorsInstance(); + + // Function called from the timer1 interrupt vector. + void TIM1_CC_IRQHandler() + { + interruptVectors.call(); + } + + // Function called from the timer2 interrupt vector. + void TIM2_IRQHandler() + { + interruptVectors.call(); + } + + // Function called from the timer3 interrupt vector. + void TIM3_IRQHandler() + { + interruptVectors.call(); + } + + // Function called from the usart1 interrupt vector. + void USART1_IRQHandler() + { + interruptVectors.call(); + } + + // Function called from the usart2 interrupt vector. + void USART2_IRQHandler() + { + interruptVectors.call(); + } +} + +//******************************** +// Timer driver. +//******************************** +class Timer +{ +public: + + // Handler for interrupts from the timer. + void InterruptHandler(const size_t id) + { + std::cout << "Timer interrupt (member) : ID " << id << "\n"; + } +}; + +//******************************** +// Free function timer driver. +//******************************** +void FreeTimerInterruptHandler(const size_t id) +{ + std::cout << "Timer interrupt (free) : ID " << id << "\n"; +} + +//******************************** +// UART driver. +//******************************** +class Uart +{ +public: + + // Constructor. + Uart(int port_id, size_t interruptId) + : port_id(port_id), + callback(etl::delegate::create(*this)) + { + GetInterruptVectorsInstance().register_delegate(interruptId, callback); + } + + // Handler for interrupts from the UART. + void InterruptHandler(const size_t id) + { + std::cout << "UART" << port_id << " : ID " << id << "\n"; + } + + etl::delegate callback; + + int port_id; +}; + +void UnhandledInterrupt(const size_t id) +{ + std::cout << "Unhandled Interrupt : ID " << id << "\n"; +} + +// Declare the driver instances. +Timer timer; +Uart uart1(0, USART1_IRQ_HANDLER); +Uart uart2(1, USART2_IRQ_HANDLER); + +// Declare a global callback for the timer. +// Uses the most efficient callback type for a class, as everthing is known at compile time. +etl::delegate timer_member_callback = etl::delegate::create(); + +// Declare the callbacks for the free functions. +etl::delegate timer_free_callback = etl::delegate::create(); +etl::delegate unhandled_callback = etl::delegate::create(); + +//******************************** +// Test it out. +//******************************** +int main() +{ + // Setup the callbacks. + InterruptVectors& interruptVectors = GetInterruptVectorsInstance(); + + interruptVectors.register_delegate(timer_member_callback); + interruptVectors.register_delegate(timer_free_callback); + interruptVectors.register_unhandled_delegate(unhandled_callback); + + // Simulate the interrupts. + TIM1_CC_IRQHandler(); + TIM2_IRQHandler(); + USART1_IRQHandler(); + USART2_IRQHandler(); + TIM3_IRQHandler(); // Unhandled! + + return 0; +} diff --git a/examples/FunctionInterruptSimulation-Delegates/etl_profile.h b/examples/FunctionInterruptSimulation-Delegates/etl_profile.h new file mode 100644 index 00000000..a321fa85 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/etl_profile.h @@ -0,0 +1,48 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_PROFILE_H__ +#define __ETL_PROFILE_H__ + +#define ETL_THROW_EXCEPTIONS +#define ETL_VERBOSE_ERRORS +#define ETL_CHECK_PUSH_POP +#define ETL_ISTRING_REPAIR_ENABLE +#define ETL_IVECTOR_REPAIR_ENABLE +#define ETL_IDEQUE_REPAIR_ENABLE +#define ETL_IN_UNIT_TEST + +#ifdef _MSC_VER + #include "profiles/msvc_x86.h" +#else + #include "profiles/gcc_windows_x86.h" +#endif + +#endif diff --git a/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation-Delegates/v15/.gitignore b/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation-Delegates/v15/.gitignore new file mode 100644 index 00000000..83235bb7 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation-Delegates/v15/.gitignore @@ -0,0 +1 @@ +*.VC.opendb diff --git a/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation/v15/.gitignore b/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation/v15/.gitignore new file mode 100644 index 00000000..83235bb7 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/vs2017/.vs/FunctionInterruptSimulation/v15/.gitignore @@ -0,0 +1 @@ +*.VC.opendb diff --git a/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.sln b/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.sln new file mode 100644 index 00000000..26180392 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionInterruptSimulation-Delegates", "FunctionInterruptSimulation-Delegates.vcxproj", "{5157DB15-C255-4E47-9FB1-AF388437F90F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x64.ActiveCfg = Debug|x64 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x64.Build.0 = Debug|x64 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x86.ActiveCfg = Debug|Win32 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Debug|x86.Build.0 = Debug|Win32 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x64.ActiveCfg = Release|x64 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x64.Build.0 = Release|x64 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x86.ActiveCfg = Release|Win32 + {5157DB15-C255-4E47-9FB1-AF388437F90F}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {260225EB-60CB-44CC-A60C-16A23BBC10EB} + EndGlobalSection +EndGlobal diff --git a/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.vcxproj b/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.vcxproj new file mode 100644 index 00000000..ca2c92e1 --- /dev/null +++ b/examples/FunctionInterruptSimulation-Delegates/vs2017/FunctionInterruptSimulation-Delegates.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 15.0 + {5157DB15-C255-4E47-9FB1-AF388437F90F} + Win32Proj + FunctionInterruptSimulation + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../src + + + Console + true + + + + + NotUsing + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../include;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/include/etl/delegate.h b/include/etl/delegate.h new file mode 100644 index 00000000..d3f9a5c1 --- /dev/null +++ b/include/etl/delegate.h @@ -0,0 +1,334 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + +Copyright (C) 2017 by Sergey A Kryukov: derived work +http://www.SAKryukov.org +http://www.codeproject.com/Members/SAKryukov + +Based on original work by Sergey Ryazanov: +"The Impossibly Fast C++ Delegates", 18 Jul 2005 +https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates + +MIT license: +http://en.wikipedia.org/wiki/MIT_License + +Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed + +******************************************************************************/ + +#ifndef ETL_DELEGATE_INCLUDED +#define ETL_DELEGATE_INCLUDED + +#include "platform.h" + +#if ETL_CPP11_SUPPORTED == 0 +#error NOT SUPPORTED FOR C++03 OR BELOW +#endif + +namespace etl +{ + template class delegate; + + template + class delegate final + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + delegate() = default; + + //************************************************************************* + // Copy constructor. + //************************************************************************* + delegate(const delegate& other) + { + other.invocation.clone(invocation); + } + + //************************************************************************* + // Constructor from lambda or functor. + //************************************************************************* + template + delegate(const TLambda& instance) + { + assign((void*)(&instance), lambda_stub); + } + + //************************************************************************* + /// Create from function (Compile time). + //************************************************************************* + template + static delegate create() + { + return delegate(nullptr, function_stub); + } + + //************************************************************************* + /// Create from Lambda or Functor. + //************************************************************************* + template + static delegate create(const TLambda& instance) + { + return delegate((void*)(&instance), lambda_stub); + } + + //************************************************************************* + /// Create from instance method (Run time). + //************************************************************************* + template + static delegate create(T& instance) + { + return delegate((void*)(&instance), method_stub); + } + + //************************************************************************* + /// Create from const instance method (Run time). + //************************************************************************* + template + static delegate create(const T& instance) + { + return delegate((void*)(&instance), const_method_stub); + } + + //************************************************************************* + /// Create from instance method (Compile time). + //************************************************************************* + template + static delegate create() + { + return delegate(method_instance_stub); + } + + //************************************************************************* + /// Create from const instance method (Compile time). + //************************************************************************* + template + static delegate create() + { + return delegate(const_method_instance_stub); + } + + //************************************************************************* + /// Execute the delegate. + //************************************************************************* + TReturn operator()(TParams... args) const + { + return (*invocation.stub)(invocation.object, args...); + } + + //************************************************************************* + /// Create from function (Compile time). + //************************************************************************* + delegate& operator =(const delegate& other) + { + other.invocation.clone(invocation); + return *this; + } + + //************************************************************************* + /// Create from Lambda or Functor. + //************************************************************************* + template + delegate& operator =(const TLambda& instance) + { + assign((void*)(&instance), lambda_stub); + return *this; + } + + //************************************************************************* + /// Checks equality. + //************************************************************************* + bool operator == (const delegate& other) const + { + return invocation == other.invocation; + } + + //************************************************************************* + /// Returns true if the delegate is valid. + //************************************************************************* + bool operator != (const delegate& other) const + { + return invocation != other.invocation; + } + + //************************************************************************* + /// Returns true if the delegate is valid. + //************************************************************************* + bool is_valid() const + { + return invocation.stub != nullptr; + } + + //************************************************************************* + /// Returns true if the delegate is valid. + //************************************************************************* + operator bool() const + { + return is_valid(); + } + + private: + + using stub_type = TReturn(*)(void* object, TParams...); + + //************************************************************************* + /// The internal invocation object. + //************************************************************************* + struct invocation_element + { + invocation_element() = default; + + //*********************************************************************** + invocation_element(void* object_, stub_type stub_) + : object(object_) + , stub(stub_) + { + } + + //*********************************************************************** + void clone(invocation_element& target) const + { + target.stub = stub; + target.object = object; + } + + //*********************************************************************** + bool operator ==(const invocation_element& another) const + { + return (another.stub == stub) && (another.object == object); + } + + //*********************************************************************** + bool operator !=(const invocation_element& another) const + { + return (another.stub != stub) || (another.object != object); + } + + //*********************************************************************** + void* object = nullptr; + stub_type stub = nullptr; + }; + + //************************************************************************* + /// Constructs a delegate from an object and stub. + //************************************************************************* + delegate(void* object, stub_type stub) + { + invocation.object = object; + invocation.stub = stub; + } + + //************************************************************************* + /// Constructs a delegate from a stub. + //************************************************************************* + delegate(stub_type stub) + { + invocation.object = nullptr; + invocation.stub = stub; + } + + //************************************************************************* + /// Assign from an object and stub. + //************************************************************************* + void assign(void* object, stub_type stub) + { + invocation.object = object; + invocation.stub = stub; + } + + //************************************************************************* + /// Stub call for a member function. Run time instance. + //************************************************************************* + template + static TReturn method_stub(void* object, TParams... params) + { + T* p = static_cast(object); + return (p->*Method)(params...); + } + + //************************************************************************* + /// Stub call for a const member function. Run time instance. + //************************************************************************* + template + static TReturn const_method_stub(void* object, TParams... params) + { + T* const p = static_cast(object); + return (p->*Method)(params...); + } + + //************************************************************************* + /// Stub call for a member function. Compile time instance. + //************************************************************************* + template + static TReturn method_instance_stub(void*, TParams... params) + { + return (Instance.*Method)(params...); + } + + //************************************************************************* + /// Stub call for a const member function. Compile time instance. + //************************************************************************* + template + static TReturn const_method_instance_stub(void*, TParams... params) + { + return (Instance.*Method)(params...); + } + + //************************************************************************* + /// Stub call for a free function. + //************************************************************************* + template + static TReturn function_stub(void*, TParams... params) + { + return (Method)(params...); + } + + //************************************************************************* + /// Stub call for a lambda or functor function. + //************************************************************************* + template + static TReturn lambda_stub(void* object, TParams... arg) + { + TLambda* p = static_cast(object); + return (p->operator())(arg...); + } + + //************************************************************************* + /// The invocation object. + //************************************************************************* + invocation_element invocation; + }; +} + +#endif diff --git a/include/etl/delegate_service.h b/include/etl/delegate_service.h new file mode 100644 index 00000000..fa65f2c2 --- /dev/null +++ b/include/etl/delegate_service.h @@ -0,0 +1,157 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_DELEGATE_SERVICE_INCLUDED +#define ETL_DELEGATE_SERVICE_INCLUDED + +#include "platform.h" +#include "nullptr.h" +#include "static_assert.h" +#include "delegate.h" +#include "array.h" + +namespace etl +{ + //*************************************************************************** + /// An indexed delegate service. + /// \tparam RANGE The number of delegates to handle. + /// \tparam OFFSET The lowest delegate id value. + /// The delegate ids must range between OFFSET and OFFSET + RANGE - 1. + //*************************************************************************** + template + class delegate_service + { + public: + + //************************************************************************* + /// Reset the delegate service. + /// Sets all delegates to the internal default. + //************************************************************************* + delegate_service() + { + etl::delegate default_delegate = etl::delegate::create, &delegate_service::unhandled>(*this); + + lookup.fill(default_delegate); + } + + //************************************************************************* + /// Registers a delegate for the specified id. + /// Compile time assert if the id is out of range. + /// \tparam ID The id of the delegate. + /// \param delegate Reference to the delegate. + //************************************************************************* + template + void register_delegate(etl::delegate callback) + { + ETL_STATIC_ASSERT(ID < (OFFSET + RANGE), "Callback Id out of range"); + ETL_STATIC_ASSERT(ID >= OFFSET, "Callback Id out of range"); + + lookup[ID - OFFSET] = callback; + } + + //************************************************************************* + /// Registers a delegate for the specified id. + /// No action if the id is out of range. + /// \param id Id of the delegate. + /// \param delegate Reference to the delegate. + //************************************************************************* + void register_delegate(const size_t id, etl::delegate callback) + { + if ((id >= OFFSET) && (id < (OFFSET + RANGE))) + { + lookup[id - OFFSET] = callback; + } + } + + //************************************************************************* + /// Registers an alternative delegate for unhandled ids. + /// \param delegate A reference to the user supplied 'unhandled' delegate. + //************************************************************************* + void register_unhandled_delegate(etl::delegate callback) + { + unhandled_delegate = callback; + } + + //************************************************************************* + /// Executes the delegate function for the index. + /// Compile time assert if the id is out of range. + /// \tparam ID The id of the delegate. + //************************************************************************* + template + void call() + { + ETL_STATIC_ASSERT(ID < (OFFSET + RANGE), "Callback Id out of range"); + ETL_STATIC_ASSERT(ID >= OFFSET, "Callback Id out of range"); + + lookup[ID - OFFSET](ID); + } + + //************************************************************************* + /// Executes the delegate function for the index. + /// \param id Id of the delegate. + //************************************************************************* + void call(const size_t id) + { + if ((id >= OFFSET) && (id < (OFFSET + RANGE))) + { + lookup[id - OFFSET](id); + } + else + { + if (unhandled_delegate.is_valid()) + { + unhandled_delegate(id); + } + } + } + + private: + + //************************************************************************* + /// The default callback function. + /// Calls the user defined 'unhandled' callback if it exists. + //************************************************************************* + void unhandled(size_t id) + { + if (unhandled_delegate.is_valid()) + { + unhandled_delegate(id); + } + } + + /// The default delegate for unhandled ids. + etl::delegate unhandled_delegate; + + /// Lookup table of delegates. + etl::array, RANGE> lookup; + }; +} + +#endif diff --git a/include/etl/multicast_delegate.h b/include/etl/multicast_delegate.h new file mode 100644 index 00000000..9fc3f31a --- /dev/null +++ b/include/etl/multicast_delegate.h @@ -0,0 +1,143 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + + Copyright (C) 2017 by Sergey A Kryukov: derived work + http://www.SAKryukov.org + http://www.codeproject.com/Members/SAKryukov + + Based on original work by Sergey Ryazanov: + "The Impossibly Fast C++ Delegates", 18 Jul 2005 + https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates + + MIT license: + http://en.wikipedia.org/wiki/MIT_License + + Original publication: https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed + +******************************************************************************/ + +//#pragma once +//#include "delegate.h" +//#include +//#include +// +//namespace SA { +// +// template +// class multicast_delegate final : private delegate_base { +// public: +// +// multicast_delegate() = default; +// ~multicast_delegate() { +// for (auto& element : invocationList) delete element; +// invocationList.clear(); +// } //~multicast_delegate +// +// bool isNull() const { return invocationList.size() < 1; } +// bool operator ==(void* ptr) const { +// return (ptr == nullptr) && this->isNull(); +// } //operator == +// bool operator !=(void* ptr) const { +// return (ptr != nullptr) || (!this->isNull()); +// } //operator != +// +// size_t size() const { return invocationList.size(); } +// +// multicast_delegate& operator =(const multicast_delegate&) = delete; +// multicast_delegate(const multicast_delegate&) = delete; +// +// bool operator ==(const multicast_delegate& another) const { +// if (invocationList.size() != another.invocationList.size()) return false; +// auto anotherIt = another.invocationList.begin(); +// for (auto it = invocationList.begin(); it != invocationList.end(); ++it) +// if (**it != **anotherIt) return false; +// return true; +// } //== +// bool operator !=(const multicast_delegate& another) const { return !(*this == another); } +// +// bool operator ==(const delegate& another) const { +// if (isNull() && another.isNull()) return true; +// if (another.isNull() || (size() != 1)) return false; +// return (another.invocation == **invocationList.begin()); +// } //== +// bool operator !=(const delegate& another) const { return !(*this == another); } +// +// multicast_delegate& operator +=(const multicast_delegate& another) { +// for (auto& item : another.invocationList) // clone, not copy; flattens hierarchy: +// this->invocationList.push_back(new typename delegate_base::InvocationElement(item->object, item->stub)); +// return *this; +// } //operator += +// +// template // template instantiation is not neededm, will be deduced/inferred: +// multicast_delegate& operator +=(const LAMBDA & lambda) { +// delegate d = delegate::template create(lambda); +// return *this += d; +// } //operator += +// +// multicast_delegate& operator +=(const delegate& another) { +// if (another.isNull()) return *this; +// this->invocationList.push_back(new typename delegate_base::InvocationElement(another.invocation.object, another.invocation.stub)); +// return *this; +// } //operator += +// +// // will work even if RET is void, return values are ignored: +// // (for handling return values, see operator(..., handler)) +// void operator()(PARAMS... arg) const { +// for (auto& item : invocationList) +// (*(item->stub))(item->object, arg...); +// } //operator() +// +// template +// void operator()(PARAMS... arg, HANDLER handler) const { +// size_t index = 0; +// for (auto& item : invocationList) { +// RET value = (*(item->stub))(item->object, arg...); +// handler(index, &value); +// ++index; +// } //loop +// } //operator() +// +// void operator()(PARAMS... arg, delegate handler) const { +// operator()(arg..., handler); +// } //operator() +// void operator()(PARAMS... arg, std::function handler) const { +// operator()(arg..., handler); +// } //operator() +// +// private: +// +// std::list::InvocationElement *> invocationList; +// +// }; //class multicast_delegate +// +//} /* namespace SA */ +// diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index e71bcdea..359ed911 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -492,14 +492,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 || @@ -600,13 +600,19 @@ namespace etl template struct size_of { - static const size_t size = sizeof(T); + enum + { + size = sizeof(T) + }; }; template <> struct size_of { - static const size_t size = 1; + enum + { + size = 1 + }; }; } diff --git a/include/etl/type_traits_generator.h b/include/etl/type_traits_generator.h index a48a78c6..c45d1ea3 100644 --- a/include/etl/type_traits_generator.h +++ b/include/etl/type_traits_generator.h @@ -605,13 +605,19 @@ namespace etl template struct size_of { - static const size_t size = sizeof(T); + enum + { + size = sizeof(T) + }; }; template <> struct size_of { - static const size_t size = 1; + enum + { + size = 1 + }; }; } diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index a4bfe86e..beb8a603 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -181,6 +181,8 @@ + + @@ -248,6 +250,9 @@ + + + @@ -362,6 +367,8 @@ + + diff --git a/test/test_callback_service.cpp b/test/test_callback_service.cpp index 67de9b16..1173c3f5 100644 --- a/test/test_callback_service.cpp +++ b/test/test_callback_service.cpp @@ -101,22 +101,22 @@ namespace // Callback for 'unhandled'. etl::function_fp unhandled_callback; -} -//***************************************************************************** -// Initialises the test results. -//***************************************************************************** -struct SetupFixture -{ - SetupFixture() + //***************************************************************************** + // Initialises the test results. + //***************************************************************************** + struct SetupFixture { - called_id = UINT_MAX; - global_called = false; - member1_called = false; - member2_called = false; - unhandled_called = false; - } -}; + SetupFixture() + { + called_id = UINT_MAX; + global_called = false; + member1_called = false; + member2_called = false; + unhandled_called = false; + } + }; +} namespace { diff --git a/test/test_delegate.cpp b/test/test_delegate.cpp new file mode 100644 index 00000000..e2a76bd7 --- /dev/null +++ b/test/test_delegate.cpp @@ -0,0 +1,506 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://www.etlcpp.com + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" + +#include "etl/delegate.h" + +namespace +{ + //***************************************************************************** + const int VALUE1 = 1; + const int VALUE2 = 2; + bool function_called = false; + bool parameter_correct = false; + + //***************************************************************************** + // Test data structure. + //***************************************************************************** + struct Data + { + int d; + }; + + Data data; + + //***************************************************************************** + // The free function taking no parameters. + //***************************************************************************** + void free_void() + { + function_called = true; + } + + //***************************************************************************** + // The free function taking an int parameter. + //***************************************************************************** + void free_int(int i, int j) + { + function_called = true; + parameter_correct = (i == VALUE1) && (j == VALUE2); + } + + //***************************************************************************** + // The free function taking a Data reference parameter. + //***************************************************************************** + void free_reference(const Data& data, int j) + { + function_called = true; + parameter_correct = (data.d == VALUE1) && (j = VALUE2); + } + + //***************************************************************************** + // The test class with member functions. + //***************************************************************************** + class Test + { + public: + + //******************************************* + // void + void member_void() + { + function_called = true; + } + + void member_void_const() const + { + function_called = true; + } + + //******************************************* + // int + void member_int(int i, int j) + { + function_called = true; + parameter_correct = (i == VALUE1) && (j == VALUE2); + } + + void member_int_const(int i, int j) const + { + function_called = true; + parameter_correct = (i == VALUE1) && (j == VALUE2); + } + + //******************************************* + // reference + void member_reference(const Data& data, int j) + { + function_called = true; + parameter_correct = (data.d == VALUE1) && (j = VALUE2); + } + + void member_reference_const(const Data& data, int j) const + { + function_called = true; + parameter_correct = (data.d == VALUE1) && (j = VALUE2); + } + + //******************************************* + // static + static void member_static(const Data& data, int j) + { + function_called = true; + parameter_correct = (data.d == VALUE1) && (j = VALUE2); + } + + //******************************************* + // operator() + void operator()() + { + function_called = true; + } + + void operator()() const + { + function_called = true; + } + }; + + Test test_static; + const Test const_test_static; +} + +//***************************************************************************** +// Initialises the test results. +//***************************************************************************** +struct SetupFixture +{ + SetupFixture() + { + function_called = false; + parameter_correct = false; + } +}; + +namespace +{ + SUITE(test_delegate) + { + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_false) + { + etl::delegate d; + + CHECK(!d.is_valid()); + CHECK(!d); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_is_valid_true) + { + etl::delegate d([] {}); + + CHECK(d.is_valid()); + CHECK(d); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_void) + { + etl::delegate d = etl::delegate::create(); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_int) + { + etl::delegate d = etl::delegate::create(); + + d(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_free_reference) + { + etl::delegate d = etl::delegate::create(); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_lambda_int) + { + etl::delegate d([](int i, int j) { function_called = true; parameter_correct = (i == VALUE1) && (j == VALUE2); }); + + d(VALUE1, VALUE2); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_lambda_int_create) + { + auto lambda = [](int i, int j) { function_called = true; parameter_correct = (i == VALUE1) && (j == VALUE2); }; + + etl::delegate d(lambda); + + d(VALUE1, VALUE2); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void) + { + Test test; + + etl::delegate d(test); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void_create) + { + Test test; + + etl::delegate d = etl::delegate::create(test); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_operator_void_const) + { + const Test test; + + etl::delegate d(test); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment_member_operator_void) + { + Test test; + + etl::delegate d; + + d = test; + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void) + { + Test test; + + etl::delegate d = etl::delegate::create(test); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void_const) + { + const Test test; + + etl::delegate d = etl::delegate::create(test); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int) + { + Test test; + + etl::delegate d = etl::delegate::create(test); + + d(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int_const) + { + const Test test; + + etl::delegate d = etl::delegate::create(test); + + d(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference) + { + Test test; + etl::delegate d = etl::delegate::create(test); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference_const) + { + const Test test; + etl::delegate d = etl::delegate::create(test); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_static) + { + etl::delegate d = etl::delegate::create(); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void_compile_time) + { + etl::delegate d = etl::delegate::create(); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_void_const_compile_time) + { + etl::delegate d = etl::delegate::create(); + + d(); + + CHECK(function_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int_compile_time) + { + etl::delegate d = etl::delegate::create(); + + d(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_int_const_compile_time) + { + etl::delegate d = etl::delegate::create(); + + d(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference_compile_time) + { + etl::delegate d = etl::delegate::create(); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_member_reference_const_compile_time) + { + etl::delegate d = etl::delegate::create(); + + Data data; + data.d = VALUE1; + + d(data, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_construct) + { + Test test; + + etl::delegate d1 = etl::delegate::create(test); + etl::delegate d2(d1); + + d2(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_assignment) + { + Test test; + + etl::delegate d1 = etl::delegate::create(test); + etl::delegate d2; + + d2 = d1; + + d2(VALUE1, VALUE2); + + CHECK(function_called); + CHECK(parameter_correct); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_equal) + { + Test test; + + etl::delegate d1 = etl::delegate::create(test); + etl::delegate d2 = d1; + + CHECK(d1 == d2); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_not_equal) + { + Test test; + + etl::delegate d1 = etl::delegate::create(test); + etl::delegate d2 = etl::delegate::create(test);; + + CHECK(d1 != d2); + } + }; +} diff --git a/test/test_delegate_service.cpp b/test/test_delegate_service.cpp new file mode 100644 index 00000000..96f8a4f2 --- /dev/null +++ b/test/test_delegate_service.cpp @@ -0,0 +1,333 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "UnitTest++.h" + +#include "etl/delegate.h" +#include "etl/delegate_service.h" + +namespace +{ + const size_t SIZE = 3U; + const size_t OFFSET = 5U; + + using Service = etl::delegate_service; + + //***************************************************************************** + bool global_called = false; + bool member1_called = false; + bool member2_called = false; + bool unhandled_called = false; + size_t called_id = UINT_MAX; + + //***************************************************************************** + // The global function taking no parameters. + //***************************************************************************** + void global(size_t id) + { + global_called = true; + called_id = id; + } + + //***************************************************************************** + // The external unhandled callback. + //***************************************************************************** + void unhandled(size_t id) + { + unhandled_called = true; + called_id = id; + } + + //***************************************************************************** + // The test class with member functions. + //***************************************************************************** + class Test + { + public: + + Test() + : callback(etl::delegate::create(*this)) + { + } + + void member1(size_t id) + { + member1_called = true; + called_id = id; + } + + void member2(size_t id) + { + member2_called = true; + called_id = id; + } + + // Callback for 'member1'. + etl::delegate callback; + }; + + Test test; + + // Callback for 'member2'. + etl::delegate member_callback = etl::delegate::create(); + + // Callback for 'global'. + etl::delegate global_callback = etl::delegate::create(); + + // Callback for 'unhandled'. + etl::delegate unhandled_callback = etl::delegate::create(); + + //***************************************************************************** + // Initialises the test results. + //***************************************************************************** + struct SetupFixture + { + SetupFixture() + { + called_id = UINT_MAX; + global_called = false; + member1_called = false; + member2_called = false; + unhandled_called = false; + } + }; +} + +namespace +{ + enum + { + GLOBAL = OFFSET, + MEMBER1, + MEMBER2, + OUT_OF_RANGE + }; + + SUITE(test_delegate_service) + { + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_global_compile_time) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(test.callback); + service.register_delegate(member_callback); + + service.call(); + + CHECK_EQUAL(GLOBAL, called_id); + CHECK(global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_global_run_time) + { + Service service; + + service.register_delegate(GLOBAL, global_callback); + service.register_delegate(MEMBER1, test.callback); + service.register_delegate(MEMBER2, member_callback); + + service.call(GLOBAL); + + CHECK_EQUAL(GLOBAL, called_id); + CHECK(global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_member1_compile_time) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(test.callback); + service.register_delegate(member_callback); + + service.call(); + + CHECK_EQUAL(MEMBER1, called_id); + CHECK(!global_called); + CHECK(member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_member1_run_time) + { + Service service; + + service.register_delegate(GLOBAL, global_callback); + service.register_delegate(MEMBER1, test.callback); + service.register_delegate(MEMBER2, member_callback); + + service.call(MEMBER1); + + CHECK_EQUAL(MEMBER1, called_id); + CHECK(!global_called); + CHECK(member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_member2_compile_time) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(test.callback); + service.register_delegate(member_callback); + + service.call(); + + CHECK_EQUAL(MEMBER2, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_unhandled_out_of_range_run_time_default) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(test.callback); + service.register_delegate(member_callback); + + service.call(OUT_OF_RANGE); + + CHECK_EQUAL(UINT_MAX, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_unhandled_out_of_range_run_time_user_supplied) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(test.callback); + service.register_delegate(member_callback); + + service.register_unhandled_delegate(unhandled_callback); + + service.call(OUT_OF_RANGE); + + CHECK_EQUAL(OUT_OF_RANGE, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_unhandled_not_registered_compile_time_default) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(member_callback); + + service.call(); + + CHECK_EQUAL(UINT_MAX, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_unhandled_not_registered_run_time_default) + { + Service service; + + service.register_delegate(GLOBAL, global_callback); + service.register_delegate(MEMBER2, member_callback); + + service.call(MEMBER1); + + CHECK_EQUAL(UINT_MAX, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(!unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_not_registered_compile_time_user_supplied) + { + Service service; + + service.register_delegate(global_callback); + service.register_delegate(member_callback); + + service.register_unhandled_delegate(unhandled_callback); + + service.call(); + + CHECK_EQUAL(MEMBER1, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(unhandled_called); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_delegate_unhandled_run_time_user_supplied) + { + Service service; + + service.register_delegate(GLOBAL, global_callback); + service.register_delegate(MEMBER2, member_callback); + + service.register_unhandled_delegate(unhandled_callback); + + service.call(MEMBER1); + + CHECK_EQUAL(MEMBER1, called_id); + CHECK(!global_called); + CHECK(!member1_called); + CHECK(!member2_called); + CHECK(unhandled_called); + } + }; +} diff --git a/test/test_function.cpp b/test/test_function.cpp index 35b7bf21..3f34e51b 100644 --- a/test/test_function.cpp +++ b/test/test_function.cpp @@ -30,123 +30,126 @@ SOFTWARE. #include "etl/function.h" -//***************************************************************************** -const int VALUE = 1; -bool function_called = false; -bool parameter_correct = false; - -//***************************************************************************** -// Test data structure. -//***************************************************************************** -struct Data +namespace { - int d; -}; + //***************************************************************************** + const int VALUE = 1; + bool function_called = false; + bool parameter_correct = false; -//***************************************************************************** -// Call the function taking no parameters. -//***************************************************************************** -void call(etl::ifunction& function) -{ - function(); -} + //***************************************************************************** + // Test data structure. + //***************************************************************************** + struct Data + { + int d; + }; -//***************************************************************************** -// Call the const function taking no parameters. -//***************************************************************************** -void call(const etl::ifunction& function) -{ - function(); -} + //***************************************************************************** + // Call the function taking no parameters. + //***************************************************************************** + void call(etl::ifunction& function) + { + function(); + } -//***************************************************************************** -// Call the function taking an int parameter. -//***************************************************************************** -void call(etl::ifunction& function) -{ - function(VALUE); -} + //***************************************************************************** + // Call the const function taking no parameters. + //***************************************************************************** + void call(const etl::ifunction& function) + { + function(); + } -//***************************************************************************** -// Call the const function taking an int parameter. -//***************************************************************************** -void call(const etl::ifunction& function) -{ - function(VALUE); -} + //***************************************************************************** + // Call the function taking an int parameter. + //***************************************************************************** + void call(etl::ifunction& function) + { + function(VALUE); + } -//***************************************************************************** -// Call the function taking a Data parameter. -//***************************************************************************** -void call(etl::ifunction& function) -{ - Data data; - data.d = VALUE; - function(data); -} + //***************************************************************************** + // Call the const function taking an int parameter. + //***************************************************************************** + void call(const etl::ifunction& function) + { + function(VALUE); + } -//***************************************************************************** -// Call the const function taking a Data parameter. -//***************************************************************************** -void call(const etl::ifunction& function) -{ - Data data; - data.d = VALUE; - function(data); -} + //***************************************************************************** + // Call the function taking a Data parameter. + //***************************************************************************** + void call(etl::ifunction& function) + { + Data data; + data.d = VALUE; + function(data); + } -//***************************************************************************** -// The free function taking no parameters. -//***************************************************************************** -void free_void() -{ - function_called = true; -} + //***************************************************************************** + // Call the const function taking a Data parameter. + //***************************************************************************** + void call(const etl::ifunction& function) + { + Data data; + data.d = VALUE; + function(data); + } -//***************************************************************************** -// The free function taking an int parameter. -//***************************************************************************** -void free_int(int i) -{ - function_called = true; - parameter_correct = (i == VALUE); -} - -//***************************************************************************** -// The free function taking a Data reference parameter. -//***************************************************************************** -void free_reference(const Data& data) -{ - function_called = true; - parameter_correct = (data.d == VALUE); -} - -//***************************************************************************** -// The test class with member functions. -//***************************************************************************** -class Test -{ -public: - - void member_void() + //***************************************************************************** + // The free function taking no parameters. + //***************************************************************************** + void free_void() { function_called = true; } - void member_int(int i) + //***************************************************************************** + // The free function taking an int parameter. + //***************************************************************************** + void free_int(int i) { function_called = true; parameter_correct = (i == VALUE); } - void member_reference(const Data& data) + //***************************************************************************** + // The free function taking a Data reference parameter. + //***************************************************************************** + void free_reference(const Data& data) { function_called = true; parameter_correct = (data.d == VALUE); } -}; -Test test_static; + //***************************************************************************** + // The test class with member functions. + //***************************************************************************** + class Test + { + public: + + void member_void() + { + function_called = true; + } + + void member_int(int i) + { + function_called = true; + parameter_correct = (i == VALUE); + } + + void member_reference(const Data& data) + { + function_called = true; + parameter_correct = (data.d == VALUE); + } + }; + + Test test_static; +} //***************************************************************************** // Initialises the test results. @@ -504,4 +507,4 @@ namespace CHECK(function_called); } }; -} \ No newline at end of file +} diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 08382b8c..13882be2 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -3688,6 +3688,20 @@ namespace CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_secure_after_resize_down) + { + Text text; + text.set_secure(); + text.assign(STR("ABCDEF")); + + Text::pointer pe = text.end(); + + text.resize(text.size() - 3U); + + CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_secure_after_erase) { diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index 55e9400a..451530f3 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -3688,6 +3688,20 @@ namespace CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_secure_after_resize_down) + { + Text text; + text.set_secure(); + text.assign(STR("ABCDEF")); + + Text::pointer pe = text.end(); + + text.resize(text.size() - 3U); + + CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_secure_after_erase) { diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index a00d8e02..5f9af498 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -3688,6 +3688,20 @@ namespace CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_secure_after_resize_down) + { + Text text; + text.set_secure(); + text.assign(STR("ABCDEF")); + + Text::pointer pe = text.end(); + + text.resize(text.size() - 3U); + + CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_secure_after_erase) { diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index e1aba926..630dd230 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -49,9 +49,12 @@ namespace namespace etl { template <> - struct etl::size_of + struct size_of { - static const size_t size = 20; + enum + { + size = 20 + }; }; } diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 09c910aa..b6bad029 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -372,6 +372,8 @@ + + @@ -582,6 +584,8 @@ + + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 9aa640d9..856baf1d 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -768,6 +768,12 @@ ETL\Containers + + ETL\Utilities + + + ETL\Frameworks + @@ -1220,6 +1226,12 @@ Source Files + + Source Files + + + Source Files +