diff --git a/etk/Function.hpp b/etk/Function.hpp index 5d02fac..a58a94a 100644 --- a/etk/Function.hpp +++ b/etk/Function.hpp @@ -9,27 +9,120 @@ #pragma once namespace etk { - /** - * @brief Generic Thread interface (OS independent) - */ - template - class Function { - private: - #ifdef __TARGET_OS__Windows - - #else - pthread_mutex_t m_thread; - #endif - uint32_t m_uid; //!< unique id of the thread - etk::String m_name; //!< Name of the thread (do not get it on the system ==> more portable) - etk::Function m_function; //!< Function to call every cycle of the thead running - public: - Thread(etk::Function&& _call, const std::string& _name); - ~Thread(); - void join(); - bool detach(); - void setName(const std::string& _name); - const std::string& setName() const; - uint32_t getIdentifier() const; + template + class Function; + template + class Function { + // 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)(char*, ETK_TYPE_FUNCTION_ARGS&&...); + typedef void (*construct_fn_t)(char*, char*); + typedef void (*destroy_fn_t)(char*); + + // 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)(std::forward(_args)...); + } + template + static void construct_fn(ETK_TYPE_FUNCTION_FUNCTOR* _constructDestination, + ETK_TYPE_FUNCTION_FUNCTOR* _constructSource) { + // the functor type must be copy-constructible + new (_constructDestination) Functor(*_constructSource); + } + template + static void destroy_fn(ETK_TYPE_FUNCTION_FUNCTOR* _functor) { + _functor->~Functor(); + } + // These pointers are storing behaviors. + invoke_fn_t invoke_f; + construct_fn_t construct_f; + 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 + std::unique_ptr m_dataPointer; + size_t m_dataSize; + public: + function() + : invoke_f(nullptr) + , construct_f(nullptr) + , destroy_f(nullptr) + , m_dataPointer(nullptr) + , m_dataSize(0) + {} + + // construct from any functor type + template + Function(ETK_TYPE_FUNCTION_FUNCTOR _funtor) + // 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(new char[sizeof(ETK_TYPE_FUNCTION_FUNCTOR)]) + , m_dataSize(sizeof(ETK_TYPE_FUNCTION_FUNCTOR)) + { + // copy the functor to internal storage + this->construct_f(this->m_dataPointer.get(), reinterpret_cast(&_functor)); + } + + // copy constructor + Function(Function const& rhs): + invoke_f(rhs.invoke_f), + construct_f(rhs.construct_f) + destroy_f(rhs.destroy_f), + dataSize(rhs.dataSize) { + if (this->invoke_f) { + // when the source is not a null function, copy its internal functor + this->m_dataPointer.reset(new char[this->m_dataSize]); + this->construct_f(this->m_dataPointer.get(), rhs.m_dataPointer.get()); + } + } + + ~Function() { + if (m_dataPointer != nullptr) { + this->destroy_f(this->m_dataPointer.get()); + } + } + + // other constructors, from nullptr, from function pointers + + ETK_TYPE_FUNCTION_RETURN operator()(ETK_TYPE_FUNCTION_ARGS&&... _args) { + return this->invoke_f(this->m_dataPointer.get(), + std::forward(_args)...); + } }; } +/* +// 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/String.cpp b/etk/String.cpp index 56215d7..0c5c695 100644 --- a/etk/String.cpp +++ b/etk/String.cpp @@ -324,7 +324,9 @@ const etk::String::Iterator etk::String::end() const { void etk::String::resize(size_t _newSize, char _value) { size_t oldSize = m_data.size(); - m_data[m_data.size()-1] = _value; + if (oldSize != 0) { + m_data[m_data.size()-1] = _value; + } m_data.resize(_newSize + 1, _value); // in all case ==> we have the last element that is '\0' m_data[_newSize] = '\0'; diff --git a/etk/Vector.hpp b/etk/Vector.hpp index 09c336c..cee836d 100644 --- a/etk/Vector.hpp +++ b/etk/Vector.hpp @@ -190,7 +190,6 @@ namespace etk { * @return the reference on the current Element */ ETK_VECTOR_TYPE* operator-> () const { - //TK_CHECK_INOUT(m_current < m_vector->size()); return &m_vector->get(m_current); } /** @@ -198,7 +197,6 @@ namespace etk { * @return the reference on the current Element */ ETK_VECTOR_TYPE& operator* () const { - //TK_CHECK_INOUT(m_current < m_vector->size()); return m_vector->get(m_current); } private: @@ -228,15 +226,13 @@ namespace etk { * @brief Re-copy constructor (copy all needed data) * @param[in] _obj Vector that might be copy */ - Vector(const etk::Vector& _obj) { - m_allocated = _obj.m_allocated; - m_size = _obj.m_size; - m_data = nullptr; - //TK_DEBUG("USE Specific vector allocator ... Evb.m_size=" << Evb.m_size << " Evb.m_increment=" << Evb.m_increment); + Vector(const etk::Vector& _obj): + m_data(nullptr), + m_size(_obj.m_size), + m_allocated(_obj.m_allocated) { // allocate all same data m_data = new ETK_VECTOR_TYPE[m_allocated]; if (m_data == nullptr) { - //TK_CRITICAL("Vector : Error in data allocation ... might nor work correctly anymore"); return; } // Copy all data ... @@ -245,6 +241,12 @@ namespace etk { m_data[iii] = _obj.m_data[iii]; } } + Vector(const etk::Vector&& _obj): + m_data(etk::move(_obj.m_data)), + m_size(etk::move(_obj.m_size)), + m_allocated(etk::move(_obj.m_allocated)) { + + } /** * @brief Destructor of the current Class */ @@ -280,7 +282,6 @@ namespace etk { * @return reference on the current re-copy vector */ Vector& operator=(const etk::Vector & _obj) { - //TK_DEBUG("USE RECOPY vector ... Evb.m_size=" << Evb.m_size << " Evb.m_increment=" << Evb.m_increment); if (this != &_obj) { if (m_data != nullptr) { delete[] m_data; @@ -292,12 +293,11 @@ namespace etk { // allocate all same data m_data = new ETK_VECTOR_TYPE[m_allocated]; if (m_data == nullptr) { - //TK_CRITICAL("Vector : Error in data allocation ... might nor work correctly anymore"); return *this; } for(size_t iii=0; iii + +#include +#include +#define NAME "Map" + +TEST(TestEtkMap, Creation) { + etk::Map testData(0,true); + EXPECT_EQ(testData.size(), 0); +} + +TEST(TestEtkMap, add_ordered) { + etk::Map testData(0,true); + EXPECT_EQ(testData.size(), 0); + testData.add(2, "a 2"); + testData.add(19, "b 19"); + testData.add(1, "c 1"); + testData.add(5, "d 5"); + testData.add(66, "e 66"); + EXPECT_EQ(testData.size(), 5); + EXPECT_EQ(testData[1], "c 1"); + EXPECT_EQ(testData.getValue(0), "c 1"); +} diff --git a/test/testHash.cpp b/test/testMapUnordered.cpp similarity index 100% rename from test/testHash.cpp rename to test/testMapUnordered.cpp diff --git a/test/testStdShared.cpp b/test/testStdShared.cpp deleted file mode 100644 index 44e9a67..0000000 --- a/test/testStdShared.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license MPL v2.0 (see license file) - */ - -#include -#include -#include -#define NAME "Shared_ptr" - -class Example : public ememory::EnableSharedFromThis { - protected: - int32_t m_id; - public: - Example() { - static int32_t mid = 0; - m_id = mid++; - std::cout << "create Example [" << m_id << "]" << std::endl; - } - ~Example() { - std::cout << "Remove Example [" << m_id << "]" << std::endl; - } -}; - - - -TEST(TestSTDSharedPtr, testBaseLocal) { - Example(); -} - -TEST(TestSTDSharedPtr, testBaseShared) { - ememory::SharedPtr tmp = ememory::makeShared(); -} - - -TEST(TestSTDSharedPtr, testBaseSharedDouble) { - ememory::SharedPtr tmp = ememory::makeShared(); - ememory::SharedPtr tmp2 = tmp; -} -/* -TEST(TestSTDSharedPtr, testBaseSharedDirectAndShared) { - Example tmp; - ememory::SharedPtr tmp2 = ememory::makeShared; -} -*/ \ No newline at end of file