Merge remote-tracking branch 'origin/development'

This commit is contained in:
John Wellbelove 2015-12-09 15:33:14 +00:00
commit 8bb5d26377
29 changed files with 3844 additions and 2651 deletions

View File

@ -0,0 +1,577 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2015 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
//*****************************************************************************
// This forward list is intended for internal library use.
// It may be used as a very low cost intrusive forward list.
// Elements in the list are accessed as basic_intrusive_forward_list_node.
// Code using this list will be required to cast to the real data type.
// etl::basic_intrusive_forward_list will throw no exceptions or errors.
//*****************************************************************************
#ifndef __ETL_BASIC_INTRUSIVE_FORWARD_LIST__
#define __ETL_BASIC_INTRUSIVE_FORWARD_LIST__
#include <iterator>
#include <stddef.h>
#include "nullptr.h"
#include "type_traits.h"
#include "basic_intrusive_forward_list_node.h"
namespace etl
{
//***************************************************************************
/// An intrusive forward list.
///\ingroup basic_intrusive_forward_list
//***************************************************************************
class basic_intrusive_forward_list
{
public:
// Node typedef.
typedef basic_intrusive_forward_list_node node_t;
// STL style typedefs.
typedef node_t value_type;
typedef node_t* pointer;
typedef const node_t* const_pointer;
typedef node_t& reference;
typedef const node_t& const_reference;
typedef size_t size_type;
public:
//*************************************************************************
/// iterator.
//*************************************************************************
class iterator : public std::iterator<std::forward_iterator_tag, value_type>
{
public:
friend class basic_intrusive_forward_list;
iterator()
: p_node(nullptr)
{
}
iterator(node_t& node)
: p_node(&node)
{
}
iterator(const iterator& other)
: p_node(other.p_node)
{
}
iterator& operator ++()
{
p_node = p_node->next;
return *this;
}
iterator operator ++(int)
{
iterator temp(*this);
p_node = p_node->next;
return temp;
}
iterator operator =(const iterator& other)
{
p_node = other.p_node;
return *this;
}
reference operator *()
{
return *p_node;
}
const_reference operator *() const
{
return *p_node;
}
pointer operator &()
{
return p_node;
}
const_pointer operator &() const
{
return p_node;
}
pointer operator ->()
{
return p_node;
}
const_pointer operator ->() const
{
return p_node;
}
friend bool operator == (const iterator& lhs, const iterator& rhs)
{
return lhs.p_node == rhs.p_node;
}
friend bool operator != (const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
template<typename T>
T& ref_cast()
{
return static_cast<T&>(*p_node);
}
template<typename T>
const T& ref_cast() const
{
return static_cast<const T&>(*p_node);
}
private:
node_t* p_node;
};
//*************************************************************************
/// const_iterator
//*************************************************************************
class const_iterator : public std::iterator<std::forward_iterator_tag, const value_type>
{
public:
friend class basic_intrusive_forward_list;
const_iterator()
: p_node(nullptr)
{
}
const_iterator(node_t& node)
: p_node(&node)
{
}
const_iterator(const node_t& node)
: p_node(&node)
{
}
const_iterator(const basic_intrusive_forward_list::iterator& other)
: p_node(other.p_node)
{
}
const_iterator(const const_iterator& other)
: p_node(other.p_node)
{
}
const_iterator& operator ++()
{
p_node = p_node->next;
return *this;
}
const_iterator operator ++(int)
{
const_iterator temp(*this);
p_node = p_node->next;
return temp;
}
const_iterator operator =(const const_iterator& other)
{
p_node = other.p_node;
return *this;
}
const_reference operator *() const
{
return *p_node;
}
const_pointer operator &() const
{
return p_node;
}
const_pointer operator ->() const
{
return p_node;
}
friend bool operator == (const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.p_node == rhs.p_node;
}
friend bool operator != (const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
template<typename T>
const T& ref_cast() const
{
return static_cast<const T&>(*p_node);
}
private:
const node_t* p_node;
};
typedef std::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
/// Constructor.
//*************************************************************************
basic_intrusive_forward_list()
{
initialise();
}
//*************************************************************************
/// Constructor from range
//*************************************************************************
template <typename TIterator>
basic_intrusive_forward_list(TIterator first, TIterator last)
{
assign(first, last);
}
//*************************************************************************
/// Gets the beginning of the basic_intrusive_forward_list.
//*************************************************************************
iterator begin()
{
return iterator(get_head());
}
//*************************************************************************
/// Gets the beginning of the basic_intrusive_forward_list.
//*************************************************************************
const_iterator begin() const
{
return const_iterator(get_head());
}
//*************************************************************************
/// Gets before the beginning of the basic_intrusive_forward_list.
//*************************************************************************
iterator before_begin()
{
return iterator(start_node);
}
//*************************************************************************
/// Gets before the beginning of the basic_intrusive_forward_list.
//*************************************************************************
const_iterator before_begin() const
{
return const_iterator(start_node);
}
//*************************************************************************
/// Gets the beginning of the basic_intrusive_forward_list.
//*************************************************************************
const_iterator cbegin() const
{
return const_iterator(get_head());
}
//*************************************************************************
/// Gets the end of the basic_intrusive_forward_list.
//*************************************************************************
iterator end()
{
return iterator();
}
//*************************************************************************
/// Gets the end of the basic_intrusive_forward_list.
//*************************************************************************
const_iterator end() const
{
return const_iterator();
}
//*************************************************************************
/// Gets the end of the basic_intrusive_forward_list.
//*************************************************************************
const_iterator cend() const
{
return const_iterator();
}
//*************************************************************************
/// Clears the basic_intrusive_forward_list.
//*************************************************************************
void clear()
{
initialise();
}
//*************************************************************************
/// Gets a reference to the first element.
//*************************************************************************
template <typename T>
T& front()
{
return static_cast<T&>(get_head());
}
//*************************************************************************
/// Gets a const reference to the first element.
//*************************************************************************
template <typename T>
const_reference front() const
{
return static_cast<const T&>(get_head());
}
//*************************************************************************
/// Assigns a range of values to the basic_intrusive_forward_list.
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
initialise();
node_t* p_last_node = &start_node;
// Add all of the elements.
while (first != last)
{
node_t& node = *first++;
join(p_last_node, &node);
join(&node, nullptr);
p_last_node = &node;
}
}
//*************************************************************************
/// Pushes a value to the front of the basic_intrusive_forward_list.
//*************************************************************************
void push_front(node_t& value)
{
insert_node_after(start_node, value);
}
//*************************************************************************
/// Removes a value from the front of the basic_intrusive_forward_list.
//*************************************************************************
void pop_front()
{
if (!empty())
{
remove_node_after(start_node);
}
}
//*************************************************************************
/// Reverses the basic_intrusive_forward_list.
//*************************************************************************
void reverse()
{
if ((start_node.next == nullptr) || (start_node.next->next == nullptr))
{
return;
}
node_t* first = nullptr; // To keep first node
node_t* second = start_node.next; // To keep second node
node_t* track = start_node.next; // Track the list
while (track != NULL)
{
track = track->next; // Track point to next node;
second->next = first; // Second node point to first
first = second; // Move first node to next
second = track; // Move second node to next
}
join(&start_node, first);
}
//*************************************************************************
/// Inserts a value to the basic_intrusive_forward_list after the specified position.
//*************************************************************************
iterator insert_after(iterator position, node_t& value)
{
insert_node_after(*position.p_node, value);
return iterator(value);
}
//*************************************************************************
/// Inserts a range of values to the basic_intrusive_forward_list after the specified position.
//*************************************************************************
template <typename TIterator>
void insert_after(iterator position, TIterator first, TIterator last)
{
while (first != last)
{
// Set up the next free node.
insert_node_after(*position.p_node, *first++);
++position;
}
}
//*************************************************************************
/// Erases the value at the specified position.
//*************************************************************************
iterator erase_after(iterator position)
{
iterator next(position);
++next;
++next;
remove_node_after(*position.p_node);
return next;
}
//*************************************************************************
/// Erases a range of elements.
//*************************************************************************
iterator erase_after(iterator first, iterator last)
{
node_t* p_first = first.p_node;
node_t* p_last = last.p_node;
node_t* p_next = p_first->next;
// Join the ends.
join(p_first, p_last);
p_first = p_next;
// Erase the ones in between.
while (p_first != p_last)
{
p_next = p_first->next; // Remember the next node.
p_first = p_next; // Move to the next node.
}
if (p_next == nullptr)
{
return end();
}
else
{
return iterator(*p_last);
}
}
//*************************************************************************
/// Returns true if the list has no elements.
//*************************************************************************
bool empty() const
{
return start_node.next == nullptr;
}
private:
node_t start_node; ///< The node that acts as the basic_intrusive_forward_list start.
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(node_t* left, node_t* right)
{
left->next = right;
}
//*************************************************************************
/// Insert a node.
//*************************************************************************
void insert_node_after(node_t& position, node_t& node)
{
// Connect to the basic_intrusive_forward_list.
join(&node, position.next);
join(&position, &node);
}
//*************************************************************************
/// Remove a node.
//*************************************************************************
void remove_node_after(node_t& node)
{
// The node to erase.
node_t* p_node = node.next;
if (p_node != nullptr)
{
// Disconnect the node from the basic_intrusive_forward_list.
join(&node, p_node->next);
}
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
node_t& get_head()
{
return *start_node.next;
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
const node_t& get_head() const
{
return *start_node.next;
}
//*************************************************************************
/// Initialise the basic_intrusive_forward_list.
//*************************************************************************
void initialise()
{
start_node.next = nullptr;
}
// Disabled.
basic_intrusive_forward_list(const basic_intrusive_forward_list& other);
basic_intrusive_forward_list& operator = (const basic_intrusive_forward_list& rhs);
};
}
#endif

View File

@ -0,0 +1,45 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2015 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_BASIC_INTRUSIVE_FORWARD_LIST_NODE__
#define __ETL_BASIC_INTRUSIVE_FORWARD_LIST_NODE__
namespace etl
{
//***************************************************************************
/// The node element in the basic_intrusive_forward_list.
/// Derive intrusive node data elements from this.
//***************************************************************************
struct basic_intrusive_forward_list_node
{
basic_intrusive_forward_list_node* next;
};
}
#endif

845
bitset.h
View File

@ -33,20 +33,12 @@ SOFTWARE.
#include <algorithm>
#include <iterator>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include "integral_limits.h"
#include "smallest.h"
#include "array.h"
#include "nullptr.h"
#include "log.h"
#include "ibitset.h"
#include "binary.h"
#if WIN32
#undef min
#endif
#if defined(COMPILER_KEIL)
#pragma diag_suppress 1300
@ -70,501 +62,22 @@ namespace etl
template <const size_t N>
class bitset : public ibitset
{
// The type used for each element in the array.
typedef typename smallest_uint_for_bits<N>::type element_t;
static const element_t ALL_SET = etl::integral_limits<element_t>::max;
static const element_t ALL_CLEAR = 0;
static const size_t BITS_PER_ELEMENT = etl::integral_limits<element_t>::bits;
static const size_t ARRAY_SIZE = (N % BITS_PER_ELEMENT == 0) ? N / BITS_PER_ELEMENT : N / BITS_PER_ELEMENT + 1;
static const size_t ARRAY_SIZE = (N % BITS_PER_ELEMENT == 0) ? N / BITS_PER_ELEMENT : N / BITS_PER_ELEMENT + 1;
public:
static const size_t TOTAL_BITS = ARRAY_SIZE * BITS_PER_ELEMENT;
private:
static const size_t TOP_MASK_SHIFT = ((BITS_PER_ELEMENT - (TOTAL_BITS - N)) % BITS_PER_ELEMENT);
static const element_t TOP_MASK = element_t(TOP_MASK_SHIFT == 0 ? ALL_SET : ~(ALL_SET << TOP_MASK_SHIFT));
static const size_t ALLOCATED_BITS = ARRAY_SIZE * BITS_PER_ELEMENT;
public:
//*************************************************************************
/// The reference type returned.
//*************************************************************************
class bit_reference
{
public:
friend class bitset<N>;
//*******************************
/// Conversion operator.
//*******************************
operator bool() const
{
return p_bitset->test(position);
}
//*******************************
/// Assignment operator.
//*******************************
bit_reference& operator = (bool b)
{
p_bitset->set(position, b);
return *this;
}
//*******************************
/// Assignment operator.
//*******************************
bit_reference& operator = (const bit_reference& r)
{
p_bitset->set(position, bool(r));
return *this;
}
//*******************************
/// Flip the bit.
//*******************************
bit_reference& flip()
{
p_bitset->flip(position);
return *this;
}
//*******************************
/// Return the logical inverse of the bit.
//*******************************
bool operator~() const
{
return !p_bitset->test(position);
}
private:
//*******************************
/// Default constructor.
//*******************************
bit_reference()
: p_bitset(nullptr),
position(0)
{
}
//*******************************
/// Constructor.
//*******************************
bit_reference(bitset<N>& r_bitset, size_t position)
: p_bitset(&r_bitset),
position(position)
{
}
bitset<N>* p_bitset; ///< The bitset.
size_t position; ///< The position in the bitset.
};
//*************************************************************************
/// The iterator type.
//*************************************************************************
class iterator : public std::iterator<std::random_access_iterator_tag, bool>
{
public:
friend class bitset<N>;
friend class const_iterator;
//*******************************
/// Constructor
//*******************************
iterator()
: position(0)
{
}
//*******************************
/// Copy constructor
//*******************************
iterator(const iterator& other)
: position(other.position)
{
}
//*******************************
/// ++ operator (pre)
//*******************************
iterator& operator ++()
{
++position;
return *this;
}
//*******************************
/// ++ operator (post)
//*******************************
iterator operator ++(int)
{
iterator temp(*this);
++position;
return temp;
}
//*******************************
/// -- operator (pre)
//*******************************
iterator& operator --()
{
--position;
return *this;
}
//*******************************
/// -- operator (post)
//*******************************
iterator operator --(int)
{
iterator temp(*this);
--position;
return temp;
}
//*******************************
/// * operator
//*******************************
bit_reference operator *()
{
return bit_reference(*p_bitset, position);
}
//*******************************
/// * operator const
//*******************************
bool operator *() const
{
return p_bitset->test(position);
}
//*******************************
/// += operator
//*******************************
iterator& operator +=(int i)
{
position += i;
return *this;
}
//*******************************
/// -= operator
//*******************************
iterator& operator -=(int i)
{
position -= i;
return *this;
}
//*******************************
/// = operator
//*******************************
iterator& operator =(const iterator& other)
{
position = other.position;
p_bitset = other.p_bitset;
return *this;
}
//*******************************
/// + operator
//*******************************
friend iterator operator +(const iterator& other, int i)
{
iterator temp(other);
temp += i;
return temp;
}
//*******************************
/// - operator
//*******************************
friend iterator operator -(const iterator& other, int i)
{
iterator temp(other);
temp -= i;
return temp;
}
//*******************************
/// - operator
//*******************************
friend long operator -(const iterator& lhs, const iterator& rhs)
{
return long(lhs.position) - long(rhs.position);
}
//*******************************
/// == operator
//*******************************
friend bool operator ==(const iterator& lhs, const iterator& rhs)
{
return lhs.position == rhs.position;
}
//*******************************
/// != operator
//*******************************
friend bool operator !=(const iterator& lhs, const iterator& rhs)
{
return lhs.position != rhs.position;
}
//*******************************
/// < operator
//*******************************
friend bool operator <(const iterator& lhs, const iterator& rhs)
{
return lhs.position < rhs.position;
}
//*******************************
/// > operator
//*******************************
friend bool operator >(const iterator& lhs, const iterator& rhs)
{
return lhs.position > rhs.position;
}
//*******************************
/// <= operator
//*******************************
friend bool operator <=(const iterator& lhs, const iterator& rhs)
{
return lhs.position <= rhs.position;
}
//*******************************
/// >= operator
//*******************************
friend bool operator >=(const iterator& lhs, const iterator& rhs)
{
return lhs.position >-rhs.position;
}
private:
//*******************************
/// Constructor
//*******************************
iterator(bitset<N>& r_bitset, size_t position)
: p_bitset(&r_bitset),
position(position)
{}
bitset<N>* p_bitset;
size_t position;
};
//*************************************************************************
/// The const_iterator type.
//*************************************************************************
class const_iterator : public std::iterator<std::random_access_iterator_tag, const bool>
{
public:
friend class bitset<N>;
//*******************************
/// Constructor
//*******************************
const_iterator()
: position(0)
{
}
//*******************************
/// Copy constructor from iterator
//*******************************
const_iterator(const typename bitset<N>::iterator& other)
: position(other.position)
{
}
//*******************************
/// Copy constructor
//*******************************
const_iterator(const const_iterator& other)
: position(other.position)
{
}
//*******************************
/// ++ operator (pre)
//*******************************
const_iterator& operator ++()
{
++position;
return *this;
}
//*******************************
/// ++ operator (post)
//*******************************
const_iterator operator ++(int)
{
const_iterator temp(*this);
++position;
return temp;
}
//*******************************
/// -- operator (pre)
//*******************************
const_iterator& operator --()
{
--position;
return *this;
}
//*******************************
/// -- operator (post)
//*******************************
const_iterator operator --(int)
{
const_iterator temp(*this);
--position;
return temp;
}
//*******************************
/// * operator const
//*******************************
bool operator *() const
{
return p_bitset->test(position);
}
//*******************************
/// += operator
//*******************************
const_iterator& operator +=(int i)
{
position += i;
return *this;
}
//*******************************
/// -= operator
//*******************************
const_iterator& operator -=(int i)
{
position -= i;
return *this;
}
//*******************************
/// = operator
//*******************************
const_iterator& operator =(const const_iterator& other)
{
position = other.position;
p_bitset = other.p_bitset;
return *this;
}
//*******************************
/// + operator
//*******************************
friend const_iterator operator +(const const_iterator& other, int i)
{
const_iterator temp(other);
temp += i;
return temp;
}
//*******************************
/// - operator
//*******************************
friend const_iterator operator -(const const_iterator& other, int i)
{
const_iterator temp(other);
temp -= i;
return temp;
}
//*******************************
/// - operator
//*******************************
friend long operator -(const const_iterator& lhs, const const_iterator& rhs)
{
return long(lhs.position) - long(rhs.position);
}
//*******************************
/// == operator
//*******************************
friend bool operator ==(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position == rhs.position;
}
//*******************************
/// != operator
//*******************************
friend bool operator !=(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position != rhs.position;
}
//*******************************
/// < operator
//*******************************
friend bool operator <(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position < rhs.position;
}
//*******************************
/// > operator
//*******************************
friend bool operator >(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position > rhs.position;
}
//*******************************
/// <= operator
//*******************************
friend bool operator <=(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position <= rhs.position;
}
//*******************************
/// >= operator
//*******************************
friend bool operator >=(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.position >- rhs.position;
}
private:
//*******************************
/// Constructor
//*******************************
const_iterator(bitset<N>& r_bitset, size_t position)
: p_bitset(&r_bitset),
position(position)
{
}
bitset<N>* p_bitset;
size_t position;
};
//*************************************************************************
/// Default constructor.
//*************************************************************************
bitset()
: ibitset(N, ARRAY_SIZE, data)
{
reset();
}
@ -573,14 +86,16 @@ namespace etl
/// Copy constructor.
//*************************************************************************
bitset(const bitset<N>& other)
: ibitset(N, ARRAY_SIZE, data)
{
data = other.data;
std::copy(other.data, other.data + ARRAY_SIZE, data);
}
//*************************************************************************
/// Construct from a value.
//*************************************************************************
bitset(unsigned long long value)
: ibitset(N, ARRAY_SIZE, data)
{
reset();
@ -602,22 +117,16 @@ namespace etl
}
}
data.back() &= TOP_MASK;
data[ARRAY_SIZE - 1] &= TOP_MASK;
}
//*************************************************************************
/// Construct from a string.
//*************************************************************************
bitset(const char* text)
: ibitset(N, ARRAY_SIZE, data)
{
reset();
size_t i = std::min(N, strlen(text));
while (i > 0)
{
set(--i, *text++ == '1');
}
set(text);
}
//*************************************************************************
@ -625,9 +134,7 @@ namespace etl
//*************************************************************************
bitset<N>& set()
{
data.fill(ALL_SET);
data.back() &= TOP_MASK;
ibitset::set();
return *this;
}
@ -636,32 +143,7 @@ namespace etl
//*************************************************************************
bitset<N>& set(size_t position, bool value = true)
{
if (position < N)
{
size_t index;
element_t bit;
if (ARRAY_SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
if (value)
{
data[index] |= bit;
}
else
{
data[index] &= ~bit;
}
}
ibitset::set(position, value);
return *this;
}
@ -670,15 +152,7 @@ namespace etl
//*************************************************************************
bitset<N>& set(const char* text)
{
reset();
size_t i = std::min(N, strlen(text));
while (i > 0)
{
set(--i, *text++ == '1');
}
ibitset::set(text);
return *this;
}
@ -687,7 +161,7 @@ namespace etl
//*************************************************************************
bitset<N>& reset()
{
data.fill(ALL_CLEAR);
ibitset::reset();
return *this;
}
@ -696,25 +170,7 @@ namespace etl
//*************************************************************************
bitset<N>& reset(size_t position)
{
if (position < N)
{
size_t index;
element_t bit;
if (ARRAY_SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
data[index] &= ~bit;
}
ibitset::reset(position);
return *this;
}
@ -723,13 +179,7 @@ namespace etl
//*************************************************************************
bitset<N>& flip()
{
for (size_t i = 0; i < ARRAY_SIZE; ++i)
{
data[i] = ~data[i];
}
data.back() &= TOP_MASK;
ibitset::flip();
return *this;
}
@ -738,216 +188,21 @@ namespace etl
//*************************************************************************
bitset<N>& flip(size_t position)
{
if (position < N)
{
size_t index;
element_t bit;
if (ARRAY_SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
data[index] ^= bit;
}
ibitset::flip(position);
return *this;
}
//*************************************************************************
/// Read [] operator.
/// operator =
//*************************************************************************
bool operator[] (size_t position) const
{
return test(position);
}
//*************************************************************************
/// Write [] operator.
//*************************************************************************
bit_reference operator [] (size_t position)
{
return bit_reference(*this, position);
}
//*************************************************************************
/// Tests a bit at a position.
/// Positions greater than the number of configured bits will return <b>false</b>.
//*************************************************************************
bool test(size_t position) const
{
if (position < N)
{
size_t index;
element_t mask;
if (ARRAY_SIZE == 1)
{
index = 0;
mask = element_t(1) << position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
mask = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
return (data[index] & mask) != 0;
}
else
{
return false;
}
}
//*************************************************************************
// Are all the bits sets?
//*************************************************************************
bool all() const
{
// All but the last.
for (size_t i = 0; i < (ARRAY_SIZE - 1); ++i)
{
if (data[i] != ALL_SET)
{
return false;
}
}
// The last.
if (data[ARRAY_SIZE - 1] != (ALL_SET & TOP_MASK))
{
return false;
}
return true;
}
//*************************************************************************
/// Are any of the bits set?
//*************************************************************************
bool any() const
{
return !none();
}
//*************************************************************************
/// Are none of the bits set?
//*************************************************************************
bool none() const
bitset<N>& operator =(const bitset<N>& other)
{
for (size_t i = 0; i < ARRAY_SIZE; ++i)
{
if (data[i] != 0)
{
return false;
}
data[i] = other.data[i];
}
return true;
}
//*************************************************************************
/// Count the number of bits set.
//*************************************************************************
size_t count() const
{
size_t n = 0;
for (size_t i = 0; i < ARRAY_SIZE; ++i)
{
n += etl::count_bits(data[i]);
}
return n;
}
//*************************************************************************
/// The size of the bitset.
//*************************************************************************
size_t size() const
{
return N;
}
//*************************************************************************
/// Finds the first bit in the specified state.
///\param state The state to search for.
///\returns The position of the bit or size() if none were found.
//*************************************************************************
size_t find_first(bool state) const
{
return find_next(state, 0);
}
//*************************************************************************
/// Finds the next bit in the specified state.
///\param state The state to search for.
///\param position The position to start from.
///\returns The position of the bit or size() if none were found.
//*************************************************************************
size_t find_next(bool state, size_t position) const
{
// Where to start.
size_t index;
size_t bit;
if (ARRAY_SIZE == 1)
{
index = 0;
bit = position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = position & (BITS_PER_ELEMENT - 1);
}
element_t mask = 1 << bit;
// For each element in the bitset...
while (index < ARRAY_SIZE)
{
element_t value = data[index];
// Needs checking?
if (( state && (value != ALL_CLEAR)) ||
(!state && (value != ALL_SET)))
{
// For each bit in the element...
while ((bit < BITS_PER_ELEMENT) && (position < N))
{
// Equal to the required state?
if (((value & mask) != 0) == state)
{
return position;
}
// Move on to the next bit.
mask <<= 1;
++position;
++bit;
}
}
else
{
position += BITS_PER_ELEMENT;
}
// Start at the beginning for all other elements.
bit = 0;
mask = 1;
++index;
}
return ibitset::npos;
return *this;
}
//*************************************************************************
@ -1115,58 +370,12 @@ namespace etl
//*************************************************************************
void swap(bitset<N>& other)
{
data.swap(other.data);
for (size_t i = 0; i < ARRAY_SIZE; ++i)
{
std::swap(data, other.data);
}
}
//*************************************************************************
/// begin
//*************************************************************************
iterator begin()
{
return iterator(*this, 0);
}
//*************************************************************************
/// begin
//*************************************************************************
const_iterator begin() const
{
return const_iterator(*this, 0);
}
//*************************************************************************
/// cbegin
//*************************************************************************
const_iterator cbegin()
{
return const_iterator(*this, 0);
}
//*************************************************************************
/// end
//*************************************************************************
iterator end()
{
return iterator(*this, N);
}
//*************************************************************************
/// end
//*************************************************************************
const_iterator end() const
{
return const_iterator(*this, N);
}
//*************************************************************************
/// cend
//*************************************************************************
const_iterator cend()
{
return const_iterator(*this, N);
}
//*************************************************************************
/// operator ==
//*************************************************************************
@ -1185,7 +394,7 @@ namespace etl
private:
etl::array<element_t, ARRAY_SIZE> data;
element_t data[ARRAY_SIZE];
};
//***************************************************************************
@ -1244,8 +453,4 @@ void swap(etl::bitset<N>& lhs, etl::bitset<N>& rhs)
lhs.swap(rhs);
}
#if WIN32
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif

View File

@ -83,7 +83,7 @@ namespace etl
enum
{
// Make the most efficient use of the bitset.
WIDTH = etl::bitset<DESIRED_WIDTH>::TOTAL_BITS
WIDTH = etl::bitset<DESIRED_WIDTH>::ALLOCATED_BITS
};
//***************************************************************************

View File

@ -87,6 +87,21 @@ namespace etl
//***************************************************************************
class forward_list_base
{
protected:
//*************************************************************************
/// The node element in the forward_list.
//*************************************************************************
struct Node
{
Node()
: next(nullptr)
{
}
Node* next;
};
public:
typedef size_t size_type; ///< The type used for determining the size of forward_list.
@ -132,6 +147,34 @@ namespace etl
return max_size() - size();
}
//*************************************************************************
/// Reverses the forward_list.
//*************************************************************************
void reverse()
{
if (is_trivial_list())
{
return;
}
Node* p_last = &start_node;
Node* p_current = p_last->next;
Node* p_next = p_current->next;
p_current->next = nullptr;
while (p_next != nullptr)
{
p_last = p_current;
p_current = p_next;
p_next = p_current->next;
p_current->next = p_last;
}
join(&start_node, p_current);
}
protected:
//*************************************************************************
@ -144,6 +187,53 @@ namespace etl
{
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
Node& get_head()
{
return *start_node.next;
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
const Node& get_head() const
{
return *start_node.next;
}
//*************************************************************************
/// Insert a node.
//*************************************************************************
void insert_node_after(Node& position, Node& node)
{
// Connect to the forward_list.
node.next = position.next;
join(&position, &node);
// One more.
++current_size;
}
//*************************************************************************
/// Is the forward_list a trivial length?
//*************************************************************************
bool is_trivial_list() const
{
return (size() < 2);
}
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(Node* left, Node* right)
{
left->next = right;
}
Node start_node; ///< The node that acts as the forward_list start.
size_type next_free; ///< The index of the next free node.
size_type current_size; ///< The number of items in the list.
const size_type MAX_SIZE; ///< The maximum size of the forward_list.

437
ibitset.h
View File

@ -30,7 +30,15 @@ SOFTWARE.
#ifndef __ETL_IBITSET__
#define __ETL_IBITSET__
#include <algorithm>
#include <stdint.h>
#include "integral_limits.h"
#include "binary.h"
#if WIN32
#undef min
#endif
namespace etl
{
@ -40,58 +48,343 @@ namespace etl
//*************************************************************************
class ibitset
{
protected:
// The type used for each element in the array.
typedef uint8_t element_t;
public:
static const element_t ALL_SET = etl::integral_limits<element_t>::max;
static const element_t ALL_CLEAR = 0;
static const size_t BITS_PER_ELEMENT = etl::integral_limits<element_t>::bits;
enum
{
npos = etl::integral_limits<size_t>::max
};
//*************************************************************************
/// Default constructor.
/// The reference type returned.
//*************************************************************************
ibitset()
class bit_reference
{
}
public:
//*************************************************************************
/// Destructor.
//*************************************************************************
virtual ~ibitset()
{
}
friend class ibitset;
//*******************************
/// Conversion operator.
//*******************************
operator bool() const
{
return p_bitset->test(position);
}
//*******************************
/// Assignment operator.
//*******************************
bit_reference& operator = (bool b)
{
p_bitset->set(position, b);
return *this;
}
//*******************************
/// Assignment operator.
//*******************************
bit_reference& operator = (const bit_reference& r)
{
p_bitset->set(position, bool(r));
return *this;
}
//*******************************
/// Flip the bit.
//*******************************
bit_reference& flip()
{
p_bitset->flip(position);
return *this;
}
//*******************************
/// Return the logical inverse of the bit.
//*******************************
bool operator~() const
{
return !p_bitset->test(position);
}
private:
//*******************************
/// Default constructor.
//*******************************
bit_reference()
: p_bitset(nullptr),
position(0)
{
}
//*******************************
/// Constructor.
//*******************************
bit_reference(ibitset& r_bitset, size_t position)
: p_bitset(&r_bitset),
position(position)
{
}
ibitset* p_bitset; ///< The bitset.
size_t position; ///< The position in the bitset.
};
//*************************************************************************
/// The size of the bitset.
//*************************************************************************
virtual size_t size() const = 0;
size_t size() const
{
return NBITS;
}
//*************************************************************************
/// Check the bit at the position.
/// Count the number of bits set.
//*************************************************************************
virtual bool test(size_t position) const = 0;
size_t count() const
{
size_t n = 0;
for (size_t i = 0; i < SIZE; ++i)
{
n += etl::count_bits(pdata[i]);
}
return n;
}
//*************************************************************************
/// Tests a bit at a position.
/// Positions greater than the number of configured bits will return <b>false</b>.
//*************************************************************************
bool test(size_t position) const
{
size_t index;
element_t mask;
if (SIZE == 1)
{
index = 0;
mask = element_t(1) << position;
}
else
{
index = position >> etl::log2<BITS_PER_ELEMENT>::value;
mask = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
return (pdata[index] & mask) != 0;
}
//*************************************************************************
/// Set the bit at the position.
//*************************************************************************
virtual ibitset& set(size_t position, bool value = true) = 0;
ibitset& set()
{
for (size_t i = 0; i < SIZE; ++i)
{
pdata[i] = ALL_SET;
}
pdata[SIZE - 1] &= TOP_MASK;
return *this;
}
//*************************************************************************
/// Set the bit at the position.
//*************************************************************************
ibitset& set(size_t position, bool value = true)
{
size_t index;
element_t bit;
if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> etl::log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
if (value)
{
pdata[index] |= bit;
}
else
{
pdata[index] &= ~bit;
}
return *this;
}
//*************************************************************************
/// Set from a string.
//*************************************************************************
ibitset& set(const char* text)
{
reset();
size_t i = std::min(NBITS, strlen(text));
while (i > 0)
{
set(--i, *text++ == '1');
}
return *this;
}
//*************************************************************************
/// Resets the bitset.
//*************************************************************************
ibitset& reset()
{
for (size_t i = 0; i < SIZE; ++i)
{
pdata[i] = ALL_CLEAR;
}
return *this;
}
//*************************************************************************
/// Reset the bit at the position.
//*************************************************************************
virtual ibitset& reset(size_t position) = 0;
ibitset& reset(size_t position)
{
size_t index;
element_t bit;
if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> etl::log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
pdata[index] &= ~bit;
return *this;
}
//*************************************************************************
/// Reset all the bits.
/// Flip all of the bits.
//*************************************************************************
virtual ibitset& reset() = 0;
ibitset& flip()
{
for (size_t i = 0; i < SIZE; ++i)
{
pdata[i] = ~pdata[i];
}
pdata[SIZE - 1] &= TOP_MASK;
return *this;
}
//*************************************************************************
/// Flip the bit at the position.
//*************************************************************************
ibitset& flip(size_t position)
{
if (position < NBITS)
{
size_t index;
element_t bit;
if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1));
}
pdata[index] ^= bit;
}
return *this;
}
//*************************************************************************
// Are all the bits sets?
//*************************************************************************
bool all() const
{
// All but the last.
for (size_t i = 0; i < (SIZE - 1); ++i)
{
if (pdata[i] != ALL_SET)
{
return false;
}
}
// The last.
if (pdata[SIZE - 1] != (ALL_SET & TOP_MASK))
{
return false;
}
return true;
}
//*************************************************************************
/// Are any of the bits set?
//*************************************************************************
bool any() const
{
return !none();
}
//*************************************************************************
/// Are none of the bits set?
//*************************************************************************
bool none() const
{
for (size_t i = 0; i < SIZE; ++i)
{
if (pdata[i] != 0)
{
return false;
}
}
return true;
}
//*************************************************************************
/// Finds the first bit in the specified state.
///\param state The state to search for.
///\returns The position of the bit or SIZE if none were found.
//*************************************************************************
virtual size_t find_first(bool state) const = 0;
size_t find_first(bool state) const
{
return find_next(state, 0);
}
//*************************************************************************
/// Finds the next bit in the specified state.
@ -99,8 +392,116 @@ namespace etl
///\param position The position to start from.
///\returns The position of the bit or SIZE if none were found.
//*************************************************************************
virtual size_t find_next(bool state, size_t position) const = 0;
size_t find_next(bool state, size_t position) const
{
// Where to start.
size_t index;
size_t bit;
if (SIZE == 1)
{
index = 0;
bit = position;
}
else
{
index = position >> log2<BITS_PER_ELEMENT>::value;
bit = position & (BITS_PER_ELEMENT - 1);
}
element_t mask = 1 << bit;
// For each element in the bitset...
while (index < SIZE)
{
element_t value = pdata[index];
// Needs checking?
if (( state && (value != ALL_CLEAR)) ||
(!state && (value != ALL_SET)))
{
// For each bit in the element...
while ((bit < BITS_PER_ELEMENT) && (position < NBITS))
{
// Equal to the required state?
if (((value & mask) != 0) == state)
{
return position;
}
// Move on to the next bit.
mask <<= 1;
++position;
++bit;
}
}
else
{
position += BITS_PER_ELEMENT;
}
// Start at the beginning for all other elements.
bit = 0;
mask = 1;
++index;
}
return ibitset::npos;
}
//*************************************************************************
/// Read [] operator.
//*************************************************************************
bool operator[] (size_t position) const
{
return test(position);
}
//*************************************************************************
/// Write [] operator.
//*************************************************************************
bit_reference operator [] (size_t position)
{
return bit_reference(*this, position);
}
protected:
//*************************************************************************
/// Gets a reference to the specified bit.
//*************************************************************************
bit_reference get_bit_reference(size_t position)
{
return bit_reference(*this, position);
}
//*************************************************************************
/// Constructor.
//*************************************************************************
ibitset(size_t nbits, size_t size, element_t* pdata)
: NBITS(nbits),
SIZE(size),
pdata(pdata)
{
size_t allocated_bits = SIZE * BITS_PER_ELEMENT;
size_t top_mask_shift = ((BITS_PER_ELEMENT - (allocated_bits - NBITS)) % BITS_PER_ELEMENT);
TOP_MASK = element_t(top_mask_shift == 0 ? ALL_SET : ~(ALL_SET << top_mask_shift));
}
element_t TOP_MASK;
private:
const size_t NBITS;
const size_t SIZE;
element_t* pdata;
};
}
#if WIN32
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif

260
ideque.h
View File

@ -38,10 +38,7 @@ SOFTWARE.
#include "type_traits.h"
#include "deque_base.h"
#include "parameter_type.h"
#ifndef ETL_THROW_EXCEPTIONS
#include "error_handler.h"
#endif
namespace etl
{
@ -496,17 +493,13 @@ namespace etl
{
if (n > MAX_SIZE)
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
initialise();
first.index = 0;
last.index = 0;
_begin.index = 0;
_end.index = 0;
while (n > 0)
{
@ -524,14 +517,10 @@ namespace etl
{
if (index >= current_size)
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_out_of_bounds();
#else
error_handler::error((deque_out_of_bounds()));
#endif
ETL_ERROR(deque_out_of_bounds());
}
iterator result(first);
iterator result(_begin);
result += index;
return *result;
@ -546,14 +535,10 @@ namespace etl
{
if (index >= current_size)
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_out_of_bounds();
#else
error_handler::error((deque_out_of_bounds()));
#endif
ETL_ERROR(deque_out_of_bounds());
}
iterator result(first);
iterator result(_begin);
result += index;
return *result;
@ -565,7 +550,7 @@ namespace etl
//*************************************************************************
reference operator [](size_t index)
{
iterator result(first);
iterator result(_begin);
result += index;
return *result;
@ -577,7 +562,7 @@ namespace etl
//*************************************************************************
const_reference operator [](size_t index) const
{
iterator result(first);
iterator result(_begin);
result += index;
return *result;
@ -589,7 +574,7 @@ namespace etl
//*************************************************************************
reference front()
{
return *first;
return *_begin;
}
//*************************************************************************
@ -598,7 +583,7 @@ namespace etl
//*************************************************************************
const_reference front() const
{
return *first;
return *_begin;
}
//*************************************************************************
@ -607,7 +592,7 @@ namespace etl
//*************************************************************************
reference back()
{
return *last;
return *(_end - 1);
}
//*************************************************************************
@ -616,7 +601,7 @@ namespace etl
//*************************************************************************
const_reference back() const
{
return *last;
return *(_end - 1);
}
//*************************************************************************
@ -624,7 +609,7 @@ namespace etl
//*************************************************************************
iterator begin()
{
return first;
return _begin;
}
//*************************************************************************
@ -632,7 +617,7 @@ namespace etl
//*************************************************************************
const_iterator begin() const
{
return first;
return _begin;
}
//*************************************************************************
@ -640,7 +625,7 @@ namespace etl
//*************************************************************************
const_iterator cbegin() const
{
return first;
return _begin;
}
//*************************************************************************
@ -648,7 +633,7 @@ namespace etl
//*************************************************************************
iterator end()
{
return ++iterator(last);
return iterator(_end);
}
//*************************************************************************
@ -656,7 +641,7 @@ namespace etl
//*************************************************************************
const_iterator end() const
{
return ++iterator(last);
return iterator(_end);
}
//*************************************************************************
@ -664,7 +649,7 @@ namespace etl
//*************************************************************************
const_iterator cend() const
{
return ++const_iterator(last);
return const_iterator(_end);
}
//*************************************************************************
@ -738,34 +723,34 @@ namespace etl
if (insert_position == begin())
{
create_element_front(value);
position = first;
position = _begin;
}
else if (insert_position == end())
{
create_element_back(value);
position = last;
position = _end - 1;
}
else
{
// Are we closer to the front?
if (std::distance(first, position) < std::distance(position, last))
if (std::distance(_begin, position) < std::distance(position, _end - 1))
{
// Construct the first.
create_element_front(*first);
// Construct the _begin.
create_element_front(*_begin);
// Move the values.
std::copy(first + 1, position, first);
std::copy(_begin + 1, position, _begin);
// Write the new value.
*--position = value;
}
else
{
// Construct the last.
create_element_back(*last);
// Construct the _end.
create_element_back(*(_end - 1));
// Move the values.
std::copy_backward(position, last - 1, last);
std::copy_backward(position, _end - 2, _end - 1);
// Write the new value.
*position = value;
@ -774,11 +759,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
return position;
@ -804,7 +785,7 @@ namespace etl
create_element_front(value);
}
position = first;
position = _begin;
}
else if (insert_position == end())
{
@ -813,7 +794,7 @@ namespace etl
create_element_back(value);
}
position = last - (n - 1);
position = _end - n;
}
else
{
@ -821,7 +802,7 @@ namespace etl
position = iterator(insert_position.index, *this, p_buffer);
// Are we closer to the front?
if (distance(first, insert_position) <= difference_type(current_size / 2))
if (distance(_begin, insert_position) <= difference_type(current_size / 2))
{
size_t insert_index = std::distance(begin(), position);
size_t n_insert = n;
@ -832,7 +813,7 @@ namespace etl
size_t n_copy_old = n_move - n_create_copy;
// Remember the original start.
iterator from = first + n_create_copy - 1;
iterator from = _begin + n_create_copy - 1;
iterator to;
// Create new.
@ -849,14 +830,14 @@ namespace etl
// Copy old.
from = position - n_copy_old;
to = first + n_create_copy;
to = _begin + n_create_copy;
etl::copy_n(from, n_copy_old, to);
// Copy new.
to = position - n_create_copy;
std::fill_n(to, n_copy_new, value);
position = first + n_move;
position = _begin + n_move;
}
else
{
@ -892,11 +873,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
return position;
@ -923,7 +900,7 @@ namespace etl
{
create_element_front(n, range_begin);
position = first;
position = _begin;
}
else if (insert_position == end())
{
@ -932,7 +909,7 @@ namespace etl
create_element_back(*range_begin++);
}
position = last - (n - 1);
position = _end - n;
}
else
{
@ -940,7 +917,7 @@ namespace etl
position = iterator(insert_position.index, *this, p_buffer);
// Are we closer to the front?
if (distance(first, insert_position) < difference_type(current_size / 2))
if (distance(_begin, insert_position) < difference_type(current_size / 2))
{
size_t insert_index = std::distance(begin(), position);
size_t n_insert = n;
@ -958,11 +935,11 @@ namespace etl
create_element_front(n_create_new, range_begin);
// Create copy.
create_element_front(n_create_copy, first + n_create_new);
create_element_front(n_create_copy, _begin + n_create_new);
// Copy old.
from = position - n_copy_old;
to = first + n_create_copy;
to = _begin + n_create_copy;
etl::copy_n(from, n_copy_old, to);
// Copy new.
@ -970,7 +947,7 @@ namespace etl
range_begin += n_create_new;
etl::copy_n(range_begin, n_copy_new, to);
position = first + n_move;
position = _begin + n_move;
}
else
{
@ -1008,11 +985,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
return position;
@ -1029,12 +1002,12 @@ namespace etl
if (distance(position) <= difference_type(current_size))
{
if (position == first)
if (position == _begin)
{
destroy_element_front();
position = begin();
}
else if (position == last)
else if (position == _end - 1)
{
destroy_element_back();
position = end();
@ -1042,26 +1015,22 @@ namespace etl
else
{
// Are we closer to the front?
if (distance(first, position) < difference_type(current_size / 2))
if (distance(_begin, position) < difference_type(current_size / 2))
{
std::copy_backward(first, position, position + 1);
std::copy_backward(_begin, position, position + 1);
destroy_element_front();
++position;
}
else
{
std::copy(position + 1, last + 1, position);
std::copy(position + 1, _end, position);
destroy_element_back();
}
}
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_out_of_bounds();
#else
error_handler::error(deque_out_of_bounds());
#endif
ETL_ERROR(deque_out_of_bounds());
}
return position;
@ -1084,7 +1053,7 @@ namespace etl
size_t length = std::distance(range_begin, range_end);
// At the beginning?
if (position == first)
if (position == _begin)
{
for (size_t i = 0; i < length; ++i)
{
@ -1094,7 +1063,7 @@ namespace etl
position = begin();
}
// At the end?
else if (position == last - length + 1)
else if (position == _end - length)
{
for (size_t i = 0; i < length; ++i)
{
@ -1107,10 +1076,10 @@ namespace etl
{
// Copy the smallest number of items.
// Are we closer to the front?
if (distance(first, position) < difference_type(current_size / 2))
if (distance(_begin, position) < difference_type(current_size / 2))
{
// Move the items.
std::copy_backward(first, position, position + length);
std::copy_backward(_begin, position, position + length);
for (size_t i = 0; i < length; ++i)
{
@ -1123,7 +1092,7 @@ namespace etl
// Must be closer to the back.
{
// Move the items.
std::copy(position + length, last + 1, position);
std::copy(position + length, _end, position);
for (size_t i = 0; i < length; ++i)
{
@ -1134,11 +1103,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_out_of_bounds();
#else
error_handler::error(deque_out_of_bounds());
#endif
ETL_ERROR(deque_out_of_bounds());
}
return position;
@ -1157,11 +1122,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
}
@ -1172,7 +1133,7 @@ namespace etl
//*************************************************************************
reference push_back()
{
reference r = *last;
reference r = *_end;
if (!full())
{
@ -1180,14 +1141,10 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
return *last;
return r;
}
//*************************************************************************
@ -1214,11 +1171,7 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
}
@ -1235,14 +1188,10 @@ namespace etl
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_full();
#else
error_handler::error(deque_full());
#endif
ETL_ERROR(deque_full());
}
return *first;
return *_begin;
}
//*************************************************************************
@ -1285,14 +1234,9 @@ namespace etl
}
}
}
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw deque_out_of_bounds();
#else
error_handler::error(deque_out_of_bounds());
#endif
ETL_ERROR(deque_out_of_bounds());
}
}
@ -1340,8 +1284,8 @@ namespace etl
clear();
}
iterator first; ///Iterator to the first item in the deque.
iterator last; ///Iterator to the last item in the deque.
iterator _begin; ///Iterator to the _begin item in the deque.
iterator _end; ///Iterator to the _end item in the deque.
pointer p_buffer; ///The buffer for the deque.
private:
@ -1353,10 +1297,10 @@ namespace etl
{
if (!empty())
{
--first;
--_begin;
}
new(&(*first)) T();
new(&(*_begin)) T();
++current_size;
}
@ -1373,16 +1317,16 @@ namespace etl
if (!empty())
{
--first;
--_begin;
--n;
}
if (n > 0)
{
first -= n;
_begin -= n;
}
iterator item = first;
iterator item = _begin;
do
{
@ -1397,12 +1341,8 @@ namespace etl
//*********************************************************************
void create_element_back()
{
if (!empty())
{
++last;
}
new(&(*last)) T();
new(&(*_end)) T();
++_end;
++current_size;
}
@ -1411,12 +1351,8 @@ namespace etl
//*********************************************************************
void create_element_front(parameter_t value)
{
if (!empty())
{
--first;
}
new(&(*first)) T(value);
--_begin;
new(&(*_begin)) T(value);
++current_size;
}
@ -1425,12 +1361,8 @@ namespace etl
//*********************************************************************
void create_element_back(parameter_t value)
{
if (!empty())
{
++last;
}
new(&(*last)) T(value);
new(&(*_end)) T(value);
++_end;
++current_size;
}
@ -1439,13 +1371,9 @@ namespace etl
//*********************************************************************
void destroy_element_front()
{
(*first).~T();
(*_begin).~T();
--current_size;
if (!empty())
{
++first;
}
++_begin;
}
//*********************************************************************
@ -1453,8 +1381,8 @@ namespace etl
//*********************************************************************
void destroy_element_back()
{
(*last).~T();
--last;
--_end;
(*_end).~T();
--current_size;
}
@ -1468,8 +1396,8 @@ namespace etl
destroy_element_back();
}
first = iterator(0, *this, p_buffer);
last = iterator(0, *this, p_buffer);
_begin = iterator(0, *this, p_buffer);
_end = iterator(0, *this, p_buffer);
}
//*************************************************************************
@ -1485,13 +1413,13 @@ namespace etl
}
//*************************************************************************
/// Measures the distance from the first iterator to the specified iterator.
/// Measures the distance from the _begin iterator to the specified iterator.
//*************************************************************************
template <typename TIterator>
static difference_type distance(const TIterator& other)
{
const difference_type index = other.get_index();
const difference_type reference_index = other.get_deque().first.index;
const difference_type reference_index = other.get_deque()._begin.index;
const size_t buffer_size = other.get_deque().BUFFER_SIZE;
if (index < reference_index)
@ -1508,7 +1436,7 @@ namespace etl
//***************************************************************************
/// Equal operator.
///\param lhs Reference to the first deque.
///\param lhs Reference to the _begin deque.
///\param rhs Reference to the second deque.
///\return <b>true</b> if the arrays are equal, otherwise <b>false</b>
///\ingroup deque
@ -1521,7 +1449,7 @@ bool operator ==(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
//***************************************************************************
/// Not equal operator.
///\param lhs Reference to the first deque.
///\param lhs Reference to the _begin deque.
///\param rhs Reference to the second deque.
///\return <b>true</b> if the arrays are not equal, otherwise <b>false</b>
///\ingroup deque
@ -1534,9 +1462,9 @@ bool operator !=(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
//***************************************************************************
/// Less than operator.
///\param lhs Reference to the first deque.
///\param lhs Reference to the _begin deque.
///\param rhs Reference to the second deque.
///\return <b>true</b> if the first deque is lexigraphically less than the second, otherwise <b>false</b>
///\return <b>true</b> if the _begin deque is lexigraphically less than the second, otherwise <b>false</b>
///\ingroup deque
//***************************************************************************
template <typename T>
@ -1550,9 +1478,9 @@ bool operator <(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
//***************************************************************************
/// Less than or equal operator.
///\param lhs Reference to the first deque.
///\param lhs Reference to the _begin deque.
///\param rhs Reference to the second deque.
///\return <b>true</b> if the first deque is lexigraphically less than or equal to the second, otherwise <b>false</b>
///\return <b>true</b> if the _begin deque is lexigraphically less than or equal to the second, otherwise <b>false</b>
///\ingroup deque
//***************************************************************************
template <typename T>
@ -1563,9 +1491,9 @@ bool operator <=(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
//***************************************************************************
/// Greater than operator.
///\param lhs Reference to the first deque.
///\param lhs Reference to the _begin deque.
///\param rhs Reference to the second deque.
///\return <b>true</b> if the first deque is lexigraphically greater than the second, otherwise <b>false</b>
///\return <b>true</b> if the _begin deque is lexigraphically greater than the second, otherwise <b>false</b>
///\ingroup deque
//***************************************************************************
template <typename T>
@ -1580,9 +1508,9 @@ bool operator >(const etl::ideque<T>& lhs, const etl::ideque<T>& rhs)
//***************************************************************************
/// Greater than or equal operator.
///\param "lhs Reference to the first deque.
///\param "lhs Reference to the _begin deque.
///\param "rhs Reference to the second deque.
///\return <b>true</b> if the first deque is lexigraphically greater than or equal to the second, otherwise <b>false</b>
///\return <b>true</b> if the _begin deque is lexigraphically greater than or equal to the second, otherwise <b>false</b>
///\ingroup deque
//***************************************************************************
template <typename T>

View File

@ -273,8 +273,8 @@ namespace etl
//*********************************************************************
/// Assigns values to the flat_map.
/// If ETL_THROW_EXCEPTIONS is defined, emits flat_map_full if the flat_map does not have enough free space.
/// If ETL_THROW_EXCEPTIONS is defined, emits flat_map_iterator if the iterators are reversed.
/// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_full if the flat_map does not have enough free space.
/// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_iterator if the iterators are reversed.
///\param first The iterator to the first element.
///\param last The iterator to the last element + 1.
//*********************************************************************
@ -286,7 +286,12 @@ namespace etl
if (count < 0)
{
ETL_ERROR(flat_map_iterator());
ETL_ERROR(flat_map_iterator());
}
if (count > difference_type(capacity()))
{
ETL_ERROR(flat_map_full());
}
#endif
@ -314,7 +319,7 @@ namespace etl
// At the end.
if (buffer.full())
{
ETL_ERROR(flat_map_full());
ETL_ERROR(flat_map_full());
}
else
{
@ -339,7 +344,7 @@ namespace etl
// A new one.
if (buffer.full())
{
ETL_ERROR(flat_map_full());
ETL_ERROR(flat_map_full());
}
else
{

View File

@ -68,21 +68,6 @@ namespace etl
typedef typename parameter_type<T, is_fundamental<T>::value || is_pointer<T>::value>::type parameter_t;
//*************************************************************************
/// The node element in the forward_list.
//*************************************************************************
struct Data_Node;
struct Node
{
Node()
: next(nullptr)
{
}
Node* next;
};
//*************************************************************************
/// The data node element in the forward_list.
//*************************************************************************
@ -561,34 +546,6 @@ namespace etl
#endif
}
//*************************************************************************
/// Reverses the forward_list.
//*************************************************************************
void reverse()
{
if (is_trivial_list())
{
return;
}
Node* p_last = &start_node;
Node* p_current = p_last->next;
Node* p_next = p_current->next;
p_current->next = nullptr;
while (p_next != nullptr)
{
p_last = p_current;
p_current = p_next;
p_next = p_current->next;
p_current->next = p_last;
}
join(&start_node, p_current);
}
//*************************************************************************
/// Inserts a value to the forward_list after the specified position.
//*************************************************************************
@ -942,8 +899,6 @@ namespace etl
initialise();
}
Node start_node; ///< The node that acts as the forward_list start.
private:
/// The pool of data nodes used in the list.
@ -981,44 +936,6 @@ namespace etl
return static_cast<const Data_Node&>(node);
}
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(Node* left, Node* right)
{
left->next = static_cast<Data_Node*>(right);
}
//*************************************************************************
/// Join two nodes.
//*************************************************************************
void join(Data_Node* left, Data_Node* right)
{
left->next = right;
}
//*************************************************************************
/// Is the forward_list a trivial length?
//*************************************************************************
bool is_trivial_list() const
{
return (size() < 2);
}
//*************************************************************************
/// Insert a node.
//*************************************************************************
void insert_node_after(Node& position, Node& node)
{
// Connect to the forward_list.
node.next = position.next;
join(&position, &node);
// One more.
++current_size;
}
//*************************************************************************
/// Remove a node.
//*************************************************************************
@ -1040,22 +957,6 @@ namespace etl
}
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
Node& get_head()
{
return *start_node.next;
}
//*************************************************************************
/// Get the head node.
//*************************************************************************
const Node& get_head() const
{
return *start_node.next;
}
//*************************************************************************
/// Initialise the forward_list.
//*************************************************************************

246
imap.h
View File

@ -90,39 +90,6 @@ namespace etl
};
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the map.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
children[0] = nullptr;
children[1] = nullptr;
}
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The data node element in the map.
@ -161,9 +128,6 @@ namespace etl
/// The pool of data nodes used in the map.
ipool<Data_Node>* p_node_pool;
/// The node that acts as the map root.
Node* root_node;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
//*************************************************************************
@ -197,6 +161,7 @@ namespace etl
}
public:
//*************************************************************************
/// iterator.
//*************************************************************************
@ -315,6 +280,7 @@ namespace etl
// Pointer to the current node for this iterator
Node* p_node;
};
friend iterator;
//*************************************************************************
@ -425,6 +391,7 @@ namespace etl
// Pointer to the current node for this iterator
const Node* p_node;
};
friend const_iterator;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
@ -895,7 +862,6 @@ namespace etl
imap(ipool<Data_Node>& node_pool, size_t max_size_)
: map_base(max_size_)
, p_node_pool(&node_pool)
, root_node(nullptr)
{
initialise();
}
@ -932,108 +898,6 @@ namespace etl
root_node = nullptr;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node*& position, Data_Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's children and weight
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
swap->weight = detached->weight;
}
//*************************************************************************
/// Find the value matching the node provided
//*************************************************************************
@ -1145,40 +1009,6 @@ namespace etl
return root_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
const Node* find_limit_node(const Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the parent node that contains the node provided in its left or
/// right tree
@ -1795,76 +1625,6 @@ namespace etl
// Return node found (might be nullptr)
return found;
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
new_root->children[dir];
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
// Attach current root to new roots right tree
new_root->children[1 - dir] = position;
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
};
}

View File

@ -37,7 +37,7 @@ SOFTWARE.
#include <stddef.h>
#include "nullptr.h"
#include "map_base.h"
#include "multimap_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "pool.h"
@ -53,7 +53,7 @@ namespace etl
///\ingroup map
//***************************************************************************
template <typename TKey, typename TMapped, typename TKeyCompare>
class imultimap : public map_base
class imultimap : public multimap_base
{
public:
@ -90,41 +90,6 @@ namespace etl
};
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the multimap.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
parent = nullptr;
children[0] = nullptr;
children[1] = nullptr;
}
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The data node element in the multimap.
@ -149,10 +114,12 @@ namespace etl
{
return key_compare()(node1.value.first, node2.value.first);
}
bool node_comp(const Data_Node& node, const key_value_parameter_t& key) const
{
return key_compare()(node.value.first, key);
}
bool node_comp(const key_value_parameter_t& key, const Data_Node& node) const
{
return key_compare()(key, node.value.first);
@ -163,9 +130,6 @@ namespace etl
/// The pool of data nodes used in the multimap.
ipool<Data_Node>* p_node_pool;
/// The node that acts as the multimap root.
Node* root_node;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
//*************************************************************************
@ -702,9 +666,9 @@ namespace etl
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw map_full();
throw multimap_full();
#else
error_handler::error(map_full());
error_handler::error(multimap_full());
#endif
}
@ -807,9 +771,8 @@ namespace etl
/// Constructor.
//*************************************************************************
imultimap(ipool<Data_Node>& node_pool, size_t max_size_)
: map_base(max_size_)
: multimap_base(max_size_)
, p_node_pool(&node_pool)
, root_node(nullptr)
{
initialise();
}
@ -846,87 +809,6 @@ namespace etl
root_node = nullptr;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node* parent, Node*& position, Data_Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Keep track of this node's parent
node.parent = parent;
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Count the nodes that match the key provided
//*************************************************************************
@ -959,39 +841,6 @@ namespace etl
return result;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's parent, children and weight
swap->parent = detached->parent;
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
if (swap->children[kLeft])
{
swap->children[kLeft]->parent = swap;
}
if (swap->children[kRight])
{
swap->children[kRight]->parent = swap;
}
swap->weight = detached->weight;
}
//*************************************************************************
/// Find the value matching the node provided
//*************************************************************************
@ -1058,23 +907,6 @@ namespace etl
return found;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key is not considered to go before the key provided
//*************************************************************************
@ -1250,7 +1082,7 @@ namespace etl
}
else
{
// Attatch node to current position (which is assumed to be root)
// Attach node to current position (which is assumed to be root)
attach_node(nullptr, position, node);
// Return newly added node at current position
@ -1261,146 +1093,6 @@ namespace etl
return found;
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent; // find_parent_node(root_node, position);
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(const Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(const Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Remove the node specified from somewhere starting at the position
/// provided
@ -1635,104 +1327,6 @@ namespace etl
destroy_data_node(data_node);
} // if(found)
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root (either B or C depending on dir) and its parent
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// Update new root's other child parent pointer
if (position->children[dir])
{
position->children[dir]->parent = position;
}
// New root's parent becomes current position's parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Clear weight factor from current position
position->weight = kNeither;
// Position's parent becomes new_root
position->parent = new_root;
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] = new_root->children[dir];
// Update new roots child parent pointer
if (new_root->children[dir])
{
new_root->children[dir]->parent = position->children[dir];
}
// Attach current left tree to new root and update its parent
new_root->children[dir] = position->children[dir];
position->children[dir]->parent = new_root;
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
if (new_root->children[1 - dir])
{
new_root->children[1 - dir]->parent = position;
}
// Attach current root to new roots right tree and assume its parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Update current position's parent and replace with new root
position->parent = new_root;
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
};
}

View File

@ -37,7 +37,7 @@ SOFTWARE.
#include <stddef.h>
#include "nullptr.h"
#include "set_base.h"
#include "multiset_base.h"
#include "type_traits.h"
#include "parameter_type.h"
#include "pool.h"
@ -53,7 +53,7 @@ namespace etl
///\ingroup set
//***************************************************************************
template <typename T, typename TCompare>
class imultiset : public set_base
class imultiset : public multiset_base
{
public:
@ -88,41 +88,6 @@ namespace etl
};
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the multiset.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
parent = nullptr;
children[0] = nullptr;
children[1] = nullptr;
}
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The data node element in the multiset.
@ -161,9 +126,6 @@ namespace etl
/// The pool of data nodes used in the multiset.
ipool<Data_Node>* p_node_pool;
/// The node that acts as the multiset root.
Node* root_node;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
//*************************************************************************
@ -685,9 +647,9 @@ namespace etl
else
{
#ifdef ETL_THROW_EXCEPTIONS
throw set_full();
throw multiset_full();
#else
error_handler::error(set_full());
error_handler::error(multiset_full());
#endif
}
@ -790,9 +752,8 @@ namespace etl
/// Constructor.
//*************************************************************************
imultiset(ipool<Data_Node>& node_pool, size_t max_size_)
: set_base(max_size_)
: multiset_base(max_size_)
, p_node_pool(&node_pool)
, root_node(nullptr)
{
initialise();
}
@ -829,87 +790,6 @@ namespace etl
root_node = nullptr;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node* parent, Node*& position, Data_Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Keep track of this node's parent
node.parent = parent;
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Count the nodes that match the key provided
//*************************************************************************
@ -942,39 +822,6 @@ namespace etl
return result;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's parent, children and weight
swap->parent = detached->parent;
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
if (swap->children[kLeft])
{
swap->children[kLeft]->parent = swap;
}
if (swap->children[kRight])
{
swap->children[kRight]->parent = swap;
}
swap->weight = detached->weight;
}
//*************************************************************************
/// Find the value matching the node provided
//*************************************************************************
@ -1041,23 +888,6 @@ namespace etl
return found;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key is not considered to go before the key provided
//*************************************************************************
@ -1244,146 +1074,6 @@ namespace etl
return found;
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent; // find_parent_node(root_node, position);
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(const Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(const Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Remove the node specified from somewhere starting at the position
/// provided
@ -1618,104 +1308,6 @@ namespace etl
destroy_data_node(data_node);
} // if(found)
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root (either B or C depending on dir) and its parent
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// Update new root's other child parent pointer
if (position->children[dir])
{
position->children[dir]->parent = position;
}
// New root's parent becomes current position's parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Clear weight factor from current position
position->weight = kNeither;
// Position's parent becomes new_root
position->parent = new_root;
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] = new_root->children[dir];
// Update new roots child parent pointer
if (new_root->children[dir])
{
new_root->children[dir]->parent = position->children[dir];
}
// Attach current left tree to new root and update its parent
new_root->children[dir] = position->children[dir];
position->children[dir]->parent = new_root;
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
if (new_root->children[1 - dir])
{
new_root->children[1 - dir]->parent = position;
}
// Attach current root to new roots right tree and assume its parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Update current position's parent and replace with new root
position->parent = new_root;
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
};
}

View File

@ -41,7 +41,7 @@ SOFTWARE.
#include "nullptr.h"
#include "type_traits.h"
#include "array.h"
#include "intrusive_forward_list_node.h"
namespace etl
{
@ -87,66 +87,6 @@ namespace etl
}
};
namespace __private_intrusive_forward_list__
{
//***************************************************************************
/// The node element in the intrusive_forward_list.
//***************************************************************************
class intrusive_forward_list_node_base
{
public:
virtual intrusive_forward_list_node_base* get_next(size_t index) const
{
return base_next;
}
virtual void set_next(size_t index, intrusive_forward_list_node_base* pnext)
{
base_next = pnext;
}
private:
intrusive_forward_list_node_base* base_next;
};
}
//***************************************************************************
/// The node element in the intrusive_forward_list.
//***************************************************************************
template <const size_t SIZE>
struct intrusive_forward_list_node : public __private_intrusive_forward_list__::intrusive_forward_list_node_base
{
public:
__private_intrusive_forward_list__::intrusive_forward_list_node_base* get_next(size_t index) const
{
#ifdef _DEBUG
if (index >= SIZE)
{
ETL_ERROR(intrusive_forward_list_index_exception());
}
#endif
return next[index];
}
void set_next(size_t index, __private_intrusive_forward_list__::intrusive_forward_list_node_base* pnext)
{
#ifdef _DEBUG
if (index >= SIZE)
{
ETL_ERROR(intrusive_forward_list_index_exception());
}
#endif
next[index] = pnext;
}
private:
etl::array<__private_intrusive_forward_list__::intrusive_forward_list_node_base*, SIZE> next;
};
//***************************************************************************
/// An intrusive forward list.
///\ingroup intrusive_forward_list
@ -518,23 +458,20 @@ namespace etl
{
return;
}
node_t* p_last = &start_node;
node_t* p_current = p_last->get_next(index);
node_t* p_next = p_current->get_next(index);
p_current->set_next(index, nullptr);
node_t* first = nullptr; // To keep first node
node_t* second = start_node.get_next(index); // To keep second node
node_t* track = start_node.get_next(index); // Track the list
while (p_next != nullptr)
while (track != NULL)
{
p_last = p_current;
p_current = p_next;
p_next = p_current->get_next(index);
p_current->set_next(index, p_last);
track = track->get_next(index); // Track point to next node;
second->set_next(index, first); // Second node point to first
first = second; // Move first node to next
second = track; // Move second node to next
}
join(&start_node, p_current);
join(&start_node, first);
}
//*************************************************************************

View File

@ -0,0 +1,99 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2015 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef __ETL_INTRUSIVE_FORWARD_LIST_NODE__
#define __ETL_INTRUSIVE_FORWARD_LIST_NODE__
#include "error_handler.h"
#include "array.h"
namespace etl
{
namespace __private_intrusive_forward_list__
{
//***************************************************************************
/// The node element in the intrusive_forward_list.
//***************************************************************************
class intrusive_forward_list_node_base
{
public:
virtual intrusive_forward_list_node_base* get_next(size_t index) const
{
return base_next;
}
virtual void set_next(size_t index, intrusive_forward_list_node_base* pnext)
{
base_next = pnext;
}
private:
intrusive_forward_list_node_base* base_next;
};
}
//***************************************************************************
/// The node element in the intrusive_forward_list.
//***************************************************************************
template <const size_t SIZE>
struct intrusive_forward_list_node : public __private_intrusive_forward_list__::intrusive_forward_list_node_base
{
public:
__private_intrusive_forward_list__::intrusive_forward_list_node_base* get_next(size_t index) const
{
#ifdef _DEBUG
if (index >= SIZE)
{
ETL_ERROR(intrusive_forward_list_index_exception());
}
#endif
return next[index];
}
void set_next(size_t index, __private_intrusive_forward_list__::intrusive_forward_list_node_base* pnext)
{
#ifdef _DEBUG
if (index >= SIZE)
{
ETL_ERROR(intrusive_forward_list_index_exception());
}
#endif
next[index] = pnext;
}
private:
etl::array<__private_intrusive_forward_list__::intrusive_forward_list_node_base*, SIZE> next;
};
}
#endif

243
iset.h
View File

@ -88,39 +88,6 @@ namespace etl
};
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the set.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
children[0] = nullptr;
children[1] = nullptr;
}
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The data node element in the set.
@ -159,9 +126,6 @@ namespace etl
/// The pool of data nodes used in the set.
ipool<Data_Node>* p_node_pool;
/// The node that acts as the set root.
Node* root_node;
//*************************************************************************
/// Downcast a Node* to a Data_Node*
//*************************************************************************
@ -822,7 +786,6 @@ namespace etl
iset(ipool<Data_Node>& node_pool, size_t max_size_)
: set_base(max_size_)
, p_node_pool(&node_pool)
, root_node(nullptr)
{
initialise();
}
@ -859,108 +822,6 @@ namespace etl
root_node = nullptr;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node*& position, Data_Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's children and weight
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
swap->weight = detached->weight;
}
//*************************************************************************
/// Find the value matching the node provided
//*************************************************************************
@ -1072,40 +933,6 @@ namespace etl
return root_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
const Node* find_limit_node(const Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the parent node that contains the node provided in its left or
/// right tree
@ -1722,76 +1549,6 @@ namespace etl
// Return node found (might be nullptr)
return found;
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
new_root->children[dir];
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
// Attach current root to new roots right tree
new_root->children[1 - dir] = position;
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
};
}

View File

@ -27,8 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#if !defined(__ETL_IN_IMAP_H__) && !defined(__ETL_IN_IMULTIMAP_H__)
#error This header is a private element of etl::map, etl::multimap & etl::imap, etl::imultimap
#if !defined(__ETL_IN_IMAP_H__)
#error This header is a private element of etl::map & etl::imap
#endif
#ifndef __ETL_MAP_BASE__
@ -157,18 +157,260 @@ namespace etl
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the map.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
children[0] = nullptr;
children[1] = nullptr;
}
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
map_base(size_type max_size)
: current_size(0)
, MAX_SIZE(max_size)
, root_node(nullptr)
{
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
new_root->children[dir];
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
// Attach current root to new roots right tree
new_root->children[1 - dir] = position;
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
const Node* find_limit_node(const Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
const Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node*& position, Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's children and weight
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
swap->weight = detached->weight;
}
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the map.
Node* root_node; ///< The node that acts as the map root.
};
}

581
multimap_base.h Normal file
View File

@ -0,0 +1,581 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2014 jwellbelove, rlindeman
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.
******************************************************************************/
#if !defined(__ETL_IN_IMULTIMAP_H__)
#error This header is a private element of etl::multimap & etl::imultimap
#endif
#ifndef __ETL_MULTIMAP_BASE__
#define __ETL_MULTIMAP_BASE__
#include <stddef.h>
#include "exception.h"
namespace etl
{
//***************************************************************************
/// Exception for the map.
///\ingroup map
//***************************************************************************
class multimap_exception : public exception
{
public:
multimap_exception(const char* what)
: exception(what)
{
}
};
//***************************************************************************
/// Full exception for the map.
///\ingroup map
//***************************************************************************
class multimap_full : public multimap_exception
{
public:
multimap_full()
: multimap_exception("multimap: full")
{
}
};
//***************************************************************************
/// Map out of bounds exception.
///\ingroup map
//***************************************************************************
class multimap_out_of_bounds : public multimap_exception
{
public:
multimap_out_of_bounds()
: multimap_exception("multimap: out of bounds")
{
}
};
//***************************************************************************
/// Iterator exception for the map.
///\ingroup map
//***************************************************************************
class multimap_iterator : public multimap_exception
{
public:
multimap_iterator()
: multimap_exception("multimap: iterator problem")
{
}
};
//***************************************************************************
/// The base class for all maps.
///\ingroup map
//***************************************************************************
class multimap_base
{
public:
typedef size_t size_type; ///< The type used for determining the size of map.
//*************************************************************************
/// Gets the size of the map.
//*************************************************************************
size_type size() const
{
return current_size;
}
//*************************************************************************
/// Gets the maximum possible size of the map.
//*************************************************************************
size_type max_size() const
{
return MAX_SIZE;
}
//*************************************************************************
/// Checks to see if the map is empty.
//*************************************************************************
bool empty() const
{
return current_size == 0;
}
//*************************************************************************
/// Checks to see if the map is full.
//*************************************************************************
bool full() const
{
return current_size == MAX_SIZE;
}
//*************************************************************************
/// Returns the capacity of the vector.
///\return The capacity of the vector.
//*************************************************************************
size_type capacity() const
{
return MAX_SIZE;
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return max_size() - size();
}
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the multimap.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
parent = nullptr;
children[0] = nullptr;
children[1] = nullptr;
}
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
multimap_base(size_type max_size)
: current_size(0)
, MAX_SIZE(max_size)
, root_node(nullptr)
{
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root (either B or C depending on dir) and its parent
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// Update new root's other child parent pointer
if (position->children[dir])
{
position->children[dir]->parent = position;
}
// New root's parent becomes current position's parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Clear weight factor from current position
position->weight = kNeither;
// Position's parent becomes new_root
position->parent = new_root;
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] = new_root->children[dir];
// Update new roots child parent pointer
if (new_root->children[dir])
{
new_root->children[dir]->parent = position->children[dir];
}
// Attach current left tree to new root and update its parent
new_root->children[dir] = position->children[dir];
position->children[dir]->parent = new_root;
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
if (new_root->children[1 - dir])
{
new_root->children[1 - dir]->parent = position;
}
// Attach current root to new roots right tree and assume its parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Update current position's parent and replace with new root
position->parent = new_root;
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent; // find_parent_node(root_node, position);
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(const Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(const Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node* parent, Node*& position, Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Keep track of this node's parent
node.parent = parent;
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's parent, children and weight
swap->parent = detached->parent;
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
if (swap->children[kLeft])
{
swap->children[kLeft]->parent = swap;
}
if (swap->children[kRight])
{
swap->children[kRight]->parent = swap;
}
swap->weight = detached->weight;
}
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the map.
Node* root_node; ///< The node that acts as the multimap root.
};
}
#endif

580
multiset_base.h Normal file
View File

@ -0,0 +1,580 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2015 jwellbelove, rlindeman
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.
******************************************************************************/
#if !defined(__ETL_IN_IMULTISET_H__)
#error This header is a private element of etl::multiset & etl::imultiset
#endif
#ifndef __ETL_MULTISET_BASE__
#define __ETL_MULTISET_BASE__
#include <stddef.h>
#include "exception.h"
namespace etl
{
//***************************************************************************
/// Exception for the set.
///\ingroup set
//***************************************************************************
class multiset_exception : public exception
{
public:
multiset_exception(const char* what)
: exception(what)
{
}
};
//***************************************************************************
/// Full exception for the set.
///\ingroup set
//***************************************************************************
class multiset_full : public multiset_exception
{
public:
multiset_full()
: multiset_exception("multiset: full")
{
}
};
//***************************************************************************
/// Map out of bounds exception.
///\ingroup set
//***************************************************************************
class multiset_out_of_bounds : public multiset_exception
{
public:
multiset_out_of_bounds()
: multiset_exception("multiset: out of bounds")
{
}
};
//***************************************************************************
/// Iterator exception for the set.
///\ingroup set
//***************************************************************************
class multiset_iterator : public multiset_exception
{
public:
multiset_iterator()
: multiset_exception("multiset: iterator problem")
{
}
};
//***************************************************************************
/// The base class for all sets.
///\ingroup set
//***************************************************************************
class multiset_base
{
public:
typedef size_t size_type; ///< The type used for determining the size of set.
//*************************************************************************
/// Gets the size of the set.
//*************************************************************************
size_type size() const
{
return current_size;
}
//*************************************************************************
/// Gets the maximum possible size of the set.
//*************************************************************************
size_type max_size() const
{
return MAX_SIZE;
}
//*************************************************************************
/// Checks to see if the set is empty.
//*************************************************************************
bool empty() const
{
return current_size == 0;
}
//*************************************************************************
/// Checks to see if the set is full.
//*************************************************************************
bool full() const
{
return current_size == MAX_SIZE;
}
//*************************************************************************
/// Returns the capacity of the vector.
///\return The capacity of the vector.
//*************************************************************************
size_type capacity() const
{
return MAX_SIZE;
}
//*************************************************************************
/// Returns the remaining capacity.
///\return The remaining capacity.
//*************************************************************************
size_t available() const
{
return max_size() - size();
}
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the multiset.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
parent = nullptr;
children[0] = nullptr;
children[1] = nullptr;
}
Node* parent;
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
multiset_base(size_type max_size)
: current_size(0)
, MAX_SIZE(max_size)
, root_node(nullptr)
{
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node* parent, Node*& position, Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Keep track of this node's parent
node.parent = parent;
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's parent, children and weight
swap->parent = detached->parent;
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
if (swap->children[kLeft])
{
swap->children[kLeft]->parent = swap;
}
if (swap->children[kRight])
{
swap->children[kRight]->parent = swap;
}
swap->weight = detached->weight;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent; // find_parent_node(root_node, position);
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the next node in sequence from the node provided
//*************************************************************************
void next_node(const Node*& position) const
{
if (position)
{
// Is there a tree on the right? then find the minimum of that tree
if (position->children[kRight])
{
// Return minimum node found
position = find_limit_node(position->children[kRight], kLeft);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on right side of parent tree
} while (parent && parent->children[kRight] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Find the previous node in sequence from the node provided
//*************************************************************************
void prev_node(const Node*& position) const
{
// If starting at the terminal end, the previous node is the maximum node
// from the root
if (!position)
{
position = find_limit_node(root_node, kRight);
}
else
{
// Is there a tree on the left? then find the maximum of that tree
if (position->children[kLeft])
{
// Return maximum node found
position = find_limit_node(position->children[kLeft], kRight);
}
// Otherwise find the parent of this node
else
{
// Start with current position as parent
const Node* parent = position;
do {
// Update current position as previous parent
position = parent;
// Find parent of current position
parent = position->parent;
// Repeat while previous position was on left side of parent tree
} while (parent && parent->children[kLeft] == position);
// Set parent node as the next position
position = parent;
}
}
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root (either B or C depending on dir) and its parent
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// Update new root's other child parent pointer
if (position->children[dir])
{
position->children[dir]->parent = position;
}
// New root's parent becomes current position's parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Clear weight factor from current position
position->weight = kNeither;
// Position's parent becomes new_root
position->parent = new_root;
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] = new_root->children[dir];
// Update new roots child parent pointer
if (new_root->children[dir])
{
new_root->children[dir]->parent = position->children[dir];
}
// Attach current left tree to new root and update its parent
new_root->children[dir] = position->children[dir];
position->children[dir]->parent = new_root;
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
if (new_root->children[1 - dir])
{
new_root->children[1 - dir]->parent = position;
}
// Attach current root to new roots right tree and assume its parent
new_root->parent = position->parent;
new_root->children[1 - dir] = position;
new_root->dir = 1 - dir;
// Update current position's parent and replace with new root
position->parent = new_root;
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the set.
Node* root_node; ///< The node that acts as the multiset root.
};
}
#endif

View File

@ -6,7 +6,7 @@ The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2014 jwellbelove, rlindeman
Copyright(c) 2015 jwellbelove, rlindeman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
@ -27,8 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#if !defined(__ETL_IN_ISET_H__) && !defined(__ETL_IN_IMULTISET_H__)
#error This header is a private element of etl::set, etl::multiset & etl::iset, etl::imultiset
#if !defined(__ETL_IN_ISET_H__)
#error This header is a private element of etl::set & etl::iset
#endif
#ifndef __ETL_SET_BASE__
@ -157,18 +157,261 @@ namespace etl
protected:
static const uint8_t kLeft = 0;
static const uint8_t kRight = 1;
static const uint8_t kNeither = 2;
//*************************************************************************
/// The node element in the set.
//*************************************************************************
struct Node
{
//***********************************************************************
/// Constructor
//***********************************************************************
Node() :
weight(kNeither),
dir(kNeither)
{
}
//***********************************************************************
/// Marks the node as a leaf.
//***********************************************************************
void mark_as_leaf()
{
weight = kNeither;
dir = kNeither;
children[0] = nullptr;
children[1] = nullptr;
}
Node* children[2];
uint8_t weight;
uint8_t dir;
};
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
set_base(size_type max_size)
: current_size(0)
, MAX_SIZE(max_size)
, root_node(nullptr)
{
}
//*************************************************************************
/// Attach the provided node to the position provided
//*************************************************************************
void attach_node(Node*& position, Node& node)
{
// Mark new node as leaf on attach to tree at position provided
node.mark_as_leaf();
// Add the node here
position = &node;
// One more.
++current_size;
}
//*************************************************************************
/// Detach the node at the position provided
//*************************************************************************
void detach_node(Node*& position, Node*& replacement)
{
// Make temporary copy of actual nodes involved because we might lose
// their references in the process (e.g. position is the same as
// replacement or replacement is a child of position)
Node* detached = position;
Node* swap = replacement;
// Update current position to point to swap (replacement) node first
position = swap;
// Update replacement node to point to child in opposite direction
// otherwise we might lose the other child of the swap node
replacement = swap->children[1 - swap->dir];
// Point swap node to detached node's children and weight
swap->children[kLeft] = detached->children[kLeft];
swap->children[kRight] = detached->children[kRight];
swap->weight = detached->weight;
}
//*************************************************************************
/// Balance the critical node at the position provided as needed
//*************************************************************************
void balance_node(Node*& critical_node)
{
// Step 1: Update weights for all children of the critical node up to the
// newly inserted node. This step is costly (in terms of traversing nodes
// multiple times during insertion) but doesn't require as much recursion
Node* weight_node = critical_node->children[critical_node->dir];
while (weight_node)
{
// Keep going until we reach a terminal node (dir == kNeither)
if (kNeither != weight_node->dir)
{
// Does this insert balance the previous weight factor value?
if (weight_node->weight == 1 - weight_node->dir)
{
weight_node->weight = kNeither;
}
else
{
weight_node->weight = weight_node->dir;
}
// Update weight factor node to point to next node
weight_node = weight_node->children[weight_node->dir];
}
else
{
// Stop loop, terminal node found
break;
}
} // while(weight_node)
// Step 2: Update weight for critical_node or rotate tree to balance node
if (kNeither == critical_node->weight)
{
critical_node->weight = critical_node->dir;
}
// If direction is different than weight, then it will now be balanced
else if (critical_node->dir != critical_node->weight)
{
critical_node->weight = kNeither;
}
// Rotate is required to balance the tree at the critical node
else
{
// If critical node matches child node direction then perform a two
// node rotate in the direction of the critical node
if (critical_node->weight == critical_node->children[critical_node->dir]->dir)
{
rotate_2node(critical_node, critical_node->dir);
}
// Otherwise perform a three node rotation in the direction of the
// critical node
else
{
rotate_3node(critical_node, critical_node->dir,
critical_node->children[critical_node->dir]->children[1 - critical_node->dir]->dir);
}
}
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
Node* find_limit_node(Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Find the node whose key would go before all the other keys from the
/// position provided
//*************************************************************************
const Node* find_limit_node(const Node* position, const int8_t dir) const
{
// Something at this position and in the direction specified? keep going
const Node* limit_node = position;
while (limit_node && limit_node->children[dir])
{
limit_node = limit_node->children[dir];
}
// Return the limit node position found
return limit_node;
}
//*************************************************************************
/// Rotate two nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_2node(Node*& position, uint8_t dir)
{
// A C A B
// B C -> A E OR B C -> D A
// D E B D D E E C
// C (new position) becomes the root
// A (position) takes ownership of D as its children[kRight] child
// C (new position) takes ownership of A as its left child
// OR
// B (new position) becomes the root
// A (position) takes ownership of E as its left child
// B (new position) takes ownership of A as its right child
// Capture new root
Node* new_root = position->children[dir];
// Replace position's previous child with new root's other child
position->children[dir] = new_root->children[1 - dir];
// New root now becomes parent of current position
new_root->children[1 - dir] = position;
// Clear weight factor from current position
position->weight = kNeither;
// Newly detached right now becomes current position
position = new_root;
// Clear weight factor from new root
position->weight = kNeither;
}
//*************************************************************************
/// Rotate three nodes at the position provided the to balance the tree
//*************************************************************************
void rotate_3node(Node*& position, uint8_t dir, uint8_t third)
{
// __A__ __E__ __A__ __D__
// _B_ C -> B A OR B _C_ -> A C
// D E D F G C D E B F G E
// F G F G
// E (new position) becomes the root
// B (position) takes ownership of F as its left child
// A takes ownership of G as its right child
// OR
// D (new position) becomes the root
// A (position) takes ownership of F as its right child
// C takes ownership of G as its left child
// Capture new root (either E or D depending on dir)
Node* new_root = position->children[dir]->children[1 - dir];
// Set weight factor for B or C based on F or G existing and being a different than dir
position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither;
// Detach new root from its tree (replace with new roots child)
position->children[dir]->children[1 - dir] =
new_root->children[dir];
// Attach current left tree to new root
new_root->children[dir] = position->children[dir];
// Set weight factor for A based on F or G
position->weight = third != kNeither && third == dir ? 1 - dir : kNeither;
// Move new root's right tree to current roots left tree
position->children[dir] = new_root->children[1 - dir];
// Attach current root to new roots right tree
new_root->children[1 - dir] = position;
// Replace current position with new root
position = new_root;
// Clear weight factor for new current position
position->weight = kNeither;
}
size_type current_size; ///< The number of the used nodes.
const size_type MAX_SIZE; ///< The maximum size of the set.
Node* root_node; ///< The node that acts as the set root.
};
}

View File

@ -0,0 +1,582 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
Copyright(c) 2015 jwellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include <UnitTest++/UnitTest++.h>
#include "ExtraCheckMacros.h"
#include "data.h"
#include "../basic_intrusive_forward_list.h"
#include <algorithm>
#include <array>
#include <forward_list>
#include <vector>
#include <list>
#include <string>
typedef TestDataDC<std::string> ItemDC;
typedef TestDataNDC<std::string> ItemNDC;
namespace
{
class ItemDCNode : public etl::basic_intrusive_forward_list_node
{
public:
ItemDCNode(const std::string& text)
: data(text)
{
}
ItemDC data;
};
class ItemNDCNode : public etl::basic_intrusive_forward_list_node
{
public:
ItemNDCNode(const std::string& text)
: data(text)
{
}
bool operator <(const ItemNDCNode& other) const
{
return data < other.data;
}
ItemNDC data;
};
bool operator ==(const ItemDCNode& lhs, const ItemDCNode& rhs)
{
return lhs.data == rhs.data;
}
bool operator ==(const ItemNDCNode& lhs, const ItemNDCNode& rhs)
{
return lhs.data == rhs.data;
}
std::ostream& operator << (std::ostream& os, const ItemNDCNode& node)
{
os << node.data;
return os;
}
struct CompareItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
{
return lhs.data < rhs.data;
}
};
struct EqualItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
{
return lhs.data == rhs.data;
}
};
}
namespace
{
SUITE(test_forward_list)
{
typedef etl::basic_intrusive_forward_list DataDC;
typedef etl::basic_intrusive_forward_list DataNDC;
typedef std::vector<ItemNDCNode> InitialDataNDC;
InitialDataNDC unsorted_data;
InitialDataNDC sorted_data;
InitialDataNDC non_unique_data;
InitialDataNDC unique_data;
InitialDataNDC small_data;
bool are_equal;
//*************************************************************************
struct SetupFixture
{
SetupFixture()
{
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") };
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") };
}
};
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_default_constructor)
{
DataNDC data;
DataNDC data1;
CHECK(data.empty());
CHECK(data1.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_constructor_range)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
CHECK(!data.empty());
}
////*************************************************************************
TEST_FIXTURE(SetupFixture, test_iterator)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
InitialDataNDC::iterator isorted = sorted_data.begin();
DataNDC::iterator idata = data.begin();
while (isorted != sorted_data.end())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *isorted;
CHECK(are_equal);
++idata;
++isorted;
}
}
////*************************************************************************
TEST_FIXTURE(SetupFixture, test_const_iterator)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
InitialDataNDC::const_iterator isorted = sorted_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (isorted != sorted_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *isorted;
CHECK(are_equal);
++idata;
++isorted;
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_clear)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
data.clear();
CHECK(data.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assign_range)
{
DataNDC data;
// Do it twice. We should only get one copy.
data.assign(sorted_data.begin(), sorted_data.end());
data.assign(sorted_data.begin(), sorted_data.end());
InitialDataNDC::const_iterator isorted = sorted_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (isorted != sorted_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *isorted;
CHECK(are_equal);
++idata;
++isorted;
}
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_after_position_value)
{
ItemNDCNode INSERT_VALUE1 = ItemNDCNode("1");
ItemNDCNode INSERT_VALUE2 = ItemNDCNode("2");
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
DataNDC data(sorted_data.begin(), sorted_data.end());
size_t offset = 2;
DataNDC::iterator i_data = data.begin();
std::advance(i_data, offset);
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
std::advance(i_compare_data, offset + 1);
data.insert_after(i_data, INSERT_VALUE1);
compare_data.insert(i_compare_data, INSERT_VALUE1);
InitialDataNDC::const_iterator icompare = compare_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_insert_after_range)
{
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());
size_t final_size = test1.size() + test2.size();
DataNDC data(test1.begin(), test1.end());
data.insert_after(data.before_begin(), test2.begin(), test2.end());
InitialDataNDC::const_iterator icompare = compare.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(final_size, std::distance(data.begin(), data.end()));
compare.assign(test1.begin(), test1.end());
data.assign(test1.begin(), test1.end());
std::vector<ItemNDCNode>::iterator icd = compare.begin();
DataNDC::iterator id = data.begin();
std::advance(icd, 4);
std::advance(id, 3);
compare.insert(icd, test2.begin(), test2.end());
data.insert_after(id, test2.begin(), test2.end());
icompare = compare.cbegin();
idata = data.cbegin();
while (icompare != compare.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(final_size, std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_push_front)
{
std::list<ItemNDCNode> compare_data;
DataNDC data;
ItemNDCNode node1("1");
ItemNDCNode node2("2");
ItemNDCNode node3("3");
ItemNDCNode node4("4");
ItemNDCNode node5("5");
ItemNDCNode node6("6");
compare_data.push_front(node1);
compare_data.push_front(node2);
compare_data.push_front(node3);
compare_data.push_front(node4);
compare_data.push_front(node5);
compare_data.push_front(node6);
data.push_front(node1);
data.push_front(node2);
data.push_front(node3);
data.push_front(node4);
data.push_front(node5);
data.push_front(node6);
std::list<ItemNDCNode>::const_iterator icompare = compare_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(6, std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_push_front_pop_front)
{
DataNDC data;
ItemNDCNode node1("1");
ItemNDCNode node2("2");
ItemNDCNode node3("3");
ItemNDCNode node4("4");
ItemNDCNode node5("5");
ItemNDCNode node6("6");
data.push_front(node1);
data.push_front(node2);
data.push_front(node3);
data.push_front(node4);
data.push_front(node5);
data.push_front(node6);
CHECK_EQUAL(6, std::distance(data.begin(), data.end()));
CHECK(!data.empty());
data.pop_front();
data.pop_front();
data.pop_front();
data.pop_front();
data.pop_front();
CHECK_EQUAL(1, std::distance(data.begin(), data.end()));
CHECK(!data.empty());
data.pop_front();
CHECK_EQUAL(0, std::distance(data.begin(), data.end()));
CHECK(data.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_after_single)
{
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
DataNDC data(sorted_data.begin(), sorted_data.end());
DataNDC::iterator i_data = data.begin();
std::advance(i_data, 2);
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
std::advance(i_compare_data, 3);
i_compare_data = compare_data.erase(i_compare_data);
i_data = data.erase_after(i_data);
std::vector<ItemNDCNode>::const_iterator icompare = compare_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK(*i_compare_data == i_data.ref_cast<ItemNDCNode>());
i_compare_data = compare_data.erase(compare_data.begin() + 1);
i_data = data.erase_after(data.begin());
icompare = compare_data.cbegin();
idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
// Move to the last value and erase.
i_compare_data = compare_data.begin() + 1;
i_compare_data = compare_data.erase(i_compare_data);
i_data = data.begin();
i_data = data.erase_after(i_data);
icompare = compare_data.cbegin();
idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_after_range)
{
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
DataNDC data(sorted_data.begin(), sorted_data.end());
DataNDC::iterator i_data_1 = data.begin();
std::advance(i_data_1, 2);
DataNDC::iterator i_data_2 = data.begin();
std::advance(i_data_2, 4);
std::vector<ItemNDCNode>::iterator i_compare_data_1 = compare_data.begin();
std::advance(i_compare_data_1, 3);
std::vector<ItemNDCNode>::iterator i_compare_data_2 = compare_data.begin();
std::advance(i_compare_data_2, 4);
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data_1, i_compare_data_2);
DataNDC::iterator i_result = data.erase_after(i_data_1, i_data_2);
CHECK_EQUAL(*i_compare_result, i_result.ref_cast<ItemNDCNode>());
std::vector<ItemNDCNode>::const_iterator icompare = compare_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_after_range_end)
{
std::vector<ItemNDCNode> compare_data(sorted_data.begin(), sorted_data.end());
DataNDC data(sorted_data.begin(), sorted_data.end());
DataNDC::iterator i_data = data.begin();
std::advance(i_data, 4);
std::vector<ItemNDCNode>::iterator i_compare_data = compare_data.begin();
std::advance(i_compare_data, 5);
std::vector<ItemNDCNode>::iterator i_compare_result = compare_data.erase(i_compare_data, compare_data.end());
DataNDC::iterator i_result = data.erase_after(i_data, data.end());
CHECK(i_result == data.end());
std::vector<ItemNDCNode>::const_iterator icompare = compare_data.cbegin();
DataNDC::const_iterator idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
icompare = compare_data.cbegin();
idata = data.cbegin();
while (icompare != compare_data.cend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *icompare;
CHECK(are_equal);
++idata;
++icompare;
}
CHECK_EQUAL(compare_data.size(), std::distance(data.begin(), data.end()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_erase_after_all)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
data.erase_after(data.before_begin(), data.end());
CHECK(data.empty());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_front)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
CHECK_EQUAL(sorted_data.front(), data.front<ItemNDCNode>());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_reverse)
{
DataNDC data(sorted_data.begin(), sorted_data.end());
data.reverse();
InitialDataNDC::const_reverse_iterator isorted = sorted_data.crbegin();
DataNDC::const_iterator idata = data.cbegin();
while (isorted != sorted_data.crend())
{
const ItemNDCNode& item = idata.ref_cast<ItemNDCNode>();
are_equal = item == *isorted;
CHECK(are_equal);
++idata;
++isorted;
}
}
};
}

View File

@ -141,6 +141,29 @@ namespace
}
}
//*************************************************************************
TEST(test_base_set)
{
std::bitset<60> compare;
etl::bitset<60> data;
etl::ibitset& idata = data;
compare.set();
idata.set();
CHECK_EQUAL(compare.size(), idata.size());
CHECK_EQUAL(compare.count(), idata.count());
CHECK_EQUAL(compare.none(), idata.none());
CHECK_EQUAL(compare.any(), idata.any());
CHECK_EQUAL(compare.all(), idata.all());
for (size_t i = 0; i < data.size(); ++i)
{
CHECK_EQUAL(compare.test(i), idata.test(i));
}
}
//*************************************************************************
TEST(test_string_set)
{
@ -192,20 +215,44 @@ namespace
etl::bitset<60> data(0xFFFFFFFFFFFFFFF);
compare.reset();
data.reset();
etl::bitset<60>& rdata = data.reset();
CHECK_EQUAL(compare.size(), data.size());
CHECK_EQUAL(compare.count(), data.count());
CHECK_EQUAL(compare.none(), data.none());
CHECK_EQUAL(compare.any(), data.any());
CHECK_EQUAL(compare.all(), data.all());
CHECK_EQUAL(compare.size(), rdata.size());
CHECK_EQUAL(compare.count(), rdata.count());
CHECK_EQUAL(compare.none(), rdata.none());
CHECK_EQUAL(compare.any(), rdata.any());
CHECK_EQUAL(compare.all(), rdata.all());
for (size_t i = 0; i < data.size(); ++i)
for (size_t i = 0; i < rdata.size(); ++i)
{
CHECK_EQUAL(compare.test(i), data.test(i));
CHECK_EQUAL(compare.test(i), rdata.test(i));
}
}
//*************************************************************************
TEST(test_base_reset)
{
std::bitset<60> compare(0xFFFFFFFFFFFFFFF);
etl::bitset<60> data(0xFFFFFFFFFFFFFFF);
etl::ibitset& idata = data;
etl::ibitset& ridata = idata.reset();
compare.reset();
CHECK_EQUAL(compare.size(), ridata.size());
CHECK_EQUAL(compare.count(), ridata.count());
CHECK_EQUAL(compare.none(), ridata.none());
CHECK_EQUAL(compare.any(), ridata.any());
CHECK_EQUAL(compare.all(), ridata.all());
for (size_t i = 0; i < ridata.size(); ++i)
{
CHECK_EQUAL(compare.test(i), ridata.test(i));
}
}
//*************************************************************************
TEST(test_position_reset)
{
@ -328,6 +375,23 @@ namespace
}
}
//*************************************************************************
TEST(test_base_flip)
{
std::bitset<60> compare;
etl::bitset<60> data;
etl::ibitset& idata = data;
compare.flip();
idata.flip();
for (size_t i = 0; i < idata.size(); ++i)
{
CHECK_EQUAL(compare.test(i), idata.test(i));
}
}
//*************************************************************************
TEST(test_flip_position)
{
@ -561,6 +625,37 @@ namespace
CHECK(data2 == data3);
}
//*************************************************************************
TEST(test_index_operator)
{
etl::bitset<60> data1(0x123456781234567);
etl::bitset<60> data2;
for (size_t i = 0; i < data1.size(); ++i)
{
data2[i] = data1[i];
}
CHECK(data1 == data2);
}
//*************************************************************************
TEST(test_base_index_operator)
{
etl::bitset<60> data1(0x123456781234567);
etl::bitset<60> data2;
etl::ibitset& idata1 = data1;
etl::ibitset& idata2 = data2;
for (size_t i = 0; i < idata1.size(); ++i)
{
idata2[i] = idata1[i];
}
CHECK(data1 == data2);
}
//*************************************************************************
TEST(test_big_bitset)
{
@ -679,66 +774,5 @@ namespace
CHECK(data1 == compare2);
CHECK(data2 == compare1);
}
//*************************************************************************
TEST(test_iterator)
{
typedef etl::bitset<16> Bitset;
Bitset data("1111000011001010");
Bitset data2(data);
int i;
// Read
Bitset::iterator b1 = data.begin();
Bitset::iterator e1 = data.end();
CHECK_EQUAL(16, std::distance(b1, e1));
i = 0;
while (b1 != e1)
{
CHECK_EQUAL(data[i], *b1);
++b1;
++i;
}
Bitset::iterator b2 = data2.begin();
Bitset::iterator e2 = data2.end();
CHECK_EQUAL(16, std::distance(b2, e2));
// Write
i = 0;
while (b2 != e2)
{
*b2 = !*b2;
CHECK_EQUAL(!data[i], *b2);
++b2;
++i;
}
}
//*************************************************************************
TEST(test_const_iterator)
{
typedef etl::bitset<16> Bitset;
Bitset data("1111000011001010");
// const_iterator
Bitset::const_iterator b1 = data.cbegin();
Bitset::const_iterator e1 = data.cend();
CHECK_EQUAL(16, std::distance(b1, e1));
int i = 0;
while (b1 != e1)
{
CHECK_EQUAL(data[i], *b1);
++b1;
++i;
}
}
};
}

View File

@ -142,18 +142,18 @@ void test_array()
//*****************************************************************************
void test_bitset()
{
etl::bitset<7> b7; // uint8_t
etl::bitset<8> b8; // uint8_t
etl::bitset<9> b9; // uint16_t
etl::bitset<15> b15; // uint16_t
etl::bitset<16> b16; // uint16_t
etl::bitset<17> b17; // uint32_t
etl::bitset<31> b31; // uint32_t
etl::bitset<32> b32; // uint32_t
etl::bitset<33> b33; // uint64_t
etl::bitset<63> b63; // uint64_t
etl::bitset<64> b64; // uint64_t
etl::bitset<65> b65; // 2 * uint64_t
etl::bitset<7> b7;
etl::bitset<8> b8;
etl::bitset<9> b9;
etl::bitset<15> b15;
etl::bitset<16> b16;
etl::bitset<17> b17;
etl::bitset<31> b31;
etl::bitset<32> b32;
etl::bitset<33> b33;
etl::bitset<63> b63;
etl::bitset<64> b64;
etl::bitset<65> b65;
b65.set();
b65.set(4, true);
@ -165,20 +165,16 @@ void test_bitset()
b65.flip();
b65.flip(5);
etl::bitset<7>::iterator b1 = b7.begin();
etl::bitset<7>::iterator e1 = b7.end();
etl::bitset<7>::const_iterator b2 = b7.cbegin();
etl::bitset<7>::const_iterator e2 = b7.cend();
etl::ibitset& ib = b65;
++b1;
--e1;
b2 += 2;
e2 -= 2;
*b1 = true;
const etl::bitset<7>::iterator b3 = b7.begin();
bool t = *b3;
ib.set();
ib.set(4, true);
ib.reset();
ib.reset(37);
b = ib[4];
b = ib[64];
ib.flip();
ib.flip(5);
}
//*****************************************************************************

View File

@ -1460,5 +1460,16 @@ namespace
CHECK(deque1 != deque2);
}
//*************************************************************************
TEST(test_iterator_comparison_empty)
{
DataNDC data;
CHECK(data.begin() == data.end());
CHECK(data.cbegin() == data.cend());
CHECK(data.rbegin() == data.rend());
CHECK(data.crbegin() == data.crend());
}
};
}

View File

@ -41,69 +41,71 @@ SOFTWARE.
typedef TestDataDC<std::string> ItemDC;
typedef TestDataNDC<std::string> ItemNDC;
class ItemDCNode : public etl::intrusive_forward_list_node<2>
namespace
{
public:
ItemDCNode(const std::string& text)
: data(text)
class ItemDCNode : public etl::intrusive_forward_list_node<2>
{
}
public:
ItemDC data;
};
ItemDCNode(const std::string& text)
: data(text)
{
}
const size_t INDEXES = 2;
ItemDC data;
};
class ItemNDCNode : public etl::intrusive_forward_list_node<INDEXES>
{
public:
const size_t INDEXES = 2;
ItemNDCNode(const std::string& text)
: data(text)
class ItemNDCNode : public etl::intrusive_forward_list_node<INDEXES>
{
}
public:
bool operator <(const ItemNDCNode& other) const
{
return data < other.data;
}
ItemNDCNode(const std::string& text)
: data(text)
{
}
ItemNDC data;
};
bool operator <(const ItemNDCNode& other) const
{
return data < other.data;
}
bool operator ==(const ItemDCNode& lhs, const ItemDCNode& rhs)
{
return lhs.data == rhs.data;
}
ItemNDC data;
};
bool operator ==(const ItemNDCNode& lhs, const ItemNDCNode& rhs)
{
return lhs.data == rhs.data;
}
std::ostream& operator << (std::ostream& os, const ItemNDCNode& node)
{
os << node.data;
return os;
}
struct CompareItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
{
return lhs.data < rhs.data;
}
};
struct EqualItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
bool operator ==(const ItemDCNode& lhs, const ItemDCNode& rhs)
{
return lhs.data == rhs.data;
}
};
bool operator ==(const ItemNDCNode& lhs, const ItemNDCNode& rhs)
{
return lhs.data == rhs.data;
}
std::ostream& operator << (std::ostream& os, const ItemNDCNode& node)
{
os << node.data;
return os;
}
struct CompareItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
{
return lhs.data < rhs.data;
}
};
struct EqualItemNDCNode
{
bool operator ()(const ItemNDCNode& lhs, const ItemNDCNode& rhs) const
{
return lhs.data == rhs.data;
}
};
}
namespace
{

View File

@ -396,7 +396,7 @@ namespace
{
Data data(initial_data.begin(), initial_data.end());
CHECK_THROW(data.insert(std::make_pair(std::string("10"), 10)), etl::map_full);
CHECK_THROW(data.insert(std::make_pair(std::string("10"), 10)), etl::multimap_full);
}
//*************************************************************************
@ -436,7 +436,7 @@ namespace
{
Data data;
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::map_full);
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multimap_full);
}
//*************************************************************************

View File

@ -371,7 +371,7 @@ namespace
{
Data data(initial_data.begin(), initial_data.end());
CHECK_THROW(data.insert(10), etl::set_full);
CHECK_THROW(data.insert(10), etl::multiset_full);
}
//*************************************************************************
@ -411,7 +411,7 @@ namespace
{
Data data;
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::set_full);
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multiset_full);
}
//*************************************************************************

View File

@ -79,6 +79,17 @@ namespace
CHECK_EQUAL(data.max_size(), SIZE);
}
//*************************************************************************
TEST(test_iterator_comparison_empty)
{
Data data;
CHECK(data.begin() == data.end());
CHECK(data.cbegin() == data.cend());
CHECK(data.rbegin() == data.rend());
CHECK(data.crbegin() == data.crend());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_constructor_size)
{

View File

@ -120,6 +120,8 @@
<ClInclude Include="..\..\algorithm.h" />
<ClInclude Include="..\..\alignment.h" />
<ClInclude Include="..\..\array.h" />
<ClInclude Include="..\..\basic_intrusive_forward_list.h" />
<ClInclude Include="..\..\basic_intrusive_forward_list_node.h" />
<ClInclude Include="..\..\binary.h" />
<ClInclude Include="..\..\bitset.h" />
<ClInclude Include="..\..\bloom_filter.h" />
@ -171,6 +173,7 @@
<ClInclude Include="..\..\instance_count.h" />
<ClInclude Include="..\..\integral_limits.h" />
<ClInclude Include="..\..\intrusive_forward_list.h" />
<ClInclude Include="..\..\intrusive_forward_list_node.h" />
<ClInclude Include="..\..\io_port.h" />
<ClInclude Include="..\..\ipool.h" />
<ClInclude Include="..\..\ipriority_queue.h" />
@ -193,7 +196,9 @@
<ClInclude Include="..\..\map_base.h" />
<ClInclude Include="..\..\mru_cache.h" />
<ClInclude Include="..\..\multimap.h" />
<ClInclude Include="..\..\multimap_base.h" />
<ClInclude Include="..\..\multiset.h" />
<ClInclude Include="..\..\multiset_base.h" />
<ClInclude Include="..\..\murmur3.h" />
<ClInclude Include="..\..\nullptr.h" />
<ClInclude Include="..\..\numeric.h" />
@ -262,6 +267,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../unittest-cpp</AdditionalIncludeDirectories>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\test_basic_intrusive_forward_list.cpp" />
<ClCompile Include="..\test_binary.cpp" />
<ClCompile Include="..\test_bitset.cpp" />
<ClCompile Include="..\test_bloom_filter.cpp" />
@ -323,8 +329,6 @@
</ItemGroup>
<ItemGroup>
<None Include="..\..\Doxyfile" />
<None Include="ClassDiagram.cd" />
<None Include="ClassDiagram1.cd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -450,6 +450,21 @@
<ClInclude Include="..\..\intrusive_forward_list.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\intrusive_forward_list_node.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\basic_intrusive_forward_list.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\basic_intrusive_forward_list_node.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\multimap_base.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\multiset_base.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\unittest-cpp\UnitTest++\AssertException.cpp">
@ -692,12 +707,13 @@
<ClCompile Include="..\test_intrusive_forward_list.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\test_basic_intrusive_forward_list.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\Doxyfile">
<Filter>Header Files</Filter>
</None>
<None Include="ClassDiagram.cd" />
<None Include="ClassDiagram1.cd" />
</ItemGroup>
</Project>