diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4cd52cc1..090b5302 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,7 +10,9 @@ COPY ./reinstall-cmake.sh /tmp/ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends \ git \ - wget + wget \ + python3-cogapp \ + && rm -rf /var/lib/apt/lists/* RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \ diff --git a/.github/workflows/generator.yml b/.github/workflows/generator.yml new file mode 100644 index 00000000..032ffd1e --- /dev/null +++ b/.github/workflows/generator.yml @@ -0,0 +1,25 @@ +name: generator checks +on: + push: + branches: [ master, development, pull-request/* ] + pull_request: + branches: [ master, pull-request/* ] + types: [opened, synchronize, reopened] + +jobs: + generator-run: + name: Header Generator + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Generate + run: | + sudo apt-get update + sudo apt-get install -y python3-cogapp + cd include/etl/generators && bash generate.bat + + - name: Check Generated Headers For Changes + run: | + git diff --exit-code diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 9288f7f6..1899443a 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library ETL", - "version": "20.44.1", + "version": "20.44.2", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index 4dac09db..e4799f0e 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.44.1 +version=20.44.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/absolute.h b/include/etl/absolute.h index 316be415..cad11b7c 100644 --- a/include/etl/absolute.h +++ b/include/etl/absolute.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_ABSOLUTE_INCLUDED #define ETL_ABSOLUTE_INCLUDED +#include "platform.h" #include "type_traits.h" #include "integral_limits.h" diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 462faec1..9a39b078 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -560,6 +560,7 @@ namespace etl //********************************************************************* reference operator [](size_type i) { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; } @@ -570,6 +571,7 @@ namespace etl //********************************************************************* const_reference operator [](size_type i) const { + ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(string_out_of_bounds)); return p_buffer[i]; } @@ -603,6 +605,7 @@ namespace etl //********************************************************************* reference front() { + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); return p_buffer[0]; } @@ -612,6 +615,7 @@ namespace etl //********************************************************************* const_reference front() const { + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); return p_buffer[0]; } @@ -621,7 +625,8 @@ namespace etl //********************************************************************* reference back() { - return p_buffer[current_size - 1]; + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); + return p_buffer[size() - 1]; } //********************************************************************* @@ -630,7 +635,8 @@ namespace etl //********************************************************************* const_reference back() const { - return p_buffer[current_size - 1]; + ETL_ASSERT_CHECK_EXTRA(size() > 0, ETL_ERROR(string_out_of_bounds)); + return p_buffer[size() - 1]; } //********************************************************************* @@ -764,7 +770,7 @@ namespace etl set_truncated(n > CAPACITY); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif @@ -912,7 +918,7 @@ namespace etl set_truncated(n > free_space); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif #endif @@ -932,6 +938,8 @@ namespace etl //********************************************************************* iterator insert(const_iterator position, T value) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + // Quick hack, as iterators are pointers. iterator insert_position = to_iterator(position); @@ -984,6 +992,8 @@ namespace etl //********************************************************************* iterator insert(const_iterator position, size_type n, T value) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + iterator position_ = to_iterator(position); if (n == 0) @@ -1071,6 +1081,9 @@ namespace etl template iterator insert(const_iterator position, TIterator first, TIterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT_CHECK_EXTRA(first <= last, ETL_ERROR(string_iterator)); + iterator position_ = to_iterator(position); if (first == last) @@ -1307,6 +1320,8 @@ namespace etl //********************************************************************* etl::ibasic_string& erase(size_type position, size_type length_ = npos) { + ETL_ASSERT_CHECK_EXTRA(position <= size(), ETL_ERROR(string_out_of_bounds)); + // Limit the length. length_ = etl::min(length_, size() - position); @@ -1322,6 +1337,8 @@ namespace etl //********************************************************************* iterator erase(iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds)); + etl::mem_move(i_element + 1, end(), i_element); p_buffer[--current_size] = 0; @@ -1335,6 +1352,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(string_out_of_bounds)); + iterator i_element_(to_iterator(i_element)); etl::mem_move(i_element + 1, end(), i_element_); @@ -1353,6 +1372,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator first, const_iterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(string_out_of_bounds)); + iterator first_ = to_iterator(first); iterator last_ = to_iterator(last); @@ -2753,8 +2774,10 @@ namespace etl set_truncated((count > free_space) || this->is_truncated() || truncated); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif +#else + (void)truncated; #endif #if ETL_HAS_STRING_CLEAR_AFTER_USE @@ -2762,6 +2785,8 @@ namespace etl { set_secure(); } +#else + (void)secure; #endif // Limit the actual distance to the capacity. @@ -2799,8 +2824,10 @@ namespace etl #if ETL_HAS_STRING_TRUNCATION_CHECKS set_truncated(truncated); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION - ETL_ASSERT(is_truncated == false, ETL_ERROR(string_truncation)); + ETL_ASSERT(is_truncated() == false, ETL_ERROR(string_truncation)); #endif +#else + (void)truncated; #endif #if ETL_HAS_STRING_CLEAR_AFTER_USE @@ -2808,6 +2835,8 @@ namespace etl { set_secure(); } +#else + (void)secure; #endif cleanup(); diff --git a/include/etl/callback_timer_deferred_locked.h b/include/etl/callback_timer_deferred_locked.h index ce760648..c6914d6f 100644 --- a/include/etl/callback_timer_deferred_locked.h +++ b/include/etl/callback_timer_deferred_locked.h @@ -29,6 +29,7 @@ SOFTWARE. #ifndef ETL_CALLBACK_TIMER_DEFERRED_LOCKED_INCLUDED #define ETL_CALLBACK_TIMER_DEFERRED_LOCKED_INCLUDED +#include "platform.h" #include "callback_timer_locked.h" #include "etl/nullptr.h" #include "etl/optional.h" diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 6382884a..36130a47 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -172,6 +172,19 @@ namespace etl } }; + //*************************************************************************** + /// Exception for call to receive/start/etc. while receive/start/etc. is already happening. + /// A call like that could result in an infinite loop or landing in an incorrect state. + //*************************************************************************** + class fsm_reentrant_transition_forbidden : public etl::fsm_exception + { + public: + fsm_reentrant_transition_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID"G"), file_name_, line_number_) + { + } + }; + namespace private_fsm { template @@ -209,6 +222,47 @@ namespace etl : etl::integral_constant::value> { }; + + //*************************************************************************** + /// RAII detection mechanism to catch reentrant calls to methods that might + /// transition the state machine to a different state. + /// This is not a mutex. + //*************************************************************************** + class fsm_reentrancy_guard + { + public: + //******************************************* + /// Constructor. + /// Checks if another method has locked reentrancy. + //******************************************* + fsm_reentrancy_guard(bool& transition_guard_flag) + : is_locked(transition_guard_flag) + { + ETL_ASSERT(!is_locked, ETL_ERROR(etl::fsm_reentrant_transition_forbidden)); + is_locked = true; + } + + //******************************************* + /// Destructor. + /// Releases lock on reentrancy. + //******************************************* + ~fsm_reentrancy_guard() ETL_NOEXCEPT + { + is_locked = false; + } + + private: + // Reference to the flag signifying a lock on the state machine. + bool& is_locked; + + // Copy & move semantics disabled since this is a guard. + fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE; +#if ETL_USING_CPP11 + fsm_reentrancy_guard(fsm_reentrancy_guard&&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard&&) ETL_DELETE; +#endif + }; } class ifsm_state; @@ -417,6 +471,7 @@ namespace etl , p_state(ETL_NULLPTR) , state_list(ETL_NULLPTR) , number_of_states(0U) + , is_processing_state_change(false) { } @@ -467,6 +522,8 @@ namespace etl //******************************************* virtual void start(bool call_on_enter_state = true) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. if (!is_started()) { @@ -497,6 +554,8 @@ namespace etl //******************************************* void receive(const etl::imessage& message) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { etl::fsm_state_id_t next_state_id = p_state->process_event(message); @@ -514,6 +573,8 @@ namespace etl //******************************************* etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { return process_state_change(new_state_id); @@ -576,6 +637,8 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started() && call_on_exit_state) { p_state->on_exit_state(); @@ -655,6 +718,7 @@ namespace etl etl::ifsm_state* p_state; ///< A pointer to the current state. etl::ifsm_state** state_list; ///< The list of added states. etl::fsm_state_id_t number_of_states; ///< The number of states. + bool is_processing_state_change; ///< Whether a method call that could potentially trigger a state change is active }; //************************************************************************************************* diff --git a/include/etl/gcd.h b/include/etl/gcd.h index 0926b2f0..185e5349 100644 --- a/include/etl/gcd.h +++ b/include/etl/gcd.h @@ -28,9 +28,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef ETL_GDC_INCLUDED -#define ETL_GDC_INCLUDED +#ifndef ETL_GCD_INCLUDED +#define ETL_GCD_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "static_assert.h" diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 161c413b..0887af6c 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -179,18 +179,6 @@ namespace etl } }; - //*************************************************************************** - /// Exception for forbidden state changes. - //*************************************************************************** - class fsm_state_composite_state_change_forbidden : public etl::fsm_exception - { - public: - fsm_state_composite_state_change_forbidden(string_type file_name_, numeric_type line_number_) - : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_) - { - } - }; - //*************************************************************************** /// Exception for message received but not started. //*************************************************************************** @@ -203,6 +191,19 @@ namespace etl } }; + //*************************************************************************** + /// Exception for call to receive/start/etc. while receive/start/etc. is already happening. + /// A call like that could result in an infinite loop or landing in an incorrect state. + //*************************************************************************** + class fsm_reentrant_transition_forbidden : public etl::fsm_exception + { + public: + fsm_reentrant_transition_forbidden(string_type file_name_, numeric_type line_number_) + : etl::fsm_exception(ETL_ERROR_TEXT("fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID"G"), file_name_, line_number_) + { + } + }; + namespace private_fsm { template @@ -240,6 +241,47 @@ namespace etl : etl::integral_constant::value> { }; + + //*************************************************************************** + /// RAII detection mechanism to catch reentrant calls to methods that might + /// transition the state machine to a different state. + /// This is not a mutex. + //*************************************************************************** + class fsm_reentrancy_guard + { + public: + //******************************************* + /// Constructor. + /// Checks if another method has locked reentrancy. + //******************************************* + fsm_reentrancy_guard(bool& transition_guard_flag) + : is_locked(transition_guard_flag) + { + ETL_ASSERT(!is_locked, ETL_ERROR(etl::fsm_reentrant_transition_forbidden)); + is_locked = true; + } + + //******************************************* + /// Destructor. + /// Releases lock on reentrancy. + //******************************************* + ~fsm_reentrancy_guard() ETL_NOEXCEPT + { + is_locked = false; + } + + private: + // Reference to the flag signifying a lock on the state machine. + bool& is_locked; + + // Copy & move semantics disabled since this is a guard. + fsm_reentrancy_guard(fsm_reentrancy_guard const&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE; +#if ETL_USING_CPP11 + fsm_reentrancy_guard(fsm_reentrancy_guard&&) ETL_DELETE; + fsm_reentrancy_guard& operator= (fsm_reentrancy_guard&&) ETL_DELETE; +#endif + }; } class ifsm_state; @@ -356,7 +398,6 @@ namespace etl if (p_default_child == ETL_NULLPTR) { - p_active_child = &state; p_default_child = &state; } } @@ -456,6 +497,7 @@ namespace etl , p_state(ETL_NULLPTR) , state_list(ETL_NULLPTR) , number_of_states(0U) + , is_processing_state_change(false) { } @@ -506,8 +548,10 @@ namespace etl //******************************************* virtual void start(bool call_on_enter_state = true) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. - if (p_state == ETL_NULLPTR) + if (!is_started()) { p_state = state_list[0]; ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception)); @@ -536,6 +580,8 @@ namespace etl //******************************************* void receive(const etl::imessage& message) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { etl::fsm_state_id_t next_state_id = p_state->process_event(message); @@ -553,6 +599,8 @@ namespace etl //******************************************* etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id) { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started()) { return process_state_change(new_state_id); @@ -615,7 +663,9 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) { - if ((p_state != ETL_NULLPTR) && call_on_exit_state) + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + + if (is_started() && call_on_exit_state) { p_state->on_exit_state(); } @@ -662,6 +712,12 @@ namespace etl //******************************************* virtual etl::fsm_state_id_t process_state_change(etl::fsm_state_id_t next_state_id) { + if (is_self_transition(next_state_id)) + { + p_state->on_exit_state(); + next_state_id = p_state->on_enter_state(); + } + if (have_changed_state(next_state_id)) { ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id()); @@ -681,11 +737,6 @@ namespace etl } } while (p_next_state != p_state); // Have we changed state again? } - else if (is_self_transition(next_state_id)) - { - p_state->on_exit_state(); - p_state->on_enter_state(); - } return p_state->get_state_id(); } @@ -693,6 +744,7 @@ namespace etl etl::ifsm_state* p_state; ///< A pointer to the current state. etl::ifsm_state** state_list; ///< The list of added states. etl::fsm_state_id_t number_of_states; ///< The number of states. + bool is_processing_state_change; ///< Whether a method call that could potentially trigger a state change is active }; //************************************************************************************************* diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index d47c14dc..c3a95f22 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -800,6 +800,7 @@ namespace etl //*************************************************************************** /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 namespace private_type_traits { @@ -828,11 +829,34 @@ namespace etl decltype(private_type_traits::nonvoid_convertible(0))::value) || (etl::is_void::value && etl::is_void::value)> {}; #endif + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = etl::is_convertible::value; + + template + inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible::value; #endif //*************************************************************************** @@ -1353,11 +1377,34 @@ typedef integral_constant true_type; #if ETL_USING_CPP11 template struct is_convertible : std::is_convertible {}; + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = std::is_convertible_v; + + template + inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible::value; #endif //*************************************************************************** @@ -2124,17 +2171,17 @@ typedef integral_constant true_type; /// is_constructible namespace private_type_traits { - template + template struct is_constructible_ : etl::false_type {}; - template - struct is_constructible_()...))>, T, Args...> : etl::true_type {}; + template + struct is_constructible_()...))>, T, TArgs...> : etl::true_type {}; } //********************************************* // is_constructible - template - using is_constructible = private_type_traits::is_constructible_, T, Args...>; + template + using is_constructible = private_type_traits::is_constructible_, T, TArgs...>; //********************************************* // is_copy_constructible @@ -2489,6 +2536,196 @@ typedef integral_constant true_type; template class Template> inline constexpr bool is_specialization_v = etl::is_specialization::value; #endif + + //********************************************* + // is_constant_evaluated + ETL_CONSTEXPR inline bool is_constant_evaluated() ETL_NOEXCEPT + { +#if ETL_USING_CPP23 + if consteval + { + return true; + } + else + { + return false; + } +#elif ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1 + // Fallback for C++20 on supported compilers + return __builtin_is_constant_evaluated(); +#else + // default if unsupported + return false; +#endif + } + +#if ETL_USING_CPP11 + //********************************* + /// Check if T is a function type + //********************************* + template + struct is_function : etl::false_type + { + }; + + // Plain / cv-qualified + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + + // Variadic + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported by the toolchain) +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_function_v = etl::is_function::value; +#endif +#endif + +#if ETL_USING_CPP11 + //********************************* + /// Check for the presence of operator() + //********************************* + template >::value, int> = 0> + struct has_call_operator + { + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + template + static etl::false_type test(...); + + static const bool value = etl::is_same(0)), etl::true_type>::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_call_operator_v = etl::has_call_operator::value; +#endif +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Check that there is only one operator() + //*************************************************************************** + template >::value, int> = 0> + struct has_unique_call_operator + { + //********************************* + // Test for presence of operator() + //********************************* + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + //********************************* + // Fallback + //********************************* + template + static auto test(...) -> etl::false_type; + + //********************************* + // true if operator() exists and is unique + //********************************* + static constexpr bool value = decltype(test>(0))::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_unique_call_operator_v = etl::has_unique_call_operator::value; +#endif +#endif + + //*************************************************************************** + /// Is T a member pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_pointer_helper : etl::false_type {}; + + template + struct is_member_pointer_helper : etl::true_type {}; + } + + template + struct is_member_pointer : private_type_traits::is_member_pointer_helper::type> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Is T a member function pointer + //*************************************************************************** + namespace private_type_traits + { + // Primary: not a member function pointer. + template + struct is_member_function_pointer_helper : etl::false_type + { + }; + + // If the type is 'TMember TObject::*' then TMember is the member + // Uses etl::is_function to detect member function pointers. + template + struct is_member_function_pointer_helper : etl::is_function + { + }; + } + + template + struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> + { + }; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Is T a member object pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_object_pointer_helper : public etl::false_type {}; + + template + struct is_member_object_pointer_helper : public etl::negation> {}; + } + + template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; +#endif } // Helper macros diff --git a/include/etl/hfsm.h b/include/etl/hfsm.h index c3f2062c..6db390f0 100644 --- a/include/etl/hfsm.h +++ b/include/etl/hfsm.h @@ -59,6 +59,8 @@ namespace etl //******************************************* void start(bool call_on_enter_state = true) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + // Can only be started once. if (!is_started()) { @@ -98,6 +100,8 @@ namespace etl //******************************************* virtual void reset(bool call_on_exit_state = false) ETL_OVERRIDE { + private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change); + if (is_started() && call_on_exit_state) { do_exits(ETL_NULLPTR, p_state); diff --git a/include/etl/lcm.h b/include/etl/lcm.h index 3ffc9821..bc73f566 100644 --- a/include/etl/lcm.h +++ b/include/etl/lcm.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_LCM_INCLUDED #define ETL_LCM_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "static_assert.h" diff --git a/include/etl/memory.h b/include/etl/memory.h index c2e162bd..ffe7b7ef 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -60,8 +60,8 @@ namespace etl //***************************************************************************** template ETL_CONSTEXPR T* to_address(T* p) ETL_NOEXCEPT - { - return p; + { + return p; } //***************************************************************************** @@ -837,7 +837,7 @@ namespace etl std::uninitialized_value_construct(o_begin, o_end); } -#else +#else //***************************************************************************** /// Default initialises a range of objects to uninitialised memory. /// https://en.cppreference.com/w/cpp/memory/uninitialized_value_construct @@ -1264,7 +1264,7 @@ namespace etl //********************************* template - default_delete(const default_delete&) ETL_NOEXCEPT + default_delete(const default_delete&) ETL_NOEXCEPT { } @@ -1353,8 +1353,8 @@ namespace etl #endif //********************************* - unique_ptr(pointer p_, typename etl::conditional::value, - TDeleter, + unique_ptr(pointer p_, typename etl::conditional::value, + TDeleter, typename etl::add_lvalue_reference::type>::type deleter_) ETL_NOEXCEPT : p(p_) , deleter(deleter_) @@ -1557,7 +1557,7 @@ namespace etl #endif //********************************* - unique_ptr(pointer p_, + unique_ptr(pointer p_, typename etl::conditional::value, TDeleter, typename etl::add_lvalue_reference::type>::type deleter_) ETL_NOEXCEPT @@ -1614,7 +1614,7 @@ namespace etl { pointer value = p; p = ETL_NULLPTR; - return value; + return value; } //********************************* @@ -1709,7 +1709,7 @@ namespace etl unique_ptr(const unique_ptr&) ETL_DELETE; unique_ptr& operator =(const unique_ptr&) ETL_DELETE; - pointer p; + pointer p; TDeleter deleter; }; } @@ -2324,7 +2324,7 @@ namespace etl reinterpret_cast(sb), sizeof(T) * n); #endif - + return db; } @@ -2374,7 +2374,7 @@ namespace etl reinterpret_cast(sb), sizeof(T) * n); #endif - + return db; } @@ -2438,7 +2438,7 @@ namespace etl /// \return The destination //*************************************************************************** template - typename etl::enable_if::value && + typename etl::enable_if::value && !etl::is_const::value && etl::is_integral::value && sizeof(T) == 1, TPointer>::type @@ -2447,11 +2447,11 @@ namespace etl ETL_STATIC_ASSERT(etl::is_trivially_copyable::value_type>::value, "Cannot mem_set a non trivially copyable type"); #if ETL_USING_BUILTIN_MEMSET - __builtin_memset(reinterpret_cast(db), + __builtin_memset(reinterpret_cast(db), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db)); #else - ::memset(reinterpret_cast(db), + ::memset(reinterpret_cast(db), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db)); #endif @@ -2504,13 +2504,13 @@ namespace etl mem_char(TPointer sb, TPointer se, T value) ETL_NOEXCEPT { #if ETL_USING_BUILTIN_MEMCHR - void* result = __builtin_memchr(reinterpret_cast(sb), + void* result = __builtin_memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); return (result == 0U) ? reinterpret_cast(se) : reinterpret_cast(result); #else - void* result = ::memchr(reinterpret_cast(sb), + void* result = ::memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); @@ -2527,7 +2527,7 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, const char*>::type @@ -2545,7 +2545,7 @@ namespace etl sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); return (result == 0U) ? reinterpret_cast(se) : reinterpret_cast(result); -#endif +#endif } //*************************************************************************** @@ -2557,25 +2557,25 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && !etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, char*>::type mem_char(TPointer sb, size_t n, T value) ETL_NOEXCEPT { #if ETL_USING_BUILTIN_MEMCHR - void* result = __builtin_memchr(reinterpret_cast(sb), + void* result = __builtin_memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * n); return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); #else - void* result = ::memchr(reinterpret_cast(sb), + void* result = ::memchr(reinterpret_cast(sb), static_cast(value), sizeof(typename etl::iterator_traits::value_type) * n); return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); -#endif +#endif } //*************************************************************************** @@ -2587,7 +2587,7 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && + typename etl::enable_if::value && etl::is_const::type>::value && etl::is_integral::value && sizeof(T) == 1, const char*>::type @@ -2607,7 +2607,7 @@ namespace etl return (result == 0U) ? reinterpret_cast(sb + n) : reinterpret_cast(result); #endif - + } #if ETL_USING_CPP11 @@ -2687,9 +2687,20 @@ namespace etl ETL_ASSERT(is_aligned(p), ETL_ERROR(alignment_error)); #endif - TObject& v = *reinterpret_cast(p); + return *reinterpret_cast(p); + } - return v; + //***************************************************************************** + /// Get the container at const 'p'. + //***************************************************************************** + template + const TObject& get_object_at(const void* p) + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(is_aligned(p), ETL_ERROR(alignment_error)); +#endif + + return *reinterpret_cast(p); } //***************************************************************************** diff --git a/include/etl/negative.h b/include/etl/negative.h index 4563f4f2..537a51dd 100644 --- a/include/etl/negative.h +++ b/include/etl/negative.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_NEGATIVE_INCLUDED #define ETL_NEGATIVE_INCLUDED +#include "platform.h" #include "type_traits.h" namespace etl diff --git a/include/etl/observer.h b/include/etl/observer.h index 8d46f89d..3e915a59 100644 --- a/include/etl/observer.h +++ b/include/etl/observer.h @@ -51,9 +51,8 @@ SOFTWARE. ///\ingroup patterns //***************************************************************************** -#include "algorithm.h" - #include "platform.h" +#include "algorithm.h" #include "vector.h" #include "exception.h" #include "error_handler.h" diff --git a/include/etl/optional.h b/include/etl/optional.h index 12d90239..3b565c5b 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -39,6 +39,7 @@ SOFTWARE. #include "error_handler.h" #include "utility.h" #include "placement_new.h" +#include "initializer_list.h" namespace etl { @@ -470,7 +471,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value) const& { - return has_value() ? value() : etl::forward(default_value); + return has_value() ? value() : static_cast(etl::forward(default_value)); } //*************************************************************************** @@ -481,7 +482,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value)&& { - return has_value() ? etl::move(value()) : etl::forward(default_value); + return has_value() ? etl::move(value()) : static_cast(etl::forward(default_value)); } #endif @@ -1084,7 +1085,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value) const& { - return has_value() ? value() : etl::forward(default_value); + return has_value() ? value() : static_cast(etl::forward(default_value)); } //*************************************************************************** @@ -1095,7 +1096,7 @@ namespace etl etl::enable_if_t::value, T> value_or(U&& default_value)&& { - return has_value() ? etl::move(value()) : etl::forward(default_value); + return has_value() ? etl::move(value()) : static_cast(etl::forward(default_value)); } #endif diff --git a/include/etl/private/variant_legacy.h b/include/etl/private/variant_legacy.h index c32044af..a53e3602 100644 --- a/include/etl/private/variant_legacy.h +++ b/include/etl/private/variant_legacy.h @@ -159,7 +159,7 @@ namespace etl private: // All types of variant are friends. - template + template friend class variant; //*************************************************************************** @@ -668,21 +668,21 @@ namespace etl /// For variants with differing declarations. ///\return true if the types are the same, otherwise false. //*************************************************************************** - template - bool is_same_type(const variant& other) const + template + bool is_same_type(const variant& other) const { bool is_same = false; switch (other.type_id) { - case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; - case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 0: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 1: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 2: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 3: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 4: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 5: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 6: is_same = (type_id == Type_Id_Lookup::type_id); break; + case 7: is_same = (type_id == Type_Id_Lookup::type_id); break; default: break; } diff --git a/include/etl/pseudo_moving_average.h b/include/etl/pseudo_moving_average.h index 60f27a38..4a53c0be 100644 --- a/include/etl/pseudo_moving_average.h +++ b/include/etl/pseudo_moving_average.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_CUMULATIVE_MOVING_AVERAGE_INCLUDED #define ETL_CUMULATIVE_MOVING_AVERAGE_INCLUDED +#include "platform.h" #include "type_traits.h" #include "iterator.h" diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index cdd0f16b..417b3143 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_ROUNDED_INTEGRAL_DIVISION_INCLUDED #define ETL_ROUNDED_INTEGRAL_DIVISION_INCLUDED +#include "platform.h" #include "type_traits.h" #include "absolute.h" #include "utility.h" diff --git a/include/etl/scaled_rounding.h b/include/etl/scaled_rounding.h index 595f8ea6..be6a44f6 100644 --- a/include/etl/scaled_rounding.h +++ b/include/etl/scaled_rounding.h @@ -31,6 +31,7 @@ SOFTWARE. #ifndef ETL_SCALED_ROUNDING_INCLUDED #define ETL_SCALED_ROUNDING_INCLUDED +#include "platform.h" #include "static_assert.h" #include "type_traits.h" #include "absolute.h" diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 3c9ac66b..bf285583 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -788,6 +788,7 @@ namespace etl //*************************************************************************** /// is_convertible + ///\ingroup type_traits #if ETL_USING_CPP11 namespace private_type_traits { @@ -816,11 +817,34 @@ namespace etl decltype(private_type_traits::nonvoid_convertible(0))::value) || (etl::is_void::value && etl::is_void::value)> {}; #endif + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = etl::is_convertible::value; + + template + inline constexpr bool is_nothrow_convertible_v = etl::is_nothrow_convertible::value; #endif //*************************************************************************** @@ -1341,11 +1365,34 @@ typedef integral_constant true_type; #if ETL_USING_CPP11 template struct is_convertible : std::is_convertible {}; + + // Is convertible and the conversion is noexcept. + template + struct is_nothrow_convertible + { + private: + // Helper: a function taking TTo to require the conversion. + static void sink(TTo) noexcept; + + // Selected only if 'sink(declval())' is a valid expression. + template + static auto test(int) -> etl::bool_constant()))>; + + // Fallback if conversion is not viable. + template + static etl::false_type test(...); + + public: + static ETL_CONSTANT bool value = decltype(test(0))::value; + }; #endif #if ETL_USING_CPP17 template inline constexpr bool is_convertible_v = std::is_convertible_v; + + template + inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible::value; #endif //*************************************************************************** @@ -2117,17 +2164,17 @@ typedef integral_constant true_type; /// is_constructible namespace private_type_traits { - template + template struct is_constructible_ : etl::false_type {}; - template - struct is_constructible_()...))>, T, Args...> : etl::true_type {}; + template + struct is_constructible_()...))>, T, TArgs...> : etl::true_type {}; } //********************************************* // is_constructible - template - using is_constructible = private_type_traits::is_constructible_, T, Args...>; + template + using is_constructible = private_type_traits::is_constructible_, T, TArgs...>; //********************************************* // is_copy_constructible @@ -2497,13 +2544,181 @@ typedef integral_constant true_type; return false; } #elif ETL_USING_BUILTIN_IS_CONSTANT_EVALUATED == 1 - // fallback for C++20 on supported compilers + // Fallback for C++20 on supported compilers return __builtin_is_constant_evaluated(); #else // default if unsupported return false; #endif } + +#if ETL_USING_CPP11 + //********************************* + /// Check if T is a function type + //********************************* + template + struct is_function : etl::false_type + { + }; + + // Plain / cv-qualified + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + + // Variadic + template + struct is_function : etl::true_type {}; + + // noexcept variants (if supported by the toolchain) +#if ETL_HAS_NOEXCEPT_FUNCTION_TYPE + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; + template + struct is_function : etl::true_type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_function_v = etl::is_function::value; +#endif +#endif + +#if ETL_USING_CPP11 + //********************************* + /// Check for the presence of operator() + //********************************* + template >::value, int> = 0> + struct has_call_operator + { + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + template + static etl::false_type test(...); + + static const bool value = etl::is_same(0)), etl::true_type>::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_call_operator_v = etl::has_call_operator::value; +#endif +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Check that there is only one operator() + //*************************************************************************** + template >::value, int> = 0> + struct has_unique_call_operator + { + //********************************* + // Test for presence of operator() + //********************************* + template + static auto test(int) -> decltype(&U::operator(), etl::true_type()); + + //********************************* + // Fallback + //********************************* + template + static auto test(...) -> etl::false_type; + + //********************************* + // true if operator() exists and is unique + //********************************* + static constexpr bool value = decltype(test>(0))::value; + }; + +#if ETL_USING_CPP17 + template + inline constexpr bool has_unique_call_operator_v = etl::has_unique_call_operator::value; +#endif +#endif + + //*************************************************************************** + /// Is T a member pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_pointer_helper : etl::false_type {}; + + template + struct is_member_pointer_helper : etl::true_type {}; + } + + template + struct is_member_pointer : private_type_traits::is_member_pointer_helper::type> {}; + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_pointer_v = etl::is_member_pointer::value; +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Is T a member function pointer + //*************************************************************************** + namespace private_type_traits + { + // Primary: not a member function pointer. + template + struct is_member_function_pointer_helper : etl::false_type + { + }; + + // If the type is 'TMember TObject::*' then TMember is the member + // Uses etl::is_function to detect member function pointers. + template + struct is_member_function_pointer_helper : etl::is_function + { + }; + } + + template + struct is_member_function_pointer : private_type_traits::is_member_function_pointer_helper> + { + }; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_function_pointer_v = etl::is_member_function_pointer::value; +#endif + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Is T a member object pointer + //*************************************************************************** + namespace private_type_traits + { + template + struct is_member_object_pointer_helper : public etl::false_type {}; + + template + struct is_member_object_pointer_helper : public etl::negation> {}; + } + + template struct is_member_object_pointer : public private_type_traits::is_member_object_pointer_helper>::type {}; +#endif + +#if ETL_USING_CPP17 + template + inline constexpr bool is_member_object_pointer_v = etl::is_member_object_pointer::value; +#endif } // Helper macros diff --git a/include/etl/version.h b/include/etl/version.h index 11790058..3309a7df 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -40,7 +40,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 20 #define ETL_VERSION_MINOR 44 -#define ETL_VERSION_PATCH 1 +#define ETL_VERSION_PATCH 2 #define ETL_VERSION ETL_STRING(ETL_VERSION_MAJOR) "." ETL_STRING(ETL_VERSION_MINOR) "." ETL_STRING(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_WIDE_STRING(ETL_VERSION_MAJOR) L"." ETL_WIDE_STRING(ETL_VERSION_MINOR) L"." ETL_WIDE_STRING(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 62519726..887a37f3 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "20.44.1", + "version": "20.44.2", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index f6e7bcd5..59a1888c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=20.44.1 +version=20.44.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 41731895..94f74931 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,4 +1,26 @@ =============================================================================== +20.44.2 + +Updates: +Replaced locally defined logical_not_t with etl::negation + +Fixes: +#1228 unused parameter 'secure' +#1224 Passing a const in optional::value_or() not compiling + +Pull Requests: +#1210 Fixed span reinterpret_as should return fixed span +#1211 Change generators to reflect changes in fsm.h and type_traits.h +#1217 Add const specialization for etl::get_object_at +#1218 Cleanup platform.h includes, add missing test for unaligned_type +#1221 Add test for swap +#1222 Basic string checks +#1223 Fix is_truncated in basic_string +#1225 Fix value_or not taking const in optional +#1226 Add missing include to optional +#1229 variant_legacy.h: Rename template parameters + +=============================================================================== 20.44.1 Updates: diff --git a/test/test_hfsm_transition_on_enter.cpp b/test/test_hfsm_transition_on_enter.cpp index ff994c10..a83c3d1a 100644 --- a/test/test_hfsm_transition_on_enter.cpp +++ b/test/test_hfsm_transition_on_enter.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/hfsm.h" #include "etl/string.h" #include +#include // entry && mode=RxEventDeviation // ┌─────────────────────────────────────────────────────┐ @@ -358,6 +359,25 @@ namespace sm.reset(true); CHECK_EQUAL("X1X2X3", sm.test_data.c_str()); } + + //************************************************************************* + TEST(reentrant_receives) + { + EntryTestSM sm; + sm.start(false); + sm.receive(ToS5Event{}); + sm.test_data.clear(); + sm.runMode = EntryTestSM::RxEventDuringTransition; + CHECK_THROW(sm.receive(ToS6Event{}),etl::fsm_reentrant_transition_forbidden); + } + + //************************************************************************* + TEST(reentrant_receives_on_start) + { + EntryTestSM sm; + sm.runMode = EntryTestSM::RxEventDuringTransition; + CHECK_THROW(sm.start(true),etl::fsm_reentrant_transition_forbidden); + } } } // namespace diff --git a/test/test_make_string.cpp b/test/test_make_string.cpp index 69468593..f24b95d9 100644 --- a/test/test_make_string.cpp +++ b/test/test_make_string.cpp @@ -141,7 +141,6 @@ namespace TEST_FIXTURE(SetupFixture, test_make_string_with_capacity_truncated) { constexpr size_t CAPACITY = 10UL; - size_t length = strlen("Hello World"); #if ETL_HAS_ERROR_ON_STRING_TRUNCATION CHECK_THROW(auto ctext = etl::make_string_with_capacity("Hello World"), etl::string_truncation); @@ -149,6 +148,8 @@ namespace CHECK_THROW(auto u16text = etl::make_string_with_capacity(u"Hello World"), etl::string_truncation);; CHECK_THROW(auto u32text = etl::make_string_with_capacity(U"Hello World"), etl::string_truncation);; #else + size_t length = strlen("Hello World"); + auto ctext = etl::make_string_with_capacity("Hello World"); auto wtext = etl::make_string_with_capacity(L"Hello World"); auto u16text = etl::make_string_with_capacity(u"Hello World"); diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 4b70f3fe..1b88c8a5 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -1256,7 +1256,7 @@ namespace uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 }; const uint32_t* data_begin = &data[0]; - + uint32_t* result = etl::mem_move(data_begin, 8, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); CHECK(result == data + 4); @@ -1269,7 +1269,7 @@ namespace uint32_t same[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t grtr[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67235501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t less[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67134501, 0x45016723, 0x01324576, 0x76453201 }; - + CHECK(etl::mem_compare(data, data + 8, same) == 0); CHECK(etl::mem_compare(data, data + 8, grtr) > 0); CHECK(etl::mem_compare(data, data + 8, less) < 0); @@ -1443,7 +1443,7 @@ namespace } //************************************************************************* - class Base + class Base { public: virtual ~Base() {}; @@ -1452,21 +1452,21 @@ namespace static bool function_was_called = false; - class Derived : public Base + class Derived : public Base { public: - Derived() + Derived() { function_was_called = false; } - void function() + void function() { function_was_called = true; } }; - void call(etl::unique_ptr ptr) + void call(etl::unique_ptr ptr) { ptr->function(); } @@ -1477,13 +1477,13 @@ namespace etl::unique_ptr ptr(new Derived()); CHECK(ptr.get() != ETL_NULLPTR); - + call(etl::move(ptr)); CHECK(function_was_called); CHECK(ptr.get() == ETL_NULLPTR); } - + struct Flags { Flags() @@ -1530,7 +1530,7 @@ namespace int a; int b; }; - + alignas(Data) char buffer1[sizeof(Data)]; char* pbuffer1 = buffer1; @@ -1581,14 +1581,14 @@ namespace CHECK_FALSE(flags.destructed); CHECK_EQUAL(1, rdata1b.a); CHECK_EQUAL(2, rdata1b.b); - + flags.Clear(); Data& rdata2b = etl::get_object_at(pbuffer2b); CHECK_FALSE(flags.constructed); CHECK_FALSE(flags.destructed); CHECK_EQUAL(data2.a, rdata2b.a); CHECK_EQUAL(data2.b, rdata2b.b); - + flags.Clear(); Data& rdata3b = etl::get_object_at(pbuffer3b); CHECK_FALSE(flags.constructed); @@ -1612,6 +1612,33 @@ namespace CHECK_TRUE(flags.destructed); } + TEST(test_get_object_at_const_specialization) + { + struct Data + { + Data() + : a(1) + , b(2) + { + flags.constructed = true; + } + + ~Data() = default; + + int a; + int b; + }; + + std::array buffer{}; + etl::construct_object_at(buffer.data(), Data()); + const void* bufferPointer = buffer.data(); + + const Data& rdata = etl::get_object_at(bufferPointer); + CHECK_TRUE(flags.constructed); + CHECK_TRUE(rdata.a == 1); + CHECK_TRUE(rdata.b == 2); + } + TEST(test_construct_get_destroy_object_misaligned) { struct Data diff --git a/test/test_optional.cpp b/test/test_optional.cpp index c5a34d08..42ab7199 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -298,6 +298,21 @@ namespace CHECK_EQUAL(Data("Value"), result); } + //************************************************************************* + TEST(test_value_or_const) + { + using FundamentalType = int; + using NonFundamentalType = std::string; + + const FundamentalType constFT{ 5 }; + int resultFT = etl::optional{}.value_or(constFT); + CHECK_EQUAL(5, resultFT); + + const NonFundamentalType constNFT{ "Default" }; + NonFundamentalType resultNFT = etl::optional{}.value_or(constNFT); + CHECK_EQUAL("Default", resultNFT); + } + //************************************************************************* struct github_bug_720_bug_helper { diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 7ee55e32..6cf70b28 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -614,8 +614,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -910,6 +910,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -924,6 +926,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -964,6 +968,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -974,6 +981,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -984,6 +994,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -994,6 +1007,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1327,6 +1343,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1402,6 +1432,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1501,6 +1546,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3266,6 +3335,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3283,6 +3369,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5043,7 +5138,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5305,7 +5400,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5323,7 +5418,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_char_external_buffer.cpp b/test/test_string_char_external_buffer.cpp index 7346042b..e644f578 100644 --- a/test/test_string_char_external_buffer.cpp +++ b/test/test_string_char_external_buffer.cpp @@ -767,8 +767,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1069,6 +1069,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1085,6 +1087,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1133,6 +1137,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1145,6 +1153,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1157,6 +1169,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1169,6 +1185,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1531,6 +1551,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1608,6 +1644,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1709,6 +1762,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3442,6 +3522,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3459,6 +3558,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5302,7 +5412,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5589,7 +5699,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5609,7 +5719,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 6662a82c..a569d269 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -658,8 +658,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -954,6 +954,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -968,6 +970,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1008,6 +1012,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1018,6 +1025,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1028,6 +1038,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1038,6 +1051,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1399,6 +1415,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1474,6 +1504,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1573,6 +1618,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3338,6 +3407,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3355,6 +3441,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5115,7 +5210,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5377,7 +5472,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5395,7 +5490,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u16_external_buffer.cpp b/test/test_string_u16_external_buffer.cpp index a7a3279c..41e60750 100644 --- a/test/test_string_u16_external_buffer.cpp +++ b/test/test_string_u16_external_buffer.cpp @@ -836,8 +836,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1138,6 +1138,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1154,6 +1156,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1202,6 +1206,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1214,6 +1222,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1226,6 +1238,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1238,6 +1254,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1632,6 +1652,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1709,6 +1745,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1810,6 +1863,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3542,6 +3622,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3559,6 +3658,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5402,7 +5512,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5689,7 +5799,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5709,7 +5819,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index 7b6be11d..5201371e 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -658,8 +658,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -954,6 +954,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -968,6 +970,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1008,6 +1012,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1018,6 +1025,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1028,6 +1038,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1038,6 +1051,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1399,6 +1415,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1474,6 +1504,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1573,6 +1618,30 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3338,6 +3407,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3355,6 +3441,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5115,7 +5210,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5377,7 +5472,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5395,7 +5490,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u32_external_buffer.cpp b/test/test_string_u32_external_buffer.cpp index fb7d2104..f02a460d 100644 --- a/test/test_string_u32_external_buffer.cpp +++ b/test/test_string_u32_external_buffer.cpp @@ -836,8 +836,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1138,6 +1138,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1154,6 +1156,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1202,6 +1206,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1214,6 +1222,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1226,6 +1238,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1238,6 +1254,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1632,6 +1652,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1709,6 +1745,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1810,6 +1863,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3542,6 +3622,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3559,6 +3658,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5402,7 +5512,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5689,7 +5799,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5709,7 +5819,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u8.cpp b/test/test_string_u8.cpp index b01a67f2..65eeb767 100644 --- a/test/test_string_u8.cpp +++ b/test/test_string_u8.cpp @@ -631,8 +631,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -927,6 +927,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -941,6 +943,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -981,6 +985,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -991,6 +998,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1001,6 +1011,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1011,6 +1024,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1344,6 +1360,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1419,6 +1449,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1512,12 +1557,36 @@ namespace compare_text.insert(compare_text.cbegin() + offset, insert_text.cbegin(), insert_text.cend()); CHECK_FALSE(text.is_truncated()); -# + bool is_equal = Equal(compare_text, text); CHECK(is_equal); } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3283,6 +3352,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3300,6 +3386,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5060,7 +5155,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5322,7 +5417,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5340,7 +5435,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_u8_external_buffer.cpp b/test/test_string_u8_external_buffer.cpp index fe79d570..6f4befa5 100644 --- a/test/test_string_u8_external_buffer.cpp +++ b/test/test_string_u8_external_buffer.cpp @@ -784,8 +784,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1086,6 +1086,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1102,6 +1104,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1150,6 +1154,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1162,6 +1170,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1174,6 +1186,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1186,6 +1202,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1548,6 +1568,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1625,6 +1661,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1726,6 +1779,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3458,6 +3538,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3475,6 +3574,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5321,7 +5431,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5608,7 +5718,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5628,7 +5738,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index b269b70c..4ac88729 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -659,8 +659,8 @@ namespace Text text(initial_text.c_str()); const Text constText(initial_text.c_str()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -955,6 +955,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -969,6 +971,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1009,6 +1013,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1019,6 +1026,9 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1029,6 +1039,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1039,6 +1052,9 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + const Text emptyText; + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1400,6 +1416,20 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1475,6 +1505,21 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1568,12 +1613,36 @@ namespace compare_text.insert(compare_text.cbegin() + offset, insert_text.cbegin(), insert_text.cend()); CHECK_FALSE(text.is_truncated()); -# + bool is_equal = Equal(compare_text, text); CHECK(is_equal); } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + Text text2; + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + Text text; + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3339,6 +3408,23 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + Text text(initial_text.c_str()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3356,6 +3442,15 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + Text text(initial_text.c_str()); + Text text2(initial_text.c_str()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5116,7 +5211,7 @@ namespace // Test with actual string type. Text text(STR("ABCDEFHIJKL")); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5378,7 +5473,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5396,7 +5491,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_string_wchar_t_external_buffer.cpp b/test/test_string_wchar_t_external_buffer.cpp index 2926beb2..6b1b5e08 100644 --- a/test/test_string_wchar_t_external_buffer.cpp +++ b/test/test_string_wchar_t_external_buffer.cpp @@ -839,8 +839,8 @@ namespace TextBuffer buffer2{0}; const Text constText(initial_text.c_str(), buffer2.data(), buffer2.size()); - CHECK_EQUAL(&text[initial_text.size()], text.end()); - CHECK_EQUAL(&constText[initial_text.size()], constText.end()); + CHECK_EQUAL(text.begin() + text.size(), text.end()); + CHECK_EQUAL(constText.begin() + constText.size(), constText.end()); } //************************************************************************* @@ -1141,6 +1141,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1157,6 +1159,8 @@ namespace } CHECK_FALSE(text.is_truncated()); + + CHECK_THROW(text[text.size()], etl::string_out_of_bounds); } //************************************************************************* @@ -1205,6 +1209,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1217,6 +1225,10 @@ namespace CHECK(text.front() == compare_text.front()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.front(), etl::string_out_of_bounds); } //************************************************************************* @@ -1229,6 +1241,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1241,6 +1257,10 @@ namespace CHECK(text.back() == compare_text.back()); CHECK_FALSE(text.is_truncated()); + + TextBuffer buffer2{0}; + const Text emptyText(buffer2.data(), buffer2.size()); + CHECK_THROW(emptyText.back(), etl::string_out_of_bounds); } //************************************************************************* @@ -1635,6 +1655,22 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1712,6 +1748,23 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const size_t INSERT_SIZE = 3UL; + const value_t INITIAL_VALUE = STR('A'); + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), INSERT_SIZE, INITIAL_VALUE), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1813,6 +1866,33 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + TextBuffer buffer2{0}; + Text text2(buffer2.data(), buffer2.size()); + + CHECK_THROW(text.insert(text2.cbegin(), insert_text.cbegin(), insert_text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_swapped_iterators) + { + const size_t INITIAL_SIZE = 5UL; + + TextBuffer buffer{0}; + Text text(buffer.data(), buffer.size()); + text.assign(initial_text.begin(), initial_text.begin() + INITIAL_SIZE); + + CHECK_THROW(text.insert(text.cbegin(), insert_text.cend(), insert_text.cbegin()), etl::string_iterator); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -3545,6 +3625,25 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.end()), etl::string_out_of_bounds); + CHECK_THROW(text.erase(text.cend()), etl::string_out_of_bounds); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_position_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + CHECK_THROW(text.erase(text.size() + 1), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -3562,6 +3661,17 @@ namespace CHECK_FALSE(text.is_truncated()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + TextBuffer buffer{0}; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + TextBuffer buffer2{0}; + Text text2(initial_text.c_str(), buffer2.data(), buffer2.size()); + + CHECK_THROW(text.erase(text2.begin(), text2.end()), etl::string_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { @@ -5405,7 +5515,7 @@ namespace TextBuffer buffer{0}; Text text(STR("ABCDEFHIJKL"), buffer.data(), buffer.size()); size_t hash = etl::hash()(text); - size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(&text[0]), reinterpret_cast(&text[text.size()])); + size_t compare_hash = etl::private_hash::generic_hash(reinterpret_cast(text.data()), reinterpret_cast(text.data_end())); CHECK_EQUAL(compare_hash, hash); // Test with interface string type. @@ -5692,7 +5802,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } @@ -5712,7 +5822,7 @@ namespace for (size_t i = text.size(); i < text.max_size(); ++i) { - CHECK_EQUAL(0, text[i]); + CHECK_EQUAL(0, text.data()[i]); } } diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index e80eeaeb..96827cba 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -1008,6 +1008,9 @@ namespace CHECK_EQUAL(0x1234, test_le.value()); CHECK_EQUAL(0x1234, test_be.value()); + + CHECK_EQUAL(0x1234, test_le); + CHECK_EQUAL(0x1234, test_be); } //************************************************************************* diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 0a9559e6..60c5163c 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -788,6 +788,43 @@ namespace CHECK_EQUAL(9U, sizeof(packed)); } #endif + + //********************************* + TEST(test_swap) + { + uint32_t a = 0x12345678; + uint32_t b = 0x87654321; + + ETL_OR_STD::swap(a, b); + + CHECK_EQUAL(a, 0x87654321); + CHECK_EQUAL(b, 0x12345678); + + uint32_t* p_a = &a; + uint32_t* p_b = &b; + + ETL_OR_STD::swap(p_a, p_b); + + CHECK_EQUAL(a, 0x87654321); + CHECK_EQUAL(b, 0x12345678); + CHECK_EQUAL(p_a, &b); + CHECK_EQUAL(p_b, &a); + + uint32_t a_a[4] {0x12345678, 0x23456789, 0x34567890, 0x09876543}; + uint32_t a_b[4] {0x12abcd78, 0x23abcd89, 0x34abcd90, 0x09abcd43}; + + ETL_OR_STD::swap(a_a, a_b); + + CHECK_EQUAL(a_a[0], 0x12abcd78); + CHECK_EQUAL(a_a[1], 0x23abcd89); + CHECK_EQUAL(a_a[2], 0x34abcd90); + CHECK_EQUAL(a_a[3], 0x09abcd43); + + CHECK_EQUAL(a_b[0], 0x12345678); + CHECK_EQUAL(a_b[1], 0x23456789); + CHECK_EQUAL(a_b[2], 0x34567890); + CHECK_EQUAL(a_b[3], 0x09876543); + } }; #if ETL_USING_CPP17 && !defined(ETL_FORCE_CPP11_NONTYPE) diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index d2b13bec..095d407d 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1003,87 +1003,104 @@ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ false @@ -1129,7 +1146,8 @@ true true - $(Configuration)\ + Build\$(Configuration)\ + $(SolutionDir)Build\$(Configuration)\ false diff --git a/version.txt b/version.txt index 66252a79..3e132281 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.44.1 +20.44.2