mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-30 22:38:44 +08:00
Merge remote-tracking branch 'origin/development'
This commit is contained in:
commit
73e38fa176
139
bsd_checksum.h
139
bsd_checksum.h
@ -1,139 +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_BSDCHECKSUM__
|
||||
#define __ETL_BSDCHECKSUM__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
#include "binary.h"
|
||||
#include "ihash.h"
|
||||
|
||||
///\defgroup bsdchecksum BSD Checksum calculation
|
||||
///\ingroup maths
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Calculates the checksum.
|
||||
///\tparam TSum The type used for the sum.
|
||||
///\ingroup checksum
|
||||
//***************************************************************************
|
||||
template <typename TSum>
|
||||
class bsd_checksum
|
||||
{
|
||||
public:
|
||||
|
||||
STATIC_ASSERT(is_unsigned<TSum>::value, "Signed TSum template parameter not supported");
|
||||
|
||||
typedef TSum value_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
bsd_checksum()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from range.
|
||||
/// \param begin Start of the range.
|
||||
/// \param end End of the range.
|
||||
//*************************************************************************
|
||||
template<typename TIterator>
|
||||
bsd_checksum(TIterator begin, const TIterator end)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Only 8 bit types supported");
|
||||
reset();
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
sum = rotate_right(sum) + *begin++;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Resets the CRC to the initial state.
|
||||
//*************************************************************************
|
||||
void reset()
|
||||
{
|
||||
sum = 0;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// 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, "Only 8 bit types supported");
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
sum = rotate_right(sum) + *begin++;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// \param value The uint8_t to add to the checksum.
|
||||
//*************************************************************************
|
||||
void add(uint8_t value)
|
||||
{
|
||||
sum = rotate_right(sum) + value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the checksum value.
|
||||
//*************************************************************************
|
||||
value_type value()
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Conversion operator to value_type.
|
||||
//*************************************************************************
|
||||
operator value_type ()
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
value_type sum;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
167
checksum.h
167
checksum.h
@ -1,24 +1,20 @@
|
||||
|
||||
///\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
|
||||
@ -35,7 +31,7 @@ SOFTWARE.
|
||||
|
||||
#include "static_assert.h"
|
||||
#include "type_traits.h"
|
||||
#include "ihash.h"
|
||||
#include "binary.h"
|
||||
|
||||
///\defgroup checksum Checksum calculation
|
||||
///\ingroup maths
|
||||
@ -43,18 +39,86 @@ SOFTWARE.
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Calculates the checksum.
|
||||
///\tparam TSum The type used for the sum.
|
||||
/// Standard addition checksum policy.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct checksum_policy_sum
|
||||
{
|
||||
inline T initial() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline T add(T sum, uint8_t value) const
|
||||
{
|
||||
return sum + value;
|
||||
}
|
||||
|
||||
inline T final(T sum) const
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// BSD checksum policy.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct checksum_policy_bsd
|
||||
{
|
||||
inline T initial() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline T add(T sum, uint8_t value) const
|
||||
{
|
||||
return etl::rotate_right(sum) + value;
|
||||
}
|
||||
|
||||
inline T final(T sum) const
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Standard XOR checksum policy.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
struct checksum_policy_xor
|
||||
{
|
||||
inline T initial() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline T add(T sum, uint8_t value) const
|
||||
{
|
||||
return sum ^ value;
|
||||
}
|
||||
|
||||
inline T final(T sum) const
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Calculates a checksum according to the specified policy.
|
||||
///\tparam TSum The type used for the sum.
|
||||
///\tparam TPolicy The type used to enact the policy. Default = checksum_policy_sum
|
||||
///\ingroup checksum
|
||||
//***************************************************************************
|
||||
template <typename TSum>
|
||||
template <typename TSum, typename TPolicy = checksum_policy_sum<TSum> >
|
||||
class checksum
|
||||
{
|
||||
public:
|
||||
|
||||
STATIC_ASSERT(is_unsigned<TSum>::value, "Signed TSum template parameter not supported");
|
||||
STATIC_ASSERT(etl::is_unsigned<TSum>::value, "Signed TSum template parameter not supported");
|
||||
|
||||
typedef TSum value_type;
|
||||
typedef TSum value_type;
|
||||
typedef TPolicy policy_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
@ -75,10 +139,7 @@ namespace etl
|
||||
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
|
||||
|
||||
reset();
|
||||
while (begin != end)
|
||||
{
|
||||
sum += *begin++;
|
||||
}
|
||||
add(begin, end);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -86,7 +147,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void reset()
|
||||
{
|
||||
sum = 0;
|
||||
sum = policy.initial();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -101,7 +162,7 @@ namespace etl
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
sum += *begin++;
|
||||
sum = policy.add(sum, *begin++);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +171,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void add(uint8_t value)
|
||||
{
|
||||
sum += value;
|
||||
sum = policy.add(sum, value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -118,7 +179,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
value_type value() const
|
||||
{
|
||||
return sum;
|
||||
return policy.final(sum);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -126,13 +187,77 @@ namespace etl
|
||||
//*************************************************************************
|
||||
operator value_type () const
|
||||
{
|
||||
return sum;
|
||||
return policy.final(sum);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
value_type sum;
|
||||
value_type sum;
|
||||
policy_type policy;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// BSD Checksum.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
class bsd_checksum : public etl::checksum<T, etl::checksum_policy_bsd<T> >
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
bsd_checksum()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from range.
|
||||
/// \param begin Start of the range.
|
||||
/// \param end End of the range.
|
||||
//*************************************************************************
|
||||
template<typename TIterator>
|
||||
bsd_checksum(TIterator begin, const TIterator end)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
|
||||
|
||||
reset();
|
||||
add(begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// XOR Checksum.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
class xor_checksum : public etl::checksum<T, etl::checksum_policy_xor<T> >
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
xor_checksum()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor from range.
|
||||
/// \param begin Start of the range.
|
||||
/// \param end End of the range.
|
||||
//*************************************************************************
|
||||
template<typename TIterator>
|
||||
xor_checksum(TIterator begin, const TIterator end)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
|
||||
|
||||
reset();
|
||||
add(begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BIN
etl.pspimage
Normal file
BIN
etl.pspimage
Normal file
Binary file not shown.
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 3.2 KiB |
8
ideque.h
8
ideque.h
@ -116,7 +116,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
iterator operator +=(difference_type offset)
|
||||
iterator& operator +=(difference_type offset)
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
@ -132,7 +132,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
iterator operator -=(difference_type offset)
|
||||
iterator& operator -=(difference_type offset)
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
@ -310,7 +310,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
const_iterator operator +=(difference_type offset)
|
||||
const_iterator& operator +=(difference_type offset)
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
@ -326,7 +326,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//***************************************************
|
||||
const_iterator operator -=(difference_type offset)
|
||||
const_iterator& operator -=(difference_type offset)
|
||||
{
|
||||
if (offset > 0)
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@ Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
http://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2015 jwellbelove
|
||||
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
|
||||
@ -45,6 +45,7 @@ SOFTWARE.
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
#include "intrusive_links.h"
|
||||
#include "algorithm.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "20"
|
||||
@ -107,12 +108,26 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Unsorted exception for the intrusive_forward_list.
|
||||
///\ingroup intrusive_list
|
||||
//***************************************************************************
|
||||
class intrusive_forward_list_unsorted : public intrusive_forward_list_exception
|
||||
{
|
||||
public:
|
||||
|
||||
intrusive_forward_list_unsorted(string_type file_name, numeric_type line_number)
|
||||
: intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:unsorted", ETL_FILE"D"), file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// An intrusive forward list.
|
||||
///\ingroup intrusive_forward_list
|
||||
///\note TLink must be a base of TValue.
|
||||
//***************************************************************************
|
||||
template <typename TValue, typename TLink = etl::forward_link<0> >
|
||||
template <typename TValue, typename TLink = etl::forward_link<>, const size_t COUNT_OPTION = etl::count_option::FAST_COUNT >
|
||||
class intrusive_forward_list
|
||||
{
|
||||
public:
|
||||
@ -128,7 +143,7 @@ namespace etl
|
||||
typedef const value_type& const_reference;
|
||||
typedef size_t size_type;
|
||||
|
||||
public:
|
||||
typedef intrusive_forward_list<TValue, TLink, COUNT_OPTION> list_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// iterator.
|
||||
@ -239,7 +254,7 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(const typename intrusive_forward_list<value_type, link_type>::iterator& other)
|
||||
const_iterator(const typename intrusive_forward_list::iterator& other)
|
||||
: p_value(other.p_value)
|
||||
{
|
||||
}
|
||||
@ -427,8 +442,7 @@ namespace etl
|
||||
while (first != last)
|
||||
{
|
||||
link_type& link = *first++;
|
||||
join(p_last_link, &link);
|
||||
join(&link, nullptr);
|
||||
etl::link_splice<link_type>(p_last_link, link);
|
||||
p_last_link = &link;
|
||||
++current_size;
|
||||
}
|
||||
@ -475,24 +489,40 @@ namespace etl
|
||||
second = track; // Move second link to next
|
||||
}
|
||||
|
||||
join(&start_link, first);
|
||||
etl::link<link_type>(start_link, first);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts a value to the intrusive_forward_list after the specified position.
|
||||
//*************************************************************************
|
||||
iterator insert_after(iterator position, value_type& value)
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::DEFAULT, iterator>::type
|
||||
insert_after(iterator position, value_type& value)
|
||||
{
|
||||
insert_link_after(*position.p_value, value);
|
||||
return iterator(value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts a value to the intrusive_forward_list after the specified position.
|
||||
/// Checks that the value is unlinked.
|
||||
//*************************************************************************
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::CHECKED, iterator>::type
|
||||
insert_after(iterator position, value_type& value)
|
||||
{
|
||||
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.
|
||||
//*************************************************************************
|
||||
template <typename TIterator>
|
||||
void insert_after(iterator position, TIterator first, TIterator last)
|
||||
template <typename TIterator, typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::DEFAULT, void>::type
|
||||
insert_after(iterator position, TIterator first, TIterator last)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
@ -502,10 +532,30 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts a range of values to the intrusive_forward_list after the specified position.
|
||||
/// Checks that the values are unlinked.
|
||||
//*************************************************************************
|
||||
template <typename TIterator, typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::CHECKED, void>::type
|
||||
insert_after(iterator position, TIterator first, TIterator last)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Erases the value at the specified position.
|
||||
//*************************************************************************
|
||||
iterator erase_after(iterator position)
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::DEFAULT, iterator>::type
|
||||
erase_after(iterator position)
|
||||
{
|
||||
iterator next(position);
|
||||
++next;
|
||||
@ -516,17 +566,37 @@ namespace etl
|
||||
return next;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Erases the value at the specified position.
|
||||
/// Clears the link after erasing.
|
||||
//*************************************************************************
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::CHECKED, iterator>::type
|
||||
erase_after(iterator position)
|
||||
{
|
||||
iterator next(position);
|
||||
++next;
|
||||
++next;
|
||||
|
||||
remove_link_after(*position.p_value);
|
||||
position.p_value->TLink::clear();
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Erases a range of elements.
|
||||
//*************************************************************************
|
||||
iterator erase_after(iterator first, iterator last)
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::DEFAULT, iterator>::type
|
||||
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.
|
||||
join(p_first, p_last);
|
||||
etl::link<link_type>(p_first, p_last);
|
||||
|
||||
p_first = p_next;
|
||||
|
||||
@ -550,6 +620,44 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Erases a range of elements.
|
||||
/// Clears the links after erasing.
|
||||
//*************************************************************************
|
||||
template <typename T = TLink>
|
||||
typename etl::enable_if<T::OPTION == etl::link_option::CHECKED, iterator>::type
|
||||
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)
|
||||
{
|
||||
// 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.
|
||||
}
|
||||
|
||||
if (p_next == nullptr)
|
||||
{
|
||||
return end();
|
||||
}
|
||||
else
|
||||
{
|
||||
return iterator(*static_cast<value_type*>(p_last));
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Removes all but the one element from every consecutive group of equal
|
||||
/// elements in the container.
|
||||
@ -679,14 +787,14 @@ namespace etl
|
||||
// Add the next link to the merged head.
|
||||
if (i_head == before_begin())
|
||||
{
|
||||
join(i_head.p_value, i_link.p_value);
|
||||
i_head = i_link;
|
||||
i_tail = i_link;
|
||||
etl::link<link_type>(i_head.p_value, i_link.p_value);
|
||||
i_head = i_link;
|
||||
i_tail = i_link;
|
||||
}
|
||||
else
|
||||
{
|
||||
join(i_tail.p_value, i_link.p_value);
|
||||
i_tail = i_link;
|
||||
etl::link<link_type>(i_tail.p_value, i_link.p_value);
|
||||
i_tail = i_link;
|
||||
}
|
||||
|
||||
i_tail.p_value->link_type::etl_next = nullptr;
|
||||
@ -737,7 +845,7 @@ namespace etl
|
||||
{
|
||||
iterator i_item = begin();
|
||||
iterator i_last_item = before_begin();
|
||||
|
||||
|
||||
while (i_item != end())
|
||||
{
|
||||
if (predicate(*i_item))
|
||||
@ -753,41 +861,296 @@ namespace etl
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns true if the list has not elements.
|
||||
/// Returns true if the list has no elements.
|
||||
//*************************************************************************
|
||||
bool empty() const
|
||||
{
|
||||
return current_size == 0;
|
||||
return start_link.etl_next == nullptr;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the number of elements.
|
||||
//*************************************************************************
|
||||
size_t size() const
|
||||
template <const size_t OPT = COUNT_OPTION>
|
||||
typename etl::enable_if<OPT == etl::count_option::FAST_COUNT, size_t>::type
|
||||
size() const
|
||||
{
|
||||
return current_size;
|
||||
return current_size.count;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Returns the number of elements.
|
||||
//*************************************************************************
|
||||
template <const size_t OPT = COUNT_OPTION>
|
||||
typename etl::enable_if<OPT == etl::count_option::SLOW_COUNT, size_t>::type
|
||||
size() const
|
||||
{
|
||||
return std::distance(cbegin(), cend());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Splice another list into this one.
|
||||
//*************************************************************************
|
||||
void splice_after(iterator position, list_type& list)
|
||||
{
|
||||
// No point splicing to ourself!
|
||||
if (&list != this)
|
||||
{
|
||||
if (!list.empty())
|
||||
{
|
||||
link_type& first = list.get_head();
|
||||
|
||||
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
|
||||
{
|
||||
if (&list != this)
|
||||
{
|
||||
current_size += list.size();
|
||||
}
|
||||
}
|
||||
|
||||
link_type& before = *position.p_value;
|
||||
link_type& after = *position.p_value->link_type::etl_next;
|
||||
|
||||
etl::link<link_type>(before, first);
|
||||
|
||||
link_type* last = &before;
|
||||
while (last->link_type::etl_next != nullptr)
|
||||
{
|
||||
last = last->link_type::etl_next;
|
||||
}
|
||||
|
||||
etl::link<link_type>(last, after);
|
||||
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Splice an element from another list into this one.
|
||||
//*************************************************************************
|
||||
void splice(iterator position, list_type& list, 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 (&list != this)
|
||||
{
|
||||
++current_size;
|
||||
--list.current_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Splice a range of elements from another list into this one.
|
||||
//*************************************************************************
|
||||
void splice_after(iterator position, list_type& list, iterator begin_, iterator end_)
|
||||
{
|
||||
if (!list.empty())
|
||||
{
|
||||
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
|
||||
{
|
||||
if (&list != this)
|
||||
{
|
||||
size_t n = std::distance(begin_, end_) - 1;
|
||||
current_size += n;
|
||||
list.current_size -= n;
|
||||
}
|
||||
}
|
||||
|
||||
link_type* first = begin_.p_value;
|
||||
link_type* last = first;
|
||||
|
||||
while (last->link_type::etl_next != end_.p_value)
|
||||
{
|
||||
last = last->link_type::etl_next;
|
||||
}
|
||||
|
||||
// Unlink from the source list.
|
||||
link_type* first_next = first->link_type::etl_next;
|
||||
etl::unlink_after(*first, *last);
|
||||
|
||||
// Fix our links.
|
||||
link_type* before = position.p_value;
|
||||
|
||||
etl::link_splice<link_type>(*before, *first_next, *last);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Merge another list into this one. Both lists should be sorted.
|
||||
//*************************************************************************
|
||||
void merge(list_type& list)
|
||||
{
|
||||
merge(list, 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)
|
||||
{
|
||||
if (!list.empty())
|
||||
{
|
||||
#if _DEBUG
|
||||
ETL_ASSERT(etl::is_sorted(list.begin(), list.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_terminal = nullptr;
|
||||
|
||||
value_type* before = static_cast<value_type*>(&start_link);
|
||||
value_type* before_next = get_next(before);
|
||||
value_type* terminal = nullptr;
|
||||
|
||||
while ((before->link_type::etl_next != terminal) && (other_begin != other_terminal))
|
||||
{
|
||||
// Find the place to insert.
|
||||
while ((before_next != terminal) && !(compare(*other_begin, *before_next)))
|
||||
{
|
||||
before = before_next;
|
||||
before_next = get_next(before_next);
|
||||
}
|
||||
|
||||
// Insert.
|
||||
if (before_next != terminal)
|
||||
{
|
||||
while ((other_begin != other_terminal) && (compare(*other_begin, *before_next)))
|
||||
{
|
||||
value_type* value = other_begin;
|
||||
other_begin = get_next(other_begin);
|
||||
etl::link_splice<link_type>(*before, *value);
|
||||
before = get_next(before);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Any left over?
|
||||
if (before_next == terminal)
|
||||
{
|
||||
while (other_begin != other_terminal)
|
||||
{
|
||||
value_type* value = other_begin;
|
||||
other_begin = get_next(other_begin);
|
||||
etl::link_splice<link_type>(*before, *value);
|
||||
before = get_next(before);
|
||||
}
|
||||
}
|
||||
|
||||
if (COUNT_OPTION == etl::count_option::FAST_COUNT)
|
||||
{
|
||||
current_size += list.size();
|
||||
}
|
||||
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
link_type start_link; ///< The link that acts as the intrusive_forward_list start.
|
||||
size_t current_size; ///< The number of elements in the list.
|
||||
size_t index; ///< The index level of the link that this list operates on.
|
||||
|
||||
//*************************************************************************
|
||||
/// Counter type based on count option.
|
||||
//*************************************************************************
|
||||
template <const size_t OPTION>
|
||||
class counter_type;
|
||||
|
||||
//*************************************************************************
|
||||
/// Join two links.
|
||||
/// Slow type.
|
||||
//*************************************************************************
|
||||
void join(link_type* left, link_type* right)
|
||||
template <>
|
||||
class counter_type<etl::count_option::SLOW_COUNT>
|
||||
{
|
||||
left->etl_next = right;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Fast type.
|
||||
//*************************************************************************
|
||||
template <>
|
||||
class counter_type<etl::count_option::FAST_COUNT>
|
||||
{
|
||||
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 count;
|
||||
};
|
||||
|
||||
counter_type<COUNT_OPTION> current_size; ///< Counts the number of elements in the list.
|
||||
|
||||
//*************************************************************************
|
||||
/// Is the intrusive_forward_list a trivial length?
|
||||
//*************************************************************************
|
||||
bool is_trivial_list() const
|
||||
{
|
||||
return current_size <= 1;
|
||||
return (start_link.link_type::etl_next == nullptr) || (start_link.link_type::etl_next->etl_next == nullptr);;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -796,8 +1159,7 @@ namespace etl
|
||||
void insert_link_after(link_type& position, link_type& link)
|
||||
{
|
||||
// Connect to the intrusive_forward_list.
|
||||
join(&link, position.etl_next);
|
||||
join(&position, &link);
|
||||
etl::link_splice<link_type>(position, link);
|
||||
++current_size;
|
||||
}
|
||||
|
||||
@ -806,13 +1168,9 @@ namespace etl
|
||||
//*************************************************************************
|
||||
void remove_link_after(link_type& link)
|
||||
{
|
||||
// The link to erase.
|
||||
link_type* p_link = link.etl_next;
|
||||
|
||||
if (p_link != nullptr)
|
||||
if (link.etl_next != nullptr)
|
||||
{
|
||||
// Disconnect the link from the intrusive_forward_list.
|
||||
join(&link, p_link->etl_next);
|
||||
etl::unlink_after<link_type>(link);
|
||||
--current_size;
|
||||
}
|
||||
}
|
||||
@ -833,6 +1191,14 @@ namespace etl
|
||||
return *start_link.etl_next;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Get the next value.
|
||||
//*************************************************************************
|
||||
value_type* get_next(link_type* link) const
|
||||
{
|
||||
return static_cast<value_type*>(link->etl_next);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Initialise the intrusive_forward_list.
|
||||
//*************************************************************************
|
||||
|
||||
@ -31,7 +31,26 @@ SOFTWARE.
|
||||
#ifndef __ETL_INTRUSIVE_LINKS__
|
||||
#define __ETL_INTRUSIVE_LINKS__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "nullptr.h"
|
||||
#include "type_traits.h"
|
||||
#include "exception.h"
|
||||
#include "error_handler.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "21"
|
||||
|
||||
//*****************************************************************************
|
||||
// Note:
|
||||
// The link functions work slightly differently to the STL 'insert' convention
|
||||
// in that the second link parameter will be inserted after the first.
|
||||
// i.e.
|
||||
// If the list contains '1', '2', '3', '4' and "link_splice '2','5'" is invoked the
|
||||
// resulting list will contain '1', '2', '5', '3', '4'
|
||||
// This is to maintain consistency between forward and bidirectional links
|
||||
// and also is intuitive.
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
@ -39,84 +58,768 @@ namespace etl
|
||||
{
|
||||
enum
|
||||
{
|
||||
NO_AUTO_UNLINK = false,
|
||||
AUTO_UNLINK = true
|
||||
DEFAULT,
|
||||
AUTO,
|
||||
CHECKED
|
||||
};
|
||||
};
|
||||
|
||||
namespace count_option
|
||||
{
|
||||
enum
|
||||
{
|
||||
SLOW_COUNT,
|
||||
FAST_COUNT
|
||||
};
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Link exception.
|
||||
//***************************************************************************
|
||||
class link_exception : public etl::exception
|
||||
{
|
||||
public:
|
||||
|
||||
link_exception(string_type what, string_type file_name, numeric_type line_number)
|
||||
: exception(what, file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// not unlinked exception.
|
||||
//***************************************************************************
|
||||
class not_unlinked_exception : public etl::link_exception
|
||||
{
|
||||
public:
|
||||
|
||||
not_unlinked_exception(string_type file_name, numeric_type line_number)
|
||||
: link_exception(ETL_ERROR_TEXT("link:still linked", ETL_FILE"A"), file_name, line_number)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace __private_intrusive_links__
|
||||
{
|
||||
//***************************************************************************
|
||||
/// 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()
|
||||
{
|
||||
etl_next = nullptr;
|
||||
}
|
||||
|
||||
bool is_linked() const
|
||||
{
|
||||
return etl_next != nullptr;
|
||||
}
|
||||
|
||||
TLink* etl_next;
|
||||
};
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// A forward link.
|
||||
//***************************************************************************
|
||||
template <const size_t ID_ = 0>
|
||||
struct forward_link
|
||||
template <const size_t ID_ = 0, const size_t OPTION_ = etl::link_option::DEFAULT>
|
||||
struct forward_link
|
||||
: public __private_intrusive_links__::forward_link_base<forward_link<ID_, OPTION_>, ID_, OPTION_>
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
|
||||
forward_link* etl_next;
|
||||
};
|
||||
|
||||
//******************************************************************
|
||||
// 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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
~forward_link()
|
||||
{
|
||||
assert(etl_next != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink& lhs, TLink& rhs)
|
||||
{
|
||||
lhs.etl_next = &rhs;
|
||||
}
|
||||
|
||||
// Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink& rhs)
|
||||
{
|
||||
rhs.etl_next = lhs.etl_next;
|
||||
lhs.etl_next = &rhs;
|
||||
}
|
||||
|
||||
// Pointer, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink* lhs, TLink* rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
lhs->etl_next = rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink* rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
rhs->etl_next = lhs->etl_next;
|
||||
}
|
||||
|
||||
lhs->etl_next = rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink& lhs, TLink* rhs)
|
||||
{
|
||||
lhs.etl_next = rhs;
|
||||
}
|
||||
|
||||
// Reference, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink* rhs)
|
||||
{
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
rhs->etl_next = lhs.etl_next;
|
||||
}
|
||||
|
||||
lhs.etl_next = rhs;
|
||||
}
|
||||
|
||||
// Pointer, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink* lhs, TLink& rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
lhs->etl_next = &rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink& rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
rhs.etl_next = lhs->etl_next;
|
||||
lhs->etl_next = &rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink& first, TLink& last)
|
||||
{
|
||||
last.etl_next = lhs.etl_next;
|
||||
lhs.etl_next = &first;
|
||||
}
|
||||
|
||||
// Pointer, Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink& first, TLink& last)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
last.etl_next = lhs->etl_next;
|
||||
lhs->etl_next = &first;
|
||||
}
|
||||
else
|
||||
{
|
||||
last.etl_next = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
unlink_after(TLink& node)
|
||||
{
|
||||
if (node.etl_next != nullptr)
|
||||
{
|
||||
node.etl_next = node.etl_next->etl_next;
|
||||
|
||||
if ((TLink::OPTION == etl::link_option::AUTO) ||
|
||||
(TLink::OPTION == etl::link_option::CHECKED))
|
||||
{
|
||||
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
|
||||
unlink_after(TLink& before, TLink& last)
|
||||
{
|
||||
before.etl_next = last.etl_next;
|
||||
|
||||
if ((TLink::OPTION == etl::link_option::AUTO) ||
|
||||
(TLink::OPTION == etl::link_option::CHECKED))
|
||||
{
|
||||
last.clear();
|
||||
}
|
||||
}
|
||||
|
||||
namespace __private_intrusive_links__
|
||||
{
|
||||
//***************************************************************************
|
||||
/// A bidirectional link base.
|
||||
//***************************************************************************
|
||||
template <typename TLink, const size_t ID_, const size_t OPTION_>
|
||||
struct bidirectional_link_base
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID = ID_,
|
||||
OPTION = OPTION_
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
etl_previous = nullptr;
|
||||
etl_next = nullptr;
|
||||
}
|
||||
|
||||
bool is_linked() const
|
||||
{
|
||||
return (etl_previous != nullptr) || (etl_next != nullptr);
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
std::swap(etl_previous, etl_next);
|
||||
}
|
||||
|
||||
TLink* etl_previous;
|
||||
TLink* etl_next;
|
||||
|
||||
protected:
|
||||
|
||||
void base_unlink()
|
||||
{
|
||||
// Connect the previous link with the next.
|
||||
if (etl_previous != nullptr)
|
||||
{
|
||||
etl_previous->etl_next = etl_next;
|
||||
}
|
||||
|
||||
// Connect the next link with the previous.
|
||||
if (etl_next != nullptr)
|
||||
{
|
||||
etl_next->etl_previous = etl_previous;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// A bidirectional link.
|
||||
//***************************************************************************
|
||||
template <const size_t ID_ = 0, const bool AUTO_UNLINK = etl::link_option::NO_AUTO_UNLINK>
|
||||
struct bidirectional_link
|
||||
template <const size_t ID_ = 0, const size_t OPTION_ = etl::link_option::DEFAULT>
|
||||
struct bidirectional_link
|
||||
: public __private_intrusive_links__::bidirectional_link_base<bidirectional_link<ID_, OPTION_>, ID_, OPTION_>
|
||||
{
|
||||
enum
|
||||
void unlink()
|
||||
{
|
||||
ID = ID_,
|
||||
};
|
||||
|
||||
bidirectional_link* etl_previous;
|
||||
bidirectional_link* etl_next;
|
||||
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_UNLINK>
|
||||
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>
|
||||
{
|
||||
enum
|
||||
bidirectional_link()
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
clear();
|
||||
}
|
||||
|
||||
~bidirectional_link()
|
||||
{
|
||||
// Connect the previous link with the next.
|
||||
if (etl_previous != nullptr)
|
||||
{
|
||||
etl_previous->etl_next = etl_next;
|
||||
}
|
||||
|
||||
// Connect the next link with the previous.
|
||||
if (etl_next != nullptr)
|
||||
{
|
||||
etl_next->etl_previous = etl_previous;
|
||||
}
|
||||
base_unlink();
|
||||
}
|
||||
|
||||
bidirectional_link* etl_previous;
|
||||
bidirectional_link* etl_next;
|
||||
void unlink()
|
||||
{
|
||||
base_unlink();
|
||||
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()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
~bidirectional_link()
|
||||
{
|
||||
assert(etl_previous == nullptr);
|
||||
assert(etl_next == nullptr);
|
||||
}
|
||||
|
||||
void unlink()
|
||||
{
|
||||
base_unlink();
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
// Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink& lhs, TLink& rhs)
|
||||
{
|
||||
lhs.etl_next = &rhs;
|
||||
rhs.etl_previous = &lhs;
|
||||
}
|
||||
|
||||
// Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink& rhs)
|
||||
{
|
||||
rhs.etl_next = lhs.etl_next;
|
||||
rhs.etl_previous = &lhs;
|
||||
|
||||
if (lhs.etl_next != nullptr)
|
||||
{
|
||||
lhs.etl_next->etl_previous = &rhs;
|
||||
}
|
||||
|
||||
lhs.etl_next = &rhs;
|
||||
}
|
||||
|
||||
// Pointer, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink* lhs, TLink* rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
lhs->etl_next = rhs;
|
||||
}
|
||||
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
rhs->etl_previous = lhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink* rhs)
|
||||
{
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
rhs->etl_next = lhs->etl_next;
|
||||
}
|
||||
|
||||
rhs->etl_previous = lhs;
|
||||
}
|
||||
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
if (lhs->etl_next != nullptr)
|
||||
{
|
||||
lhs->etl_next->etl_previous = rhs;
|
||||
}
|
||||
|
||||
lhs->etl_next = rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink& lhs, TLink* rhs)
|
||||
{
|
||||
lhs.etl_next = rhs;
|
||||
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
rhs->etl_previous = &lhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink* rhs)
|
||||
{
|
||||
if (rhs != nullptr)
|
||||
{
|
||||
rhs->etl_next = lhs.etl_next;
|
||||
rhs->etl_previous = &lhs;
|
||||
}
|
||||
|
||||
if (lhs.etl_next != nullptr)
|
||||
{
|
||||
lhs.etl_next->etl_previous = rhs;
|
||||
}
|
||||
|
||||
lhs.etl_next = rhs;
|
||||
}
|
||||
|
||||
// Pointer, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link(TLink* lhs, TLink& rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
lhs->etl_next = &rhs;
|
||||
}
|
||||
|
||||
rhs.etl_previous = lhs;
|
||||
}
|
||||
|
||||
// Pointer, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink& rhs)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
rhs.etl_next = lhs->etl_next;
|
||||
}
|
||||
|
||||
rhs.etl_previous = lhs;
|
||||
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
if (lhs->etl_next != nullptr)
|
||||
{
|
||||
lhs->etl_next->etl_previous = &rhs;
|
||||
}
|
||||
|
||||
lhs->etl_next = &rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink& lhs, TLink& first, TLink& last)
|
||||
{
|
||||
last.etl_next = lhs.etl_next;
|
||||
first.etl_previous = &lhs;
|
||||
|
||||
if (last.etl_next != nullptr)
|
||||
{
|
||||
last.etl_next->etl_previous = &last;
|
||||
}
|
||||
|
||||
lhs.etl_next = &first;
|
||||
}
|
||||
|
||||
// Pointer, Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_splice(TLink* lhs, TLink& first, TLink& last)
|
||||
{
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
last.etl_next = lhs->etl_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
last.etl_next = nullptr;
|
||||
}
|
||||
|
||||
first.etl_previous = lhs;
|
||||
|
||||
if (last.etl_next != nullptr)
|
||||
{
|
||||
last.etl_next->etl_previous = &last;
|
||||
}
|
||||
|
||||
if (lhs != nullptr)
|
||||
{
|
||||
lhs->etl_next = &first;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
unlink(TLink& node)
|
||||
{
|
||||
node.unlink();
|
||||
}
|
||||
|
||||
// Reference Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
unlink(TLink& first, TLink& last)
|
||||
{
|
||||
if (&first == &last)
|
||||
{
|
||||
first.unlink();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last.etl_next != nullptr)
|
||||
{
|
||||
last.etl_next->etl_previous = first.etl_previous;
|
||||
}
|
||||
|
||||
if (first.etl_previous != nullptr)
|
||||
{
|
||||
first.etl_previous->etl_next = last.etl_next;
|
||||
}
|
||||
|
||||
if ((TLink::OPTION == etl::link_option::AUTO) ||
|
||||
(TLink::OPTION == etl::link_option::CHECKED))
|
||||
{
|
||||
first.etl_previous = nullptr;
|
||||
last.etl_next = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace __private_intrusive_links__
|
||||
{
|
||||
//***************************************************************************
|
||||
/// A tree link base.
|
||||
//***************************************************************************
|
||||
template <typename TLink, const size_t ID_, const size_t OPTION_>
|
||||
struct tree_link_base
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID = ID_,
|
||||
OPTION = OPTION_
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
etl_parent = nullptr;
|
||||
etl_left = nullptr;
|
||||
etl_right = nullptr;
|
||||
}
|
||||
|
||||
bool is_linked() const
|
||||
{
|
||||
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_ = 0>
|
||||
template <const size_t ID_ = 0, const size_t OPTION_ = etl::link_option::DEFAULT>
|
||||
struct tree_link
|
||||
: public __private_intrusive_links__::tree_link_base<tree_link<ID_, OPTION_>, ID_, OPTION_>
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID = ID_
|
||||
};
|
||||
|
||||
tree_link* etl_parent;
|
||||
tree_link* etl_left;
|
||||
tree_link* etl_right;
|
||||
};
|
||||
|
||||
//******************************************************************
|
||||
// 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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
~tree_link()
|
||||
{
|
||||
assert(etl_parent != nullptr);
|
||||
assert(etl_left != nullptr);
|
||||
assert(etl_right != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Reference, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_left(TLink& parent, TLink& leaf)
|
||||
{
|
||||
parent.etl_left = &leaf;
|
||||
leaf.etl_parent = &parent;
|
||||
}
|
||||
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_right(TLink& parent, TLink& leaf)
|
||||
{
|
||||
parent.etl_right = &leaf;
|
||||
leaf.etl_parent = &parent;
|
||||
}
|
||||
|
||||
// Pointer, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_left(TLink* parent, TLink* leaf)
|
||||
{
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->etl_left = leaf;
|
||||
}
|
||||
|
||||
if (leaf != nullptr)
|
||||
{
|
||||
leaf->etl_parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_right(TLink* parent, TLink* leaf)
|
||||
{
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->etl_right = leaf;
|
||||
}
|
||||
|
||||
if (leaf != nullptr)
|
||||
{
|
||||
leaf->etl_parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Reference, Pointer
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_left(TLink& parent, TLink* leaf)
|
||||
{
|
||||
parent.etl_left = leaf;
|
||||
|
||||
if (leaf != nullptr)
|
||||
{
|
||||
leaf->etl_parent = &parent;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_right(TLink& parent, TLink* leaf)
|
||||
{
|
||||
parent.etl_right = leaf;
|
||||
|
||||
if (leaf != nullptr)
|
||||
{
|
||||
leaf->etl_parent = &parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer, Reference
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_left(TLink* parent, TLink& leaf)
|
||||
{
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->etl_left = &leaf;
|
||||
}
|
||||
|
||||
leaf.etl_parent = parent;
|
||||
}
|
||||
|
||||
template <typename TLink>
|
||||
typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID, TLink::OPTION> >::value, void>::type
|
||||
link_right(TLink* parent, TLink& leaf)
|
||||
{
|
||||
if (parent != nullptr)
|
||||
{
|
||||
parent->etl_right = &leaf;
|
||||
}
|
||||
|
||||
leaf.etl_parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#undef ETL_FILE
|
||||
#endif
|
||||
1244
intrusive_list.h
Normal file
1244
intrusive_list.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,31 +33,30 @@ SOFTWARE.
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../bsd_checksum.h"
|
||||
#include "../endian.h"
|
||||
|
||||
template <typename TSum, typename TIterator>
|
||||
TSum reference_checksum(TIterator begin, TIterator end)
|
||||
{
|
||||
typedef typename std::iterator_traits<TIterator>::value_type value_type;
|
||||
TSum checksum = 0;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
value_type value = *begin++;
|
||||
|
||||
for (int i = 0; i < sizeof(value_type); ++i)
|
||||
{
|
||||
uint8_t byte = (value >> (i * 8)) & 0xFF;
|
||||
checksum = etl::rotate_right(checksum) + byte;
|
||||
}
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
#include "../checksum.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
{
|
||||
template <typename TSum, typename TIterator>
|
||||
TSum reference_checksum(TIterator begin, TIterator end)
|
||||
{
|
||||
typedef typename std::iterator_traits<TIterator>::value_type value_type;
|
||||
TSum checksum = 0;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
value_type value = *begin++;
|
||||
|
||||
for (int i = 0; i < sizeof(value_type); ++i)
|
||||
{
|
||||
uint8_t byte = (value >> (i * 8)) & 0xFF;
|
||||
checksum = etl::rotate_right(checksum) + byte;
|
||||
}
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
SUITE(test_checksum)
|
||||
{
|
||||
//*************************************************************************
|
||||
|
||||
@ -76,6 +76,11 @@ namespace
|
||||
return data < other.data;
|
||||
}
|
||||
|
||||
bool operator >(const ItemNDCNode& other) const
|
||||
{
|
||||
return other.data < data;
|
||||
}
|
||||
|
||||
ItemNDC data;
|
||||
};
|
||||
|
||||
@ -130,25 +135,6 @@ namespace
|
||||
typedef etl::intrusive_forward_list<ItemNDCNode, SecondLink> DataNDC1;
|
||||
|
||||
typedef std::vector<ItemNDCNode> InitialDataNDC;
|
||||
|
||||
template <typename TIterator1, typename TIterator2>
|
||||
bool Equal(TIterator1 begin1,
|
||||
TIterator1 end1,
|
||||
TIterator2 begin2)
|
||||
{
|
||||
while (begin1 != end1)
|
||||
{
|
||||
if (*begin1 != *begin2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
++begin1;
|
||||
++begin2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -157,9 +143,15 @@ namespace
|
||||
{
|
||||
InitialDataNDC unsorted_data;
|
||||
InitialDataNDC sorted_data;
|
||||
InitialDataNDC sorted_data2;
|
||||
InitialDataNDC non_unique_data;
|
||||
InitialDataNDC unique_data;
|
||||
InitialDataNDC small_data;
|
||||
InitialDataNDC merge_data0;
|
||||
InitialDataNDC merge_data1;
|
||||
InitialDataNDC merge_data2;
|
||||
InitialDataNDC merge_data3;
|
||||
InitialDataNDC merge_data4;
|
||||
|
||||
bool are_equal;
|
||||
|
||||
@ -170,9 +162,16 @@ namespace
|
||||
{
|
||||
unsorted_data = { ItemNDCNode("1"), ItemNDCNode("0"), ItemNDCNode("3"), ItemNDCNode("2"), ItemNDCNode("5"), ItemNDCNode("4"), ItemNDCNode("7"), ItemNDCNode("6"), ItemNDCNode("9"), ItemNDCNode("8") };
|
||||
sorted_data = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("8"), ItemNDCNode("9") };
|
||||
sorted_data2 = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("8"), ItemNDCNode("9") };
|
||||
non_unique_data = { ItemNDCNode("0"), ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5") };
|
||||
unique_data = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5") };
|
||||
small_data = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5") };
|
||||
|
||||
merge_data0 = { ItemNDCNode("1"), ItemNDCNode("1"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("5"), ItemNDCNode("7"), ItemNDCNode("8") };
|
||||
merge_data1 = { ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("6"), ItemNDCNode("9"), ItemNDCNode("9") };
|
||||
merge_data2 = { ItemNDCNode("0"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("7") };
|
||||
merge_data3 = { ItemNDCNode("0"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("6"), ItemNDCNode("7") };
|
||||
merge_data4 = { ItemNDCNode("0"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("3"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("8"), ItemNDCNode("9") };
|
||||
}
|
||||
};
|
||||
|
||||
@ -195,6 +194,20 @@ namespace
|
||||
CHECK_EQUAL(sorted_data.size(), data0.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_empty_begin_end)
|
||||
{
|
||||
DataNDC0 data0;
|
||||
|
||||
CHECK(data0.begin() == data0.end());
|
||||
|
||||
DataNDC0::const_iterator begin = data0.begin();
|
||||
DataNDC0::const_iterator end = data0.end();
|
||||
CHECK(begin == end);
|
||||
|
||||
CHECK(data0.cbegin() == data0.cend());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_iterator)
|
||||
{
|
||||
@ -317,7 +330,7 @@ namespace
|
||||
ItemNDCNode INSERT_VALUE1 = ItemNDCNode("1");
|
||||
ItemNDCNode INSERT_VALUE2 = ItemNDCNode("2");
|
||||
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
@ -326,16 +339,16 @@ namespace
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, offset);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, offset + 1);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, offset);
|
||||
|
||||
data0.insert_after(i_data, INSERT_VALUE1);
|
||||
compare_data.insert(i_compare_data, INSERT_VALUE1);
|
||||
compare_data.insert_after(i_compare_data, INSERT_VALUE1);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -348,19 +361,19 @@ namespace
|
||||
std::advance(i_data, offset);
|
||||
|
||||
i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, offset + 1);
|
||||
std::advance(i_compare_data, offset);
|
||||
|
||||
std::vector<ItemNDCNode> temp(data0.begin(), data0.end());
|
||||
std::forward_list<ItemNDCNode> temp(data0.begin(), data0.end());
|
||||
|
||||
data0.insert_after(i_data, INSERT_VALUE2);
|
||||
compare_data.insert(i_compare_data, INSERT_VALUE2);
|
||||
compare_data.insert_after(i_compare_data, INSERT_VALUE2);
|
||||
|
||||
temp.assign(data0.begin(), data0.end());
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -373,8 +386,8 @@ namespace
|
||||
{
|
||||
std::vector<ItemNDCNode> test1 = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4") };
|
||||
std::vector<ItemNDCNode> test2 = { ItemNDCNode("5"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("8"), ItemNDCNode("9") };
|
||||
std::vector<ItemNDCNode> compare(test2);
|
||||
compare.insert(compare.end(), test1.begin(), test1.end());
|
||||
std::forward_list<ItemNDCNode> compare(test1.begin(), test1.end());
|
||||
compare.insert_after(compare.before_begin(), test2.begin(), test2.end());
|
||||
|
||||
DataNDC0 data0(test1.begin(), test1.end());
|
||||
DataNDC1 data1(test1.begin(), test1.end());
|
||||
@ -392,16 +405,16 @@ namespace
|
||||
compare.assign(test1.begin(), test1.end());
|
||||
data0.assign(test1.begin(), test1.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator icd = compare.begin();
|
||||
std::forward_list<ItemNDCNode>::iterator icd = compare.begin();
|
||||
DataNDC0::iterator id = data0.begin();
|
||||
|
||||
std::advance(icd, 4);
|
||||
std::advance(icd, 3);
|
||||
std::advance(id, 3);
|
||||
|
||||
compare.insert(icd, test2.begin(), test2.end());
|
||||
compare.insert_after(icd, test2.begin(), test2.end());
|
||||
data0.insert_after(id, test2.begin(), test2.end());
|
||||
|
||||
std::vector<ItemNDCNode> out(data0.begin(), data0.end());
|
||||
std::forward_list<ItemNDCNode> out(data0.begin(), data0.end());
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare.begin());
|
||||
CHECK(are_equal);
|
||||
@ -500,17 +513,17 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_single)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, 2);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, 3);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, 2);
|
||||
|
||||
i_compare_data = compare_data.erase(i_compare_data);
|
||||
i_compare_data = compare_data.erase_after(i_compare_data);
|
||||
i_data = data0.erase_after(i_data);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
@ -518,14 +531,14 @@ namespace
|
||||
CHECK(are_equal);
|
||||
CHECK(*i_compare_data == *i_data);
|
||||
|
||||
i_compare_data = compare_data.erase(compare_data.begin() + 1);
|
||||
i_compare_data = compare_data.erase_after(compare_data.begin());
|
||||
i_data = data0.erase_after(data0.begin());
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -536,8 +549,8 @@ namespace
|
||||
CHECK(are_equal);
|
||||
|
||||
// Move to the last value and erase.
|
||||
i_compare_data = compare_data.begin() + 1;
|
||||
i_compare_data = compare_data.erase(i_compare_data);
|
||||
i_compare_data = compare_data.begin();
|
||||
i_compare_data = compare_data.erase_after(i_compare_data);
|
||||
|
||||
i_data = data0.begin();
|
||||
i_data = data0.erase_after(i_data);
|
||||
@ -545,8 +558,8 @@ namespace
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -560,23 +573,23 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_range)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data2.begin(), sorted_data2.end());
|
||||
|
||||
DataNDC0::iterator i_data_1 = data0.begin();
|
||||
std::advance(i_data_1, 2);
|
||||
|
||||
DataNDC0::iterator i_data_2 = data0.begin();
|
||||
std::advance(i_data_2, 4);
|
||||
std::advance(i_data_2, 5);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data_1 = compare_data.begin();
|
||||
std::advance(i_compare_data_1, 3);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_data_1 = compare_data.begin();
|
||||
std::advance(i_compare_data_1, 2);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data_2 = compare_data.begin();
|
||||
std::advance(i_compare_data_2, 4);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_data_2 = compare_data.begin();
|
||||
std::advance(i_compare_data_2, 5);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data_1, i_compare_data_2);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_result = compare_data.erase_after(i_compare_data_1, i_compare_data_2);
|
||||
|
||||
DataNDC0::iterator i_result = data0.erase_after(i_data_1, i_data_2);
|
||||
|
||||
@ -584,8 +597,8 @@ namespace
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -596,17 +609,17 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_after_range_end)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC0::iterator i_data = data0.begin();
|
||||
std::advance(i_data, 4);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, 5);
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
|
||||
std::advance(i_compare_data, 4);
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data, compare_data.end());
|
||||
std::forward_list<ItemNDCNode>::iterator i_compare_result = compare_data.erase_after(i_compare_data, compare_data.end());
|
||||
|
||||
DataNDC0::iterator i_result = data0.erase_after(i_data, data0.end());
|
||||
|
||||
@ -614,8 +627,8 @@ namespace
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -665,19 +678,18 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_remove)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_item = std::find(compare_data.begin(), compare_data.end(), ItemNDCNode("7"));
|
||||
compare_data.erase(i_item);
|
||||
compare_data.remove(ItemNDCNode("7"));
|
||||
data0.remove(ItemNDCNode("7"));
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -688,19 +700,18 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_remove_if)
|
||||
{
|
||||
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
std::forward_list<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC1 data1(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
std::vector<ItemNDCNode>::iterator i_item = std::find(compare_data.begin(), compare_data.end(), ItemNDCNode("7"));
|
||||
compare_data.erase(i_item);
|
||||
compare_data.remove_if(std::bind2nd(std::equal_to<ItemNDCNode>(), ItemNDCNode("7")));
|
||||
data0.remove_if(std::bind2nd(std::equal_to<ItemNDCNode>(), ItemNDCNode("7")));
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin());
|
||||
|
||||
CHECK(are_equal);
|
||||
CHECK_EQUAL(compare_data.size(), data0.size());
|
||||
CHECK_EQUAL(compare_data.size(), std::distance(data0.begin(), data0.end()));
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare_data.begin(), compare_data.end()), std::distance(data0.begin(), data0.end()));
|
||||
|
||||
are_equal = std::equal(data1.begin(), data1.end(), sorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
@ -752,5 +763,242 @@ namespace
|
||||
are_equal = std::equal(data1.begin(), data1.end(), unsorted_data.begin());
|
||||
CHECK(are_equal);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_list)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data1(sorted_data2.begin(), sorted_data2.end());
|
||||
|
||||
DataNDC0::iterator idata_destination = data0.begin();
|
||||
std::advance(idata_destination, 3);
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(data0.begin(), data0.end());
|
||||
std::forward_list<ItemNDCNode> compare1(data1.begin(), data1.end());
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_destination = compare0.begin();
|
||||
std::advance(icompare_destination, 3);
|
||||
|
||||
data0.splice_after(idata_destination, data1);
|
||||
compare0.splice_after(icompare_destination, compare1);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare1.begin(), compare1.end()), data1.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_list_self)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC0::iterator idata_destination = data0.begin();
|
||||
std::advance(idata_destination, 3);
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(data0.begin(), data0.end());
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_destination = compare0.begin();
|
||||
std::advance(icompare_destination, 3);
|
||||
|
||||
data0.splice_after(idata_destination, data0);
|
||||
compare0.splice_after(icompare_destination, compare0);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_range)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
DataNDC0 data1(sorted_data2.begin(), sorted_data2.end());
|
||||
|
||||
DataNDC0::iterator idata_destination = data0.begin();
|
||||
std::advance(idata_destination, 2);
|
||||
|
||||
DataNDC0::iterator idata_begin = data1.begin();
|
||||
std::advance(idata_begin, 4);
|
||||
|
||||
DataNDC0::iterator idata_end = data1.begin();
|
||||
std::advance(idata_end, 7);
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(data0.begin(), data0.end());
|
||||
std::forward_list<ItemNDCNode> compare1(data1.begin(), data1.end());
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_destination = compare0.begin();
|
||||
std::advance(icompare_destination, 2);
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_begin = compare1.begin();
|
||||
std::advance(icompare_begin, 4);
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_end = compare1.begin();
|
||||
std::advance(icompare_end, 7);
|
||||
|
||||
data0.splice_after(idata_destination, data1, idata_begin, idata_end);
|
||||
compare0.splice_after(icompare_destination, compare1, icompare_begin, icompare_end);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare1.begin(), compare1.end()), data1.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_splice_range_self)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(sorted_data.begin(), sorted_data.end());
|
||||
|
||||
DataNDC0::iterator idata_destination = data0.begin();
|
||||
std::advance(idata_destination, 2);
|
||||
|
||||
DataNDC0::iterator idata_begin = data0.begin();
|
||||
std::advance(idata_begin, 4);
|
||||
|
||||
DataNDC0::iterator idata_end = data0.begin();
|
||||
std::advance(idata_end, 7);
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(data0.begin(), data0.end());
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_destination = compare0.begin();
|
||||
std::advance(icompare_destination, 2);
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_begin = compare0.begin();
|
||||
std::advance(icompare_begin, 4);
|
||||
|
||||
std::forward_list<ItemNDCNode>::iterator icompare_end = compare0.begin();
|
||||
std::advance(icompare_end, 7);
|
||||
|
||||
data0.splice_after(idata_destination, data0, idata_begin, idata_end);
|
||||
compare0.splice_after(icompare_destination, compare0, icompare_begin, icompare_end);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_0_1)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC0 data1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(merge_data0.begin(), merge_data0.end());
|
||||
std::forward_list<ItemNDCNode> compare1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
data0.merge(data1);
|
||||
compare0.merge(compare1);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare1.begin(), compare1.end()), data1.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_0_2)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC0 data2(merge_data2.begin(), merge_data2.end());
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(merge_data0.begin(), merge_data0.end());
|
||||
std::forward_list<ItemNDCNode> compare2(merge_data2.begin(), merge_data2.end());
|
||||
|
||||
data0.merge(data2);
|
||||
compare0.merge(compare2);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare2.begin(), compare2.end()), data2.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_0_3)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC0 data3(merge_data3.begin(), merge_data3.end());
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(merge_data0.begin(), merge_data0.end());
|
||||
std::forward_list<ItemNDCNode> compare3(merge_data3.begin(), merge_data3.end());
|
||||
|
||||
data0.merge(data3);
|
||||
compare0.merge(compare3);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare3.begin(), compare3.end()), data3.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_0_4)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC0 data4(merge_data4.begin(), merge_data4.end());
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(merge_data0.begin(), merge_data0.end());
|
||||
std::forward_list<ItemNDCNode> compare4(merge_data4.begin(), merge_data4.end());
|
||||
|
||||
data0.merge(data4);
|
||||
compare0.merge(compare4);
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare4.begin(), compare4.end()), data4.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_merge_0_1_reverse_order)
|
||||
{
|
||||
bool are_equal;
|
||||
|
||||
DataNDC0 data0(merge_data0.begin(), merge_data0.end());
|
||||
DataNDC0 data1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
data0.reverse();
|
||||
data1.reverse();
|
||||
|
||||
std::forward_list<ItemNDCNode> compare0(merge_data0.begin(), merge_data0.end());
|
||||
std::forward_list<ItemNDCNode> compare1(merge_data1.begin(), merge_data1.end());
|
||||
|
||||
compare0.reverse();
|
||||
compare1.reverse();
|
||||
|
||||
data0.merge(data1, std::greater<ItemNDCNode>());
|
||||
compare0.merge(compare1, std::greater<ItemNDCNode>());
|
||||
|
||||
are_equal = std::equal(data0.begin(), data0.end(), compare0.begin());
|
||||
CHECK(are_equal);
|
||||
|
||||
CHECK_EQUAL(std::distance(compare0.begin(), compare0.end()), data0.size());
|
||||
CHECK_EQUAL(std::distance(compare1.begin(), compare1.end()), data1.size());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1098
test/test_intrusive_list.cpp
Normal file
1098
test/test_intrusive_list.cpp
Normal file
File diff suppressed because it is too large
Load Diff
149
test/test_xor_checksum.cpp
Normal file
149
test/test_xor_checksum.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/******************************************************************************
|
||||
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.
|
||||
******************************************************************************/
|
||||
|
||||
#include <UnitTest++/UnitTest++.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../checksum.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename TSum, typename TIterator>
|
||||
TSum reference_checksum(TIterator begin, TIterator end)
|
||||
{
|
||||
typedef typename std::iterator_traits<TIterator>::value_type value_type;
|
||||
TSum checksum = 0;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
value_type value = *begin++;
|
||||
checksum ^= value;
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
SUITE(test_checksum)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_constructor)
|
||||
{
|
||||
std::string data("123456789");
|
||||
|
||||
uint8_t sum = etl::xor_checksum<uint8_t>(data.begin(), data.end());
|
||||
uint8_t compare = reference_checksum<uint8_t>(data.begin(), data.end());
|
||||
|
||||
CHECK_EQUAL(int(compare), int(sum));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_add_values8_add)
|
||||
{
|
||||
std::string data("123456789");
|
||||
|
||||
etl::xor_checksum<uint8_t> checksum_calculator;
|
||||
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
checksum_calculator.add(data[i]);
|
||||
}
|
||||
|
||||
uint8_t sum = checksum_calculator;
|
||||
uint8_t compare = reference_checksum<uint8_t>(data.begin(), data.end());
|
||||
|
||||
CHECK_EQUAL(int(compare), int(sum));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_add_values8_operator_plus_equals)
|
||||
{
|
||||
std::string data("123456789");
|
||||
|
||||
etl::xor_checksum<uint8_t> checksum_calculator;
|
||||
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
{
|
||||
checksum_calculator.add(data[i]);
|
||||
}
|
||||
|
||||
uint8_t sum = checksum_calculator;
|
||||
uint8_t compare = reference_checksum<uint8_t>(data.begin(), data.end());
|
||||
|
||||
CHECK_EQUAL(int(compare), int(sum));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_add_range)
|
||||
{
|
||||
std::string data("123456789");
|
||||
|
||||
etl::xor_checksum<uint8_t> checksum_calculator;
|
||||
|
||||
checksum_calculator.add(data.begin(), data.end());
|
||||
|
||||
uint8_t sum = checksum_calculator.value();
|
||||
uint8_t compare = reference_checksum<uint8_t>(data.begin(), data.end());
|
||||
|
||||
CHECK_EQUAL(int(compare), int(sum));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_add_range_sum32)
|
||||
{
|
||||
std::string data("1");
|
||||
|
||||
etl::xor_checksum<uint32_t> checksum_calculator;
|
||||
|
||||
checksum_calculator.add(data.begin(), data.end());
|
||||
|
||||
uint32_t sum = checksum_calculator.value();
|
||||
uint32_t compare = reference_checksum<uint32_t>(data.begin(), data.end());
|
||||
|
||||
CHECK_EQUAL(compare, sum);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_checksum_add_range_endian)
|
||||
{
|
||||
std::vector<uint8_t> data1 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
||||
std::vector<uint32_t> data2 = { 0x04030201, 0x08070605 };
|
||||
std::vector<uint8_t> data3 = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
|
||||
|
||||
uint64_t hash1 = etl::xor_checksum<uint8_t>(data1.begin(), data1.end());
|
||||
uint64_t hash2 = etl::xor_checksum<uint8_t>((uint8_t*)&data2[0], (uint8_t*)&data2[0] + (data2.size() * sizeof(uint32_t)));
|
||||
uint64_t hash3 = etl::xor_checksum<uint8_t>(data3.rbegin(), data3.rend());
|
||||
CHECK_EQUAL(hash1, hash2);
|
||||
CHECK_EQUAL(hash1, hash3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -7,10 +7,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "etl", "etl.vcxproj", "{C21D
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug No Unit Tests|Win32 = Debug No Unit Tests|Win32
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug No Unit Tests|Win32.ActiveCfg = Debug No Unit Tests|Win32
|
||||
{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug No Unit Tests|Win32.Build.0 = Debug No Unit Tests|Win32
|
||||
{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Release|Win32.ActiveCfg = Release|Win32
|
||||
|
||||
@ -160,7 +160,6 @@
|
||||
<ClInclude Include="..\..\binary.h" />
|
||||
<ClInclude Include="..\..\bitset.h" />
|
||||
<ClInclude Include="..\..\bloom_filter.h" />
|
||||
<ClInclude Include="..\..\bsd_checksum.h" />
|
||||
<ClInclude Include="..\..\char_traits.h" />
|
||||
<ClInclude Include="..\..\checksum.h" />
|
||||
<ClInclude Include="..\..\crc16.h" />
|
||||
@ -206,6 +205,7 @@
|
||||
<ClInclude Include="..\..\integral_limits.h" />
|
||||
<ClInclude Include="..\..\intrusive_forward_list.h" />
|
||||
<ClInclude Include="..\..\intrusive_links.h" />
|
||||
<ClInclude Include="..\..\intrusive_list.h" />
|
||||
<ClInclude Include="..\..\io_port.h" />
|
||||
<ClInclude Include="..\..\ipool.h" />
|
||||
<ClInclude Include="..\..\ipriority_queue.h" />
|
||||
@ -338,6 +338,7 @@
|
||||
<ClCompile Include="..\test_integral_limits.cpp" />
|
||||
<ClCompile Include="..\test_intrusive_forward_list.cpp" />
|
||||
<ClCompile Include="..\test_intrusive_links.cpp" />
|
||||
<ClCompile Include="..\test_intrusive_list.cpp" />
|
||||
<ClCompile Include="..\test_io_port.cpp" />
|
||||
<ClCompile Include="..\test_jenkins.cpp" />
|
||||
<ClCompile Include="..\test_largest.cpp" />
|
||||
@ -369,6 +370,7 @@
|
||||
<ClCompile Include="..\test_variant.cpp" />
|
||||
<ClCompile Include="..\test_vector.cpp" />
|
||||
<ClCompile Include="..\test_visitor.cpp" />
|
||||
<ClCompile Include="..\test_xor_checksum.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Doxyfile" />
|
||||
|
||||
@ -372,9 +372,6 @@
|
||||
<ClInclude Include="..\..\pearson.h">
|
||||
<Filter>ETL\Maths</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\bsd_checksum.h">
|
||||
<Filter>ETL\Maths</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\flat_multimap.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
@ -465,6 +462,9 @@
|
||||
<ClInclude Include="..\..\intrusive_links.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\intrusive_list.h">
|
||||
<Filter>ETL\Containers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\unittest-cpp\UnitTest++\AssertException.cpp">
|
||||
@ -713,6 +713,12 @@
|
||||
<ClCompile Include="..\test_intrusive_links.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_intrusive_list.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_xor_checksum.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Doxyfile">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user