From 5f2795185eceeaa4d707378ca0db91ad125e8ea9 Mon Sep 17 00:00:00 2001 From: jwellbelove Date: Sat, 1 Nov 2014 15:27:20 +0000 Subject: [PATCH] Added list container --- ilist.h | 1236 +++++++++++++++++++++++++++++++++++++++++++++++++++ list.h | 113 +++++ list_base.h | 143 ++++++ 3 files changed, 1492 insertions(+) create mode 100644 ilist.h create mode 100644 list.h create mode 100644 list_base.h diff --git a/ilist.h b/ilist.h new file mode 100644 index 00000000..df0f405f --- /dev/null +++ b/ilist.h @@ -0,0 +1,1236 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_ilist__ +#define __etl_ilist__ +#define __etl_in_ilist_h__ + +#if WIN32 +#undef min +#endif + +#include +#include +#include +#include + +#include "nullptr.h" +#include "list_base.h" + +namespace etl +{ + //*************************************************************************** + /// A templated base for all etl::list types. + ///\ingroup list + //*************************************************************************** + template + class ilist : public list_base + { + protected: + + //************************************************************************* + /// The node element in the list. + //************************************************************************* + struct Node + { + Node() + : previous(nullptr), + next(nullptr) + { + } + + void mark_as_free() + { + previous = nullptr; + next = nullptr; + } + + bool is_free() const + { + return next == nullptr; + } + + void reverse() + { + std::swap(previous, next); + } + + T value; + Node* previous; + Node* next; + }; + + private: + + Node terminal_node; ///< The node that acts as the list start and end. + Node* node_pool; ///< The pool of nodes used in the list. + + public: + + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + + typedef size_t size_type; ///< The type used for determining the size of list. + + //************************************************************************* + /// iterator. + //************************************************************************* + class iterator : public std::iterator + { + public: + + friend class ilist; + + iterator() + : p_node(nullptr) + { + } + + iterator(Node& 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 --() + { + p_node = p_node->previous; + return *this; + } + + iterator operator --(int) + { + iterator temp(*this); + p_node = p_node->previous; + return temp; + } + + iterator operator =(const iterator& other) + { + p_node = other.p_node; + return *this; + } + + reference operator *() + { + return p_node->value; + } + + const_reference operator *() const + { + return p_node->value; + } + + pointer operator &() + { + return &(p_node->value); + } + + const_pointer operator &() const + { + return &(p_node->value); + } + + pointer operator ->() + { + return &(p_node->value); + } + + const_pointer operator ->() const + { + return &(p_node->value); + } + + 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); + } + + private: + + Node* p_node; + }; + + //************************************************************************* + /// const_iterator + //************************************************************************* + class const_iterator : public std::iterator + { + public: + + friend class ilist; + + const_iterator() + : p_node(nullptr) + { + } + + const_iterator(Node& node) + : p_node(&node) + { + } + + const_iterator(const Node& node) + : p_node(&node) + { + } + + const_iterator(const typename ilist::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 --() + { + p_node = p_node->previous; + return *this; + } + + const_iterator operator --(int) + { + const_iterator temp(*this); + p_node = p_node->previous; + return temp; + } + + const_iterator operator =(const const_iterator& other) + { + p_node = other.p_node; + return *this; + } + + const_reference operator *() const + { + return p_node->value; + } + + const_pointer operator &() const + { + return &(p_node->value); + } + + Node* operator ->() + { + return p_node; + } + + const Node* 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); + } + + private: + + const Node* p_node; + }; + + typedef typename std::iterator_traits::difference_type difference_type; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + //************************************************************************* + /// Gets the beginning of the list. + //************************************************************************* + iterator begin() + { + return iterator(get_head()); + } + + //************************************************************************* + /// Gets the beginning of the list. + //************************************************************************* + const_iterator begin() const + { + return const_iterator(get_head()); + } + + //************************************************************************* + /// Gets the beginning of the list. + //************************************************************************* + const_iterator cbegin() const + { + return const_iterator(get_head()); + } + + //************************************************************************* + /// Gets the reverse beginning of the list. + //************************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(terminal_node); + } + + //************************************************************************* + /// Gets the reverse beginning of the list. + //************************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(terminal_node); + } + + //************************************************************************* + /// Gets the reverse beginning of the list. + //************************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(terminal_node); + } + + //************************************************************************* + /// Gets the end of the list. + //************************************************************************* + iterator end() + { + return iterator(terminal_node); + } + + //************************************************************************* + /// Gets the end of the list. + //************************************************************************* + const_iterator end() const + { + return const_iterator(terminal_node); + } + + //************************************************************************* + /// Gets the end of the list. + //************************************************************************* + const_iterator cend() const + { + return const_iterator(terminal_node); + } + + //************************************************************************* + /// Gets the reverse end of the list. + //************************************************************************* + reverse_iterator rend() + { + return reverse_iterator(get_head()); + } + + //************************************************************************* + /// Gets the reverse end of the list. + //************************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(get_head()); + } + + //************************************************************************* + /// Gets the reverse end of the list. + //************************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(get_head()); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ilist& operator = (const ilist& rhs) + { + assign(rhs.cbegin(), rhs.cend()); + + return *this; + } + + //************************************************************************* + /// Clears the list. + //************************************************************************* + void clear() + { + initialise(); + } + + //************************************************************************* + /// Gets a reference to the first element. + //************************************************************************* + reference front() + { + return get_head().value; + } + + //************************************************************************* + /// Gets a const reference to the first element. + //************************************************************************* + const_reference front() const + { + return get_head().value; + } + + //************************************************************************* + /// Gets a reference to the last element. + //************************************************************************* + reference back() + { + return get_tail().value; + } + + //************************************************************************* + /// Gets a reference to the last element. + //************************************************************************* + const_reference back() const + { + return get_tail().value; + } + + //************************************************************************* + /// Assigns a range of values to the list. + /// If ETL_USE_EXCEPTIONS is defined throws etl::list_full_exception if the list does not have enough free space. + /// If ETL_USE_EXCEPTIONS & _DEBUG are defined throws list_iterator_exception if the iterators are reversed. + //************************************************************************* + template + void assign(TIterator first, TIterator last) + { +#ifdef _DEBUG + if (std::distance(first, last) < 0) + { +#ifdef ETL_USE_EXCEPTIONS + throw list_iterator_exception(); +#endif + } + else +#endif + { + // Reset the links. + join(terminal_node, terminal_node); + + size_t i = 0; + + // Add all of the elements. + while (first != last) + { +#ifdef ETL_USE_EXCEPTIONS + if (i == MAX_SIZE) + { + throw list_full_exception(); + } +#endif + Node& node = node_pool[i]; + node.value = *first++; + join(*terminal_node.previous, node); + join(node, terminal_node); + ++i; + } + + next_free = i; + count = i; + + // Clear the remaining elements in the node pool. + while (i < MAX_SIZE) + { + node_pool[i].mark_as_free(); + ++i; + } + } + } + + //************************************************************************* + /// Assigns 'n' copies of a value to the list. + //************************************************************************* + void assign(size_t n, const_reference value) + { + if (n <= MAX_SIZE) + { + // Reset the links. + join(terminal_node, terminal_node); + + size_t i = 0; + + // Add all of the elements. + while (i < n) + { + Node& node = node_pool[i]; + node.value = value; + join(*terminal_node.previous, node); + join(node, terminal_node); + ++i; + } + + next_free = i; + count = i; + + // Clear the remaining elements in the node pool. + while (i < MAX_SIZE) + { + node_pool[i].mark_as_free(); + ++i; + } + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Adds a node to the front of the list so a new value can be assigned to front(). + //************************************************************************* + void push_front() + { + if (!full()) + { + Node& node = node_pool[next_free]; + + insert_node(get_head(), node); + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Pushes a value to the front of the list. + //************************************************************************* + void push_front(const_reference value) + { + if (!full()) + { + Node& node = node_pool[next_free]; + node.value = value; + + insert_node(get_head(), node); + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Adds a node to the back of the list so a new value can be assigned to back(). + //************************************************************************* + void push_back() + { + if (!full()) + { + Node& node = node_pool[next_free]; + + insert_node(terminal_node, node); + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Pushes a value to the back of the list.. + //************************************************************************* + void push_back(const_reference value) + { + if (!full()) + { + Node& node = node_pool[next_free]; + node.value = value; + + insert_node(terminal_node, node); + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Removes a value from the front of the list. + //************************************************************************* + void pop_front() + { + if (!empty()) + { + remove_node(get_head()); + } + } + + //************************************************************************* + /// Removes a value from the back of the list. + //************************************************************************* + void pop_back() + { + if (!empty()) + { + remove_node(get_tail()); + } + } + + //************************************************************************* + /// Resizes the list. + //************************************************************************* + void resize(size_t n) + { + resize(n, T()); + } + + //************************************************************************* + /// Resizes the list. + //************************************************************************* + void resize(size_t n, T value) + { + if (n <= MAX_SIZE) + { + // Reduce if necessary. + while (size() > n) + { + pop_back(); + } + + // Increase if necessary. + while (size() < n) + { + push_back(value); + } + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Reverses the list. + //************************************************************************* + void reverse() + { + if (is_trivial_list()) + { + return; + } + + Node* p_current = &get_head(); + + for (size_t i = 0; i < size(); ++i) + { + p_current->reverse(); + p_current = p_current->previous; + } + + terminal_node.reverse(); + } + + //************************************************************************* + /// Inserts a value to the list at the specified position. + //************************************************************************* + iterator insert(iterator position, const value_type& value) + { + if (!full()) + { + Node& node = node_pool[next_free]; + node.value = value; + + insert_node(*position.p_node, node); + + return iterator(node); + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Inserts 'n' copies of a value to the list at the specified position. + //************************************************************************* + void insert(iterator position, size_t n, const value_type& value) + { + if (!full()) + { + for (size_t i = 0; !full() && (i < n); ++i) + { + // Set up the next free node. + Node& node = node_pool[next_free]; + node.value = value; + + insert_node(*position.p_node, node); + } + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Inserts a range of values to the list at the specified position. + //************************************************************************* + template + void insert(iterator position, TIterator first, TIterator last) + { + if ((size() + std::distance(first, last)) <= MAX_SIZE) + { + while (first != last) + { + // Set up the next free node. + Node& node = node_pool[next_free]; + node.value = *first; + + insert_node(*position.p_node, node); + ++first; + } + } +#if ETL_USE_EXCEPTIONS + else + { + throw list_full_exception(); + } +#endif + } + + //************************************************************************* + /// Erases the value at the specified position. + //************************************************************************* + iterator erase(iterator position) + { + iterator next(position); + ++next; + + remove_node(*position.p_node); + + return next; + } + + //************************************************************************* + /// Erases a range of elements. + //************************************************************************* + iterator erase(iterator first, iterator last) + { + Node* p_first = first.p_node; + Node* p_last = last.p_node; + Node* p_next; + + // Join the ends. + join(*(p_first->previous), *p_last); + + // Erase the ones in between. + while (p_first != p_last) + { + // Update the position of the earliest free node in the pool. + size_t new_free = std::distance(&node_pool[0], p_first); + next_free = std::min(next_free, new_free); + + // One less. + --count; + + p_next = p_first->next; // Remember the next node. + p_first->mark_as_free(); // Free the current node. + p_first = p_next; // Move to the next node. + } + + return last; + } + + //************************************************************************* + /// Removes all but the first element from every consecutive group of equal + /// elements in the container. + //************************************************************************* + void unique() + { + unique(std::equal_to()); + } + + //************************************************************************* + /// Removes all but the first element from every consecutive group of equal + /// elements in the container. + //************************************************************************* + template + void unique(TIsEqual isEqual) + { + Node* current = get_head().next; + + while (current != &terminal_node) + { + Node* next = current->next; + if (isEqual(current->previous->value, current->value)) + { + remove_node(*current); + } + + current = next; + } + } + + //************************************************************************* + /// Sort using in-place merge sort algorithm. + /// Uses 'less-than operator as the predicate. + //************************************************************************* + void sort() + { + sort(std::less()); + } + + //************************************************************************* + /// Sort using in-place merge sort algorithm. + /// Uses a supplied predicate function or functor. + /// This is not my algorithm. I got it off the web somewhere. + //************************************************************************* + template + void sort(TCompare compare) + { + Node* p_left; + Node* p_right; + Node* p_node; + Node* p_head; + Node* p_tail; + int list_size = 1; + int number_of_merges; + int left_size; + int right_size; + + if (is_trivial_list()) + { + return; + } + + while (true) + { + p_left = &get_head(); + p_head = &terminal_node; + p_tail = &terminal_node; + + number_of_merges = 0; // Count the number of merges we do in this pass. + + while (p_left != &terminal_node) + { + ++number_of_merges; // There exists a merge to be done. + p_right = p_left; + left_size = 0; + + // Step 'list_size' places along from left + for (int i = 0; i < list_size; ++i) + { + ++left_size; + + p_right = p_right->next; + + if (p_right == &terminal_node) + { + break; + } + } + + // If right hasn't fallen off end, we have two lists to merge. + right_size = list_size; + + // Now we have two lists. Merge them. + while (left_size > 0 || (right_size > 0 && p_right != &terminal_node)) + { + // Decide whether the next node of merge comes from left or right. + if (left_size == 0) + { + // Left is empty. The node must come from right. + p_node = p_right; + p_right = p_right->next; + --right_size; + } + else if (right_size == 0 || p_right == &terminal_node) + { + // Right is empty. The node must come from left. + p_node = p_left; + p_left = p_left->next; + --left_size; + } + else if (compare(p_left->value, p_right->value)) + { + // First node of left is lower or same. The node must come from left. + p_node = p_left; + p_left = p_left->next; + --left_size; + } + else + { + // First node of right is lower. The node must come from right. + p_node = p_right; + p_right = p_right->next; + --right_size; + } + + // Add the next node to the merged head. + if (p_head == &terminal_node) + { + join(*p_head, *p_node); + p_head = p_node; + p_tail = p_node; + } + else + { + join(*p_tail, *p_node); + p_tail = p_node; + } + + join(*p_tail, terminal_node); + } + + // Now left has stepped `list_size' places along, and right has too. + p_left = p_right; + } + + // If we have done only one merge, we're finished. + if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case + { + return; + } + + // Otherwise repeat, merging lists twice the size + list_size *= 2; + } + } + + //************************************************************************* + // Removes the values specified. + //************************************************************************* + void remove(const value_type& value) + { + iterator iValue = begin(); + + while (iValue != end()) + { + if (value == *iValue) + { + iValue = erase(iValue); + } + else + { + ++iValue; + } + } + } + + //************************************************************************* + /// Removes according to a predicate. + //************************************************************************* + template + void remove_if(TPredicate predicate) + { + iterator iValue = begin(); + + while (iValue != end()) + { + if (predicate(*iValue)) + { + iValue = erase(iValue); + } + else + { + ++iValue; + } + } + } + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + ilist(Node* node_pool, size_t max_size_) + : list_base(max_size_), + node_pool(node_pool) + { + initialise(); + } + + private: + + //************************************************************************* + /// Join two nodes. + //************************************************************************* + void join(Node& left, Node& right) + { + left.next = &right; + right.previous = &left; + } + + //************************************************************************* + /// Is the list a trivial length? + //************************************************************************* + bool is_trivial_list() const + { + return (size() < 2); + } + + //************************************************************************* + /// Finds the next free node. + //************************************************************************* + void find_next_free() + { + while (next_free != MAX_SIZE) + { + if (node_pool[next_free].is_free()) + { + return; + } + else + { + ++next_free; + } + } + } + + //************************************************************************* + /// Insert a node. + //************************************************************************* + void insert_node(Node& position, Node& node) + { + // Connect to the list. + join(*position.previous, node); + join(node, position); + + // One more. + ++count; + + // Update the position of the next free node in the pool. + find_next_free(); + } + + //************************************************************************* + /// Remove a node. + //************************************************************************* + void remove_node(Node& node) + { + // Update the position of the next free node in the pool. + size_t new_free = std::distance(&node_pool[0], &node); + next_free = std::min(next_free, new_free); + + // One less. + --count; + + // Disconnect the node from the list. + join(*node.previous, *node.next); + node.mark_as_free(); + } + + //************************************************************************* + /// Get the head node. + //************************************************************************* + Node& get_head() + { + return *terminal_node.next; + } + + //************************************************************************* + /// Get the head node. + //************************************************************************* + const Node& get_head() const + { + return *terminal_node.next; + } + + //************************************************************************* + /// Get the tail node. + //************************************************************************* + Node& get_tail() + { + return *terminal_node.previous; + } + + //************************************************************************* + /// Get the tail node. + //************************************************************************* + const Node& get_tail() const + { + return *terminal_node.previous; + } + + //************************************************************************* + /// initialise the list. + //************************************************************************* + void initialise() + { + // Reset the node pool. + for (size_t i = 0; i < max_size(); ++i) + { + node_pool[i].mark_as_free(); + } + + next_free = 0; + count = 0; + join(terminal_node, terminal_node); + } + }; +} + +//************************************************************************* +/// Equal operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the arrays are equal, otherwise false. +//************************************************************************* +template +bool operator ==(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return (lhs.size() == rhs.size()) && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +//************************************************************************* +/// Not equal operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the arrays are not equal, otherwise false. +//************************************************************************* +template +bool operator !=(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return !(lhs == rhs); +} + +//************************************************************************* +/// Less than operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the first list is lexigraphically less than the +/// second, otherwise false. +//************************************************************************* +template +bool operator <(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return std::lexicographical_compare(lhs.begin(), + lhs.end(), + rhs.begin(), + rhs.end()); +} + +//************************************************************************* +/// Greater than operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the first list is lexigraphically greater than the +/// second, otherwise false. +//************************************************************************* +template +bool operator >(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return std::lexicographical_compare(lhs.begin(), + lhs.end(), + rhs.begin(), + rhs.end(), + std::greater()); +} + +//************************************************************************* +/// Less than or equal operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the first list is lexigraphically less than or equal +/// to the second, otherwise false. +//************************************************************************* +template +bool operator <=(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return !operator >(lhs, rhs); +} + +//************************************************************************* +/// Greater than or equal operator. +///\param lhs Reference to the first list. +///\param rhs Reference to the second list. +///\return true if the first list is lexigraphically greater than or +/// equal to the second, otherwise false. +//************************************************************************* +template +bool operator >=(const etl::ilist& lhs, const etl::ilist& rhs) +{ + return !operator <(lhs, rhs); +} + +#if WIN32 +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#endif diff --git a/list.h b/list.h new file mode 100644 index 00000000..6ce75452 --- /dev/null +++ b/list.h @@ -0,0 +1,113 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_list__ +#define __etl_list__ + +#include + +#include "ilist.h" + +namespace etl +{ + //************************************************************************* + /// A templated list implementation that uses a fixed size buffer. + /// MAX_SIZE_ elements will be always be constructed. + /// The list will allocate one more element than 'MAX_SIZE'. + ///\note 'merge', 'swap' and 'splice' and are not supported. + //************************************************************************* + template + class list : public ilist + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + public: + + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + inline list() + : ilist(&node_pool[0], MAX_SIZE) + { + } + + //************************************************************************* + /// Construct from size and value. + //************************************************************************* + inline explicit list(size_t initialSize, T value = T()) + : ilist(&node_pool[0], MAX_SIZE) + { + ilist::assign(initialSize, value); + } + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + explicit list(const list& other) + : ilist(&node_pool[0], MAX_SIZE) + { + ilist::assign(other.cbegin(), other.cend()); + } + + //************************************************************************* + /// Construct from range. + //************************************************************************* + template + list(TIterator first, TIterator last) + : ilist(&node_pool[0], MAX_SIZE) + { + ilist::assign(first, last); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + list& operator = (const list& rhs) + { + ilist::assign(rhs.cbegin(), rhs.cend()); + + return *this; + } + + private: + + /// The pool of nodes used in the list. + typename ilist::Node node_pool[MAX_SIZE]; + }; +} + +#endif diff --git a/list_base.h b/list_base.h new file mode 100644 index 00000000..03bee02e --- /dev/null +++ b/list_base.h @@ -0,0 +1,143 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_in_ilist_h__ +#error This header is a private element of etl::list & etl::ilist +#endif + +#ifndef __etl_list_base__ +#define __etl_list_base__ + +#include +#include "exception.h" + +namespace etl +{ +#ifdef ETL_USE_EXCEPTIONS + //*************************************************************************** + /// Exception for the list. + ///\ingroup list + //*************************************************************************** + class list_exception : public exception + { + public: + + list_exception(const char* what) + : exception(what) + { + } + }; + + //*************************************************************************** + /// Full exception for the list. + ///\ingroup list + //*************************************************************************** + class list_full_exception : public list_exception + { + public: + + list_full_exception() + : list_exception("List full") + { + } + }; + + //*************************************************************************** + /// Iterator exception for the list. + ///\ingroup list + //*************************************************************************** + class list_iterator_exception : public list_exception + { + public: + + list_iterator_exception() + : list_exception("Iterator problem") + { + } + }; +#endif + + //*************************************************************************** + /// The base class for all lists. + ///\ingroup list + //*************************************************************************** + class list_base + { + public: + + typedef size_t size_type; ///< The type used for determining the size of list. + + //************************************************************************* + /// Gets the size of the list. + //************************************************************************* + size_type size() const + { + return count; + } + + //************************************************************************* + /// Gets the maximum possible size of the list. + //************************************************************************* + size_type max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Checks to see if the list is empty. + //************************************************************************* + bool empty() const + { + return count == 0; + } + + //************************************************************************* + /// Checks to see if the list is full. + //************************************************************************* + bool full() const + { + return count == MAX_SIZE; + } + + protected: + + //************************************************************************* + /// The constructor that is called from derived classes. + //************************************************************************* + list_base(size_type max_size) + : MAX_SIZE(max_size) + { + } + + size_type next_free; ///< The index of the next free node. + size_type count; ///< The number of the used nodes. + const size_type MAX_SIZE; ///< The maximum size of the list. + }; +} + +#endif