Merge branch 'Emplace' into development

# Conflicts:
#	src/CreateFSM.bat
#	src/CreateMessageRouter.bat
#	src/flat_map.h
#	src/fsm.h
#	src/fsm_generator.h
#	src/message_router.h
#	src/message_router_generator.h
#	src/queue.h
#	src/vector.h
#	test/codeblocks/ETL.depend
#	test/codeblocks/ETL.layout
#	test/data.h
#	test/test_fsm.cpp
#	test/test_message_router.cpp
#	test/vs2017/etl.vcxproj
#	test/vs2017/etl.vcxproj.filters
#	test/vs2017/random.csv
This commit is contained in:
John Wellbelove 2017-07-26 10:06:23 +01:00
parent 74beb3421d
commit 044535d6d6
8 changed files with 662 additions and 5 deletions

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "container.h"
#include "alignment.h"
#include "array.h"
#include "memory.h"
#include "exception.h"
#include "error_handler.h"
#include "debug_count.h"
@ -899,6 +900,266 @@ namespace etl
return position;
}
//*************************************************************************
/// Emplaces data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
///\param insert_position>The insert position.
//*************************************************************************
template <typename T1>
iterator emplace(const_iterator insert_position, const T1& value1)
{
iterator position(insert_position.index, *this, p_buffer);
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
void* p;
if (insert_position == begin())
{
--_begin;
p = etl::addressof(*_begin);
++current_size;
++construct_count;
position = _begin;
}
else if (insert_position == end())
{
p = etl::addressof(*_end);
++_end;
++current_size;
++construct_count;
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the _begin.
create_element_front(*_begin);
// Move the values.
std::copy(_begin + 1, position, _begin);
// Write the new value.
--position;
(*position).~T();
p = etl::addressof(*position);
}
else
{
// Construct the _end.
create_element_back(*(_end - 1));
// Move the values.
std::copy_backward(position, _end - 2, _end - 1);
// Write the new value.
(*position).~T();
p = etl::addressof(*position);
}
}
::new (p) T(value1);
return position;
}
//*************************************************************************
/// Emplaces data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
///\param insert_position>The insert position.
//*************************************************************************
template <typename T1, typename T2>
iterator emplace(const_iterator insert_position, const T1& value1, const T2& value2)
{
iterator position(insert_position.index, *this, p_buffer);
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
void* p;
if (insert_position == begin())
{
--_begin;
p = etl::addressof(*_begin);
++current_size;
++construct_count;
position = _begin;
}
else if (insert_position == end())
{
p = etl::addressof(*_end);
++_end;
++current_size;
++construct_count;
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the _begin.
create_element_front(*_begin);
// Move the values.
std::copy(_begin + 1, position, _begin);
// Write the new value.
--position;
(*position).~T();
p = etl::addressof(*position);
}
else
{
// Construct the _end.
create_element_back(*(_end - 1));
// Move the values.
std::copy_backward(position, _end - 2, _end - 1);
// Write the new value.
(*position).~T();
p = etl::addressof(*position);
}
}
::new (p) T(value1, value2);
return position;
}
//*************************************************************************
/// Emplaces data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
///\param insert_position>The insert position.
//*************************************************************************
template <typename T1, typename T2, typename T3>
iterator emplace(const_iterator insert_position, const T1& value1, const T2& value2, const T3& value3)
{
iterator position(insert_position.index, *this, p_buffer);
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
void* p;
if (insert_position == begin())
{
--_begin;
p = etl::addressof(*_begin);
++current_size;
++construct_count;
position = _begin;
}
else if (insert_position == end())
{
p = etl::addressof(*_end);
++_end;
++current_size;
++construct_count;
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the _begin.
create_element_front(*_begin);
// Move the values.
std::copy(_begin + 1, position, _begin);
// Write the new value.
--position;
(*position).~T();
p = etl::addressof(*position);
}
else
{
// Construct the _end.
create_element_back(*(_end - 1));
// Move the values.
std::copy_backward(position, _end - 2, _end - 1);
// Write the new value.
(*position).~T();
p = etl::addressof(*position);
}
}
::new (p) T(value1, value2, value3);
return position;
}
//*************************************************************************
/// Emplaces data into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
///\param insert_position>The insert position.
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
iterator emplace(const_iterator insert_position, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
iterator position(insert_position.index, *this, p_buffer);
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
void* p;
if (insert_position == begin())
{
--_begin;
p = etl::addressof(*_begin);
++current_size;
++construct_count;
position = _begin;
}
else if (insert_position == end())
{
p = etl::addressof(*_end);
++_end;
++current_size;
++construct_count;
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the _begin.
create_element_front(*_begin);
// Move the values.
std::copy(_begin + 1, position, _begin);
// Write the new value.
--position;
(*position).~T();
p = etl::addressof(*position);
}
else
{
// Construct the _end.
create_element_back(*(_end - 1));
// Move the values.
std::copy_backward(position, _end - 2, _end - 1);
// Write the new value.
(*position).~T();
p = etl::addressof(*position);
}
}
::new (p) T(value1, value2, value3, value4);
return position;
}
//*************************************************************************
/// Inserts 'n' copies of a value into the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full.
@ -1247,6 +1508,74 @@ namespace etl
return r;
}
//*************************************************************************
/// Emplaces an item to the back of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1>
void emplace_back(const T1& value1)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
::new (&(*_end)) T(value1);
++_end;
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the back of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2>
void emplace_back(const T1& value1, const T2& value2)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
::new (&(*_end)) T(value1, value2);
++_end;
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the back of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2, typename T3>
void emplace_back(const T1& value1, const T2& value2, const T3& value3)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
::new (&(*_end)) T(value1, value2, value3);
++_end;
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the back of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
void emplace_back(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
::new (&(*_end)) T(value1, value2, value3, value4);
++_end;
++current_size;
++construct_count;
}
//*************************************************************************
/// Removes the oldest item from the deque.
//*************************************************************************
@ -1286,6 +1615,74 @@ namespace etl
return *_begin;
}
//*************************************************************************
/// Emplaces an item to the front of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1>
void emplace_front(const T1& value1)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
--_begin;
::new (&(*_begin)) T(value1);
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the front of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2>
void emplace_front(const T1& value1, const T2& value2)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
--_begin;
::new (&(*_begin)) T(value1, value2);
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the front of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2, typename T3>
void emplace_front(const T1& value1, const T2& value2, const T3& value3)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
--_begin;
::new (&(*_begin)) T(value1, value2, value3);
++current_size;
++construct_count;
}
//*************************************************************************
/// Emplaces an item to the front of the deque.
/// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full.
//*************************************************************************
template <typename T1, typename T2, typename T3, typename T4>
void emplace_front(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(deque_full));
#endif
--_begin;
::new (&(*_begin)) T(value1, value2, value3, value4);
++current_size;
++construct_count;
}
//*************************************************************************
/// Removes the oldest item from the deque.
//*************************************************************************

View File

@ -30,4 +30,8 @@
30 reference_flat_map
31 reference_flat_multimap
32 reference_flat_set
33 reference_flat_multiset
33 reference_flat_multiset
34 fsm
35 message_router
36 scheduler
37 task

View File

@ -35,6 +35,8 @@ SOFTWARE.
///\ingroup utilities
#include "type_traits.h"
#include "smallest.h"
#include "static_assert.h"
namespace etl
{
@ -163,6 +165,57 @@ namespace etl
::value>::value>::value>::value>::value>::value>::value
};
};
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
///\ingroup largest
//***************************************************************************
template <typename T>
struct larger_int_type
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_int_for_bits<etl::integral_limits<typename etl::make_signed<T>::type>::bits + 1>::type type;
};
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
///\ingroup largest
//***************************************************************************
template <typename T>
struct larger_uint_type
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<typename etl::make_unsigned<T>::type>::bits + 1>::type type;
};
//***************************************************************************
/// Defines a type that is as larger or larger than the specified type.
/// Will return the specified type is there is not a larger type.
/// The returned type will be of the same sign.
///\ingroup largest
//***************************************************************************
template <typename T, bool IS_SIGNED = etl::is_signed<T>::value>
struct larger_type;
template <typename T>
struct larger_type<T, false>
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_uint_for_bits<etl::integral_limits<T>::bits + 1>::type type;
};
template <typename T>
struct larger_type<T, true>
{
STATIC_ASSERT(etl::is_integral<T>::value, "Must be an integral type");
typedef typename etl::smallest_int_for_bits<etl::integral_limits<T>::bits + 1>::type type;
};
}
#endif

View File

@ -243,7 +243,6 @@ namespace etl
return (size() < 2);
}
protected:
//*************************************************************************
@ -332,7 +331,7 @@ namespace etl
protected:
typedef typename etl::parameter_type<T, is_fundamental<T>::value || is_pointer<T>::value>::type parameter_t;
typedef typename etl::parameter_type<T>::type parameter_t;
//*************************************************************************
/// The data node element in the list.

View File

@ -617,7 +617,21 @@ namespace
DataNDC data(compare_data.begin(), compare_data.end());
Compare_Data::iterator cposition = compare_data.insert(compare_data.begin(), N14);
DataNDC::iterator position = data.insert(data.begin(), N14);
DataNDC::iterator position = data.insert(data.begin(), N14);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
CHECK_EQUAL(std::distance(compare_data.begin(), cposition), std::distance(data.begin(), position));
}
//*************************************************************************
TEST(test_emplace_value_begin)
{
Compare_Data compare_data(initial_data_under.begin(), initial_data_under.end());
DataNDC data(compare_data.begin(), compare_data.end());
Compare_Data::iterator cposition = compare_data.emplace(compare_data.begin(), N14.value);
DataNDC::iterator position = data.emplace(data.begin(), N14.value);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
@ -631,7 +645,21 @@ namespace
DataNDC data(compare_data.begin(), compare_data.end());
Compare_Data::iterator cposition = compare_data.insert(compare_data.end(), N14);
DataNDC::iterator position = data.insert(data.end(), N14);
DataNDC::iterator position = data.insert(data.end(), N14);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
CHECK_EQUAL(std::distance(compare_data.begin(), cposition), std::distance(data.begin(), position));
}
//*************************************************************************
TEST(test_emplace_value_end)
{
Compare_Data compare_data(initial_data_under.begin(), initial_data_under.end());
DataNDC data(compare_data.begin(), compare_data.end());
Compare_Data::iterator cposition = compare_data.emplace(compare_data.end(), N14.value);
DataNDC::iterator position = data.emplace(data.end(), N14.value);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
@ -662,6 +690,30 @@ namespace
CHECK_EQUAL(std::distance(compare_data.begin(), cposition), std::distance(data.begin(), position));
}
//*************************************************************************
TEST(test_emplace_value)
{
Compare_Data compare_data(initial_data_under.begin(), initial_data_under.end());
DataNDC data(compare_data.begin(), compare_data.end());
Compare_Data::iterator cposition = compare_data.emplace(compare_data.begin() + 3, N14.value);
DataNDC::iterator position = data.emplace(data.begin() + 3, N14.value);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
CHECK_EQUAL(std::distance(compare_data.begin(), cposition), std::distance(data.begin(), position));
compare_data.assign(initial_data_under.begin(), initial_data_under.end());
data.assign(compare_data.begin(), compare_data.end());
cposition = compare_data.emplace(compare_data.begin() + 4, N14.value);
position = data.emplace(data.begin() + 4, N14.value);
CHECK_EQUAL(compare_data.size(), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
CHECK_EQUAL(std::distance(compare_data.begin(), cposition), std::distance(data.begin(), position));
}
//*************************************************************************
TEST(test_insert_n_value_position)
{
@ -1174,6 +1226,33 @@ namespace
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
}
//*************************************************************************
TEST(test_emplace_back)
{
Compare_Data compare_data = { N1, N2, N3, N4, N5 };
DataNDC data;
CHECK_NO_THROW(data.emplace_back("1"));
CHECK_EQUAL(size_t(1), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end() - 4, data.begin()));
CHECK_NO_THROW(data.emplace_back("2"));
CHECK_EQUAL(size_t(2), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end() - 3, data.begin()));
CHECK_NO_THROW(data.emplace_back("3"));
CHECK_EQUAL(size_t(3), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end() - 2, data.begin()));
CHECK_NO_THROW(data.emplace_back("4"));
CHECK_EQUAL(size_t(4), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end() - 1, data.begin()));
CHECK_NO_THROW(data.emplace_back("5"));
CHECK_EQUAL(size_t(5), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
}
//*************************************************************************
TEST(test_push_back_excess)
{
@ -1288,6 +1367,33 @@ namespace
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
}
//*************************************************************************
TEST(test_emplace_front)
{
Compare_Data compare_data = { N5, N4, N3, N2, N1 };
DataNDC data;
CHECK_NO_THROW(data.emplace_front("1"));
CHECK_EQUAL(size_t(1), data.size());
CHECK(std::equal(compare_data.begin() + 4, compare_data.end(), data.begin()));
CHECK_NO_THROW(data.emplace_front("2"));
CHECK_EQUAL(size_t(2), data.size());
CHECK(std::equal(compare_data.begin() + 3, compare_data.end(), data.begin()));
CHECK_NO_THROW(data.emplace_front("3"));
CHECK_EQUAL(size_t(3), data.size());
CHECK(std::equal(compare_data.begin() + 2, compare_data.end(), data.begin()));
CHECK_NO_THROW(data.emplace_front("4"));
CHECK_EQUAL(size_t(4), data.size());
CHECK(std::equal(compare_data.begin() + 1, compare_data.end(), data.begin()));
CHECK_NO_THROW(data.emplace_front("5"));
CHECK_EQUAL(size_t(5), data.size());
CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin()));
}
//*************************************************************************
TEST(test_push_front_excess)
{

View File

@ -477,6 +477,35 @@ namespace
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_emplace_front)
{
CompareDataNDC compare_data;
DataNDC data;
compare_data.emplace_front("1");
compare_data.emplace_front("2");
compare_data.emplace_front("3");
compare_data.emplace_front("4");
compare_data.emplace_front("5");
compare_data.emplace_front("6");
CHECK_NO_THROW(data.emplace_front("1"));
CHECK_NO_THROW(data.emplace_front("2"));
CHECK_NO_THROW(data.emplace_front("3"));
CHECK_NO_THROW(data.emplace_front("4"));
CHECK_NO_THROW(data.emplace_front("5"));
CHECK_NO_THROW(data.emplace_front("6"));
CHECK_EQUAL(6U, data.size());
CHECK_EQUAL(6, std::distance(data.begin(), data.end()));
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data.size());
are_equal = std::equal(data.begin(), data.end(), compare_data.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_push_front_null)
{

View File

@ -97,5 +97,47 @@ namespace
CHECK_EQUAL(std::alignment_of<S3>::value, size);
}
//*************************************************************************
TEST(test_larger_int_type)
{
CHECK(bool(std::is_same<etl::larger_int_type<int8_t>::type, int16_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<int16_t>::type, int32_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<int32_t>::type, int64_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<int64_t>::type, int64_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<uint8_t>::type, int16_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<uint16_t>::type, int32_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<uint32_t>::type, int64_t>::value));
CHECK(bool(std::is_same<etl::larger_int_type<uint64_t>::type, int64_t>::value));
}
//*************************************************************************
TEST(test_larger_uint_type)
{
CHECK(bool(std::is_same<etl::larger_uint_type<int8_t>::type, uint16_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<int16_t>::type, uint32_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<int32_t>::type, uint64_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<int64_t>::type, uint64_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<uint8_t>::type, uint16_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<uint16_t>::type, uint32_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<uint32_t>::type, uint64_t>::value));
CHECK(bool(std::is_same<etl::larger_uint_type<uint64_t>::type, uint64_t>::value));
}
//*************************************************************************
TEST(test_larger_type)
{
CHECK(bool(std::is_same<etl::larger_type<int8_t>::type, int16_t>::value));
CHECK(bool(std::is_same<etl::larger_type<int16_t>::type, int32_t>::value));
CHECK(bool(std::is_same<etl::larger_type<int32_t>::type, int64_t>::value));
CHECK(bool(std::is_same<etl::larger_type<int64_t>::type, int64_t>::value));
CHECK(bool(std::is_same<etl::larger_type<uint8_t>::type, uint16_t>::value));
CHECK(bool(std::is_same<etl::larger_type<uint16_t>::type, uint32_t>::value));
CHECK(bool(std::is_same<etl::larger_type<uint32_t>::type, uint64_t>::value));
CHECK(bool(std::is_same<etl::larger_type<uint64_t>::type, uint64_t>::value));
}
};
}

View File

@ -621,6 +621,33 @@ namespace
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_emplace_position_value)
{
const size_t INITIAL_SIZE = 5;
const std::string INITIAL_VALUE("1");
for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset)
{
CompareDataNDC compare_data;
DataNDC data;
data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
compare_data.assign(initial_data.begin(), initial_data.begin() + INITIAL_SIZE);
data.emplace(data.begin() + offset, INITIAL_VALUE);
compare_data.emplace(compare_data.begin() + offset, INITIAL_VALUE);
CHECK_EQUAL(compare_data.size(), data.size());
bool is_equal = std::equal(data.begin(),
data.end(),
compare_data.begin());
CHECK(is_equal);
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_position_value_excess)
{