From 5a245687f6eb0ef9bcbea8752681212c98dd9fed Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 11 Sep 2017 13:27:23 +0200 Subject: [PATCH] [DEV] new etk::Function is now correct --- etest/etest.cpp | 5 +- etest/etest.hpp | 4 +- etk/Color.cpp | 2 - etk/Color.hpp | 1 - etk/Function.hpp | 341 +++++++++++++++++------------------------ etk/NullPtr.hpp | 79 ++++++++++ etk/RegEx.hpp | 1 - etk/String.cpp | 4 +- etk/String.hpp | 55 ++++++- etk/UString.hpp | 33 +++- etk/etk.cpp | 3 +- etk/stdTools.hpp | 35 ++++- etk/typeTrait.hpp | 45 ++++++ etk/types.hpp | 117 +------------- lutin_etk-base.py | 1 + lutin_etk-test.py | 1 + test/testFunction.cpp | 54 +++++++ test/testTrait.cpp | 98 ++++++++---- test/testVector2_f.cpp | 2 - 19 files changed, 515 insertions(+), 366 deletions(-) create mode 100644 etk/NullPtr.hpp diff --git a/etest/etest.cpp b/etest/etest.cpp index ab2dcf7..fa396b9 100644 --- a/etest/etest.cpp +++ b/etest/etest.cpp @@ -110,6 +110,9 @@ void etest::init(int32_t _argc, const char** _argv) { } else if (data == "--etest-list") { listAllTest(); exit(0); + } else if (data == "--etest-filter=") { + ETEST_PRINT("Missing data in the filter list..."); + exit(0); } else if (data.startWith("--etest-filter=") == true) { etk::String filter = &data[15]; ETEST_PRINT(" Filter: " << filter); @@ -199,7 +202,7 @@ int32_t etest::runAllTest() { } ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << ":"); echrono::Steady ticGroup = echrono::Steady::now(); - for (auto &it: getListOfTest()) { + for (auto &it: runList) { if (it->getTestGroup() != itGroup) { continue; } diff --git a/etest/etest.hpp b/etest/etest.hpp index abba79c..936be70 100644 --- a/etest/etest.hpp +++ b/etest/etest.hpp @@ -151,7 +151,7 @@ namespace etest { #define EXPECT_EQ(element, result) \ do { \ - bool ETEST_VARIABLE_TMP_res = (element == result); \ + bool ETEST_VARIABLE_TMP_res = ((element) == (result)); \ if (etest::g_currentTest == nullptr) { \ ETEST_CRITICAL("Not in a test"); \ } else { \ @@ -166,7 +166,7 @@ namespace etest { #define EXPECT_NE(element, result) \ do { \ - bool ETEST_VARIABLE_TMP_res = (element != result); \ + bool ETEST_VARIABLE_TMP_res = ((element) != (result)); \ if (etest::g_currentTest == nullptr) { \ ETEST_CRITICAL("Not in a test"); \ } else { \ diff --git a/etk/Color.cpp b/etk/Color.cpp index 8c31046..21a1bd4 100644 --- a/etk/Color.cpp +++ b/etk/Color.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include class ColorList { public: diff --git a/etk/Color.hpp b/etk/Color.hpp index c6529a6..bd30bcc 100644 --- a/etk/Color.hpp +++ b/etk/Color.hpp @@ -10,7 +10,6 @@ #include #include -#include namespace etk { /** diff --git a/etk/Function.hpp b/etk/Function.hpp index 27fc14e..442a919 100644 --- a/etk/Function.hpp +++ b/etk/Function.hpp @@ -1,18 +1,22 @@ /** @file * @author Edouard DUPIN - * @copyright 2011, Edouard DUPIN, all right reserved + * @copyright 2017, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ #pragma once #include -//#include +#include -//#define ETK_FUNCTION_ENABLE_NEW +// TO facilitate debug when have a problem ... +#define ETK_FUNCTION_DEBUG(...) do {} while(false) +//#define ETK_FUNCTION_DEBUG printf namespace etk { + template + class FunctionPrivateLambda; template - class FunctionPrivateSpecific; + class FunctionPrivateFunction; template class FunctionPrivate; @@ -22,241 +26,170 @@ namespace etk { virtual ~FunctionPrivate() { } - // other constructors, from nullptr, from function pointers virtual ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const = 0; - FunctionPrivate* copy() { + virtual FunctionPrivate* copy() { + ETK_FUNCTION_DEBUG(" COPY NULLPTR \n"); return nullptr; } }; - template - class FunctionPrivateSpecific: + template + class FunctionPrivateLambda: public FunctionPrivate { private: - // function pointer types for the type-erasure behaviors - // all these char* parameters are actually casted from some functor type - typedef ETK_TYPE_FUNCTION_RETURN (*invoke_fn_t)(void*, ETK_TYPE_FUNCTION_ARGS&&...); - #ifdef ETK_FUNCTION_ENABLE_NEW - typedef void* (*construct_fn_t)(); - #endif - typedef void (*destroy_fn_t)(void*); - // type-aware generic functions for invoking - // the specialization of these functions won't be capable with - // the above function pointer types, so we need some cast - template - static ETK_TYPE_FUNCTION_RETURN invoke_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor, - ETK_TYPE_FUNCTION_ARGS&&... _args) { - return (*_functor)(etk::forward(_args)...); - } - #ifdef ETK_FUNCTION_ENABLE_NEW - template - static void* construct_fn() { - // the functor type must be copy-constructible - return new ETK_TYPE_FUNCTION_FUNCTOR(); - } - #endif - template - static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) { - _functor->~ETK_TYPE_FUNCTION_FUNCTOR(); - } - // These pointers are storing behaviors. - invoke_fn_t invoke_f; - #ifdef ETK_FUNCTION_ENABLE_NEW - construct_fn_t construct_f; - #endif - destroy_fn_t destroy_f; - // Erase the type of any functor and store it into a char* - // so the storage size should be obtained as well - void* m_dataPointer; + ETK_TYPE_FUNCTION_FUNCTOR m_dataPointer; public: - FunctionPrivateSpecific(): - invoke_f(nullptr), - #ifdef ETK_FUNCTION_ENABLE_NEW - construct_f(nullptr), - #endif - destroy_f(nullptr), - m_dataPointer(nullptr) { - + FunctionPrivateLambda(ETK_TYPE_FUNCTION_FUNCTOR _functor): + m_dataPointer(_functor) { + ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n"); } - FunctionPrivateSpecific(etk::NullPtr): - invoke_f(nullptr), - #ifdef ETK_FUNCTION_ENABLE_NEW - construct_f(nullptr), - #endif - destroy_f(nullptr), - m_dataPointer(nullptr) { - - } - #ifdef ETK_FUNCTION_ENABLE_NEW - // construct from any functor type - template - FunctionPrivateSpecific(ETK_TYPE_FUNCTION_FUNCTOR _functor): - // specialize functions and erase their type info by casting - invoke_f(reinterpret_cast(invoke_fn)), - construct_f(reinterpret_cast(construct_fn)), - destroy_f(reinterpret_cast(destroy_fn)), - m_dataPointer(nullptr) { - m_dataPointer = construct_f(); - } - // copy constructor /* - FunctionPrivateSpecific(const FunctionPrivateSpecific& _obj): - invoke_f(_obj.invoke_f), - construct_f(_obj.construct_f), - destroy_f(_obj.destroy_f), - m_dataSize(_obj.m_dataSize) { - if (invoke_f) { - // when the source is not a null function, copy its internal functor - delete(m_dataPointer); - m_dataPointer = new char[m_dataSize]; - construct_f(m_dataPointer, _obj.m_dataPointer); - } + FunctionPrivateLambda(const ETK_TYPE_FUNCTION_FUNCTOR& _functor): + m_dataPointer(_functor) { + ETK_FUNCTION_DEBUG(" NEW FunctionPrivateLambda \n"); } */ - #else - // move from any functor type - template - FunctionPrivateSpecific(ETK_TYPE_FUNCTION_FUNCTOR&& _functor): - // specialize functions and erase their type info by casting - invoke_f(reinterpret_cast(invoke_fn)), - #ifdef ETK_FUNCTION_ENABLE_NEW - construct_f(reinterpret_cast(construct_fn)), - #endif - destroy_f(reinterpret_cast(destroy_fn)), - m_dataPointer(nullptr) { - m_dataPointer = etk::move(_functor); + ~FunctionPrivateLambda() { + } - - #endif - ~FunctionPrivateSpecific() { - if (m_dataPointer != nullptr) { - destroy_f(m_dataPointer); - m_dataPointer = nullptr; - } - } - // other constructors, from nullptr, from function pointers ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const { - return invoke_f(m_dataPointer, - etk::forward(_args)...); + return m_dataPointer(etk::forward(_args)...); } - - bool operator!= (etk::NullPtr) const { - return m_dataPointer != nullptr; - } - bool operator== (etk::NullPtr) const { - return m_dataPointer == nullptr; + FunctionPrivate* copy() { + ETK_FUNCTION_DEBUG(" COPY FunctionPrivateLambda \n"); + return new FunctionPrivateLambda(m_dataPointer); } }; + template class Function; + extern uint32_t MM___pppppp; template class Function { private: FunctionPrivate* m_pointerPrivate; - + uint32_t m_pppppp; public: Function(): m_pointerPrivate(nullptr) { - + m_pppppp = MM___pppppp++; + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 1 \n", m_pppppp, (uint64_t)this); } - Function(etk::NullPtr): + Function(const etk::NullPtr&): m_pointerPrivate(nullptr) { - + m_pppppp = MM___pppppp++; + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 2\n", m_pppppp, (uint64_t)this); } - #ifdef ETK_FUNCTION_ENABLE_NEW - // construct from any functor type - template - Function(ETK_TYPE_FUNCTION_FUNCTOR _functor): - m_pointerPrivate(new FunctionPrivateSpecific(_functor)) { - - } - // copy constructor - Function(const Function& _obj): - m_pointerPrivate(nullptr) { - if (_obj.m_pointerPrivate != nullptr) { - m_pointerPrivate = _obj.m_pointerPrivate->copy(); - } - } - #else - // construct from any functor type - template - Function(ETK_TYPE_FUNCTION_FUNCTOR&& _functor): - m_pointerPrivate(new FunctionPrivateSpecific(_functor)) { - - } - #endif - // copy constructor - Function(Function&& _obj): - m_pointerPrivate(_obj.m_pointerPrivate) { - _obj.m_pointerPrivate = nullptr; - } - ~Function() { - delete m_pointerPrivate; - m_pointerPrivate = nullptr; - } - // other constructors, from nullptr, from function pointers - ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const { - if (m_pointerPrivate == nullptr) { - throw; - } - return (*m_pointerPrivate)(etk::forward(_args)...); - } - - bool operator!= (etk::NullPtr) const { - return m_pointerPrivate != nullptr; - } - bool operator== (etk::NullPtr) const { - return m_pointerPrivate == nullptr; - } - #ifdef ETK_FUNCTION_ENABLE_NEW - Function& operator= (const Function& _obj) { - delete m_pointerPrivate; - m_pointerPrivate = nullptr; + Function(const Function& _obj): + m_pointerPrivate(nullptr) { + m_pppppp = MM___pppppp++; + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ---------------------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); if (_obj.m_pointerPrivate != nullptr) { m_pointerPrivate = _obj.m_pointerPrivate->copy(); } - return *this; + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function (copy constructor) ------- (done) ------- [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); } - #endif - Function& operator= (Function&& _obj) { + Function(Function&& _obj): + m_pointerPrivate(nullptr) { + m_pppppp = MM___pppppp++; + ETK_FUNCTION_DEBUG("[%d] new Function 2\n", m_pppppp); + _obj.swap(*this); + ETK_FUNCTION_DEBUG("[%d] new Function 2 (done)\n", m_pppppp); + } + template ::value + && !etk::IsSame::value, int + >::type = 0 + > + Function(ETK_TYPE_FUNCTION_FUNCTOR _functor): + m_pointerPrivate(nullptr) { + m_pppppp = MM___pppppp++; + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 \n", m_pppppp, (uint64_t)this); + m_pointerPrivate = new FunctionPrivateLambda(_functor); + ETK_FUNCTION_DEBUG("[%d=0X%lx] new Function 4 (done)\n", m_pppppp, (uint64_t)this); + } + ~Function() { + ETK_FUNCTION_DEBUG("[%d=0X%lx] DELETE Function \n", m_pppppp, (uint64_t)this); delete m_pointerPrivate; - m_pointerPrivate = _obj.m_pointerPrivate; - _obj.m_pointerPrivate = nullptr; + m_pointerPrivate = nullptr; + } + ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) const { + if (m_pointerPrivate == nullptr) { + ETK_FUNCTION_DEBUG("[%d=0X%lx] call Function (With nullptr !!! ==> must assert ...)\n", m_pppppp, (uint64_t)this); + throw; + } + ETK_FUNCTION_DEBUG("[%d=0X%lx] call Function \n", m_pppppp, (uint64_t)this); + return (*m_pointerPrivate)(etk::forward(_args)...); + } + Function& operator= (const Function& _obj){ + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(set) Function [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); + Function(_obj).swap(*this); + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(set) Function [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); return *this; } + Function& operator= (Function&& _obj){ + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(move) Function [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); + Function(etk::move(_obj)).swap(*this); + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator=(move) Function [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)&_obj); + return *this; + } + Function& operator= (etk::NullPtr _obj) { + delete m_pointerPrivate; + m_pointerPrivate = nullptr; + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = nullptr 0X%lx\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate); + return *this; + } + + void swap(Function& _obj) { + ETK_FUNCTION_DEBUG("[%d=0X%lx] swap [%d=0X%lx]\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)_obj); + etk::swap(m_pointerPrivate, _obj.m_pointerPrivate); + etk::swap(m_pppppp, _obj.m_pppppp); + ETK_FUNCTION_DEBUG("[%d=0X%lx] swap [%d=0X%lx] (done)\n", m_pppppp, (uint64_t)this, _obj.m_pppppp, (uint64_t)_obj); + } + template ::value + && !etk::IsSame::value, int + >::type = 0 + > + Function& operator= (ETK_TYPE_FUNCTION_FUNCTOR&& _functor){ + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = FUNCTOR \n", m_pppppp, (uint64_t)this); + Function(etk::forward(_functor)).swap(*this); + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = FUNCTOR (done)\n", m_pppppp, (uint64_t)this); + return *this; + } + template ::value + && !etk::IsSame::value, int + >::type = 0 + > + Function& operator= (const ETK_TYPE_FUNCTION_FUNCTOR& _functor){ + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = const FUNCTOR& \n", m_pppppp, (uint64_t)this); + Function(_functor).swap(*this); + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator = const FUNCTOR& (done)\n", m_pppppp, (uint64_t)this); + return *this; + } + operator bool() const { + return m_pointerPrivate != nullptr; + } + bool operator!= (etk::NullPtr) const { + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator != nullptr ==> 0X%lx %s\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate, (m_pointerPrivate != nullptr)?"true":"false"); + return m_pointerPrivate != nullptr; + } + bool operator== (etk::NullPtr) const { + ETK_FUNCTION_DEBUG("[%d=0X%lx] operator == nullptr ==> 0X%lx %s\n", m_pppppp, (uint64_t)this, (uint64_t)m_pointerPrivate, (m_pointerPrivate == nullptr)?"true":"false"); + return m_pointerPrivate == nullptr; + } + etk::String toString() const { + etk::String out = "etk::Function<..(...)>(@"; + out += etk::toString((uint64_t)m_pointerPrivate); + out += ")"; + return out; + } }; - - + //! @not_in_doc + template + etk::Stream& operator <<(etk::Stream& _os, const etk::Function& _obj) { + _os << _obj.toString(); + return _os; + } } - -/* -// examples -int main() -{ - int i = 0; - auto fn = [i](etk::String const& s) mutable - { - std::cout << ++i << ". " << s << std::endl; - }; - fn("first"); // 1. first - fn("second"); // 2. second - - // construct from lambda - ::function f(fn); - f("third"); // 3. third - - // copy from another function - ::function g(f); - f("forth - f"); // 4. forth - f - g("forth - g"); // 4. forth - g - - // capture and copy non-trivial types like std::string - std::string x("xxxx"); - ::function h([x]() { std::cout << x << std::endl; }); - h(); - - ::function k(h); - k(); - return 0; -} -*/ \ No newline at end of file diff --git a/etk/NullPtr.hpp b/etk/NullPtr.hpp new file mode 100644 index 0000000..214d217 --- /dev/null +++ b/etk/NullPtr.hpp @@ -0,0 +1,79 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2017, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#pragma once + +namespace etk { + class NullPtr { + public: + template + operator T*() const { + return 0; + } + template + operator T C::*() const { + return 0; + } + typedef void* (etk::NullPtr::*bool_)() const; + template + ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) { + throw; + } + }; + inline NullPtr getNullPointer() { + // etk::nullptr exists. + NullPtr n = { }; + return n; + } +} +// If somebody hasn't already defined nullptr in a custom way... +#if !defined(nullptr) + #define nullptr etk::getNullPointer() +#endif + +template +inline bool operator==(T* p, const etk::NullPtr) { + return p == 0; +} + +template +inline bool operator==(const etk::NullPtr, T* p) { + return p == 0; +} + +template +inline bool operator==(T U::* p, const etk::NullPtr) { + return p == 0; +} + +template +inline bool operator==(const etk::NullPtr, T U::* p) { + return p == 0; +} + +inline bool operator==(const etk::NullPtr, const etk::NullPtr) { + return true; +} + +inline bool operator!=(const etk::NullPtr, const etk::NullPtr) { + return false; +} + +inline bool operator<(const etk::NullPtr, const etk::NullPtr) { + return false; +} + +inline bool operator>(const etk::NullPtr, const etk::NullPtr) { + return false; +} + +inline bool operator<=(const etk::NullPtr, const etk::NullPtr) { + return true; +} + +inline bool operator>=(const etk::NullPtr, const etk::NullPtr) { + return true; +} + diff --git a/etk/RegEx.hpp b/etk/RegEx.hpp index 4ae592d..e202a9f 100644 --- a/etk/RegEx.hpp +++ b/etk/RegEx.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #define TK_REG_DEBUG TK_HIDDEN //#define TK_REG_DEBUG TK_VERBOSE diff --git a/etk/String.cpp b/etk/String.cpp index 5ff6b2f..31e01e5 100644 --- a/etk/String.cpp +++ b/etk/String.cpp @@ -316,11 +316,11 @@ const etk::String::Iterator etk::String::begin() const { } etk::String::Iterator etk::String::end() { - return position( size()-1 ); + return position( size() ); } const etk::String::Iterator etk::String::end() const { - return position( size()-1 ); + return position( size() ); } void etk::String::resize(size_t _newSize, char _value) { diff --git a/etk/String.hpp b/etk/String.hpp index f63b2de..c571c41 100644 --- a/etk/String.hpp +++ b/etk/String.hpp @@ -194,6 +194,9 @@ namespace etk { m_string(const_cast(_obj)) { // nothing to do ... } + size_t getCurrent() const { + return m_current; + } friend class String; }; private: @@ -359,30 +362,50 @@ namespace etk { * @param[in] _nbElement Number of element to add in the String */ void insert(size_t _pos, const char* _item, size_t _nbElement); + //! @previous + void insert(const Iterator& _pos, const char* _item, size_t _nbElement) { + insert(_pos.getCurrent(), _item, _nbElement); + }; /** * @brief Insert one element in the String at a specific position * @param[in] _pos Position to add the elements. * @param[in] _item Element to add. */ void insert(size_t _pos, const char _item); + //! @previous + void insert(const Iterator& _pos, const char _item) { + insert(_pos.getCurrent(), _item); + } /** * @brief Insert one element in the String at a specific position * @param[in] _pos Position to add the elements. * @param[in] _item Element to add. */ void insert(size_t _pos, const String& _value); + //! @previous + void insert(const Iterator& _pos, const String& _value) { + insert(_pos.getCurrent(), _value); + } /** * @brief Remove N element * @param[in] _pos Position to remove the data * @param[in] _nbElement number of element to remove */ void erase(size_t _pos, size_t _nbElement=1); + //! @previous + void erase(const Iterator& _pos) { + erase(_pos.getCurrent(), 1); + } /** * @brief Remove N elements - * @param[in] _pos Position to remove the data - * @param[in] _posEnd Last position number + * @param[in] _start Position to remove the data + * @param[in] _stop Last position number */ - void eraseRange(size_t _pos, size_t _posEnd); + void eraseRange(size_t _start, size_t _stop); + //! @previous + void erase(const Iterator& _start, const Iterator& _stop) { + eraseRange(_start.getCurrent(), _stop.getCurrent()); + } /** * @brief extract data between two point : * @param[in] _posStart start position to extract data @@ -390,6 +413,10 @@ namespace etk { * @return the extracted string */ etk::String extract(size_t _posStart = 0, size_t _posEnd=etk::String::npos) const; + //! @previous + etk::String extract(const Iterator& _start, const Iterator& _stop) const { + return extract(_start.getCurrent(), _stop.getCurrent()); + } /** * @brief Get the pointer on the data * @return pointer on the "C" string @@ -401,18 +428,21 @@ namespace etk { * @return The Iterator */ Iterator position(size_t _pos); + //! @previous const Iterator position(size_t _pos) const; /** * @brief Get an Iterator on the start position of the String * @return The Iterator */ Iterator begin(); + //! @previous const Iterator begin() const; /** * @brief Get an Iterator on the end position of the String * @return The Iterator */ Iterator end(); + //! @previous const Iterator end() const; /** * @brief Change the current size of the string @@ -465,6 +495,25 @@ namespace etk { String operator+ (const char* _left, const String& _right); String operator+ (const String& _left, char _right); String operator+ (char _left, const String& _right); + + inline bool operator== (const char* _left, const String& _right) { + return _right == _left; + } + inline bool operator!= (const char* _left, const String& _right) { + return _right != _left; + } + inline bool operator> (const char* _left, const String& _right) { + return _right > _left; + } + inline bool operator>= (const char* _left, const String& _right) { + return _right >= _left; + } + inline bool operator< (const char* _left, const String& _right) { + return _right < _left; + } + inline bool operator<= (const char* _left, const String& _right) { + return _right <= _left; + } /** * @brief Template to declare conversion from anything in etk::String * @param[in] _variable Variable to convert diff --git a/etk/UString.hpp b/etk/UString.hpp index 753de3a..4661990 100644 --- a/etk/UString.hpp +++ b/etk/UString.hpp @@ -195,6 +195,9 @@ namespace etk { m_string(const_cast(_obj)) { // nothing to do ... } + size_t getCurrent() const { + return m_current; + } friend class UString; }; private: @@ -358,30 +361,50 @@ namespace etk { * @param[in] _nbElement Number of element to add in the String */ void insert(size_t _pos, const char32_t* _item, size_t _nbElement); + //! @previous + void insert(const Iterator& _pos, const char32_t* _item, size_t _nbElement) { + insert(_pos.getCurrent(), _item, _nbElement); + }; /** * @brief Insert one element in the String at a specific position * @param[in] _pos Position to add the elements. * @param[in] _item Element to add. */ void insert(size_t _pos, const char32_t _item); + //! @previous + void insert(const Iterator& _pos, const char32_t _item) { + insert(_pos.getCurrent(), _item); + } /** * @brief Insert one element in the String at a specific position * @param[in] _pos Position to add the elements. * @param[in] _item Element to add. */ void insert(size_t _pos, const etk::UString& _value); + //! @previous + void insert(const Iterator& _pos, const UString& _value) { + insert(_pos.getCurrent(), _value); + } /** * @brief Remove N element * @param[in] _pos Position to remove the data * @param[in] _nbElement number of element to remove */ void erase(size_t _pos, size_t _nbElement=1); + //! @previous + void erase(const Iterator& _pos) { + erase(_pos.getCurrent(), 1); + } /** * @brief Remove N elements - * @param[in] _pos Position to remove the data - * @param[in] _posEnd Last position number + * @param[in] _start Position to remove the data + * @param[in] _stop Last position number */ - void eraseRange(size_t _pos, size_t _posEnd); + void eraseRange(size_t _start, size_t _stop); + //! @previous + void erase(const Iterator& _start, const Iterator& _stop) { + eraseRange(_start.getCurrent(), _stop.getCurrent()); + } /** * @brief extract data between two point : * @param[in] _posStart start position to extract data @@ -389,6 +412,10 @@ namespace etk { * @return the extracted string */ etk::UString extract(size_t _posStart = 0, size_t _posEnd=etk::UString::npos) const; + //! @previous + etk::UString extract(const Iterator& _start, const Iterator& _stop) const { + return extract(_start.getCurrent(), _stop.getCurrent()); + } /** * @brief Get the pointer on the data * @return pointer on the "C" string diff --git a/etk/etk.cpp b/etk/etk.cpp index db84391..e261e44 100644 --- a/etk/etk.cpp +++ b/etk/etk.cpp @@ -10,9 +10,10 @@ #include #include #include +#include static int32_t nbTimeInit = 0; - +uint32_t etk::MM___pppppp = 0; void etk::unInit() { if (nbTimeInit > 1) { nbTimeInit--; diff --git a/etk/stdTools.hpp b/etk/stdTools.hpp index 139597f..11e8655 100644 --- a/etk/stdTools.hpp +++ b/etk/stdTools.hpp @@ -1,2 +1,35 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2017, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#pragma once - +namespace etk { + template const TYPE& min(const TYPE& _val1, const TYPE& _val2) { + return (_val1 > _val2) ? _val2 : _val1; + } + template const TYPE& max(const TYPE& _val1, const TYPE& _val2) { + return (_val1 > _val2) ? _val1 : _val2; + } + /** + * @brief in std, we have min, max but not avg ==> it is missing... the Define of avg template. + * @param[in] _min Minimum value of the range + * @param[in] _val The value that we want a min/max + * @param[in] _max Maximum value of the range + * @return Value that min/max applied + */ + template const TYPE& avg(const TYPE& _min, const TYPE& _val, const TYPE& _max) { + return etk::min(etk::max(_min,_val),_max); + } + template + size_t distance(const ETK_ITERATOR_TYPE& _start, const ETK_ITERATOR_TYPE& _stop) { + size_t out = 0; + ETK_ITERATOR_TYPE tmp = _start; + while (tmp != _stop) { + out++; + ++tmp; + } + return out; + } +} \ No newline at end of file diff --git a/etk/typeTrait.hpp b/etk/typeTrait.hpp index f34a648..fc2fd8f 100644 --- a/etk/typeTrait.hpp +++ b/etk/typeTrait.hpp @@ -109,4 +109,49 @@ namespace etk { public etk::IntegralConstant { }; + + template + struct IsFunction; + + template + struct IsFunction : + public etk::typeFalse { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; + + template + struct IsFunction: + public etk::typeTrue { + + }; } diff --git a/etk/types.hpp b/etk/types.hpp index af85f7f..57c4b9c 100644 --- a/etk/types.hpp +++ b/etk/types.hpp @@ -88,121 +88,8 @@ extern "C" { #define M_PI 3.14159265358979323846 #endif -#if 0 -typedef decltype(nullptr) etk::NullPtr; -#else -namespace etk { - class NullPtr { - public: - // When tested a pointer, acts as 0. - template - operator T*() const { - return 0; - } - template // When tested as a member pointer, acts as 0. - operator T C::*() const { - return 0; - } - typedef void* (etk::NullPtr::*bool_)() const; - // An rvalue of type etk::NullPtr can be converted to an rvalue of type bool; the resulting value is false. - /* - operator bool_() const { - // We can't use operator bool(){ return false; } because bool is convertable to int which breaks other required functionality. - return false; - } - */ - // We can't enable this without generating warnings about nullptr being uninitialized after being used when created without "= {}". - //void* mSizeofVoidPtr; // sizeof(etk::NullPtr) == sizeof(void*). Needs to be public if etk::NullPtr is to be a POD. - template - ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS... _args) { - throw; - //return ETK_TYPE_FUNCTION_RETURN(); - } - private: - //void operator&() const; // Address cannot be taken. ==> TODO: this is really bad, because this create an error in many code - }; - - inline NullPtr nullptrGet() { - // etk::nullptr exists. - NullPtr n = { }; - return n; - } -} +#include -// If somebody hasn't already defined nullptr in a custom way... -#if !defined(nullptr) - #define nullptr etk::nullptrGet() -#endif - -#endif - -template -inline bool operator==(T* p, const etk::NullPtr) { - return p == 0; -} - -template -inline bool operator==(const etk::NullPtr, T* p) -{ return p == 0; } - -template -inline bool operator==(T U::* p, const etk::NullPtr) -{ return p == 0; } - -template -inline bool operator==(const etk::NullPtr, T U::* p) -{ return p == 0; } - -inline bool operator==(const etk::NullPtr, const etk::NullPtr) -{ return true; } - -inline bool operator!=(const etk::NullPtr, const etk::NullPtr) -{ return false; } - -inline bool operator<(const etk::NullPtr, const etk::NullPtr) -{ return false; } - -inline bool operator>(const etk::NullPtr, const etk::NullPtr) -{ return false; } - -inline bool operator<=(const etk::NullPtr, const etk::NullPtr) -{ return true; } - -inline bool operator>=(const etk::NullPtr, const etk::NullPtr) -{ return true; } - -// TODO: remove ... -// exported to global namespace. -//using etk::NullPtr; - - -namespace etk { - template const TYPE& min(const TYPE& _val1, const TYPE& _val2) { - return (_val1 > _val2) ? _val2 : _val1; - } - template const TYPE& max(const TYPE& _val1, const TYPE& _val2) { - return (_val1 > _val2) ? _val1 : _val2; - } - /** - * @brief in std, we have min, max but not avg ==> it is missing... the Define of avg template. - * @param[in] _min Minimum value of the range - * @param[in] _val The value that we want a min/max - * @param[in] _max Maximum value of the range - * @return Value that min/max applied - */ - template const TYPE& avg(const TYPE& _min, const TYPE& _val, const TYPE& _max) { - return etk::min(etk::max(_min,_val),_max); - } - template - size_t distance(const ETK_ITERATOR_TYPE& _start, const ETK_ITERATOR_TYPE& _stop) { - size_t out = 0; - ETK_ITERATOR_TYPE tmp = _start; - while (tmp != _stop) { - out++; - ++tmp; - } - return out; - } -} +#include #include #include diff --git a/lutin_etk-base.py b/lutin_etk-base.py index d670f1b..fac5330 100644 --- a/lutin_etk-base.py +++ b/lutin_etk-base.py @@ -51,6 +51,7 @@ def configure(target, my_module): 'etk/move.hpp', 'etk/typeTrait.hpp', 'etk/Function.hpp', + 'etk/NullPtr.hpp', ]) # build in C++ mode diff --git a/lutin_etk-test.py b/lutin_etk-test.py index d445e1f..10ee332 100644 --- a/lutin_etk-test.py +++ b/lutin_etk-test.py @@ -42,6 +42,7 @@ def configure(target, my_module): 'test/testQuaternion.cpp', 'test/testVector2_f.cpp', 'test/testString.cpp', + 'test/testTrait.cpp', ]) my_module.add_depend([ 'etk', diff --git a/test/testFunction.cpp b/test/testFunction.cpp index 0cb8912..f27bd8d 100644 --- a/test/testFunction.cpp +++ b/test/testFunction.cpp @@ -51,6 +51,7 @@ TEST(TestFunction, setALambda) { etk::Function f_display = []() { print_num(642); };; EXPECT_NE(f_display, nullptr); } + TEST(TestFunction, callAlLambda) { globalValue = 0; // Test contructor value @@ -59,6 +60,58 @@ TEST(TestFunction, callAlLambda) { EXPECT_EQ(globalValue, 42 + 1000); } +class testObject { + private: + uint32_t m_id; + public: + testObject(int32_t iii) { + m_id = iii; + TEST_DEBUG("Call testObject Contructor " << m_id); + } + ~testObject() { + TEST_DEBUG("Call testObject Destructor " << m_id); + } + void operator() (int32_t iii) { + globalValue = m_id + iii; + } +}; + +/* +TEST(TestFunction, setCallableObject) { + globalValue = 0; + // Test contructor value + testObject tmp(100000); + etk::Function f_display = tmp; + EXPECT_NE(f_display, nullptr); +} + +TEST(TestFunction, callCallableObject) { + globalValue = 0; + // Test contructor value + testObject tmp(550000); + etk::Function f_display = tmp; + f_display(43); + EXPECT_EQ(globalValue, 43 + 550000); +} +*/ +etk::Function createTmpFunction(uint32_t _value) { + return [=](int32_t _data) { globalValue = _value + _data;}; +} + +TEST(TestFunction, setLambdaOnStack) { + globalValue = 0; + etk::Function f_display = createTmpFunction(87000); + EXPECT_NE(f_display, nullptr); +} + +TEST(TestFunction, callLambdaOnStack) { + globalValue = 0; + etk::Function f_display = createTmpFunction(88000); + f_display(44); + EXPECT_EQ(globalValue, 44 + 88000); +} + +/* TEST(TestFunction, setAMemberFunction) { globalValue = 0; // Test contructor value @@ -74,4 +127,5 @@ TEST(TestFunction, callAMemberFunction) { f_display(foo, 16); EXPECT_EQ(globalValue, 16 + 70000); } +*/ diff --git a/test/testTrait.cpp b/test/testTrait.cpp index cab2096..b8bd616 100644 --- a/test/testTrait.cpp +++ b/test/testTrait.cpp @@ -11,30 +11,37 @@ TEST(typeTrait, RemoveConstVolatile_1) { typedef std::remove_cv::type type1; - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, RemoveConstVolatile_2) { typedef std::remove_cv::type type1; - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, RemoveConstVolatile_3) { typedef std::remove_cv::type type1; - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, RemoveConstVolatile_4) { typedef std::remove_cv::type type1; - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, RemoveConstVolatile_5) { typedef std::remove_cv::type type1; - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsVoid_1) { - EXPECT_EQ(etk::IsVoid::value, true); + auto ret = etk::IsVoid::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsVoid_2) { - EXPECT_EQ(etk::IsVoid::value, false); + auto ret = etk::IsVoid::value; + EXPECT_EQ(ret, false); } class A {}; @@ -44,52 +51,79 @@ class B : A {}; class C {}; TEST(typeTrait, IsBaseOf_1) { - EXPECT_EQ(etk::IsBaseOf::value, true); + auto ret = etk::IsBaseOf::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsBaseOf_2) { - EXPECT_EQ(etk::IsBaseOf::value, false); + auto ret = etk::IsBaseOf::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsBaseOf_3) { - EXPECT_EQ(etk::IsBaseOf::value, false); + auto ret = etk::IsBaseOf::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsBaseOf_4) { - EXPECT_EQ(etk::IsBaseOf::value, true); + auto ret = etk::IsBaseOf::value; + EXPECT_EQ(ret, true); } + +TEST(typeTrait, isSame_nullptr) { + typedef etk::NullPtr type1; + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); +} +/* +TEST(typeTrait, isSame_nullptr2) { + typedef etk::NullPtr type1; + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); +} +*/ + TEST(typeTrait, IsSame_1) { - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsSame_2) { - EXPECT_EQ(etk::IsSame::value, false); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsSame_3) { - EXPECT_EQ(etk::IsSame::value, false); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsSame_4) { - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsSame_5) { - EXPECT_EQ(etk::IsSame::value, false); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsSame_6) { - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsSame_7) { - EXPECT_EQ(etk::IsSame::value, true); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsSame_8) { - EXPECT_EQ(etk::IsSame::value, false); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsSame_9) { - EXPECT_EQ(etk::IsSame::value, false); + auto ret = etk::IsSame::value; + EXPECT_EQ(ret, false); } @@ -101,16 +135,20 @@ class K_B {}; enum class K_C {}; TEST(typeTrait, IsClass_1) { - EXPECT_EQ(etk::IsClass::value, true); + auto ret = etk::IsClass::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsClass_2) { - EXPECT_EQ(etk::IsClass::value, true); + auto ret = etk::IsClass::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsClass_3) { - EXPECT_EQ(etk::IsClass::value, false); + auto ret = etk::IsClass::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsClass_4) { - EXPECT_EQ(etk::IsClass::value, false); + auto ret = etk::IsClass::value; + EXPECT_EQ(ret, false); } @@ -129,16 +167,20 @@ struct J_C { }; TEST(typeTrait, IsUnion_1) { - EXPECT_EQ(etk::IsUnion::value, false); + auto ret = etk::IsUnion::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsUnion_2) { - EXPECT_EQ(etk::IsUnion::value, true); + auto ret = etk::IsUnion::value; + EXPECT_EQ(ret, true); } TEST(typeTrait, IsUnion_3) { - EXPECT_EQ(etk::IsUnion::value, false); + auto ret = etk::IsUnion::value; + EXPECT_EQ(ret, false); } TEST(typeTrait, IsUnion_4) { - EXPECT_EQ(etk::IsUnion::value, false); + auto ret = etk::IsUnion::value; + EXPECT_EQ(ret, false); } diff --git a/test/testVector2_f.cpp b/test/testVector2_f.cpp index 470866e..7e73cd3 100644 --- a/test/testVector2_f.cpp +++ b/test/testVector2_f.cpp @@ -32,8 +32,6 @@ TEST(TestVector2D_f, constructor) { TEST(TestVector2D_f, constructorString) { etk::Vector2D vect1("(4,-8.5)"); EXPECT_EQ(vect1, etk::Vector2D(4.0,-8.5)); - EXPECT_FLOAT_EQ(vect1.y(), -8.5); - EXPECT_FLOAT_EQ(vect1.y(), -8.5); etk::Vector2D vect2("-6,5.5"); EXPECT_FLOAT_EQ(vect2.x(), -6.0); EXPECT_FLOAT_EQ(vect2.y(), 5.5);