mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Fix vector insert of a value that refers to an element of the vector
insert(position, value) and insert(position, n, value) shifted the elements before reading value, so a value taken from the vector at or after the insert position read the shifted element instead. Fixes #1629
This commit is contained in:
parent
ea54954c54
commit
442c6baac9
@ -611,9 +611,18 @@ namespace etl
|
||||
}
|
||||
else
|
||||
{
|
||||
// value may refer to an element that is about to be shifted.
|
||||
const_pointer p_value = etl::addressof(value);
|
||||
|
||||
create_back(back());
|
||||
etl::move_backward(position_, p_end - 2, p_end - 1);
|
||||
*position_ = value;
|
||||
|
||||
if ((p_value >= position_) && (p_value < p_end))
|
||||
{
|
||||
++p_value;
|
||||
}
|
||||
|
||||
*position_ = *p_value;
|
||||
}
|
||||
|
||||
return position_;
|
||||
@ -836,6 +845,14 @@ namespace etl
|
||||
size_t copy_new_n = construct_old_n;
|
||||
size_t construct_new_n = insert_n - copy_new_n;
|
||||
|
||||
// value may refer to an element that is about to be shifted.
|
||||
const_pointer p_value = etl::addressof(value);
|
||||
|
||||
if ((p_value >= position_) && (p_value < p_end))
|
||||
{
|
||||
p_value += n;
|
||||
}
|
||||
|
||||
// Construct old.
|
||||
etl::uninitialized_move(p_end - construct_old_n, p_end, p_construct_old);
|
||||
ETL_ADD_DEBUG_COUNT(construct_old_n);
|
||||
@ -844,11 +861,11 @@ namespace etl
|
||||
etl::move_backward(p_buffer + insert_begin, p_buffer + insert_begin + copy_old_n, p_buffer + insert_end + copy_old_n);
|
||||
|
||||
// Construct new.
|
||||
etl::uninitialized_fill_n(p_end, construct_new_n, value);
|
||||
etl::uninitialized_fill_n(p_end, construct_new_n, *p_value);
|
||||
ETL_ADD_DEBUG_COUNT(construct_new_n);
|
||||
|
||||
// Copy new.
|
||||
etl::fill_n(p_buffer + insert_begin, copy_new_n, value);
|
||||
etl::fill_n(p_buffer + insert_begin, copy_new_n, *p_value);
|
||||
|
||||
p_end += n;
|
||||
}
|
||||
|
||||
@ -777,6 +777,33 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_position_value_from_self)
|
||||
{
|
||||
const size_t INITIAL_SIZE = 5;
|
||||
|
||||
for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset)
|
||||
{
|
||||
for (size_t source = 0; source < INITIAL_SIZE; ++source)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
|
||||
compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
|
||||
|
||||
data.insert(data.cbegin() + offset, data[source]);
|
||||
compare_data.insert(compare_data.cbegin() + static_cast<ptrdiff_t>(offset), compare_data[source]);
|
||||
|
||||
CHECK_EQUAL(compare_data.size(), data.size());
|
||||
|
||||
bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin());
|
||||
|
||||
CHECK(is_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds)
|
||||
{
|
||||
@ -971,6 +998,36 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_position_n_value_from_self)
|
||||
{
|
||||
const size_t INITIAL_SIZE = 5;
|
||||
|
||||
for (size_t insert_size = 1; insert_size <= 4; ++insert_size)
|
||||
{
|
||||
for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset)
|
||||
{
|
||||
for (size_t source = 0; source < INITIAL_SIZE; ++source)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
|
||||
compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
|
||||
|
||||
data.insert(data.cbegin() + offset, insert_size, data[source]);
|
||||
compare_data.insert(compare_data.cbegin() + static_cast<ptrdiff_t>(offset), insert_size, compare_data[source]);
|
||||
|
||||
CHECK_EQUAL(compare_data.size(), data.size());
|
||||
|
||||
bool is_equal = std::equal(data.cbegin(), data.cend(), compare_data.cbegin());
|
||||
|
||||
CHECK(is_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#include "etl/private/diagnostic_uninitialized_push.h"
|
||||
TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user