Merge remote-tracking branch 'refs/remotes/ETLCPP/master'

This commit is contained in:
Ashley Roll 2017-03-08 14:37:21 +10:00
commit 9171050799
172 changed files with 16328 additions and 6327 deletions

View File

@ -1,9 +1,9 @@
name=Embedded Template Library
version=8.2.0
version=9.1.0
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
sentence=A C++ template library tailored for embedded systems.
paragraph=Requires some support from STL. See http://andybrown.me.uk/2011/01/15/the-standard-template-library-stl-for-avr-with-c-streams/
category=Other
url=http://www.etlcpp.com/
architectures=*
architectures=*

View File

@ -33,14 +33,17 @@ SOFTWARE.
///\defgroup algorithm algorithm
/// Reverse engineered algorithms from C++ 0x11
/// Additional new variants of certain algorithms.
///\ingroup utilities
#include <algorithm>
#include <iterator>
#include <utility>
#include <functional>
#include <iterator>
#include <stdint.h>
#include "iterator.h"
#include "type_traits.h"
namespace etl
@ -50,8 +53,11 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"></a>
///\ingroup algorithm
//***************************************************************************
template <typename TIterator, typename TCompare>
std::pair<TIterator, TIterator> minmax_element(TIterator begin, TIterator end, TCompare compare)
template <typename TIterator,
typename TCompare>
std::pair<TIterator, TIterator> minmax_element(TIterator begin,
TIterator end,
TCompare compare)
{
TIterator minimum = begin;
TIterator maximum = begin;
@ -67,7 +73,7 @@ namespace etl
{
maximum = begin;
}
++begin;
}
@ -80,7 +86,8 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax_element"></a>
//***************************************************************************
template <typename TIterator>
std::pair<TIterator, TIterator> minmax_element(TIterator begin, TIterator end)
std::pair<TIterator, TIterator> minmax_element(TIterator begin,
TIterator end)
{
typedef typename std::iterator_traits<TIterator>::value_type value_t;
@ -93,9 +100,10 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax"></a>
//***************************************************************************
template <typename T>
std::pair<const T&, const T&> minmax(const T& a, const T& b)
std::pair<const T&, const T&> minmax(const T& a,
const T& b)
{
return (b < a) ? std::pair<const T&, const T&>(b, a) : std::pair<const T&, const T&>(a, b);
return (b < a) ? std::pair<const T&, const T&>(b, a) : std::pair<const T&, const T&>(a, b);
}
//***************************************************************************
@ -103,8 +111,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/minmax"></a>
//***************************************************************************
template <typename T, typename TCompare>
std::pair<const T&, const T&> minmax(const T& a, const T& b, TCompare compare)
template <typename T,
typename TCompare>
std::pair<const T&, const T&> minmax(const T& a,
const T& b,
TCompare compare)
{
return compare(b, a) ? std::pair<const T&, const T&>(b, a) : std::pair<const T&, const T&>(a, b);
}
@ -115,7 +126,8 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
//***************************************************************************
template <typename TIterator>
TIterator is_sorted_until(TIterator begin, TIterator end)
TIterator is_sorted_until(TIterator begin,
TIterator end)
{
if (begin != end)
{
@ -140,8 +152,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted_until"></a>
//***************************************************************************
template <typename TIterator, typename TCompare>
TIterator is_sorted_until(TIterator begin, TIterator end, TCompare compare)
template <typename TIterator,
typename TCompare>
TIterator is_sorted_until(TIterator begin,
TIterator end,
TCompare compare)
{
if (begin != end)
{
@ -167,7 +182,8 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"></a>
//***************************************************************************
template<typename TIterator>
bool is_sorted(TIterator begin, TIterator end)
bool is_sorted(TIterator begin,
TIterator end)
{
return etl::is_sorted_until(begin, end) == end;
}
@ -177,29 +193,99 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_sorted"></a>
//***************************************************************************
template<typename TIterator, typename TCompare>
bool is_sorted(TIterator begin, TIterator end, TCompare compare)
template<typename TIterator,
typename TCompare>
bool is_sorted(TIterator begin,
TIterator end,
TCompare compare)
{
return etl::is_sorted_until(begin, end, compare) == end;
}
//***************************************************************************
/// copy
/// A form of copy where the smallest of the two ranges is used.
/// There is currently no STL equivalent.
/// Specialisation for random access iterators.
///\param i_begin Beginning of the input range.
///\param i_end End of the input range.
///\param o_begin Beginning of the output range.
///\param o_end End of the output range.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TOutputIterator>
typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value &&
etl::is_random_iterator<TOutputIterator>::value, TOutputIterator>::type
copy(TInputIterator i_begin,
TInputIterator i_end,
TOutputIterator o_begin,
TOutputIterator o_end)
{
size_t s_size = std::distance(i_begin, i_end);
size_t d_size = std::distance(o_begin, o_end);
size_t size = (s_size < d_size) ? s_size : d_size;
return std::copy(i_begin, i_begin + size, o_begin);
}
//***************************************************************************
/// copy
/// A form of copy where the smallest of the two ranges is used.
/// There is currently no STL equivalent.
/// Specialisation for non random access iterators.
///\param i_begin Beginning of the input range.
///\param i_end End of the input range.
///\param o_begin Beginning of the output range.
///\param o_end End of the output range.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TOutputIterator>
typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value ||
!etl::is_random_iterator<TOutputIterator>::value, TOutputIterator>::type
copy(TInputIterator i_begin,
TInputIterator i_end,
TOutputIterator o_begin,
TOutputIterator o_end)
{
while ((i_begin != i_end) && (o_begin != o_end))
{
*o_begin++ = *i_begin++;
}
return o_begin;
}
//***************************************************************************
/// copy_n
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/copy_n"></a>
//***************************************************************************
template <typename TInputIterator, typename Size, typename TOutputIterator>
TOutputIterator copy_n(TInputIterator begin, Size count, TOutputIterator result)
template <typename TInputIterator,
typename TSize,
typename TOutputIterator>
TOutputIterator copy_n(TInputIterator begin,
TSize count,
TOutputIterator result)
{
if (count > 0)
{
for (Size i = 0; i < count; ++i)
{
*result++ = *begin++;
}
}
return std::copy(begin, begin + count, result);
}
return result;
//***************************************************************************
/// copy_n
/// A form of copy_n where the smallest of the two ranges is used.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TSize,
typename TOutputIterator>
TOutputIterator copy_n(TInputIterator i_begin,
TSize count,
TOutputIterator o_begin,
TOutputIterator o_end)
{
return etl::copy(i_begin, i_begin + count, o_begin, o_end);;
}
//***************************************************************************
@ -207,8 +293,13 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/copy"></a>
//***************************************************************************
template <typename TIterator, typename TOutputIterator, typename TUnaryPredicate>
TOutputIterator copy_if(TIterator begin, TIterator end, TOutputIterator out, TUnaryPredicate predicate)
template <typename TIterator,
typename TOutputIterator,
typename TUnaryPredicate>
TOutputIterator copy_if(TIterator begin,
TIterator end,
TOutputIterator out,
TUnaryPredicate predicate)
{
while (begin != end)
{
@ -223,13 +314,44 @@ namespace etl
return out;
}
//***************************************************************************
/// copy_if
/// A form of copy_if where it terminates when the first end iterator is reached.
/// There is currently no STL equivelent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TOutputIterator,
typename TUnaryPredicate>
TOutputIterator copy_if(TInputIterator i_begin,
TInputIterator i_end,
TOutputIterator o_begin,
TOutputIterator o_end,
TUnaryPredicate predicate)
{
while ((i_begin != i_end) && (o_begin != o_end))
{
if (predicate(*i_begin))
{
*o_begin++ = *i_begin;
}
++i_begin;
}
return o_begin;
}
//***************************************************************************
/// find_if_not
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/find"></a>
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate>
TIterator find_if_not(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
TIterator find_if_not(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
while (begin != end)
{
@ -249,8 +371,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate >
bool all_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
bool all_of(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
return etl::find_if_not(begin, end, predicate) == end;
}
@ -260,8 +385,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate >
bool any_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
bool any_of(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
return std::find_if(begin, end, predicate) != end;
}
@ -271,8 +399,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/all_any_none_of"></a>
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate >
bool none_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
bool none_of(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
return std::find_if(begin, end, predicate) == end;
}
@ -282,8 +413,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
//***************************************************************************
template <typename TIterator1, typename TIterator2>
bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2)
template <typename TIterator1,
typename TIterator2>
bool is_permutation(TIterator1 begin1,
TIterator1 end1,
TIterator2 begin2)
{
if (begin1 != end1)
{
@ -313,8 +447,12 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
//***************************************************************************
template <typename TIterator1, typename TIterator2>
bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TIterator2 end2)
template <typename TIterator1,
typename TIterator2>
bool is_permutation(TIterator1 begin1,
TIterator1 end1,
TIterator2 begin2,
TIterator2 end2)
{
if (begin1 != end1)
{
@ -340,8 +478,13 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
//***************************************************************************
template <typename TIterator1, typename TIterator2, typename TBinaryPredicate>
bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TBinaryPredicate predicate)
template <typename TIterator1,
typename TIterator2,
typename TBinaryPredicate>
bool is_permutation(TIterator1 begin1,
TIterator1 end1,
TIterator2 begin2,
TBinaryPredicate predicate)
{
if (begin1 != end1)
{
@ -371,8 +514,14 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_permutation"></a>
//***************************************************************************
template <typename TIterator1, typename TIterator2, typename TBinaryPredicate>
bool is_permutation(TIterator1 begin1, TIterator1 end1, TIterator2 begin2, TIterator2 end2, TBinaryPredicate predicate)
template <typename TIterator1,
typename TIterator2,
typename TBinaryPredicate>
bool is_permutation(TIterator1 begin1,
TIterator1 end1,
TIterator2 begin2,
TIterator2 end2,
TBinaryPredicate predicate)
{
if (begin1 != end1)
{
@ -398,8 +547,11 @@ namespace etl
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/is_partitioned"></a>
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate>
bool is_partitioned(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
bool is_partitioned(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
while (begin != end)
{
@ -425,8 +577,11 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/partition_point"></a>
///\ingroup algorithm
//***************************************************************************
template <typename TIterator, typename TUnaryPredicate>
TIterator partition_point(TIterator begin, TIterator end, TUnaryPredicate predicate)
template <typename TIterator,
typename TUnaryPredicate>
TIterator partition_point(TIterator begin,
TIterator end,
TUnaryPredicate predicate)
{
while (begin != end)
{
@ -447,12 +602,15 @@ namespace etl
///<a href="http://en.cppreference.com/w/cpp/algorithm/partition_copy"></a>
///\ingroup algorithm
//***************************************************************************
template <typename TSource, typename TDestinationTrue, typename TDestinationFalse, typename TUnaryPredicate>
template <typename TSource,
typename TDestinationTrue,
typename TDestinationFalse,
typename TUnaryPredicate>
std::pair<TDestinationTrue, TDestinationFalse> partition_copy(TSource begin,
TSource end,
TDestinationTrue destination_true,
TDestinationFalse destination_false,
TUnaryPredicate predicate)
TSource end,
TDestinationTrue destination_true,
TDestinationFalse destination_false,
TUnaryPredicate predicate)
{
while (begin != end)
{
@ -468,6 +626,266 @@ namespace etl
return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
}
//***************************************************************************
/// Like std::for_each but applies a predicate before calling the function.
///\ingroup algorithm
//***************************************************************************
template <typename TIterator,
typename TUnaryFunction,
typename TUnaryPredicate>
TUnaryFunction for_each_if(TIterator begin,
const TIterator end,
TUnaryFunction function,
TUnaryPredicate predicate)
{
while (begin != end)
{
if (predicate(*begin))
{
function(*begin);
}
++begin;
}
return function;
}
//***************************************************************************
/// A form of std::transform where the transform returns when the first range
/// end is reached.
/// There is currently no STL equivalent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TOutputIterator,
typename TUnaryFunction>
void transform(TInputIterator i_begin,
TInputIterator i_end,
TOutputIterator o_begin,
TOutputIterator o_end,
TUnaryFunction function)
{
while ((i_begin != i_end) && (o_begin != o_end))
{
*o_begin++ = function(*i_begin++);
}
}
//***************************************************************************
/// Transform 'n' items.
/// Random iterators.
/// There is currently no STL equivalent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TSize,
typename TOutputIterator,
typename TUnaryFunction>
typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value, void>::type
transform_n(TInputIterator i_begin,
TSize n,
TOutputIterator o_begin,
TUnaryFunction function)
{
std::transform(i_begin, i_begin + n, o_begin, function);
}
//***************************************************************************
/// Transform 'n' items from two ranges.
/// Random iterators.
/// There is currently no STL equivalent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator1,
typename TInputIterator2,
typename TSize,
typename TOutputIterator,
typename TBinaryFunction>
typename etl::enable_if<etl::is_random_iterator<TInputIterator1>::value &&
etl::is_random_iterator<TInputIterator2>::value, void>::type
transform_n(TInputIterator1 i_begin1,
TInputIterator2 i_begin2,
TSize n,
TOutputIterator o_begin,
TBinaryFunction function)
{
std::transform(i_begin, i_begin + n, i_begin2, o_begin, function);
}
//***************************************************************************
/// Transform 'n' items.
/// Non-random iterators.
/// There is currently no STL equivalent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TSize,
typename TOutputIterator,
typename TUnaryFunction>
typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value, void>::type
transform_n(TInputIterator i_begin,
TSize n,
TOutputIterator o_begin,
TUnaryFunction function)
{
while (n > 0)
{
*o_begin++ = function(*i_begin++);
--n;
}
}
//***************************************************************************
/// Transform 'n' items from two ranges.
/// Non-random iterators.
/// There is currently no STL equivalent.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator1,
typename TInputIterator2,
typename TSize,
typename TOutputIterator,
typename TBinaryFunction>
typename etl::enable_if<!etl::is_random_iterator<TInputIterator1>::value ||
!etl::is_random_iterator<TInputIterator2>::value, void>::type
transform_n(TInputIterator1 i_begin1,
TInputIterator2 i_begin2,
TSize n,
TOutputIterator o_begin,
TBinaryFunction function)
{
while (n > 0)
{
*o_begin++ = function(*i_begin1++, *i_begin2++);
--n;
}
}
//***************************************************************************
/// Like std::transform but applies a predicate before calling the function.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TOutputIterator,
typename TUnaryFunction,
typename TUnaryPredicate>
TOutputIterator transform_if(TInputIterator i_begin,
const TInputIterator i_end,
TOutputIterator o_begin,
TUnaryFunction function,
TUnaryPredicate predicate)
{
while (i_begin != i_end)
{
if (predicate(*i_begin))
{
*o_begin++ = function(*i_begin);
}
++i_begin;
}
return o_begin;
}
//***************************************************************************
/// Like etl::transform_if but inputs from two ranges.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator1,
typename TInputIterator2,
typename TOutputIterator,
typename TBinaryFunction,
typename TBinaryPredicate>
TOutputIterator transform_if(TInputIterator1 i_begin1,
const TInputIterator1 i_end1,
TInputIterator2 i_begin2,
TOutputIterator o_begin,
TBinaryFunction function,
TBinaryPredicate predicate)
{
while (i_begin1 != i_end1)
{
if (predicate(*i_begin1, *i_begin2))
{
*o_begin++ = function(*i_begin1, *i_begin2);
}
++i_begin1;
++i_begin2;
}
return o_begin;
}
//***************************************************************************
/// Transforms the elements from the range (begin, end) to two different ranges
/// depending on the value returned by the predicate.<br>
///\ingroup algorithm
//***************************************************************************
template <typename TSource, typename TDestinationTrue, typename TDestinationFalse,
typename TUnaryFunctionTrue, typename TUnaryFunctionFalse,
typename TUnaryPredicate>
std::pair<TDestinationTrue, TDestinationFalse> partition_transform(TSource begin,
TSource end,
TDestinationTrue destination_true,
TDestinationFalse destination_false,
TUnaryFunctionTrue function_true,
TUnaryFunctionFalse function_false,
TUnaryPredicate predicate)
{
while (begin != end)
{
if (predicate(*begin))
{
*destination_true++ = function_true(*begin++);
}
else
{
*destination_false++ = function_false(*begin++);
}
}
return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
}
//***************************************************************************
/// Transforms the elements from the ranges (begin1, end1) & (begin2)
/// to two different ranges depending on the value returned by the predicate.
///\ingroup algorithm
//***************************************************************************
template <typename TSource1,
typename TSource2,
typename TDestinationTrue,
typename TDestinationFalse,
typename TBinaryFunctionTrue,
typename TBinaryFunctionFalse,
typename TBinaryPredicate>
std::pair<TDestinationTrue, TDestinationFalse> partition_transform(TSource1 begin1,
TSource1 end1,
TSource2 begin2,
TDestinationTrue destination_true,
TDestinationFalse destination_false,
TBinaryFunctionTrue function_true,
TBinaryFunctionFalse function_false,
TBinaryPredicate predicate)
{
while (begin1 != end1)
{
if (predicate(*begin1, *begin2))
{
*destination_true++ = function_true(*begin1++, *begin2++);
}
else
{
*destination_false++ = function_false(*begin1++, *begin2++);
}
}
return std::pair<TDestinationTrue, TDestinationFalse>(destination_true, destination_false);
}
}
#endif

View File

@ -174,7 +174,7 @@ namespace etl
union
{
uint8_t data[LENGTH];
uint_least8_t data[LENGTH];
typename etl::type_with_alignment<ALIGNMENT>::type __etl_alignment_type__; // A POD type that has the same alignment as ALIGNMENT.
};
};

View File

@ -41,6 +41,7 @@ SOFTWARE.
#include "parameter_type.h"
#include "static_assert.h"
#include "error_handler.h"
#include "algorithm.h"
///\defgroup array array
/// A replacement for std::array if you haven't got C++0x11.
@ -76,18 +77,18 @@ namespace etl
}
};
//***************************************************************************
//***************************************************************************
///\ingroup array
/// A replacement for std::array if you haven't got C++0x11.
//***************************************************************************
//***************************************************************************
template <typename T, const size_t SIZE_>
class array
{
{
private:
typedef typename parameter_type<T>::type parameter_t;
public:
public:
enum
{
@ -102,9 +103,9 @@ namespace etl
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
//*************************************************************************
// Element access
@ -204,29 +205,29 @@ namespace etl
// Iterators
//*************************************************************************
//*************************************************************************
/// Returns an iterator to the beginning of the array.
//*************************************************************************
iterator begin()
{
return &_buffer[0];
}
//*************************************************************************
/// Returns a const iterator to the beginning of the array.
//*************************************************************************
const_iterator begin() const
{
return &_buffer[0];
}
//*************************************************************************
/// Returns an iterator to the beginning of the array.
//*************************************************************************
iterator begin()
{
return &_buffer[0];
}
//*************************************************************************
/// Returns a const iterator to the beginning of the array.
//*************************************************************************
const_iterator cbegin() const
{
return begin();
}
//*************************************************************************
/// Returns a const iterator to the beginning of the array.
//*************************************************************************
const_iterator begin() const
{
return &_buffer[0];
}
//*************************************************************************
/// Returns a const iterator to the beginning of the array.
//*************************************************************************
const_iterator cbegin() const
{
return begin();
}
//*************************************************************************
/// Returns an iterator to the end of the array.
@ -252,53 +253,53 @@ namespace etl
return &_buffer[SIZE];
}
//*************************************************************************
// Returns an reverse iterator to the reverse beginning of the array.
//*************************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
//*************************************************************************
/// Returns a const reverse iterator to the reverse beginning of the array.
//*************************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
// Returns an reverse iterator to the reverse beginning of the array.
//*************************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
//*************************************************************************
/// Returns a const reverse iterator to the reverse beginning of the array.
//*************************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
/// Returns a const reverse iterator to the reverse beginning of the array.
//*************************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
/// Returns a reverse iterator to the end of the array.
//*************************************************************************
reverse_iterator rend()
{
return reverse_iterator(begin());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the array.
//*************************************************************************
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
/// Returns a const reverse iterator to the reverse beginning of the array.
//*************************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(end());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the array.
//*************************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
/// Returns a reverse iterator to the end of the array.
//*************************************************************************
reverse_iterator rend()
{
return reverse_iterator(begin());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the array.
//*************************************************************************
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
/// Returns a const reverse iterator to the end of the array.
//*************************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(begin());
}
//*************************************************************************
// Capacity
@ -312,21 +313,21 @@ namespace etl
return (SIZE == 0);
}
//*************************************************************************
/// Returns the size of the array.
//*************************************************************************
size_t size() const
{
return SIZE;
}
//*************************************************************************
/// Returns the size of the array.
//*************************************************************************
size_t size() const
{
return SIZE;
}
//*************************************************************************
/// Returns the maximum possible size of the array.
//*************************************************************************
size_t max_size() const
{
return SIZE;
}
//*************************************************************************
/// Returns the maximum possible size of the array.
//*************************************************************************
size_t max_size() const
{
return SIZE;
}
//*************************************************************************
// Operations
@ -353,20 +354,215 @@ namespace etl
}
}
//*************************************************************************
/// Fills the array from the range.
/// If the range is larger than the array then the extra data is ignored.
/// If the range is smaller than the array then the unused array elements are left unmodified.
///\param first The iterator to the first item in the ramge.
///\param last The iterator to one past the final item in the range.
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, const TIterator last)
{
iterator itr = begin();
etl::copy(first, last, begin(), end());
}
//*************************************************************************
/// Fills the array from the range.
/// If the range is larger than the array then the extra data is ignored.
/// If the range is smaller than the array then the unused array elements are initialised with the supplied value.
///\param first The iterator to the first item in the ramge.
///\param last The iterator to one past the final item in the range.
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, const TIterator last, parameter_t value)
{
// Copy from the range.
iterator p = etl::copy(first, last, begin(), end());
// Default initialise any that are left.
std::fill(p, end(), value);
}
//*************************************************************************
/// Inserts a value into the array.
///\param position The index of the position to insert at.
///\param value The value to insert.
//*************************************************************************
inline iterator insert_at(size_t position, parameter_t value)
{
return insert(begin() + position, value);
}
//*************************************************************************
/// Inserts a value into the array.
///\param position The iterator to the position to insert at.
///\param value The value to insert.
//*************************************************************************
iterator insert(const_iterator position, parameter_t value)
{
iterator p = const_cast<iterator>(position);
std::copy_backward(p, end() - 1, end());
*p = value;
return p;
}
//*************************************************************************
/// Insert into the array from the range.
///\param position The position to insert at.
///\param first The iterator to the first item in the range.
///\param last The iterator to one past the final item in the range.
//*************************************************************************
template <typename TIterator>
inline iterator insert_at(size_t position, TIterator first, const TIterator last)
{
return insert(begin() + position, first, last);
}
//*************************************************************************
/// Insert into the array from the range.
///\param position The position to insert at.
///\param first The iterator to the first item in the range.
///\param last The iterator to one past the final item in the range.
//*************************************************************************
template <typename TIterator>
iterator insert(const_iterator position, TIterator first, const TIterator last)
{
iterator p = const_cast<iterator>(position);
iterator result(p);
size_t source_size = std::distance(first, last);
size_t destination_space = std::distance(position, cend());
// Do we need to move anything?
if (source_size < destination_space)
{
size_t length = SIZE - (std::distance(begin(), p) + source_size);
std::copy_backward(p, p + length, end());
}
// Copy from the range.
etl::copy(first, last, p, end());
return result;
}
//*************************************************************************
/// Erases a value from the array.
/// The after erase, the last value in the array will be unmodified.
///\param position The index of the position to erase at.
//*************************************************************************
inline iterator erase_at(size_t position)
{
return erase(begin() + position);
}
//*************************************************************************
/// Inserts a value into the array.
/// The after erase, the last value in the array will be unmodified.
///\param position The iterator to the position to erase at.
//*************************************************************************
iterator erase(const_iterator position)
{
iterator p = const_cast<iterator>(position);
std::copy(p + 1, end(), p);
return p;
}
//*************************************************************************
/// Erases a range of values from the array.
/// The after erase, the last values in the array will be unmodified.
///\param first The first item to erase.
///\param last The one past the last item to erase.
//*************************************************************************
iterator erase_range(size_t first, size_t last)
{
return erase(begin() + first, begin() + last);
}
//*************************************************************************
/// Erases a range of values from the array.
/// The after erase, the last values in the array will be unmodified.
///\param first The first item to erase.
///\param last The one past the last item to erase.
//*************************************************************************
iterator erase(const_iterator first, const_iterator last)
{
iterator p = const_cast<iterator>(first);
std::copy(last, cend(), p);
return p;
}
//*************************************************************************
/// Erases a value from the array.
///\param position The index of the position to erase at.
///\param value The value to use to overwrite the last element in the array.
//*************************************************************************
inline iterator erase_at(size_t position, parameter_t value)
{
return erase(begin() + position, value);
}
//*************************************************************************
/// Inserts a value into the array.
///\param position The iterator to the position to erase at.
///\param value The value to use to overwrite the last element in the array.
//*************************************************************************
iterator erase(const_iterator position, parameter_t value)
{
iterator p = const_cast<iterator>(position);
std::copy(p + 1, end(), p);
back() = value;
return p;
}
//*************************************************************************
/// Erases a range of values from the array.
///\param first The first item to erase.
///\param last The one past the last item to erase.
///\param value The value to use to overwrite the last elements in the array.
//*************************************************************************
iterator erase_range(size_t first, size_t last, parameter_t value)
{
return erase(begin() + first, begin() + last, value);
}
//*************************************************************************
/// Erases a range of values from the array.
///\param position The iterator to the position to erase at.
///\param value The value to use to overwrite the last elements in the array.
//*************************************************************************
iterator erase(const_iterator first, const_iterator last, parameter_t value)
{
iterator p = const_cast<iterator>(first);
p = std::copy(last, cend(), p);
std::fill(p, end(), value);
return const_cast<iterator>(first);
}
/// The array data.
T _buffer[SIZE];
};
//*************************************************************************
/// Overloaded swap for etl::array<T, SIZE>
///\param lhs The first array.
///\param rhs The second array.
//*************************************************************************
/// Overloaded swap for etl::array<T, SIZE>
///\param lhs The first array.
///\param rhs The second array.
//*************************************************************************
template <typename T, const size_t SIZE>
void swap(etl::array<T, SIZE> &lhs, etl::array<T, SIZE> &rhs)
{
lhs.swap(rhs);
}
{
lhs.swap(rhs);
}
//*************************************************************************
/// Equal operator.
@ -391,7 +587,7 @@ namespace etl
{
return !(lhs == rhs);
}
//*************************************************************************
/// Less than operator.
///\param lhs The first array.
@ -402,8 +598,8 @@ namespace etl
bool operator <(const etl::array<T, SIZE>& lhs, const etl::array<T, SIZE>& rhs)
{
return std::lexicographical_compare(lhs.cbegin(),
lhs.cend(),
rhs.cbegin(),
lhs.cend(),
rhs.cbegin(),
rhs.cend());
}

View File

@ -44,6 +44,7 @@ SOFTWARE.
#include "log.h"
#include "power.h"
#include "smallest.h"
#include "platform.h"
namespace etl
{
@ -170,6 +171,7 @@ namespace etl
return result;
}
#if ETL_8BIT_SUPPORT
//***************************************************************************
/// Reverse 8 bits.
//***************************************************************************
@ -183,6 +185,7 @@ namespace etl
return value;
}
#endif
//***************************************************************************
/// Reverse 16 bits.
@ -282,6 +285,7 @@ namespace etl
return (value >> 1) ^ value;
}
#if ETL_8BIT_SUPPORT
//***************************************************************************
/// Converts Gray code to binary.
//***************************************************************************
@ -295,6 +299,7 @@ namespace etl
return value;
}
#endif
//***************************************************************************
/// Converts Gray code to binary.
@ -344,6 +349,7 @@ namespace etl
return value;
}
#if ETL_8BIT_SUPPORT
//***************************************************************************
/// Count set bits. 8 bits.
//***************************************************************************
@ -361,6 +367,7 @@ namespace etl
return count;
}
#endif
//***************************************************************************
/// Count set bits. 16 bits.
@ -389,14 +396,10 @@ namespace etl
count_bits(T value)
{
uint32_t count;
static const int S[] = { 1, 2, 4, 8, 16 };
static const uint32_t B[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF };
count = value - ((value >> 1) & B[0]);
count = ((count >> S[1]) & B[1]) + (count & B[1]);
count = ((count >> S[2]) + count) & B[2];
count = ((count >> S[3]) + count) & B[3];
count = ((count >> S[4]) + count) & B[4];
value = value - ((value >> 1) & 0x55555555);
value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
count = ((value + (value >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
return count;
}
@ -422,6 +425,7 @@ namespace etl
return size_t(count);
}
#if ETL_8BIT_SUPPORT
//***************************************************************************
/// Parity. 8bits. 0 = even, 1 = odd
//***************************************************************************
@ -433,6 +437,7 @@ namespace etl
value &= 0x0F;
return (0x6996 >> value) & 1;
}
#endif
//***************************************************************************
/// Parity. 16bits. 0 = even, 1 = odd
@ -555,6 +560,224 @@ namespace etl
return signed_value;
}
#if ETL_8BIT_SUPPORT
//***************************************************************************
/// Count trailing zeros. bit.
/// Uses a binary search.
//***************************************************************************
template <typename T>
typename etl::enable_if<etl::is_same<typename etl::make_unsigned<T>::type, uint8_t>::value, uint_least8_t>::type
count_trailing_zeros(T value)
{
uint_least8_t count;
if (value & 0x1)
{
count = 0;
}
else
{
count = 1;
if ((value & 0xF) == 0)
{
value >>= 4;
count += 4;
}
if ((value & 0x3) == 0)
{
value >>= 2;
count += 2;
}
count -= value & 0x1;
}
return count;
}
#endif
//***************************************************************************
/// Count trailing zeros. 16bit.
/// Uses a binary search.
//***************************************************************************
template <typename T>
typename etl::enable_if<etl::is_same<typename etl::make_unsigned<T>::type, uint16_t>::value, uint_least8_t>::type
count_trailing_zeros(T value)
{
uint_least8_t count;
if (value & 0x1)
{
count = 0;
}
else
{
count = 1;
if ((value & 0xFF) == 0)
{
value >>= 8;
count += 8;
}
if ((value & 0xF) == 0)
{
value >>= 4;
count += 4;
}
if ((value & 0x3) == 0)
{
value >>= 2;
count += 2;
}
count -= value & 0x1;
}
return count;
}
//***************************************************************************
/// Count trailing zeros. 32bit.
/// Uses a binary search.
//***************************************************************************
template <typename T>
typename etl::enable_if<etl::is_same<typename etl::make_unsigned<T>::type, uint32_t>::value, uint_least8_t>::type
count_trailing_zeros(T value)
{
uint_least8_t count;
if (value & 0x1)
{
count = 0;
}
else
{
count = 1;
if ((value & 0xFFFF) == 0)
{
value >>= 16;
count += 16;
}
if ((value & 0xFF) == 0)
{
value >>= 8;
count += 8;
}
if ((value & 0xF) == 0)
{
value >>= 4;
count += 4;
}
if ((value & 0x3) == 0)
{
value >>= 2;
count += 2;
}
count -= value & 0x1;
}
return count;
}
//***************************************************************************
/// Count trailing zeros. 64bit.
/// Uses a binary search.
//***************************************************************************
template <typename T>
typename etl::enable_if<etl::is_same<typename etl::make_unsigned<T>::type, uint64_t>::value, uint_least8_t>::type
count_trailing_zeros(T value)
{
uint_least8_t count;
if (value & 0x1)
{
count = 0;
}
else
{
count = 1;
if ((value & 0xFFFFFFFF) == 0)
{
value >>= 32;
count += 32;
}
if ((value & 0xFFFF) == 0)
{
value >>= 16;
count += 16;
}
if ((value & 0xFF) == 0)
{
value >>= 8;
count += 8;
}
if ((value & 0xF) == 0)
{
value >>= 4;
count += 4;
}
if ((value & 0x3) == 0)
{
value >>= 2;
count += 2;
}
count -= value & 0x1;
}
return count;
}
//***************************************************************************
/// Find the position of the first set bit.
/// Starts from LSB.
//***************************************************************************
template <typename T>
uint_least8_t first_set_bit_position(T value)
{
return count_trailing_zeros(value);
}
//***************************************************************************
/// Find the position of the first clear bit.
/// Starts from LSB.
//***************************************************************************
template <typename T>
uint_least8_t first_clear_bit_position(T value)
{
value = ~value;
return count_trailing_zeros(value);
}
//***************************************************************************
/// Find the position of the first bit that is clear or set.
/// Starts from LSB.
//***************************************************************************
template <typename T>
uint_least8_t first_bit_position(bool state, T value)
{
if (!state)
{
value = ~value;
}
return count_trailing_zeros(value);
}
//***************************************************************************
/// 8 bit binary constants.
//***************************************************************************

81
src/callback.h Normal file
View File

@ -0,0 +1,81 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2015 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_CALLBACK__
#define __ETL_CALLBACK__
namespace etl
{
//***************************************************************************
/// A callback class designed to be multiply inherited by other client classes.
/// The class is parametrised with a callback parameter type and a unique id.
/// The unique id allows multiple callbacks with the same parameter type.
///\tparam TParameter The callback parameter type.
///\tparam ID The unique id for this callback.
//***************************************************************************
template <typename TParameter, const int ID>
class callback
{
private:
// Creates a parameter type unique to this ID.
template <typename T, const int I>
struct parameter
{
parameter(T value)
: value(value)
{
}
typedef T value_type;
T value;
private:
parameter();
};
// Specialisation for void.
template <const int I>
struct parameter<void, I>
{
typedef void value_type;
};
public:
typedef parameter<TParameter, ID> type;
virtual void etl_callback(type p = type()) = 0;
};
}
#endif

View File

@ -44,7 +44,7 @@ SOFTWARE.
//*****************************************************************************
// Define the large character types if necessary.
#ifdef NO_LARGE_CHAR_SUPPORT
#ifdef ETL_NO_LARGE_CHAR_SUPPORT
typedef int16_t char16_t;
typedef int32_t char32_t;
#endif

View File

@ -277,7 +277,7 @@ namespace etl
///\ingroup container
///**************************************************************************
template<typename TValue, const size_t ARRAY_SIZE>
size_t size(TValue(&data)[ARRAY_SIZE])
size_t size(TValue(&)[ARRAY_SIZE])
{
return ARRAY_SIZE;
}

View File

@ -30,6 +30,11 @@ SOFTWARE.
#include <stdint.h>
#include "platform.h"
#include "static_assert.h"
STATIC_ASSERT(ETL_8BIT_SUPPORT, "This file does not currently support targets with no 8bit type");
namespace etl
{
//***************************************************************************

View File

@ -33,6 +33,8 @@ SOFTWARE.
#include "platform.h"
#include "basic_string.h"
#include "ibasic_string.h"
#include "hash.h"
#if defined(ETL_COMPILER_MICROSOFT)
#undef min
@ -40,7 +42,7 @@ SOFTWARE.
namespace etl
{
typedef ibasic_string<char> istring;
typedef etl::ibasic_string<char> istring;
//***************************************************************************
/// A string implementation that uses a fixed size buffer.
@ -151,11 +153,11 @@ namespace etl
{
etl::string<MAX_SIZE_> new_string;
if (position != size())
if (position != this->size())
{
ETL_ASSERT(position < size(), ETL_ERROR(string_out_of_bounds));
ETL_ASSERT(position < this->size(), ETL_ERROR(string_out_of_bounds));
length = std::min(length, size() - position);
length = std::min(length, this->size() - position);
new_string.assign(buffer + position, buffer + position + length);
}
@ -180,6 +182,19 @@ namespace etl
value_type buffer[MAX_SIZE + 1];
};
//*************************************************************************
/// Hash function.
//*************************************************************************
template <>
struct hash<etl::istring>
{
size_t operator()(const etl::istring& text) const
{
return etl::__private_hash__::generic_hash<>(reinterpret_cast<const uint8_t*>(&text[0]),
reinterpret_cast<const uint8_t*>(&text[text.size()]));
}
};
}
#if defined(ETL_COMPILER_MICROSOFT)

View File

@ -116,7 +116,7 @@ namespace etl
REPEATING = 16
};
uint8_t state;
uint_least8_t state;
/// The state count.
uint16_t count;

137
src/debug_count.h Normal file
View File

@ -0,0 +1,137 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2017 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_DEBUG_COUNT__
#define __ETL_DEBUG_COUNT__
#include <stdint.h>
#include <assert.h>
#include "platform.h"
///\defgroup debug_count debug count
///\ingroup utilities
namespace etl
{
//***************************************************************************
/// Used to count instances.
/// Asserts if the count is decremented below zero.
/// Asserts if the count is not zero when destructed.
/// Does nothing in a non-debug build.
///\ingroup reference
//***************************************************************************
class debug_count
{
public:
#if defined(ETL_DEBUG)
inline debug_count()
: count(0)
{
}
inline ~debug_count()
{
assert(count == 0);
}
inline debug_count& operator ++()
{
++count;
return *this;
}
inline debug_count& operator --()
{
--count;
assert(count >= 0);
return *this;
}
inline debug_count& operator +=(int32_t n)
{
count += n;
return *this;
}
inline debug_count& operator -=(int32_t n)
{
count -= n;
return *this;
}
inline operator int32_t()
{
return count;
}
private:
int32_t count;
#else
inline debug_count()
{
}
inline ~debug_count()
{
}
inline debug_count& operator ++()
{
return *this;
}
inline debug_count& operator --()
{
return *this;
}
inline debug_count& operator +=(int32_t /*n*/)
{
return *this;
}
inline debug_count& operator -=(int32_t /*n*/)
{
return *this;
}
inline operator int32_t()
{
return 0;
}
#endif
};
}
#endif

View File

@ -86,6 +86,14 @@ namespace etl
ideque<T>::initialise();
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~deque()
{
ideque<T>::initialise();
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************

View File

@ -54,11 +54,11 @@ namespace etl
native
};
DECLARE_ENUM_TYPE(endian, int)
ENUM_TYPE(little, "little")
ENUM_TYPE(big, "big")
ENUM_TYPE(native, "native")
END_ENUM_TYPE
ETL_DECLARE_ENUM_TYPE(endian, int)
ETL_ENUM_TYPE(little, "little")
ETL_ENUM_TYPE(big, "big")
ETL_ENUM_TYPE(native, "native")
ETL_END_ENUM_TYPE
};
//***************************************************************************
@ -68,7 +68,7 @@ namespace etl
struct endianness
{
endianness()
: ETL_ENDIAN_TEST(0x0011)
: ETL_ENDIAN_TEST(0x0011223344556677)
{
}
@ -79,12 +79,12 @@ namespace etl
operator endian() const
{
return (*reinterpret_cast<const uint8_t*>(&ETL_ENDIAN_TEST) == 0x11) ? endian::little : endian::big;
return (*reinterpret_cast<const uint32_t*>(&ETL_ENDIAN_TEST) == 0x44556677) ? endian::little : endian::big;
}
private:
const uint16_t ETL_ENDIAN_TEST;
const uint64_t ETL_ENDIAN_TEST;
};
}

View File

@ -48,12 +48,12 @@ SOFTWARE.
/// West = 270
/// };
///
/// DECLARE_ENUM_TYPE(CompassDirection, int)
/// ENUM_TYPE(North, "North")
/// ENUM_TYPE(South, "South")
/// ENUM_TYPE(East, "East")
/// ENUM_TYPE(West, "West")
/// END_ENUM_TYPE
/// ETL_DECLARE_ENUM_TYPE(CompassDirection, int)
/// ETL_ENUM_TYPE(North, "North")
/// ETL_ENUM_TYPE(South, "South")
/// ETL_ENUM_TYPE(East, "East")
/// ETL_ENUM_TYPE(West, "West")
/// ETL_END_ENUM_TYPE
/// };
///\endcode
/// <b>Using the enumeration.</b>
@ -72,15 +72,15 @@ SOFTWARE.
///
/// std::cout << "Direction = " << direction.c_str(); // Prints "Direction = North"
///\endcode
/// If a conversion to a string is not required then the 'ENUM_TYPE' declaration may be omitted.
/// If a conversion to a string is not required then the 'ETL_ENUM_TYPE' declaration may be omitted.
/// In that case the c_str() function will return a "?". This will also be the case for any
/// enumeration value that does not have an ENUM_TYPE entry.
/// enumeration value that does not have an ETL_ENUM_TYPE entry.
///\ingroup utilities
//*****************************************************************************
// The declaration of the member functions and the first section of the 'c_str' function.
//*****************************************************************************
#define DECLARE_ENUM_TYPE(TypeName, ValueType) \
#define ETL_DECLARE_ENUM_TYPE(TypeName, ValueType) \
typedef ValueType value_type; \
TypeName() {} \
TypeName(const TypeName &other) : value(other.value) {} \
@ -98,14 +98,14 @@ SOFTWARE.
//*****************************************************************************
// A case in the 'c_str' function's switch statement.
//*****************************************************************************
#define ENUM_TYPE(value, name) \
#define ETL_ENUM_TYPE(value, name) \
case value: \
return name; \
//*****************************************************************************
// The final section of the 'c_str' function and the value declaration.
//*****************************************************************************
#define END_ENUM_TYPE \
#define ETL_END_ENUM_TYPE \
default: \
return "?"; \
} \

View File

@ -35,7 +35,7 @@ SOFTWARE.
/// The base class for all ETL exceptions.
///\ingroup utilities
namespace etl
namespace etl
{
//***************************************************************************
///\ingroup exception
@ -66,6 +66,7 @@ namespace etl
: reason(reason),
line(line)
{
(void)file;
}
#endif

View File

@ -8,7 +8,7 @@
8 map_base
9 multimap_base
10 multiset_base
11 pool_base
11 ipool
12 ipriority_queue
13 queue_base
14 set_base
@ -23,4 +23,7 @@
23 iunordered_set, iunordered_multiset
24 variant
25 iunordered_multimap
26 iunordered_multiset
26 iunordered_multiset
27 string_base
28 intrusive_stack
29 intrusive_queue

View File

@ -137,7 +137,7 @@ namespace etl
//***************************************************************************
/// += operator.
//***************************************************************************
fixed_iterator& operator +=(typename std::iterator_traits<TIterator>::difference_type offset)
fixed_iterator& operator +=(typename std::iterator_traits<TIterator>::difference_type /*offset*/)
{
return *this;
}
@ -145,7 +145,7 @@ namespace etl
//***************************************************************************
/// -= operator.
//***************************************************************************
fixed_iterator& operator -=(typename std::iterator_traits<TIterator>::difference_type offset)
fixed_iterator& operator -=(typename std::iterator_traits<TIterator>::difference_type /*offset*/)
{
return *this;
}
@ -179,7 +179,7 @@ namespace etl
//*****************************************************************************
template <typename TIterator>
etl::fixed_iterator<TIterator>& operator +(etl::fixed_iterator<TIterator>& lhs,
typename std::iterator_traits<TIterator>::difference_type rhs)
typename std::iterator_traits<TIterator>::difference_type /*rhs*/)
{
return lhs;
}
@ -189,7 +189,7 @@ etl::fixed_iterator<TIterator>& operator +(etl::fixed_iterator<TIterator>& lhs,
//*****************************************************************************
template <typename TIterator>
etl::fixed_iterator<TIterator>& operator -(etl::fixed_iterator<TIterator>& lhs,
typename std::iterator_traits<TIterator>::difference_type rhs)
typename std::iterator_traits<TIterator>::difference_type /*rhs*/)
{
return lhs;
}

View File

@ -37,18 +37,18 @@ SOFTWARE.
#include "iflat_map.h"
#include "vector.h"
#include "pool.h"
//*****************************************************************************
///\defgroup flat_map flat_map
/// A flat_map with the capacity defined at compile time.
/// Has insertion of O(N) and flat_map of O(logN)
/// Duplicate entries and not allowed.
/// Duplicate entries are not allowed.
///\ingroup containers
//*****************************************************************************
namespace etl
{
template <typename TKey, typename TValue, const size_t MAX_SIZE_, typename TCompare = std::less<TKey> >
//***************************************************************************
/// A flat_map implementation that uses a fixed size buffer.
///\tparam TKey The key type.
@ -57,6 +57,7 @@ namespace etl
///\tparam MAX_SIZE_ The maximum number of elements that can be stored.
///\ingroup flat_map
//***************************************************************************
template <typename TKey, typename TValue, const size_t MAX_SIZE_, typename TCompare = std::less<TKey> >
class flat_map : public iflat_map<TKey, TValue, TCompare>
{
public:
@ -67,7 +68,7 @@ namespace etl
/// Constructor.
//*************************************************************************
flat_map()
: iflat_map<TKey, TValue, TCompare>(buffer)
: iflat_map<TKey, TValue, TCompare>(lookup, storage)
{
}
@ -75,7 +76,7 @@ namespace etl
/// Copy constructor.
//*************************************************************************
flat_map(const flat_map& other)
: iflat_map<TKey, TValue, TCompare>(buffer)
: iflat_map<TKey, TValue, TCompare>(lookup, storage)
{
iflat_map<TKey, TValue, TCompare>::assign(other.cbegin(), other.cend());
}
@ -88,11 +89,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
flat_map(TIterator first, TIterator last)
: iflat_map<TKey, TValue, TCompare>(buffer)
: iflat_map<TKey, TValue, TCompare>(lookup, storage)
{
iflat_map<TKey, TValue, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~flat_map()
{
iflat_map<TKey, TValue, TCompare>::clear();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -108,7 +117,13 @@ namespace etl
private:
etl::vector<typename iflat_map<TKey, TValue, TCompare>::value_type, MAX_SIZE> buffer; ///<The vector that stores the elements.
typedef typename iflat_map<TKey, TValue, TCompare>::value_type node_t;
// The pool of nodes.
etl::pool<node_t, MAX_SIZE> storage;
// The vector that stores pointers to the nodes.
etl::vector<node_t*, MAX_SIZE> lookup;
};
}

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include "iflat_multimap.h"
#include "vector.h"
#include "pool.h"
//*****************************************************************************
///\defgroup flat_multimap flat_multimap
@ -67,7 +68,7 @@ namespace etl
/// Constructor.
//*************************************************************************
flat_multimap()
: iflat_multimap<TKey, TValue, TCompare>(buffer)
: iflat_multimap<TKey, TValue, TCompare>(lookup, storage)
{
}
@ -75,7 +76,7 @@ namespace etl
/// Copy constructor.
//*************************************************************************
flat_multimap(const flat_multimap& other)
: iflat_multimap<TKey, TValue, TCompare>(buffer)
: iflat_multimap<TKey, TValue, TCompare>(lookup, storage)
{
iflat_multimap<TKey, TValue, TCompare>::assign(other.cbegin(), other.cend());
}
@ -88,11 +89,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
flat_multimap(TIterator first, TIterator last)
: iflat_multimap<TKey, TValue, TCompare>(buffer)
: iflat_multimap<TKey, TValue, TCompare>(lookup, storage)
{
iflat_multimap<TKey, TValue, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~flat_multimap()
{
iflat_multimap<TKey, TValue, TCompare>::clear();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -108,7 +117,13 @@ namespace etl
private:
etl::vector<typename iflat_multimap<TKey, TValue, TCompare>::value_type, MAX_SIZE> buffer; ///<The vector that stores the elements.
typedef typename iflat_multimap<TKey, TValue, TCompare>::value_type node_t;
// The pool of nodes.
etl::pool<node_t, MAX_SIZE> storage;
// The vector that stores pointers to the nodes.
etl::vector<node_t*, MAX_SIZE> lookup;
};
}

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include "iflat_multiset.h"
#include "vector.h"
#include "pool.h"
//*****************************************************************************
///\defgroup flat_multiset flat_multiset
@ -66,7 +67,7 @@ namespace etl
/// Constructor.
//*************************************************************************
flat_multiset()
: iflat_multiset<T, TCompare>(buffer)
: iflat_multiset<T, TCompare>(lookup, storage)
{
}
@ -74,7 +75,7 @@ namespace etl
/// Copy constructor.
//*************************************************************************
flat_multiset(const flat_multiset& other)
: iflat_multiset<T, TCompare>(buffer)
: iflat_multiset<T, TCompare>(lookup, storage)
{
iflat_multiset<T, TCompare>::assign(other.cbegin(), other.cend());
}
@ -87,11 +88,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
flat_multiset(TIterator first, TIterator last)
: iflat_multiset<T, TCompare>(buffer)
: iflat_multiset<T, TCompare>(lookup, storage)
{
iflat_multiset<T, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~flat_multiset()
{
iflat_multiset<T, TCompare>::clear();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -107,7 +116,13 @@ namespace etl
private:
etl::vector<T, MAX_SIZE> buffer; ///<The vector that stores the elements.
typedef typename iflat_multiset<T, TCompare>::value_type node_t;
// The pool of nodes.
etl::pool<node_t, MAX_SIZE> storage;
// The vector that stores pointers to the nodes.
etl::vector<node_t*, MAX_SIZE> lookup;
};
}

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include "iflat_set.h"
#include "vector.h"
#include "pool.h"
//*****************************************************************************
///\defgroup flat_set flat_set
@ -66,7 +67,7 @@ namespace etl
/// Constructor.
//*************************************************************************
flat_set()
: iflat_set<T, TCompare>(buffer)
: iflat_set<T, TCompare>(lookup, storage)
{
}
@ -74,7 +75,7 @@ namespace etl
/// Copy constructor.
//*************************************************************************
flat_set(const flat_set& other)
: iflat_set<T, TCompare>(buffer)
: iflat_set<T, TCompare>(lookup, storage)
{
iflat_set<T, TCompare>::assign(other.cbegin(), other.cend());
}
@ -87,11 +88,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
flat_set(TIterator first, TIterator last)
: iflat_set<T, TCompare>(buffer)
: iflat_set<T, TCompare>(lookup, storage)
{
iflat_set<T, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~flat_set()
{
iflat_set<T, TCompare>::clear();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -107,7 +116,13 @@ namespace etl
private:
etl::vector<T, MAX_SIZE> buffer; ///<The vector that stores the elements.
typedef typename iflat_set<T, TCompare>::value_type node_t;
// The pool of nodes.
etl::pool<node_t, MAX_SIZE> storage;
// The vector that stores pointers to the nodes.
etl::vector<node_t*, MAX_SIZE> lookup;
};
}

View File

@ -37,6 +37,8 @@ SOFTWARE.
#include "static_assert.h"
#include "type_traits.h"
#include "ihash.h"
#include "frame_check_sequence.h"
#if defined(ETL_COMPILER_KEIL)
#pragma diag_suppress 1300
@ -47,22 +49,49 @@ SOFTWARE.
namespace etl
{
//***************************************************************************
/// fnv_1 policy.
/// Calculates FNV1.
//***************************************************************************
struct fnv_1_policy_64
{
typedef uint64_t value_type;
inline uint64_t initial() const
{
return OFFSET_BASIS;
}
inline uint64_t add(uint64_t hash, uint8_t value) const
{
hash *= PRIME;
hash ^= value;
return hash;
}
inline uint64_t final(uint64_t hash) const
{
return hash;
}
static const uint64_t OFFSET_BASIS = 0xCBF29CE484222325;
static const uint64_t PRIME = 0x00000100000001b3;
};
//***************************************************************************
/// Calculates the fnv_1_64 hash.
///\ingroup fnv_1_64
//***************************************************************************
class fnv_1_64
class fnv_1_64 : public etl::frame_check_sequence<fnv_1_policy_64>
{
public:
typedef uint64_t value_type;
//*************************************************************************
/// Default constructor.
//*************************************************************************
fnv_1_64()
{
reset();
this->reset();
}
//*************************************************************************
@ -73,70 +102,36 @@ namespace etl
template<typename TIterator>
fnv_1_64(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
this->reset();
this->add(begin, end);
}
};
reset();
while (begin != end)
//***************************************************************************
/// fnv_1a policy.
/// Calculates FNV1A.
//***************************************************************************
struct fnv_1a_policy_64
{
typedef uint64_t value_type;
inline uint64_t initial() const
{
hash *= PRIME;
hash ^= *begin++;
}
return OFFSET_BASIS;
}
//*************************************************************************
/// Resets the CRC to the initial state.
//*************************************************************************
void reset()
inline uint64_t add(uint64_t hash, uint8_t value) const
{
hash = OFFSET_BASIS;
}
//*************************************************************************
/// Adds a range.
/// \param begin
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
while (begin != end)
{
hash *= PRIME;
hash ^= *begin++;
}
}
//*************************************************************************
/// \param value The char to add to the fnv_1_64.
//*************************************************************************
void add(uint8_t value)
{
hash *= PRIME;
hash ^= value;
}
//*************************************************************************
/// Gets the fnv_1_64 value.
//*************************************************************************
value_type value() const
{
hash *= PRIME;
return hash;
}
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
inline uint64_t final(uint64_t hash) const
{
return hash;
}
private:
value_type hash;
static const uint64_t OFFSET_BASIS = 0xCBF29CE484222325;
static const uint64_t PRIME = 0x00000100000001b3;
};
@ -145,18 +140,16 @@ namespace etl
/// Calculates the fnv_1a_64 hash.
///\ingroup fnv_1a_64
//***************************************************************************
class fnv_1a_64
class fnv_1a_64 : public etl::frame_check_sequence<fnv_1a_policy_64>
{
public:
typedef uint64_t value_type;
//*************************************************************************
/// Default constructor.
//*************************************************************************
fnv_1a_64()
{
reset();
this->reset();
}
//*************************************************************************
@ -167,90 +160,54 @@ namespace etl
template<typename TIterator>
fnv_1a_64(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
reset();
while (begin != end)
{
hash ^= *begin++;
hash *= PRIME;
}
this->reset();
this->add(begin, end);
}
};
//*************************************************************************
/// Resets the CRC to the initial state.
//*************************************************************************
void reset()
//***************************************************************************
/// fnv_1 policy.
/// Calculates FNV1.
//***************************************************************************
struct fnv_1_policy_32
{
hash = OFFSET_BASIS;
}
//*************************************************************************
/// Adds a range.
/// \param begin
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
typedef uint32_t value_type;
while (begin != end)
inline uint32_t initial() const
{
hash ^= *begin++;
hash *= PRIME;
}
return OFFSET_BASIS;
}
//*************************************************************************
/// \param value The char to add to the fnv_1a_64.
//*************************************************************************
void add(uint8_t value)
inline uint32_t add(uint32_t hash, uint8_t value) const
{
hash ^= value;
hash *= PRIME;
hash ^= value;
return hash;
}
//*************************************************************************
/// Gets the fnv_1a_64 value.
//*************************************************************************
value_type value() const
inline uint32_t final(uint32_t hash) const
{
return hash;
}
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
{
return hash;
}
private:
value_type hash;
static const uint64_t OFFSET_BASIS = 0xCBF29CE484222325;
static const uint64_t PRIME = 0x00000100000001b3;
static const uint32_t OFFSET_BASIS = 0x811C9DC5;
static const uint32_t PRIME = 0x01000193;
};
//***************************************************************************
/// Calculates the fnv_1_32 hash.
///\ingroup fnv_1_32
//***************************************************************************
class fnv_1_32
class fnv_1_32 : public etl::frame_check_sequence<fnv_1_policy_32>
{
public:
typedef uint32_t value_type;
//*************************************************************************
/// Default constructor.
//*************************************************************************
fnv_1_32()
{
reset();
this->reset();
}
//*************************************************************************
@ -261,70 +218,36 @@ namespace etl
template<typename TIterator>
fnv_1_32(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
this->reset();
this->add(begin, end);
}
};
reset();
while (begin != end)
//***************************************************************************
/// fnv_1a policy.
/// Calculates FNV1A.
//***************************************************************************
struct fnv_1a_policy_32
{
typedef uint32_t value_type;
inline uint32_t initial() const
{
hash *= PRIME;
hash ^= *begin++;
}
return OFFSET_BASIS;
}
//*************************************************************************
/// Resets the CRC to the initial state.
//*************************************************************************
void reset()
inline uint32_t add(uint32_t hash, uint8_t value) const
{
hash = OFFSET_BASIS;
}
//*************************************************************************
/// Adds a range.
/// \param begin
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
while (begin != end)
{
hash *= PRIME;
hash ^= *begin++;
}
}
//*************************************************************************
/// \param value The char to add to the fnv_1_32.
//*************************************************************************
void add(uint8_t value)
{
hash *= PRIME;
hash ^= value;
}
//*************************************************************************
/// Gets the fnv_1_32 value.
//*************************************************************************
value_type value() const
{
hash *= PRIME;
return hash;
}
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
inline uint32_t final(uint32_t hash) const
{
return hash;
}
private:
value_type hash;
static const uint32_t OFFSET_BASIS = 0x811C9DC5;
static const uint32_t PRIME = 0x01000193;
};
@ -333,18 +256,16 @@ namespace etl
/// Calculates the fnv_1a_32 hash.
///\ingroup fnv_1a_32
//***************************************************************************
class fnv_1a_32
class fnv_1a_32 : public etl::frame_check_sequence<fnv_1a_policy_32>
{
public:
typedef uint32_t value_type;
//*************************************************************************
/// Default constructor.
//*************************************************************************
fnv_1a_32()
{
reset();
this->reset();
}
//*************************************************************************
@ -355,72 +276,9 @@ namespace etl
template<typename TIterator>
fnv_1a_32(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
reset();
while (begin != end)
{
hash ^= *begin++;
hash *= PRIME;
}
this->reset();
this->add(begin, end);
}
//*************************************************************************
/// Resets the CRC to the initial state.
//*************************************************************************
void reset()
{
hash = OFFSET_BASIS;
}
//*************************************************************************
/// Adds a range.
/// \param begin
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
while (begin != end)
{
hash ^= *begin++;
hash *= PRIME;
}
}
//*************************************************************************
/// \param value The char to add to the fnv_1a_32.
//*************************************************************************
void add(uint8_t value)
{
hash ^= value;
hash *= PRIME;
}
//*************************************************************************
/// Gets the fnv_1a_32 value.
//*************************************************************************
value_type value() const
{
return hash;
}
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
{
return hash;
}
private:
value_type hash;
static const uint32_t OFFSET_BASIS = 0x811C9DC5;
static const uint32_t PRIME = 0x01000193;
};
}

View File

@ -89,7 +89,7 @@ namespace etl
forward_list(const forward_list& other)
: iforward_list<T>(node_pool, MAX_SIZE)
{
iforward_list<T>::assign(other.cbegin(), other.cend());
iforward_list<T>::assign(other.cbegin(), other.cend());
}
//*************************************************************************
@ -102,6 +102,14 @@ namespace etl
iforward_list<T>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~forward_list()
{
iforward_list<T>::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -118,7 +126,7 @@ namespace etl
private:
/// The pool of nodes used in the list.
etl::pool<typename iforward_list<T>::Data_Node, MAX_SIZE> node_pool;
etl::pool<typename iforward_list<T>::data_node_t, MAX_SIZE> node_pool;
};
}

View File

@ -29,10 +29,13 @@ SOFTWARE.
#include <stdint.h>
#include "platform.h"
#include "static_assert.h"
#include "type_traits.h"
#include "binary.h"
STATIC_ASSERT(ETL_8BIT_SUPPORT, "This file does not currently support targets with no 8bit type");
///\defgroup frame_check_sequence Frame check sequence calculation
///\ingroup maths
@ -50,9 +53,9 @@ namespace etl
typedef TPolicy policy_type;
typedef typename policy_type::value_type value_type;
STATIC_ASSERT(etl::is_unsigned<value_type>::value, "Signed frame check type not supported");
//*************************************************************************
/// Default constructor.
//*************************************************************************
@ -110,7 +113,7 @@ namespace etl
//*************************************************************************
/// Gets the FCS value.
//*************************************************************************
value_type value() const
value_type value()
{
return policy.final(frame_check);
}
@ -118,7 +121,7 @@ namespace etl
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
operator value_type ()
{
return policy.final(frame_check);
}

View File

@ -200,8 +200,8 @@ namespace etl
/// Constructor.
///\param p_function Pointer to the function.
//*************************************************************************
function(void(*p_function)(void))
: p_function(p_function)
function(void(*p_function_)(void))
: p_function(p_function_)
{
}

View File

@ -32,6 +32,7 @@ SOFTWARE.
#define __ETL_HASH__
#include <stdint.h>
#include <stdlib.h>
// The default hash calculation.
#include "fnv_1.h"
@ -49,9 +50,9 @@ namespace etl
/// Hash to use when size_t is 16 bits.
/// T is always expected to be size_t.
//*************************************************************************
template <typename T>
template <typename T = size_t>
typename enable_if<sizeof(T) == sizeof(uint16_t), size_t>::type
generic_hash(uint8_t* begin, uint8_t* end)
generic_hash(const uint8_t* begin, const uint8_t* end)
{
uint32_t h = fnv_1a_32(begin, end);
@ -62,9 +63,9 @@ namespace etl
/// Hash to use when size_t is 32 bits.
/// T is always expected to be size_t.
//*************************************************************************
template <typename T>
template <typename T = size_t>
typename enable_if<sizeof(T) == sizeof(uint32_t), size_t>::type
generic_hash(uint8_t* begin, uint8_t* end)
generic_hash(const uint8_t* begin, const uint8_t* end)
{
return fnv_1a_32(begin, end);
}
@ -73,9 +74,9 @@ namespace etl
/// Hash to use when size_t is 64 bits.
/// T is always expected to be size_t.
//*************************************************************************
template <typename T>
template <typename T = size_t>
typename enable_if<sizeof(T) == sizeof(uint64_t), size_t>::type
generic_hash(uint8_t* begin, uint8_t* end)
generic_hash(const uint8_t* begin, const uint8_t* end)
{
return fnv_1a_64(begin, end);
}
@ -229,9 +230,9 @@ namespace etl
template<>
struct hash<long>
{
// If it fits into a size_t.
size_t operator ()(long v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) >= sizeof(v))
{
return static_cast<size_t>(v);
@ -251,9 +252,9 @@ namespace etl
template<>
struct hash<long long>
{
// If it fits into a size_t.
size_t operator ()(long long v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) >= sizeof(v))
{
return static_cast<size_t>(v);
@ -273,9 +274,9 @@ namespace etl
template<>
struct hash<unsigned long>
{
// If it fits into a size_t.
size_t operator ()(unsigned long v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) >= sizeof(v))
{
return static_cast<size_t>(v);
@ -295,9 +296,9 @@ namespace etl
template<>
struct hash<unsigned long long>
{
// If it fits into a size_t.
size_t operator ()(unsigned long long v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) >= sizeof(v))
{
return static_cast<size_t>(v);
@ -317,12 +318,20 @@ namespace etl
template<>
struct hash<float>
{
// If it's the same size as a size_t.
size_t operator ()(float v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) == sizeof(v))
{
return *reinterpret_cast<size_t*>(&v);
union
{
size_t s;
float v;
} u;
u.v = v;
return u.s;
}
else
{
@ -339,12 +348,20 @@ namespace etl
template<>
struct hash<double>
{
// If it's the same size as a size_t.
size_t operator ()(double v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) == sizeof(v))
{
return *reinterpret_cast<size_t*>(&v);
union
{
size_t s;
double v;
} u;
u.v = v;
return u.s;
}
else
{
@ -361,12 +378,20 @@ namespace etl
template<>
struct hash<long double>
{
// If it's the same size as a size_t.
size_t operator ()(long double v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) == sizeof(v))
{
return *reinterpret_cast<size_t*>(&v);
union
{
size_t s;
long double v;
} u;
u.v = v;
return u.s;
}
else
{
@ -385,9 +410,18 @@ namespace etl
{
size_t operator ()(const T* v) const
{
// If it's the same size as a size_t.
if (sizeof(size_t) == sizeof(T*))
{
return reinterpret_cast<size_t>(v);
union
{
size_t s;
const T* v;
} u;
u.v = v;
return u.s;
}
else
{

View File

@ -36,7 +36,7 @@ SOFTWARE.
#include <algorithm>
#include <functional>
#include <stddef.h>
#include <cstring>
#include <string.h>
#include "private/string_base.h"
#include "platform.h"
@ -148,7 +148,7 @@ namespace etl
//*********************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(end());
return reverse_iterator(end());
}
//*********************************************************************
@ -157,7 +157,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
return const_reverse_iterator(end());
}
//*********************************************************************
@ -184,7 +184,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(cend());
return const_reverse_iterator(cend());
}
//*********************************************************************
@ -193,7 +193,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(cbegin());
return const_reverse_iterator(cbegin());
}
//*********************************************************************
@ -400,7 +400,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(string_iterator));
#endif
@ -464,10 +464,11 @@ namespace etl
//*************************************************************************
void pop_back()
{
if (current_size > 0)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(string_empty));
#endif
p_buffer[--current_size] = 0;
}
}
//*********************************************************************
@ -892,7 +893,7 @@ namespace etl
//*********************************************************************
size_t find(const_pointer s, size_t pos = 0) const
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
if ((pos + etl::strlen(s)) > size())
{
return npos;
@ -919,7 +920,7 @@ namespace etl
//*********************************************************************
size_t find(const_pointer s, size_t pos, size_t n) const
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
if ((pos + etl::strlen(s) - n) > size())
{
return npos;

View File

@ -85,7 +85,7 @@ namespace etl
// The type used for each element in the array.
#if !defined(ETL_BITSET_ELEMENT_TYPE)
typedef uint8_t element_t;
typedef uint_least8_t element_t;
#else
typedef ETL_BITSET_ELEMENT_TYPE element_t;
#endif

View File

@ -295,7 +295,7 @@ namespace etl
//***************************************************
const_iterator& operator ++()
{
index = (index == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1;
index = (static_cast<size_t>(index) == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1;
return *this;
}
@ -331,7 +331,7 @@ namespace etl
if (offset > 0)
{
index -= offset;
index = (index < 0) ? index + p_deque->BUFFER_SIZE : index;
index = (index < 0) ? static_cast<size_t>(index) + p_deque->BUFFER_SIZE : index;
}
else if (offset < 0)
{
@ -1251,13 +1251,10 @@ namespace etl
//*********************************************************************
void create_element_front()
{
if (!empty())
{
--_begin;
}
new(&(*_begin)) T();
--_begin;
::new (&(*_begin)) T();
++current_size;
++construct_count;
}
//*********************************************************************
@ -1286,9 +1283,10 @@ namespace etl
do
{
new(&(*item++)) T(*from);
::new (&(*item++)) T(*from);
++from;
++current_size;
++construct_count;
} while (n-- != 0);
}
@ -1297,9 +1295,10 @@ namespace etl
//*********************************************************************
void create_element_back()
{
new(&(*_end)) T();
::new (&(*_end)) T();
++_end;
++current_size;
++construct_count;
}
//*********************************************************************
@ -1308,8 +1307,9 @@ namespace etl
void create_element_front(parameter_t value)
{
--_begin;
new(&(*_begin)) T(value);
::new (&(*_begin)) T(value);
++current_size;
++construct_count;
}
//*********************************************************************
@ -1317,9 +1317,10 @@ namespace etl
//*********************************************************************
void create_element_back(parameter_t value)
{
new(&(*_end)) T(value);
::new (&(*_end)) T(value);
++_end;
++current_size;
++construct_count;
}
//*********************************************************************
@ -1329,6 +1330,7 @@ namespace etl
{
(*_begin).~T();
--current_size;
--construct_count;
++_begin;
}
@ -1340,6 +1342,7 @@ namespace etl
--_end;
(*_end).~T();
--current_size;
--construct_count;
}
//*************************************************************************

View File

@ -38,10 +38,12 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "private/flat_map_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "ivector.h"
#include "ipool.h"
#include "error_handler.h"
namespace etl
@ -60,22 +62,229 @@ namespace etl
private:
typedef etl::ivector<value_type> buffer_t;
typedef etl::ivector<value_type*> lookup_t;
typedef etl::ipool storage_t;
public:
typedef TKey key_type;
typedef TMapped mapped_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef typename buffer_t::iterator iterator;
typedef typename buffer_t::const_iterator const_iterator;
typedef typename buffer_t::reverse_iterator reverse_iterator;
typedef typename buffer_t::const_reverse_iterator const_reverse_iterator;
typedef size_t size_type;
typedef TKey key_type;
typedef TMapped mapped_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
//*************************************************************************
class iterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
{
public:
friend class iflat_map;
iterator()
{
}
iterator(typename lookup_t::iterator ilookup)
: ilookup(ilookup)
{
}
iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
iterator& operator ++()
{
++ilookup;
return *this;
}
iterator operator ++(int)
{
iterator temp(*this);
++ilookup;
return temp;
}
iterator& operator --()
{
--ilookup;
return *this;
}
iterator operator --(int)
{
iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return &(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::iterator ilookup;
};
//*************************************************************************
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const value_type>
{
public:
friend class iflat_map;
const_iterator()
{
}
const_iterator(typename lookup_t::const_iterator ilookup)
: ilookup(ilookup)
{
}
const_iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator(const const_iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator =(const const_iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator ++()
{
++ilookup;
return *this;
}
const_iterator operator ++(int)
{
const_iterator temp(*this);
++ilookup;
return temp;
}
const_iterator& operator --()
{
--ilookup;
return *this;
}
const_iterator operator --(int)
{
const_iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return etl::addressof(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::const_iterator ilookup;
};
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
protected:
@ -110,7 +319,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return buffer.begin();
return iterator(lookup.begin());
}
//*********************************************************************
@ -119,7 +328,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return buffer.begin();
return const_iterator(lookup.begin());
}
//*********************************************************************
@ -128,7 +337,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return buffer.end();
return iterator(lookup.end());
}
//*********************************************************************
@ -137,7 +346,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return buffer.end();
return const_iterator(lookup.end());
}
//*********************************************************************
@ -146,7 +355,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return buffer.cbegin();
return const_iterator(lookup.cbegin());
}
//*********************************************************************
@ -155,7 +364,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return buffer.cend();
return const_iterator(lookup.cend());
}
//*********************************************************************
@ -164,7 +373,7 @@ namespace etl
//*********************************************************************
reverse_iterator rbegin()
{
return buffer.rbegin();
return reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -173,7 +382,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rbegin() const
{
return buffer.rbegin();
return reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -182,7 +391,7 @@ namespace etl
//*********************************************************************
reverse_iterator rend()
{
return buffer.rend();
return reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -191,7 +400,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rend() const
{
return buffer.rend();
return const_reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -200,7 +409,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crbegin() const
{
return buffer.crbegin();
return const_reverse_iterator(lookup.crbegin());
}
//*********************************************************************
@ -209,7 +418,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crend() const
{
return buffer.crend();
return const_reverse_iterator(lookup.crend());
}
//*********************************************************************
@ -223,9 +432,9 @@ namespace etl
if (i_element == end())
{
// Doesn't exist, so create a new one.
value_type value(key, mapped_type());
i_element = insert(value).first;
std::pair<iterator, bool> result = insert_at(i_element, value_type(key, mapped_type()));
i_element = result.first;
}
return i_element->second;
@ -254,7 +463,7 @@ namespace etl
//*********************************************************************
const mapped_type& at(key_value_parameter_t key) const
{
typename buffer_t::const_iterator i_element = lower_bound(key);
typename const_iterator i_element = lower_bound(key);
ETL_ASSERT(i_element != end(), ETL_ERROR(flat_map_out_of_bounds));
@ -271,7 +480,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_map_full));
#endif
@ -291,33 +500,9 @@ namespace etl
//*********************************************************************
std::pair<iterator, bool> insert(const value_type& value)
{
std::pair<iterator, bool> result(end(), false);
iterator i_element = lower_bound(value.first);
if (i_element == end())
{
// At the end.
ETL_ASSERT(!buffer.full(), ETL_ERROR(flat_map_full));
buffer.push_back(value);
result.first = end() - 1;
result.second = true;
}
else
{
// Not at the end.
// Existing element?
if (value.first != i_element->first)
{
// A new one.
ETL_ASSERT(!buffer.full(), ETL_ERROR(flat_map_full));
buffer.insert(i_element, value);
result.first = i_element;
result.second = true;
}
}
return result;
return insert_at(i_element, value);
}
//*********************************************************************
@ -362,7 +547,10 @@ namespace etl
}
else
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
return 1;
}
}
@ -373,7 +561,10 @@ namespace etl
//*********************************************************************
void erase(iterator i_element)
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
}
//*********************************************************************
@ -385,7 +576,17 @@ namespace etl
//*********************************************************************
void erase(iterator first, iterator last)
{
buffer.erase(first, last);
iterator itr = first;
while (itr != last)
{
itr->~value_type();
storage.release(etl::addressof(*itr));
++itr;
--construct_count;
}
lookup.erase(first.ilookup, last.ilookup);
}
//*************************************************************************
@ -393,7 +594,7 @@ namespace etl
//*************************************************************************
void clear()
{
buffer.clear();
erase(begin(), end());
}
//*********************************************************************
@ -531,23 +732,120 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the flat_map.
///\return The current size of the flat_map.
//*************************************************************************
size_type size() const
{
return lookup.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_map.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return lookup.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_map.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return lookup.full();
}
//*************************************************************************
/// Returns the capacity of the flat_map.
///\return The capacity of the flat_map.
//*************************************************************************
size_type capacity() const
{
return lookup.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_map.
///\return The maximum size of the flat_map.
//*************************************************************************
size_type max_size() const
{
return lookup.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return lookup.available();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
iflat_map(buffer_t& buffer)
: flat_map_base(buffer),
buffer(buffer)
iflat_map(lookup_t& lookup_, storage_t& storage_)
: lookup(lookup_),
storage(storage_)
{
}
private:
//*********************************************************************
/// Inserts a value to the flat_map.
///\param i_element The place to insert.
///\param value The value to insert.
//*********************************************************************
std::pair<iterator, bool> insert_at(iterator i_element, const value_type& value)
{
std::pair<iterator, bool> result(end(), false);
if (i_element == end())
{
// At the end.
ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_map_full));
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.push_back(pvalue);
result.first = --end();
result.second = true;
++construct_count;
}
else
{
// Not at the end.
result.first = i_element;
// Existing element?
if (value.first != i_element->first)
{
// A new one.
ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_map_full));
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.insert(i_element.ilookup, pvalue);
result.second = true;
++construct_count;
}
}
return result;
}
// Disable copy construction.
iflat_map(const iflat_map&);
buffer_t& buffer;
lookup_t& lookup;
storage_t& storage;
};
//***************************************************************************

View File

@ -38,11 +38,13 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "private/flat_multimap_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "ivector.h"
#include "error_handler.h"
#include "ipool.h"
namespace etl
{
@ -60,22 +62,229 @@ namespace etl
private:
typedef etl::ivector<value_type> buffer_t;
typedef etl::ivector<value_type*> lookup_t;
typedef etl::ipool storage_t;
public:
typedef TKey key_type;
typedef TMapped mapped_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef typename buffer_t::iterator iterator;
typedef typename buffer_t::const_iterator const_iterator;
typedef typename buffer_t::reverse_iterator reverse_iterator;
typedef typename buffer_t::const_reverse_iterator const_reverse_iterator;
typedef size_t size_type;
typedef TKey key_type;
typedef TMapped mapped_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
//*************************************************************************
class iterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
{
public:
friend class iflat_multimap;
iterator()
{
}
iterator(typename lookup_t::iterator ilookup)
: ilookup(ilookup)
{
}
iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
iterator& operator ++()
{
++ilookup;
return *this;
}
iterator operator ++(int)
{
iterator temp(*this);
++ilookup;
return temp;
}
iterator& operator --()
{
--ilookup;
return *this;
}
iterator operator --(int)
{
iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return &(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::iterator ilookup;
};
//*************************************************************************
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const value_type>
{
public:
friend class iflat_multimap;
const_iterator()
{
}
const_iterator(typename lookup_t::const_iterator ilookup)
: ilookup(ilookup)
{
}
const_iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator(const const_iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator =(const const_iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator ++()
{
++ilookup;
return *this;
}
const_iterator operator ++(int)
{
const_iterator temp(*this);
++ilookup;
return temp;
}
const_iterator& operator --()
{
--ilookup;
return *this;
}
const_iterator operator --(int)
{
const_iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return etl::addressof(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::const_iterator ilookup;
};
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
protected:
@ -110,7 +319,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return buffer.begin();
return iterator(lookup.begin());
}
//*********************************************************************
@ -119,7 +328,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return buffer.begin();
return const_iterator(lookup.begin());
}
//*********************************************************************
@ -128,7 +337,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return buffer.end();
return iterator(lookup.end());
}
//*********************************************************************
@ -137,7 +346,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return buffer.end();
return const_iterator(lookup.end());
}
//*********************************************************************
@ -146,7 +355,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return buffer.cbegin();
return const_iterator(lookup.cbegin());
}
//*********************************************************************
@ -155,7 +364,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return buffer.cend();
return const_iterator(lookup.cend());
}
//*********************************************************************
@ -164,7 +373,7 @@ namespace etl
//*********************************************************************
reverse_iterator rbegin()
{
return buffer.rbegin();
return reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -173,7 +382,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rbegin() const
{
return buffer.rbegin();
return const_reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -182,7 +391,7 @@ namespace etl
//*********************************************************************
reverse_iterator rend()
{
return buffer.rend();
return reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -191,7 +400,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rend() const
{
return buffer.rend();
return const_reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -200,7 +409,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crbegin() const
{
return buffer.crbegin();
return const_reverse_iterator(lookup.crbegin());
}
//*********************************************************************
@ -209,7 +418,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crend() const
{
return buffer.crend();
return const_reverse_iterator(lookup.crend());
}
//*********************************************************************
@ -222,7 +431,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_multimap_full));
#endif
@ -242,28 +451,13 @@ namespace etl
//*********************************************************************
std::pair<iterator, bool> insert(const value_type& value)
{
ETL_ASSERT(!buffer.full(), ETL_ERROR(flat_multimap_full));
ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multimap_full));
std::pair<iterator, bool> result(end(), false);
std::pair<iterator, bool> result(end(), false);
iterator i_element = lower_bound(value.first);
if (i_element == end())
{
// At the end.
buffer.push_back(value);
result.first = end() - 1;
result.second = true;
}
else
{
// Not at the end.
buffer.insert(i_element, value);
result.first = i_element;
result.second = true;
}
return result;
return insert_at(i_element, value);
}
//*********************************************************************
@ -300,7 +494,7 @@ namespace etl
//*********************************************************************
size_t erase(key_value_parameter_t key)
{
std::pair<iterator, iterator> range = equal_range(key);
std::pair<iterator, iterator> range = equal_range(key);
if (range.first == end())
{
@ -308,8 +502,8 @@ namespace etl
}
else
{
size_t count = std::distance(range.first, range.second);
erase(range.first, range.second);
size_t count = std::distance(range.first, range.second);
erase(range.first, range.second);
return count;
}
}
@ -320,7 +514,10 @@ namespace etl
//*********************************************************************
void erase(iterator i_element)
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
}
//*********************************************************************
@ -332,7 +529,17 @@ namespace etl
//*********************************************************************
void erase(iterator first, iterator last)
{
buffer.erase(first, last);
iterator itr = first;
while (itr != last)
{
itr->~value_type();
storage.release(etl::addressof(*itr));
++itr;
--construct_count;
}
lookup.erase(first.ilookup, last.ilookup);
}
//*************************************************************************
@ -340,7 +547,7 @@ namespace etl
//*************************************************************************
void clear()
{
buffer.clear();
erase(begin(), end());
}
//*********************************************************************
@ -398,9 +605,9 @@ namespace etl
//*********************************************************************
size_t count(key_value_parameter_t key) const
{
std::pair<const_iterator, const_iterator> range = equal_range(key);
std::pair<const_iterator, const_iterator> range = equal_range(key);
return std::distance(range.first, range.second);
return std::distance(range.first, range.second);
}
//*********************************************************************
@ -480,23 +687,111 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the flat_multiset.
///\return The current size of the flat_multiset.
//*************************************************************************
size_type size() const
{
return lookup.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_multiset.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return lookup.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_multiset.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return lookup.full();
}
//*************************************************************************
/// Returns the capacity of the flat_multiset.
///\return The capacity of the flat_multiset.
//*************************************************************************
size_type capacity() const
{
return lookup.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_multiset.
///\return The maximum size of the flat_multiset.
//*************************************************************************
size_type max_size() const
{
return lookup.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return lookup.available();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
iflat_multimap(buffer_t& buffer)
: flat_multimap_base(buffer),
buffer(buffer)
iflat_multimap(lookup_t& lookup_, storage_t& storage_)
: lookup(lookup_),
storage(storage_)
{
}
private:
//*********************************************************************
/// Inserts a value to the flat_multimap.
///\param i_element The place to insert.
///\param value The value to insert.
//*********************************************************************
std::pair<iterator, bool> insert_at(iterator i_element, const value_type& value)
{
std::pair<iterator, bool> result(end(), false);
if (i_element == end())
{
// At the end.
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.push_back(pvalue);
result.first = --end();
result.second = true;
}
else
{
// Not at the end.
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.insert(i_element.ilookup, pvalue);
result.first = i_element;
result.second = true;
}
++construct_count;
return result;
}
// Disable copy construction.
iflat_multimap(const iflat_multimap&);
buffer_t& buffer;
lookup_t& lookup;
storage_t& storage;
};
//***************************************************************************

View File

@ -38,11 +38,13 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "private/flat_multiset_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "ivector.h"
#include "error_handler.h"
#include "ipool.h"
namespace etl
{
@ -54,26 +56,237 @@ namespace etl
template <typename T, typename TKeyCompare = std::less<T> >
class iflat_multiset : public flat_multiset_base
{
public:
typedef T key_type;
typedef T value_type;
private:
typedef etl::ivector<T> buffer_t;
typedef etl::ivector<value_type*> lookup_t;
typedef etl::ipool storage_t;
public:
typedef T key_type;
typedef T value_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef typename buffer_t::iterator iterator;
typedef typename buffer_t::const_iterator const_iterator;
typedef typename buffer_t::reverse_iterator reverse_iterator;
typedef typename buffer_t::const_reverse_iterator const_reverse_iterator;
typedef size_t size_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
//*************************************************************************
class iterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
{
public:
friend class iflat_multiset;
iterator()
{
}
iterator(typename lookup_t::iterator ilookup)
: ilookup(ilookup)
{
}
iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
iterator& operator ++()
{
++ilookup;
return *this;
}
iterator operator ++(int)
{
iterator temp(*this);
++ilookup;
return temp;
}
iterator& operator --()
{
--ilookup;
return *this;
}
iterator operator --(int)
{
iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return &(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::iterator ilookup;
};
//*************************************************************************
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const value_type>
{
public:
friend class iflat_multiset;
const_iterator()
{
}
const_iterator(typename lookup_t::const_iterator ilookup)
: ilookup(ilookup)
{
}
const_iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator(const const_iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator =(const const_iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator ++()
{
++ilookup;
return *this;
}
const_iterator operator ++(int)
{
const_iterator temp(*this);
++ilookup;
return temp;
}
const_iterator& operator --()
{
--ilookup;
return *this;
}
const_iterator operator --(int)
{
const_iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return etl::addressof(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::const_iterator ilookup;
};
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
protected:
typedef typename parameter_type<T>::type parameter_t;
@ -86,7 +299,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return buffer.begin();
return iterator(lookup.begin());
}
//*********************************************************************
@ -95,7 +308,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return buffer.begin();
return const_iterator(lookup.begin());
}
//*********************************************************************
@ -104,7 +317,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return buffer.end();
return iterator(lookup.end());
}
//*********************************************************************
@ -113,7 +326,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return buffer.end();
return const_iterator(lookup.end());
}
//*********************************************************************
@ -122,7 +335,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return buffer.cbegin();
return const_iterator(lookup.cbegin());
}
//*********************************************************************
@ -131,7 +344,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return buffer.cend();
return const_iterator(lookup.cend());
}
//*********************************************************************
@ -140,7 +353,7 @@ namespace etl
//*********************************************************************
reverse_iterator rbegin()
{
return buffer.rbegin();
return reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -149,7 +362,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rbegin() const
{
return buffer.rbegin();
return const_reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -158,7 +371,7 @@ namespace etl
//*********************************************************************
reverse_iterator rend()
{
return buffer.rend();
return reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -167,7 +380,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rend() const
{
return buffer.rend();
return const_reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -176,7 +389,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crbegin() const
{
return buffer.crbegin();
return const_reverse_iterator(lookup.crbegin());
}
//*********************************************************************
@ -185,7 +398,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crend() const
{
return buffer.crend();
return const_reverse_iterator(lookup.crend());
}
//*********************************************************************
@ -198,7 +411,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_multiset_full));
#endif
@ -220,25 +433,31 @@ namespace etl
{
std::pair<iterator, bool> result(end(), false);
ETL_ASSERT(!buffer.full(), ETL_ERROR(flat_multiset_full));
ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multiset_full));
iterator i_element = std::lower_bound(begin(), end(), value, TKeyCompare());
if (i_element == end())
{
// At the end.
buffer.push_back(value);
result.first = end() - 1;
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.push_back(pvalue);
result.first = --end();
result.second = true;
}
else
{
// Not at the end.
buffer.insert(i_element, value);
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.insert(i_element.ilookup, pvalue);
result.first = i_element;
result.second = true;
}
++construct_count;
return result;
}
@ -276,7 +495,7 @@ namespace etl
//*********************************************************************
size_t erase(parameter_t key)
{
std::pair<iterator, iterator> range = equal_range(key);
std::pair<iterator, iterator> range = equal_range(key);
if (range.first == end())
{
@ -284,9 +503,9 @@ namespace etl
}
else
{
size_t count = std::distance(range.first, range.second);
erase(range.first, range.second);
return count;
size_t count = std::distance(range.first, range.second);
erase(range.first, range.second);
return count;
}
}
@ -296,7 +515,10 @@ namespace etl
//*********************************************************************
void erase(iterator i_element)
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
}
//*********************************************************************
@ -308,7 +530,17 @@ namespace etl
//*********************************************************************
void erase(iterator first, iterator last)
{
buffer.erase(first, last);
iterator itr = first;
while (itr != last)
{
itr->~value_type();
storage.release(etl::addressof(*itr));
++itr;
--construct_count;
}
lookup.erase(first.ilookup, last.ilookup);
}
//*************************************************************************
@ -316,7 +548,7 @@ namespace etl
//*************************************************************************
void clear()
{
buffer.clear();
erase(begin(), end());
}
//*********************************************************************
@ -376,7 +608,7 @@ namespace etl
{
std::pair<const_iterator, const_iterator> range = equal_range(key);
return std::distance(range.first, range.second);
return std::distance(range.first, range.second);
}
//*********************************************************************
@ -452,14 +684,68 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the flat_multiset.
///\return The current size of the flat_multiset.
//*************************************************************************
size_type size() const
{
return lookup.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_multiset.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return lookup.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_multiset.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return lookup.full();
}
//*************************************************************************
/// Returns the capacity of the flat_multiset.
///\return The capacity of the flat_multiset.
//*************************************************************************
size_type capacity() const
{
return lookup.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_multiset.
///\return The maximum size of the flat_multiset.
//*************************************************************************
size_type max_size() const
{
return lookup.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return lookup.available();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
iflat_multiset(buffer_t& buffer)
: flat_multiset_base(buffer),
buffer(buffer)
iflat_multiset(lookup_t& lookup_, storage_t& storage_)
: lookup(lookup_),
storage(storage_)
{
}
@ -468,7 +754,8 @@ namespace etl
// Disable copy construction.
iflat_multiset(const iflat_multiset&);
buffer_t& buffer;
lookup_t& lookup;
storage_t& storage;
};
//***************************************************************************

View File

@ -38,10 +38,12 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "private/flat_set_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "ivector.h"
#include "ipool.h"
#include "error_handler.h"
namespace etl
@ -54,25 +56,230 @@ namespace etl
template <typename T, typename TKeyCompare = std::less<T> >
class iflat_set : public flat_set_base
{
public:
typedef T key_type;
typedef T value_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
private:
typedef etl::ivector<T> buffer_t;
typedef etl::ivector<value_type*> lookup_t;
typedef etl::ipool storage_t;
public:
typedef T key_type;
typedef T value_type;
typedef TKeyCompare key_compare;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef typename buffer_t::iterator iterator;
typedef typename buffer_t::const_iterator const_iterator;
typedef typename buffer_t::reverse_iterator reverse_iterator;
typedef typename buffer_t::const_reverse_iterator const_reverse_iterator;
typedef size_t size_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
class iterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
{
public:
friend class iflat_set;
iterator()
{
}
iterator(typename lookup_t::iterator ilookup)
: ilookup(ilookup)
{
}
iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
iterator& operator ++()
{
++ilookup;
return *this;
}
iterator operator ++(int)
{
iterator temp(*this);
++ilookup;
return temp;
}
iterator& operator --()
{
--ilookup;
return *this;
}
iterator operator --(int)
{
iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return &(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::iterator ilookup;
};
//*************************************************************************
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const value_type>
{
public:
friend class iflat_set;
const_iterator()
{
}
const_iterator(typename lookup_t::const_iterator ilookup)
: ilookup(ilookup)
{
}
const_iterator(const iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator(const const_iterator& other)
: ilookup(other.ilookup)
{
}
const_iterator& operator =(const iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator =(const const_iterator& other)
{
ilookup = other.ilookup;
return *this;
}
const_iterator& operator ++()
{
++ilookup;
return *this;
}
const_iterator operator ++(int)
{
const_iterator temp(*this);
++ilookup;
return temp;
}
const_iterator& operator --()
{
--ilookup;
return *this;
}
const_iterator operator --(int)
{
const_iterator temp(*this);
--ilookup;
return temp;
}
reference operator *()
{
return *(*ilookup);
}
const_reference operator *() const
{
return *(*ilookup);
}
pointer operator &()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator &() const
{
return etl::addressof(*(*ilookup));
}
pointer operator ->()
{
return etl::addressof(*(*ilookup));
}
const_pointer operator ->() const
{
return etl::addressof(*(*ilookup));
}
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.ilookup == rhs.ilookup;
}
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
typename lookup_t::const_iterator ilookup;
};
protected:
@ -80,13 +287,17 @@ namespace etl
public:
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
//*********************************************************************
/// Returns an iterator to the beginning of the flat_set.
///\return An iterator to the beginning of the flat_set.
//*********************************************************************
iterator begin()
{
return buffer.begin();
return iterator(lookup.begin());
}
//*********************************************************************
@ -95,7 +306,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return buffer.begin();
return const_iterator(lookup.begin());
}
//*********************************************************************
@ -104,7 +315,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return buffer.end();
return iterator(lookup.end());
}
//*********************************************************************
@ -113,7 +324,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return buffer.end();
return const_iterator(lookup.end());
}
//*********************************************************************
@ -122,7 +333,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return buffer.cbegin();
return const_iterator(lookup.cbegin());
}
//*********************************************************************
@ -131,7 +342,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return buffer.cend();
return const_iterator(lookup.cend());
}
//*********************************************************************
@ -140,7 +351,7 @@ namespace etl
//*********************************************************************
reverse_iterator rbegin()
{
return buffer.rbegin();
return reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -149,7 +360,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rbegin() const
{
return buffer.rbegin();
return const_reverse_iterator(lookup.rbegin());
}
//*********************************************************************
@ -158,7 +369,7 @@ namespace etl
//*********************************************************************
reverse_iterator rend()
{
return buffer.rend();
return reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -167,7 +378,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator rend() const
{
return buffer.rend();
return const_reverse_iterator(lookup.rend());
}
//*********************************************************************
@ -176,7 +387,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crbegin() const
{
return buffer.crbegin();
return const_reverse_iterator(lookup.crbegin());
}
//*********************************************************************
@ -185,7 +396,7 @@ namespace etl
//*********************************************************************
const_reverse_iterator crend() const
{
return buffer.crend();
return const_reverse_iterator(lookup.crend());
}
//*********************************************************************
@ -198,7 +409,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_set_full));
#endif
@ -220,16 +431,19 @@ namespace etl
{
std::pair<iterator, bool> result(end(), false);
ETL_ASSERT(!buffer.full(), ETL_ERROR(flat_set_full));
ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_set_full));
iterator i_element = std::lower_bound(begin(), end(), value, TKeyCompare());
if (i_element == end())
{
// At the end. Doesn't exist.
buffer.push_back(value);
result.first = end() - 1;
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.push_back(pvalue);
result.first = --end();
result.second = true;
++construct_count;
}
else
{
@ -237,9 +451,12 @@ namespace etl
// Does not exist already?
if (*i_element != value)
{
buffer.insert(i_element, value);
value_type* pvalue = storage.allocate<value_type>();
::new (pvalue) value_type(value);
lookup.insert(i_element.ilookup, pvalue);
result.first = i_element;
result.second = true;
++construct_count;
}
else
{
@ -293,7 +510,10 @@ namespace etl
}
else
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
return 1;
}
}
@ -304,7 +524,10 @@ namespace etl
//*********************************************************************
void erase(iterator i_element)
{
buffer.erase(i_element);
i_element->~value_type();
storage.release(etl::addressof(*i_element));
lookup.erase(i_element.ilookup);
--construct_count;
}
//*********************************************************************
@ -316,7 +539,17 @@ namespace etl
//*********************************************************************
void erase(iterator first, iterator last)
{
buffer.erase(first, last);
iterator itr = first;
while (itr != last)
{
itr->~value_type();
storage.release(etl::addressof(*itr));
++itr;
--construct_count;
}
lookup.erase(first.ilookup, last.ilookup);;
}
//*************************************************************************
@ -324,7 +557,7 @@ namespace etl
//*************************************************************************
void clear()
{
buffer.clear();
erase(begin(), end());
}
//*********************************************************************
@ -458,14 +691,68 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the flat_set.
///\return The current size of the flat_set.
//*************************************************************************
size_type size() const
{
return lookup.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_set.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return lookup.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_set.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return lookup.full();
}
//*************************************************************************
/// Returns the capacity of the flat_set.
///\return The capacity of the flat_set.
//*************************************************************************
size_type capacity() const
{
return lookup.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_set.
///\return The maximum size of the flat_set.
//*************************************************************************
size_type max_size() const
{
return lookup.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return lookup.available();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
iflat_set(buffer_t& buffer)
: flat_set_base(buffer),
buffer(buffer)
iflat_set(lookup_t& lookup_, storage_t& storage)
: lookup(lookup_),
storage(storage)
{
}
@ -474,7 +761,8 @@ namespace etl
// Disable copy construction.
iflat_set(const iflat_set&);
buffer_t& buffer;
lookup_t& lookup;
storage_t& storage;
};
//***************************************************************************

View File

@ -74,9 +74,9 @@ namespace etl
//*************************************************************************
/// The data node element in the forward_list.
//*************************************************************************
struct Data_Node : public Node
struct data_node_t : public node_t
{
explicit Data_Node(parameter_t value)
explicit data_node_t(parameter_t value)
: value(value)
{}
@ -99,7 +99,7 @@ namespace etl
{
}
iterator(Node& node)
iterator(node_t& node)
: p_node(&node)
{
}
@ -170,7 +170,7 @@ namespace etl
private:
Node* p_node;
node_t* p_node;
};
//*************************************************************************
@ -187,12 +187,12 @@ namespace etl
{
}
const_iterator(Node& node)
const_iterator(node_t& node)
: p_node(&node)
{
}
const_iterator(const Node& node)
const_iterator(const node_t& node)
: p_node(&node)
{
}
@ -253,10 +253,10 @@ namespace etl
private:
const Node* p_node;
const node_t* p_node;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
/// Gets the beginning of the forward_list.
@ -279,7 +279,7 @@ namespace etl
//*************************************************************************
iterator before_begin()
{
return iterator(static_cast<Data_Node&>(start_node));
return iterator(static_cast<data_node_t&>(start_node));
}
//*************************************************************************
@ -287,7 +287,7 @@ namespace etl
//*************************************************************************
const_iterator before_begin() const
{
return const_iterator(static_cast<const Data_Node&>(start_node));
return const_iterator(static_cast<const data_node_t&>(start_node));
}
//*************************************************************************
@ -348,31 +348,30 @@ namespace etl
//*************************************************************************
/// Assigns a range of values to the forward_list.
/// If asserts or exceptions are enabled throws etl::forward_list_full if the forward_list does not have enough free space.
/// If asserts or exceptions are enabled throws etl::forward_list_full if the forward_list does not have enough free space.
/// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws forward_list_iterator if the iterators are reversed.
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(forward_list_iterator));
#endif
initialise();
Node* p_last_node = &start_node;
node_t* p_last_node = &start_node;
// Add all of the elements.
while (first != last)
{
ETL_ASSERT(!full(), ETL_ERROR(forward_list_iterator));
Data_Node& data_node = allocate_data_node(*first++);
data_node_t& data_node = allocate_data_node(*first++);
join(p_last_node, &data_node);
data_node.next = nullptr;
p_last_node = &data_node;
++current_size;
}
}
@ -385,16 +384,15 @@ namespace etl
initialise();
Node* p_last_node = &start_node;
node_t* p_last_node = &start_node;
// Add all of the elements.
while (current_size < n)
while (size() < n)
{
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
join(p_last_node, &data_node);
data_node.next = nullptr;
p_last_node = &data_node;
++current_size;
}
}
@ -403,11 +401,7 @@ namespace etl
//*************************************************************************
void push_front()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(forward_list_full));
#endif
Data_Node& data_node = allocate_data_node(T());
insert_node_after(start_node, data_node);
push_front(T());
}
//*************************************************************************
@ -418,7 +412,8 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(forward_list_full));
#endif
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node_after(start_node, data_node);
}
@ -485,7 +480,7 @@ namespace etl
{
ETL_ASSERT(!full(), ETL_ERROR(forward_list_full));
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node_after(*position.p_node, data_node);
return iterator(data_node);
@ -501,7 +496,7 @@ namespace etl
for (size_t i = 0; !full() && (i < n); ++i)
{
// Set up the next free node.
Data_Node& data_node = allocate_data_node(value);
data_node_t& data_node = allocate_data_node(value);
insert_node_after(*position.p_node, data_node);
}
}
@ -512,15 +507,15 @@ namespace etl
template <typename TIterator>
void insert_after(iterator position, TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT((count + current_size) <= MAX_SIZE, ETL_ERROR(forward_list_full));
ETL_ASSERT((count + size()) <= MAX_SIZE, ETL_ERROR(forward_list_full));
#endif
while (first != last)
{
// Set up the next free node.
Data_Node& data_node = allocate_data_node(*first++);
data_node_t& data_node = allocate_data_node(*first++);
insert_node_after(*position.p_node, data_node);
++position;
}
@ -532,10 +527,15 @@ namespace etl
iterator erase_after(iterator position)
{
iterator next(position);
++next;
++next;
remove_node_after(*position.p_node);
if (next != end())
{
++next;
if (next != end())
{
++next;
remove_node_after(*position.p_node);
}
}
return next;
}
@ -545,33 +545,37 @@ namespace etl
//*************************************************************************
iterator erase_after(iterator first, iterator last)
{
Node* p_first = first.p_node;
Node* p_last = last.p_node;
Node* p_next = p_first->next;
// Join the ends.
join(p_first, p_last);
p_first = p_next;
// Erase the ones in between.
while (p_first != p_last)
if (first != end() && (first != last))
{
// One less.
--current_size;
node_t* p_first = first.p_node;
node_t* p_last = last.p_node;
node_t* p_next = p_first->next;
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<Data_Node&>(*p_first)); // Destroy the pool object.
p_first = p_next; // Move to the next node.
}
// Join the ends.
join(p_first, p_last);
if (p_next == nullptr)
{
return end();
p_first = p_next;
// Erase the ones in between.
while (p_first != p_last)
{
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the pool object.
p_first = p_next; // Move to the next node.
}
if (p_next == nullptr)
{
return end();
}
else
{
return iterator(*p_last);
}
}
else
{
return iterator(*p_last);
return end();
}
}
@ -580,15 +584,15 @@ namespace etl
//*************************************************************************
void move_after(const_iterator from_before, const_iterator to_before)
{
if (from_before == to_before) // Can't more to after yourself!
if (from_before == to_before) // Can't move to after yourself!
{
return;
}
Node* p_from_before = const_cast<Node*>(from_before.p_node); // We're not changing the value, just it's position.
Node* p_to_before = const_cast<Node*>(to_before.p_node); // We're not changing the value, just it's position.
node_t* p_from_before = const_cast<node_t*>(from_before.p_node); // We're not changing the value, just it's position.
node_t* p_to_before = const_cast<node_t*>(to_before.p_node); // We're not changing the value, just it's position.
Node* p_from = p_from_before->next;
node_t* p_from = p_from_before->next;
// Disconnect from the list.
join(p_from_before, p_from->next);
@ -609,7 +613,7 @@ namespace etl
return; // Can't more to before yourself!
}
#ifdef _DEBUG
#if defined(ETL_DEBUG)
// Check that we are not doing an illegal move!
for (const_iterator item = first_before; item != last; ++item)
{
@ -617,11 +621,11 @@ namespace etl
}
#endif
Node* p_first_before = const_cast<Node*>(first_before.p_node); // We're not changing the value, just it's position.
Node* p_last = const_cast<Node*>(last.p_node); // We're not changing the value, just it's position.
Node* p_to_before = const_cast<Node*>(to_before.p_node); // We're not changing the value, just it's position.
Node* p_first = p_first_before->next;
Node* p_final = p_first_before;
node_t* p_first_before = const_cast<node_t*>(first_before.p_node); // We're not changing the value, just it's position.
node_t* p_last = const_cast<node_t*>(last.p_node); // We're not changing the value, just it's position.
node_t* p_to_before = const_cast<node_t*>(to_before.p_node); // We're not changing the value, just it's position.
node_t* p_first = p_first_before->next;
node_t* p_final = p_first_before;
// Find the last node that will be moved.
while (p_final->next != p_last)
@ -658,8 +662,8 @@ namespace etl
return;
}
Node* last = &get_head();
Node* current = last->next;
node_t* last = &get_head();
node_t* current = last->next;
while (current != nullptr)
{
@ -707,7 +711,7 @@ namespace etl
if (is_trivial_list())
{
return;
return;
}
while (true)
@ -746,32 +750,32 @@ namespace etl
// Decide whether the next node of merge comes from left or right.
if (left_size == 0)
{
// Left is empty. The node must come from right.
p_node = p_right;
// Left is empty. The node must come from right.
p_node = p_right;
++p_right;
--right_size;
}
}
else if (right_size == 0 || p_right == end())
{
// Right is empty. The node must come from left.
p_node = p_left;
// Right is empty. The node must come from left.
p_node = p_left;
++p_left;
--left_size;
}
}
else if (compare(*p_left, *p_right))
{
// First node of left is lower or same. The node must come from left.
p_node = p_left;
// First node of left is lower or same. The node must come from left.
p_node = p_left;
++p_left;
--left_size;
}
}
else
{
// First node of right is lower. The node must come from right.
p_node = p_right;
// First node of right is lower. The node must come from right.
p_node = p_right;
++p_right;
--right_size;
}
}
// Add the next node to the merged head.
if (p_head == before_begin())
@ -867,9 +871,8 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
iforward_list(etl::ipool<Data_Node>& node_pool, size_t max_size_)
: forward_list_base(max_size_),
p_node_pool(&node_pool)
iforward_list(etl::ipool& node_pool, size_t max_size_)
: forward_list_base(node_pool, max_size_)
{
}
@ -880,57 +883,62 @@ namespace etl
{
if (!empty())
{
p_node_pool->release_all();
node_t* p_first = start_node.next;
node_t* p_next;
// Erase the ones in between.
while (p_first != nullptr)
{
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the pool object.
p_first = p_next; // Move to the next node.
}
}
current_size = 0;
start_node.next = nullptr;
}
private:
/// The pool of data nodes used in the list.
etl::ipool<Data_Node>* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
/// Downcast a node_t* to a data_node_t*
//*************************************************************************
static Data_Node* data_cast(Node* p_node)
static data_node_t* data_cast(node_t* p_node)
{
return static_cast<Data_Node*>(p_node);
return static_cast<data_node_t*>(p_node);
}
//*************************************************************************
/// Downcast a Node& to a Data_Node&
/// Downcast a node_t& to a data_node_t&
//*************************************************************************
static Data_Node& data_cast(Node& node)
static data_node_t& data_cast(node_t& node)
{
return static_cast<Data_Node&>(node);
return static_cast<data_node_t&>(node);
}
//*************************************************************************
/// Downcast a const Node* to a const Data_Node*
/// Downcast a const node_t* to a const data_node_t*
//*************************************************************************
static const Data_Node* data_cast(const Node* p_node)
static const data_node_t* data_cast(const node_t* p_node)
{
return static_cast<const Data_Node*>(p_node);
return static_cast<const data_node_t*>(p_node);
}
//*************************************************************************
/// Downcast a const Node& to a const Data_Node&
/// Downcast a const node_t& to a const data_node_t&
//*************************************************************************
static const Data_Node& data_cast(const Node& node)
static const data_node_t& data_cast(const node_t& node)
{
return static_cast<const Data_Node&>(node);
return static_cast<const data_node_t&>(node);
}
//*************************************************************************
/// Remove a node.
//*************************************************************************
void remove_node_after(Node& node)
void remove_node_after(node_t& node)
{
// The node to erase.
Node* p_node = node.next;
node_t* p_node = node.next;
if (p_node != nullptr)
{
@ -938,27 +946,30 @@ namespace etl
join(&node, p_node->next);
// Destroy the pool object.
destroy_data_node(static_cast<Data_Node&>(*p_node));
// One less.
--current_size;
destroy_data_node(static_cast<data_node_t&>(*p_node));
}
}
//*************************************************************************
/// Allocate a Data_Node.
/// Allocate a data_node_t.
//*************************************************************************
Data_Node& allocate_data_node(parameter_t value) const
data_node_t& allocate_data_node(parameter_t value)
{
return *(p_node_pool->allocate(Data_Node(value)));
data_node_t* p_node = p_node_pool->allocate<data_node_t>();
::new (&(p_node->value)) T(value);
++construct_count;
return *p_node;
}
//*************************************************************************
/// Destroy a Data_Node.
/// Destroy a data_node_t.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(data_node_t& node)
{
p_node_pool->release(node);
node.value.~T();
p_node_pool->release(&node);
--construct_count;
}
// Disable copy construction.

View File

@ -37,12 +37,12 @@ SOFTWARE.
#include <functional>
#include <stddef.h>
#include "platform.h"
#include "nullptr.h"
#include "private/list_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "pool.h"
#include "platform.h"
#include "algorithm.h"
#ifdef ETL_COMPILER_MICROSOFT
#undef min
@ -85,15 +85,12 @@ namespace etl
private:
/// The pool of data nodes used in the list.
etl::ipool<data_node_t>* p_node_pool;
//*************************************************************************
/// Downcast a node_t* to a data_node_t*
//*************************************************************************
static data_node_t* data_cast(node_t* p_node)
{
return static_cast<data_node_t*>(p_node);
return reinterpret_cast<data_node_t*>(p_node);
}
//*************************************************************************
@ -101,7 +98,7 @@ namespace etl
//*************************************************************************
static data_node_t& data_cast(node_t& node)
{
return static_cast<data_node_t&>(node);
return reinterpret_cast<data_node_t&>(node);
}
//*************************************************************************
@ -109,7 +106,7 @@ namespace etl
//*************************************************************************
static const data_node_t* data_cast(const node_t* p_node)
{
return static_cast<const data_node_t*>(p_node);
return reinterpret_cast<const data_node_t*>(p_node);
}
//*************************************************************************
@ -117,7 +114,7 @@ namespace etl
//*************************************************************************
static const data_node_t& data_cast(const node_t& node)
{
return static_cast<const data_node_t&>(node);
return reinterpret_cast<const data_node_t&>(node);
}
public:
@ -452,7 +449,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(list_iterator));
ETL_ASSERT(size_t(count) <= MAX_SIZE, ETL_ERROR(list_full));
@ -462,11 +459,10 @@ namespace etl
// Add all of the elements.
while (first != last)
{
data_node_t& data_node = allocate_data_node(*first);
join(get_tail(), data_node);
join(data_node, terminal_node);
data_node_t& node = allocate_data_node(*first);
join(get_tail(), node);
join(node, terminal_node);
++first;
++current_size;
}
}
@ -475,19 +471,18 @@ namespace etl
//*************************************************************************
void assign(size_t n, parameter_t value)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full));
#endif
initialise();
// Add all of the elements.
while (current_size < n)
while (size() < n)
{
data_node_t& data_node = allocate_data_node(value);
join(*terminal_node.previous, data_node);
join(data_node, terminal_node);
++current_size;
data_node_t& node = allocate_data_node(value);
join(*terminal_node.previous, node);
join(node, terminal_node);
}
}
@ -496,11 +491,7 @@ namespace etl
//*************************************************************************
void push_front()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
data_node_t& data_node = allocate_data_node(T());
insert_node(get_head(), data_node);
push_front(T());
}
//*************************************************************************
@ -511,8 +502,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
node_t& data_node = allocate_data_node(value);
insert_node(get_head(), data_node);
insert_node(get_head(), allocate_data_node(value));
}
//*************************************************************************
@ -532,11 +522,7 @@ namespace etl
//*************************************************************************
void push_back()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
data_node_t& data_node = allocate_data_node(T());
insert_node(terminal_node, data_node);
push_back(T());
}
//*************************************************************************
@ -547,8 +533,7 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(list_full));
#endif
data_node_t& data_node = allocate_data_node(value);
insert_node(terminal_node, data_node);
insert_node(terminal_node, allocate_data_node(value));
}
//*************************************************************************
@ -586,8 +571,7 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
data_node_t& data_node = allocate_data_node(value);
insert_node(*position.p_node, data_node);
insert_node(*position.p_node, allocate_data_node(value));
}
}
@ -602,8 +586,7 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(list_full));
// Set up the next free node and insert.
data_node_t& data_node = allocate_data_node(*first++);
insert_node(*position.p_node, data_node);
insert_node(*position.p_node, allocate_data_node(*first++));
}
}
@ -612,12 +595,9 @@ namespace etl
//*************************************************************************
iterator erase(iterator position)
{
iterator next(position);
++next;
remove_node(*position.p_node);
return next;
++position;
remove_node(*position.p_node->previous);
return position;
}
//*************************************************************************
@ -635,12 +615,9 @@ namespace etl
// Erase the ones in between.
while (p_first != p_last)
{
// One less.
--current_size;
p_next = p_first->next; // Remember the next node.
p_next = p_first->next; // Remember the next node.
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
p_first = p_next; // Move to the next node.
p_first = p_next; // Move to the next node.
}
return last;
@ -846,6 +823,9 @@ namespace etl
++this_begin;
}
bool t = this_begin != this_end;
bool o = other_begin != other_end;
// Insert.
if (this_begin != this_end)
{
@ -853,6 +833,8 @@ namespace etl
{
insert(this_begin, *other_begin);
++other_begin;
o = other_begin != other_end;
}
}
}
@ -1001,15 +983,14 @@ namespace etl
return *this;
}
protected:
//*************************************************************************
/// Constructor.
//*************************************************************************
ilist(etl::ipool<data_node_t>& node_pool, size_t max_size_)
: list_base(max_size_),
p_node_pool(&node_pool)
ilist(etl::ipool& node_pool, size_t max_size_)
: list_base(node_pool, max_size_)
{
}
@ -1020,10 +1001,16 @@ namespace etl
{
if (!empty())
{
p_node_pool->release_all();
node_t* p_first = terminal_node.next;
node_t* p_last = &terminal_node;
while (p_first != p_last)
{
destroy_data_node(static_cast<data_node_t&>(*p_first)); // Destroy the current node.
p_first = p_first->next; // Move to the next node.
}
}
current_size = 0;
join(terminal_node, terminal_node);
}
@ -1062,7 +1049,7 @@ namespace etl
return; // Can't more to before yourself!
}
#ifdef _DEBUG
#if defined(ETL_DEBUG)
// Check that we are not doing an illegal move!
for (const_iterator item = first; item != last; ++item)
{
@ -1093,25 +1080,28 @@ namespace etl
// Destroy the pool object.
destroy_data_node(static_cast<data_node_t&>(node));
// One less.
--current_size;
}
//*************************************************************************
/// Allocate a data_node_t.
//*************************************************************************
data_node_t& allocate_data_node(parameter_t value) const
data_node_t& allocate_data_node(parameter_t value)
{
return *(p_node_pool->allocate(data_node_t(value)));
data_node_t* p_data_node = p_node_pool->allocate<data_node_t>();
::new (&(p_data_node->value)) T(value);
++construct_count;
return *p_data_node;
}
//*************************************************************************
/// Destroy a data_node_t.
//*************************************************************************
void destroy_data_node(data_node_t& node) const
void destroy_data_node(data_node_t& node)
{
node.value.~T();
p_node_pool->release(&node);
--construct_count;
}
// Disable copy construction.

View File

@ -103,6 +103,11 @@ namespace etl
{
}
~Data_Node()
{
}
value_type value;
};
@ -128,7 +133,7 @@ namespace etl
private:
/// The pool of data nodes used in the map.
ipool<Data_Node>* p_node_pool;
ipool* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
@ -830,7 +835,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
imap(ipool<Data_Node>& node_pool, size_t max_size_)
imap(ipool& node_pool, size_t max_size_)
: map_base(max_size_)
, p_node_pool(&node_pool)
{
@ -841,13 +846,7 @@ namespace etl
//*************************************************************************
void initialise()
{
if (!empty())
{
p_node_pool->release_all();
}
current_size = 0;
root_node = nullptr;
erase(begin(), end());
}
private:
@ -855,17 +854,22 @@ namespace etl
//*************************************************************************
/// Allocate a Data_Node.
//*************************************************************************
Data_Node& allocate_data_node(value_type value) const
Data_Node& allocate_data_node(value_type value)
{
return *(p_node_pool->allocate(Data_Node(value)));
Data_Node& node = *p_node_pool->allocate<Data_Node>();
::new (&node.value) const value_type(value);
++construct_count;
return node;
}
//*************************************************************************
/// Destroy a Data_Node.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(Data_Node& node)
{
node.value.~value_type();
p_node_pool->release(&node);
--construct_count;
}
//*************************************************************************

View File

@ -130,7 +130,7 @@ namespace etl
private:
/// The pool of data nodes used in the multimap.
ipool<Data_Node>* p_node_pool;
ipool* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
@ -675,7 +675,7 @@ namespace etl
///\param position The position that would precede the value to insert.
///\param value The value to insert.
//*********************************************************************
iterator insert(iterator position, const value_type& value)
iterator insert(iterator /*position*/, const value_type& value)
{
// Ignore position provided and just do a normal insert
return insert(value);
@ -687,7 +687,7 @@ namespace etl
///\param position The position that would precede the value to insert.
///\param value The value to insert.
//*********************************************************************
iterator insert(const_iterator position, const value_type& value)
iterator insert(const_iterator /*position*/, const value_type& value)
{
// Ignore position provided and just do a normal insert
return insert(value);
@ -772,7 +772,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
imultimap(ipool<Data_Node>& node_pool, size_t max_size_)
imultimap(ipool& node_pool, size_t max_size_)
: multimap_base(max_size_)
, p_node_pool(&node_pool)
{
@ -783,13 +783,7 @@ namespace etl
//*************************************************************************
void initialise()
{
if (!empty())
{
p_node_pool->release_all();
}
current_size = 0;
root_node = nullptr;
erase(begin(), end());
}
private:
@ -797,17 +791,22 @@ namespace etl
//*************************************************************************
/// Allocate a Data_Node.
//*************************************************************************
Data_Node& allocate_data_node(value_type value) const
Data_Node& allocate_data_node(value_type value)
{
return *(p_node_pool->allocate(Data_Node(value)));
Data_Node& node = *p_node_pool->allocate<Data_Node>();
::new (&node.value) const value_type(value);
++construct_count;
return node;
}
//*************************************************************************
/// Destroy a Data_Node.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(Data_Node& node)
{
node.value.~value_type();
p_node_pool->release(&node);
--construct_count;
}
//*************************************************************************

View File

@ -126,7 +126,7 @@ namespace etl
private:
/// The pool of data nodes used in the multiset.
ipool<Data_Node>* p_node_pool;
ipool* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
@ -656,7 +656,7 @@ namespace etl
///\param position The position that would precede the value to insert.
///\param value The value to insert.
//*********************************************************************
iterator insert(iterator position, const value_type& value)
iterator insert(iterator /*position*/, const value_type& value)
{
// Ignore position provided and just do a normal insert
return insert(value);
@ -668,7 +668,7 @@ namespace etl
///\param position The position that would precede the value to insert.
///\param value The value to insert.
//*********************************************************************
iterator insert(const_iterator position, const value_type& value)
iterator insert(const_iterator /*position*/, const value_type& value)
{
// Ignore position provided and just do a normal insert
return insert(value);
@ -753,7 +753,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
imultiset(ipool<Data_Node>& node_pool, size_t max_size_)
imultiset(ipool& node_pool, size_t max_size_)
: multiset_base(max_size_)
, p_node_pool(&node_pool)
{
@ -764,13 +764,7 @@ namespace etl
//*************************************************************************
void initialise()
{
if (!empty())
{
p_node_pool->release_all();
}
current_size = 0;
root_node = nullptr;
erase(begin(), end());
}
private:
@ -778,17 +772,22 @@ namespace etl
//*************************************************************************
/// Allocate a Data_Node.
//*************************************************************************
Data_Node& allocate_data_node(value_type value) const
Data_Node& allocate_data_node(value_type value)
{
return *(p_node_pool->allocate(Data_Node(value)));
Data_Node& node = *p_node_pool->allocate<Data_Node>();
::new ((void*)&node.value) value_type(value);
++construct_count;
return node;
}
//*************************************************************************
/// Destroy a Data_Node.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(Data_Node& node)
{
node.value.~value_type();
p_node_pool->release(&node);
--construct_count;
}
//*************************************************************************

View File

@ -42,6 +42,7 @@ SOFTWARE.
#include <functional>
#include <stddef.h>
#include "platform.h"
#include "nullptr.h"
#include "type_traits.h"
#include "exception.h"
@ -145,13 +146,6 @@ namespace etl
typedef const value_type& const_reference;
typedef size_t size_type;
enum
{
// The count option is based on the type of link.
COUNT_OPTION = ((TLink::OPTION == etl::link_option::AUTO) ||
(TLink::OPTION == etl::link_option::CHECKED)) ? etl::count_option::SLOW_COUNT : etl::count_option::FAST_COUNT
};
typedef intrusive_forward_list<TValue, TLink> list_type;
//*************************************************************************
@ -324,7 +318,7 @@ namespace etl
const value_type* p_value;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
/// Constructor.
@ -334,6 +328,14 @@ namespace etl
initialise();
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~intrusive_forward_list()
{
clear();
}
//*************************************************************************
/// Constructor from range
//*************************************************************************
@ -438,7 +440,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(intrusive_forward_list_iterator_exception));
#endif
@ -503,33 +505,21 @@ namespace etl
//*************************************************************************
/// Inserts a value to the intrusive_forward_list after the specified position.
/// Checks that the value is unlinked if CHECKED.
//*************************************************************************
iterator insert_after(iterator position, value_type& value)
{
if (TLink::OPTION == etl::link_option::CHECKED)
{
ETL_ASSERT(!value.TLink::is_linked(), ETL_ERROR(etl::not_unlinked_exception));
}
insert_link_after(*position.p_value, value);
return iterator(value);
}
//*************************************************************************
/// Inserts a range of values to the intrusive_forward_list after the specified position.
/// Checks that the values are unlinked if CHECKED.
//*************************************************************************
template <typename TIterator>
void insert_after(iterator position, TIterator first, TIterator last)
{
while (first != last)
{
if (TLink::OPTION == etl::link_option::CHECKED)
{
ETL_ASSERT(!position.p_value->TLink::is_linked(), ETL_ERROR(etl::not_unlinked_exception));
}
// Set up the next free link.
insert_link_after(*position.p_value, *first++);
++position;
@ -538,19 +528,18 @@ namespace etl
//*************************************************************************
/// Erases the value at the specified position.
/// Clears the link after erasing if CHECKED.
//*************************************************************************
iterator erase_after(iterator position)
{
iterator next(position);
++next;
++next;
remove_link_after(*position.p_value);
if (TLink::OPTION == etl::link_option::CHECKED)
if (next != end())
{
position.p_value->TLink::clear();
++next;
if (next != end())
{
++next;
remove_link_after(*position.p_value);
}
}
return next;
@ -558,42 +547,32 @@ namespace etl
//*************************************************************************
/// Erases a range of elements.
/// Clears the links after erasing if CHECKED.
//*************************************************************************
iterator erase_after(iterator first, iterator last)
{
link_type* p_first = first.p_value;
link_type* p_last = last.p_value;
link_type* p_next = p_first->etl_next;
// Join the ends.
etl::link<link_type>(p_first, p_last);
p_first = p_next;
// Erase the ones in between.
while (p_first != p_last)
if (first != end() && (first != last))
{
// One less.
--current_size;
current_size -= std::distance(first, last) - 1;
p_next = p_first->etl_next; // Remember the next link.
link_type* p_first = first.p_value;
link_type* p_last = last.p_value;
link_type* p_next = p_first->etl_next;
if (TLink::OPTION == etl::link_option::CHECKED)
// Join the ends.
etl::link<link_type>(p_first, p_last);
if (p_next == nullptr)
{
p_first->TLink::clear(); // Clear the link.
return end();
}
else
{
return last;
}
p_first = p_next; // Move to the next link.
}
if (p_next == nullptr)
{
return end();
}
else
{
return iterator(*static_cast<value_type*>(p_last));
return last;
}
}
@ -657,7 +636,7 @@ namespace etl
if (is_trivial_list())
{
return;
return;
}
while (true)
@ -696,32 +675,32 @@ namespace etl
// Decide whether the next link of merge comes from left or right.
if (left_size == 0)
{
// Left is empty. The link must come from right.
i_link = i_right;
// Left is empty. The link must come from right.
i_link = i_right;
++i_right;
--right_size;
}
}
else if (right_size == 0 || i_right == end())
{
// Right is empty. The link must come from left.
i_link = i_left;
// Right is empty. The link must come from left.
i_link = i_left;
++i_left;
--left_size;
}
}
else if (compare(*i_left, *i_right))
{
// First link of left is lower or same. The link must come from left.
i_link = i_left;
// First link of left is lower or same. The link must come from left.
i_link = i_left;
++i_left;
--left_size;
}
}
else
{
// First link of right is lower. The link must come from right.
i_link = i_right;
// First link of right is lower. The link must come from right.
i_link = i_right;
++i_right;
--right_size;
}
}
// Add the next link to the merged head.
if (i_head == before_begin())
@ -812,34 +791,24 @@ namespace etl
//*************************************************************************
size_t size() const
{
if (COUNT_OPTION == etl::count_option::SLOW_COUNT)
{
return std::distance(cbegin(), cend());
}
else
{
return current_size.get_count();
}
return current_size;
}
//*************************************************************************
/// Splice another list into this one.
//*************************************************************************
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& list)
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other)
{
// No point splicing to ourself!
if (&list != this)
if (&other != this)
{
if (!list.empty())
if (!other.empty())
{
link_type& first = list.get_head();
link_type& first = other.get_head();
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
current_size += list.size();
}
current_size += other.size();
}
link_type& before = *position.p_value;
@ -855,7 +824,7 @@ namespace etl
etl::link<link_type>(last, after);
list.clear();
other.initialise();
}
}
}
@ -863,38 +832,32 @@ namespace etl
//*************************************************************************
/// Splice an element from another list into this one.
//*************************************************************************
void splice(iterator position, etl::intrusive_forward_list<TValue, TLink>& list, iterator isource)
void splice(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator isource)
{
link_type& before = *position.p_value;
etl::unlink<link_type>(*isource.p_value);
etl::link_splice<link_type>(before, *isource.p_value);
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
++current_size;
--list.current_size;
}
++current_size;
--other.current_size;
}
}
//*************************************************************************
/// Splice a range of elements from another list into this one.
//*************************************************************************
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& list, iterator begin_, iterator end_)
void splice_after(iterator position, etl::intrusive_forward_list<TValue, TLink>& other, iterator begin_, iterator end_)
{
if (!list.empty())
if (!other.empty())
{
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
size_t n = std::distance(begin_, end_) - 1;
current_size += n;
list.current_size -= n;
}
size_t n = std::distance(begin_, end_) - 1;
current_size += n;
other.current_size -= n;
}
link_type* first = begin_.p_value;
@ -919,25 +882,25 @@ namespace etl
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
void merge(list_type& list)
void merge(list_type& other)
{
merge(list, std::less<value_type>());
merge(other, std::less<value_type>());
}
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
template <typename TCompare>
void merge(list_type& list, TCompare compare)
void merge(list_type& other, TCompare compare)
{
if (!list.empty())
if (!other.empty())
{
#if _DEBUG
ETL_ASSERT(etl::is_sorted(list.begin(), list.end(), compare), ETL_ERROR(intrusive_forward_list_unsorted));
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_forward_list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_forward_list_unsorted));
#endif
value_type* other_begin = static_cast<value_type*>(&list.get_head());
value_type* other_begin = static_cast<value_type*>(&other.get_head());
value_type* other_terminal = nullptr;
value_type* before = static_cast<value_type*>(&start_link);
@ -978,12 +941,9 @@ namespace etl
}
}
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
{
current_size += list.size();
}
current_size += other.size();
list.clear();
other.initialise();
}
}
@ -991,105 +951,7 @@ namespace etl
link_type start_link; ///< The link that acts as the intrusive_forward_list start.
//*************************************************************************
/// Counter type based on count option.
//*************************************************************************
template <const size_t OPTION, bool dummy = true>
class counter_type
{
};
//*************************************************************************
/// Slow type.
//*************************************************************************
template <bool dummy>
class counter_type<etl::count_option::SLOW_COUNT, dummy>
{
public:
counter_type& operator ++()
{
return *this;
}
counter_type& operator --()
{
return *this;
}
counter_type& operator =(size_t new_count)
{
return *this;
}
counter_type& operator +=(size_t diff)
{
return *this;
}
counter_type& operator -=(size_t diff)
{
return *this;
}
size_t get_count() const
{
return 0;
}
};
//*************************************************************************
/// Fast type.
//*************************************************************************
template <bool dummy>
class counter_type<etl::count_option::FAST_COUNT, dummy>
{
public:
counter_type()
: count(0)
{
}
counter_type& operator ++()
{
++count;
return *this;
}
counter_type& operator --()
{
--count;
return *this;
}
counter_type& operator =(size_t new_count)
{
count = new_count;
return *this;
}
counter_type& operator +=(size_t diff)
{
count += diff;
return *this;
}
counter_type& operator -=(size_t diff)
{
count -= diff;
return *this;
}
size_t get_count() const
{
return count;
}
size_t count;
};
counter_type<COUNT_OPTION> current_size; ///< Counts the number of elements in the list.
size_t current_size; ///< Counts the number of elements in the list.
//*************************************************************************
/// Is the intrusive_forward_list a trivial length?
@ -1114,7 +976,9 @@ namespace etl
//*************************************************************************
void remove_link_after(link_type& link)
{
if (link.etl_next != nullptr)
link_type* p_next = link.etl_next;
if (p_next != nullptr)
{
etl::unlink_after<link_type>(link);
--current_size;

View File

@ -55,25 +55,6 @@ SOFTWARE.
namespace etl
{
namespace link_option
{
enum
{
DEFAULT,
AUTO,
CHECKED
};
}
namespace count_option
{
enum
{
SLOW_COUNT,
FAST_COUNT
};
}
//***************************************************************************
/// Link exception.
//***************************************************************************
@ -100,18 +81,15 @@ namespace etl
}
};
namespace __private_intrusive_links__
//***************************************************************************
/// A forward link.
//***************************************************************************
template <const size_t ID_>
struct forward_link
{
//***************************************************************************
/// A forward link base.
//***************************************************************************
template <typename TLink, const size_t ID_, const size_t OPTION_>
struct forward_link_base
{
enum
{
ID = ID_,
OPTION = OPTION_
};
void clear()
@ -124,55 +102,12 @@ namespace etl
return etl_next != nullptr;
}
TLink* etl_next;
};
}
//***************************************************************************
/// A forward link.
//***************************************************************************
template <const size_t ID_, const size_t OPTION_ = etl::link_option::DEFAULT>
struct forward_link
: public __private_intrusive_links__::forward_link_base<forward_link<ID_, OPTION_>, ID_, OPTION_>
{
};
//******************************************************************
// There is no valid specialisation for auto link
//******************************************************************
template <const size_t ID_>
struct forward_link<ID_, etl::link_option::AUTO>
: public __private_intrusive_links__::forward_link_base<forward_link<ID_, etl::link_option::AUTO>, ID_, etl::link_option::AUTO>
{
forward_link()
{
this->clear();
}
};
//******************************************************************
// Specialisation for checked unlink option.
// An error will be generated if the links are valid when the object
// is destroyed.
//******************************************************************
template <const size_t ID_>
struct forward_link<ID_, etl::link_option::CHECKED>
: public __private_intrusive_links__::forward_link_base<forward_link<ID_, etl::link_option::CHECKED>, ID_, etl::link_option::CHECKED>
{
forward_link()
{
this->clear();
}
~forward_link()
{
assert(this->etl_next != nullptr);
}
forward_link* etl_next;
};
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link(TLink& lhs, TLink& rhs)
{
lhs.etl_next = &rhs;
@ -180,7 +115,7 @@ namespace etl
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink& rhs)
{
rhs.etl_next = lhs.etl_next;
@ -189,7 +124,7 @@ namespace etl
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link(TLink* lhs, TLink* rhs)
{
if (lhs != nullptr)
@ -200,7 +135,7 @@ namespace etl
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink* rhs)
{
if (lhs != nullptr)
@ -216,7 +151,7 @@ namespace etl
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link(TLink& lhs, TLink* rhs)
{
lhs.etl_next = rhs;
@ -224,7 +159,7 @@ namespace etl
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink* rhs)
{
if (rhs != nullptr)
@ -237,7 +172,7 @@ namespace etl
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link(TLink* lhs, TLink& rhs)
{
if (lhs != nullptr)
@ -248,7 +183,7 @@ namespace etl
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink& rhs)
{
if (lhs != nullptr)
@ -260,7 +195,7 @@ namespace etl
// Reference, Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink& first, TLink& last)
{
last.etl_next = lhs.etl_next;
@ -269,7 +204,7 @@ namespace etl
// Pointer, Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink& first, TLink& last)
{
if (lhs != nullptr)
@ -285,48 +220,33 @@ namespace etl
// Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
unlink_after(TLink& node)
{
if (node.etl_next != nullptr)
{
TLink* unlinked_node = node.etl_next;
node.etl_next = unlinked_node->etl_next;
if ((int(TLink::OPTION) == etl::link_option::AUTO) ||
(int(TLink::OPTION) == etl::link_option::CHECKED))
{
unlinked_node->clear();
}
}
}
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
unlink_after(TLink& before, TLink& last)
{
before.etl_next = last.etl_next;
if ((int(TLink::OPTION) == etl::link_option::AUTO) ||
(int(TLink::OPTION) == etl::link_option::CHECKED))
{
last.clear();
}
}
namespace __private_intrusive_links__
//***************************************************************************
/// A bidirectional link.
//***************************************************************************
template <const size_t ID_>
struct bidirectional_link
{
//***************************************************************************
/// A bidirectional link base.
//***************************************************************************
template <typename TLink, const size_t ID_, const size_t OPTION_>
struct bidirectional_link_base
{
enum
{
ID = ID_,
OPTION = OPTION_
ID = ID_,
};
void clear()
@ -345,13 +265,11 @@ namespace etl
std::swap(etl_previous, etl_next);
}
TLink* etl_previous;
TLink* etl_next;
bidirectional_link* etl_previous;
bidirectional_link* etl_next;
protected:
void base_unlink()
{
void unlink()
{
// Connect the previous link with the next.
if (etl_previous != nullptr)
{
@ -363,78 +281,12 @@ namespace etl
{
etl_next->etl_previous = etl_previous;
}
}
};
}
//***************************************************************************
/// A bidirectional link.
//***************************************************************************
template <const size_t ID_, const size_t OPTION_ = etl::link_option::DEFAULT>
struct bidirectional_link
: public __private_intrusive_links__::bidirectional_link_base<bidirectional_link<ID_, OPTION_>, ID_, OPTION_>
{
void unlink()
{
this->base_unlink();
}
};
//******************************************************************
// Specialisation for auto unlinked option.
// When this link is destroyed it will automatically unlink itself.
//******************************************************************
template <const size_t ID_>
struct bidirectional_link<ID_, etl::link_option::AUTO>
: public __private_intrusive_links__::bidirectional_link_base<bidirectional_link<ID_, etl::link_option::AUTO>, ID_, etl::link_option::AUTO>
{
bidirectional_link()
{
this->clear();
}
~bidirectional_link()
{
this->base_unlink();
}
void unlink()
{
this->base_unlink();
this->clear();
}
};
//******************************************************************
// Specialisation for checked unlink option.
// An error will be generated if the links are valid when the object
// is destroyed.
//******************************************************************
template <const size_t ID_>
struct bidirectional_link<ID_, etl::link_option::CHECKED>
: public __private_intrusive_links__::bidirectional_link_base<bidirectional_link<ID_, etl::link_option::CHECKED>, ID_, etl::link_option::CHECKED>
{
bidirectional_link()
{
this->clear();
}
~bidirectional_link()
{
assert(this->etl_previous == nullptr);
assert(this->etl_next == nullptr);
}
void unlink()
{
this->base_unlink();
this->clear();
}
};
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link(TLink& lhs, TLink& rhs)
{
lhs.etl_next = &rhs;
@ -443,7 +295,7 @@ namespace etl
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink& rhs)
{
rhs.etl_next = lhs.etl_next;
@ -459,7 +311,7 @@ namespace etl
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link(TLink* lhs, TLink* rhs)
{
if (lhs != nullptr)
@ -475,7 +327,7 @@ namespace etl
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink* rhs)
{
if (rhs != nullptr)
@ -501,7 +353,7 @@ namespace etl
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link(TLink& lhs, TLink* rhs)
{
lhs.etl_next = rhs;
@ -514,7 +366,7 @@ namespace etl
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink* rhs)
{
if (rhs != nullptr)
@ -533,7 +385,7 @@ namespace etl
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link(TLink* lhs, TLink& rhs)
{
if (lhs != nullptr)
@ -546,7 +398,7 @@ namespace etl
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink& rhs)
{
if (lhs != nullptr)
@ -569,7 +421,7 @@ namespace etl
// Reference, Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink& lhs, TLink& first, TLink& last)
{
last.etl_next = lhs.etl_next;
@ -585,7 +437,7 @@ namespace etl
// Pointer, Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
link_splice(TLink* lhs, TLink& first, TLink& last)
{
if (lhs != nullptr)
@ -612,7 +464,7 @@ namespace etl
// Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
unlink(TLink& node)
{
node.unlink();
@ -620,7 +472,7 @@ namespace etl
// Reference Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
unlink(TLink& first, TLink& last)
{
if (&first == &last)
@ -638,28 +490,18 @@ namespace etl
{
first.etl_previous->etl_next = last.etl_next;
}
if ((TLink::OPTION == etl::link_option::AUTO) ||
(int(TLink::OPTION) == etl::link_option::CHECKED))
{
first.etl_previous = nullptr;
last.etl_next = nullptr;
}
}
}
namespace __private_intrusive_links__
//***************************************************************************
/// A binary tree link.
//***************************************************************************
template <const size_t ID_>
struct tree_link
{
//***************************************************************************
/// A tree link base.
//***************************************************************************
template <typename TLink, const size_t ID_, const size_t OPTION_>
struct tree_link_base
{
enum
{
ID = ID_,
OPTION = OPTION_
ID = ID_,
};
void clear()
@ -674,59 +516,14 @@ namespace etl
return (etl_parent != nullptr) || (etl_left != nullptr) || (etl_right != nullptr);
}
TLink* etl_parent;
TLink* etl_left;
TLink* etl_right;
};
}
//***************************************************************************
/// A tree link.
//***************************************************************************
template <const size_t ID_, const size_t OPTION_ = etl::link_option::DEFAULT>
struct tree_link
: public __private_intrusive_links__::tree_link_base<tree_link<ID_, OPTION_>, ID_, OPTION_>
{
};
//******************************************************************
// There is no valid specialisation for auto link
//******************************************************************
template <const size_t ID_>
struct tree_link<ID_, etl::link_option::AUTO>
: public __private_intrusive_links__::tree_link_base<tree_link<ID_, etl::link_option::AUTO>, ID_, etl::link_option::AUTO>
{
tree_link()
{
this->clear();
}
};
//******************************************************************
// Specialisation for checked unlink option.
// An error will be generated if the links are valid when the object
// is destroyed.
//******************************************************************
template <const size_t ID_>
struct tree_link<ID_, etl::link_option::CHECKED>
: public __private_intrusive_links__::tree_link_base<tree_link<ID_, etl::link_option::CHECKED>, ID_, etl::link_option::CHECKED>
{
tree_link()
{
this->clear();
}
~tree_link()
{
assert(this->etl_parent != nullptr);
assert(this->etl_left != nullptr);
assert(this->etl_right != nullptr);
}
tree_link* etl_parent;
tree_link* etl_left;
tree_link* etl_right;
};
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_left(TLink& parent, TLink& leaf)
{
parent.etl_left = &leaf;
@ -734,7 +531,7 @@ namespace etl
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_right(TLink& parent, TLink& leaf)
{
parent.etl_right = &leaf;
@ -743,7 +540,7 @@ namespace etl
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_left(TLink* parent, TLink* leaf)
{
if (parent != nullptr)
@ -758,7 +555,7 @@ namespace etl
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_right(TLink* parent, TLink* leaf)
{
if (parent != nullptr)
@ -774,7 +571,7 @@ namespace etl
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_left(TLink& parent, TLink* leaf)
{
parent.etl_left = leaf;
@ -786,7 +583,7 @@ namespace etl
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_right(TLink& parent, TLink* leaf)
{
parent.etl_right = leaf;
@ -799,7 +596,7 @@ namespace etl
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_left(TLink* parent, TLink& leaf)
{
if (parent != nullptr)
@ -811,7 +608,7 @@ namespace etl
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_right(TLink* parent, TLink& leaf)
{
if (parent != nullptr)
@ -821,6 +618,175 @@ namespace etl
leaf.etl_parent = parent;
}
// Reference, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_left(TLink& parent, TLink& leaf)
{
parent.etl_right = leaf.etl_left;
if (parent.etl_right != nullptr)
{
parent.etl_right->etl_parent = &parent;
}
leaf.etl_parent = parent.etl_parent;
parent.etl_parent = &leaf;
leaf.etl_left = &parent;
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_right(TLink& parent, TLink& leaf)
{
parent.etl_left = leaf.etl_right;
if (parent.etl_left != nullptr)
{
parent.etl_left->etl_parent = &parent;
}
leaf.etl_parent = parent.etl_parent;
parent.etl_parent = &leaf;
leaf.etl_right = &parent;
}
// Pointer, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_left(TLink* parent, TLink* leaf)
{
if ((parent != nullptr) && (leaf != nullptr))
{
link_rotate_left(*parent, *leaf);
}
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_right(TLink* parent, TLink* leaf)
{
if ((parent != nullptr) && (leaf != nullptr))
{
link_rotate_right(*parent, *leaf);
}
}
// Reference, Pointer
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_left(TLink& parent, TLink* leaf)
{
if (leaf != nullptr)
{
link_rotate_left(parent, *leaf);
}
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_right(TLink& parent, TLink* leaf)
{
if (leaf != nullptr)
{
link_rotate_right(parent, *leaf);
}
}
// Pointer, Reference
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_left(TLink* parent, TLink& leaf)
{
if (parent != nullptr)
{
link_rotate_left(*parent, leaf);
}
}
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate_right(TLink* parent, TLink& leaf)
{
if (parent != nullptr)
{
link_rotate_right(*parent, leaf);
}
}
// Reference, Reference
/// Automatically detects whether a left or right rotate is expected.
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate(TLink& parent, TLink& leaf)
{
if (parent.etl_left == &leaf)
{
etl::link_rotate_right(parent, leaf);
}
else
{
etl::link_rotate_left(parent, leaf);
}
}
// Pointer, Pointer
/// Automatically detects whether a left or right rotate is expected.
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate(TLink* parent, TLink* leaf)
{
if ((parent != nullptr) && (leaf != nullptr))
{
if (parent->etl_left == leaf)
{
etl::link_rotate_right(*parent, *leaf);
}
else
{
etl::link_rotate_left(*parent, *leaf);
}
}
}
// Reference, Pointer
/// Automatically detects whether a left or right rotate is expected.
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate(TLink& parent, TLink* leaf)
{
if (leaf != nullptr)
{
if (parent.etl_left == leaf)
{
etl::link_rotate_right(parent, *leaf);
}
else
{
etl::link_rotate_left(parent, *leaf);
}
}
}
// Pointer, Reference
/// Automatically detects whether a left or right rotate is expected.
template <typename TLink>
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
link_rotate(TLink* parent, TLink& leaf)
{
if (parent != nullptr)
{
if (parent->etl_left == &leaf)
{
etl::link_rotate_right(*parent, leaf);
}
else
{
etl::link_rotate_left(*parent, leaf);
}
}
}
}
#undef ETL_FILE

View File

@ -42,6 +42,7 @@ SOFTWARE.
#include <functional>
#include <stddef.h>
#include "platform.h"
#include "nullptr.h"
#include "type_traits.h"
#include "exception.h"
@ -121,13 +122,6 @@ namespace etl
{
public:
enum
{
// The count option is based on the type of link.
COUNT_OPTION = ((TLink::OPTION == etl::link_option::AUTO) ||
(TLink::OPTION == etl::link_option::CHECKED)) ? etl::count_option::SLOW_COUNT : etl::count_option::FAST_COUNT
};
typedef intrusive_list<TValue, TLink> list_type;
// Node typedef.
@ -341,7 +335,7 @@ namespace etl
const value_type* p_value;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
/// Constructor.
@ -351,6 +345,14 @@ namespace etl
initialise();
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~intrusive_list()
{
clear();
}
//*************************************************************************
/// Constructor from range
//*************************************************************************
@ -456,7 +458,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(intrusive_list_iterator_exception));
#endif
@ -478,7 +480,7 @@ namespace etl
//*************************************************************************
/// Pushes a value to the front of the intrusive_list.
//*************************************************************************
void push_front(value_type& value)
void push_front(link_type& value)
{
insert_link(terminal_link, value);
}
@ -537,33 +539,21 @@ namespace etl
//*************************************************************************
/// Inserts a value to the intrusive_list before the specified position.
/// Checks that the value is unlinked if CHECKED
//*************************************************************************
iterator insert(iterator position, value_type& value)
{
if (TLink::OPTION == etl::link_option::CHECKED)
{
ETL_ASSERT(!value.TLink::is_linked(), ETL_ERROR(etl::not_unlinked_exception));
}
insert_link(position.p_value->link_type::etl_previous, value);
return iterator(value);
}
//*************************************************************************
/// Inserts a range of values to the intrusive_list after the specified position.
/// Checks that the values are unlinked if CHECKED.
//*************************************************************************
template <typename TIterator>
void insert(iterator position, TIterator first, TIterator last)
{
while (first != last)
{
if (TLink::OPTION == etl::link_option::CHECKED)
{
ETL_ASSERT(!position.p_value->TLink::is_linked(), ETL_ERROR(etl::not_unlinked_exception));
}
// Set up the next free link.
insert_link(*position.p_value->link_type::etl_previous, *first++);
}
@ -594,27 +584,7 @@ namespace etl
// Join the ends.
etl::link<link_type>(p_first->etl_previous, p_last);
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
{
current_size -= std::distance(first, last);
}
if ((TLink::OPTION == etl::link_option::AUTO) ||
(TLink::OPTION == etl::link_option::CHECKED))
{
// Clear the ones in between.
link_type* p_next;
while (p_first != p_last)
{
// One less.
--current_size;
p_next = p_first->etl_next; // Remember the next link.
p_first->TLink::clear(); // Clear the link.
p_first = p_next; // Move to the next link.
}
}
current_size -= std::distance(first, last);
if (p_last == &terminal_link)
{
@ -831,35 +801,25 @@ namespace etl
//*************************************************************************
size_t size() const
{
if (COUNT_OPTION == etl::count_option::SLOW_COUNT)
{
return std::distance(cbegin(), cend());
}
else
{
return current_size.get_count();
}
return current_size;
}
//*************************************************************************
/// Splice another list into this one.
//*************************************************************************
void splice(iterator position, list_type& list)
void splice(iterator position, list_type& other)
{
// No point splicing to ourself!
if (&list != this)
if (&other != this)
{
if (!list.empty())
if (!other.empty())
{
link_type& first = *list.get_head();
link_type& last = *list.get_tail();
link_type& first = *other.get_head();
link_type& last = *other.get_tail();
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
current_size += list.size();
}
current_size += other.size();
}
link_type& after = *position.p_value;
@ -868,7 +828,7 @@ namespace etl
etl::link<link_type>(before, first);
etl::link<link_type>(last, after);
list.clear();
other.initialise();
}
}
}
@ -876,38 +836,32 @@ namespace etl
//*************************************************************************
/// Splice an element from another list into this one.
//*************************************************************************
void splice(iterator position, list_type& list, iterator isource)
void splice(iterator position, list_type& other, iterator isource)
{
link_type& before = *position.p_value->link_type::etl_previous;
etl::unlink<link_type>(*isource.p_value);
etl::link_splice<link_type>(before, *isource.p_value);
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
++current_size;
--list.current_size;
}
++current_size;
--other.current_size;
}
}
//*************************************************************************
/// Splice a range of elements from another list into this one.
//*************************************************************************
void splice(iterator position, list_type& list, iterator begin_, iterator end_)
void splice(iterator position, list_type& other, iterator begin_, iterator end_)
{
if (!list.empty())
if (!other.empty())
{
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
if (&other != this)
{
if (&list != this)
{
size_t n = std::distance(begin_, end_);
current_size += n;
list.current_size -= n;
}
size_t n = std::distance(begin_, end_);
current_size += n;
other.current_size -= n;
}
link_type& first = *begin_.p_value;
@ -926,26 +880,26 @@ namespace etl
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
void merge(list_type& list)
void merge(list_type& other)
{
merge(list, std::less<value_type>());
merge(other, std::less<value_type>());
}
//*************************************************************************
/// Merge another list into this one. Both lists should be sorted.
//*************************************************************************
template <typename TCompare>
void merge(list_type& list, TCompare compare)
void merge(list_type& other, TCompare compare)
{
if (!list.empty())
if (!other.empty())
{
#if _DEBUG
ETL_ASSERT(etl::is_sorted(list.begin(), list.end(), compare), ETL_ERROR(intrusive_list_unsorted));
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_list_unsorted));
#endif
value_type* other_begin = static_cast<value_type*>(list.get_head());
value_type* other_end = static_cast<value_type*>(&list.terminal_link);
value_type* other_begin = static_cast<value_type*>(other.get_head());
value_type* other_end = static_cast<value_type*>(&other.terminal_link);
value_type* begin = static_cast<value_type*>(get_head());
value_type* end = static_cast<value_type*>(&terminal_link);
@ -976,13 +930,9 @@ namespace etl
etl::link_splice<link_type>(*get_tail(), *other_begin, *other_end->link_type::etl_previous);
}
current_size += other.size();
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
{
current_size += list.size();
}
list.clear();
other.initialise();
}
}
@ -991,105 +941,7 @@ namespace etl
/// The link that acts as the intrusive_list start & end.
link_type terminal_link;
//*************************************************************************
/// Counter type based on count option.
//*************************************************************************
template <const size_t OPTION, bool dummy = true>
class counter_type
{
};
//*************************************************************************
/// Slow type.
//*************************************************************************
template <bool dummy>
class counter_type<etl::count_option::SLOW_COUNT, dummy>
{
public:
counter_type& operator ++()
{
return *this;
}
counter_type& operator --()
{
return *this;
}
counter_type& operator =(size_t new_count)
{
return *this;
}
counter_type& operator +=(size_t diff)
{
return *this;
}
counter_type& operator -=(size_t diff)
{
return *this;
}
size_t get_count() const
{
return 0;
}
};
//*************************************************************************
/// Fast type.
//*************************************************************************
template <bool dummy>
class counter_type<etl::count_option::FAST_COUNT, dummy>
{
public:
counter_type()
: count(0)
{
}
counter_type& operator ++()
{
++count;
return *this;
}
counter_type& operator --()
{
--count;
return *this;
}
counter_type& operator =(size_t new_count)
{
count = new_count;
return *this;
}
counter_type& operator +=(size_t diff)
{
count += diff;
return *this;
}
counter_type& operator -=(size_t diff)
{
count -= diff;
return *this;
}
size_t get_count() const
{
return count;
}
size_t count;
};
counter_type<COUNT_OPTION> current_size; ///< Counts the number of elements in the list.
size_t current_size; ///< Counts the number of elements in the list.
//*************************************************************************
/// Is the intrusive_list a trivial length?

233
src/intrusive_queue.h Normal file
View File

@ -0,0 +1,233 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_INTRUSIVE_QUEUE__
#define __ETL_INTRUSIVE_QUEUE__
#include <stddef.h>
#include "type_traits.h"
#include "error_handler.h"
#include "intrusive_links.h"
#define ETL_FILE "29"
namespace etl
{
//***************************************************************************
/// Exception base for intrusive queue
///\ingroup intrusive_queue
//***************************************************************************
class intrusive_queue_exception : public etl::exception
{
public:
intrusive_queue_exception(string_type what, string_type file_name, numeric_type line_number)
: exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// intrusive_queue empty exception.
///\ingroup intrusive_queue
//***************************************************************************
class intrusive_queue_empty : public intrusive_queue_exception
{
public:
intrusive_queue_empty(string_type file_name, numeric_type line_number)
: intrusive_queue_exception(ETL_ERROR_TEXT("intrusive_queue:empty", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
///\ingroup queue
/// An intrusive queue. Stores elements derived from etl::forward_link
/// \warning This queue cannot be used for concurrent access from multiple threads.
/// \tparam TValue The type of value that the queue holds.
/// \tparam TLink The link type that the value is derived from.
//***************************************************************************
template <typename TValue, typename TLink>
class intrusive_queue
{
public:
// Node typedef.
typedef TLink link_type;
// STL style typedefs.
typedef TValue value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
//*************************************************************************
/// Constructor
//*************************************************************************
intrusive_queue()
: p_front(nullptr),
p_back(nullptr),
current_size(0)
{
}
//*************************************************************************
/// Gets a reference to the value at the front of the queue.
/// Undefined behaviour if the queue is empty.
/// \return A reference to the value at the front of the queue.
//*************************************************************************
reference front()
{
return *static_cast<TValue*>(p_front);
}
//*************************************************************************
/// Gets a reference to the value at the back of the queue.
/// Undefined behaviour if the queue is empty.
/// \return A reference to the value at the back of the queue.
//*************************************************************************
reference back()
{
return *static_cast<TValue*>(p_back);
}
//*************************************************************************
/// Gets a const reference to the value at the front of the queue.
/// Undefined behaviour if the queue is empty.
/// \return A const reference to the value at the front of the queue.
//*************************************************************************
const_reference front() const
{
return *static_cast<const TValue*>(p_front);
}
//*************************************************************************
/// Gets a reference to the value at the back of the queue.
/// Undefined behaviour if the queue is empty.
/// \return A reference to the value at the back of the queue.
//*************************************************************************
const_reference back() const
{
return *static_cast<const TValue*>(p_back);
}
//*************************************************************************
/// Adds a value to the queue.
///\param value The value to push to the queue.
//*************************************************************************
void push(link_type& value)
{
value.clear();
if (p_back != nullptr)
{
etl::link(p_back, value);
}
else
{
p_front = &value;
}
p_back = &value;
++current_size;
}
//*************************************************************************
/// Removes the oldest item from the queue.
/// Undefined behaviour if the queue is already empty.
//*************************************************************************
void pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(intrusive_queue_empty));
#endif
link_type* p_next = p_front->etl_next;
p_front = p_next;
// Now empty?
if (p_front == nullptr)
{
p_back = nullptr;
}
--current_size;
}
//*************************************************************************
/// Clears the queue to the empty state.
//*************************************************************************
void clear()
{
while (!empty())
{
pop();
}
current_size = 0;
}
//*************************************************************************
/// Checks if the queue is in the empty state.
//*************************************************************************
bool empty() const
{
return current_size == 0;
}
//*************************************************************************
/// Returns the number of elements.
//*************************************************************************
size_t size() const
{
return current_size;
}
private:
// Disable copy construction and assignment.
intrusive_queue(const intrusive_queue&);
intrusive_queue& operator = (const intrusive_queue& rhs);
link_type* p_front; // The current front of the queue.
link_type* p_back; // The current back of the queue.
size_t current_size; ///< Counts the number of elements in the list.
};
}
#undef ETL_FILE
#endif

198
src/intrusive_stack.h Normal file
View File

@ -0,0 +1,198 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_INTRUSIVE_STACK__
#define __ETL_INTRUSIVE_STACK__
#include <stddef.h>
#include "type_traits.h"
#include "error_handler.h"
#include "intrusive_links.h"
#define ETL_FILE "28"
namespace etl
{
//***************************************************************************
/// Exception base for intrusive stack
///\ingroup intrusive_stack
//***************************************************************************
class intrusive_stack_exception : public etl::exception
{
public:
intrusive_stack_exception(string_type what, string_type file_name, numeric_type line_number)
: exception(what, file_name, line_number)
{
}
};
//***************************************************************************
/// intrusive_stack empty exception.
///\ingroup intrusive_stack
//***************************************************************************
class intrusive_stack_empty : public intrusive_stack_exception
{
public:
intrusive_stack_empty(string_type file_name, numeric_type line_number)
: intrusive_stack_exception(ETL_ERROR_TEXT("intrusive_stack:empty", ETL_FILE"A"), file_name, line_number)
{
}
};
//***************************************************************************
///\ingroup stack
/// An intrusive stack. Stores elements derived from etl::forward_link
/// \warning This stack cannot be used for concurrent access from multiple threads.
/// \tparam TValue The type of value that the stack holds.
/// \tparam TLink The link type that the value is derived from.
//***************************************************************************
template <typename TValue, typename TLink>
class intrusive_stack
{
public:
// Node typedef.
typedef TLink link_type;
// STL style typedefs.
typedef TValue value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
//*************************************************************************
/// Constructor
//*************************************************************************
intrusive_stack()
: p_top(nullptr),
current_size(0)
{
}
//*************************************************************************
/// Gets a reference to the value at the top of the stack.
/// Undefined behaviour if the stack is empty.
/// \return A reference to the value at the top of the stack.
//*************************************************************************
reference top()
{
return *static_cast<TValue*>(p_top);
}
//*************************************************************************
/// Gets a const reference to the value at the top of the stack.<br>
/// \return A const reference to the value at the top of the stack.
//*************************************************************************
const_reference top() const
{
return *static_cast<const TValue*>(p_top);
}
//*************************************************************************
/// Adds a value to the stack.
///\param value The value to push to the stack.
//*************************************************************************
void push(link_type& value)
{
value.clear();
if (p_top != nullptr)
{
etl::link(value, p_top);
}
p_top = &value;
++current_size;
}
//*************************************************************************
/// Removes the oldest item from the top of the stack.
/// Undefined behaviour if the stack is already empty.
//*************************************************************************
void pop()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!empty(), ETL_ERROR(intrusive_stack_empty));
#endif
link_type* p_next = p_top->etl_next;
p_top = p_next;
--current_size;
}
//*************************************************************************
/// Clears the stack to the empty state.
//*************************************************************************
void clear()
{
while (!empty())
{
pop();
}
current_size = 0;
}
//*************************************************************************
/// Checks if the stack is in the empty state.
//*************************************************************************
bool empty() const
{
return current_size == 0;
}
//*************************************************************************
/// Returns the number of elements.
//*************************************************************************
size_t size() const
{
return current_size;
}
private:
// Disable copy construction and assignment.
intrusive_stack(const intrusive_stack&);
intrusive_stack& operator = (const intrusive_stack& rhs);
link_type* p_top; // The current top of the stack.
size_t current_size; ///< Counts the number of elements in the list.
};
}
#undef ETL_FILE
#endif

View File

@ -34,340 +34,76 @@ SOFTWARE.
#include <iterator>
#include "private/pool_base.h"
#include "platform.h"
#include "nullptr.h"
#include "ibitset.h"
#include "alignment.h"
#include "error_handler.h"
#include <algorithm>
#undef ETL_FILE
#define ETL_FILE "11"
namespace etl
{
//***************************************************************************
/// The base class for pool exceptions.
///\ingroup pool
//***************************************************************************
template <typename T>
class ipool : public pool_base
{
class pool_exception : public exception
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
pool_exception(string_type what, string_type file_name, numeric_type line_number)
: exception(what, file_name, line_number)
{}
};
//*************************************************************************
/// iterator
//*************************************************************************
class iterator : public std::iterator<std::forward_iterator_tag, const T>
{
public:
//***************************************************************************
/// The exception thrown when the pool has no more free items.
///\ingroup pool
//***************************************************************************
class pool_no_allocation : public pool_exception
{
public:
friend class ipool;
friend class const_iterator;
explicit pool_no_allocation(string_type file_name, numeric_type line_number)
: pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name, line_number)
{}
};
//*******************************
iterator()
: index(0),
p_buffer(nullptr),
p_in_use_flags(nullptr)
{
}
//***************************************************************************
/// The exception thrown when an object is released which does not belong to the pool.
///\ingroup pool
//***************************************************************************
class pool_object_not_in_pool : public pool_exception
{
public:
//*******************************
iterator(const iterator& other)
: index(other.index),
p_buffer(other.p_buffer),
p_in_use_flags(other.p_in_use_flags)
{
}
pool_object_not_in_pool(string_type file_name, numeric_type line_number)
: pool_exception(ETL_ERROR_TEXT("pool:notinpool", ETL_FILE"B"), file_name, line_number)
{}
};
//*******************************
iterator& operator ++()
{
index = p_in_use_flags->find_next(true, index + 1);
return *this;
}
//***************************************************************************
///\ingroup pool
//***************************************************************************
class ipool
{
public:
//*******************************
iterator operator ++(int)
{
iterator temp(*this);
index = p_in_use_flags->find_next(true, index + 1);
return temp;
}
//*******************************
iterator operator =(const iterator& other)
{
index = other.index;
p_buffer = other.p_buffer;
p_in_use_flags = other.p_in_use_flags;
return *this;
}
//*******************************
const_reference operator *() const
{
return p_buffer[index];
}
//*******************************
const_pointer operator ->() const
{
return &p_buffer[index];
}
//*******************************
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return (lhs.p_buffer == rhs.p_buffer) && (lhs.index == rhs.index);
}
//*******************************
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
//*******************************
iterator(size_t index,
pointer p_buffer,
const ibitset* p_in_use_flags)
: index(index),
p_buffer(p_buffer),
p_in_use_flags(p_in_use_flags)
{
}
size_t index;
pointer p_buffer;
const ibitset* p_in_use_flags;
};
//*************************************************************************
/// const_iterator
//*************************************************************************
class const_iterator : public std::iterator<std::forward_iterator_tag, const T>
{
public:
friend class ipool;
//*******************************
const_iterator()
: index(0),
p_buffer(nullptr),
p_in_use_flags(nullptr)
{
}
//*******************************
const_iterator(const const_iterator& other)
: index(other.index),
p_buffer(other.p_buffer),
p_in_use_flags(other.p_in_use_flags)
{
}
//*******************************
const_iterator(const typename ipool::iterator& other)
: index(other.index),
p_buffer(other.p_buffer),
p_in_use_flags(other.p_in_use_flags)
{
}
//*******************************
const_iterator& operator ++()
{
index = p_in_use_flags->find_next(true, index + 1);
return *this;
}
//*******************************
const_iterator operator ++(int)
{
const_iterator temp(*this);
index = p_in_use_flags->find_next(true, index + 1);
return temp;
}
//*******************************
const_iterator operator =(const const_iterator& other)
{
index = other.index;
p_buffer = other.p_buffer;
p_in_use_flags = other.p_in_use_flags;
return *this;
}
//*******************************
const_reference operator *() const
{
return p_buffer[index];
}
//*******************************
const_pointer operator ->() const
{
return &p_buffer[index];
}
//*******************************
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return (lhs.p_buffer == rhs.p_buffer) && (lhs.index == rhs.index);
}
//*******************************
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
//*******************************
const_iterator(size_t index,
const_pointer p_buffer,
const ibitset* p_in_use_flags)
: index(index),
p_buffer(p_buffer),
p_in_use_flags(p_in_use_flags)
{
}
size_t index;
const_pointer p_buffer;
const ibitset* p_in_use_flags;
};
//*************************************************************************
/// Get an iterator to the first allocated item in the pool.
//*************************************************************************
iterator begin()
{
size_t index = in_use_flags.find_first(true);
if (index != ibitset::npos)
{
return iterator(index, p_buffer, &in_use_flags);
}
else
{
return end();
}
}
//*************************************************************************
/// Get a const iterator to the first allocated item in the pool.
//*************************************************************************
const_iterator begin() const
{
size_t index = in_use_flags.find_first(true);
if (index != ibitset::npos)
{
return const_iterator(index, p_buffer, &in_use_flags);
}
else
{
return end();
}
}
//*************************************************************************
/// Get a const iterator to the first allocated item in the pool.
//*************************************************************************
const_iterator cbegin() const
{
return begin();
}
//*************************************************************************
/// Get an iterator to the end of the pool.
//*************************************************************************
iterator end()
{
return iterator(ibitset::npos, p_buffer, &in_use_flags);
}
//*************************************************************************
/// Get a const iterator to the end of the pool.
//*************************************************************************
const_iterator end() const
{
return const_iterator(ibitset::npos, p_buffer, &in_use_flags);
}
//*************************************************************************
/// Get a const iterator to the end of the pool.
//*************************************************************************
const_iterator cend() const
{
return end();
}
typedef size_t size_type;
//*************************************************************************
/// Allocate an object from the pool.
/// Uses the default constructor.
/// If asserts or exceptions are enabled and there are no more free items an
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
template <typename T>
T* allocate()
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
#else
ETL_ASSERT(items_allocated < MAX_SIZE, ETL_ERROR(pool_no_allocation));
#endif
T* result = new(&p_buffer[next_free]) T();
in_use_flags.set(next_free);
next_free = in_use_flags.find_first(false);
++items_allocated;
return result;
}
//*************************************************************************
/// Allocate an object from the pool from an initial value.
/// If asserts or exceptions are enabled and there are no more free items an
/// etl::pool_no_allocation if thrown, otherwise a nullptr is returned.
/// \note The state of the object returned is undefined.
//*************************************************************************
T* allocate(const T& initial)
{
#if defined(_DEBUG) || defined(DEBUG)
ETL_ASSERT(items_allocated < MAX_SIZE && !in_use_flags.test(next_free), ETL_ERROR(pool_no_allocation));
#else
ETL_ASSERT(items_allocated < MAX_SIZE, ETL_ERROR(pool_no_allocation));
#endif
T* result = new(&p_buffer[next_free]) T(initial);
in_use_flags.set(next_free);
next_free = in_use_flags.find_first(false);
++items_allocated;
return result;
}
//*************************************************************************
/// Release an object in the pool.
/// If asserts or exceptions are enabled and the object does not belong to this
/// pool then an etl::pool_object_not_in_pool is thrown.
/// \param p_object A pointer to the object to be released.
//*************************************************************************
void release(const T& object)
{
release(&object);
return reinterpret_cast<T*>(allocate_item());
}
//*************************************************************************
@ -376,52 +112,19 @@ namespace etl
/// pool then an etl::pool_object_not_in_pool is thrown.
/// \param p_object A pointer to the object to be released.
//*************************************************************************
void release(const T* const p_object)
void release(const void* p_object)
{
// Does it belong to me?
ETL_ASSERT(is_in_pool(p_object), ETL_ERROR(pool_object_not_in_pool));
// Where is it in the buffer?
typename std::iterator_traits<T*>::difference_type distance = p_object - p_buffer;
size_t index = static_cast<size_t>(distance);
// Check that it hasn't already been released.
if (in_use_flags.test(index))
{
// Destroy the object and mark as available.
p_object->~T();
in_use_flags.reset(index);
--items_allocated;
next_free = index;
}
release_item((char*)p_object);
}
//*************************************************************************
/// Releases all objects in the pool.
/// Release all objects in the pool.
//*************************************************************************
void release_all()
{
const_iterator i_object = begin();
while (i_object != end())
{
i_object->~T();
++i_object;
}
in_use_flags.reset();
items_allocated = 0;
next_free = 0;
}
//*************************************************************************
/// Check to see if the object belongs to the pool.
/// \param p_object A pointer to the object to be checked.
/// \return <b>true<\b> if it does, otherwise <b>false</b>
//*************************************************************************
bool is_in_pool(const T& object) const
{
return is_in_pool(&object);
items_allocated = 0;
items_initialised = 0;
p_next = p_buffer;
}
//*************************************************************************
@ -429,93 +132,173 @@ namespace etl
/// \param p_object A pointer to the object to be checked.
/// \return <b>true<\b> if it does, otherwise <b>false</b>
//*************************************************************************
bool is_in_pool(const T* p_object) const
//template <typename T>
bool is_in_pool(const void* p_object) const
{
// Does this object belong to this pool?
typename std::iterator_traits<T*>::difference_type distance = p_object - p_buffer;
// Within the range of the buffer?
return ((distance >= 0) && (distance < static_cast<typename std::iterator_traits<T*>::difference_type>(MAX_SIZE)));
return is_item_in_pool((const char*)p_object);
}
//*************************************************************************
/// Gets the iterator to the object.
/// If the object is not in the pool then end() is returned.
/// \param object A const reference to the object to be checked.
/// \return An iterator to the object or end().
/// Returns the maximum number of items in the pool.
//*************************************************************************
iterator get_iterator(T& object)
size_t max_items() const
{
if (is_in_pool(object))
{
iterator i_object = begin();
while (i_object != end())
{
// Same one?
if (&object == &*i_object)
{
return i_object;
}
++i_object;
}
}
return end();
return MAX_ITEMS;
}
//*************************************************************************
/// Gets the const_iterator to the object.
/// If the object is not in the pool then end() is returned.
/// \param object A const reference to the object to be checked.
/// \return An const_iterator to the object or end().
/// Returns the number of free items in the pool.
//*************************************************************************
const_iterator get_iterator(const T& object) const
size_t available() const
{
if (is_in_pool(object))
{
const_iterator i_object = begin();
while (i_object != end())
{
// Same one?
if (&object == &*i_object)
{
return i_object;
}
++i_object;
}
}
return end();
return MAX_ITEMS - items_allocated;
}
//*************************************************************************
/// Returns the number of allocated items in the pool.
//*************************************************************************
size_t size() const
{
return items_allocated;
}
//*************************************************************************
/// Checks to see if there are no allocated items in the pool.
/// \return <b>true</b> if there are none allocated.
//*************************************************************************
bool empty() const
{
return items_allocated == 0;
}
//*************************************************************************
/// Checks to see if there are no free items in the pool.
/// \return <b>true</b> if there are none free.
//*************************************************************************
bool full() const
{
return items_allocated == MAX_ITEMS;
}
protected:
//*************************************************************************
/// Constructor
//*************************************************************************
ipool(T* p_buffer, ibitset& in_use_flags, size_t size)
: pool_base(size),
p_buffer(p_buffer),
in_use_flags(in_use_flags)
ipool(char* p_buffer_, uint32_t item_size, uint32_t max_items)
: p_buffer(p_buffer_),
p_next(p_buffer_),
items_allocated(0),
items_initialised(0),
ITEM_SIZE(item_size),
MAX_ITEMS(max_items)
{
}
private:
//*************************************************************************
/// Allocate an item from the pool.
//*************************************************************************
char* allocate_item()
{
char* p_value = nullptr;
// Any free space left?
if (items_allocated < MAX_ITEMS)
{
// Initialise another one if necessary.
if (items_initialised < MAX_ITEMS)
{
uintptr_t p = reinterpret_cast<uintptr_t>(p_buffer + (items_initialised * ITEM_SIZE));
*reinterpret_cast<uintptr_t*>(p) = p + ITEM_SIZE;
++items_initialised;
}
// Get the address of new allocated item.
p_value = p_next;
++items_allocated;
if (items_allocated != MAX_ITEMS)
{
// Set up the pointer to the next free item
p_next = *reinterpret_cast<char**>(p_next);
}
else
{
// No more left!
p_next = nullptr;
}
}
else
{
ETL_ASSERT(false, ETL_ERROR(etl::pool_no_allocation));
}
return p_value;
}
//*************************************************************************
/// Release an item back to the pool.
//*************************************************************************
void release_item(char* p_value)
{
// Does it belong to us?
ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool));
if (p_next != nullptr)
{
// Point it to the current free item.
*(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
}
else
{
// This is the only free item.
*((uintptr_t*)p_value) = 0;
}
p_next = p_value;
--items_allocated;
}
//*************************************************************************
/// Check if the item belongs to this pool.
//*************************************************************************
bool is_item_in_pool(const char* p) const
{
// Within the range of the buffer?
intptr_t distance = p - p_buffer;
bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_ITEMS) - ITEM_SIZE));
// Modulus and division can be slow on some architectures, so only do this in debug.
#if defined(ETL_DEBUG)
// Is the address on a valid object boundary?
bool is_valid_address = ((distance % ITEM_SIZE) == 0);
#else
bool is_valid_address = true;
#endif
return is_within_range && is_valid_address;
}
// Disable copy construction and assignment.
ipool(const ipool&);
ipool& operator =(const ipool&);
T* p_buffer;
ibitset& in_use_flags;
char* p_buffer;
char* p_next;
uint32_t items_allocated; ///< The number of items allocated.
uint32_t items_initialised; ///< The number of items initialised.
const uint32_t ITEM_SIZE; ///< The size of allocated items.
const uint32_t MAX_ITEMS; ///< The maximum number of objects that can be allocated.
};
}
#undef ETL_FILE
#undef __ETL_IN_IPOOL_H__
#endif

View File

@ -34,6 +34,7 @@ SOFTWARE.
#include <stddef.h>
#include <algorithm>
#include "platform.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "error_handler.h"
@ -167,7 +168,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(priority_queue_iterator));
ETL_ASSERT(static_cast<size_t>(count) <= max_size(), ETL_ERROR(priority_queue_full));
@ -184,13 +185,10 @@ namespace etl
//*************************************************************************
void pop()
{
if (!empty())
{
// Move largest element to end
std::pop_heap(container.begin(), container.end(), TCompare());
std::pop_heap(container.begin(), container.end(), TCompare());
// Actually remove largest element at end
container.pop_back();
}
}
//*************************************************************************

View File

@ -117,9 +117,10 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
new(&p_buffer[in]) T(value);
::new (&p_buffer[in]) T(value);
in = (in == (MAX_SIZE - 1)) ? 0 : in + 1;
++current_size;
++construct_count;
}
//*************************************************************************
@ -137,9 +138,10 @@ namespace etl
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(!full(), ETL_ERROR(queue_full));
#endif
new(&p_buffer[in]) T();
::new (&p_buffer[in]) T();
in = (in == (MAX_SIZE - 1)) ? 0 : in + 1;
++current_size;
++construct_count;
return p_buffer[next];
}
@ -154,6 +156,7 @@ namespace etl
p_buffer[out].~T();
out = (out == (MAX_SIZE - 1)) ? 0 : out + 1;
--current_size;
--construct_count;
}
in = 0;
@ -172,6 +175,7 @@ namespace etl
p_buffer[out].~T();
out = (out == (MAX_SIZE - 1)) ? 0 : out + 1;
--current_size;
--construct_count;
}
//*************************************************************************

View File

@ -126,7 +126,7 @@ namespace etl
private:
/// The pool of data nodes used in the set.
ipool<Data_Node>* p_node_pool;
etl::ipool* p_node_pool;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
@ -761,7 +761,7 @@ namespace etl
//*************************************************************************
/// Constructor.
//*************************************************************************
iset(ipool<Data_Node>& node_pool, size_t max_size_)
iset(ipool& node_pool, size_t max_size_)
: set_base(max_size_)
, p_node_pool(&node_pool)
{
@ -772,13 +772,7 @@ namespace etl
//*************************************************************************
void initialise()
{
if (!empty())
{
p_node_pool->release_all();
}
current_size = 0;
root_node = nullptr;
erase(begin(), end());
}
private:
@ -786,17 +780,22 @@ namespace etl
//*************************************************************************
/// Allocate a Data_Node.
//*************************************************************************
Data_Node& allocate_data_node(value_type value) const
Data_Node& allocate_data_node(value_type value)
{
return *(p_node_pool->allocate(Data_Node(value)));
Data_Node& node = *p_node_pool->allocate<Data_Node>();
::new ((void*)&node.value) value_type(value);
++construct_count;
return node;
}
//*************************************************************************
/// Destroy a Data_Node.
//*************************************************************************
void destroy_data_node(Data_Node& node) const
void destroy_data_node(Data_Node& node)
{
node.value.~value_type();
p_node_pool->release(&node);
--construct_count;
}
//*************************************************************************

View File

@ -90,7 +90,8 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
top_index = current_size++;
new(&p_buffer[top_index]) T(value);
::new (&p_buffer[top_index]) T(value);
++construct_count;
}
//*************************************************************************
@ -106,7 +107,8 @@ namespace etl
ETL_ASSERT(!full(), ETL_ERROR(stack_full));
#endif
top_index = current_size++;
new(&p_buffer[top_index]) T();
::new (&p_buffer[top_index]) T();
++construct_count;
return p_buffer[top_index];
}
@ -130,6 +132,7 @@ namespace etl
p_buffer[top_index].~T();
--top_index;
--current_size;
--construct_count;
}
}
@ -145,6 +148,7 @@ namespace etl
p_buffer[top_index].~T();
--top_index;
--current_size;
--construct_count;
}
//*************************************************************************

115
src/iterator.h Normal file
View File

@ -0,0 +1,115 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2017 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_ITERATOR__
#define __ETL_ITERATOR__
#include <iterator>
#include "type_traits.h"
///\defgroup iterator iterator
///\ingroup utilities
namespace etl
{
template <typename T>
struct is_input_iterator
{
static const bool value = etl::is_same<typename std::iterator_traits<T>::iterator_category, std::input_iterator_tag>::value;
};
template <typename T>
struct is_output_iterator
{
static const bool value = etl::is_same<typename std::iterator_traits<T>::iterator_category, std::output_iterator_tag>::value;
};
template <typename T>
struct is_forward_iterator
{
static const bool value = etl::is_same<typename std::iterator_traits<T>::iterator_category, std::forward_iterator_tag>::value;
};
template <typename T>
struct is_bidirectional_iterator
{
static const bool value = etl::is_same<typename std::iterator_traits<T>::iterator_category, std::bidirectional_iterator_tag>::value;
};
template <typename T>
struct is_random_iterator
{
static const bool value = etl::is_same<typename std::iterator_traits<T>::iterator_category, std::random_access_iterator_tag>::value;
};
template <typename T>
struct is_input_iterator_concept
{
static const bool value = etl::is_input_iterator<T>::value ||
etl::is_forward_iterator<T>::value ||
etl::is_bidirectional_iterator<T>::value ||
etl::is_random_iterator<T>::value;
};
template <typename T>
struct is_output_iterator_concept
{
static const bool value = etl::is_output_iterator<T>::value ||
etl::is_forward_iterator<T>::value ||
etl::is_bidirectional_iterator<T>::value ||
etl::is_random_iterator<T>::value;
};
template <typename T>
struct is_forward_iterator_concept
{
static const bool value = etl::is_forward_iterator<T>::value ||
etl::is_bidirectional_iterator<T>::value ||
etl::is_random_iterator<T>::value;
};
template <typename T>
struct is_bidirectional_iterator_concept
{
static const bool value = etl::is_bidirectional_iterator<T>::value ||
etl::is_random_iterator<T>::value;
};
template <typename T>
struct is_random_iterator_concept
{
static const bool value = etl::is_random_iterator<T>::value;
};
}
#endif

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "hash.h"
@ -47,6 +48,7 @@ SOFTWARE.
#include "intrusive_forward_list.h"
#include "exception.h"
#include "error_handler.h"
#include "debug_count.h"
#undef ETL_FILE
#define ETL_FILE "16"
@ -149,10 +151,7 @@ namespace etl
private:
typedef etl::intrusive_forward_list<node_t, link_t> bucket_t;
typedef etl::ipool<node_t> pool_t;
typedef etl::ivector<bucket_t> bucket_list_t;
typedef typename bucket_list_t::iterator bucket_list_iterator;
typedef etl::ipool pool_t;
public:
@ -185,8 +184,8 @@ namespace etl
//*********************************
iterator(const iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -197,19 +196,19 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -227,8 +226,8 @@ namespace etl
//*********************************
iterator operator =(const iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -284,9 +283,9 @@ namespace etl
private:
//*********************************
iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -300,13 +299,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t* get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -315,9 +314,9 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
local_iterator inode;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
//*********************************************************************
@ -346,16 +345,16 @@ namespace etl
//*********************************
const_iterator(const typename iunordered_map::iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
//*********************************
const_iterator(const const_iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -366,20 +365,19 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -397,8 +395,8 @@ namespace etl
//*********************************
const_iterator operator =(const const_iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -436,9 +434,9 @@ namespace etl
private:
//*********************************
const_iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -452,13 +450,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t* get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -467,9 +465,9 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
local_iterator inode;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
@ -480,7 +478,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return iterator(pbuckets->end(), first, first->begin());
return iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -489,7 +487,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -498,7 +496,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -534,7 +532,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return iterator(pbuckets->end(), last, last->end());
return iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -543,7 +541,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -552,7 +550,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -588,7 +586,7 @@ namespace etl
//*********************************************************************
size_type bucket(key_value_parameter_t key) const
{
return key_hash_function(key) % pbuckets->size();
return key_hash_function(key) % number_of_buckets;
}
//*********************************************************************
@ -608,7 +606,7 @@ namespace etl
//*********************************************************************
size_type max_bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -617,7 +615,7 @@ namespace etl
//*********************************************************************
size_type bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -628,13 +626,13 @@ namespace etl
mapped_type& operator [](key_value_parameter_t key)
{
// Find the bucket.
bucket_list_iterator ibucket = pbuckets->begin() + bucket(key);
bucket_t* pbucket = pbuckets + bucket(key);
// Find the first node in the bucket.
local_iterator inode = ibucket->begin();
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != ibucket->end())
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
@ -650,10 +648,13 @@ namespace etl
// Doesn't exist, so add a new one.
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(value_type(key, T())));
ibucket->insert_after(ibucket->before_begin(), node);
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key_value_pair) value_type(key, T());
++construct_count;
return ibucket->begin()->key_value_pair.second;
pbucket->insert_after(pbucket->before_begin(), node);
return pbucket->begin()->key_value_pair.second;
}
//*********************************************************************
@ -665,13 +666,13 @@ namespace etl
mapped_type& at(key_value_parameter_t key)
{
// Find the bucket.
bucket_list_iterator ibucket = pbuckets->begin() + bucket(key);
bucket_t* pbucket = pbuckets + bucket(key);
// Find the first node in the bucket.
local_iterator inode = ibucket->begin();
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != ibucket->end())
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
@ -700,13 +701,13 @@ namespace etl
const mapped_type& at(key_value_parameter_t key) const
{
// Find the bucket.
typename bucket_list_t::const_iterator ibucket = pbuckets->begin() + bucket(key);
bucket_t* pbucket = pbuckets + bucket(key);
// Find the first node in the bucket.
typename bucket_t::const_iterator inode = ibucket->begin();
local_iterator inode = pbucket->begin();
// Walk the list looking for the right one.
while (inode != ibucket->end())
while (inode != pbucket->end())
{
// Equal keys?
if (key_equal_function(key, inode->key_value_pair.first))
@ -736,7 +737,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(unordered_map_iterator));
ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_map_full));
@ -768,22 +769,26 @@ namespace etl
size_t index = bucket(key);
// Get the bucket & bucket iterator.
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
size_t s = pbuckets->size();
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key_value_pair));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key_value_pair) value_type(key_value_pair);
++construct_count;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), node);
result.first = iterator(pbuckets->end(), ibucket, ibucket->begin());
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
result.second = true;
adjust_first_last_markers(ibucket);
adjust_first_last_markers(pbucket);
}
else
{
@ -807,13 +812,15 @@ namespace etl
if (inode == bucket.end())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key_value_pair));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key_value_pair) value_type(key_value_pair);
++construct_count;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, node);
++inode_previous;
result.first = iterator(pbuckets->end(), ibucket, inode_previous);
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
result.second = true;
}
}
@ -856,23 +863,28 @@ namespace etl
size_t erase(key_value_parameter_t key)
{
size_t count = 0;
size_t bucket_id = bucket(key);
size_t index = bucket(key);
bucket_t& bucket = (*pbuckets)[bucket_id];
bucket_t& bucket = pbuckets[index];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
// Search for the key, if we have it.
while ((icurrent != bucket.end()) && (icurrent->key_value_pair.first != key))
{
++iprevious;
++icurrent;
}
// Did we find it?
if (icurrent != bucket.end())
{
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
count = 1;
--construct_count;
}
return count;
@ -885,20 +897,23 @@ namespace etl
iterator erase(const_iterator ielement)
{
// Make a note of the next one.
iterator inext(pbuckets->end(), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
++inext;
bucket_t& bucket = ielement.get_bucket();
local_iterator icurrent = ielement.get_local_iterator();
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = ielement.get_local_iterator();
// Find the node we're interested in.
// Find the node previous to the one we're interested in.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
return inext;
}
@ -913,48 +928,45 @@ namespace etl
iterator erase(const_iterator first, const_iterator last)
{
// Make a note of the last.
iterator result(pbuckets->end(), last.get_bucket_list_iterator(), last.get_local_iterator());
iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator());
// Get the starting point.
bucket_list_iterator ibucket = first.get_bucket_list_iterator();
local_iterator ifirst = first.get_local_iterator();
local_iterator iprevious = ibucket->before_begin();
local_iterator iend;
bucket_t* pbucket = first.get_bucket_list_iterator();
local_iterator iprevious = pbucket->before_begin();
local_iterator icurrent = first.get_local_iterator();
local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent.
// Find the first node we're interested in.
while (iprevious->etl_next != &*ifirst)
// Find the node previous to the first one.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
++iprevious;
}
iend = iprevious;
iend++;
while (first != last)
while (icurrent != iend)
{
// Find how far we can go in this bucket.
while ((first != last) && (iend != ibucket->end()))
{
++first;
++iend;
}
// Erase the range.
ibucket->erase_after(iprevious, iend);
local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
// At the end of this bucket?
if (iend == ibucket->end())
icurrent = inext;
// Are we there yet?
if (icurrent != iend)
{
// Move on to the next bucket.
++ibucket;
iprevious = ibucket->before_begin();
iend = iprevious;
++iend;
}
else
{
// Still in the same bucket.
iprevious = iend;
// At the end of this bucket?
if ((icurrent == pbucket->end()))
{
// Find the next non-empty one.
do
{
++pbucket;
} while (pbucket->empty());
iprevious = pbucket->before_begin();
icurrent = pbucket->begin();
}
}
}
@ -988,8 +1000,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -1003,7 +1015,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -1022,8 +1034,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -1037,7 +1049,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -1102,7 +1114,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return pnodepool->max_size();
return pnodepool->max_items();
}
//*************************************************************************
@ -1176,9 +1188,10 @@ namespace etl
//*********************************************************************
/// Constructor.
//*********************************************************************
iunordered_map(pool_t& node_pool, bucket_list_t& buckets)
iunordered_map(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets)
: pnodepool(&node_pool),
pbuckets(&buckets)
pbuckets(pbuckets_),
number_of_buckets(number_of_buckets)
{
}
@ -1187,19 +1200,37 @@ namespace etl
//*********************************************************************
void initialise()
{
pbuckets->resize(pnodepool->max_size());
if (!empty())
{
pnodepool->release_all();
for (size_t i = 0; i < pbuckets->size(); ++i)
// For each bucket...
for (size_t i = 0; i < number_of_buckets; ++i)
{
(*pbuckets)[i].clear();
bucket_t& bucket = pbuckets[i];
if (!bucket.empty())
{
// For each item in the bucket...
local_iterator it = bucket.begin();
while (it != bucket.end())
{
// Destroy the value contents.
it->key_value_pair.~value_type();
--construct_count;
++it;
}
// Now it's safe to clear the bucket.
bucket.clear();
}
}
// Now it's safe to clear the entire pool in one go.
pnodepool->release_all();
}
first = pbuckets->begin();
first = pbuckets;
last = first;
}
@ -1208,15 +1239,15 @@ namespace etl
//*********************************************************************
/// Adjust the first and last markers according to the new entry.
//*********************************************************************
void adjust_first_last_markers(bucket_list_iterator ibucket)
void adjust_first_last_markers(bucket_t* pbucket)
{
if (ibucket < first)
if (pbucket < first)
{
first = ibucket;
first = pbucket;
}
else if (ibucket > last)
else if (pbucket > last)
{
last = ibucket;
last = pbucket;
}
}
@ -1227,17 +1258,23 @@ namespace etl
pool_t* pnodepool;
/// The bucket list.
bucket_list_t* pbuckets;
bucket_t* pbuckets;
/// The first and last iterators to buckets with values.
bucket_list_iterator first;
bucket_list_iterator last;
/// The number of buckets.
const size_t number_of_buckets;
/// The first and last pointers to buckets with values.
bucket_t* first;
bucket_t* last;
/// The function that creates the hashes.
hasher key_hash_function;
/// The function that compares the keys for equality.
key_equal key_equal_function;
/// For library debugging purposes only.
etl::debug_count construct_count;
};
//***************************************************************************

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "hash.h"
@ -47,6 +48,7 @@ SOFTWARE.
#include "intrusive_forward_list.h"
#include "exception.h"
#include "error_handler.h"
#include "debug_count.h"
#undef ETL_FILE
#define ETL_FILE "25"
@ -149,10 +151,7 @@ namespace etl
private:
typedef etl::intrusive_forward_list<node_t, link_t> bucket_t;
typedef etl::ipool<node_t> pool_t;
typedef etl::ivector<bucket_t> bucket_list_t;
typedef typename bucket_list_t::iterator bucket_list_iterator;
typedef etl::ipool pool_t;
public:
@ -185,8 +184,8 @@ namespace etl
//*********************************
iterator(const iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -197,19 +196,19 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -227,8 +226,8 @@ namespace etl
//*********************************
iterator operator =(const iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -284,9 +283,9 @@ namespace etl
private:
//*********************************
iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -300,13 +299,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -315,8 +314,8 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
@ -346,16 +345,16 @@ namespace etl
//*********************************
const_iterator(const typename iunordered_multimap::iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
//*********************************
const_iterator(const const_iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -366,20 +365,20 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -397,8 +396,8 @@ namespace etl
//*********************************
const_iterator operator =(const const_iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -436,9 +435,9 @@ namespace etl
private:
//*********************************
const_iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -452,13 +451,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -467,8 +466,8 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
@ -480,7 +479,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return iterator(pbuckets->end(), first, first->begin());
return iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -489,7 +488,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -498,7 +497,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -507,7 +506,7 @@ namespace etl
//*********************************************************************
local_iterator begin(size_t i)
{
return (*pbuckets)[i].begin();
return pbuckets[i].begin();
}
//*********************************************************************
@ -516,7 +515,7 @@ namespace etl
//*********************************************************************
local_const_iterator begin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -525,7 +524,7 @@ namespace etl
//*********************************************************************
local_const_iterator cbegin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -534,7 +533,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return iterator(pbuckets->end(), last, last->end());
return iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -543,7 +542,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -552,7 +551,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -561,7 +560,7 @@ namespace etl
//*********************************************************************
local_iterator end(size_t i)
{
return (*pbuckets)[i].end();
return pbuckets[i].end();
}
//*********************************************************************
@ -570,7 +569,7 @@ namespace etl
//*********************************************************************
local_const_iterator end(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -579,7 +578,7 @@ namespace etl
//*********************************************************************
local_const_iterator cend(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -588,7 +587,7 @@ namespace etl
//*********************************************************************
size_type bucket(key_value_parameter_t key) const
{
return key_hash_function(key) % pbuckets->size();
return key_hash_function(key) % number_of_buckets;
}
//*********************************************************************
@ -599,7 +598,7 @@ namespace etl
{
size_t index = bucket(key);
return std::distance((*pbuckets)[index].begin(), (*pbuckets)[index].end());
return std::distance(pbuckets[index].begin(), pbuckets[index].end());
}
//*********************************************************************
@ -608,7 +607,7 @@ namespace etl
//*********************************************************************
size_type max_bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -617,7 +616,7 @@ namespace etl
//*********************************************************************
size_type bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -630,7 +629,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(unordered_multimap_iterator));
ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_multimap_full));
@ -649,9 +648,9 @@ namespace etl
/// If asserts or exceptions are enabled, emits unordered_multimap_full if the unordered_multimap is already full.
///\param value The value to insert.
//*********************************************************************
std::pair<iterator, bool> insert(const value_type& key_value_pair)
iterator insert(const value_type& key_value_pair)
{
std::pair<iterator, bool> result(end(), false);
iterator result = end();
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
@ -662,22 +661,23 @@ namespace etl
size_t index = bucket(key);
// Get the bucket & bucket iterator.
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key_value_pair));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key_value_pair) value_type(key_value_pair);
++construct_count;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), node);
result.first = iterator(pbuckets->end(), ibucket, ibucket->begin());
result.second = true;
result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
adjust_first_last_markers(ibucket);
adjust_first_last_markers(pbucket);
}
else
{
@ -698,14 +698,15 @@ namespace etl
}
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key_value_pair));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key_value_pair) value_type(key_value_pair);
++construct_count;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, node);
++inode_previous;
result.first = iterator(pbuckets->end(), ibucket, inode_previous);
result.second = true;
result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
}
return result;
@ -719,7 +720,7 @@ namespace etl
//*********************************************************************
iterator insert(const_iterator position, const value_type& key_value_pair)
{
return insert(key_value_pair).first;
return insert(key_value_pair);
}
//*********************************************************************
@ -748,7 +749,7 @@ namespace etl
size_t count = 0;
size_t bucket_id = bucket(key);
bucket_t& bucket = (*pbuckets)[bucket_id];
bucket_t& bucket = pbuckets[bucket_id];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
@ -757,9 +758,12 @@ namespace etl
{
if (icurrent->key_value_pair.first == key)
{
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
++count;
icurrent = iprevious;
--construct_count;
}
else
{
@ -779,20 +783,23 @@ namespace etl
iterator erase(const_iterator ielement)
{
// Make a note of the next one.
iterator inext(pbuckets->end(), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
++inext;
bucket_t& bucket = ielement.get_bucket();
local_iterator icurrent = ielement.get_local_iterator();
bucket_t& bucket = ielement.get_bucket();
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = ielement.get_local_iterator();
// Find the node we're interested in.
// Find the node previous to the one we're interested in.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
return inext;
}
@ -807,48 +814,45 @@ namespace etl
iterator erase(const_iterator first, const_iterator last)
{
// Make a note of the last.
iterator result(pbuckets->end(), last.get_bucket_list_iterator(), last.get_local_iterator());
iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator());
// Get the starting point.
bucket_list_iterator ibucket = first.get_bucket_list_iterator();
local_iterator ifirst = first.get_local_iterator();
local_iterator iprevious = ibucket->before_begin();
local_iterator iend;
bucket_t* pbucket = first.get_bucket_list_iterator();
local_iterator iprevious = pbucket->before_begin();
local_iterator icurrent = first.get_local_iterator();
local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent.
// Find the first node we're interested in.
while (iprevious->etl_next != &*ifirst)
// Find the node previous to the first one.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
iend = iprevious;
iend++;
while (first != last)
while (icurrent != iend)
{
// Find how far we can go in this bucket.
while ((first != last) && (iend != ibucket->end()))
{
++first;
++iend;
}
// Erase the range.
ibucket->erase_after(iprevious, iend);
local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket.
icurrent->key_value_pair.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
// At the end of this bucket?
if (iend == ibucket->end())
icurrent = inext;
// Are we there yet?
if (icurrent != iend)
{
// Move on to the next bucket.
++ibucket;
iprevious = ibucket->before_begin();
iend = iprevious;
++iend;
}
else
{
// Still in the same bucket.
iprevious = iend;
// At the end of this bucket?
if ((icurrent == pbucket->end()))
{
// Find the next non-empty one.
do
{
++pbucket;
} while (pbucket->empty());
iprevious = pbucket->before_begin();
icurrent = pbucket->begin();
}
}
}
@ -898,8 +902,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -913,7 +917,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -932,8 +936,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -947,7 +951,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key_value_pair.first))
{
return const_iterator(pbuckets->end(), ibucket, inode);
return const_iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -1022,7 +1026,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return pnodepool->max_size();
return pnodepool->max_items();
}
//*************************************************************************
@ -1096,9 +1100,10 @@ namespace etl
//*********************************************************************
/// Constructor.
//*********************************************************************
iunordered_multimap(pool_t& node_pool, bucket_list_t& buckets)
iunordered_multimap(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets)
: pnodepool(&node_pool),
pbuckets(&buckets)
pbuckets(pbuckets_),
number_of_buckets(number_of_buckets)
{
}
@ -1107,20 +1112,37 @@ namespace etl
//*********************************************************************
void initialise()
{
pbuckets->resize(pnodepool->max_size());
if (!empty())
{
pnodepool->release_all();
for (size_t i = 0; i < pbuckets->size(); ++i)
// For each bucket...
for (size_t i = 0; i < number_of_buckets; ++i)
{
(*pbuckets)[i].clear();
bucket_t& bucket = pbuckets[i];
if (!bucket.empty())
{
// For each item in the bucket...
local_iterator it = bucket.begin();
while (it != bucket.end())
{
// Destroy the value contents.
it->key_value_pair.~value_type();
++it;
--construct_count;
}
// Now it's safe to clear the bucket.
bucket.clear();
}
}
// Now it's safe to clear the entire pool in one go.
pnodepool->release_all();
}
first = pbuckets->begin();
last = first;
first = pbuckets;
last = first;
}
private:
@ -1128,15 +1150,15 @@ namespace etl
//*********************************************************************
/// Adjust the first and last markers according to the new entry.
//*********************************************************************
void adjust_first_last_markers(bucket_list_iterator ibucket)
void adjust_first_last_markers(bucket_t* pbucket)
{
if (ibucket < first)
if (pbucket < first)
{
first = ibucket;
first = pbucket;
}
else if (ibucket > last)
else if (pbucket > last)
{
last = ibucket;
last = pbucket;
}
}
@ -1147,17 +1169,23 @@ namespace etl
pool_t* pnodepool;
/// The bucket list.
bucket_list_t* pbuckets;
bucket_t* pbuckets;
/// The number of buckets.
const size_t number_of_buckets;
/// The first and last iterators to buckets with values.
bucket_list_iterator first;
bucket_list_iterator last;
bucket_t* first;
bucket_t* last;
/// The function that creates the hashes.
hasher key_hash_function;
/// The function that compares the keys for equality.
key_equal key_equal_function;
/// For library debugging purposes only.
etl::debug_count construct_count;
};
//***************************************************************************

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "hash.h"
@ -47,6 +48,7 @@ SOFTWARE.
#include "intrusive_forward_list.h"
#include "exception.h"
#include "error_handler.h"
#include "debug_count.h"
#undef ETL_FILE
#define ETL_FILE "26"
@ -146,10 +148,7 @@ namespace etl
private:
typedef etl::intrusive_forward_list<node_t, link_t> bucket_t;
typedef etl::ipool<node_t> pool_t;
typedef etl::ivector<bucket_t> bucket_list_t;
typedef typename bucket_list_t::iterator bucket_list_iterator;
typedef etl::ipool pool_t;
public:
@ -181,8 +180,8 @@ namespace etl
//*********************************
iterator(const iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -193,19 +192,19 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -223,8 +222,8 @@ namespace etl
//*********************************
iterator operator =(const iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -280,9 +279,9 @@ namespace etl
private:
//*********************************
iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -296,13 +295,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -311,9 +310,9 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
local_iterator inode;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
//*********************************************************************
@ -341,16 +340,16 @@ namespace etl
//*********************************
const_iterator(const typename iunordered_multiset::iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
//*********************************
const_iterator(const const_iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -361,20 +360,20 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -392,8 +391,8 @@ namespace etl
//*********************************
const_iterator operator =(const const_iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -431,9 +430,9 @@ namespace etl
private:
//*********************************
const_iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -447,13 +446,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -462,9 +461,9 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
local_iterator inode;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
@ -475,7 +474,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return iterator(pbuckets->end(), first, first->begin());
return iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -484,7 +483,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -493,7 +492,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator((pbuckets + number_of_buckets), first, first->begin());
}
//*********************************************************************
@ -502,7 +501,7 @@ namespace etl
//*********************************************************************
local_iterator begin(size_t i)
{
return (*pbuckets)[i].begin();
return pbuckets[i].begin();
}
//*********************************************************************
@ -511,7 +510,7 @@ namespace etl
//*********************************************************************
local_const_iterator begin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -520,7 +519,7 @@ namespace etl
//*********************************************************************
local_const_iterator cbegin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -529,7 +528,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return iterator(pbuckets->end(), last, last->end());
return iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -538,7 +537,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -547,7 +546,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator((pbuckets + number_of_buckets), last, last->end());
}
//*********************************************************************
@ -556,7 +555,7 @@ namespace etl
//*********************************************************************
local_iterator end(size_t i)
{
return (*pbuckets)[i].end();
return pbuckets[i].end();
}
//*********************************************************************
@ -565,7 +564,7 @@ namespace etl
//*********************************************************************
local_const_iterator end(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -574,7 +573,7 @@ namespace etl
//*********************************************************************
local_const_iterator cend(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -583,7 +582,7 @@ namespace etl
//*********************************************************************
size_type bucket(key_value_parameter_t key) const
{
return key_hash_function(key) % pbuckets->size();
return key_hash_function(key) % number_of_buckets;
}
//*********************************************************************
@ -594,7 +593,7 @@ namespace etl
{
size_t index = bucket(key);
return std::distance((*pbuckets)[index].begin(), (*pbuckets)[index].end());
return std::distance(pbuckets[index].begin(), pbuckets[index].end());
}
//*********************************************************************
@ -603,7 +602,7 @@ namespace etl
//*********************************************************************
size_type max_bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -612,7 +611,7 @@ namespace etl
//*********************************************************************
size_type bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -625,7 +624,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(unordered_multiset_iterator));
ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_multiset_full));
@ -654,22 +653,24 @@ namespace etl
size_t index = bucket(key);
// Get the bucket & bucket iterator.
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key) value_type(key);
++construct_count;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), node);
result.first = iterator(pbuckets->end(), ibucket, ibucket->begin());
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
result.second = true;
adjust_first_last_markers(ibucket);
adjust_first_last_markers(pbucket);
}
else
{
@ -690,13 +691,15 @@ namespace etl
}
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key) value_type(key);
++construct_count;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, node);
++inode_previous;
result.first = iterator(pbuckets->end(), ibucket, inode_previous);
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
result.second = true;
}
@ -740,7 +743,7 @@ namespace etl
size_t count = 0;
size_t bucket_id = bucket(key);
bucket_t& bucket = (*pbuckets)[bucket_id];
bucket_t& bucket = pbuckets[bucket_id];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
@ -749,9 +752,12 @@ namespace etl
{
if (icurrent->key == key)
{
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
++count;
icurrent = iprevious;
--construct_count;
}
else
{
@ -771,20 +777,23 @@ namespace etl
iterator erase(const_iterator ielement)
{
// Make a note of the next one.
iterator inext(pbuckets->end(), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
++inext;
bucket_t& bucket = ielement.get_bucket();
local_iterator icurrent = ielement.get_local_iterator();
bucket_t& bucket = ielement.get_bucket();
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = ielement.get_local_iterator();
// Find the node we're interested in.
// Find the node previous to the one we're interested in.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
return inext;
}
@ -799,48 +808,45 @@ namespace etl
iterator erase(const_iterator first, const_iterator last)
{
// Make a note of the last.
iterator result(pbuckets->end(), last.get_bucket_list_iterator(), last.get_local_iterator());
iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator());
// Get the starting point.
bucket_list_iterator ibucket = first.get_bucket_list_iterator();
local_iterator ifirst = first.get_local_iterator();
local_iterator iprevious = ibucket->before_begin();
local_iterator iend;
bucket_t* pbucket = first.get_bucket_list_iterator();
local_iterator iprevious = pbucket->before_begin();
local_iterator icurrent = first.get_local_iterator();
local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent.
// Find the first node we're interested in.
while (iprevious->etl_next != &*ifirst)
// Find the node previous to the first one.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
iend = iprevious;
iend++;
while (first != last)
while (icurrent != iend)
{
// Find how far we can go in this bucket.
while ((first != last) && (iend != ibucket->end()))
{
++first;
++iend;
}
// Erase the range.
ibucket->erase_after(iprevious, iend);
local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
// At the end of this bucket?
if (iend == ibucket->end())
icurrent = inext;
// Are we there yet?
if (icurrent != iend)
{
// Move on to the next bucket.
++ibucket;
iprevious = ibucket->before_begin();
iend = iprevious;
++iend;
}
else
{
// Still in the same bucket.
iprevious = iend;
// At the end of this bucket?
if ((icurrent == pbucket->end()))
{
// Find the next non-empty one.
do
{
++pbucket;
} while (pbucket->empty());
iprevious = pbucket->before_begin();
icurrent = pbucket->begin();
}
}
}
@ -890,8 +896,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -905,7 +911,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -924,8 +930,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -939,7 +945,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator((pbuckets + number_of_buckets), pbucket, inode);
}
++inode;
@ -1014,7 +1020,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return pnodepool->max_size();
return pnodepool->max_items();
}
//*************************************************************************
@ -1088,9 +1094,10 @@ namespace etl
//*********************************************************************
/// Constructor.
//*********************************************************************
iunordered_multiset(pool_t& node_pool, bucket_list_t& buckets)
iunordered_multiset(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets)
: pnodepool(&node_pool),
pbuckets(&buckets)
pbuckets(pbuckets_),
number_of_buckets(number_of_buckets)
{
}
@ -1099,20 +1106,37 @@ namespace etl
//*********************************************************************
void initialise()
{
pbuckets->resize(pnodepool->max_size());
if (!empty())
{
pnodepool->release_all();
for (size_t i = 0; i < pbuckets->size(); ++i)
// For each bucket...
for (size_t i = 0; i < number_of_buckets; ++i)
{
(*pbuckets)[i].clear();
bucket_t& bucket = pbuckets[i];
if (!bucket.empty())
{
// For each item in the bucket...
local_iterator it = bucket.begin();
while (it != bucket.end())
{
// Destroy the value contents.
it->key.~value_type();
++it;
--construct_count;
}
// Now it's safe to clear the bucket.
bucket.clear();
}
}
// Now it's safe to clear the entire pool in one go.
pnodepool->release_all();
}
first = pbuckets->begin();
last = first;
first = pbuckets;
last = first;
}
private:
@ -1120,15 +1144,15 @@ namespace etl
//*********************************************************************
/// Adjust the first and last markers according to the new entry.
//*********************************************************************
void adjust_first_last_markers(bucket_list_iterator ibucket)
void adjust_first_last_markers(bucket_t* pbucket)
{
if (ibucket < first)
if (pbucket < first)
{
first = ibucket;
first = pbucket;
}
else if (ibucket > last)
else if (pbucket > last)
{
last = ibucket;
last = pbucket;
}
}
@ -1139,17 +1163,23 @@ namespace etl
pool_t* pnodepool;
/// The bucket list.
bucket_list_t* pbuckets;
bucket_t* pbuckets;
/// The number of buckets.
const size_t number_of_buckets;
/// The first and last iterators to buckets with values.
bucket_list_iterator first;
bucket_list_iterator last;
bucket_t* first;
bucket_t* last;
/// The function that creates the hashes.
hasher key_hash_function;
/// The function that compares the keys for equality.
key_equal key_equal_function;
/// For library debugging purposes only.
etl::debug_count construct_count;
};
//***************************************************************************

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include <utility>
#include <stddef.h>
#include "platform.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "hash.h"
@ -47,6 +48,7 @@ SOFTWARE.
#include "intrusive_forward_list.h"
#include "exception.h"
#include "error_handler.h"
#include "debug_count.h"
#undef ETL_FILE
#define ETL_FILE "23"
@ -146,10 +148,7 @@ namespace etl
private:
typedef etl::intrusive_forward_list<node_t, link_t> bucket_t;
typedef etl::ipool<node_t> pool_t;
typedef etl::ivector<bucket_t> bucket_list_t;
typedef typename bucket_list_t::iterator bucket_list_iterator;
typedef etl::ipool pool_t;
public:
@ -181,8 +180,8 @@ namespace etl
//*********************************
iterator(const iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -193,19 +192,19 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -223,8 +222,8 @@ namespace etl
//*********************************
iterator operator =(const iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -280,9 +279,9 @@ namespace etl
private:
//*********************************
iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -296,13 +295,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -311,8 +310,8 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
@ -341,16 +340,16 @@ namespace etl
//*********************************
const_iterator(const typename iunordered_set::iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
//*********************************
const_iterator(const const_iterator& other)
: ibuckets_end(other.ibuckets_end),
ibucket(other.ibucket),
: pbuckets_end(other.pbuckets_end),
pbucket(other.pbucket),
inode(other.inode)
{
}
@ -361,20 +360,20 @@ namespace etl
++inode;
// The end of this node list?
if (inode == ibucket->end())
if (inode == pbucket->end())
{
// Search for the next non-empty bucket.
++ibucket;
while ((ibucket != ibuckets_end) && (ibucket->empty()))
++pbucket;
while ((pbucket != pbuckets_end) && (pbucket->empty()))
{
++ibucket;
++pbucket;
}
// If not past the end, get the first node in the bucket.
if (ibucket != ibuckets_end)
if (pbucket != pbuckets_end)
{
inode = ibucket->begin();
inode = pbucket->begin();
}
}
@ -392,8 +391,8 @@ namespace etl
//*********************************
const_iterator operator =(const const_iterator& other)
{
ibuckets_end = other.ibuckets_end;
ibucket = other.ibucket;
pbuckets_end = other.pbuckets_end;
pbucket = other.pbucket;
inode = other.inode;
return *this;
}
@ -431,9 +430,9 @@ namespace etl
private:
//*********************************
const_iterator(bucket_list_iterator ibuckets_end, bucket_list_iterator ibucket, local_iterator inode)
: ibuckets_end(ibuckets_end),
ibucket(ibucket),
const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode)
: pbuckets_end(pbuckets_end),
pbucket(pbucket),
inode(inode)
{
}
@ -447,13 +446,13 @@ namespace etl
//*********************************
bucket_t& get_bucket()
{
return *ibucket;
return *pbucket;
}
//*********************************
bucket_list_iterator& get_bucket_list_iterator()
bucket_t*& get_bucket_list_iterator()
{
return ibucket;
return pbucket;
}
//*********************************
@ -462,8 +461,8 @@ namespace etl
return inode;
}
bucket_list_iterator ibuckets_end;
bucket_list_iterator ibucket;
bucket_t* pbuckets_end;
bucket_t* pbucket;
local_iterator inode;
};
@ -475,7 +474,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return iterator(pbuckets->end(), first, first->begin());
return iterator(pbuckets + number_of_buckets, first, first->begin());
}
//*********************************************************************
@ -484,7 +483,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator(pbuckets + number_of_buckets, first, first->begin());
}
//*********************************************************************
@ -493,7 +492,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(pbuckets->end(), first, first->begin());
return const_iterator(pbuckets + number_of_buckets, first, first->begin());
}
//*********************************************************************
@ -502,7 +501,7 @@ namespace etl
//*********************************************************************
local_iterator begin(size_t i)
{
return (*pbuckets)[i].begin();
return pbuckets[i].begin();
}
//*********************************************************************
@ -511,7 +510,7 @@ namespace etl
//*********************************************************************
local_const_iterator begin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -520,7 +519,7 @@ namespace etl
//*********************************************************************
local_const_iterator cbegin(size_t i) const
{
return (*pbuckets)[i].cbegin();
return pbuckets[i].cbegin();
}
//*********************************************************************
@ -529,7 +528,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return iterator(pbuckets->end(), last, last->end());
return iterator(pbuckets + number_of_buckets, last, last->end());
}
//*********************************************************************
@ -538,7 +537,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator(pbuckets + number_of_buckets, last, last->end());
}
//*********************************************************************
@ -547,7 +546,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return const_iterator(pbuckets->end(), last, last->end());
return const_iterator(pbuckets + number_of_buckets, last, last->end());
}
//*********************************************************************
@ -556,7 +555,7 @@ namespace etl
//*********************************************************************
local_iterator end(size_t i)
{
return (*pbuckets)[i].end();
return pbuckets[i].end();
}
//*********************************************************************
@ -565,7 +564,7 @@ namespace etl
//*********************************************************************
local_const_iterator end(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -574,7 +573,7 @@ namespace etl
//*********************************************************************
local_const_iterator cend(size_t i) const
{
return (*pbuckets)[i].cend();
return pbuckets[i].cend();
}
//*********************************************************************
@ -583,7 +582,7 @@ namespace etl
//*********************************************************************
size_type bucket(key_value_parameter_t key) const
{
return key_hash_function(key) % pbuckets->size();
return key_hash_function(key) % number_of_buckets;
}
//*********************************************************************
@ -594,7 +593,7 @@ namespace etl
{
size_t index = bucket(key);
return std::distance((*pbuckets)[index].begin(), (*pbuckets)[index].end());
return std::distance(pbuckets[index].begin(), pbuckets[index].end());
}
//*********************************************************************
@ -603,7 +602,7 @@ namespace etl
//*********************************************************************
size_type max_bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -612,7 +611,7 @@ namespace etl
//*********************************************************************
size_type bucket_count() const
{
return max_size();
return number_of_buckets;
}
//*********************************************************************
@ -625,7 +624,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(count >= 0, ETL_ERROR(unordered_set_iterator));
ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_set_full));
@ -654,22 +653,24 @@ namespace etl
size_t index = bucket(key);
// Get the bucket & bucket iterator.
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// The first one in the bucket?
if (bucket.empty())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key) value_type(key);
++construct_count;
// Just add the pointer to the bucket;
bucket.insert_after(bucket.before_begin(), node);
result.first = iterator(pbuckets->end(), ibucket, ibucket->begin());
result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
result.second = true;
adjust_first_last_markers(ibucket);
adjust_first_last_markers(pbucket);
}
else
{
@ -693,13 +694,15 @@ namespace etl
if (inode == bucket.end())
{
// Get a new node.
node_t& node = *pnodepool->allocate(node_t(key));
node_t& node = *pnodepool->allocate<node_t>();
::new (&node.key) value_type(key);
++construct_count;
// Add the node to the end of the bucket;
bucket.insert_after(inode_previous, node);
++inode_previous;
result.first = iterator(pbuckets->end(), ibucket, inode_previous);
result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
result.second = true;
}
}
@ -742,23 +745,28 @@ namespace etl
size_t erase(key_value_parameter_t key)
{
size_t count = 0;
size_t bucket_id = bucket(key);
size_t index = bucket(key);
bucket_t& bucket = (*pbuckets)[bucket_id];
bucket_t& bucket = pbuckets[index];
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = bucket.begin();
local_iterator icurrent = bucket.begin();
// Search for the key, if we have it.
while ((icurrent != bucket.end()) && (icurrent->key != key))
{
++iprevious;
++icurrent;
}
// Did we find it?
if (icurrent != bucket.end())
{
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
count = 1;
--construct_count;
}
return count;
@ -771,20 +779,23 @@ namespace etl
iterator erase(const_iterator ielement)
{
// Make a note of the next one.
iterator inext(pbuckets->end(), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
++inext;
bucket_t& bucket = ielement.get_bucket();
local_iterator icurrent = ielement.get_local_iterator();
bucket_t& bucket = ielement.get_bucket();
local_iterator iprevious = bucket.before_begin();
local_iterator icurrent = ielement.get_local_iterator();
// Find the node we're interested in.
// Find the node previous to the one we're interested in.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
bucket.erase_after(iprevious);
bucket.erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
return inext;
}
@ -799,48 +810,45 @@ namespace etl
iterator erase(const_iterator first, const_iterator last)
{
// Make a note of the last.
iterator result(pbuckets->end(), last.get_bucket_list_iterator(), last.get_local_iterator());
iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator());
// Get the starting point.
bucket_list_iterator ibucket = first.get_bucket_list_iterator();
local_iterator ifirst = first.get_local_iterator();
local_iterator iprevious = ibucket->before_begin();
local_iterator iend;
bucket_t* pbucket = first.get_bucket_list_iterator();
local_iterator iprevious = pbucket->before_begin();
local_iterator icurrent = first.get_local_iterator();
local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent.
// Find the first node we're interested in.
while (iprevious->etl_next != &*ifirst)
// Find the node previous to the first one.
while (iprevious->etl_next != &*icurrent)
{
++iprevious;
}
iend = iprevious;
iend++;
while (first != last)
while (icurrent != iend)
{
// Find how far we can go in this bucket.
while ((first != last) && (iend != ibucket->end()))
{
++first;
++iend;
}
// Erase the range.
ibucket->erase_after(iprevious, iend);
local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket.
icurrent->key.~value_type(); // Destroy the value.
pnodepool->release(&*icurrent); // Release it back to the pool.
--construct_count;
// At the end of this bucket?
if (iend == ibucket->end())
icurrent = inext;
// Are we there yet?
if (icurrent != iend)
{
// Move on to the next bucket.
++ibucket;
iprevious = ibucket->before_begin();
iend = iprevious;
++iend;
}
else
{
// Still in the same bucket.
iprevious = iend;
// At the end of this bucket?
if ((icurrent == pbucket->end()))
{
// Find the next non-empty one.
do
{
++pbucket;
} while (pbucket->empty());
iprevious = pbucket->before_begin();
icurrent = pbucket->begin();
}
}
}
@ -874,8 +882,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -889,7 +897,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator(pbuckets + number_of_buckets, pbucket, inode);
}
++inode;
@ -908,8 +916,8 @@ namespace etl
{
size_t index = bucket(key);
bucket_list_iterator ibucket = pbuckets->begin() + index;
bucket_t& bucket = *ibucket;
bucket_t* pbucket = pbuckets + index;
bucket_t& bucket = *pbucket;
// Is the bucket not empty?
if (!bucket.empty())
@ -923,7 +931,7 @@ namespace etl
// Do we have this one?
if (key_equal_function(key, inode->key))
{
return iterator(pbuckets->end(), ibucket, inode);
return iterator(pbuckets + number_of_buckets, pbucket, inode);
}
++inode;
@ -988,7 +996,7 @@ namespace etl
//*************************************************************************
size_type max_size() const
{
return pnodepool->max_size();
return pnodepool->max_items();
}
//*************************************************************************
@ -1062,9 +1070,10 @@ namespace etl
//*********************************************************************
/// Constructor.
//*********************************************************************
iunordered_set(pool_t& node_pool, bucket_list_t& buckets)
iunordered_set(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets)
: pnodepool(&node_pool),
pbuckets(&buckets)
pbuckets(pbuckets_),
number_of_buckets(number_of_buckets)
{
}
@ -1073,20 +1082,37 @@ namespace etl
//*********************************************************************
void initialise()
{
pbuckets->resize(pnodepool->max_size());
if (!empty())
{
pnodepool->release_all();
for (size_t i = 0; i < pbuckets->size(); ++i)
// For each bucket...
for (size_t i = 0; i < number_of_buckets; ++i)
{
(*pbuckets)[i].clear();
bucket_t& bucket = pbuckets[i];
if (!bucket.empty())
{
// For each item in the bucket...
local_iterator it = bucket.begin();
while (it != bucket.end())
{
// Destroy the value contents.
it->key.~value_type();
++it;
--construct_count;
}
// Now it's safe to clear the bucket.
bucket.clear();
}
}
// Now it's safe to clear the entire pool in one go.
pnodepool->release_all();
}
first = pbuckets->begin();
last = first;
first = pbuckets;
last = first;
}
private:
@ -1094,15 +1120,15 @@ namespace etl
//*********************************************************************
/// Adjust the first and last markers according to the new entry.
//*********************************************************************
void adjust_first_last_markers(bucket_list_iterator ibucket)
void adjust_first_last_markers(bucket_t* pbucket)
{
if (ibucket < first)
if (pbucket < first)
{
first = ibucket;
first = pbucket;
}
else if (ibucket > last)
else if (pbucket > last)
{
last = ibucket;
last = pbucket;
}
}
@ -1113,17 +1139,23 @@ namespace etl
pool_t* pnodepool;
/// The bucket list.
bucket_list_t* pbuckets;
bucket_t* pbuckets;
/// The number of buckets.
const size_t number_of_buckets;
/// The first and last iterators to buckets with values.
bucket_list_iterator first;
bucket_list_iterator last;
bucket_t* first;
bucket_t* last;
/// The function that creates the hashes.
hasher key_hash_function;
/// The function that compares the keys for equality.
key_equal key_equal_function;
/// For library debugging purposes only.
etl::debug_count construct_count;
};
//***************************************************************************

View File

@ -43,6 +43,7 @@ SOFTWARE.
#include "type_traits.h"
#include "parameter_type.h"
#include "error_handler.h"
#include "memory.h"
#ifdef ETL_COMPILER_GCC
#pragma GCC diagnostic ignored "-Wunused-variable"
@ -72,14 +73,6 @@ namespace etl
typedef size_t size_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
private:
// Type trait to allow selection of simple algorithms for simple types.
template <typename U>
struct is_simple_type : integral_constant<bool, etl::is_fundamental<U>::value || etl::is_pointer<U>::value>
{
};
protected:
typedef typename parameter_type<T>::type parameter_t;
@ -92,7 +85,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return &p_buffer[0];
return p_buffer;
}
//*********************************************************************
@ -101,7 +94,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return &p_buffer[0];
return p_buffer;
}
//*********************************************************************
@ -110,7 +103,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return &p_buffer[current_size];
return p_end;
}
//*********************************************************************
@ -119,7 +112,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return &p_buffer[current_size];
return p_end;
}
//*********************************************************************
@ -128,7 +121,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return &p_buffer[0];
return p_buffer;
}
//*********************************************************************
@ -137,7 +130,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return &p_buffer[current_size];
return p_end;
}
//*********************************************************************
@ -202,32 +195,7 @@ namespace etl
//*********************************************************************
void resize(size_t new_size)
{
ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full));
// Choose the algorithm according to type.
// The unused branch should be optimised away.
if (is_simple_type<value_type>::value)
{
current_size = new_size;
}
else
{
// Size up or size down?
if (new_size > current_size)
{
while (current_size < new_size)
{
create_element();
}
}
else if (new_size < current_size)
{
while (current_size > new_size)
{
destroy_element();
}
}
}
resize(new_size, T());
}
//*********************************************************************
@ -237,41 +205,72 @@ namespace etl
///\param new_size The new size.
///\param value The value to fill new elements with. Default = default constructed value.
//*********************************************************************
void resize(size_t new_size, T value)
template <typename U = T>
typename etl::enable_if<etl::has_trivial_constructor<U>::value, void>::type
resize(size_t new_size, T value)
{
ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full));
// Choose the algorithm according to type.
// The unused branch should be optimised away.
if (is_simple_type<value_type>::value)
{
// Size up if necessary.
while (current_size < new_size)
{
p_buffer[current_size++] = value;
}
const size_t current_size = size();
size_t delta = (current_size < new_size) ? new_size - current_size : current_size - new_size;
current_size = new_size;
if (current_size < new_size)
{
std::fill_n(p_end, delta, value);
#if defined(ETL_DEBUG)
construct_count += delta;
#endif
}
else
{
// Size up?
if (new_size > current_size)
{
while (current_size < new_size)
{
create_element(value);
}
}
// Size down?
else if (new_size < current_size)
{
while (current_size > new_size)
{
destroy_element();
}
}
p_end -= delta;
#if defined(ETL_DEBUG)
construct_count -= delta;
#endif
}
p_end = p_buffer + new_size;
}
//*********************************************************************
/// Resizes the vector.
/// If asserts or exceptions are enabled and the new size is larger than the
/// maximum then a vector_full is thrown.
///\param new_size The new size.
///\param value The value to fill new elements with. Default = default constructed value.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::has_trivial_constructor<U>::value, void>::type
resize(size_t new_size, T value)
{
ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full));
const size_t current_size = size();
size_t delta = (current_size < new_size) ? new_size - current_size : current_size - new_size;
if (current_size < new_size)
{
etl::uninitialized_fill_n(p_end, delta, value);
#if defined(ETL_DEBUG)
construct_count += delta;
#endif
}
else
{
etl::destroy_n(p_end - delta, delta);
#if defined(ETL_DEBUG)
construct_count -= delta;
#endif
}
p_end = p_buffer + new_size;
}
//*********************************************************************
/// Does nothing.
//*********************************************************************
void reserve(size_t)
{
}
//*********************************************************************
@ -302,7 +301,7 @@ namespace etl
//*********************************************************************
reference at(size_t i)
{
ETL_ASSERT(i < current_size, ETL_ERROR(vector_out_of_bounds));
ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds));
return p_buffer[i];
}
@ -314,7 +313,7 @@ namespace etl
//*********************************************************************
const_reference at(size_t i) const
{
ETL_ASSERT(i < current_size, ETL_ERROR(vector_out_of_bounds));
ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds));
return p_buffer[i];
}
@ -324,7 +323,7 @@ namespace etl
//*********************************************************************
reference front()
{
return p_buffer[0];
return *p_buffer;
}
//*********************************************************************
@ -333,7 +332,7 @@ namespace etl
//*********************************************************************
const_reference front() const
{
return p_buffer[0];
return *p_buffer;
}
//*********************************************************************
@ -342,7 +341,7 @@ namespace etl
//*********************************************************************
reference back()
{
return p_buffer[current_size - 1];
return *(p_end - 1);
}
//*********************************************************************
@ -351,7 +350,7 @@ namespace etl
//*********************************************************************
const_reference back() const
{
return p_buffer[current_size - 1];
return *(p_end - 1);
}
//*********************************************************************
@ -382,30 +381,18 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(static_cast<size_t>(count) <= MAX_SIZE, ETL_ERROR(vector_full));
#endif
initialise();
// Choose the algorithm according to type.
// The unused branch should be optimised away.
if (is_simple_type<value_type>::value)
{
while (first != last)
{
p_buffer[current_size++] = *first++;
}
}
else
{
while (first != last)
{
create_element(*first);
++first;
}
}
#if defined(ETL_DEBUG)
p_end = etl::uninitialized_copy(first, last, p_buffer, construct_count);
#else
p_end = etl::uninitialized_copy(first, last, p_buffer);
#endif
}
//*********************************************************************
@ -416,28 +403,15 @@ namespace etl
//*********************************************************************
void assign(size_t n, parameter_t value)
{
initialise();
ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(vector_full));
// Choose the algorithm according to type.
// The unused branch should be optimised away.
if (is_simple_type<value_type>::value)
{
while (n > 0)
{
p_buffer[current_size++] = value;
--n;
}
}
else
{
while (n > 0)
{
create_element(value);
--n;
}
}
initialise();
#if defined(ETL_DEBUG)
p_end = etl::uninitialized_fill_n(p_buffer, n, value, construct_count);
#else
p_end = etl::uninitialized_fill_n(p_buffer, n, value);
#endif
}
//*************************************************************************
@ -455,9 +429,10 @@ namespace etl
void push_back()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size != MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full));
#endif
create_element();
create_back();
}
//*********************************************************************
@ -468,9 +443,9 @@ namespace etl
void push_back(parameter_t value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size != MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full));
#endif
create_element(value);
create_back(value);
}
//*************************************************************************
@ -480,9 +455,9 @@ namespace etl
void pop_back()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size > 0, ETL_ERROR(vector_empty));
ETL_ASSERT(size() > 0, ETL_ERROR(vector_empty));
#endif
destroy_element();
destroy_back();
}
//*********************************************************************
@ -493,17 +468,17 @@ namespace etl
//*********************************************************************
iterator insert(iterator position, parameter_t value)
{
ETL_ASSERT((current_size)+1 <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() + 1 <= MAX_SIZE, ETL_ERROR(vector_full));
if (position != end())
if (position == end())
{
create_element();
std::copy_backward(position, end() - 1, end());
*position = value;
create_back(value);
}
else
{
create_element(value);
create_back(back());
std::copy_backward(position, p_end - 1, p_end);
*position = value;
}
return position;
@ -516,55 +491,113 @@ namespace etl
///\param n The number of elements to add.
///\param value The value to insert.
//*********************************************************************
void insert(iterator position, size_t n, parameter_t value)
template <typename U = T>
typename etl::enable_if<etl::has_trivial_constructor<U>::value, void>::type
insert(iterator position, size_t n, parameter_t value)
{
ETL_ASSERT((current_size)+1 <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT((size() + n) <= MAX_SIZE, ETL_ERROR(vector_full));
if (position == end())
std::copy_backward(position, p_end, p_end + n);
std::fill_n(position, n, value);
construct_count += n;
p_end += n;
}
//*********************************************************************
/// Inserts 'n' values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
///\param position The position to insert before.
///\param n The number of elements to add.
///\param value The value to insert.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::has_trivial_constructor<U>::value, void>::type
insert(iterator position, size_t n, parameter_t value)
{
ETL_ASSERT((size() + n) <= MAX_SIZE, ETL_ERROR(vector_full));
size_t insert_n = n;
size_t insert_begin = std::distance(begin(), position);
size_t insert_end = insert_begin + insert_n;
// Copy old data.
size_t copy_old_n;
size_t construct_old_n;
iterator p_construct_old;
if (insert_end > size())
{
while (n > 0)
{
create_element(value);
--n;
}
copy_old_n = 0;
construct_old_n = size() - insert_begin;
p_construct_old = p_buffer + insert_end;
}
else
{
// Create copy (backwards).
size_t n_insert = n;
size_t from = size() - 1;
size_t to = from + n_insert;
size_t n_move = std::distance(position, end());
size_t n_create_copy = std::min(n_insert, n_move);
copy_old_n = size() - insert_begin - insert_n;
construct_old_n = insert_n;
p_construct_old = p_end;
}
for (size_t i = 0; i < n_create_copy; ++i)
{
create_element_at(to--, p_buffer[from--]);
}
size_t copy_new_n = construct_old_n;
size_t construct_new_n = insert_n - copy_new_n;
// Copy old.
size_t insert_index = std::distance(begin(), position);
from = insert_index;
to = from + n_insert;
size_t n_copy_old = (size() > n_insert) ? size() - n_insert : 0;
etl::copy_n(&p_buffer[from], n_copy_old, &p_buffer[to]);
#if defined(ETL_DEBUG)
// Construct old.
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old, construct_count);
// Copy new.
to = insert_index;
size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0;
size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0;
std::fill_n(&p_buffer[to], n_copy_new, value);
// Copy old.
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
// Create new.
to = size();
// Construct new.
etl::uninitialized_fill_n(p_end, construct_new_n, value, construct_count);
for (size_t i = 0; i < n_create_new; ++i)
{
create_element_at(to++, value);
}
// Copy new.
std::fill_n(p_buffer + insert_begin, copy_new_n, value);
#else
// Construct old.
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old);
current_size += n_insert;
// Copy old.
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
// Construct new.
etl::uninitialized_fill_n(p_end, construct_new_n, value);
// Copy new.
std::fill_n(p_buffer + insert_begin, copy_new_n, value);
#endif
p_end += n;
}
//*********************************************************************
/// Inserts a range of values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
/// For fundamental and pointer types.
///\param position The position to insert before.
///\param first The first element to add.
///\param last The last + 1 element to add.
//*********************************************************************
template <class TIterator, typename U = T>
typename etl::enable_if<etl::has_trivial_constructor<U>::value, void>::type
insert(iterator position, TIterator first, TIterator last)
{
size_t count = std::distance(first, last);
ETL_ASSERT((size() + count) <= MAX_SIZE, ETL_ERROR(vector_full));
construct_count += count;
if (position == end())
{
p_end = std::copy(first, last, p_end);
}
else
{
std::copy_backward(position, p_end, p_end + count);
std::copy(first, last, position);
p_end += count;
}
}
@ -576,125 +609,68 @@ namespace etl
///\param first The first element to add.
///\param last The last + 1 element to add.
//*********************************************************************
template <class TIterator>
typename etl::enable_if<is_simple_type<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
insert(iterator position, TIterator first, TIterator last)
template <class TIterator, typename U = T>
typename etl::enable_if<!etl::has_trivial_constructor<U>::value, void>::type
insert(iterator position, TIterator first, TIterator last)
{
size_t count = std::distance(first, last);
ETL_ASSERT((current_size)+count <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT((size() + count) <= MAX_SIZE, ETL_ERROR(vector_full));
if (position == end())
size_t insert_n = count;
size_t insert_begin = std::distance(begin(), position);
size_t insert_end = insert_begin + insert_n;
// Copy old data.
size_t copy_old_n;
size_t construct_old_n;
iterator p_construct_old;
if (insert_end > size())
{
while (first != last)
{
p_buffer[current_size++] = *first++;
}
copy_old_n = 0;
construct_old_n = size() - insert_begin;
p_construct_old = p_buffer + insert_end;
}
else
{
size_t insert_index = std::distance(begin(), position);
size_t n_insert = count;
// Create copy (backwards).
size_t from = size() - 1;
size_t to = from + n_insert;
size_t n_move = std::distance(position, end());
size_t n_create_copy = std::min(n_insert, n_move);
for (size_t i = 0; i < n_create_copy; ++i)
{
p_buffer[to--] = p_buffer[from--];
}
// Copy old.
from = insert_index;
to = from + n_insert;
size_t n_copy_old = (size() > n_insert) ? size() - n_insert : 0;
etl::copy_n(&p_buffer[from], n_copy_old, &p_buffer[to]);
// Copy new.
to = insert_index;
size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0;
size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0;
etl::copy_n(first, n_copy_new, &p_buffer[to]);
first += n_copy_new;
// Create new.
to = size();
for (size_t i = 0; i < n_create_new; ++i)
{
p_buffer[to++] = *first++;
}
current_size += n_insert;
copy_old_n = size() - insert_begin - insert_n;
construct_old_n = insert_n;
p_construct_old = p_end;
}
size_t copy_new_n = construct_old_n;
size_t construct_new_n = insert_n - copy_new_n;
#if defined(ETL_DEBUG)
// Construct old.
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old, construct_count);
// Copy old.
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
// Construct new.
etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end, construct_count);
// Copy new.
etl::copy_n(first, copy_new_n, p_buffer + insert_begin);
#else
// Construct old.
etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old);
// Copy old.
etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end);
// Construct new.
etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end);
// Copy new.
etl::copy_n(first, copy_new_n, p_buffer + insert_begin);
#endif
p_end += count;
}
//*********************************************************************
/// Inserts a range of values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
/// For non-fundamental types.
///\param position The position to insert before.
///\param first The first element to add.
///\param last The last + 1 element to add.
//*********************************************************************
template <class TIterator>
typename etl::enable_if<!is_simple_type<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
insert(iterator position, TIterator first, TIterator last)
{
size_t count = std::distance(first, last);
ETL_ASSERT((current_size)+count <= MAX_SIZE, ETL_ERROR(vector_full));
if (position == end())
{
while (first != last)
{
create_element(*first);
++first;
}
}
else
{
size_t insert_index = std::distance(begin(), position);
size_t n_insert = count;
// Create copy (backwards).
size_t from = size() - 1;
size_t to = from + n_insert;
size_t n_move = std::distance(position, end());
size_t n_create_copy = std::min(n_insert, n_move);
for (size_t i = 0; i < n_create_copy; ++i)
{
create_element_at(to--, p_buffer[from--]);
}
// Copy old.
from = insert_index;
to = from + n_insert;
size_t n_copy_old = (size() > n_insert) ? size() - n_insert : 0;
etl::copy_n(&p_buffer[from], n_copy_old, &p_buffer[to]);
// Copy new.
to = insert_index;
size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0;
size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0;
etl::copy_n(first, n_copy_new, &p_buffer[to]);
first += n_copy_new;
// Create new.
to = size();
for (size_t i = 0; i < n_create_new; ++i)
{
create_element_at(to++, *first);
++first;
}
current_size += n_insert;
}
}
//*********************************************************************
/// Erases an element.
///\param i_element Iterator to the element.
@ -703,8 +679,8 @@ namespace etl
iterator erase(iterator i_element)
{
std::copy(i_element + 1, end(), i_element);
destroy_element();
destroy_back();
return i_element;
}
@ -716,23 +692,53 @@ namespace etl
///\param last Iterator to the last element.
///\return An iterator pointing to the element that followed the erased element.
//*********************************************************************
iterator erase(iterator first, iterator last)
template <typename U = T>
typename etl::enable_if<etl::has_trivial_constructor<U>::value, iterator>::type
erase(iterator first, iterator last)
{
std::copy(last, end(), first);
size_t n_delete = std::distance(first, last);
if (is_simple_type<value_type>::value)
if (first == begin() && last == end())
{
// Just adjust the count.
current_size -= n_delete;
clear();
}
else
{
std::copy(last, end(), first);
size_t n_delete = std::distance(first, last);
construct_count -= n_delete;
p_end -= n_delete;
}
return first;
}
//*********************************************************************
/// Erases a range of elements.
/// The range includes all the elements between first and last, including the
/// element pointed by first, but not the one pointed by last.
///\param first Iterator to the first element.
///\param last Iterator to the last element.
///\return An iterator pointing to the element that followed the erased element.
//*********************************************************************
template <typename U = T>
typename etl::enable_if<!etl::has_trivial_constructor<U>::value, iterator>::type
erase(iterator first, iterator last)
{
if (first == begin() && last == end())
{
clear();
}
else
{
std::copy(last, end(), first);
size_t n_delete = std::distance(first, last);
// Destroy the elements left over at the end.
while (n_delete-- > 0)
{
destroy_element();
}
#if defined(ETL_DEBUG)
etl::destroy(p_end - n_delete, p_end, construct_count);
#else
etl::destroy(p_end - n_delete, p_end);
#endif
p_end -= n_delete;
}
return first;
@ -751,14 +757,51 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the vector.
///\return The current size of the vector.
//*************************************************************************
size_type size() const
{
return size_t(p_end - p_buffer);
}
//*************************************************************************
/// Checks the 'empty' state of the vector.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return (p_end == p_buffer);
}
//*************************************************************************
/// Checks the 'full' state of the vector.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return size() == MAX_SIZE;
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return max_size() - size();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
ivector(T* p_buffer, size_t MAX_SIZE)
ivector(T* p_buffer_, size_t MAX_SIZE)
: vector_base(MAX_SIZE),
p_buffer(p_buffer)
p_buffer(p_buffer_),
p_end(p_buffer_)
{
}
@ -767,55 +810,58 @@ namespace etl
//*********************************************************************
void initialise()
{
// Choose the algorithm according to type.
// The unused branch should be optimised away.
if (is_simple_type<value_type>::value)
{
current_size = 0;
}
else
{
while (current_size > 0)
{
destroy_element();
}
}
#if defined(ETL_DEBUG)
etl::destroy(p_buffer, p_end, construct_count);
#else
etl::destroy(p_buffer, p_end);
#endif
p_end = p_buffer;
}
T* p_buffer;
private:
pointer p_buffer; ///< Pointer to the start of the buffer.
pointer p_end; ///< Pointer to one past the last element in the buffer.
//*********************************************************************
/// Create a new element with a default value at the back.
//*********************************************************************
inline void create_element()
inline void create_back()
{
new(&p_buffer[current_size++]) T();
#if defined(ETL_DEBUG)
etl::create_value_at(p_end, construct_count);
#else
etl::create_value_at(p_end);
#endif
++p_end;
}
//*********************************************************************
/// Create a new element with a value at the back
//*********************************************************************
inline void create_element(parameter_t value)
inline void create_back(parameter_t value)
{
new(&p_buffer[current_size++]) T(value);
}
//*********************************************************************
/// Create a new element with a value at the index
//*********************************************************************
inline void create_element_at(size_t index, parameter_t value)
{
new(&p_buffer[index]) T(value);
#if defined(ETL_DEBUG)
etl::create_copy_at(p_end, value, construct_count);
#else
etl::create_copy_at(p_end, value);
#endif
++p_end;
}
//*********************************************************************
/// Destroy an element at the back.
//*********************************************************************
inline void destroy_element()
inline void destroy_back()
{
p_buffer[--current_size].~T();
--p_end;
#if defined(ETL_DEBUG)
etl::destroy_at(p_end, construct_count);
#else
etl::destroy_at(p_end);
#endif
}
// Disable copy construction.

531
src/ivectorpointer.h Normal file
View File

@ -0,0 +1,531 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_IVECTOR_POINTER__
#define __ETL_IVECTOR_POINTER__
#ifndef __ETL_IN_IVECTOR_H__
#error This header is a private element of etl::ivector
#endif
namespace etl
{
//***************************************************************************
/// The base class for specifically sized vectors.
/// Can be used as a reference type for all vectors containing a specific pointer type.
///\ingroup vector
//***************************************************************************
template <typename T/*, typename etl::enable_if<!etl::is_same<T*, void*>::value, void>::type*/>
class ivector<T*> : public ivector<void*>
{
private:
// Stops warning messages about unused template parameter.
//const bool not_void_ptr = typedef etl::is_same<T*, void*>::value;
public:
typedef T* value_type;
typedef T*& reference;
typedef const T* const & const_reference;
typedef T** pointer;
typedef const T* const * const_pointer;
typedef T** iterator;
typedef const T* const * const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef size_t size_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
protected:
typedef value_type parameter_t;
private:
typedef ivector<void*> base_t;
public:
//*********************************************************************
/// Returns an iterator to the beginning of the vector.
///\return An iterator to the beginning of the vector.
//*********************************************************************
iterator begin()
{
return iterator(base_t::begin());
}
//*********************************************************************
/// Returns a const_iterator to the beginning of the vector.
///\return A const iterator to the beginning of the vector.
//*********************************************************************
const_iterator begin() const
{
return const_iterator(base_t::begin());
}
//*********************************************************************
/// Returns an iterator to the end of the vector.
///\return An iterator to the end of the vector.
//*********************************************************************
iterator end()
{
return iterator(base_t::end());
}
//*********************************************************************
/// Returns a const_iterator to the end of the vector.
///\return A const iterator to the end of the vector.
//*********************************************************************
const_iterator end() const
{
return const_iterator(base_t::end());
}
//*********************************************************************
/// Returns a const_iterator to the beginning of the vector.
///\return A const iterator to the beginning of the vector.
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(base_t::cbegin());
}
//*********************************************************************
/// Returns a const_iterator to the end of the vector.
///\return A const iterator to the end of the vector.
//*********************************************************************
const_iterator cend() const
{
return const_iterator(base_t::cend());
}
//*********************************************************************
/// Returns an reverse iterator to the reverse beginning of the vector.
///\return Iterator to the reverse beginning of the vector.
//*********************************************************************
reverse_iterator rbegin()
{
return reverse_iterator(iterator(base_t::end()));
}
//*********************************************************************
/// Returns a const reverse iterator to the reverse beginning of the vector.
///\return Const iterator to the reverse beginning of the vector.
//*********************************************************************
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(const_iterator(base_t::end()));
}
//*********************************************************************
/// Returns a reverse iterator to the end + 1 of the vector.
///\return Reverse iterator to the end + 1 of the vector.
//*********************************************************************
reverse_iterator rend()
{
return reverse_iterator(iterator(base_t::begin()));
}
//*********************************************************************
/// Returns a const reverse iterator to the end + 1 of the vector.
///\return Const reverse iterator to the end + 1 of the vector.
//*********************************************************************
const_reverse_iterator rend() const
{
return const_reverse_iterator(const_iterator(base_t::begin()));
}
//*********************************************************************
/// Returns a const reverse iterator to the reverse beginning of the vector.
///\return Const reverse iterator to the reverse beginning of the vector.
//*********************************************************************
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(const_iterator(base_t::cend()));
}
//*********************************************************************
/// Returns a const reverse iterator to the end + 1 of the vector.
///\return Const reverse iterator to the end + 1 of the vector.
//*********************************************************************
const_reverse_iterator crend() const
{
return const_reverse_iterator(const_iterator(base_t::cbegin()));
}
//*********************************************************************
/// Resizes the vector.
/// If asserts or exceptions are enabled and the new size is larger than the
/// maximum then a vector_full is thrown.
///\param new_size The new size.
//*********************************************************************
void resize(size_t new_size)
{
base_t::resize(new_size);
}
//*********************************************************************
/// Resizes the vector.
/// If asserts or exceptions are enabled and the new size is larger than the
/// maximum then a vector_full is thrown.
///\param new_size The new size.
///\param value The value to fill new elements with. Default = default constructed value.
//*********************************************************************
void resize(size_t new_size, value_type value)
{
base_t::resize(new_size, value);
}
//*********************************************************************
/// Returns a reference to the value at index 'i'
///\param i The index.
///\return A reference to the value at index 'i'
//*********************************************************************
reference operator [](size_t i)
{
return reference(base_t::operator[](i));
}
//*********************************************************************
/// Returns a const reference to the value at index 'i'
///\param i The index.
///\return A const reference to the value at index 'i'
//*********************************************************************
const_reference operator [](size_t i) const
{
return const_reference(base_t::operator[](i));
}
//*********************************************************************
/// Returns a reference to the value at index 'i'
/// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range.
///\param i The index.
///\return A reference to the value at index 'i'
//*********************************************************************
reference at(size_t i)
{
return reference(base_t::at(i));
}
//*********************************************************************
/// Returns a const reference to the value at index 'i'
/// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range.
///\param i The index.
///\return A const reference to the value at index 'i'
//*********************************************************************
const_reference at(size_t i) const
{
return const_reference(base_t::at(i));
}
//*********************************************************************
/// Returns a reference to the first element.
///\return A reference to the first element.
//*********************************************************************
reference front()
{
return reference(base_t::front());
}
//*********************************************************************
/// Returns a const reference to the first element.
///\return A const reference to the first element.
//*********************************************************************
const_reference front() const
{
return const_reference(base_t::front());
}
//*********************************************************************
/// Returns a reference to the last element.
///\return A reference to the last element.
//*********************************************************************
reference back()
{
return reference(base_t::back());
}
//*********************************************************************
/// Returns a const reference to the last element.
///\return A const reference to the last element.
//*********************************************************************
const_reference back() const
{
return const_reference(base_t::back());
}
//*********************************************************************
/// Returns a pointer to the beginning of the vector data.
///\return A pointer to the beginning of the vector data.
//*********************************************************************
pointer data()
{
return pointer(base_t::data());
}
//*********************************************************************
/// Returns a const pointer to the beginning of the vector data.
///\return A const pointer to the beginning of the vector data.
//*********************************************************************
const_pointer data() const
{
return const_pointer(base_t::data());
}
//*********************************************************************
/// Assigns values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
/// If asserts or exceptions are enabled, emits vector_iterator if the iterators are reversed.
///\param first The iterator to the first element.
///\param last The iterator to the last element + 1.
//*********************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
base_t::initialise();
while (first != last)
{
p_buffer[current_size++] = (void*)*first++;
}
}
//*********************************************************************
/// Assigns values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
///\param n The number of elements to add.
///\param value The value to insert for each element.
//*********************************************************************
void assign(size_t n, parameter_t value)
{
base_t::assign(n, value);
}
//*************************************************************************
/// Clears the vector.
//*************************************************************************
void clear()
{
base_t::clear();
}
//*************************************************************************
/// Increases the size of the vector by one, but does not initialise the new element.
/// If asserts or exceptions are enabled, throws a vector_full if the vector is already full.
//*************************************************************************
void push_back()
{
base_t::push_back();
}
//*********************************************************************
/// Inserts a value at the end of the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector is already full.
///\param value The value to add.
//*********************************************************************
void push_back(parameter_t value)
{
base_t::push_back(value);
}
//*************************************************************************
/// Removes an element from the end of the vector.
/// Does nothing if the vector is empty.
//*************************************************************************
void pop_back()
{
base_t::pop_back();
}
//*********************************************************************
/// Inserts a value to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector is already full.
///\param position The position to insert before.
///\param value The value to insert.
//*********************************************************************
iterator insert(iterator position, parameter_t value)
{
return iterator(base_t::insert(base_t::iterator(position), value));
}
//*********************************************************************
/// Inserts 'n' values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
///\param position The position to insert before.
///\param n The number of elements to add.
///\param value The value to insert.
//*********************************************************************
void insert(iterator position, size_t n, parameter_t value)
{
base_t::insert(base_t::iterator(position), n, value);
}
//*********************************************************************
/// Inserts a range of values to the vector.
/// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space.
///\param position The position to insert before.
///\param first The first element to add.
///\param last The last + 1 element to add.
//*********************************************************************
template <class TIterator>
void insert(iterator position, TIterator first, TIterator last)
{
base_t::insert(base_t::iterator(position), first, last);
}
//*********************************************************************
/// Erases an element.
///\param i_element Iterator to the element.
///\return An iterator pointing to the element that followed the erased element.
//*********************************************************************
iterator erase(iterator i_element)
{
return iterator(base_t::erase(base_t::iterator(i_element)));
}
//*********************************************************************
/// Erases a range of elements.
/// The range includes all the elements between first and last, including the
/// element pointed by first, but not the one pointed by last.
///\param first Iterator to the first element.
///\param last Iterator to the last element.
///\return An iterator pointing to the element that followed the erased element.
//*********************************************************************
iterator erase(iterator first, iterator last)
{
return iterator(base_t::erase(base_t::iterator(first), base_t::iterator(last)));
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
ivector& operator = (const ivector& rhs)
{
if (&rhs != this)
{
assign(rhs.cbegin(), rhs.cend());
}
return *this;
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
ivector(void** p_buffer, size_t MAX_SIZE)
: ivector<void*>(p_buffer, MAX_SIZE)
{
}
};
//***************************************************************************
/// Equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator ==(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
//***************************************************************************
/// Not equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator !=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs == rhs);
}
//***************************************************************************
/// Less than operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically less than the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator <(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
//***************************************************************************
/// Greater than operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically greater than the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator >(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return (rhs < lhs);
}
//***************************************************************************
/// Less than or equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexigraphically less than or equal to the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator <=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs > rhs);
}
//***************************************************************************
/// Greater than or equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexigraphically greater than or equal to the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
template <typename T>
bool operator >=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs < rhs);
}
}
#endif

View File

@ -39,35 +39,69 @@ SOFTWARE.
#include "type_traits.h"
#include "error_handler.h"
#include "ihash.h"
#include "frame_check_sequence.h"
#if defined(ETL_COMPILER_KEIL)
#pragma diag_suppress 1300
#pragma diag_suppress 1300
#endif
///\defgroup jenkins Jenkins 32 & 64 bit hash calculations
///\defgroup jenkins Jenkins 32 hash calculation
///\ingroup maths
namespace etl
{
//***************************************************************************
/// Calculates the jenkins hash.
///\ingroup jenkins
/// Jenkins policy.
/// Calculates 32 bit Jenkins hash.
//***************************************************************************
template <typename THash>
class jenkins
struct jenkins_policy
{
typedef uint32_t value_type;
inline uint32_t initial()
{
is_finalised = false;
return 0;
}
inline uint32_t add(value_type hash, uint8_t value) const
{
ETL_ASSERT(!is_finalised, ETL_ERROR(hash_finalised));
hash += value;
hash += (hash << 10);
hash ^= (hash >> 6);
return hash;
}
inline uint32_t final(value_type hash)
{
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
is_finalised = true;
return hash;
}
bool is_finalised;
};
//*************************************************************************
/// jenkins
//*************************************************************************
class jenkins : public etl::frame_check_sequence<etl::jenkins_policy>
{
public:
STATIC_ASSERT((etl::is_same<THash, uint32_t>::value || etl::is_same<THash, uint64_t>::value), "Only 32 & 64 bit types supported");
typedef THash value_type;
//*************************************************************************
/// Default constructor.
//*************************************************************************
jenkins()
{
reset();
this->reset();
}
//*************************************************************************
@ -78,90 +112,9 @@ namespace etl
template<typename TIterator>
jenkins(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Incompatible type");
reset();
while (begin != end)
{
hash += *begin++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
this->reset();
this->add(begin, end);
}
//*************************************************************************
/// Resets the CRC to the initial state.
//*************************************************************************
void reset()
{
hash = 0;
is_finalised = false;
}
//*************************************************************************
/// Adds a range.
/// \param begin
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Incompatible type");
ETL_ASSERT(!is_finalised, ETL_ERROR(hash_finalised));
while (begin != end)
{
hash += *begin++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
}
//*************************************************************************
/// \param value The char to add to the jenkins.
//*************************************************************************
void add(uint8_t value)
{
ETL_ASSERT(!is_finalised, ETL_ERROR(hash_finalised));
hash += value;
hash += (hash << 10);
hash ^= (hash >> 6);
}
//*************************************************************************
/// Gets the jenkins value.
//*************************************************************************
value_type value()
{
finalise();
return hash;
}
//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type ()
{
return value();
}
private:
void finalise()
{
if (!is_finalised)
{
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
is_finalised = true;
}
}
value_type hash;
bool is_finalised;
};
}

View File

@ -38,24 +38,24 @@ SOFTWARE.
namespace etl
{
//***************************************************************************
/// Template to determine the largest type and size.
//***************************************************************************
/// Template to determine the largest type and size.
/// Supports up to 16 types.
/// Defines 'value_type' which is the type of the largest parameter.
/// Defines 'size' which is the size of the largest parameter.
/// Defines 'value_type' which is the type of the largest parameter.
/// Defines 'size' which is the size of the largest parameter.
///\ingroup largest
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct largest_type
{
private:
//***************************************************************************
template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
struct largest_type
{
private:
// Declaration.
template <const bool Boolean, typename TrueType, typename FalseType>
struct choose_type;
template <const bool Boolean, typename TrueType, typename FalseType>
struct choose_type;
// Specialisation for 'true'.
// Defines 'type' as 'TrueType'.
@ -65,49 +65,49 @@ namespace etl
typedef TrueType type;
};
// Specialisation for 'false'.
// Specialisation for 'false'.
// Defines 'type' as 'FalseType'.
template <typename TrueType, typename FalseType>
struct choose_type<false, TrueType, FalseType>
{
{
typedef FalseType type;
};
};
public:
public:
// Define 'largest_other' as 'largest_type' with all but the first parameter.
typedef typename largest_type<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::type largest_other;
// Define 'largest_other' as 'largest_type' with all but the first parameter.
typedef typename largest_type<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::type largest_other;
// Set 'type' to be the largest of the first parameter and any of the others.
// Set 'type' to be the largest of the first parameter and any of the others.
// This is recursive.
typedef typename choose_type<(sizeof(T1) > sizeof(largest_other)), // Boolean
T1, // TrueType
largest_other> // FalseType
::type type; // The largest type of the two.
T1, // TrueType
largest_other> // FalseType
::type type; // The largest type of the two.
// The size of the largest type.
enum
{
size = sizeof(type)
};
};
// The size of the largest type.
enum
{
size = sizeof(type)
};
};
//***************************************************************************
// Specialisation for one template parameter.
//***************************************************************************
template <typename T1>
struct largest_type<T1, void, void, void,
void, void, void, void,
void, void, void, void,
void, void, void, void>
{
typedef T1 type;
// Specialisation for one template parameter.
//***************************************************************************
template <typename T1>
struct largest_type<T1, void, void, void,
void, void, void, void,
void, void, void, void,
void, void, void, void>
{
typedef T1 type;
enum
{
size = sizeof(type)
};
};
enum
{
size = sizeof(type)
};
};
//***************************************************************************
/// Template to determine the largest alignment.

View File

@ -74,6 +74,14 @@ namespace etl
ilist<T>::initialise();
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~list()
{
ilist<T>::initialise();
}
//*************************************************************************
/// Construct from size.
//*************************************************************************

View File

@ -72,7 +72,7 @@ namespace etl
map(const map& other)
: imap<TKey, TValue, TCompare>(node_pool, MAX_SIZE)
{
imap<TKey, TValue, TCompare>::assign(other.cbegin(), other.cend());
imap<TKey, TValue, TCompare>::assign(other.cbegin(), other.cend());
}
//*************************************************************************
@ -88,6 +88,14 @@ namespace etl
imap<TKey, TValue, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~map()
{
imap<TKey, TValue, TCompare>::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************

667
src/memory.h Normal file
View File

@ -0,0 +1,667 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2017 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_MEMORY__
#define __ETL_MEMORY__
#include <iterator>
#include <algorithm>
#include "type_traits.h"
///\defgroup memory memory
///\ingroup etl
namespace etl
{
//*****************************************************************************
/// Gets the address of an object.
///\ingroup memory
//*****************************************************************************
template <typename T>
T* addressof(T& t)
{
return reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(t)));
}
//*****************************************************************************
/// Fills uninitialised memory range with a value.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename T>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_fill(TOutputIterator o_begin, TOutputIterator o_end, const T& value)
{
std::fill(o_begin, o_end, value);
return o_end;
}
//*****************************************************************************
/// Fills uninitialised memory range with a value.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename T>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_fill(TOutputIterator o_begin, TOutputIterator o_end, const T& value)
{
typedef typename std::iterator_traits<TOutputIterator>::value_type value_type;
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type(value);
++o_begin;
}
return o_end;
}
//*****************************************************************************
/// Fills uninitialised memory range with a value.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename T, typename TCounter>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_fill(TOutputIterator o_begin, TOutputIterator o_end, const T& value, TCounter& count)
{
count += std::distance(o_begin, o_end);
std::fill(o_begin, o_end, value);
return o_end;
}
//*****************************************************************************
/// Fills uninitialised memory range with a value.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename T, typename TCounter>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_fill(TOutputIterator o_begin, TOutputIterator o_end, const T& value, TCounter& count)
{
count += std::distance(o_begin, o_end);
etl::uninitialized_fill(o_begin, o_end, value);
return o_end;
}
//*****************************************************************************
/// Fills uninitialised memory with N values.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize, typename T>
inline TOutputIterator uninitialized_fill_n(TOutputIterator o_begin, TSize n, const T& value)
{
return etl::uninitialized_fill(o_begin, o_begin + n, value);
}
//*****************************************************************************
/// Fills uninitialised memory with N values.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize, typename T, typename TCounter>
inline TOutputIterator uninitialized_fill_n(TOutputIterator o_begin, TSize n, const T& value, TCounter& count)
{
count += n;
return etl::uninitialized_fill(o_begin, o_begin + n, value);
}
//*****************************************************************************
/// Copies a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TOutputIterator>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_copy(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin)
{
return std::copy(i_begin, i_end, o_begin);
}
//*****************************************************************************
/// Copies a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TOutputIterator>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_copy(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin)
{
typedef typename std::iterator_traits<TOutputIterator>::value_type value_type;
TOutputIterator o_end = o_begin;
while (i_begin != i_end)
{
::new (static_cast<void*>(etl::addressof(*o_end))) value_type(*i_begin);
++i_begin;
++o_end;
}
return o_end;
}
//*****************************************************************************
/// Copies a range of objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TOutputIterator, typename TCounter>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_copy(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count)
{
TOutputIterator o_end = std::copy(i_begin, i_end, o_begin);
count += std::distance(o_begin, o_end);
return o_end;
}
//*****************************************************************************
/// Copies a range of objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TOutputIterator, typename TCounter>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_copy(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count)
{
TOutputIterator o_end = etl::uninitialized_copy(i_begin, i_end, o_begin);
count += std::distance(o_begin, o_end);
return o_end;
}
//*****************************************************************************
/// Copies N objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TSize, typename TOutputIterator>
inline TOutputIterator uninitialized_copy_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin)
{
return etl::uninitialized_copy(i_begin, i_begin + n, o_begin);
}
//*****************************************************************************
/// Copies N objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TInputIterator, typename TSize, typename TOutputIterator, typename TCounter>
inline TOutputIterator uninitialized_copy_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TCounter& count)
{
count += n;
return etl::uninitialized_copy(i_begin, i_begin + n, o_begin);
}
//*****************************************************************************
/// Default contruct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
typename etl::enable_if<etl::has_trivial_constructor<T>::value, void>::type
create_default_at(T* /*p*/)
{
}
//*****************************************************************************
/// Default contruct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
typename etl::enable_if<etl::has_trivial_constructor<T>::value, void>::type
create_default_at(T* /*p*/, TCounter& count)
{
++count;
}
//*****************************************************************************
/// Default contruct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
typename etl::enable_if<!etl::has_trivial_constructor<T>::value, void>::type
create_default_at(T* p)
{
::new (p) T;
}
//*****************************************************************************
/// Default contruct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
typename etl::enable_if<!etl::has_trivial_constructor<T>::value, void>::type
create_default_at(T* p, TCounter& count)
{
::new (p) T;
++count;
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_default_construct(TOutputIterator /*o_begin*/, TOutputIterator /*o_end*/)
{
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_default_construct(TOutputIterator o_begin, TOutputIterator o_end)
{
typedef typename std::iterator_traits<TOutputIterator>::value_type value_type;
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type;
++o_begin;
}
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TCounter>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_default_construct(TOutputIterator o_begin, TOutputIterator o_end, TCounter& count)
{
count = std::distance(o_begin, o_end);
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TCounter>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_default_construct(TOutputIterator o_begin, TOutputIterator o_end, TCounter& count)
{
count += std::distance(o_begin, o_end);
etl::uninitialized_default_construct(o_begin, o_end);
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_default_construct_n(TOutputIterator o_begin, TSize n)
{
TOutputIterator o_end = o_begin + n;
return o_end;
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_default_construct_n(TOutputIterator o_begin, TSize n)
{
TOutputIterator o_end = o_begin + n;
etl::uninitialized_default_construct(o_begin, o_end);
return o_end;
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize, typename TCounter>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_default_construct_n(TOutputIterator o_begin, TSize n, TCounter& count)
{
TOutputIterator o_end = o_begin + n;
count += n;
return o_end;
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize, typename TCounter>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, TOutputIterator>::type
uninitialized_default_construct_n(TOutputIterator o_begin, TSize n, TCounter& count)
{
TOutputIterator o_end = o_begin + n;
etl::uninitialized_default_construct(o_begin, o_end);
count += n;
return o_end;
}
//*****************************************************************************
/// Value construct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
inline void create_value_at(T* p)
{
::new (p) T();
}
//*****************************************************************************
/// Value construct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
inline void create_value_at(T* p, TCounter& count)
{
::new (p) T();
++count;
}
//*****************************************************************************
/// Copy construct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
inline void create_copy_at(T* p, const T& value)
{
::new (p) T(value);
}
//*****************************************************************************
/// Copy construct an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
inline void create_copy_at(T* p, const T& value, TCounter& count)
{
::new (p) T(value);
++count;
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator>
typename etl::enable_if<etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_value_construct(TOutputIterator o_begin, TOutputIterator o_end)
{
typedef typename std::iterator_traits<TOutputIterator>::value_type value_type;
std::fill(o_begin, o_end, value_type());
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator>
typename etl::enable_if<!etl::has_trivial_constructor<typename std::iterator_traits<TOutputIterator>::value_type>::value, void>::type
uninitialized_value_construct(TOutputIterator o_begin, TOutputIterator o_end)
{
typedef typename std::iterator_traits<TOutputIterator>::value_type value_type;
while (o_begin != o_end)
{
::new (static_cast<void*>(etl::addressof(*o_begin))) value_type();
++o_begin;
}
}
//*****************************************************************************
/// Default initialises a range of objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TCounter>
void uninitialized_value_construct(TOutputIterator o_begin, TOutputIterator o_end, TCounter& count)
{
count += std::distance(o_begin, o_end);
etl::uninitialized_value_construct(o_begin, o_end);
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize>
TOutputIterator uninitialized_value_construct_n(TOutputIterator o_begin, TSize n)
{
TOutputIterator o_end = o_begin + n;
etl::uninitialized_value_construct(o_begin, o_end);
return o_end;
}
//*****************************************************************************
/// Default initialises N objects to uninitialised memory.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TOutputIterator, typename TSize, typename TCounter>
TOutputIterator uninitialized_value_construct_n(TOutputIterator o_begin, TSize n, TCounter& count)
{
TOutputIterator o_end = o_begin + n;
etl::uninitialized_value_construct(o_begin, o_end);
count += n;
return o_end;
}
//*****************************************************************************
/// Destroys an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
typename etl::enable_if<etl::has_trivial_destructor<T>::value, void>::type
destroy_at(T* /*p*/)
{
}
//*****************************************************************************
/// Destroys an item at address p.
///\ingroup memory
//*****************************************************************************
template <typename T>
typename etl::enable_if<!etl::has_trivial_destructor<T>::value, void>::type
destroy_at(T* p)
{
p->~T();
}
//*****************************************************************************
/// Destroys an item at address p.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
typename etl::enable_if<etl::has_trivial_destructor<T>::value, void>::type
destroy_at(T* /*p*/, TCounter& count)
{
--count;
}
//*****************************************************************************
/// Destroys an item at address p.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename T, typename TCounter>
typename etl::enable_if<!etl::has_trivial_destructor<T>::value, void>::type
destroy_at(T* p, TCounter& count)
{
p->~T();
--count;
}
//*****************************************************************************
/// Destroys a range of items.
///\ingroup memory
//*****************************************************************************
template <typename TIterator>
typename etl::enable_if<etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
destroy(TIterator /*i_begin*/, TIterator /*i_end*/)
{
}
//*****************************************************************************
/// Destroys a range of items.
///\ingroup memory
//*****************************************************************************
template <typename TIterator>
typename etl::enable_if<!etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
destroy(TIterator i_begin, TIterator i_end)
{
while (i_begin != i_end)
{
etl::destroy_at(etl::addressof(*i_begin));
++i_begin;
}
}
//*****************************************************************************
/// Destroys a range of items.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TCounter>
typename etl::enable_if<etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
destroy(TIterator i_begin, TIterator i_end, TCounter& count)
{
count -= std::distance(i_begin, i_end);
}
//*****************************************************************************
/// Destroys a range of items.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TCounter>
typename etl::enable_if<!etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, void>::type
destroy(TIterator i_begin, TIterator i_end, TCounter& count)
{
count -= std::distance(i_begin, i_end);
while (i_begin != i_end)
{
etl::destroy_at(etl::addressof(*i_begin));
++i_begin;
}
}
//*****************************************************************************
/// Destroys a number of items.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TSize>
typename etl::enable_if<etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, TIterator>::type
destroy_n(TIterator i_begin, TSize n)
{
return i_begin + n;
}
//*****************************************************************************
/// Destroys a number of items.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TSize>
typename etl::enable_if<!etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, TIterator>::type
destroy_n(TIterator i_begin, TSize n)
{
while (n > 0)
{
etl::destroy_at(etl::addressof(*i_begin));
++i_begin;
--n;
}
return i_begin;
}
//*****************************************************************************
/// Destroys a number of items.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TSize, typename TCounter>
typename etl::enable_if<etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, TIterator>::type
destroy_n(TIterator i_begin, TSize n, TCounter& count)
{
count -= n;
return i_begin + n;
}
//*****************************************************************************
/// Destroys a number of items.
/// Debug counter version.
///\ingroup memory
//*****************************************************************************
template <typename TIterator, typename TSize, typename TCounter>
typename etl::enable_if<!etl::has_trivial_destructor<typename std::iterator_traits<TIterator>::value_type>::value, TIterator>::type
destroy_n(TIterator i_begin, TSize n, TCounter& count)
{
count -= n;
while (n > 0)
{
etl::destroy_at(etl::addressof(*i_begin));
++i_begin;
--n;
}
return i_begin;
}
}
#endif

View File

@ -68,7 +68,7 @@ namespace etl
//*************************************************************************
/// Copy constructor.
//*************************************************************************
explicit multimap(const multimap& other)
multimap(const multimap& other)
: imultimap<TKey, TValue, TCompare>(node_pool, MAX_SIZE)
{
imultimap<TKey, TValue, TCompare>::assign(other.cbegin(), other.cend());
@ -87,6 +87,14 @@ namespace etl
imultimap<TKey, TValue, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~multimap()
{
imultimap<TKey, TValue, TCompare>::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************

View File

@ -68,7 +68,7 @@ namespace etl
//*************************************************************************
/// Copy constructor.
//*************************************************************************
explicit multiset(const multiset& other)
multiset(const multiset& other)
: imultiset<T, TCompare>(node_pool, MAX_SIZE)
{
imultiset<T, TCompare>::assign(other.cbegin(), other.cend());
@ -87,6 +87,14 @@ namespace etl
imultiset<T, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~multiset()
{
imultiset<T, TCompare>::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************

View File

@ -37,7 +37,7 @@ SOFTWARE.
/// A definition of nullptr for compilers that don't support it as standard.
///\ingroup utilities
#if defined(NO_NULLPTR_SUPPORT)
#if defined(ETL_NO_NULLPTR_SUPPORT)
namespace std
{
//*****************************************************************************

View File

@ -31,6 +31,7 @@ SOFTWARE.
#ifndef __ETL_OPTIONAL__
#define __ETL_OPTIONAL__
#include "platform.h"
#include "alignment.h"
#include "type_traits.h"
#include "exception.h"
@ -128,7 +129,7 @@ namespace etl
{
if (valid)
{
new (storage.template get_address<T>()) T(other.value());
::new (storage.template get_address<T>()) T(other.value());
}
}
@ -137,7 +138,7 @@ namespace etl
//***************************************************************************
optional(const T& value)
{
new (storage.template get_address<T>()) T(value);
::new (storage.template get_address<T>()) T(value);
valid = true;
}
@ -186,7 +187,7 @@ namespace etl
}
else
{
new (storage.template get_address<T>()) T(other.value());
::new (storage.template get_address<T>()) T(other.value());
valid = true;
}
}
@ -206,7 +207,7 @@ namespace etl
}
else
{
new (storage.template get_address<T>()) T(value);
::new (storage.template get_address<T>()) T(value);
valid = true;
}
@ -218,7 +219,7 @@ namespace etl
//***************************************************************************
T* operator ->()
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
@ -230,7 +231,7 @@ namespace etl
//***************************************************************************
const T* operator ->() const
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
@ -242,7 +243,7 @@ namespace etl
//***************************************************************************
T& operator *()
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
@ -254,7 +255,7 @@ namespace etl
//***************************************************************************
const T& operator *() const
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
@ -274,7 +275,7 @@ namespace etl
//***************************************************************************
T& value()
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif
@ -286,7 +287,7 @@ namespace etl
//***************************************************************************
const T& value() const
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
#endif

View File

@ -30,6 +30,11 @@ SOFTWARE.
#include <stdint.h>
#include "platform.h"
#include "static_assert.h"
STATIC_ASSERT(ETL_8BIT_SUPPORT, "This file does not currently support targets with no 8bit type");
namespace etl
{
//***************************************************************************

View File

@ -41,6 +41,8 @@ SOFTWARE.
#include "array.h"
#include "container.h"
STATIC_ASSERT(ETL_8BIT_SUPPORT, "This file does not currently support targets with no 8bit type");
#if defined(ETL_COMPILER_KEIL)
#pragma diag_suppress 1300
#endif

View File

@ -28,46 +28,63 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
// Define the platform.
// For FreeRTOS you must define ETL_PLATFORM_FREERTOS in the project settings.
#if defined(__linux__)
#define ETL_PLATFORM_LINUX
#elif defined(WIN32) || defined(WIN64)
#define ETL_PLATFORM_WINDOWS
#elif defined(__VXWORKS__) || defined(_WRS_VXWORKS_MAJOR)
#define ETL_PLATFORM_VXWORKS
#elif defined(__QNX__) || defined(__QNXNTO__)
#define ETL_PLATFORM_QNX
#elif defined(_WIN32_WCE)
#define ETL_PLATFORM_WINDOWS_CE
#else
#define ETL_PLATFORM_GENERIC
#endif
#include <stdint.h>
#include <limits.h>
// Define the compiler.
#if defined(__IAR_SYSTEMS_ICC__)
#define ETL_COMPILER_IAR
#define ETL_COMPILER_IAR
#elif defined(__KEIL__) && !defined(__GNUC__)
#define ETL_COMPILER_KEIL
#define ETL_COMPILER_KEIL
#elif defined(__ghs__)
#define ETL_COMPILER_GREEN_HILLS
#define ETL_COMPILER_GREEN_HILLS
#elif defined(__INTEL_COMPILER)
#define ETL_COMPILER_INTEL
#define ETL_COMPILER_INTEL
#elif defined(_MSC_VER)
#define ETL_COMPILER_MICROSOFT
#define ETL_COMPILER_MICROSOFT
#elif defined(__GNUC__)
#define ETL_COMPILER_GCC
#define ETL_COMPILER_GCC
#elif defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
#define ETL_COMPILER_TI_MSP430
#define ETL_COMPILER_TI_MSP430
#elif defined(_MRI)
#define ETL_COMPILER_MICROTEC
#elif defined(__HIGHC__)
#define ETL_COMPILER_METAWARE_HIGH
#elif defined(__llvm__)
#define ETL_COMPILER_LLVM
#elif defined(__KCC_VERSION)
#define ETL_COMPILER_KAI
#elif defined(_COMO__)
#define ETL_COMPILER_COMEAU
#elif defined(__BORLANDC__)
#define ETL_COMPILER_BORLAND
#elif defined(__CC_ARM)
#define ETL_COMPILER_ARM
#elif defined(__MRC__)
#define ETL_COMPILER_MPW
#else
#define ETL_COMPILER_GENERIC
#define ETL_COMPILER_GENERIC
#endif
// Check to see if the compiler supports nullptr and large character types.
#if (defined(ETL_COMPILER_MICROSOFT) && (_MSC_VER < 1600)) || \
defined(ETL_COMPILER_KEIL) || \
defined(ETL_COMPILER_TI_MSP430) || \
defined(ETL_COMPILER_IAR) || \
(defined(ETL_COMPILER_GCC) && (__cplusplus < 201103L))
#define NO_NULLPTR_SUPPORT
#define NO_LARGE_CHAR_SUPPORT
#define ETL_NO_NULLPTR_SUPPORT
#define ETL_NO_LARGE_CHAR_SUPPORT
#endif
// Check to see if the compiler supports static_assert.
#if (defined(ETL_COMPILER_MICROSOFT) && (_MSC_VER >= 1600)) || \
(defined(ETL_COMPILER_GCC) && (__cplusplus >= 201103L))
#define ETL_STATIC_ASSERT_SUPPORTED
#endif
// Some targets do not support 8bit types.
#define ETL_8BIT_SUPPORT (CHAR_BIT == 8)
#if defined(_DEBUG) || defined(DEBUG)
#define ETL_DEBUG
#endif

View File

@ -33,10 +33,12 @@ SOFTWARE.
#include "alignment.h"
#include "array.h"
#include "bitset.h"
#include "container.h"
#include "integral_limits.h"
#include "ipool.h"
#include <iterator>
#include <algorithm>
//*****************************************************************************
///\defgroup pool pool
@ -51,7 +53,7 @@ namespace etl
///\ingroup pool
//*************************************************************************
template <typename T, const size_t SIZE_>
class pool : public ipool<T>
class pool : public ipool
{
public:
@ -61,25 +63,29 @@ namespace etl
/// Constructor
//*************************************************************************
pool()
: ipool<T>(reinterpret_cast<T*>(&buffer[0]), in_use, SIZE)
: ipool(reinterpret_cast<char*>(&buffer[0]), ELEMENT_SIZE, SIZE)
{
}
//*************************************************************************
/// Destructor
//*************************************************************************
~pool()
{
ipool<T>::release_all();
}
private:
///< The memory for the pool of objects.
typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[SIZE];
// The pool element.
union Element
{
uint32_t next; ///< Index of the next free element.
char value[sizeof(T)]; ///< Storage for value type.
typename etl::type_with_alignment<etl::alignment_of<T>::value>::type dummy; ///< Dummy item to get correct alignment.
};
///< The set of flags that indicate which items are free in the pool.
bitset<SIZE> in_use;
///< The memory for the pool of objects.
typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[SIZE];
static const uint32_t ELEMENT_SIZE = sizeof(Element);
// Should not be copied.
pool(const pool&);

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "1"
@ -168,9 +169,10 @@ namespace etl
{
}
size_type current_size; ///< The current number of elements in the deque.
const size_type MAX_SIZE; ///< The maximum number of elements in the deque.
const size_type BUFFER_SIZE; ///< The number of elements in the buffer.
size_type current_size; ///< The current number of elements in the deque.
const size_type MAX_SIZE; ///< The maximum number of elements in the deque.
const size_type BUFFER_SIZE; ///< The number of elements in the buffer.
etl::debug_count construct_count; ///< Internal debugging.
};
}

View File

@ -40,6 +40,7 @@ SOFTWARE.
#include "../exception.h"
#include "../ivector.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "2"
@ -98,71 +99,9 @@ namespace etl
typedef size_t size_type;
//*************************************************************************
/// Gets the current size of the flat_map.
///\return The current size of the flat_map.
//*************************************************************************
size_type size() const
{
return vbase.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_map.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return vbase.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_map.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return vbase.full();
}
//*************************************************************************
/// Returns the capacity of the flat_map.
///\return The capacity of the flat_map.
//*************************************************************************
size_type capacity() const
{
return vbase.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_map.
///\return The maximum size of the flat_map.
//*************************************************************************
size_type max_size() const
{
return vbase.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return vbase.available();
}
protected:
//*************************************************************************
/// Constructor.
//*************************************************************************
flat_map_base(vector_base& vbase)
: vbase(vbase)
{
}
vector_base& vbase;
etl::debug_count construct_count; ///< Internal debugging.
};
}

View File

@ -40,6 +40,7 @@ SOFTWARE.
#include "../exception.h"
#include "../ivector.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "3"
@ -84,71 +85,9 @@ namespace etl
typedef size_t size_type;
//*************************************************************************
/// Gets the current size of the flat_multimap.
///\return The current size of the flat_multimap.
//*************************************************************************
size_type size() const
{
return vbase.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_multimap.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return vbase.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_multimap.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return vbase.full();
}
//*************************************************************************
/// Returns the capacity of the flat_multimap.
///\return The capacity of the flat_multimap.
//*************************************************************************
size_type capacity() const
{
return vbase.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_multimap.
///\return The maximum size of the flat_multimap.
//*************************************************************************
size_type max_size() const
{
return vbase.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return vbase.available();
}
protected:
//*************************************************************************
/// Constructor.
//*************************************************************************
flat_multimap_base(vector_base& vbase)
: vbase(vbase)
{
}
vector_base& vbase;
etl::debug_count construct_count;
};
}

View File

@ -40,6 +40,7 @@ SOFTWARE.
#include "../exception.h"
#include "../ivector.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "4"
@ -84,71 +85,18 @@ namespace etl
typedef size_t size_type;
//*************************************************************************
/// Gets the current size of the flat_multiset.
///\return The current size of the flat_multiset.
//*************************************************************************
size_type size() const
{
return vbase.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_multiset.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return vbase.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_multiset.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return vbase.full();
}
//*************************************************************************
/// Returns the capacity of the flat_multiset.
///\return The capacity of the flat_multiset.
//*************************************************************************
size_type capacity() const
{
return vbase.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_multiset.
///\return The maximum size of the flat_multiset.
//*************************************************************************
size_type max_size() const
{
return vbase.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return vbase.available();
}
protected:
protected:
etl::debug_count construct_count;
//*************************************************************************
/// Constructor.
//*************************************************************************
flat_multiset_base(vector_base& vbase)
: vbase(vbase)
flat_multiset_base()
{
}
vector_base& vbase;
};
}

View File

@ -38,8 +38,8 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../ivector.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "5"
@ -98,71 +98,9 @@ namespace etl
typedef size_t size_type;
//*************************************************************************
/// Gets the current size of the flat_set.
///\return The current size of the flat_set.
//*************************************************************************
size_type size() const
{
return vbase.size();
}
//*************************************************************************
/// Checks the 'empty' state of the flat_set.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return vbase.empty();
}
//*************************************************************************
/// Checks the 'full' state of the flat_set.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return vbase.full();
}
//*************************************************************************
/// Returns the capacity of the flat_set.
///\return The capacity of the flat_set.
//*************************************************************************
size_type capacity() const
{
return vbase.capacity();
}
//*************************************************************************
/// Returns the maximum possible size of the flat_set.
///\return The maximum size of the flat_set.
//*************************************************************************
size_type max_size() const
{
return vbase.max_size();
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return vbase.available();
}
protected:
//*************************************************************************
/// Constructor.
//*************************************************************************
flat_set_base(vector_base& vbase)
: vbase(vbase)
{
}
vector_base& vbase;
etl::debug_count construct_count;
};
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "6"
@ -111,14 +112,14 @@ namespace etl
//*************************************************************************
/// The node element in the forward_list.
//*************************************************************************
struct Node
struct node_t
{
Node()
node_t()
: next(nullptr)
{
}
Node* next;
node_t* next;
};
public:
@ -130,7 +131,7 @@ namespace etl
//*************************************************************************
size_type size() const
{
return current_size;
return p_node_pool->size();
}
//*************************************************************************
@ -146,7 +147,7 @@ namespace etl
//*************************************************************************
bool empty() const
{
return current_size == 0;
return p_node_pool->empty();
}
//*************************************************************************
@ -154,7 +155,7 @@ namespace etl
//*************************************************************************
bool full() const
{
return current_size == MAX_SIZE;
return p_node_pool->full();
}
//*************************************************************************
@ -163,7 +164,7 @@ namespace etl
//*************************************************************************
size_t available() const
{
return max_size() - size();
return p_node_pool->available();
}
//*************************************************************************
@ -176,9 +177,9 @@ namespace etl
return;
}
Node* p_last = &start_node;
Node* p_current = p_last->next;
Node* p_next = p_current->next;
node_t* p_last = &start_node;
node_t* p_current = p_last->next;
node_t* p_next = p_current->next;
p_current->next = nullptr;
@ -199,9 +200,8 @@ namespace etl
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
forward_list_base(size_type max_size)
: next_free(0),
current_size(0),
forward_list_base(etl::ipool& node_pool, size_type max_size)
: p_node_pool(&node_pool),
MAX_SIZE(max_size)
{
}
@ -209,7 +209,7 @@ namespace etl
//*************************************************************************
/// Get the head node.
//*************************************************************************
Node& get_head()
node_t& get_head()
{
return *start_node.next;
}
@ -217,7 +217,7 @@ namespace etl
//*************************************************************************
/// Get the head node.
//*************************************************************************
const Node& get_head() const
const node_t& get_head() const
{
return *start_node.next;
}
@ -225,17 +225,13 @@ namespace etl
//*************************************************************************
/// Insert a node.
//*************************************************************************
void insert_node_after(Node& position, Node& node)
inline void insert_node_after(node_t& position, node_t& node)
{
// Connect to the forward_list.
node.next = position.next;
join(&node, position.next);
join(&position, &node);
// One more.
++current_size;
}
//*************************************************************************
/// Is the forward_list a trivial length?
//*************************************************************************
@ -247,15 +243,15 @@ namespace etl
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(Node* left, Node* right)
void join(node_t* left, node_t* right)
{
left->next = right;
}
Node start_node; ///< The node that acts as the forward_list start.
size_type next_free; ///< The index of the next free node.
size_type current_size; ///< The number of items in the list.
const size_type MAX_SIZE; ///< The maximum size of the forward_list.
node_t start_node; ///< The node that acts as the forward_list start.
etl::ipool* p_node_pool; ///< The pool of data nodes used in the list.
const size_type MAX_SIZE; ///< The maximum size of the forward_list.
etl::debug_count construct_count; ///< Internal debugging.
};
}

View File

@ -312,7 +312,7 @@ namespace etl
while (first != last)
{
p_buffer[current_size++] = (void*)*first++;
*p_end++ = (void*)*first++;
}
}
@ -456,7 +456,7 @@ namespace etl
template <typename T>
bool operator ==(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
return pvoidvector_equal(lhs, rhs);
}
//***************************************************************************
@ -469,7 +469,7 @@ namespace etl
template <typename T>
bool operator !=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs == rhs);
return pvoidvector_not_equal(lhs, rhs);
}
//***************************************************************************
@ -482,7 +482,7 @@ namespace etl
template <typename T>
bool operator <(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
return pvoidvector_less_than(lhs, rhs);
}
//***************************************************************************
@ -495,7 +495,7 @@ namespace etl
template <typename T>
bool operator >(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return (rhs < lhs);
return pvoidvector_greater_than(lhs, rhs);
}
//***************************************************************************
@ -508,7 +508,7 @@ namespace etl
template <typename T>
bool operator <=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs > rhs);
return pvoidvector_less_than_equal(lhs, rhs);
}
//***************************************************************************
@ -521,7 +521,40 @@ namespace etl
template <typename T>
bool operator >=(const etl::ivector<T*>& lhs, const etl::ivector<T*>& rhs)
{
return !(lhs < rhs);
return pvoidvector_greater_than_equal(lhs, rhs);
}
//***************************************************************************
// Helper functions
//***************************************************************************
inline bool pvoidvector_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator ==(lhs, rhs);
}
inline bool pvoidvector_not_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator !=(lhs, rhs);
}
inline bool pvoidvector_less_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator <(lhs, rhs);
}
inline bool pvoidvector_greater_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator >(lhs, rhs);
}
inline bool pvoidvector_less_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator <=(lhs, rhs);
}
inline bool pvoidvector_greater_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return operator >=(lhs, rhs);
}
}

View File

@ -36,8 +36,10 @@ SOFTWARE.
#define __ETL_LIST_BASE__
#include <stddef.h>
#include "pool.h"
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "7"
@ -141,7 +143,7 @@ namespace etl
//***********************************************************************
/// Reverses the previous & next pointers.
//***********************************************************************
void reverse()
inline void reverse()
{
std::swap(previous, next);
}
@ -163,21 +165,18 @@ namespace etl
node_t* p_node = terminal_node.next;
while (p_node != &terminal_node)
{
p_node->reverse();
p_node = p_node->previous; // Now we've reversed it, we must go to the previous node.
{
node_t* p_temp = p_node->previous;
p_node->previous = p_node->next;
p_node->next = p_temp;
p_node = p_node->previous;
}
// Terminal node.
p_node->reverse();
}
//*************************************************************************
/// Gets the size of the list.
//*************************************************************************
size_type size() const
{
return current_size;
node_t* p_temp = p_node->previous;
p_node->previous = p_node->next;
p_node->next = p_temp;
p_node = p_node->previous;
}
//*************************************************************************
@ -188,12 +187,20 @@ namespace etl
return MAX_SIZE;
}
//*************************************************************************
/// Gets the size of the list.
//*************************************************************************
size_type size() const
{
return p_node_pool->size();
}
//*************************************************************************
/// Checks to see if the list is empty.
//*************************************************************************
bool empty() const
{
return current_size == 0;
return p_node_pool->empty();
}
//*************************************************************************
@ -201,7 +208,7 @@ namespace etl
//*************************************************************************
bool full() const
{
return current_size == MAX_SIZE;
return p_node_pool->size() == MAX_SIZE;
}
//*************************************************************************
@ -213,6 +220,15 @@ namespace etl
return max_size() - size();
}
//*************************************************************************
/// Is the list a trivial length?
//*************************************************************************
bool is_trivial_list() const
{
return (size() < 2);
}
protected:
//*************************************************************************
@ -255,17 +271,6 @@ namespace etl
// Connect to the list.
join(*position.previous, node);
join(node, position);
// One more.
++current_size;
}
//*************************************************************************
/// Is the list a trivial length?
//*************************************************************************
bool is_trivial_list() const
{
return (size() < 2);
}
//*************************************************************************
@ -280,17 +285,18 @@ namespace etl
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
list_base(size_type max_size)
: current_size(0),
list_base(etl::ipool& node_pool,
size_type max_size)
: p_node_pool(&node_pool),
MAX_SIZE(max_size)
{
}
node_t terminal_node; ///< The node that acts as the list start and end.
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the list.
etl::ipool* p_node_pool; ///< The pool of data nodes used in the list.
node_t terminal_node; ///< The node that acts as the list start and end.
const size_type MAX_SIZE; ///< The maximum size of the list.
etl::debug_count construct_count; ///< Internal debugging.
};
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "8"
@ -178,25 +179,30 @@ namespace etl
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
weight(uint_least8_t(kNeither)),
dir(uint_least8_t(kNeither))
{
}
~Node()
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
weight = uint_least8_t(kNeither);
dir = uint_least8_t(kNeither);
children[0] = nullptr;
children[1] = nullptr;
}
Node* children[2];
uint8_t weight;
uint8_t dir;
uint_least8_t weight;
uint_least8_t dir;
};
//*************************************************************************
@ -222,12 +228,12 @@ namespace etl
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
if (uint_least8_t(kNeither) != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
weight_node->weight = uint_least8_t(kNeither);
}
else
{
@ -245,14 +251,14 @@ namespace etl
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
if (uint_least8_t(kNeither) == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
critical_node->weight = uint_least8_t(kNeither);
}
// Rotate is required to balance the tree at the critical node
else
@ -276,7 +282,7 @@ namespace etl
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
void rotate_2node(Node*& position, uint_least8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
@ -296,17 +302,17 @@ namespace etl
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
@ -323,7 +329,7 @@ namespace etl
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
position->children[dir]->weight = third != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(kNeither);
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
@ -331,7 +337,7 @@ namespace etl
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
position->weight = third != uint_least8_t(kNeither) && third == dir ? 1 - dir : uint_least8_t(kNeither);
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
@ -340,7 +346,7 @@ namespace etl
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
}
//*************************************************************************
@ -419,6 +425,7 @@ namespace etl
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the map.
Node* root_node; ///< The node that acts as the map root.
etl::debug_count construct_count;
};
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "9"
@ -162,9 +163,9 @@ namespace etl
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
static const uint_least8_t kLeft = 0;
static const uint_least8_t kRight = 1;
static const uint_least8_t kNeither = 2;
//*************************************************************************
/// The node element in the multimap.
@ -194,8 +195,8 @@ namespace etl
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
uint_least8_t weight;
uint_least8_t dir;
};
//*************************************************************************
@ -275,7 +276,7 @@ namespace etl
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
void rotate_2node(Node*& position, uint_least8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
@ -316,7 +317,7 @@ namespace etl
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
@ -580,6 +581,7 @@ namespace etl
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the map.
Node* root_node; ///< The node that acts as the multimap root.
etl::debug_count construct_count;
};
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "10"
@ -162,9 +163,9 @@ namespace etl
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
static const uint_least8_t kLeft = 0;
static const uint_least8_t kRight = 1;
static const uint_least8_t kNeither = 2;
//*************************************************************************
/// The node element in the multiset.
@ -194,8 +195,8 @@ namespace etl
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
uint_least8_t weight;
uint_least8_t dir;
};
//*************************************************************************
@ -482,7 +483,7 @@ namespace etl
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
void rotate_2node(Node*& position, uint_least8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
@ -523,7 +524,7 @@ namespace etl
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
@ -579,6 +580,7 @@ namespace etl
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the set.
Node* root_node; ///< The node that acts as the multiset root.
etl::debug_count construct_count;
};
}

View File

@ -1,159 +0,0 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2014 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_IN_IPOOL_H__
#error This header is a private element of etl::pool & etl::ipool
#endif
#ifndef __ETL_POOL_BASE__
#define __ETL_POOL_BASE__
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../error_handler.h"
#undef ETL_FILE
#define ETL_FILE "11"
namespace etl
{
//***************************************************************************
/// The base class for pool exceptions.
///\ingroup pool
//***************************************************************************
class pool_exception : public exception
{
public:
pool_exception(string_type what, string_type file_name, numeric_type line_number)
: exception(what, file_name, line_number)
{}
};
//***************************************************************************
/// The exception thrown when the pool has no more free items.
///\ingroup pool
//***************************************************************************
class pool_no_allocation : public pool_exception
{
public:
explicit pool_no_allocation(string_type file_name, numeric_type line_number)
: pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name, line_number)
{}
};
//***************************************************************************
/// The exception thrown when an object is released which does not belong to the pool.
///\ingroup pool
//***************************************************************************
class pool_object_not_in_pool : public pool_exception
{
public:
pool_object_not_in_pool(string_type file_name, numeric_type line_number)
: pool_exception(ETL_ERROR_TEXT("pool:notinpool", ETL_FILE"B"), file_name, line_number)
{}
};
//*************************************************************************
/// The base class for all templated pool types.
///\ingroup pool
//*************************************************************************
class pool_base
{
public:
//*************************************************************************
/// Returns the maximum number of items in the pool.
//*************************************************************************
size_t max_size() const
{
return MAX_SIZE;
}
//*************************************************************************
/// Returns the number of free items in the pool.
//*************************************************************************
size_t available() const
{
return MAX_SIZE - items_allocated;
}
//*************************************************************************
/// Returns the number of allocated items in the pool.
//*************************************************************************
size_t size() const
{
return items_allocated;
}
//*************************************************************************
/// Checks to see if there are no allocated items in the pool.
/// \return <b>true</b> if there are none allocated.
//*************************************************************************
bool empty() const
{
return items_allocated == 0;
}
//*************************************************************************
/// Checks to see if there are no free items in the pool.
/// \return <b>true</b> if there are none free.
//*************************************************************************
bool full() const
{
return items_allocated == MAX_SIZE;
}
protected:
//*************************************************************************
/// Constructor
//*************************************************************************
pool_base(size_t max_size)
: next_free(0),
items_allocated(0),
MAX_SIZE(max_size)
{
}
size_t next_free; ///< The next free slot in the block.
size_t items_allocated; ///< The number of items allocated.
const size_t MAX_SIZE; ///< The maximum number of objects that can be allocated.
};
}
#undef ETL_FILE
#endif

107
src/private/pvoidvector.cpp Normal file
View File

@ -0,0 +1,107 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include "pvoidvector.h"
namespace etl
{
//***************************************************************************
/// Equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
bool operator ==(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
//***************************************************************************
/// Not equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
bool operator !=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return !(lhs == rhs);
}
//***************************************************************************
/// Less than operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically less than the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
inline bool operator <(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
//***************************************************************************
/// Greater than operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically greater than the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
bool operator >(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return (rhs < lhs);
}
//***************************************************************************
/// Less than or equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically less than or equal to the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
bool operator <=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return !(lhs > rhs);
}
//***************************************************************************
/// Greater than or equal operator.
///\param lhs Reference to the first vector.
///\param rhs Reference to the second vector.
///\return <b>true</b> if the first vector is lexicographically greater than or equal to the second, otherwise <b>false</b>
///\ingroup vector
//***************************************************************************
bool operator >=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs)
{
return !(lhs < rhs);
}
}

View File

@ -82,7 +82,7 @@ namespace etl
//*********************************************************************
iterator begin()
{
return &p_buffer[0];
return p_buffer;
}
//*********************************************************************
@ -91,7 +91,7 @@ namespace etl
//*********************************************************************
const_iterator begin() const
{
return const_iterator(&p_buffer[0]);
return const_iterator(p_buffer);
}
//*********************************************************************
@ -100,7 +100,7 @@ namespace etl
//*********************************************************************
iterator end()
{
return &p_buffer[current_size];
return p_end;
}
//*********************************************************************
@ -109,7 +109,7 @@ namespace etl
//*********************************************************************
const_iterator end() const
{
return const_iterator(&p_buffer[current_size]);
return const_iterator(p_end);
}
//*********************************************************************
@ -118,7 +118,7 @@ namespace etl
//*********************************************************************
const_iterator cbegin() const
{
return const_iterator(&p_buffer[0]);
return const_iterator(p_buffer);
}
//*********************************************************************
@ -127,7 +127,7 @@ namespace etl
//*********************************************************************
const_iterator cend() const
{
return const_iterator(&p_buffer[current_size]);
return const_iterator(p_end);
}
//*********************************************************************
@ -194,7 +194,7 @@ namespace etl
{
ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full));
current_size = new_size;
p_end = p_buffer + new_size;
}
//*********************************************************************
@ -208,13 +208,15 @@ namespace etl
{
ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full));
pointer p_new_end = p_buffer + new_size;
// Size up if necessary.
while (current_size < new_size)
if (p_end < p_new_end)
{
p_buffer[current_size++] = value;
std::fill(p_end, p_new_end, value);
}
current_size = new_size;
p_end = p_new_end;
}
//*********************************************************************
@ -245,7 +247,7 @@ namespace etl
//*********************************************************************
reference at(size_t i)
{
ETL_ASSERT(i < current_size, ETL_ERROR(vector_out_of_bounds));
ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds));
return p_buffer[i];
}
@ -257,7 +259,7 @@ namespace etl
//*********************************************************************
const_reference at(size_t i) const
{
ETL_ASSERT(i < current_size, ETL_ERROR(vector_out_of_bounds));
ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds));
return const_reference(p_buffer[i]);
}
@ -285,7 +287,7 @@ namespace etl
//*********************************************************************
reference back()
{
return p_buffer[current_size - 1];
return *(p_end -1);
}
//*********************************************************************
@ -294,7 +296,7 @@ namespace etl
//*********************************************************************
const_reference back() const
{
return const_reference(p_buffer[current_size - 1]);
return const_reference(*(p_end - 1));
}
//*********************************************************************
@ -325,7 +327,7 @@ namespace etl
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#ifdef _DEBUG
#if defined(ETL_DEBUG)
difference_type count = std::distance(first, last);
ETL_ASSERT(static_cast<size_t>(count) <= MAX_SIZE, ETL_ERROR(vector_full));
#endif
@ -334,7 +336,7 @@ namespace etl
while (first != last)
{
p_buffer[current_size++] = const_cast<void*>(*first++);
*p_end++ = const_cast<void*>(*first++);
}
}
@ -352,7 +354,7 @@ namespace etl
for (size_t current_size = 0; current_size < n; ++current_size)
{
p_buffer[current_size] = value;
*p_end++ = value;
}
}
@ -371,10 +373,10 @@ namespace etl
void push_back()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size != MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full));
#endif
++current_size;
++p_end;
}
//*********************************************************************
@ -385,9 +387,9 @@ namespace etl
void push_back(value_type value)
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size != MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full));
#endif
p_buffer[current_size++] = value;
*p_end++ = value;
}
//*************************************************************************
@ -397,9 +399,9 @@ namespace etl
void pop_back()
{
#if defined(ETL_CHECK_PUSH_POP)
ETL_ASSERT(current_size > 0, ETL_ERROR(vector_empty));
ETL_ASSERT(size() > 0, ETL_ERROR(vector_empty));
#endif
--current_size;
--p_end;
}
//*********************************************************************
@ -410,17 +412,17 @@ namespace etl
//*********************************************************************
iterator insert(iterator position, value_type value)
{
ETL_ASSERT((current_size)+1 <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT(size() + 1 <= MAX_SIZE, ETL_ERROR(vector_full));
if (position != end())
{
++current_size;
++p_end;
std::copy_backward(position, end() - 1, end());
*position = value;
}
else
{
p_buffer[current_size++] = value;
*p_end++ = value;
}
return position;
@ -435,53 +437,12 @@ namespace etl
//*********************************************************************
void insert(iterator position, size_t n, value_type value)
{
ETL_ASSERT((current_size)+1 <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT((size() + 1) <= MAX_SIZE, ETL_ERROR(vector_full));
if (position == end())
{
while (n > 0)
{
p_buffer[current_size++] = value;
--n;
}
}
else
{
// Create copy (backwards).
size_t n_insert = n;
size_t from = size() - 1;
size_t to = from + n_insert;
size_t n_move = std::distance(position, end());
size_t n_create_copy = std::min(n_insert, n_move);
std::copy_backward(position, p_end, p_end + n);
std::fill_n(position, n, value);
for (size_t i = 0; i < n_create_copy; ++i)
{
p_buffer[to--] = p_buffer[from--];
}
// Copy old.
size_t insert_index = std::distance(begin(), position);
from = insert_index;
to = from + n_insert;
size_t n_copy_old = (size() > n_insert) ? size() - n_insert : 0;
etl::copy_n(&p_buffer[from], n_copy_old, &p_buffer[to]);
// Copy new.
to = insert_index;
size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0;
size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0;
std::fill_n(&p_buffer[to], n_copy_new, value);
// Create new.
to = size();
for (size_t i = 0; i < n_create_new; ++i)
{
p_buffer[to++] = value;
}
current_size += n_insert;
}
p_end += n;
}
//*********************************************************************
@ -497,52 +458,11 @@ namespace etl
{
size_t count = std::distance(first, last);
ETL_ASSERT((current_size)+count <= MAX_SIZE, ETL_ERROR(vector_full));
ETL_ASSERT((size() + count) <= MAX_SIZE, ETL_ERROR(vector_full));
if (position == end())
{
while (first != last)
{
p_buffer[current_size++] = *first++;
}
}
else
{
size_t insert_index = std::distance(begin(), position);
size_t n_insert = count;
// Create copy (backwards).
size_t from = size() - 1;
size_t to = from + n_insert;
size_t n_move = std::distance(position, end());
size_t n_create_copy = std::min(n_insert, n_move);
for (size_t i = 0; i < n_create_copy; ++i)
{
p_buffer[to--] = p_buffer[from--];
}
// Copy old.
from = insert_index;
to = from + n_insert;
size_t n_copy_old = (size() > n_insert) ? size() - n_insert : 0;
etl::copy_n(&p_buffer[from], n_copy_old, &p_buffer[to]);
// Copy new.
to = insert_index;
size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0;
size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0;
etl::copy_n(first, n_copy_new, &p_buffer[to]);
first += n_copy_new;
// Create new.
to = size();
for (size_t i = 0; i < n_create_new; ++i)
{
p_buffer[to++] = *first++;
}
current_size += n_insert;
}
std::copy_backward(position, p_end, p_end + count);
std::copy(first, last, position);
p_end += count;
}
//*********************************************************************
@ -553,7 +473,7 @@ namespace etl
iterator erase(iterator i_element)
{
std::copy(i_element + 1, end(), i_element);
--current_size;
--p_end;
return i_element;
}
@ -572,7 +492,7 @@ namespace etl
size_t n_delete = std::distance(first, last);
// Just adjust the count.
current_size -= n_delete;
p_end -= n_delete;
return first;
}
@ -590,14 +510,51 @@ namespace etl
return *this;
}
//*************************************************************************
/// Gets the current size of the vector.
///\return The current size of the vector.
//*************************************************************************
size_type size() const
{
return size_t(p_end - p_buffer);
}
//*************************************************************************
/// Checks the 'empty' state of the vector.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return (p_end == p_buffer);
}
//*************************************************************************
/// Checks the 'full' state of the vector.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return size() == MAX_SIZE;
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return max_size() - size();
}
protected:
//*********************************************************************
/// Constructor.
//*********************************************************************
pvoidvector(void** p_buffer, size_t MAX_SIZE)
pvoidvector(void** p_buffer_, size_t MAX_SIZE)
: vector_base(MAX_SIZE),
p_buffer(p_buffer)
p_buffer(p_buffer_),
p_end(p_buffer_)
{
}
@ -606,16 +563,31 @@ namespace etl
//*********************************************************************
void initialise()
{
current_size = 0;
p_end = p_buffer;
}
void** p_buffer;
void** p_end;
private:
// Disable copy construction.
pvoidvector(const pvoidvector&);
};
bool pvoidvector_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool pvoidvector_not_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool pvoidvector_less_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool pvoidvector_greater_than(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool pvoidvector_less_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool pvoidvector_greater_than_equal(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator ==(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator !=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator <(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator >(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator <=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
bool operator >=(const etl::pvoidvector& lhs, const etl::pvoidvector& rhs);
}
#ifdef ETL_COMPILER_MICROSOFT

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#undef ETL_FILE
#define ETL_FILE "13"
@ -153,10 +154,11 @@ namespace etl
{
}
size_type in; ///< Where to input new data.
size_type out; ///< Where to get the oldest data.
size_type current_size; ///< The number of items in the queue.
const size_type MAX_SIZE; ///< The maximum number of items in the queue.
size_type in; ///< Where to input new data.
size_type out; ///< Where to get the oldest data.
size_type current_size; ///< The number of items in the queue.
const size_type MAX_SIZE; ///< The maximum number of items in the queue.
etl::debug_count construct_count; ///< For internal debugging purposes.
};
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <stddef.h>
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#define ETL_FILE "14"
@ -194,8 +195,8 @@ namespace etl
}
Node* children[2];
uint8_t weight;
uint8_t dir;
uint_least8_t weight;
uint_least8_t dir;
};
//*************************************************************************
@ -260,12 +261,12 @@ namespace etl
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
if (uint_least8_t(kNeither) != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
weight_node->weight = uint_least8_t(kNeither);
}
else
{
@ -283,14 +284,14 @@ namespace etl
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
if (uint_least8_t(kNeither) == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
critical_node->weight = uint_least8_t(kNeither);
}
// Rotate is required to balance the tree at the critical node
else
@ -348,7 +349,7 @@ namespace etl
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
void rotate_2node(Node*& position, uint_least8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
@ -368,17 +369,17 @@ namespace etl
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
@ -395,7 +396,7 @@ namespace etl
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
position->children[dir]->weight = third != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(kNeither);
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
@ -403,7 +404,7 @@ namespace etl
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
position->weight = third != uint_least8_t(kNeither) && third == dir ? 1 - dir : uint_least8_t(kNeither);
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
@ -412,13 +413,14 @@ namespace etl
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
position->weight = uint_least8_t(kNeither);
}
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the set.
Node* root_node; ///< The node that acts as the set root.
etl::debug_count construct_count;
};
}

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#define ETL_FILE "15"
@ -152,9 +153,10 @@ namespace etl
{
}
size_type top_index; ///< The index of the top of the stack.
size_type current_size; ///< The number of items in the stack.
const size_type MAX_SIZE; ///< The maximum number of items in the stack.
size_type top_index; ///< The index of the top of the stack.
size_type current_size; ///< The number of items in the stack.
const size_type MAX_SIZE; ///< The maximum number of items in the stack.
etl::debug_count construct_count; ///< For internal debugging purposes.
};
}

View File

@ -42,7 +42,7 @@ SOFTWARE.
#include "../exception.h"
#include "../error_handler.h"
#define ETL_FILE "24"
#define ETL_FILE "27"
#ifdef ETL_COMPILER_MICROSOFT
#undef max
@ -116,7 +116,10 @@ namespace etl
typedef size_t size_type;
static const size_t npos = etl::integral_limits<size_t>::max;
enum
{
npos = etl::integral_limits<size_t>::max
};
//*************************************************************************
/// Gets the current size of the string.

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "../exception.h"
#include "../error_handler.h"
#include "../debug_count.h"
#define ETL_FILE "17"
@ -110,33 +111,6 @@ namespace etl
typedef size_t size_type;
//*************************************************************************
/// Gets the current size of the vector.
///\return The current size of the vector.
//*************************************************************************
size_type size() const
{
return current_size;
}
//*************************************************************************
/// Checks the 'empty' state of the vector.
///\return <b>true</b> if empty.
//*************************************************************************
bool empty() const
{
return (current_size == 0);
}
//*************************************************************************
/// Checks the 'full' state of the vector.
///\return <b>true</b> if full.
//*************************************************************************
bool full() const
{
return current_size == MAX_SIZE;
}
//*************************************************************************
/// Returns the capacity of the vector.
///\return The capacity of the vector.
@ -155,28 +129,18 @@ namespace etl
return MAX_SIZE;
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return max_size() - size();
}
protected:
//*************************************************************************
/// Constructor.
//*************************************************************************
vector_base(size_t max_size)
: current_size(0),
MAX_SIZE(max_size)
: MAX_SIZE(max_size)
{
}
size_type current_size; ///<The current number of elements in the vector.
const size_type MAX_SIZE; ///<The maximum number of elements in the vector.
const size_type MAX_SIZE; ///<The maximum number of elements in the vector.
etl::debug_count construct_count; ///< Internal debugging.
};
}

View File

@ -53,13 +53,13 @@ namespace etl
hex = 16
};
DECLARE_ENUM_TYPE(radix, uint8_t)
ENUM_TYPE(undefined, "undefined")
ENUM_TYPE(binary, "binary")
ENUM_TYPE(octal, "octal")
ENUM_TYPE(decimal, "decimal")
ENUM_TYPE(hex, "hex")
END_ENUM_TYPE
ETL_DECLARE_ENUM_TYPE(radix, uint_least8_t)
ETL_ENUM_TYPE(undefined, "undefined")
ETL_ENUM_TYPE(binary, "binary")
ETL_ENUM_TYPE(octal, "octal")
ETL_ENUM_TYPE(decimal, "decimal")
ETL_ENUM_TYPE(hex, "hex")
ETL_END_ENUM_TYPE
};
}

87
src/random.cpp Normal file
View File

@ -0,0 +1,87 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2017 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include "random.h"
namespace etl
{
//***************************************************************************
/// Default constructor.
/// Attempts to come up with a reasonable non-zero seed.
//***************************************************************************
random_xorshift::random_xorshift()
{
// An attempt to come up with a reasonable non-zero seed,
// based on the address of the instance.
uintptr_t n = reinterpret_cast<uintptr_t>(this);
uint32_t seed = static_cast<uint32_t>(n);
initialise(seed);
}
//***************************************************************************
/// Constructor with seed value.
///\param seed The new seed value.
//***************************************************************************
random_xorshift::random_xorshift(uint32_t seed)
{
initialise(seed);
}
//***************************************************************************
/// Initialises the sequence with a new seed value.
///\param seed The new seed value.
//***************************************************************************
void random_xorshift::initialise(uint32_t seed)
{
// Add the first four primes to ensure that the seed isn't zero.
state[0] = seed + 3;
state[1] = seed + 5;
state[2] = seed + 7;
state[3] = seed + 11;
}
//***************************************************************************
/// Get the next random_xorshift number.
//***************************************************************************
uint32_t random_xorshift::operator()()
{
uint32_t n = state[3];
n ^= n << 11;
n ^= n >> 8;
state[3] = state[2];
state[2] = state[1];
state[1] = state[0];
n ^= state[0];
n ^= state[0] >> 19;
state[0] = n;
return n;
}
}

72
src/random.h Normal file
View File

@ -0,0 +1,72 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2017 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_RANDOM__
#define __ETL_RANDOM__
#include <stdint.h>
namespace etl
{
//***************************************************************************
/// The base for all 32 bit random number generators.
//***************************************************************************
class random
{
public:
virtual ~random()
{
}
virtual uint32_t operator()() = 0;
};
//***************************************************************************
/// A 32 bit random number generator.
/// Uses a 128 bit XOR shift algorithm.
/// https://en.wikipedia.org/wiki/Xorshift
//***************************************************************************
class random_xorshift : public random
{
public:
random_xorshift();
random_xorshift(uint32_t seed);
void initialise(uint32_t seed);
uint32_t operator()();
private:
uint32_t state[4];
};
}
#endif

94
src/ratio.h Normal file
View File

@ -0,0 +1,94 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
http://www.etlcpp.com
Copyright(c) 2016 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_RATIO__
#define __ETL_RATIO__
#include <stdint.h>
///\defgroup ratio ratio
///\ingroup utilities
namespace etl
{
template <const size_t NUM, const size_t DEN = 1>
struct ratio
{
static const std::intmax_t num = NUM;
static const std::intmax_t den = DEN;
};
#if INT_MAX > INT32_MAX
typedef ratio<1, 1000000000000000000000000> yocto;
typedef ratio<1, 1000000000000000000000> zepto;
typedef ratio<1, 1000000000000000000> atto
typedef ratio<1, 1000000000000000> femto
typedef ratio<1, 1000000000000> pico;
#endif
#if (INT_MAX >= INT32_MAX)
typedef ratio<1, 1000000000> nano;
typedef ratio<1, 1000000> micro;
#endif
#if (INT_MAX >= INT16_MAX)
typedef ratio<1, 1000> milli;
typedef ratio<1, 100> centi;
typedef ratio<1, 10> deci;
typedef ratio<10, 1> deca;
typedef ratio<100, 1> hecto
typedef ratio<1000, 1> kilo
#endif
#if (INT_MAX >= INT32_MAX)
typedef ratio<1000000, 1> mega;
typedef ratio<1000000000, 1> giga;
#endif
#if INT_MAX > INT32_MAX
typedef ratio<1000000000000, 1> tera;
typedef ratio<1000000000000000, 1> peta;
typedef ratio<1000000000000000000, 1> exa;
typedef ratio<1000000000000000000000, 1> zetta;
typedef ratio<1000000000000000000000000, 1> yotta;
#endif
/// An approximation of PI to 6 digits.
typedef ratio<355, 113> ratio_pi;
/// An approximation of root 2.
typedef ratio<239, 169> ratio_root2;
/// An approximation of e.
typedef ratio<326, 120> ratio_e;
}
#endif

View File

@ -69,7 +69,7 @@ namespace etl
//*************************************************************************
/// Copy constructor.
//*************************************************************************
explicit set(const set& other)
set(const set& other)
: iset<T, TCompare>(node_pool, MAX_SIZE)
{
iset<T, TCompare>::assign(other.cbegin(), other.cend());
@ -88,6 +88,14 @@ namespace etl
iset<T, TCompare>::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~set()
{
iset<T, TCompare>::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************

View File

@ -154,6 +154,48 @@ namespace etl
{
typedef uint_least64_t type;
};
//*************************************************************************
// Determine the type to hold the number of bits based on the index.
//*************************************************************************
template <const int index>
struct best_fit_int_type;
//*************************************************************************
// Less than or equal to 8 bits.
//*************************************************************************
template <>
struct best_fit_int_type<0>
{
typedef int_least8_t type;
};
//*************************************************************************
// 9 to 16 bits.
//*************************************************************************
template <>
struct best_fit_int_type<1>
{
typedef int_least16_t type;
};
//*************************************************************************
// 17 to 31 bits.
//*************************************************************************
template <>
struct best_fit_int_type<2>
{
typedef int_least32_t type;
};
//*************************************************************************
// Greater than 32 bits.
//*************************************************************************
template <>
struct best_fit_int_type<3>
{
typedef int_least64_t type;
};
}
//***************************************************************************
@ -168,12 +210,77 @@ namespace etl
private:
// Determines the index of the best unsigned type for the required number of bits.
static const int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) + ((NBITS > 16) ? 1 : 0) + ((NBITS > 32) ? 1 : 0);
static const int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
((NBITS > 16) ? 1 : 0) +
((NBITS > 32) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest signed int type that can contain a
/// value with the specified number of bits.
/// Defines 'type' which is the type of the smallest signed integer.
///\ingroup smallest
//***************************************************************************
template <const size_t NBITS>
struct smallest_int_for_bits
{
private:
// Determines the index of the best unsigned type for the required number of bits.
static const int TYPE_INDEX = ((NBITS > 8) ? 1 : 0) +
((NBITS > 16) ? 1 : 0) +
((NBITS > 32) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest unsigned int type that can contain the
/// specified unsigned value.
/// Defines 'type' which is the type of the smallest unsigned integer.
///\ingroup smallest
//***************************************************************************
template <const uintmax_t VALUE>
struct smallest_uint_for_value
{
private:
// Determines the index of the best unsigned type for the required value.
static const int TYPE_INDEX = ((VALUE > UINT8_MAX) ? 1 : 0) +
((VALUE > UINT16_MAX) ? 1 : 0) +
((VALUE > UINT32_MAX) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
};
//***************************************************************************
/// Template to determine the smallest int type that can contain the
/// specified signed value.
/// Defines 'type' which is the type of the smallest signed integer.
///\ingroup smallest
//***************************************************************************
template <const intmax_t VALUE>
struct smallest_int_for_value
{
private:
// Determines the index of the best signed type for the required value.
static const int TYPE_INDEX = (((VALUE > INT8_MAX) || (VALUE < INT8_MIN)) ? 1 : 0) +
(((VALUE > INT16_MAX) || (VALUE < INT16_MIN)) ? 1 : 0) +
(((VALUE > INT32_MAX) || (VALUE < INT32_MIN)) ? 1 : 0);
public:
typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
};
}
#endif

View File

@ -31,9 +31,7 @@ SOFTWARE.
#include "platform.h"
#if defined(ETL_COMPILER_MICROSOFT)
#define STATIC_ASSERT(Condition, Message) static_assert(Condition, Message)
#elif defined(ETL_COMPILER_GCC)
#if defined(ETL_STATIC_ASSERT_SUPPORTED)
#define STATIC_ASSERT(Condition, Message) static_assert(Condition, Message)
#else
template <bool Condition>
@ -42,12 +40,13 @@ SOFTWARE.
template <>
struct STATIC_ASSERT_FAILED<true> {};
#define ETL_FCAT(a,b) a##b
#define ETL_ACAT(a,b) ETL_FCAT(a,b)
#define STATIC_ASSERT(cond,msg) \
enum \
{ ETL_ACAT(dummy,__LINE__)=sizeof(STATIC_ASSERT_FAILED<(bool)(cond)>) \
}
#define ETL_SA1(a,b) a##b
#define ETL_SA2(a,b) ETL_SA1(a,b)
#define STATIC_ASSERT(Condition, Message) \
enum \
{ \
ETL_SA2(dummy, __LINE__) = sizeof(STATIC_ASSERT_FAILED<(bool)(Condition)>) \
}
#endif
#endif

View File

@ -41,7 +41,7 @@ namespace etl
///\code
/// // Short form.
/// ETL_TYPEDEF(int, mytype);
///
///
/// // Long form.
/// class mytype_t_tag;
/// typedef etl::type_def<mytype_t_tag, int> mytype_t_tag;
@ -243,7 +243,13 @@ namespace etl
}
//*********************************************************************
TValue get() const
TValue& get()
{
return value;
}
//*********************************************************************
const TValue& get() const
{
return value;
}

View File

@ -232,6 +232,32 @@ namespace etl
template <typename T> struct is_reference : false_type {};
template <typename T> struct is_reference<T&> : true_type {};
/// is_pod
/// For C++03, only fundamental and pointers types are recognised.
///\ingroup type_traits
template <typename T> struct is_pod : etl::integral_constant<bool, etl::is_fundamental<T>::value ||
etl::is_pointer<T>::value> {};
/// has_trivial_constructor
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct has_trivial_constructor : etl::is_pod<T> {};
/// has_trivial_copy_constructor
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct has_trivial_copy_constructor : etl::is_pod<T> {};
/// has_trivial_destructor
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct has_trivial_destructor : etl::is_pod<T> {};
/// has_trivial_assignment
/// For C++03, only POD types are recognised.
///\ingroup type_traits
template <typename T> struct has_trivial_assignment : etl::is_pod<T> {};
/// conditional
///\ingroup type_traits
template <bool B, typename T, typename F> struct conditional { typedef T type; };
@ -242,19 +268,16 @@ namespace etl
template <typename T> struct make_signed { typedef T type; };
template <> struct make_signed<char> { typedef signed char type; };
template <> struct make_signed<unsigned char> { typedef signed char type; };
#if defined(ETL_COMPILER_GCC)
template <> struct make_signed<wchar_t>
{
typedef wchar_t type;
typedef typename etl::conditional<sizeof(wchar_t) == sizeof(int16_t),
int16_t,
etl::conditional<sizeof(wchar_t) == sizeof(int32_t),
int32_t,
void>::type>::type type;
};
#else
template <> struct make_signed<wchar_t>
{
typedef etl::conditional<sizeof(wchar_t) == sizeof(short), short,
etl::conditional<sizeof(wchar_t) == sizeof(int), int,
etl::conditional<sizeof(wchar_t) == sizeof(long), long, void>::type>::type>::type type;
};
#endif
template <> struct make_signed<unsigned short> { typedef short type; };
template <> struct make_signed<unsigned int> { typedef int type; };
template <> struct make_signed<unsigned long> { typedef long type; };
@ -269,19 +292,16 @@ namespace etl
template <> struct make_unsigned<char> { typedef unsigned char type; };
template <> struct make_unsigned<signed char> { typedef unsigned char type; };
template <> struct make_unsigned<short> { typedef unsigned short type; };
#if defined(ETL_COMPILER_GCC) && !defined(ETL_PLATFORM_LINUX)
template <> struct make_unsigned<wchar_t>
{
typedef wchar_t type;
typedef typename etl::conditional<sizeof(wchar_t) == sizeof(uint16_t),
uint16_t,
etl::conditional<sizeof(wchar_t) == sizeof(uint32_t),
uint32_t,
void>::type>::type type;
};
#else
template <> struct make_unsigned<wchar_t>
{
typedef etl::conditional<sizeof(wchar_t) == sizeof(unsigned short), unsigned short,
etl::conditional<sizeof(wchar_t) == sizeof(unsigned int), unsigned int,
etl::conditional<sizeof(wchar_t) == sizeof(unsigned long), unsigned long, void>::type>::type>::type type;
};
#endif
template <> struct make_unsigned<int> { typedef unsigned int type; };
template <> struct make_unsigned<long> { typedef unsigned long type; };
template <> struct make_unsigned<long long> { typedef unsigned long long type; };

View File

@ -33,6 +33,7 @@ SOFTWARE.
#include "platform.h"
#include "basic_string.h"
#include "hash.h"
#if defined(ETL_COMPILER_MICROSOFT)
#undef min
@ -180,6 +181,19 @@ namespace etl
value_type buffer[MAX_SIZE + 1];
};
//*************************************************************************
/// Hash function.
//*************************************************************************
template <>
struct hash<etl::iu16string>
{
size_t operator()(const etl::iu16string& text) const
{
return etl::__private_hash__::generic_hash<>(reinterpret_cast<const uint8_t*>(&text[0]),
reinterpret_cast<const uint8_t*>(&text[text.size()]));
}
};
}
#if defined(ETL_COMPILER_MICROSOFT)

View File

@ -33,6 +33,7 @@ SOFTWARE.
#include "platform.h"
#include "basic_string.h"
#include "hash.h"
#if defined(ETL_COMPILER_MICROSOFT)
#undef min
@ -180,6 +181,19 @@ namespace etl
value_type buffer[MAX_SIZE + 1];
};
//*************************************************************************
/// Hash function.
//*************************************************************************
template <>
struct hash<etl::iu32string>
{
size_t operator()(const etl::iu32string& text) const
{
return etl::__private_hash__::generic_hash<>(reinterpret_cast<const uint8_t*>(&text[0]),
reinterpret_cast<const uint8_t*>(&text[text.size()]));
}
};
}
#if defined(ETL_COMPILER_MICROSOFT)

View File

@ -38,7 +38,7 @@ SOFTWARE.
#include "iunordered_map.h"
#include "container.h"
#include "pool.h"
#include "vector.h"
#include "array.h"
#include "intrusive_forward_list.h"
#include "hash.h"
@ -53,7 +53,7 @@ namespace etl
//*************************************************************************
/// A templated unordered_map implementation that uses a fixed size buffer.
//*************************************************************************
template <typename TKey, typename TValue, const size_t MAX_SIZE_, typename THash = etl::hash<TKey>, typename TKeyEqual = std::equal_to<TKey> >
template <typename TKey, typename TValue, const size_t MAX_SIZE_, const size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>, typename TKeyEqual = std::equal_to<TKey> >
class unordered_map : public iunordered_map<TKey, TValue, THash, TKeyEqual>
{
private:
@ -62,13 +62,14 @@ namespace etl
public:
static const size_t MAX_SIZE = MAX_SIZE_;
static const size_t MAX_SIZE = MAX_SIZE_;
static const size_t MAX_BUCKETS = MAX_BUCKETS_;
//*************************************************************************
/// Default constructor.
//*************************************************************************
unordered_map()
: base(node_pool, buckets)
: base(node_pool, buckets, MAX_BUCKETS_)
{
base::initialise();
}
@ -77,9 +78,9 @@ namespace etl
/// Copy constructor.
//*************************************************************************
unordered_map(const unordered_map& other)
: base(node_pool, buckets)
: base(node_pool, buckets, MAX_BUCKETS_)
{
base::assign(other.cbegin(), other.cend());
base::assign(other.cbegin(), other.cend());
}
//*************************************************************************
@ -90,11 +91,19 @@ namespace etl
//*************************************************************************
template <typename TIterator>
unordered_map(TIterator first, TIterator last)
: base(node_pool, buckets)
: base(node_pool, buckets, MAX_BUCKETS_)
{
base::assign(first, last);
}
//*************************************************************************
/// Destructor.
//*************************************************************************
~unordered_map()
{
base::initialise();
}
//*************************************************************************
/// Assignment operator.
//*************************************************************************
@ -115,7 +124,7 @@ namespace etl
etl::pool<typename base::node_t, MAX_SIZE> node_pool;
/// The buckets of node lists.
etl::vector<etl::intrusive_forward_list<typename base::node_t>, MAX_SIZE> buckets;
etl::intrusive_forward_list<typename base::node_t> buckets[MAX_BUCKETS_];
};
}

Some files were not shown because too many files have changed in this diff Show More