Merge remote-tracking branch 'origin/development'

This commit is contained in:
John Wellbelove 2016-02-10 19:08:58 +00:00
commit 73e38fa176
18 changed files with 5186 additions and 402 deletions

View File

@ -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

View File

@ -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.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

BIN
etl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

BIN
etl.pspimage Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -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)
{

View File

@ -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.
//*************************************************************************

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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)
{
//*************************************************************************

View File

@ -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

File diff suppressed because it is too large Load Diff

149
test/test_xor_checksum.cpp Normal file
View 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);
}
};
}

View File

@ -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

View File

@ -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" />

View File

@ -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">