diff --git a/include/etl/indirect_vector.h b/include/etl/indirect_vector.h index 36d6c695..c0d41438 100644 --- a/include/etl/indirect_vector.h +++ b/include/etl/indirect_vector.h @@ -292,6 +292,11 @@ namespace etl return lhs.lookup_itr < rhs.lookup_itr; } + friend bool operator <= (const iterator& lhs, const iterator& rhs) + { + return lhs.lookup_itr <= rhs.lookup_itr; + } + private: iterator(indirect_iterator itr_) @@ -424,6 +429,11 @@ namespace etl return lhs.lookup_itr < rhs.lookup_itr; } + friend bool operator <= (const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.lookup_itr <= rhs.lookup_itr; + } + private: typedef typename etl::ivector::const_iterator lookup_itr_t; @@ -757,7 +767,7 @@ namespace etl //********************************************************************* void push_back(const_reference value) { - ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(vector_full)); T* p = storage.create(value); lookup.push_back(p); @@ -771,7 +781,7 @@ namespace etl //********************************************************************* void push_back(rvalue_reference value) { - ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(vector_full)); T* p = storage.create(etl::move(value)); lookup.push_back(p); @@ -787,6 +797,8 @@ namespace etl template reference emplace_back(Args && ... args) { + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + T* p = storage.create(etl::forward(args)...); lookup.push_back(p); return back(); @@ -799,7 +811,9 @@ namespace etl //********************************************************************* reference emplace_back() { - T* p = storage.create(T()); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(); lookup.push_back(p); return back(); } @@ -812,7 +826,9 @@ namespace etl template reference emplace_back(const T1& value1) { - T* p = storage.create(T(value1)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1); lookup.push_back(p); return back(); } @@ -825,7 +841,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2) { - T* p = storage.create(T(value1, value2)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2); lookup.push_back(p); return back(); } @@ -838,7 +856,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2, const T3& value3) { - T* p = storage.create(T(value1, value2, value3)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2, value3); lookup.push_back(p); return back(); } @@ -851,7 +871,9 @@ namespace etl template reference emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4) { - T* p = storage.create(T(value1, value2, value3, value4)); + ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(vector_full)); + + T* p = storage.create(value1, value2, value3, value4); lookup.push_back(p); return back(); } @@ -862,7 +884,7 @@ namespace etl //************************************************************************* void pop_back() { - ETL_ASSERT(!empty(), ETL_ERROR(vector_empty)); + ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(vector_empty)); reference object = back(); storage.destroy(etl::addressof(object)); @@ -878,8 +900,9 @@ namespace etl iterator insert(const_iterator position, const_reference value) { ETL_ASSERT(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value)); + T* p = storage.create(value); position = iterator(lookup.insert(position.lookup_itr, p)); return to_iterator(position); @@ -895,8 +918,9 @@ namespace etl iterator insert(const_iterator position, rvalue_reference value) { ETL_ASSERT(size() != capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(etl::move(value))); + T* p = storage.create(etl::move(value)); position = iterator(lookup.insert(position.lookup_itr, p)); return to_iterator(position); @@ -908,68 +932,74 @@ namespace etl //************************************************************************* #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_VECTOR_FORCE_CPP03_IMPLEMENTATION) template - iterator emplace(iterator position, Args && ... args) + iterator emplace(const_iterator position, Args && ... args) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(etl::forward(args)...)); + T* p = storage.create(etl::forward(args)...); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } #else - iterator emplace(iterator position) + iterator emplace(const_iterator position) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T()); + T* p = storage.create(); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1) + iterator emplace(const_iterator position, const T1& value1) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1)); + T* p = storage.create(value1); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2) + iterator emplace(const_iterator position, const T1& value1, const T2& value2) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2)); + T* p = storage.create(value1, value2); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3) + iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2, value3)); + T* p = storage.create(value1, value2, value3); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } template - iterator emplace(iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) + iterator emplace(const_iterator position, const T1& value1, const T2& value2, const T3& value3, const T4& value4) { ETL_ASSERT(!full(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); - T* p = storage.create(T(value1, value2, value3, value4)); + T* p = storage.create(value1, value2, value3, value4); position = iterator(lookup.insert(position.lookup_itr, p)); - return position; + return to_iterator(position); } #endif @@ -983,6 +1013,7 @@ namespace etl iterator insert(const_iterator position, size_t n, parameter_t value) { ETL_ASSERT((size() + n) <= capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); iterator position_ = to_iterator(position); @@ -1012,6 +1043,7 @@ namespace etl size_t count = size_t(etl::distance(first, last)); ETL_ASSERT((size() + count) <= capacity(), ETL_ERROR(vector_full)); + ETL_ASSERT_CHECK_EXTRA(cbegin() <= position && position <= cend(), ETL_ERROR(vector_out_of_bounds)); // Make space for the new lookup pointers. typename etl::ivector::iterator lookup_itr = to_iterator(position).lookup_itr; @@ -1034,6 +1066,8 @@ namespace etl //********************************************************************* iterator erase(iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(vector_out_of_bounds)); + storage.destroy(etl::addressof(*i_element)); return iterator(lookup.erase(i_element.lookup_itr)); @@ -1046,6 +1080,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator i_element) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= i_element && i_element < cend(), ETL_ERROR(vector_out_of_bounds)); + storage.destroy(etl::addressof(*i_element)); return iterator(lookup.erase(i_element.lookup_itr)); @@ -1061,6 +1097,8 @@ namespace etl //********************************************************************* iterator erase(const_iterator first, const_iterator last) { + ETL_ASSERT_CHECK_EXTRA(cbegin() <= first && first <= last && last <= cend(), ETL_ERROR(vector_out_of_bounds)); + iterator element = to_iterator(first); while (element != last) diff --git a/test/test_indirect_vector.cpp b/test/test_indirect_vector.cpp index cd639a6b..26b61ac8 100644 --- a/test/test_indirect_vector.cpp +++ b/test/test_indirect_vector.cpp @@ -536,6 +536,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -549,6 +551,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -586,6 +590,9 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.front() == compare_data.front()); + + DataNDC emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -595,6 +602,9 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.front() == compare_data.front()); + + const DataNDC emptyData; + CHECK_THROW(emptyData.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -604,6 +614,9 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.back() == compare_data.back()); + + DataNDC emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -613,6 +626,9 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end()); CHECK(data.back() == compare_data.back()); + + const DataNDC emptyData; + CHECK_THROW(emptyData.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -759,6 +775,21 @@ namespace CHECK_EQUAL(back, data.back()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_excess) + { + DataNDC data; + + for (size_t i = 0UL; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + data.emplace_back(value); + } + + CHECK_THROW(data.emplace_back("Z"), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr) { @@ -996,6 +1027,18 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_position_default_value) { @@ -1048,6 +1091,18 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5; + const std::string INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.emplace(data2.begin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1097,6 +1152,17 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + DataNDC data; + DataNDC data2; + + CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1151,6 +1217,15 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + DataNDC data; + DataNDC data2; + + CHECK_THROW(data.insert(data2.end(), insert_data.begin(), insert_data.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -1195,6 +1270,15 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.cend()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -1214,6 +1298,15 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + DataNDC data(initial_data.begin(), initial_data.end()); + DataNDC data2(initial_data.begin(), initial_data.end()); + + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { diff --git a/test/test_indirect_vector_external_buffer.cpp b/test/test_indirect_vector_external_buffer.cpp index 4ce54e75..3f94bc71 100644 --- a/test/test_indirect_vector_external_buffer.cpp +++ b/test/test_indirect_vector_external_buffer.cpp @@ -646,6 +646,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -662,6 +664,8 @@ namespace { CHECK_EQUAL(data[i], compare_data[i]); } + + CHECK_THROW(data[data.size()], etl::vector_out_of_bounds); } //************************************************************************* @@ -708,6 +712,12 @@ namespace DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.front() == compare_data.front()); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -720,6 +730,12 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.front() == compare_data.front()); + + LookupNDC lookup2; + PoolNDC pool2; + + const DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.front(), etl::vector_out_of_bounds); } //************************************************************************* @@ -732,6 +748,12 @@ namespace DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.back() == compare_data.back()); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -744,6 +766,12 @@ namespace const DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); CHECK(data.back() == compare_data.back()); + + LookupNDC lookup2; + PoolNDC pool2; + + const DataNDC data2(lookup2, pool2); + CHECK_THROW(data2.back(), etl::vector_out_of_bounds); } //************************************************************************* @@ -875,6 +903,24 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_back_excess) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + for (size_t i = 0UL; i < SIZE; ++i) + { + std::string value(" "); + value[0] = char('A' + i); + data.emplace_back(value); + } + + CHECK_THROW(data.emplace_back("Z"), etl::vector_full); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_push_back_unique_ptr) { @@ -1028,6 +1074,26 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.insert(data2.cbegin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_emplace_position_value) { @@ -1058,6 +1124,25 @@ namespace } } + TEST_FIXTURE(SetupFixture, test_emplace_position_value_outofbounds) + { + const size_t INITIAL_SIZE = 5UL; + const std::string INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE); + CHECK_THROW(data.emplace(data2.begin(), INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_value_excess) { @@ -1113,6 +1198,24 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_n_value_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + CHECK_THROW(data.insert(data2.end(), 1, INITIAL_VALUE), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_n_value_excess) { @@ -1173,6 +1276,24 @@ namespace } } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_position_range_outofbounds) + { + const NDC INITIAL_VALUE("1"); + + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(lookup2, pool2); + + CHECK_THROW(data.insert(data2.end(), insert_data.begin(), insert_data.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_position_range_excess) { @@ -1223,6 +1344,18 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_single_outofbounds) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); + + CHECK_THROW(data.erase(data.end()), etl::vector_out_of_bounds); + CHECK_THROW(data.erase(data.cend()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_range) { @@ -1245,6 +1378,22 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_erase_range_outofbounds) + { + LookupNDC lookup; + PoolNDC pool; + + DataNDC data(initial_data.begin(), initial_data.end(), lookup, pool); + + LookupNDC lookup2; + PoolNDC pool2; + + DataNDC data2(initial_data.begin(), initial_data.end(), lookup2, pool2); + + CHECK_THROW(data.erase(data2.begin(), data2.end()), etl::vector_out_of_bounds); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) {