diff --git a/include/etl/memory.h b/include/etl/memory.h index 0d06a1f0..de82cc95 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -31,13 +31,14 @@ SOFTWARE. #ifndef ETL_MEMORY_INCLUDED #define ETL_MEMORY_INCLUDED -#include "algorithm.h" - #include "platform.h" +#include "algorithm.h" #include "type_traits.h" #include "stl/iterator.h" +#include + ///\defgroup memory memory ///\ingroup etl namespace etl @@ -96,7 +97,7 @@ namespace etl count += int32_t(std::distance(o_begin, o_end)); std::fill(o_begin, o_end, value); - + return o_end; } @@ -340,7 +341,7 @@ namespace etl /// Default initialises N objects to uninitialised memory. ///\ingroup memory //***************************************************************************** - template + template typename etl::enable_if::value_type>::value, TOutputIterator>::type uninitialized_default_construct_n(TOutputIterator o_begin, TSize n) { @@ -770,12 +771,41 @@ namespace etl }; //***************************************************************************** - /// Unique pointer. + /// Default deleter. ///\tparam T The pointed to type type. ///\ingroup memory //***************************************************************************** template - class unique_ptr + struct default_delete + { + void operator()(T* p) const + { + delete p; + } + }; + + //***************************************************************************** + /// Default deleter for arrays. + ///\tparam T The pointed to type type. + ///\ingroup memory + //***************************************************************************** + template + struct default_delete + { + template + void operator()(U* p) const + { + delete[] p; + } + }; + + //***************************************************************************** + /// Unique pointer. + ///\tparam T The pointed to type type. + ///\ingroup memory + //***************************************************************************** + template > + class unique_ptr { public: @@ -799,22 +829,32 @@ namespace etl { } #endif - + ~unique_ptr() { - delete p; + deleter(p); } ETL_CONSTEXPR pointer get() const { return p; } - + + TDeleter& get_deleter() + { + return deleter; + } + + const TDeleter& get_deleter() const + { + return deleter; + } + pointer release() - { + { pointer value = p; p = nullptr; - + return value; } @@ -826,21 +866,21 @@ namespace etl p = p_; delete value; } - + void swap(unique_ptr& value) - { + { std::swap(p, value.p); } - + ETL_CONSTEXPR explicit operator bool() const { return (p != nullptr); } - + unique_ptr& operator =(pointer p_) { reset(p_); - + return *this; } @@ -848,36 +888,36 @@ namespace etl unique_ptr& operator =(unique_ptr&& p_) { reset(p_.release()); - - return *this; + + return *this; } #endif - + ETL_CONSTEXPR reference operator *() const { return *get(); } - + ETL_CONSTEXPR pointer operator ->() const { return get(); } - + ETL_CONSTEXPR reference operator [](size_t i) const { return get()[i]; } - + ETL_CONSTEXPR bool operator== (const pointer p_) const { return p == p_; } - + ETL_CONSTEXPR bool operator== (const unique_ptr& p_) const { return p == p_.p; } - + ETL_CONSTEXPR bool operator< (const unique_ptr& p_) const { return p < p_.p; @@ -889,25 +929,26 @@ namespace etl unique_ptr(const unique_ptr&); unique_ptr& operator =(const unique_ptr&); + TDeleter deleter; + pointer p; }; - //***************************************************************************** /// Unique pointer for arrays. ///\tparam T The pointed to type type. ///\ingroup memory //***************************************************************************** - template - class unique_ptr + template + class unique_ptr { public: typedef T element_type; typedef T* pointer; typedef T& reference; - - ETL_CONSTEXPR unique_ptr() + + ETL_CONSTEXPR unique_ptr() : p(nullptr) { } @@ -916,43 +957,53 @@ namespace etl : p(p_) { } - + #if ETL_CPP11_SUPPORTED unique_ptr(unique_ptr&& p_) : p(p_.release()) { } #endif - - ~unique_ptr() + + ~unique_ptr() { - delete[] p; + deleter(p); } - + ETL_CONSTEXPR pointer get() const { return p; } - - pointer release() + + TDeleter& get_deleter() + { + return deleter; + } + + const TDeleter& get_deleter() const + { + return deleter; + } + + pointer release() { pointer value = p; p = nullptr; return value; } - + void reset(pointer p_) { assert(p_ != p); - pointer value = p; - p = p_; - delete[] value; + pointer value = p; + p = p_; + delete[] value; } void swap(unique_ptr& v) { - std::swap(p, v.p); + std::swap(p, v.p); } ETL_CONSTEXPR explicit operator bool() const @@ -963,8 +1014,8 @@ namespace etl unique_ptr& operator =(pointer p_) { reset(p_); - - return *this; + + return *this; } #if ETL_CPP11_SUPPORTED @@ -972,31 +1023,31 @@ namespace etl { reset(p_.release()); - return *this; + return *this; } #endif ETL_CONSTEXPR reference operator *() const { - return *p; + return *p; } ETL_CONSTEXPR pointer operator ->() const { - return p; + return p; } ETL_CONSTEXPR reference operator [](size_t i) const { - return p[i]; + return p[i]; } ETL_CONSTEXPR bool operator ==(const pointer p_) const { - return (p == p_); + return (p == p_); } - ETL_CONSTEXPR bool operator ==(const unique_ptr& p_) const + ETL_CONSTEXPR bool operator ==(const unique_ptr& p_) const { return (p == p_.p); } @@ -1005,14 +1056,33 @@ namespace etl { return (p < p_.p); } - + private: // Deleted. unique_ptr(const unique_ptr&); unique_ptr& operator =(const unique_ptr&); - pointer p; + TDeleter deleter; + + pointer p; + }; + + //***************************************************************************** + /// Base class for objects that require their memory to be wiped after use. + /// Erases the object's memory to zero. + /// Note: This must be the last destructor called for the derived object. + ///\tparam T The derived type. + ///\ingroup memory + //***************************************************************************** + template + struct wipe_on_destruct + { + ~wipe_on_destruct() + { + char* pobject = reinterpret_cast(static_cast(this)); + memset(pobject, 0, sizeof(T)); + } }; } diff --git a/include/etl/version.h b/include/etl/version.h index caaedbcf..933abed9 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -37,10 +37,10 @@ SOFTWARE. /// Definitions of the ETL version ///\ingroup utilities -#define ETL_VERSION "11.13.2" +#define ETL_VERSION "11.14.0" #define ETL_VERSION_MAJOR 11 -#define ETL_VERSION_MINOR 13 -#define ETL_VERSION_PATCH 2 +#define ETL_VERSION_MINOR 14 +#define ETL_VERSION_PATCH 0 #endif diff --git a/support/Release notes.txt b/support/Release notes.txt index e9202643..3d4b9fac 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,9 @@ +=============================================================================== +11.14.0 +Added tests for limited support for self insert for strings. +Added 'wipe_on_destruct' template class for secure wiping of objects on destruction. +Updated unique_ptr API. + =============================================================================== 11.13.2 Protected destructor for some FSM classes. diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 0f5f0f4e..85eab67a 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -528,5 +528,47 @@ namespace CHECK_EQUAL(test_item_trivial, etl::make_copy_at(pn, test_item_trivial, count)); CHECK_EQUAL(3U, count); } + + //************************************************************************* + TEST(test_wipe_on_destruct) + { + struct Data : public etl::wipe_on_destruct + { + Data(int a_, char b_, double c_) + : a(a_), + b(b_), + c(c_) + { + } + + bool operator ==(const Data& other) const + { + return (a == other.a) && (b == other.b) && (c == other.c); + } + + int a; + char b; + double c; + }; + + std::array buffer; + buffer.fill(0); + + // Construct in-place. + ::new (buffer.data()) Data(1, 'b', 3.4); + + Data& other = *reinterpret_cast(buffer.data()); + CHECK(other == Data(1, 'b', 3.4)); + + // Cleared compare buffer. + std::array clear; + clear.fill(0); + + // Destruct; + other.~Data(); + + // Storage should be wiped. + CHECK(buffer == clear); + } }; } diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 3d9aab80..948476f3 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -48,6 +48,7 @@ namespace typedef etl::istring IText; typedef std::string Compare_Text; typedef Text::value_type value_t; + typedef etl::string<52> TextL; Compare_Text initial_text; Compare_Text less_text; @@ -867,6 +868,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_self) + { + size_t length = TextL::MAX_SIZE / 2; + + for (size_t offset = 10; offset < length; ++offset) + { + Compare_Text compare_text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + TextL text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + text.insert(text.begin() + offset, text.begin() + 5, text.begin() + 10); + compare_text.insert(compare_text.begin() + offset, compare_text.begin() + 5, compare_text.begin() + 10); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + } + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_size_t_position_string) { diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 62de9237..81ed3a4a 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -47,6 +47,7 @@ namespace typedef etl::iu16string IText; typedef std::u16string Compare_Text; typedef Text::value_type value_t; + typedef etl::u16string<52> TextL; Compare_Text initial_text; Compare_Text less_text; @@ -866,6 +867,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_self) + { + size_t length = TextL::MAX_SIZE / 2; + + for (size_t offset = 10; offset < length; ++offset) + { + Compare_Text compare_text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + TextL text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + text.insert(text.begin() + offset, text.begin() + 5, text.begin() + 10); + compare_text.insert(compare_text.begin() + offset, compare_text.begin() + 5, compare_text.begin() + 10); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + } + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_size_t_position_string) { diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index 4cfd43f9..e3f3528e 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -47,6 +47,7 @@ namespace typedef etl::iu32string IText; typedef std::u32string Compare_Text; typedef Text::value_type value_t; + typedef etl::u32string<52> TextL; Compare_Text initial_text; Compare_Text less_text; @@ -583,8 +584,6 @@ namespace CHECK(is_equal); } - - //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back) { @@ -866,6 +865,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_self) + { + size_t length = TextL::MAX_SIZE / 2; + + for (size_t offset = 10; offset < length; ++offset) + { + Compare_Text compare_text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + TextL text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + text.insert(text.begin() + offset, text.begin() + 5, text.begin() + 10); + compare_text.insert(compare_text.begin() + offset, compare_text.begin() + 5, compare_text.begin() + 10); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + } + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_size_t_position_string) { diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index ff538896..e1cbdad2 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -47,6 +47,7 @@ namespace typedef etl::iwstring IText; typedef std::wstring Compare_Text; typedef Text::value_type value_t; + typedef etl::wstring<52> TextL; Compare_Text initial_text; Compare_Text less_text; @@ -866,6 +867,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_self) + { + size_t length = TextL::MAX_SIZE / 2; + + for (size_t offset = 10; offset < length; ++offset) + { + Compare_Text compare_text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + TextL text = STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + text.insert(text.begin() + offset, text.begin() + 5, text.begin() + 10); + compare_text.insert(compare_text.begin() + offset, compare_text.begin() + 5, compare_text.begin() + 10); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + } + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_size_t_position_string) {