mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-28 21:38:44 +08:00
Merge remote-tracking branch 'refs/remotes/ETLCPP/master'
This commit is contained in:
commit
9171050799
@ -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=*
|
||||
|
||||
520
src/algorithm.h
520
src/algorithm.h
@ -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
|
||||
|
||||
@ -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.
|
||||
};
|
||||
};
|
||||
|
||||
390
src/array.h
390
src/array.h
@ -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());
|
||||
}
|
||||
|
||||
|
||||
237
src/binary.h
237
src/binary.h
@ -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
81
src/callback.h
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -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)
|
||||
@ -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
137
src/debug_count.h
Normal 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
|
||||
|
||||
@ -86,6 +86,14 @@ namespace etl
|
||||
ideque<T>::initialise();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~deque()
|
||||
{
|
||||
ideque<T>::initialise();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Copy constructor.
|
||||
//*************************************************************************
|
||||
|
||||
16
src/endian.h
16
src/endian.h
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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 "?"; \
|
||||
} \
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
326
src/fnv_1.h
326
src/fnv_1.h
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
68
src/hash.h
68
src/hash.h
@ -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
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
27
src/ideque.h
27
src/ideque.h
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
424
src/iflat_map.h
424
src/iflat_map.h
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
366
src/iflat_set.h
366
src/iflat_set.h
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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.
|
||||
|
||||
114
src/ilist.h
114
src/ilist.h
@ -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.
|
||||
|
||||
28
src/imap.h
28
src/imap.h
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
233
src/intrusive_queue.h
Normal 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
198
src/intrusive_stack.h
Normal 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
|
||||
593
src/ipool.h
593
src/ipool.h
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
23
src/iset.h
23
src/iset.h
@ -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;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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
115
src/iterator.h
Normal 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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
670
src/ivector.h
670
src/ivector.h
@ -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
531
src/ivectorpointer.h
Normal 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
|
||||
141
src/jenkins.h
141
src/jenkins.h
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -74,6 +74,14 @@ namespace etl
|
||||
ilist<T>::initialise();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Destructor.
|
||||
//*************************************************************************
|
||||
~list()
|
||||
{
|
||||
ilist<T>::initialise();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Construct from size.
|
||||
//*************************************************************************
|
||||
|
||||
10
src/map.h
10
src/map.h
@ -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
667
src/memory.h
Normal 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
|
||||
@ -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.
|
||||
//*************************************************************************
|
||||
|
||||
@ -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.
|
||||
//*************************************************************************
|
||||
|
||||
@ -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
|
||||
{
|
||||
//*****************************************************************************
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
{
|
||||
//***************************************************************************
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
28
src/pool.h
28
src/pool.h
@ -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&);
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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
107
src/private/pvoidvector.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
14
src/radix.h
14
src/radix.h
@ -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
87
src/random.cpp
Normal 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
72
src/random.h
Normal 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
94
src/ratio.h
Normal 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
|
||||
|
||||
10
src/set.h
10
src/set.h
@ -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.
|
||||
//*************************************************************************
|
||||
|
||||
109
src/smallest.h
109
src/smallest.h
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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; };
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user