mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-16 00:46:03 +08:00
Merge remote-tracking branch 'origin/development'
This commit is contained in:
commit
8bb5d26377
577
basic_intrusive_forward_list.h
Normal file
577
basic_intrusive_forward_list.h
Normal 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
|
||||
45
basic_intrusive_forward_list_node.h
Normal file
45
basic_intrusive_forward_list_node.h
Normal 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
845
bitset.h
@ -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
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -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
437
ibitset.h
@ -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
260
ideque.h
@ -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>
|
||||
|
||||
15
iflat_map.h
15
iflat_map.h
@ -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
|
||||
{
|
||||
|
||||
@ -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
246
imap.h
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
422
imultimap.h
422
imultimap.h
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
418
imultiset.h
418
imultiset.h
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
99
intrusive_forward_list_node.h
Normal file
99
intrusive_forward_list_node.h
Normal 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
243
iset.h
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
246
map_base.h
246
map_base.h
@ -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
581
multimap_base.h
Normal 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
580
multiset_base.h
Normal 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
|
||||
249
set_base.h
249
set_base.h
@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
582
test/test_basic_intrusive_forward_list.cpp
Normal file
582
test/test_basic_intrusive_forward_list.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
Loading…
x
Reference in New Issue
Block a user