diff --git a/src/ibasic_string.h b/src/ibasic_string.h deleted file mode 100644 index 88fbf484..00000000 --- a/src/ibasic_string.h +++ /dev/null @@ -1,2031 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_ISTRING__ -#define __ETL_ISTRING__ -#define __ETL_IN_ISTRING_H__ - -#include -#include -#include -#include -#include - -#include "private/string_base.h" -#include "platform.h" -#include "algorithm.h" -#include "type_traits.h" -#include "error_handler.h" -#include "algorithm.h" -#include "char_traits.h" - -#ifdef ETL_COMPILER_GCC -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif - -#ifdef ETL_COMPILER_MICROSOFT - #undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// Alternative strlen for all character types. - //*************************************************************************** - template - size_t strlen(const T* t) - { - return etl::char_traits::length(t); - } - - //*************************************************************************** - /// The base class for specifically sized strings. - /// Can be used as a reference type for all strings containing a specific type. - ///\ingroup string - //*************************************************************************** - template - class ibasic_string : public string_base - { - public: - - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef size_t size_type; - - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the string. - ///\return An iterator to the beginning of the string. - //********************************************************************* - iterator begin() - { - return &p_buffer[0]; - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the string. - ///\return A const iterator to the beginning of the string. - //********************************************************************* - const_iterator begin() const - { - return &p_buffer[0]; - } - - //********************************************************************* - /// Returns an iterator to the end of the string. - ///\return An iterator to the end of the string. - //********************************************************************* - iterator end() - { - return &p_buffer[current_size]; - } - - //********************************************************************* - /// Returns a const_iterator to the end of the string. - ///\return A const iterator to the end of the string. - //********************************************************************* - const_iterator end() const - { - return &p_buffer[current_size]; - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the string. - ///\return A const iterator to the beginning of the string. - //********************************************************************* - const_iterator cbegin() const - { - return &p_buffer[0]; - } - - //********************************************************************* - /// Returns a const_iterator to the end of the string. - ///\return A const iterator to the end of the string. - //********************************************************************* - const_iterator cend() const - { - return &p_buffer[current_size]; - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the string. - ///\return Iterator to the reverse beginning of the string. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(end()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the string. - ///\return Const iterator to the reverse beginning of the string. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(end()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the string. - ///\return Reverse iterator to the end + 1 of the string. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(begin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the string. - ///\return Const reverse iterator to the end + 1 of the string. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(begin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the string. - ///\return Const reverse iterator to the reverse beginning of the string. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(cend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the string. - ///\return Const reverse iterator to the end + 1 of the string. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(cbegin()); - } - - //********************************************************************* - /// Resizes the string. - /// If asserts or exceptions are enabled and the new size is larger than the - ///\param new_size The new size. - //********************************************************************* - void resize(size_t new_size) - { - resize(new_size, 0); - } - - //********************************************************************* - /// Resizes the string. - ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default constructed value. - //********************************************************************* - void resize(size_t new_size, T value) - { - new_size = std::min(new_size, MAX_SIZE); - - // Size up? - if (new_size > current_size) - { - std::fill(p_buffer + current_size, p_buffer + new_size, value); - } - - current_size = new_size; - p_buffer[new_size] = 0; - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference operator [](size_t i) - { - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference operator [](size_t i) const - { - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference at(size_t i) - { - ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds)); - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference at(size_t i) const - { - ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds)); - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a reference to the first element. - ///\return A reference to the first element. - //********************************************************************* - reference front() - { - return p_buffer[0]; - } - - //********************************************************************* - /// Returns a const reference to the first element. - ///\return A const reference to the first element. - //********************************************************************* - const_reference front() const - { - return p_buffer[0]; - } - - //********************************************************************* - /// Returns a reference to the last element. - ///\return A reference to the last element. - //********************************************************************* - reference back() - { - return p_buffer[current_size - 1]; - } - - //********************************************************************* - /// Returns a const reference to the last element. - ///\return A const reference to the last element. - //********************************************************************* - const_reference back() const - { - return p_buffer[current_size - 1]; - } - - //********************************************************************* - /// Returns a pointer to the beginning of the string data. - ///\return A pointer to the beginning of the string data. - //********************************************************************* - pointer data() - { - return p_buffer; - } - - //********************************************************************* - /// Returns a const pointer to the beginning of the string data. - ///\return A const pointer to the beginning of the string data. - //********************************************************************* - const_pointer data() const - { - return p_buffer; - } - - //********************************************************************* - /// Assigns values to the string. - /// Truncates if the string does not have enough free space. - ///\param other The other string. - //********************************************************************* - void assign(const etl::ibasic_string& other) - { - size_t length = std::min(MAX_SIZE, other.size()); - assign(other.begin(), other.begin() + length); - } - - //********************************************************************* - /// Assigns values to the string. - /// Truncates if the string does not have enough free space. - ///\param other The other string. - ///\param subposition The position to start from. - ///\param sublength The length to copy. - //********************************************************************* - void assign(const etl::ibasic_string& other, size_t subposition, size_t sublength) - { - if (sublength == npos) - { - sublength = other.size() - subposition; - } - - ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds)); - - assign(other.begin() + subposition, sublength); - } - - //********************************************************************* - /// Assigns values to the string. - /// Truncates if the string does not have enough free space. - ///\param other The other string. - //********************************************************************* - void assign(const_pointer other) - { - initialise(); - - while ((*other != 0) && (current_size < MAX_SIZE)) - { - p_buffer[current_size++] = *other++; - } - - is_truncated = (*other != 0); - - p_buffer[current_size] = 0; - } - - //********************************************************************* - /// Assigns values to the string. - /// Truncates if the string does not have enough free space. - ///\param other The other string. - ///\param length The length to copy. - //********************************************************************* - void assign(const_pointer other, size_t length) - { - length = std::min(length, MAX_SIZE); - - initialise(); - - etl::copy_n(other, length, begin()); - - current_size = length; - p_buffer[current_size] = 0; - } - - //********************************************************************* - /// Assigns values to the string. - /// If asserts or exceptions are enabled, emits string_iterator if the iterators are reversed. - /// Truncates if the string does not have enough free space. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(string_iterator)); -#endif - - initialise(); - - while ((first != last) && (current_size != MAX_SIZE)) - { - p_buffer[current_size++] = *first++; - } - - p_buffer[current_size] = 0; - } - - //********************************************************************* - /// Assigns values to the string. - /// Truncates if the string does not have enough free space. - ///\param n The number of elements to add. - ///\param value The value to insert for each element. - //********************************************************************* - void assign(size_t n, T value) - { - initialise(); - - n = std::min(n, MAX_SIZE); - - std::fill_n(begin(), n, value); - current_size = n; - p_buffer[current_size] = 0; - } - - //************************************************************************* - /// Clears the string. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Inserts a value at the end of the string. - /// Sets 'truncated' if the string is already full. - ///\param value The value to add. - //********************************************************************* - void push_back(T value) - { - if (current_size != MAX_SIZE) - { - p_buffer[current_size++] = value; - is_truncated = false; - } - else - { - is_truncated = true; - } - } - - //************************************************************************* - /// Removes an element from the end of the string. - /// Does nothing if the string is empty. - //************************************************************************* - void pop_back() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(string_empty)); -#endif - - p_buffer[--current_size] = 0; - } - - //********************************************************************* - /// Appends to the string. - ///\param str The string to append. - //********************************************************************* - ibasic_string& append(const ibasic_string& str) - { - insert(end(), str.begin(), str.end()); - return *this; - } - - //********************************************************************* - /// Appends to the string. - ///\param str The string to append. - ///\param subposition The position in str. - ///\param sublength The number of characters. - //********************************************************************* - ibasic_string& append(const ibasic_string& str, size_t subposition, size_t sublength = npos) - { - ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); - - insert(size(), str, subposition, sublength); - return *this; - } - - //********************************************************************* - /// Appends to the string. - ///\param str The string to append. - //********************************************************************* - ibasic_string& append(const T* str) - { - insert(size(), str); - return *this; - } - - //********************************************************************* - /// Appends to the string. - ///\param str The string to append. - ///\param n The number of characters. - //********************************************************************* - ibasic_string& append(const T* str, size_t n) - { - insert(size(), str, n); - return *this; - } - - //********************************************************************* - /// Appends to the string. - ///\param n The number of characters. - ///\param c The character. - //********************************************************************* - ibasic_string& append(size_t n, T c) - { - insert(size(), n, c); - return *this; - } - - //********************************************************************* - /// Appends to the string. - ///\param first The first of the characters to append. - ///\param last The last + 1 character to add. - //********************************************************************* - template - ibasic_string& append(TIterator first, TIterator last) - { - insert(end(), first, last); - return *this; - } - - //********************************************************************* - /// Inserts a value to the string. - ///\param position The position to insert before. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, T value) - { - is_truncated = false; - - // Quick hack, as iterators are pointers. - iterator insert_position = const_cast(position); - - if (current_size < MAX_SIZE) - { - // Not full yet. - if (position != end()) - { - // Insert in the middle. - ++current_size; - std::copy_backward(insert_position, end() - 1, end()); - *insert_position = value; - } - else - { - // Insert at the end. - *insert_position = value; - ++current_size; - } - } - else - { - // Already full. - if (position != end()) - { - // Insert in the middle. - std::copy_backward(insert_position, end() - 1, end()); - *insert_position = value; - } - - is_truncated = true; - } - - p_buffer[current_size] = 0; - - return insert_position; - } - - //********************************************************************* - /// Inserts 'n' values to the string. - ///\param position The position to insert before. - ///\param n The number of elements to add. - ///\param value The value to insert. - //********************************************************************* - void insert(const_iterator position, size_t n, T value) - { - is_truncated = false; - - if (n == 0) - { - return; - } - - // Quick hack, as iterators are pointers. - iterator insert_position = const_cast(position); - const size_t start = std::distance(cbegin(), position); - - // No effect. - if (start == MAX_SIZE) - { - return; - } - - // Fills the string to the end? - if ((start + n) >= MAX_SIZE) - { - is_truncated = ((current_size + n) > MAX_SIZE); - current_size = MAX_SIZE; - std::fill(insert_position, end(), value); - } - else - { - // Lets do some shifting. - const size_t shift_amount = n; - const size_t to_position = start + shift_amount; - const size_t remaining_characters = current_size - start; - const size_t max_shift_characters = MAX_SIZE - start - shift_amount; - const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters); - - // Will the string truncate? - if ((start + shift_amount + remaining_characters) > MAX_SIZE) - { - current_size = MAX_SIZE; - is_truncated = true; - } - else - { - current_size += shift_amount; - } - - std::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift); - std::fill(insert_position, insert_position + shift_amount, value); - } - - p_buffer[current_size] = 0; - } - - //********************************************************************* - /// Inserts a range of values to the string. - /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space. - ///\param position The position to insert before. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(iterator position, TIterator first, TIterator last) - { - is_truncated = false; - - if (first == last) - { - return; - } - - const size_t start = std::distance(begin(), position); - const size_t n = std::distance(first, last); - - // No effect. - if (start == MAX_SIZE) - { - return; - } - - // Fills the string to the end? - if ((start + n) >= MAX_SIZE) - { - is_truncated = ((current_size + n) > MAX_SIZE); - current_size = MAX_SIZE; - - while (position != end()) - { - *position++ = *first++; - } - } - else - { - // Lets do some shifting. - const size_t shift_amount = n; - const size_t to_position = start + shift_amount; - const size_t remaining_characters = current_size - start; - const size_t max_shift_characters = MAX_SIZE - start - shift_amount; - const size_t characters_to_shift = std::min(max_shift_characters, remaining_characters); - - // Will the string truncate? - if ((start + shift_amount + remaining_characters) > MAX_SIZE) - { - current_size = MAX_SIZE; - is_truncated = true; - } - else - { - current_size += shift_amount; - } - - std::copy_backward(position, position + characters_to_shift, begin() + to_position + characters_to_shift); - - while (first != last) - { - *position++ = *first++; - } - } - - p_buffer[current_size] = 0; - } - - //********************************************************************* - /// Inserts a string at the specified position. - ///\param position The position to insert before. - ///\param str The string to insert. - //********************************************************************* - etl::ibasic_string& insert(size_t position, const etl::ibasic_string& str) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - insert(begin() + position, str.cbegin(), str.cend()); - return *this; - } - - //********************************************************************* - /// Inserts a string at the specified position from subposition for sublength. - ///\param position The position to insert before. - ///\param str The string to insert. - ///\param subposition The subposition to start from. - ///\param sublength The number of characters to insert. - //********************************************************************* - etl::ibasic_string& insert(size_t position, const etl::ibasic_string& str, size_t subposition, size_t sublength) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); - - if ((sublength == npos) || (subposition + sublength > str.size())) - { - sublength = str.size() - subposition; - } - - insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength); - return *this; - } - - //********************************************************************* - /// Inserts a string at the specified position from pointer. - ///\param position The position to insert before. - ///\param s The string to insert. - //********************************************************************* - etl::ibasic_string& insert(size_t position, const_pointer s) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - insert(begin() + position, s, s + strlen(s)); - return *this; - } - - //********************************************************************* - /// Inserts a string at the specified position from pointer for n characters. - ///\param position The position to insert before. - ///\param s The string to insert. - ///\param n The number of characters to insert. - //********************************************************************* - etl::ibasic_string& insert(size_t position, const_pointer s, size_t n) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - insert(begin() + position, s, s + n); - return *this; - } - - //********************************************************************* - /// Insert n characters of c at position. - ///\param position The position to insert before. - ///\param n The number of characters to insert. - ///\param c The character to insert. - //********************************************************************* - etl::ibasic_string& insert(size_t position, size_t n, value_type c) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - insert(begin() + position, n, c); - return *this; - } - - //********************************************************************* - /// Erases a sequence. - ///\param position Position to start from. - ///\param length Number of characters. - ///\return A refernce to this string. - //********************************************************************* - etl::ibasic_string& erase(size_t position, size_t length = npos) - { - // Limit the length. - length = std::min(length, size() - position); - - erase(begin() + position, begin() + position + length); - - return *this; - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased element. - //********************************************************************* - iterator erase(iterator i_element) - { - std::copy(i_element + 1, end(), i_element); - p_buffer[--current_size] = 0; - - return i_element; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased element. - //********************************************************************* - iterator erase(iterator first, iterator last) - { - std::copy(last, end(), first); - size_t n_delete = std::distance(first, last); - - current_size -= n_delete; - p_buffer[current_size] = 0; - - return first; - } - - //********************************************************************* - /// Return a pointer to a C string. - //********************************************************************* - const_pointer c_str() const - { - return p_buffer; - } - - //********************************************************************* - /// Copies a portion of a string. - ///\param s Pointer to the string to copy. - ///\param len The number of characters to copy. - ///\param pos The position to start copying from. - //********************************************************************* - size_t copy(pointer s, size_t len, size_t pos = 0) - { - size_t endpos = std::min(pos + len, size()); - - for (size_t i = pos; i < endpos; ++i) - { - *s++ = p_buffer[i]; - } - - return endpos - pos; - } - - //********************************************************************* - /// Find content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find(const ibasic_string& str, size_t pos = 0) const - { - if ((pos + str.size()) > size()) - { - return npos; - } - - const_iterator iposition = std::search(begin() + pos, end(), str.begin(), str.end()); - - if (iposition == end()) - { - return npos; - } - else - { - return std::distance(begin(), iposition); - } - } - - //********************************************************************* - /// Find content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find(const_pointer s, size_t pos = 0) const - { -#if defined(ETL_DEBUG) - if ((pos + etl::strlen(s)) > size()) - { - return npos; - } -#endif - - const_iterator iposition = std::search(begin() + pos, end(), s, s + etl::strlen(s)); - - if (iposition == end()) - { - return npos; - } - else - { - return std::distance(begin(), iposition); - } - } - - //********************************************************************* - /// Find content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - ///\param n The number of characters to search for. - //********************************************************************* - size_t find(const_pointer s, size_t pos, size_t n) const - { -#if defined(ETL_DEBUG) - if ((pos + etl::strlen(s) - n) > size()) - { - return npos; - } -#endif - - const_iterator iposition = std::search(begin() + pos, end(), s, s + n); - - if (iposition == end()) - { - return npos; - } - else - { - return std::distance(begin(), iposition); - } - } - - //********************************************************************* - /// Find character within the string - ///\param c The character to find. - ///\param position The position to start searching from. - //********************************************************************* - size_t find(T c, size_t position = 0) const - { - const_iterator i = std::find(begin() + position, end(), c); - - if (i != end()) - { - return std::distance(begin(), i); - } - else - { - return npos; - } - } - - //********************************************************************* - /// Find content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t rfind(const ibasic_string& str, size_t position = npos) const - { - if ((str.size()) > size()) - { - return npos; - } - - if (position >= size()) - { - position = size(); - } - - position = size() - position; - - const_reverse_iterator iposition = std::search(rbegin() + position, rend(), str.rbegin(), str.rend()); - - if (iposition == rend()) - { - return npos; - } - else - { - return size() - str.size() - std::distance(rbegin(), iposition); - } - } - - //********************************************************************* - /// Find content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t rfind(const_pointer s, size_t position = npos) const - { - size_t length = etl::strlen(s); - - if (length > size()) - { - return npos; - } - - if (position >= size()) - { - position = size(); - } - - position = size() - position; - - const_reverse_iterator srbegin(s + length); - const_reverse_iterator srend(s); - - const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend); - - if (iposition == rend()) - { - return npos; - } - else - { - return size() - length - std::distance(rbegin(), iposition); - } - } - - //********************************************************************* - /// Find content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t rfind(const_pointer s, size_t position, size_t length) const - { - if (length > size()) - { - return npos; - } - - if (position >= size()) - { - position = size(); - } - - position = size() - position; - - const_reverse_iterator srbegin(s + length); - const_reverse_iterator srend(s); - - const_reverse_iterator iposition = std::search(rbegin() + position, rend(), srbegin, srend); - - if (iposition == rend()) - { - return npos; - } - else - { - return size() - length - std::distance(rbegin(), iposition); - } - } - - //********************************************************************* - /// Find character within the string - ///\param c The character to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t rfind(T c, size_t position = npos) const - { - if (position >= size()) - { - position = size(); - } - - position = size() - position; - - const_reverse_iterator i = std::find(rbegin() + position, rend(), c); - - if (i != rend()) - { - return size() - std::distance(rbegin(), i) - 1; - } - else - { - return npos; - } - } - - //********************************************************************* - /// Replace 'length' characters from 'position' with 'str'. - ///\param position The position to start from. - ///\param length The number of characters to replace. - ///\param str The string to replace it with. - //********************************************************************* - ibasic_string& replace(size_t position, size_t length, const ibasic_string& str) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the length. - length = std::min(length, size() - position); - - // Erase the bit we want to replace. - erase(position, length); - - // Insert the new stuff. - insert(position, str); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'first' to one before 'last' with 'str'. - ///\param first The position to start from. - ///\param last The one after the position to end at. - ///\param str The string to replace it with. - //********************************************************************* - ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str) - { - // Quick hack, as iterators are pointers. - iterator first_ = const_cast(first); - iterator last_ = const_cast(last); - - // Erase the bit we want to replace. - erase(first_, last_); - - // Insert the new stuff. - insert(first_, str.begin(), str.end()); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'position' of 'length' with 'str' from 'subpsotion' of 'sublength'. - //********************************************************************* - ibasic_string& replace(size_t position, size_t length, const ibasic_string& str, size_t subposition, size_t sublength) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the lengths. - length = std::min(length, size() - position); - sublength = std::min(sublength, str.size() - subposition); - - // Erase the bit we want to replace. - erase(position, length); - - // Insert the new stuff. - insert(position, str, subposition, sublength); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'position' of 'length' with pointed to string. - //********************************************************************* - ibasic_string& replace(size_t position, size_t length, const_pointer s) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the length. - length = std::min(length, size() - position); - - // Erase the bit we want to replace. - erase(position, length); - - // Insert the new stuff. - insert(position, s, etl::strlen(s)); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'first' 'last' with pointed to string. - //********************************************************************* - ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s) - { - // Quick hack, as iterators are pointers. - iterator first_ = const_cast(first); - iterator last_ = const_cast(last); - - // Erase the bit we want to replace. - erase(first_, last_); - - // Insert the new stuff. - insert(first_, s, s + etl::strlen(s)); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'position' of 'length' with 'n' characters from pointed to string. - //********************************************************************* - ibasic_string& replace(size_t position, size_t length, const_pointer s, size_t n) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the length. - length = std::min(length, size() - position); - - // Erase the bit we want to replace. - erase(position, length); - - // Insert the new stuff. - insert(position, s, n); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'first' to 'last' with 'n' characters from pointed to string. - //********************************************************************* - ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_t n) - { - // Quick hack, as iterators are pointers. - iterator first_ = const_cast(first); - iterator last_ = const_cast(last); - - // Erase the bit we want to replace. - erase(first_, last_); - - // Insert the new stuff. - insert(first_, s, s + n); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'position' of 'length' with 'n' copies of 'c'. - //********************************************************************* - ibasic_string& replace(size_t position, size_t length, size_t n, value_type c) - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the length. - length = std::min(length, size() - position); - - // Erase the bit we want to replace. - erase(position, length); - - // Insert the new stuff. - insert(position, n, c); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'first' of 'last' with 'n' copies of 'c'. - //********************************************************************* - ibasic_string& replace(const_iterator first, const_iterator last, size_t n, value_type c) - { - // Quick hack, as iterators are pointers. - iterator first_ = const_cast(first); - iterator last_ = const_cast(last); - - // Erase the bit we want to replace. - erase(first_, last_); - - // Insert the new stuff. - insert(first_, n, c); - - return *this; - } - - //********************************************************************* - /// Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'. - //********************************************************************* - template - ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace) - { - // Quick hack, as iterators are pointers. - iterator first_ = const_cast(first); - iterator last_ = const_cast(last); - - // Erase the bit we want to replace. - erase(first_, last_); - - // Insert the new stuff. - insert(first_, first_replace, last_replace); - - return *this; - } - - //************************************************************************* - /// Compare with string. - //************************************************************************* - int compare(const ibasic_string& str) const - { - return compare(p_buffer, - p_buffer + size(), - str.p_buffer, - str.p_buffer + str.size()); - } - - //************************************************************************* - /// Compare position / length with string. - //************************************************************************* - int compare(size_t position, size_t length, const ibasic_string& str) const - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the length. - length = std::min(length, size() - position); - - return compare(p_buffer + position, - p_buffer + position + length, - str.p_buffer, - str.p_buffer + str.size()); - } - - //************************************************************************* - /// Compare position / length with string / subposition / sublength. - //************************************************************************* - int compare(size_t position, size_t length, const ibasic_string& str, size_t subposition, size_t sublength) const - { - ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); - ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); - - // Limit the lengths. - length = std::min(length, size() - position); - sublength = std::min(sublength, str.size() - subposition); - - return compare(p_buffer + position, - p_buffer + position + length, - str.p_buffer + subposition, - str.p_buffer + subposition + sublength); - } - - //************************************************************************* - /// Compare with C string - //************************************************************************* - int compare(const value_type* s) const - { - return compare(p_buffer, - p_buffer+ size(), - s, - s + etl::strlen(s)); - } - - //************************************************************************* - /// Compare position / length with C string. - //************************************************************************* - int compare(size_t position, size_t length, const_pointer s) const - { - return compare(p_buffer + position, - p_buffer + position + length, - s, - s + etl::strlen(s)); - } - - //************************************************************************* - /// Compare position / length with C string / n. - //************************************************************************* - int compare(size_t position, size_t length, const_pointer s, size_t n) const - { - return compare(p_buffer + position, - p_buffer + position + length, - s, - s + n);; - } - - //********************************************************************* - /// Find first of any of content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_of(const ibasic_string& str, size_t position = 0) const - { - return find_first_of(str.c_str(), position, str.size()); - } - - //********************************************************************* - /// Find first of any of content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_of(const_pointer s, size_t position = 0) const - { - return find_first_of(s, position, etl::strlen(s)); - } - - //********************************************************************* - /// Find first of any of content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - ///\param n The number of characters to search for. - //********************************************************************* - size_t find_first_of(const_pointer s, size_t position, size_t n) const - { - if (position < size()) - { - for (size_t i = position; i < size(); ++i) - { - for (size_t j = 0; j < n; ++j) - { - if (p_buffer[i] == s[j]) - { - return i; - } - } - } - } - - return npos; - } - - //********************************************************************* - /// Find first of character within the string - ///\param c The character to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_of(value_type c, size_t position = 0) const - { - if (position < size()) - { - for (size_t i = position; i < size(); ++i) - { - if (p_buffer[i] == c) - { - return i; - } - } - } - - return npos; - } - - //********************************************************************* - /// Find last of any of content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_last_of(const ibasic_string& str, size_t position = npos) const - { - return find_last_of(str.c_str(), position, str.size()); - } - - //********************************************************************* - /// Find last of any of content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_last_of(const_pointer s, size_t position = npos) const - { - return find_last_of(s, position, etl::strlen(s)); - } - - //********************************************************************* - /// Find last of any of content within the string - ///\param s Pointer to the content to find - ///\param pos The position to start searching from. - ///\param n The number of characters to search for. - //********************************************************************* - size_t find_last_of(const_pointer s, size_t position, size_t n) const - { - if (empty()) - { - return npos; - } - - position = std::min(position, size() - 1); - - const_reverse_iterator it = rbegin() + size() - position - 1; - - while (it != rend()) - { - for (size_t j = 0; j < n; ++j) - { - if (p_buffer[position] == s[j]) - { - return position; - } - } - - ++it; - --position; - } - - return npos; - } - - //********************************************************************* - /// Find last of character within the string - ///\param c The character to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_last_of(value_type c, size_t position = npos) const - { - if (empty()) - { - return npos; - } - - position = std::min(position, size() - 1); - - const_reverse_iterator it = rbegin() + size() - position - 1; - - while (it != rend()) - { - if (p_buffer[position] == c) - { - return position; - } - - ++it; - --position; - } - - return npos; - } - - //********************************************************************* - /// Find first not of any of content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_not_of(const ibasic_string& str, size_t position = 0) const - { - return find_first_not_of(str.c_str(), position, str.size()); - } - - //********************************************************************* - /// Find first not of any of content within the string - ///\param s Pointer to the content to not find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_not_of(const_pointer s, size_t position = 0) const - { - return find_first_not_of(s, position, etl::strlen(s)); - } - - //********************************************************************* - /// Find first not of any of content within the string - ///\param s Pointer to the content to not find - ///\param pos The position to start searching from. - ///\param n The number of characters to search for. - //********************************************************************* - size_t find_first_not_of(const_pointer s, size_t position, size_t n) const - { - if (position < size()) - { - for (size_t i = position; i < size(); ++i) - { - bool found = false; - - for (size_t j = 0; j < n; ++j) - { - if (p_buffer[i] == s[j]) - { - found = true; - } - } - - if (!found) - { - return i; - } - } - } - - return npos; - } - - //********************************************************************* - /// Find first not of character within the string - ///\param c The character to not find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_first_not_of(value_type c, size_t position = 0) const - { - if (position < size()) - { - for (size_t i = position; i < size(); ++i) - { - if (p_buffer[i] != c) - { - return i; - } - } - } - - return npos; - } - - //********************************************************************* - /// Find last not of any of content within the string - ///\param str The content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_last_not_of(const ibasic_string& str, size_t position = npos) const - { - return find_last_not_of(str.c_str(), position, str.size()); - } - - //********************************************************************* - /// Find last not of any of content within the string - ///\param s The pointer to the content to find - ///\param pos The position to start searching from. - //********************************************************************* - size_t find_last_not_of(const_pointer s, size_t position = npos) const - { - return find_last_not_of(s, position, etl::strlen(s)); - } - - //********************************************************************* - /// Find last not of any of content within the string - ///\param s The pointer to the content to find - ///\param pos The position to start searching from. - ///\param n The number of characters to use. - //********************************************************************* - size_t find_last_not_of(const_pointer s, size_t position, size_t n) const - { - if (empty()) - { - return npos; - } - - position = std::min(position, size() - 1); - - const_reverse_iterator it = rbegin() + size() - position - 1; - - while (it != rend()) - { - bool found = false; - - for (size_t j = 0; j < n; ++j) - { - if (p_buffer[position] == s[j]) - { - found = true; - } - } - - if (!found) - { - return position; - } - - ++it; - --position; - } - - return npos; - } - - //********************************************************************* - // - //********************************************************************* - size_t find_last_not_of(value_type c, size_t position = npos) const - { - if (empty()) - { - return npos; - } - - position = std::min(position, size() - 1); - - const_reverse_iterator it = rbegin() + size() - position - 1; - - while (it != rend()) - { - if (p_buffer[position] != c) - { - return position; - } - - ++it; - --position; - } - - return npos; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ibasic_string& operator = (const ibasic_string& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// += operator. - //************************************************************************* - ibasic_string& operator += (const ibasic_string& rhs) - { - if (&rhs != this) - { - append(rhs); - } - - return *this; - } - - //************************************************************************* - /// += operator. - //************************************************************************* - ibasic_string& operator += (const T* rhs) - { - append(rhs); - - return *this; - } - - //************************************************************************* - /// += operator. - //************************************************************************* - ibasic_string& operator += (T rhs) - { - append(size_t(1), rhs); - - return *this; - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - ibasic_string(T* p_buffer, size_t MAX_SIZE) - : string_base(MAX_SIZE), - p_buffer(p_buffer) - { - } - - //********************************************************************* - /// Initialise the string. - //********************************************************************* - void initialise() - { - current_size = 0; - p_buffer[0] = 0; - } - - private: - - //************************************************************************* - /// Compare helper function - //************************************************************************* - int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const - { - while ((first1 != last1) && (first2 != last2)) - { - if (*first1 < *first2) - { - // Compared character is lower. - return -1; - } - else if (*first1 > *first2) - { - // Compared character is higher. - return 1; - } - - ++first1; - ++first2; - } - - // We reached the end of one or both of the strings. - if ((first1 == last1) && (first2 == last2)) - { - // Same length. - return 0; - } - else if (first1 == last1) - { - // Compared string is shorter. - return -1; - } - else - { - // Compared string is longer. - return 1; - } - } - - // Disable copy construction. - ibasic_string(const ibasic_string&); - - T* p_buffer; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator ==(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator ==(const etl::ibasic_string& lhs, const T* rhs) - { - return (lhs.size() == etl::strlen(rhs)) && std::equal(lhs.begin(), lhs.end(), rhs); - } - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator ==(const T* lhs, const etl::ibasic_string& rhs) - { - return (rhs.size() == etl::strlen(lhs)) && std::equal(rhs.begin(), rhs.end(), lhs); - } - - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator !=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return !(lhs == rhs); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator !=(const etl::ibasic_string& lhs, const T* rhs) - { - return !(lhs == rhs); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator !=(const T* lhs, const etl::ibasic_string& rhs) - { - return !(lhs == rhs); - } - - - //*************************************************************************** - /// Less than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); - } - - //*************************************************************************** - /// Less than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <(const etl::ibasic_string& lhs, const T* rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs)); - } - - //*************************************************************************** - /// Less than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <(const T* lhs, const etl::ibasic_string& rhs) - { - return std::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end()); - } - - - //*************************************************************************** - /// Greater than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return (rhs < lhs); - } - - //*************************************************************************** - /// Greater than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >(const etl::ibasic_string& lhs, const T* rhs) - { - return (rhs < lhs); - } - - //*************************************************************************** - /// Greater than operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >(const T* lhs, const etl::ibasic_string& rhs) - { - return (rhs < lhs); - } - - - //*************************************************************************** - /// Less than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return !(lhs > rhs); - } - - //*************************************************************************** - /// Less than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <=(const etl::ibasic_string& lhs, const T* rhs) - { - return !(lhs > rhs); - } - - //*************************************************************************** - /// Less than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically less than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator <=(const T* lhs, const etl::ibasic_string& rhs) - { - return !(lhs > rhs); - } - - - //*************************************************************************** - /// Greater than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) - { - return !(lhs < rhs); - } - - //*************************************************************************** - /// Greater than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >=(const etl::ibasic_string& lhs, const T* rhs) - { - return !(lhs < rhs); - } - - //*************************************************************************** - /// Greater than or equal operator. - ///\param lhs Reference to the first string. - ///\param rhs Reference to the second string. - ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false - ///\ingroup string - //*************************************************************************** - template - bool operator >=(const T* lhs, const etl::ibasic_string& rhs) - { - return !(lhs < rhs); - } -} - -#ifdef ETL_COMPILER_MICROSOFT - #define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_ISTRING_H__ -#endif diff --git a/src/ibitset.h b/src/ibitset.h deleted file mode 100644 index b207c7a8..00000000 --- a/src/ibitset.h +++ /dev/null @@ -1,712 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IBITSET__ -#define __ETL_IBITSET__ - -#include -#include -#include - -#include "exception.h" -#include "integral_limits.h" -#include "binary.h" -#include "algorithm.h" -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// Exception base for bitset - ///\ingroup bitset - //*************************************************************************** - class bitset_exception : public etl::exception - { - public: - - bitset_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Bitset nullptr exception. - ///\ingroup bitset - //*************************************************************************** - class bitset_nullptr : public bitset_exception - { - public: - - bitset_nullptr(string_type file_name, numeric_type line_number) - : bitset_exception("bitset: nullptr", file_name, line_number) - { - } - }; - - //************************************************************************* - /// The base class for etl::bitset - ///\ingroup bitset - //************************************************************************* - class ibitset - { - protected: - - // The type used for each element in the array. -#if !defined(ETL_BITSET_ELEMENT_TYPE) - typedef uint_least8_t element_t; -#else - typedef ETL_BITSET_ELEMENT_TYPE element_t; -#endif - - public: - - static const element_t ALL_SET = etl::integral_limits::max; - static const element_t ALL_CLEAR = 0; - - static const size_t BITS_PER_ELEMENT = etl::integral_limits::bits; - - enum - { - npos = etl::integral_limits::max - }; - - //************************************************************************* - /// The reference type returned. - //************************************************************************* - class bit_reference - { - public: - - 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. - //************************************************************************* - size_t size() const - { - return NBITS; - } - - //************************************************************************* - /// Count the number of bits set. - //************************************************************************* - 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 false. - //************************************************************************* - 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::value; - mask = element_t(1) << (position & (BITS_PER_ELEMENT - 1)); - } - - return (pdata[index] & mask) != 0; - } - - //************************************************************************* - /// Set the bit at the position. - //************************************************************************* - 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::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. - //************************************************************************* - 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::value; - bit = element_t(1) << (position & (BITS_PER_ELEMENT - 1)); - } - - pdata[index] &= ~bit; - - return *this; - } - - //************************************************************************* - /// Flip all of the bits. - //************************************************************************* - 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::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. - //************************************************************************* - 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 (SIZE == 1) - { - index = 0; - bit = position; - } - else - { - index = position >> log2::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); - } - - //************************************************************************* - /// operator &= - //************************************************************************* - ibitset& operator &=(const ibitset& other) - { - for (size_t i = 0; i < SIZE; ++i) - { - pdata[i] &= other.pdata[i]; - } - - return *this; - } - - //************************************************************************* - /// operator |= - //************************************************************************* - ibitset& operator |=(const ibitset& other) - { - for (size_t i = 0; i < SIZE; ++i) - { - pdata[i] |= other.pdata[i]; - } - - return *this; - } - - //************************************************************************* - /// operator ^= - //************************************************************************* - ibitset& operator ^=(const ibitset& other) - { - for (size_t i = 0; i < SIZE; ++i) - { - pdata[i] ^= other.pdata[i]; - } - - return *this; - } - - //************************************************************************* - /// operator <<= - //************************************************************************* - ibitset& operator<<=(size_t shift) - { - if (SIZE == 1) - { - pdata[0] <<= shift; - } - else - { - size_t source = NBITS - shift - 1; - size_t destination = NBITS - 1; - - for (size_t i = 0; i < (NBITS - shift); ++i) - { - set(destination--, test(source--)); - } - - for (size_t i = 0; i < shift; ++i) - { - reset(destination--); - } - } - - return *this; - } - - //************************************************************************* - /// operator >>= - //************************************************************************* - ibitset& operator>>=(size_t shift) - { - if (SIZE == 1) - { - pdata[0] >>= shift; - } - else - { - size_t source = shift; - size_t destination = 0; - - for (size_t i = 0; i < (NBITS - shift); ++i) - { - set(destination++, test(source++)); - } - - for (size_t i = 0; i < shift; ++i) - { - reset(destination++); - } - } - - return *this; - } - - //************************************************************************* - /// operator = - //************************************************************************* - ibitset& operator =(const ibitset& other) - { - if (this != &other) - { - etl::copy_n(other.pdata, SIZE, pdata); - } - - return *this; - } - - //************************************************************************* - /// swap - //************************************************************************* - void swap(ibitset& other) - { - std::swap_ranges(pdata, pdata + SIZE, other.pdata); - } - - protected: - - //************************************************************************* - /// Initialise from an unsigned long long. - //************************************************************************* - ibitset& initialise(unsigned long long value) - { - reset(); - - const size_t SHIFT = (integral_limits::bits <= (int)BITS_PER_ELEMENT) ? 0 : BITS_PER_ELEMENT; - - // Can we do it in one hit? - if (SHIFT == 0) - { - pdata[0] = element_t(value); - } - else - { - size_t i = 0; - - while ((value != 0) && (i < SIZE)) - { - pdata[i++] = value & ALL_SET; - value = value >> SHIFT; - } - } - - pdata[SIZE - 1] &= TOP_MASK; - - return *this; - } - - //************************************************************************* - /// Invert - //************************************************************************* - void invert() - { - for (size_t i = 0; i < SIZE; ++i) - { - pdata[i] = ~pdata[i]; - } - } - - //************************************************************************* - /// 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)); - } - - //************************************************************************* - /// Compare bitsets. - //************************************************************************* - static bool is_equal(const ibitset& lhs, const ibitset&rhs) - { - return std::equal(lhs.pdata, lhs.pdata + lhs.SIZE, rhs.pdata); - } - - element_t TOP_MASK; - - private: - - // Disable copy construction. - ibitset(const ibitset&); - - const size_t NBITS; - const size_t SIZE; - element_t* pdata; - }; -} - - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#endif diff --git a/src/ideque.h b/src/ideque.h deleted file mode 100644 index d5d47141..00000000 --- a/src/ideque.h +++ /dev/null @@ -1,1468 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IDEQUE__ -#define __ETL_IDEQUE__ -#define __ETL_IN_IDEQUE_H__ - -#include -#include - -#include "algorithm.h" -#include "type_traits.h" -#include "private/deque_base.h" -#include "parameter_type.h" -#include "error_handler.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for all etl::deque classes. - ///\tparam T The type of values this deque should hold. - ///\ingroup deque - //*************************************************************************** - template - class ideque : public deque_base - { - public: - - typedef T value_type; - typedef size_t size_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef typename std::iterator_traits::difference_type difference_type; - - protected: - - typedef typename parameter_type::type parameter_t; - - //************************************************************************* - /// Test for an iterator. - //************************************************************************* - template - struct is_iterator : public etl::integral_constant::value && !etl::is_floating_point::value> - { - }; - - public: - - //************************************************************************* - /// Iterator - //************************************************************************* - struct iterator : public std::iterator - { - friend class ideque; - - //*************************************************** - iterator() - : index(0), - p_deque(0), - p_buffer(0) - { - } - - //*************************************************** - iterator(const iterator& other) - : index(other.index), - p_deque(other.p_deque), - p_buffer(other.p_buffer) - { - } - - //*************************************************** - iterator& operator ++() - { - index = (static_cast(index) == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1; - - return *this; - } - - //*************************************************** - iterator operator ++(int) - { - iterator previous(*this); - index = (static_cast(index) == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1; - - return previous; - } - - //*************************************************** - iterator& operator +=(difference_type offset) - { - if (offset > 0) - { - index += offset; - index = (static_cast(index) > p_deque->BUFFER_SIZE - 1) ? index - p_deque->BUFFER_SIZE : index; - } - else if (offset < 0) - { - operator -= (-offset); - } - - return *this; - } - - //*************************************************** - iterator& operator -=(difference_type offset) - { - if (offset > 0) - { - index -= offset; - index = (index < 0) ? index + p_deque->BUFFER_SIZE : index; - } - else if (offset < 0) - { - operator += (-offset); - } - - return *this; - } - - //*************************************************** - iterator& operator --() - { - index = (index == 0) ? p_deque->BUFFER_SIZE - 1 : index - 1; - - return *this; - } - - //*************************************************** - iterator operator --(int) - { - iterator previous(*this); - index = (index == 0) ? p_deque->BUFFER_SIZE - 1 : index - 1; - - return previous; - } - - //*************************************************** - reference operator *() - { - return p_buffer[index]; - } - - //*************************************************** - const_reference operator *() const - { - return p_buffer[index]; - } - - //*************************************************** - pointer operator ->() - { - return &p_buffer[index]; - } - - //*************************************************** - const_pointer operator ->() const - { - return &p_buffer[index]; - } - - //*************************************************** - bool operator <(const iterator& other) const - { - return ideque::distance(*this, other) > 0; - } - - //*************************************************** - friend iterator operator +(const iterator& lhs, difference_type offset) - { - iterator result(lhs); - result += offset; - return result; - } - - //*************************************************** - friend iterator operator -(const iterator& lhs, difference_type offset) - { - iterator result(lhs); - result -= offset; - return result; - } - - //*************************************************** - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.index == rhs.index; - } - - //*************************************************** - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - //*************************************************** - difference_type get_index() const - { - return index; - } - - //*************************************************** - ideque& get_deque() const - { - return *p_deque; - } - - //*************************************************** - pointer get_buffer() const - { - return p_buffer; - } - - //*************************************************** - void swap(iterator& other) - { - std::swap(index, other.index); - } - - private: - - //*************************************************** - iterator(difference_type index, ideque& the_deque, pointer p_buffer) - : index(index), - p_deque(&the_deque), - p_buffer(p_buffer) - { - } - - difference_type index; - ideque* p_deque; - pointer p_buffer; - }; - - //************************************************************************* - /// Const Iterator - //************************************************************************* - struct const_iterator : public std::iterator - { - friend class ideque; - - //*************************************************** - const_iterator() - : index(0), - p_deque(0), - p_buffer(0) - { - } - - //*************************************************** - const_iterator(const const_iterator& other) - : index(other.index), - p_deque(other.p_deque), - p_buffer(other.p_buffer) - { - } - - //*************************************************** - const_iterator(const typename ideque::iterator& other) - : index(other.index), - p_deque(other.p_deque), - p_buffer(other.p_buffer) - { - } - - //*************************************************** - const_iterator& operator ++() - { - index = (static_cast(index) == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1; - - return *this; - } - - //*************************************************** - const_iterator operator ++(int) - { - const_iterator previous(*this); - index = (static_cast(index) == p_deque->BUFFER_SIZE - 1) ? 0 : index + 1; - - return previous; - } - - //*************************************************** - const_iterator& operator +=(difference_type offset) - { - if (offset > 0) - { - index += offset; - index = (static_cast(index) > p_deque->BUFFER_SIZE - 1) ? index - p_deque->BUFFER_SIZE : index; - } - else if (offset < 0) - { - operator -= (-offset); - } - - return *this; - } - - //*************************************************** - const_iterator& operator -=(difference_type offset) - { - if (offset > 0) - { - index -= offset; - index = (index < 0) ? static_cast(index) + p_deque->BUFFER_SIZE : index; - } - else if (offset < 0) - { - operator += (-offset); - } - - return *this; - } - - //*************************************************** - const_iterator& operator --() - { - index = (index == 0) ? p_deque->BUFFER_SIZE - 1 : index - 1; - - return *this; - } - - //*************************************************** - const_iterator operator --(int) - { - const_iterator previous(*this); - index = (index == 0) ? p_deque->BUFFER_SIZE - 1 : index - 1; - - return previous; - } - - //*************************************************** - const_reference operator *() const - { - return p_buffer[index]; - } - - //*************************************************** - const_pointer operator ->() const - { - return &p_buffer[index]; - } - - //*************************************************** - bool operator <(const const_iterator& other) const - { - return ideque::distance(*this, other) > 0; - } - - //*************************************************** - friend const_iterator operator +(const const_iterator& lhs, difference_type offset) - { - const_iterator result(lhs); - result += offset; - return result; - } - - //*************************************************** - friend const_iterator operator -(const const_iterator& lhs, difference_type offset) - { - const_iterator result(lhs); - result -= offset; - return result; - } - - //*************************************************** - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.index == rhs.index; - } - - //*************************************************** - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - //*************************************************** - difference_type get_index() const - { - return index; - } - - //*************************************************** - ideque& get_deque() const - { - return *p_deque; - } - - //*************************************************** - pointer get_buffer() const - { - return p_buffer; - } - - //*************************************************** - void swap(const_iterator& other) - { - std::swap(index, other.index); - } - - private: - - //*************************************************** - difference_type distance(difference_type firstIndex, difference_type index) - { - if (index < firstIndex) - { - return p_deque->BUFFER_SIZE + index - firstIndex; - } - else - { - return index - firstIndex; - } - } - - //*************************************************** - const_iterator(difference_type index, ideque& the_deque, pointer p_buffer) - : index(index), - p_deque(&the_deque), - p_buffer(p_buffer) - { - } - - difference_type index; - ideque* p_deque; - pointer p_buffer; - }; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - //************************************************************************* - /// Assigns a range to the deque. - //************************************************************************* - template - typename etl::enable_if::value, void>::type - assign(TIterator range_begin, TIterator range_end) - { - initialise(); - - while (range_begin != range_end) - { - push_back(*range_begin++); - } - } - - //************************************************************************* - /// Assigns 'n' copies of a value to the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full is 'n' is too large. - ///\param n The number of copies to assign. - ///\param value The value to add.< - //************************************************************************* - void assign(size_type n, const value_type& value) - { - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(deque_full)); - - initialise(); - - _begin.index = 0; - _end.index = 0; - - while (n > 0) - { - create_element_back(value); - --n; - } - } - - //************************************************************************* - /// Gets a reference to the item at the index. - /// If asserts or exceptions are enabled, throws an etl::deque_out_of_bounds if the index is out of range. - ///\return A reference to the item at the index. - //************************************************************************* - reference at(size_t index) - { - ETL_ASSERT(index < current_size, ETL_ERROR(deque_out_of_bounds)); - - iterator result(_begin); - result += index; - - return *result; - } - - //************************************************************************* - /// Gets a const reference to the item at the index. - /// If asserts or exceptions are enabled, throws an etl::deque_out_of_bounds if the index is out of range. - ///\return A const reference to the item at the index. - //************************************************************************* - const_reference at(size_t index) const - { - ETL_ASSERT(index < current_size, ETL_ERROR(deque_out_of_bounds)); - - iterator result(_begin); - result += index; - - return *result; - } - - //************************************************************************* - /// Gets a reference to the item at the index. - ///\return A reference to the item at the index. - //************************************************************************* - reference operator [](size_t index) - { - iterator result(_begin); - result += index; - - return *result; - } - - //************************************************************************* - /// Gets a const reference to the item at the index. - ///\return A const reference to the item at the index. - //************************************************************************* - const_reference operator [](size_t index) const - { - iterator result(_begin); - result += index; - - return *result; - } - - //************************************************************************* - /// Gets a reference to the item at the front of the deque. - ///\return A reference to the item at the front of the deque. - //************************************************************************* - reference front() - { - return *_begin; - } - - //************************************************************************* - /// Gets a const reference to the item at the front of the deque. - ///\return A const reference to the item at the front of the deque. - //************************************************************************* - const_reference front() const - { - return *_begin; - } - - //************************************************************************* - /// Gets a reference to the item at the back of the deque. - ///\return A reference to the item at the back of the deque. - //************************************************************************* - reference back() - { - return *(_end - 1); - } - - //************************************************************************* - /// Gets a const reference to the item at the back of the deque. - ///\return A const reference to the item at the back of the deque. - //************************************************************************* - const_reference back() const - { - return *(_end - 1); - } - - //************************************************************************* - /// Gets an iterator to the beginning of the deque. - //************************************************************************* - iterator begin() - { - return _begin; - } - - //************************************************************************* - /// Gets a const iterator to the beginning of the deque. - //************************************************************************* - const_iterator begin() const - { - return _begin; - } - - //************************************************************************* - /// Gets a const iterator to the beginning of the deque. - //************************************************************************* - const_iterator cbegin() const - { - return _begin; - } - - //************************************************************************* - /// Gets an iterator to the end of the deque. - //************************************************************************* - iterator end() - { - return iterator(_end); - } - - //************************************************************************* - /// Gets a const iterator to the end of the deque. - //************************************************************************* - const_iterator end() const - { - return iterator(_end); - } - - //************************************************************************* - /// Gets a const iterator to the end of the deque. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(_end); - } - - //************************************************************************* - /// Gets a reverse iterator to the end of the deque. - //************************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(end()); - } - - //************************************************************************* - /// Gets a const reverse iterator to the end of the deque. - //************************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(end()); - } - - //************************************************************************* - /// Gets a const reverse iterator to the end of the deque. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(cend()); - } - - //************************************************************************* - /// Gets a reverse iterator to the beginning of the deque. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(begin()); - } - - //************************************************************************* - /// Gets a const reverse iterator to the beginning of the deque. - //************************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(begin()); - } - - //************************************************************************* - /// Gets a const reverse iterator to the beginning of the deque. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(cbegin()); - } - - //************************************************************************* - /// Clears the deque. - //************************************************************************* - void clear() - { - initialise(); - } - - //************************************************************************* - /// Inserts data into the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full. - ///\param insert_position>The insert position. - ///\param value>The value to insert. - //************************************************************************* - iterator insert(const_iterator insert_position, const value_type& value) - { - iterator position(insert_position.index, *this, p_buffer); - - ETL_ASSERT(!full(), ETL_ERROR(deque_full)); - - if (insert_position == begin()) - { - create_element_front(value); - position = _begin; - } - else if (insert_position == end()) - { - create_element_back(value); - position = _end - 1; - } - else - { - // Are we closer to the front? - if (std::distance(_begin, position) < std::distance(position, _end - 1)) - { - // Construct the _begin. - create_element_front(*_begin); - - // Move the values. - std::copy(_begin + 1, position, _begin); - - // Write the new value. - *--position = value; - } - else - { - // Construct the _end. - create_element_back(*(_end - 1)); - - // Move the values. - std::copy_backward(position, _end - 2, _end - 1); - - // Write the new value. - *position = value; - } - } - - return position; - } - - //************************************************************************* - /// Inserts 'n' copies of a value into the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is full. - ///\param insert_position The insert position. - ///\param n The number of values to insert. - ///\param value The value to insert. - //************************************************************************* - iterator insert(const_iterator insert_position, size_type n, const value_type& value) - { - iterator position; - - ETL_ASSERT((current_size + n) <= MAX_SIZE, ETL_ERROR(deque_full)); - - if (insert_position == begin()) - { - for (size_t i = 0; i < n; ++i) - { - create_element_front(value); - } - - position = _begin; - } - else if (insert_position == end()) - { - for (size_t i = 0; i < n; ++i) - { - create_element_back(value); - } - - position = _end - n; - } - else - { - // Non-const insert iterator. - position = iterator(insert_position.index, *this, p_buffer); - - // Are we closer to the front? - if (distance(_begin, insert_position) <= difference_type(current_size / 2)) - { - size_t n_insert = n; - size_t n_move = std::distance(begin(), position); - size_t n_create_copy = std::min(n_insert, n_move); - size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0; - size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0; - size_t n_copy_old = n_move - n_create_copy; - - // Remember the original start. - iterator from = _begin + n_create_copy - 1; - iterator to; - - // Create new. - for (size_t i = 0; i < n_create_new; ++i) - { - create_element_front(value); - } - - // Create copy. - for (size_t i = 0; i < n_create_copy; ++i) - { - create_element_front(*from--); - } - - // Copy old. - from = position - n_copy_old; - 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 = _begin + n_move; - } - else - { - size_t n_insert = n; - size_t n_move = std::distance(position, end()); - size_t n_create_copy = std::min(n_insert, n_move); - size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0; - size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0; - size_t n_copy_old = n_move - n_create_copy; - - // Create new. - for (size_t i = 0; i < n_create_new; ++i) - { - create_element_back(value); - } - - // Create copy. - const_iterator from = position + n_copy_old; - - for (size_t i = 0; i < n_create_copy; ++i) - { - create_element_back(*from++); - } - - // Copy old. - std::copy_backward(position, position + n_copy_old, position + n_insert + n_copy_old); - - // Copy new. - std::fill_n(position, n_copy_new, value); - } - } - - return position; - } - - //************************************************************************* - /// Inserts a range into the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_empty if the deque is full. - ///\param insert_position>The insert position. - ///\param range_begin The beginning of the range to insert. - ///\param range_end The end of the range to insert. - //************************************************************************* - template - typename enable_if::value, iterator>::type - insert(const_iterator insert_position, TIterator range_begin, TIterator range_end) - { - iterator position; - - difference_type n = std::distance(range_begin, range_end); - - ETL_ASSERT((current_size + n) <= MAX_SIZE, ETL_ERROR(deque_full)); - - if (insert_position == begin()) - { - create_element_front(n, range_begin); - - position = _begin; - } - else if (insert_position == end()) - { - for (difference_type i = 0; i < n; ++i) - { - create_element_back(*range_begin++); - } - - position = _end - n; - } - else - { - // Non-const insert iterator. - position = iterator(insert_position.index, *this, p_buffer); - - // Are we closer to the front? - if (distance(_begin, insert_position) < difference_type(current_size / 2)) - { - size_t n_insert = n; - size_t n_move = std::distance(begin(), position); - size_t n_create_copy = std::min(n_insert, n_move); - size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0; - size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0; - size_t n_copy_old = n_move - n_create_copy; - - // Remember the original start. - iterator from; - iterator to; - - // Create new. - create_element_front(n_create_new, range_begin); - - // Create copy. - create_element_front(n_create_copy, _begin + n_create_new); - - // Copy old. - from = position - n_copy_old; - to = _begin + n_create_copy; - etl::copy_n(from, n_copy_old, to); - - // Copy new. - to = position - n_create_copy; - range_begin += n_create_new; - etl::copy_n(range_begin, n_copy_new, to); - - position = _begin + n_move; - } - else - { - size_t n_insert = n; - size_t n_move = std::distance(position, end()); - size_t n_create_copy = std::min(n_insert, n_move); - size_t n_create_new = (n_insert > n_create_copy) ? n_insert - n_create_copy : 0; - size_t n_copy_new = (n_insert > n_create_new) ? n_insert - n_create_new : 0; - size_t n_copy_old = n_move - n_create_copy; - - // Create new. - TIterator item = range_begin + (n - n_create_new); - for (size_t i = 0; i < n_create_new; ++i) - { - create_element_back(*item++); - } - - // Create copy. - const_iterator from = position + n_copy_old; - - for (size_t i = 0; i < n_create_copy; ++i) - { - create_element_back(*from++); - } - - // Copy old. - std::copy_backward(position, position + n_copy_old, position + n_insert + n_copy_old); - - // Copy new. - item = range_begin; - etl::copy_n(item, n_copy_new, position); - } - } - - return position; - } - - //************************************************************************* - /// Erase an item. - /// If asserts or exceptions are enabled, throws an etl::deque_out_of_bounds if the position is out of range. - ///\param erase_position The position to erase. - //************************************************************************* - iterator erase(const_iterator erase_position) - { - iterator position(erase_position.index, *this, p_buffer); - - ETL_ASSERT(distance(position) <= difference_type(current_size), ETL_ERROR(deque_out_of_bounds)); - - if (position == _begin) - { - destroy_element_front(); - position = begin(); - } - else if (position == _end - 1) - { - destroy_element_back(); - position = end(); - } - else - { - // Are we closer to the front? - if (distance(_begin, position) < difference_type(current_size / 2)) - { - std::copy_backward(_begin, position, position + 1); - destroy_element_front(); - ++position; - } - else - { - std::copy(position + 1, _end, position); - destroy_element_back(); - } - } - - return position; - } - - //************************************************************************* - /// erase a range. - /// If asserts or exceptions are enabled, throws an etl::deque_out_of_bounds if the iterators are out of range. - ///\param range_begin The beginning of the range to erase. - ///\param range_end The end of the range to erase. - //************************************************************************* - iterator erase(const_iterator range_begin, const_iterator range_end) - { - iterator position(range_begin.index, *this, p_buffer); - - ETL_ASSERT((distance(range_begin) <= difference_type(current_size)) && (distance(range_end) <= difference_type(current_size)), ETL_ERROR(deque_out_of_bounds)); - - // How many to erase? - size_t length = std::distance(range_begin, range_end); - - // At the beginning? - if (position == _begin) - { - for (size_t i = 0; i < length; ++i) - { - destroy_element_front(); - } - - position = begin(); - } - // At the end? - else if (position == _end - length) - { - for (size_t i = 0; i < length; ++i) - { - destroy_element_back(); - } - - position = end(); - } - else - { - // Copy the smallest number of items. - // Are we closer to the front? - if (distance(_begin, position) < difference_type(current_size / 2)) - { - // Move the items. - std::copy_backward(_begin, position, position + length); - - for (size_t i = 0; i < length; ++i) - { - destroy_element_front(); - } - - position += length; - } - else - // Must be closer to the back. - { - // Move the items. - std::copy(position + length, _end, position); - - for (size_t i = 0; i < length; ++i) - { - destroy_element_back(); - } - } - } - - return position; - } - - //************************************************************************* - /// Adds an item to the back of the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full. - ///\param item The item to push to the deque. - //************************************************************************* - void push_back(parameter_t item) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(deque_full)); -#endif - create_element_back(item); - } - - //************************************************************************* - /// Adds one to the front of the deque and returns a reference to the new element. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full. - ///\return A reference to the item to assign to. - //************************************************************************* - reference push_back() - { - reference r = *_end; -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(deque_full)); -#endif - create_element_back(); - - return r; - } - - //************************************************************************* - /// Removes the oldest item from the deque. - //************************************************************************* - void pop_back() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(deque_empty)); -#endif - destroy_element_back(); - } - - //************************************************************************* - /// Adds an item to the front of the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full. - ///\param item The item to push to the deque. - //************************************************************************* - void push_front(parameter_t item) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(deque_full)); -#endif - create_element_front(item); - } - - //************************************************************************* - /// Adds one to the front of the deque and returns a reference to the new element. - /// If asserts or exceptions are enabled, throws an etl::deque_full if the deque is already full. - ///\return A reference to the item to assign to. - //************************************************************************* - reference push_front() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(deque_full)); -#endif - create_element_front(); - - return *_begin; - } - - //************************************************************************* - /// Removes the oldest item from the deque. - //************************************************************************* - void pop_front() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(deque_empty)); -#endif - destroy_element_front(); - } - - //************************************************************************* - /// Resizes the deque. - /// If asserts or exceptions are enabled, throws an etl::deque_full is 'new_size' is too large. - ///\param new_size The new size of the deque. - ///\param value The value to assign if the new size is larger. Default = Default constructed value. - //************************************************************************* - void resize(size_t new_size, const value_type& value = value_type()) - { - ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(deque_out_of_bounds)); - - // Make it smaller? - if (new_size < current_size) - { - while (current_size > new_size) - { - destroy_element_back(); - } - } - // Make it larger? - else if (new_size > current_size) - { - size_t count = new_size - current_size; - - for (size_t i = 0; i < count; ++i) - { - create_element_back(value); - } - } - } - - //************************************************************************* - /// - operator for iterator - //************************************************************************* - friend difference_type operator -(const iterator& lhs, const iterator& rhs) - { - return distance(rhs, lhs); - } - - //************************************************************************* - /// - operator for const_iterator - //************************************************************************* - friend difference_type operator -(const const_iterator& lhs, const const_iterator& rhs) - { - return distance(rhs, lhs); - } - - //************************************************************************* - /// - operator for reverse_iterator - //************************************************************************* - friend difference_type operator -(const reverse_iterator& lhs, const reverse_iterator& rhs) - { - return distance(lhs.base(), rhs.base()); - } - - //************************************************************************* - /// - operator for const_reverse_iterator - //************************************************************************* - friend difference_type operator -(const const_reverse_iterator& lhs, const const_reverse_iterator& rhs) - { - return distance(lhs.base(), rhs.base()); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ideque& operator =(const ideque& rhs) - { - if (&rhs != this) - { - assign(rhs.begin(), rhs.end()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - ideque(pointer p_buffer, size_t max_size, size_t buffer_size) - : deque_base(max_size, buffer_size), - p_buffer(p_buffer) - { - } - - //********************************************************************* - /// Initialise the deque. - //********************************************************************* - void initialise() - { - while (current_size > 0) - { - destroy_element_back(); - } - - _begin = iterator(0, *this, p_buffer); - _end = iterator(0, *this, p_buffer); - } - - 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: - - //********************************************************************* - /// Create a new element with a default value at the front. - //********************************************************************* - void create_element_front() - { - --_begin; - ::new (&(*_begin)) T(); - ++current_size; - ++construct_count; - } - - //********************************************************************* - /// Create a new elements from a range at the front. - //********************************************************************* - template - void create_element_front(size_t n, TIterator from) - { - if (n == 0) - { - return; - } - - if (!empty()) - { - --_begin; - --n; - } - - if (n > 0) - { - _begin -= n; - } - - iterator item = _begin; - - do - { - ::new (&(*item++)) T(*from); - ++from; - ++current_size; - ++construct_count; - } while (n-- != 0); - } - - //********************************************************************* - /// Create a new element with a default value at the back. - //********************************************************************* - void create_element_back() - { - ::new (&(*_end)) T(); - ++_end; - ++current_size; - ++construct_count; - } - - //********************************************************************* - /// Create a new element with a default value at the front. - //********************************************************************* - void create_element_front(parameter_t value) - { - --_begin; - ::new (&(*_begin)) T(value); - ++current_size; - ++construct_count; - } - - //********************************************************************* - /// Create a new element with a value at the back - //********************************************************************* - void create_element_back(parameter_t value) - { - ::new (&(*_end)) T(value); - ++_end; - ++current_size; - ++construct_count; - } - - //********************************************************************* - /// Destroy an element at the front. - //********************************************************************* - void destroy_element_front() - { - (*_begin).~T(); - --current_size; - --construct_count; - ++_begin; - } - - //********************************************************************* - /// Destroy an element at the back. - //********************************************************************* - void destroy_element_back() - { - --_end; - (*_end).~T(); - --current_size; - --construct_count; - } - - //************************************************************************* - /// Measures the distance between two iterators. - //************************************************************************* - template - static difference_type distance(const TIterator1& range_begin, const TIterator2& range_end) - { - difference_type distance1 = distance(range_begin); - difference_type distance2 = distance(range_end); - - return distance2 - distance1; - } - - //************************************************************************* - /// Measures the distance from the _begin iterator to the specified iterator. - //************************************************************************* - template - static difference_type distance(const TIterator& other) - { - const difference_type index = other.get_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) - { - return buffer_size + index - reference_index; - } - else - { - return index - reference_index; - } - } - - // Disable copy construction. - ideque(const ideque&); - }; -} - -//*************************************************************************** -/// Equal operator. -///\param lhs Reference to the _begin deque. -///\param rhs Reference to the second deque. -///\return true if the arrays are equal, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator ==(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//*************************************************************************** -/// Not equal operator. -///\param lhs Reference to the _begin deque. -///\param rhs Reference to the second deque. -///\return true if the arrays are not equal, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator !=(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return !(lhs == rhs); -} - -//*************************************************************************** -/// Less than operator. -///\param lhs Reference to the _begin deque. -///\param rhs Reference to the second deque. -///\return true if the _begin deque is lexicographically less than the second, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator <(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return std::lexicographical_compare(lhs.begin(), - lhs.end(), - rhs.begin(), - rhs.end()); -} - -//*************************************************************************** -/// Less than or equal operator. -///\param lhs Reference to the _begin deque. -///\param rhs Reference to the second deque. -///\return true if the _begin deque is lexicographically less than or equal to the second, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator <=(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return !(lhs > rhs); -} - -//*************************************************************************** -/// Greater than operator. -///\param lhs Reference to the _begin deque. -///\param rhs Reference to the second deque. -///\return true if the _begin deque is lexicographically greater than the second, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator >(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return (rhs < lhs); -} - -//*************************************************************************** -/// Greater than or equal operator. -///\param "lhs Reference to the _begin deque. -///\param "rhs Reference to the second deque. -///\return true if the _begin deque is lexicographically greater than or equal to the second, otherwise false -///\ingroup deque -//*************************************************************************** -template -bool operator >=(const etl::ideque& lhs, const etl::ideque& rhs) -{ - return !(lhs < rhs); -} - -#undef __ETL_IN_IDEQUE_H__ - -#endif diff --git a/src/iflat_map.h b/src/iflat_map.h deleted file mode 100644 index fa831db1..00000000 --- a/src/iflat_map.h +++ /dev/null @@ -1,864 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IFLAT_MAP__ -#define __ETL_IFLAT_MAP__ -#define __ETL_IN_IFLAT_MAP_H__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "private/flat_map_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "ivector.h" -#include "ipool.h" -#include "error_handler.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized flat_maps. - /// Can be used as a reference type for all flat_maps containing a specific type. - ///\ingroup flat_map - //*************************************************************************** - template > - class iflat_map : public flat_map_base - { - public: - - typedef std::pair value_type; - - private: - - typedef etl::ivector lookup_t; - typedef etl::ipool storage_t; - - public: - - typedef TKey key_type; - typedef TMapped mapped_type; - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iflat_map; - - iterator() - { - } - - iterator(typename lookup_t::iterator ilookup) - : ilookup(ilookup) - { - } - - iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - iterator& operator ++() - { - ++ilookup; - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - ++ilookup; - return temp; - } - - iterator& operator --() - { - --ilookup; - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - --ilookup; - return temp; - } - - reference operator *() - { - return *(*ilookup); - } - - const_reference operator *() const - { - return *(*ilookup); - } - - pointer operator &() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator &() const - { - return &(*(*ilookup)); - } - - pointer operator ->() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::iterator ilookup; - }; - - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iflat_map; - - const_iterator() - { - } - - const_iterator(typename lookup_t::const_iterator ilookup) - : ilookup(ilookup) - { - } - - const_iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator(const const_iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator =(const const_iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator ++() - { - ++ilookup; - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - ++ilookup; - return temp; - } - - const_iterator& operator --() - { - --ilookup; - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - --ilookup; - return temp; - } - - const_reference operator *() const - { - return *(*ilookup); - } - - const_pointer operator &() const - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::const_iterator ilookup; - }; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef typename std::iterator_traits::difference_type difference_type; - - protected: - - typedef typename parameter_type::type key_value_parameter_t; - - private: - - //********************************************************************* - /// How to compare elements and keys. - //********************************************************************* - class compare - { - public: - - bool operator ()(const value_type& element, key_type key) const - { - return key_compare()(element.first, key); - } - - bool operator ()(key_type key, const value_type& element) const - { - return key_compare()(key, element.first); - } - }; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the flat_map. - ///\return An iterator to the beginning of the flat_map. - //********************************************************************* - iterator begin() - { - return iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_map. - ///\return A const iterator to the beginning of the flat_map. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the flat_map. - ///\return An iterator to the end of the flat_map. - //********************************************************************* - iterator end() - { - return iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_map. - ///\return A const iterator to the end of the flat_map. - //********************************************************************* - const_iterator end() const - { - return const_iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_map. - ///\return A const iterator to the beginning of the flat_map. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(lookup.cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_map. - ///\return A const iterator to the end of the flat_map. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(lookup.cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the flat_map. - ///\return Iterator to the reverse beginning of the flat_map. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_map. - ///\return Const iterator to the reverse beginning of the flat_map. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the flat_map. - ///\return Reverse iterator to the end + 1 of the flat_map. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_map. - ///\return Const reverse iterator to the end + 1 of the flat_map. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_map. - ///\return Const reverse iterator to the reverse beginning of the flat_map. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(lookup.crbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_map. - ///\return Const reverse iterator to the end + 1 of the flat_map. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(lookup.crend()); - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - ///\param i The index. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& operator [](key_value_parameter_t key) - { - iterator i_element = lower_bound(key); - - if (i_element == end()) - { - std::pair result = insert_at(i_element, value_type(key, mapped_type())); - - i_element = result.first; - } - - return i_element->second; - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::flat_map_out_of_bounds if the key is not in the range. - ///\param i The index. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& at(key_value_parameter_t key) - { - iterator i_element = lower_bound(key); - - ETL_ASSERT(i_element != end(), ETL_ERROR(flat_map_out_of_bounds)); - - return i_element->second; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::flat_map_out_of_bounds if the key is not in the range. - ///\param i The index. - ///\return A const reference to the value at index 'key' - //********************************************************************* - const mapped_type& at(key_value_parameter_t key) const - { - const_iterator i_element = lower_bound(key); - - ETL_ASSERT(i_element != end(), ETL_ERROR(flat_map_out_of_bounds)); - - return i_element->second; - } - - //********************************************************************* - /// Assigns values to the flat_map. - /// 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. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_map_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the flat_map. - /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& value) - { - iterator i_element = lower_bound(value.first); - - return insert_at(i_element, value); - } - - //********************************************************************* - /// Inserts a value to the flat_map. - /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator position, const value_type& value) - { - return insert(value).first; - } - - //********************************************************************* - /// Inserts a range of values to the flat_map. - /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - iterator i_element = find(key); - - if (i_element == end()) - { - return 0; - } - else - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - return 1; - } - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - //********************************************************************* - void erase(iterator i_element) - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - void erase(iterator first, iterator last) - { - iterator itr = first; - - while (itr != last) - { - itr->~value_type(); - storage.release(etl::addressof(*itr)); - ++itr; - --construct_count; - } - - lookup.erase(first.ilookup, last.ilookup); - } - - //************************************************************************* - /// Clears the flat_map. - //************************************************************************* - void clear() - { - erase(begin(), end()); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(key_value_parameter_t key) - { - iterator itr = lower_bound(key); - - if (itr != end()) - { - if (!key_compare()(itr->first, key) && !key_compare()(key, itr->first)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - const_iterator itr = lower_bound(key); - - if (itr != end()) - { - if (!key_compare()(itr->first, key) && !key_compare()(key, itr->first)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - return (find(key) == end()) ? 0 : 1; - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator lower_bound(key_value_parameter_t key) - { - return std::lower_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator lower_bound(key_value_parameter_t key) const - { - return std::lower_bound(cbegin(), cend(), key, compare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator upper_bound(key_value_parameter_t key) - { - return std::upper_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator upper_bound(key_value_parameter_t key) const - { - return std::upper_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(key_value_parameter_t key) - { - iterator i_lower = std::lower_bound(begin(), end(), key, compare()); - - return std::make_pair(i_lower, std::upper_bound(i_lower, end(), key, compare())); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(key_value_parameter_t key) const - { - const_iterator i_lower = std::lower_bound(cbegin(), cend(), key, compare()); - - return std::make_pair(i_lower, std::upper_bound(i_lower, cend(), key, compare())); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iflat_map& operator = (const iflat_map& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the current size of the flat_map. - ///\return The current size of the flat_map. - //************************************************************************* - size_type size() const - { - return lookup.size(); - } - - //************************************************************************* - /// Checks the 'empty' state of the flat_map. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return lookup.empty(); - } - - //************************************************************************* - /// Checks the 'full' state of the flat_map. - ///\return true if full. - //************************************************************************* - bool full() const - { - return lookup.full(); - } - - //************************************************************************* - /// Returns the capacity of the flat_map. - ///\return The capacity of the flat_map. - //************************************************************************* - size_type capacity() const - { - return lookup.capacity(); - } - - //************************************************************************* - /// Returns the maximum possible size of the flat_map. - ///\return The maximum size of the flat_map. - //************************************************************************* - size_type max_size() const - { - return lookup.max_size(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return lookup.available(); - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iflat_map(lookup_t& lookup_, storage_t& storage_) - : lookup(lookup_), - storage(storage_) - { - } - - private: - - //********************************************************************* - /// Inserts a value to the flat_map. - ///\param i_element The place to insert. - ///\param value The value to insert. - //********************************************************************* - std::pair insert_at(iterator i_element, const value_type& value) - { - std::pair result(end(), false); - - if (i_element == end()) - { - // At the end. - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_map_full)); - - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.push_back(pvalue); - result.first = --end(); - result.second = true; - ++construct_count; - } - else - { - // Not at the end. - result.first = i_element; - - // Existing element? - if (value.first != i_element->first) - { - // A new one. - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_map_full)); - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.insert(i_element.ilookup, pvalue); - result.second = true; - ++construct_count; - } - } - - return result; - } - - // Disable copy construction. - iflat_map(const iflat_map&); - - lookup_t& lookup; - storage_t& storage; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first flat_map. - ///\param rhs Reference to the second flat_map. - ///\return true if the arrays are equal, otherwise false - ///\ingroup flat_map - //*************************************************************************** - template - bool operator ==(const etl::iflat_map& lhs, const etl::iflat_map& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first flat_map. - ///\param rhs Reference to the second flat_map. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup flat_map - //*************************************************************************** - template - bool operator !=(const etl::iflat_map& lhs, const etl::iflat_map& rhs) - { - return !(lhs == rhs); - } -} - -#undef __ETL_IN_IFLAT_MAP_H__ -#endif diff --git a/src/iflat_multimap.h b/src/iflat_multimap.h deleted file mode 100644 index 38e17715..00000000 --- a/src/iflat_multimap.h +++ /dev/null @@ -1,810 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IFLAT_MULTIMAP__ -#define __ETL_IFLAT_MULTIMAP__ -#define __ETL_IN_IFLAT_MULTIMAP_H__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "private/flat_multimap_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "ivector.h" -#include "error_handler.h" -#include "ipool.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized flat_multimaps. - /// Can be used as a reference type for all flat_multimaps containing a specific type. - ///\ingroup flat_multimap - //*************************************************************************** - template > - class iflat_multimap : public flat_multimap_base - { - public: - - typedef std::pair value_type; - - private: - - typedef etl::ivector lookup_t; - typedef etl::ipool storage_t; - - public: - - typedef TKey key_type; - typedef TMapped mapped_type; - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iflat_multimap; - - iterator() - { - } - - iterator(typename lookup_t::iterator ilookup) - : ilookup(ilookup) - { - } - - iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - iterator& operator ++() - { - ++ilookup; - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - ++ilookup; - return temp; - } - - iterator& operator --() - { - --ilookup; - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - --ilookup; - return temp; - } - - reference operator *() - { - return *(*ilookup); - } - - const_reference operator *() const - { - return *(*ilookup); - } - - pointer operator &() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator &() const - { - return &(*(*ilookup)); - } - - pointer operator ->() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::iterator ilookup; - }; - - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iflat_multimap; - - const_iterator() - { - } - - const_iterator(typename lookup_t::const_iterator ilookup) - : ilookup(ilookup) - { - } - - const_iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator(const const_iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator =(const const_iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator ++() - { - ++ilookup; - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - ++ilookup; - return temp; - } - - const_iterator& operator --() - { - --ilookup; - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - --ilookup; - return temp; - } - - const_reference operator *() const - { - return *(*ilookup); - } - - const_pointer operator &() const - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::const_iterator ilookup; - }; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef typename std::iterator_traits::difference_type difference_type; - - protected: - - typedef typename parameter_type::type key_value_parameter_t; - - private: - - //********************************************************************* - /// How to compare elements and keys. - //********************************************************************* - class compare - { - public: - - bool operator ()(const value_type& element, key_type key) const - { - return key_compare()(element.first, key); - } - - bool operator ()(key_type key, const value_type& element) const - { - return key_compare()(key, element.first); - } - }; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the flat_multimap. - ///\return An iterator to the beginning of the flat_multimap. - //********************************************************************* - iterator begin() - { - return iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_multimap. - ///\return A const iterator to the beginning of the flat_multimap. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the flat_multimap. - ///\return An iterator to the end of the flat_multimap. - //********************************************************************* - iterator end() - { - return iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_multimap. - ///\return A const iterator to the end of the flat_multimap. - //********************************************************************* - const_iterator end() const - { - return const_iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_multimap. - ///\return A const iterator to the beginning of the flat_multimap. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(lookup.cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_multimap. - ///\return A const iterator to the end of the flat_multimap. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(lookup.cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the flat_multimap. - ///\return Iterator to the reverse beginning of the flat_multimap. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_multimap. - ///\return Const iterator to the reverse beginning of the flat_multimap. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the flat_multimap. - ///\return Reverse iterator to the end + 1 of the flat_multimap. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_multimap. - ///\return Const reverse iterator to the end + 1 of the flat_multimap. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_multimap. - ///\return Const reverse iterator to the reverse beginning of the flat_multimap. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(lookup.crbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_multimap. - ///\return Const reverse iterator to the end + 1 of the flat_multimap. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(lookup.crend()); - } - - //********************************************************************* - /// Assigns values to the flat_multimap. - /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap does not have enough free space. - /// If asserts or exceptions are enabled, emits flat_multimap_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_multimap_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the flat_multimap. - /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& value) - { - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multimap_full)); - -std::pair result(end(), false); - - iterator i_element = lower_bound(value.first); - - return insert_at(i_element, value); - } - - //********************************************************************* - /// Inserts a value to the flast_multi. - /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator position, const value_type& value) - { - return insert(value).first; - } - - //********************************************************************* - /// Inserts a range of values to the flat_multimap. - /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - std::pair range = equal_range(key); - - if (range.first == end()) - { - return 0; - } - else - { - size_t count = std::distance(range.first, range.second); - erase(range.first, range.second); - return count; - } - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - //********************************************************************* - void erase(iterator i_element) - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - void erase(iterator first, iterator last) - { - iterator itr = first; - - while (itr != last) - { - itr->~value_type(); - storage.release(etl::addressof(*itr)); - ++itr; - --construct_count; - } - - lookup.erase(first.ilookup, last.ilookup); - } - - //************************************************************************* - /// Clears the flat_multimap. - //************************************************************************* - void clear() - { - erase(begin(), end()); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(key_value_parameter_t key) - { - iterator itr = lower_bound(key); - - if (itr != end()) - { - if (!key_compare()(itr->first, key) && !key_compare()(key, itr->first)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - const_iterator itr = lower_bound(key); - - if (itr != end()) - { - if (!key_compare()(itr->first, key) && !key_compare()(key, itr->first)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - std::pair range = equal_range(key); - - return std::distance(range.first, range.second); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator lower_bound(key_value_parameter_t key) - { - return std::lower_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator lower_bound(key_value_parameter_t key) const - { - return std::lower_bound(cbegin(), cend(), key, compare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator upper_bound(key_value_parameter_t key) - { - return std::upper_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator upper_bound(key_value_parameter_t key) const - { - return std::upper_bound(begin(), end(), key, compare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(key_value_parameter_t key) - { - iterator i_lower = std::lower_bound(begin(), end(), key, compare()); - - return std::make_pair(i_lower, std::upper_bound(i_lower, end(), key, compare())); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(key_value_parameter_t key) const - { - const_iterator i_lower = std::lower_bound(cbegin(), cend(), key, compare()); - - return std::make_pair(i_lower, std::upper_bound(i_lower, cend(), key, compare())); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iflat_multimap& operator = (const iflat_multimap& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the current size of the flat_multiset. - ///\return The current size of the flat_multiset. - //************************************************************************* - size_type size() const - { - return lookup.size(); - } - - //************************************************************************* - /// Checks the 'empty' state of the flat_multiset. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return lookup.empty(); - } - - //************************************************************************* - /// Checks the 'full' state of the flat_multiset. - ///\return true if full. - //************************************************************************* - bool full() const - { - return lookup.full(); - } - - //************************************************************************* - /// Returns the capacity of the flat_multiset. - ///\return The capacity of the flat_multiset. - //************************************************************************* - size_type capacity() const - { - return lookup.capacity(); - } - - //************************************************************************* - /// Returns the maximum possible size of the flat_multiset. - ///\return The maximum size of the flat_multiset. - //************************************************************************* - size_type max_size() const - { - return lookup.max_size(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return lookup.available(); - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iflat_multimap(lookup_t& lookup_, storage_t& storage_) - : lookup(lookup_), - storage(storage_) - { - } - - private: - - //********************************************************************* - /// Inserts a value to the flat_multimap. - ///\param i_element The place to insert. - ///\param value The value to insert. - //********************************************************************* - std::pair insert_at(iterator i_element, const value_type& value) - { - std::pair result(end(), false); - - if (i_element == end()) - { - // At the end. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.push_back(pvalue); - result.first = --end(); - result.second = true; - } - else - { - // Not at the end. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.insert(i_element.ilookup, pvalue); - result.first = i_element; - result.second = true; - } - - ++construct_count; - - return result; - } - - // Disable copy construction. - iflat_multimap(const iflat_multimap&); - - lookup_t& lookup; - storage_t& storage; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first flat_multimap. - ///\param rhs Reference to the second flat_multimap. - ///\return true if the arrays are equal, otherwise false - ///\ingroup flat_multimap - //*************************************************************************** - template - bool operator ==(const etl::iflat_multimap& lhs, const etl::iflat_multimap& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first flat_multimap. - ///\param rhs Reference to the second flat_multimap. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup flat_multimap - //*************************************************************************** - template - bool operator !=(const etl::iflat_multimap& lhs, const etl::iflat_multimap& rhs) - { - return !(lhs == rhs); - } -} - -#undef __ETL_IN_IFLAT_MULTIMAP_H__ -#endif diff --git a/src/iflat_multiset.h b/src/iflat_multiset.h deleted file mode 100644 index a33e593b..00000000 --- a/src/iflat_multiset.h +++ /dev/null @@ -1,774 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IFLAT_MULTISET__ -#define __ETL_IFLAT_MULTISET__ -#define __ETL_IN_IFLAT_MULTISET_H__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "private/flat_multiset_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "ivector.h" -#include "error_handler.h" -#include "ipool.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized flat_multisets. - /// Can be used as a reference type for all flat_multisets containing a specific type. - ///\ingroup flat_multiset - //*************************************************************************** - template > - class iflat_multiset : public flat_multiset_base - { - public: - - typedef T key_type; - typedef T value_type; - - private: - - typedef etl::ivector lookup_t; - typedef etl::ipool storage_t; - - public: - - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iflat_multiset; - - iterator() - { - } - - iterator(typename lookup_t::iterator ilookup) - : ilookup(ilookup) - { - } - - iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - iterator& operator ++() - { - ++ilookup; - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - ++ilookup; - return temp; - } - - iterator& operator --() - { - --ilookup; - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - --ilookup; - return temp; - } - - reference operator *() - { - return *(*ilookup); - } - - const_reference operator *() const - { - return *(*ilookup); - } - - pointer operator &() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator &() const - { - return &(*(*ilookup)); - } - - pointer operator ->() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::iterator ilookup; - }; - - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iflat_multiset; - - const_iterator() - { - } - - const_iterator(typename lookup_t::const_iterator ilookup) - : ilookup(ilookup) - { - } - - const_iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator(const const_iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator =(const const_iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator ++() - { - ++ilookup; - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - ++ilookup; - return temp; - } - - const_iterator& operator --() - { - --ilookup; - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - --ilookup; - return temp; - } - - const_reference operator *() const - { - return *(*ilookup); - } - - const_pointer operator &() const - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::const_iterator ilookup; - }; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef typename std::iterator_traits::difference_type difference_type; - - - protected: - - typedef typename parameter_type::type parameter_t; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the flat_multiset. - ///\return An iterator to the beginning of the flat_multiset. - //********************************************************************* - iterator begin() - { - return iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_multiset. - ///\return A const iterator to the beginning of the flat_multiset. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the flat_multiset. - ///\return An iterator to the end of the flat_multiset. - //********************************************************************* - iterator end() - { - return iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_multiset. - ///\return A const iterator to the end of the flat_multiset. - //********************************************************************* - const_iterator end() const - { - return const_iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_multiset. - ///\return A const iterator to the beginning of the flat_multiset. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(lookup.cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_multiset. - ///\return A const iterator to the end of the flat_multiset. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(lookup.cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the flat_multiset. - ///\return Iterator to the reverse beginning of the flat_multiset. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_multiset. - ///\return Const iterator to the reverse beginning of the flat_multiset. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the flat_multiset. - ///\return Reverse iterator to the end + 1 of the flat_multiset. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_multiset. - ///\return Const reverse iterator to the end + 1 of the flat_multiset. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_multiset. - ///\return Const reverse iterator to the reverse beginning of the flat_multiset. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(lookup.crbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_multiset. - ///\return Const reverse iterator to the end + 1 of the flat_multiset. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(lookup.crend()); - } - - //********************************************************************* - /// Assigns values to the flat_multiset. - /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset does not have enough free space. - /// If asserts or exceptions are enabled, emits flat_multiset_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_multiset_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the flat_multiset. - /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(parameter_t value) - { - std::pair result(end(), false); - - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_multiset_full)); - - iterator i_element = std::lower_bound(begin(), end(), value, TKeyCompare()); - - if (i_element == end()) - { - // At the end. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.push_back(pvalue); - result.first = --end(); - result.second = true; - } - else - { - // Not at the end. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.insert(i_element.ilookup, pvalue); - result.first = i_element; - result.second = true; - } - - ++construct_count; - - return result; - } - - //********************************************************************* - /// Inserts a value to the flat_multiset. - /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator position, parameter_t value) - { - return insert(value).first; - } - - //********************************************************************* - /// Inserts a range of values to the flat_multiset. - /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(parameter_t key) - { - std::pair range = equal_range(key); - - if (range.first == end()) - { - return 0; - } - else - { - size_t count = std::distance(range.first, range.second); - erase(range.first, range.second); - return count; - } - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - //********************************************************************* - void erase(iterator i_element) - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - void erase(iterator first, iterator last) - { - iterator itr = first; - - while (itr != last) - { - itr->~value_type(); - storage.release(etl::addressof(*itr)); - ++itr; - --construct_count; - } - - lookup.erase(first.ilookup, last.ilookup); - } - - //************************************************************************* - /// Clears the flat_multiset. - //************************************************************************* - void clear() - { - erase(begin(), end()); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(parameter_t key) - { - iterator itr = std::lower_bound(begin(), end(), key, TKeyCompare()); - - if (itr != end()) - { - if (!key_compare()(*itr, key) && !key_compare()(key, *itr)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(parameter_t key) const - { - const_iterator itr = std::lower_bound(begin(), end(), key, TKeyCompare()); - - if (itr != end()) - { - if (!key_compare()(*itr, key) && !key_compare()(key, *itr)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(parameter_t key) const - { - std::pair range = equal_range(key); - - return std::distance(range.first, range.second); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator lower_bound(parameter_t key) - { - return std::lower_bound(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator lower_bound(parameter_t key) const - { - return std::lower_bound(cbegin(), cend(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator upper_bound(parameter_t key) - { - return std::upper_bound(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator upper_bound(parameter_t key) const - { - return std::upper_bound(cbegin(), cend(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(parameter_t key) - { - return std::equal_range(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(parameter_t key) const - { - return std::equal_range(cbegin(), cend(), key, TKeyCompare()); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iflat_multiset& operator = (const iflat_multiset& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the current size of the flat_multiset. - ///\return The current size of the flat_multiset. - //************************************************************************* - size_type size() const - { - return lookup.size(); - } - - //************************************************************************* - /// Checks the 'empty' state of the flat_multiset. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return lookup.empty(); - } - - //************************************************************************* - /// Checks the 'full' state of the flat_multiset. - ///\return true if full. - //************************************************************************* - bool full() const - { - return lookup.full(); - } - - //************************************************************************* - /// Returns the capacity of the flat_multiset. - ///\return The capacity of the flat_multiset. - //************************************************************************* - size_type capacity() const - { - return lookup.capacity(); - } - - //************************************************************************* - /// Returns the maximum possible size of the flat_multiset. - ///\return The maximum size of the flat_multiset. - //************************************************************************* - size_type max_size() const - { - return lookup.max_size(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return lookup.available(); - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iflat_multiset(lookup_t& lookup_, storage_t& storage_) - : lookup(lookup_), - storage(storage_) - { - } - - private: - - // Disable copy construction. - iflat_multiset(const iflat_multiset&); - - lookup_t& lookup; - storage_t& storage; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first flat_multiset. - ///\param rhs Reference to the second flat_multiset. - ///\return true if the arrays are equal, otherwise false - ///\ingroup flat_multiset - //*************************************************************************** - template - bool operator ==(const etl::iflat_multiset& lhs, const etl::iflat_multiset& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first flat_multiset. - ///\param rhs Reference to the second flat_multiset. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup flat_multiset - //*************************************************************************** - template - bool operator !=(const etl::iflat_multiset& lhs, const etl::iflat_multiset& rhs) - { - return !(lhs == rhs); - } -} - -#undef __ETL_IN_IFLAT_MULTISET_H__ -#endif diff --git a/src/iflat_set.h b/src/iflat_set.h deleted file mode 100644 index 6369392b..00000000 --- a/src/iflat_set.h +++ /dev/null @@ -1,781 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IFLAT_SET__ -#define __ETL_IFLAT_SET__ -#define __ETL_IN_IFLAT_SET_H__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "private/flat_set_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "ivector.h" -#include "ipool.h" -#include "error_handler.h" - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized flat_sets. - /// Can be used as a reference type for all flat_sets containing a specific type. - ///\ingroup flat_set - //*************************************************************************** - template > - class iflat_set : public flat_set_base - { - public: - - typedef T key_type; - typedef T value_type; - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - private: - - typedef etl::ivector lookup_t; - typedef etl::ipool storage_t; - - public: - - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iflat_set; - - iterator() - { - } - - iterator(typename lookup_t::iterator ilookup) - : ilookup(ilookup) - { - } - - iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - iterator& operator ++() - { - ++ilookup; - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - ++ilookup; - return temp; - } - - iterator& operator --() - { - --ilookup; - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - --ilookup; - return temp; - } - - reference operator *() - { - return *(*ilookup); - } - - const_reference operator *() const - { - return *(*ilookup); - } - - pointer operator &() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator &() const - { - return &(*(*ilookup)); - } - - pointer operator ->() - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::iterator ilookup; - }; - - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iflat_set; - - const_iterator() - { - } - - const_iterator(typename lookup_t::const_iterator ilookup) - : ilookup(ilookup) - { - } - - const_iterator(const iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator(const const_iterator& other) - : ilookup(other.ilookup) - { - } - - const_iterator& operator =(const iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator =(const const_iterator& other) - { - ilookup = other.ilookup; - return *this; - } - - const_iterator& operator ++() - { - ++ilookup; - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - ++ilookup; - return temp; - } - - const_iterator& operator --() - { - --ilookup; - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - --ilookup; - return temp; - } - - const_reference operator *() const - { - return *(*ilookup); - } - - const_pointer operator &() const - { - return etl::addressof(*(*ilookup)); - } - - const_pointer operator ->() const - { - return etl::addressof(*(*ilookup)); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.ilookup == rhs.ilookup; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - typename lookup_t::const_iterator ilookup; - }; - - protected: - - typedef typename parameter_type::type parameter_t; - - public: - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the flat_set. - ///\return An iterator to the beginning of the flat_set. - //********************************************************************* - iterator begin() - { - return iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_set. - ///\return A const iterator to the beginning of the flat_set. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(lookup.begin()); - } - - //********************************************************************* - /// Returns an iterator to the end of the flat_set. - ///\return An iterator to the end of the flat_set. - //********************************************************************* - iterator end() - { - return iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_set. - ///\return A const iterator to the end of the flat_set. - //********************************************************************* - const_iterator end() const - { - return const_iterator(lookup.end()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the flat_set. - ///\return A const iterator to the beginning of the flat_set. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(lookup.cbegin()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the flat_set. - ///\return A const iterator to the end of the flat_set. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(lookup.cend()); - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the flat_set. - ///\return Iterator to the reverse beginning of the flat_set. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_set. - ///\return Const iterator to the reverse beginning of the flat_set. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(lookup.rbegin()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the flat_set. - ///\return Reverse iterator to the end + 1 of the flat_set. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_set. - ///\return Const reverse iterator to the end + 1 of the flat_set. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(lookup.rend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the flat_set. - ///\return Const reverse iterator to the reverse beginning of the flat_set. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(lookup.crbegin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the flat_set. - ///\return Const reverse iterator to the end + 1 of the flat_set. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(lookup.crend()); - } - - //********************************************************************* - /// Assigns values to the flat_set. - /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set does not have enough free space. - /// If asserts or exceptions are enabled, emits flat_set_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count <= difference_type(capacity()), ETL_ERROR(flat_set_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the flat_set. - /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(parameter_t value) - { - std::pair result(end(), false); - - ETL_ASSERT(!lookup.full(), ETL_ERROR(flat_set_full)); - - iterator i_element = std::lower_bound(begin(), end(), value, TKeyCompare()); - - if (i_element == end()) - { - // At the end. Doesn't exist. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.push_back(pvalue); - result.first = --end(); - result.second = true; - ++construct_count; - } - else - { - // Not at the end. - // Does not exist already? - if (*i_element != value) - { - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - lookup.insert(i_element.ilookup, pvalue); - result.first = i_element; - result.second = true; - ++construct_count; - } - else - { - result.first = i_element; - result.second = false; - } - } - - return result; - } - - //********************************************************************* - /// Inserts a value to the flat_set. - /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator position, parameter_t value) - { - return insert(value).first; - } - - //********************************************************************* - /// Inserts a range of values to the flat_set. - /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(parameter_t key) - { - iterator i_element = find(key); - - if (i_element == end()) - { - return 0; - } - else - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - return 1; - } - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - //********************************************************************* - void erase(iterator i_element) - { - i_element->~value_type(); - storage.release(etl::addressof(*i_element)); - lookup.erase(i_element.ilookup); - --construct_count; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - void erase(iterator first, iterator last) - { - iterator itr = first; - - while (itr != last) - { - itr->~value_type(); - storage.release(etl::addressof(*itr)); - ++itr; - --construct_count; - } - - lookup.erase(first.ilookup, last.ilookup);; - } - - //************************************************************************* - /// Clears the flat_set. - //************************************************************************* - void clear() - { - erase(begin(), end()); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(parameter_t key) - { - iterator itr = std::lower_bound(begin(), end(), key, TKeyCompare()); - - if (itr != end()) - { - if (!key_compare()(*itr, key) && !key_compare()(key, *itr)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(parameter_t key) const - { - const_iterator itr = std::lower_bound(begin(), end(), key, TKeyCompare()); - - if (itr != end()) - { - if (!key_compare()(*itr, key) && !key_compare()(key, *itr)) - { - return itr; - } - else - { - return end(); - } - } - - return end(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(parameter_t key) const - { - return (find(key) == end()) ? 0 : 1; - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator lower_bound(parameter_t key) - { - return std::lower_bound(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the lower bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator lower_bound(parameter_t key) const - { - return std::lower_bound(cbegin(), cend(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - iterator upper_bound(parameter_t key) - { - return std::upper_bound(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the upper bound of a key - ///\param key The key to search for. - ///\return An iterator. - //********************************************************************* - const_iterator upper_bound(parameter_t key) const - { - return std::upper_bound(cbegin(), cend(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(parameter_t key) - { - return std::equal_range(begin(), end(), key, TKeyCompare()); - } - - //********************************************************************* - /// Finds the range of equal elements of a key - ///\param key The key to search for. - ///\return An iterator pair. - //********************************************************************* - std::pair equal_range(parameter_t key) const - { - return std::upper_bound(cbegin(), cend(), key, TKeyCompare()); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iflat_set& operator = (const iflat_set& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the current size of the flat_set. - ///\return The current size of the flat_set. - //************************************************************************* - size_type size() const - { - return lookup.size(); - } - - //************************************************************************* - /// Checks the 'empty' state of the flat_set. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return lookup.empty(); - } - - //************************************************************************* - /// Checks the 'full' state of the flat_set. - ///\return true if full. - //************************************************************************* - bool full() const - { - return lookup.full(); - } - - //************************************************************************* - /// Returns the capacity of the flat_set. - ///\return The capacity of the flat_set. - //************************************************************************* - size_type capacity() const - { - return lookup.capacity(); - } - - //************************************************************************* - /// Returns the maximum possible size of the flat_set. - ///\return The maximum size of the flat_set. - //************************************************************************* - size_type max_size() const - { - return lookup.max_size(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return lookup.available(); - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iflat_set(lookup_t& lookup_, storage_t& storage) - : lookup(lookup_), - storage(storage) - { - } - - private: - - // Disable copy construction. - iflat_set(const iflat_set&); - - lookup_t& lookup; - storage_t& storage; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first flat_set. - ///\param rhs Reference to the second flat_set. - ///\return true if the arrays are equal, otherwise false - ///\ingroup flat_set - //*************************************************************************** - template - bool operator ==(const etl::iflat_set& lhs, const etl::iflat_set& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first flat_set. - ///\param rhs Reference to the second flat_set. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup flat_set - //*************************************************************************** - template - bool operator !=(const etl::iflat_set& lhs, const etl::iflat_set& rhs) - { - return !(lhs == rhs); - } -} - -#undef __ETL_IN_IFLAT_SET_H__ -#endif diff --git a/src/iforward_list.h b/src/iforward_list.h deleted file mode 100644 index c128ec55..00000000 --- a/src/iforward_list.h +++ /dev/null @@ -1,1066 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IFORWARD_LIST__ -#define __ETL_IFORWARD_LIST__ -#define __ETL_IN_IFORWARD_LIST_H__ - -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -#include -#include -#include -#include - -#include "pool.h" -#include "nullptr.h" -#include "private/forward_list_base.h" -#include "type_traits.h" -#include "parameter_type.h" - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::forward_list types. - ///\ingroup forward_list - //*************************************************************************** - template - class iforward_list : public forward_list_base - { - 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; - - protected: - - typedef typename parameter_type::value || is_pointer::value>::type parameter_t; - - //************************************************************************* - /// The data node element in the forward_list. - //************************************************************************* - struct data_node_t : public node_t - { - explicit data_node_t(parameter_t value) - : value(value) - {} - - T value; - }; - - public: - - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iforward_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 iforward_list::data_cast(p_node)->value; - } - - const_reference operator *() const - { - return iforward_list::data_cast(p_node)->value; - } - - pointer operator &() - { - return &(iforward_list::data_cast(p_node)->value); - } - - const_pointer operator &() const - { - return &(iforward_list::data_cast(p_node)->value); - } - - pointer operator ->() - { - return &(iforward_list::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(iforward_list::data_cast(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_t* p_node; - }; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iforward_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 typename iforward_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 iforward_list::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return iforward_list::data_cast(p_node)->value; - } - - const_pointer operator ->() const - { - return &(iforward_list::data_cast(p_node)->value); - } - - 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_t* p_node; - }; - - typedef typename std::iterator_traits::difference_type difference_type; - - //************************************************************************* - /// Gets the beginning of the forward_list. - //************************************************************************* - iterator begin() - { - return iterator(data_cast(get_head())); - } - - //************************************************************************* - /// Gets the beginning of the forward_list. - //************************************************************************* - const_iterator begin() const - { - return const_iterator(data_cast(get_head())); - } - - //************************************************************************* - /// Gets before the beginning of the forward_list. - //************************************************************************* - iterator before_begin() - { - return iterator(static_cast(start_node)); - } - - //************************************************************************* - /// Gets before the beginning of the forward_list. - //************************************************************************* - const_iterator before_begin() const - { - return const_iterator(static_cast(start_node)); - } - - //************************************************************************* - /// Gets the beginning of the forward_list. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(get_head()); - } - - //************************************************************************* - /// Gets the end of the forward_list. - //************************************************************************* - iterator end() - { - return iterator(); - } - - //************************************************************************* - /// Gets the end of the forward_list. - //************************************************************************* - const_iterator end() const - { - return const_iterator(); - } - - //************************************************************************* - /// Gets the end of the forward_list. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(); - } - - //************************************************************************* - /// Clears the forward_list. - //************************************************************************* - void clear() - { - initialise(); - } - - //************************************************************************* - /// Gets a reference to the first element. - //************************************************************************* - reference front() - { - return data_cast(get_head()).value; - } - - //************************************************************************* - /// Gets a const reference to the first element. - //************************************************************************* - const_reference front() const - { - return data_cast(get_head()).value; - } - - //************************************************************************* - /// Assigns a range of values to the forward_list. - /// If asserts or exceptions are enabled throws etl::forward_list_full if the forward_list does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws forward_list_iterator if the iterators are reversed. - //************************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(forward_list_iterator)); -#endif - - initialise(); - - node_t* p_last_node = &start_node; - - // Add all of the elements. - while (first != last) - { - ETL_ASSERT(!full(), ETL_ERROR(forward_list_iterator)); - - data_node_t& data_node = allocate_data_node(*first++); - join(p_last_node, &data_node); - data_node.next = nullptr; - p_last_node = &data_node; - } - } - - //************************************************************************* - /// Assigns 'n' copies of a value to the forward_list. - //************************************************************************* - void assign(size_t n, parameter_t value) - { - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(forward_list_full)); - - initialise(); - - node_t* p_last_node = &start_node; - - // Add all of the elements. - while (size() < n) - { - data_node_t& data_node = allocate_data_node(value); - join(p_last_node, &data_node); - data_node.next = nullptr; - p_last_node = &data_node; - } - } - - //************************************************************************* - /// Adds a node to the front of the forward_list so a new value can be assigned to front(). - //************************************************************************* - void push_front() - { - push_front(T()); - } - - //************************************************************************* - /// Pushes a value to the front of the forward_list. - //************************************************************************* - void push_front(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); -#endif - - data_node_t& data_node = allocate_data_node(value); - insert_node_after(start_node, data_node); - } - - //************************************************************************* - /// Removes a value from the front of the forward_list. - //************************************************************************* - void pop_front() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(forward_list_empty)); -#endif - remove_node_after(start_node); - } - - //************************************************************************* - /// Resizes the forward_list. - //************************************************************************* - void resize(size_t n) - { - resize(n, T()); - } - - //************************************************************************* - /// Resizes the forward_list. - /// If asserts or exceptions are enabled, will throw an etl::forward_list_full - /// if n is larger than the maximum size. - //************************************************************************* - void resize(size_t n, T value) - { - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(forward_list_full)); - - size_t i = 0; - iterator i_node = begin(); - iterator i_last_node; - - // Find where we're currently at. - while ((i < n) && (i_node != end())) - { - ++i; - i_last_node = i_node; - ++i_node; - } - - if (i_node != end()) - { - // Reduce. - erase_after(i_last_node, end()); - } - else if (i_node == end()) - { - // Increase. - while (i < n) - { - i_last_node = insert_after(i_last_node, value); - ++i; - } - } - } - - //************************************************************************* - /// Inserts a value to the forward_list after the specified position. - //************************************************************************* - iterator insert_after(iterator position, parameter_t value) - { - ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - - data_node_t& data_node = allocate_data_node(value); - insert_node_after(*position.p_node, data_node); - - return iterator(data_node); - } - - //************************************************************************* - /// Inserts 'n' copies of a value to the forward_list after the specified position. - //************************************************************************* - void insert_after(iterator position, size_t n, parameter_t value) - { - ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - - for (size_t i = 0; !full() && (i < n); ++i) - { - // Set up the next free node. - data_node_t& data_node = allocate_data_node(value); - insert_node_after(*position.p_node, data_node); - } - } - - //************************************************************************* - /// Inserts a range of values to the forward_list after the specified position. - //************************************************************************* - template - void insert_after(iterator position, TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT((count + size()) <= MAX_SIZE, ETL_ERROR(forward_list_full)); -#endif - - while (first != last) - { - // Set up the next free node. - data_node_t& data_node = allocate_data_node(*first++); - insert_node_after(*position.p_node, data_node); - ++position; - } - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase_after(iterator position) - { - iterator next(position); - if (next != end()) - { - ++next; - if (next != end()) - { - ++next; - remove_node_after(*position.p_node); - } - } - - return next; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase_after(iterator first, iterator last) - { - if (first != end() && (first != 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. - destroy_data_node(static_cast(*p_first)); // Destroy the pool object. - p_first = p_next; // Move to the next node. - } - - if (p_next == nullptr) - { - return end(); - } - else - { - return iterator(*p_last); - } - } - else - { - return end(); - } - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - void move_after(const_iterator from_before, const_iterator to_before) - { - if (from_before == to_before) // Can't move to after yourself! - { - return; - } - - node_t* p_from_before = const_cast(from_before.p_node); // We're not changing the value, just it's position. - node_t* p_to_before = const_cast(to_before.p_node); // We're not changing the value, just it's position. - - node_t* p_from = p_from_before->next; - - // Disconnect from the list. - join(p_from_before, p_from->next); - - // Attach it to the new position. - join(p_from, p_to_before->next); - join(p_to_before, p_from); - } - - //************************************************************************* - /// Moves a range from one position to another within the list. - /// Moves a range at position 'first_before'/'last' to the position before 'to_before'. - //************************************************************************* - void move_after(const_iterator first_before, const_iterator last, const_iterator to_before) - { - if ((first_before == to_before) || (last == to_before)) - { - return; // Can't more to before yourself! - } - -#if defined(ETL_DEBUG) - // Check that we are not doing an illegal move! - for (const_iterator item = first_before; item != last; ++item) - { - ETL_ASSERT(item != to_before, ETL_ERROR(forward_list_iterator)); - } -#endif - - node_t* p_first_before = const_cast(first_before.p_node); // We're not changing the value, just it's position. - node_t* p_last = const_cast(last.p_node); // We're not changing the value, just it's position. - node_t* p_to_before = const_cast(to_before.p_node); // We're not changing the value, just it's position. - node_t* p_first = p_first_before->next; - node_t* p_final = p_first_before; - - // Find the last node that will be moved. - while (p_final->next != p_last) - { - p_final = p_final->next; - } - - // Disconnect from the list. - join(p_first_before, p_final->next); - - // Attach it to the new position. - join(p_final, p_to_before->next); - join(p_to_before, p_first); - } - - //************************************************************************* - /// 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 one element from every consecutive group of equal - /// elements in the container. - //************************************************************************* - template - void unique(TIsEqual isEqual) - { - if (empty()) - { - return; - } - - node_t* last = &get_head(); - node_t* current = last->next; - - while (current != nullptr) - { - // Is this value the same as the last? - if (isEqual(data_cast(current)->value, data_cast(last)->value)) - { - remove_node_after(*last); - } - else - { - // Move on one. - last = current; - } - - current = last->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) - { - iterator p_left; - iterator p_right; - iterator p_node; - iterator p_head; - iterator 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 = begin(); - p_head = before_begin(); - p_tail = before_begin(); - - number_of_merges = 0; // Count the number of merges we do in this pass. - - while (p_left != end()) - { - ++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; - - if (p_right == end()) - { - 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 != end())) - { - // 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; - --right_size; - } - else if (right_size == 0 || p_right == end()) - { - // Right is empty. The node must come from left. - p_node = p_left; - ++p_left; - --left_size; - } - else if (compare(*p_left, *p_right)) - { - // First node of left is lower or same. The node must come from left. - p_node = p_left; - ++p_left; - --left_size; - } - else - { - // First node of right is lower. The node must come from right. - p_node = p_right; - ++p_right; - --right_size; - } - - // Add the next node to the merged head. - if (p_head == before_begin()) - { - join(p_head.p_node, p_node.p_node); - p_head = p_node; - p_tail = p_node; - } - else - { - join(p_tail.p_node, p_node.p_node); - p_tail = p_node; - } - - p_tail.p_node->next = nullptr; - } - - // 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(parameter_t value) - { - iterator i_item = begin(); - iterator i_last_item = before_begin(); - - while (i_item != end()) - { - if (*i_item == value) - { - i_item = erase_after(i_last_item); - } - else - { - ++i_item; - ++i_last_item; - } - } - } - - //************************************************************************* - /// Removes according to a predicate. - //************************************************************************* - template - void remove_if(TPredicate predicate) - { - iterator i_item = begin(); - iterator i_last_item = before_begin(); - - while (i_item != end()) - { - if (predicate(*i_item)) - { - i_item = erase_after(i_last_item); - } - else - { - ++i_item; - ++i_last_item; - } - } - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iforward_list& operator = (const iforward_list& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - iforward_list(etl::ipool& node_pool, size_t max_size_) - : forward_list_base(node_pool, max_size_) - { - } - - //************************************************************************* - /// Initialise the forward_list. - //************************************************************************* - void initialise() - { - if (!empty()) - { - node_t* p_first = start_node.next; - node_t* p_next; - - // Erase the ones in between. - while (p_first != nullptr) - { - p_next = p_first->next; // Remember the next node. - destroy_data_node(static_cast(*p_first)); // Destroy the pool object. - p_first = p_next; // Move to the next node. - } - } - - start_node.next = nullptr; - } - - private: - - //************************************************************************* - /// Downcast a node_t* to a data_node_t* - //************************************************************************* - static data_node_t* data_cast(node_t* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a node_t& to a data_node_t& - //************************************************************************* - static data_node_t& data_cast(node_t& node) - { - return static_cast(node); - } - - //************************************************************************* - /// Downcast a const node_t* to a const data_node_t* - //************************************************************************* - static const data_node_t* data_cast(const node_t* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a const node_t& to a const data_node_t& - //************************************************************************* - static const data_node_t& data_cast(const node_t& node) - { - return static_cast(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 forward_list. - join(&node, p_node->next); - - // Destroy the pool object. - destroy_data_node(static_cast(*p_node)); - } - } - - //************************************************************************* - /// Allocate a data_node_t. - //************************************************************************* - data_node_t& allocate_data_node(parameter_t value) - { - data_node_t* p_node = p_node_pool->allocate(); - ::new (&(p_node->value)) T(value); - ++construct_count; - - return *p_node; - } - - //************************************************************************* - /// Destroy a data_node_t. - //************************************************************************* - void destroy_data_node(data_node_t& node) - { - node.value.~T(); - p_node_pool->release(&node); - --construct_count; - } - - // Disable copy construction. - iforward_list(const iforward_list&); - }; -} - -//************************************************************************* -/// Equal operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the arrays are equal, otherwise false. -//************************************************************************* -template -bool operator ==(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return (lhs.size() == rhs.size()) && - std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//************************************************************************* -/// Not equal operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the arrays are not equal, otherwise false. -//************************************************************************* -template -bool operator !=(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return !(lhs == rhs); -} - -//************************************************************************* -/// Less than operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the first forward_list is lexicographically less than the -/// second, otherwise false. -//************************************************************************* -template -bool operator <(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return std::lexicographical_compare(lhs.begin(), - lhs.end(), - rhs.begin(), - rhs.end()); -} - -//************************************************************************* -/// Greater than operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the first forward_list is lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// Less than or equal operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the first forward_list is lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return !(lhs > rhs); -} - -//************************************************************************* -/// Greater than or equal operator. -///\param lhs Reference to the first forward_list. -///\param rhs Reference to the second forward_list. -///\return true if the first forward_list is lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::iforward_list& lhs, const etl::iforward_list& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_IFORWARD_LIST_H__ - -#endif diff --git a/src/ilist.h b/src/ilist.h deleted file mode 100644 index 9d42904a..00000000 --- a/src/ilist.h +++ /dev/null @@ -1,1197 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_ILIST__ -#define __ETL_ILIST__ -#define __ETL_IN_ILIST_H__ - -#include -#include -#include -#include - -#include "platform.h" -#include "nullptr.h" -#include "private/list_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "algorithm.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::list types. - ///\ingroup list - //*************************************************************************** - template - class ilist : public list_base - { - 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; - - protected: - - typedef typename parameter_type::value || is_pointer::value>::type parameter_t; - - //************************************************************************* - /// The data node element in the list. - //************************************************************************* - struct data_node_t : public node_t - { - explicit data_node_t(parameter_t value) - : value(value) - { - } - - T value; - }; - - private: - - //************************************************************************* - /// Downcast a node_t* to a data_node_t* - //************************************************************************* - static data_node_t* data_cast(node_t* p_node) - { - return reinterpret_cast(p_node); - } - - //************************************************************************* - /// Downcast a node_t& to a data_node_t& - //************************************************************************* - static data_node_t& data_cast(node_t& node) - { - return reinterpret_cast(node); - } - - //************************************************************************* - /// Downcast a const node_t* to a const data_node_t* - //************************************************************************* - static const data_node_t* data_cast(const node_t* p_node) - { - return reinterpret_cast(p_node); - } - - //************************************************************************* - /// Downcast a const node_t& to a const data_node_t& - //************************************************************************* - static const data_node_t& data_cast(const node_t& node) - { - return reinterpret_cast(node); - } - - public: - - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class ilist; - - 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 --() - { - 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 ilist::data_cast(p_node)->value; - } - - const_reference operator *() const - { - return ilist::data_cast(p_node)->value; - } - - pointer operator &() - { - return &(ilist::data_cast(p_node)->value); - } - - const_pointer operator &() const - { - return &(ilist::data_cast(p_node)->value); - } - - pointer operator ->() - { - return &(ilist::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(ilist::data_cast(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_t* p_node; - }; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class ilist; - - 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 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 ilist::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return ilist::data_cast(p_node)->value; - } - - const data_node_t* 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_t* 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 end of the list. - //************************************************************************* - iterator end() - { - return iterator(terminal_node); - } - - //************************************************************************* - /// Gets the end of the list. - //************************************************************************* - const_iterator end() const - { - return const_iterator(static_cast(terminal_node)); - } - - //************************************************************************* - /// Gets the beginning of the list. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(get_head()); - } - - //************************************************************************* - /// Gets the end of the list. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(static_cast(terminal_node)); - } - - //************************************************************************* - /// 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(static_cast(terminal_node)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(get_head()); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(static_cast(terminal_node)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(get_head()); - } - - //************************************************************************* - /// Gets a reference to the first element. - //************************************************************************* - reference front() - { - return data_cast(get_head()).value; - } - - //************************************************************************* - /// Gets a const reference to the first element. - //************************************************************************* - const_reference front() const - { - return data_cast(get_head()).value; - } - - //************************************************************************* - /// Gets a reference to the last element. - //************************************************************************* - reference back() - { - return data_cast(get_tail()).value; - } - - //************************************************************************* - /// Gets a reference to the last element. - //************************************************************************* - const_reference back() const - { - return data_cast(get_tail()).value; - } - - //************************************************************************* - /// Assigns a range of values to the list. - /// If asserts or exceptions are enabled throws etl::list_full if the list does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws list_iterator if the iterators are reversed. - //************************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(list_iterator)); - ETL_ASSERT(size_t(count) <= MAX_SIZE, ETL_ERROR(list_full)); -#endif - initialise(); - - // Add all of the elements. - while (first != last) - { - data_node_t& node = allocate_data_node(*first); - join(get_tail(), node); - join(node, terminal_node); - ++first; - } - } - - //************************************************************************* - /// Assigns 'n' copies of a value to the list. - //************************************************************************* - void assign(size_t n, parameter_t value) - { -#if defined(ETL_DEBUG) - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full)); -#endif - - initialise(); - - // Add all of the elements. - while (size() < n) - { - data_node_t& node = allocate_data_node(value); - join(*terminal_node.previous, node); - join(node, terminal_node); - } - } - - //************************************************************************* - /// Adds a node to the front of the list so a new value can be assigned to front(). - //************************************************************************* - void push_front() - { - push_front(T()); - } - - //************************************************************************* - /// Pushes a value to the front of the list. - //************************************************************************* - void push_front(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(list_full)); -#endif - insert_node(get_head(), allocate_data_node(value)); - } - - //************************************************************************* - /// Removes a value from the front of the list. - //************************************************************************* - void pop_front() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(list_empty)); -#endif - node_t& node = get_head(); - remove_node(node); - } - - //************************************************************************* - /// Adds a node to the back of the list so a new value can be assigned to back(). - //************************************************************************* - void push_back() - { - push_back(T()); - } - - //************************************************************************* - /// Pushes a value to the back of the list.. - //************************************************************************* - void push_back(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(list_full)); -#endif - insert_node(terminal_node, allocate_data_node(value)); - } - - //************************************************************************* - /// Removes a value from the back of the list. - //************************************************************************* - void pop_back() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(list_empty)); -#endif - node_t& node = get_tail(); - remove_node(node); - } - - //************************************************************************* - /// Inserts a value to the list at the specified position. - //************************************************************************* - iterator insert(iterator position, const value_type& value) - { - ETL_ASSERT(!full(), ETL_ERROR(list_full)); - - data_node_t& data_node = allocate_data_node(value); - insert_node(*position.p_node, data_node); - - return iterator(data_node); - } - - //************************************************************************* - /// Inserts 'n' copies of a value to the list at the specified position. - //************************************************************************* - void insert(iterator position, size_t n, const value_type& value) - { - for (size_t i = 0; i < n; ++i) - { - ETL_ASSERT(!full(), ETL_ERROR(list_full)); - - // Set up the next free node and insert. - insert_node(*position.p_node, allocate_data_node(value)); - } - } - - //************************************************************************* - /// Inserts a range of values to the list at the specified position. - //************************************************************************* - template - void insert(iterator position, TIterator first, TIterator last) - { - while (first != last) - { - ETL_ASSERT(!full(), ETL_ERROR(list_full)); - - // Set up the next free node and insert. - insert_node(*position.p_node, allocate_data_node(*first++)); - } - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase(iterator position) - { - ++position; - remove_node(*position.p_node->previous); - return position; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(iterator first, iterator last) - { - node_t* p_first = first.p_node; - node_t* p_last = last.p_node; - node_t* p_next; - - // Join the ends. - join(*(p_first->previous), *p_last); - - // Erase the ones in between. - while (p_first != p_last) - { - p_next = p_first->next; // Remember the next node. - destroy_data_node(static_cast(*p_first)); // Destroy the current node. - p_first = p_next; // Move to the next node. - } - - return last; - } - - //************************************************************************* - /// Resizes the list. - //************************************************************************* - void resize(size_t n) - { - resize(n, T()); - } - - //************************************************************************* - /// Resizes the list. - //************************************************************************* - void resize(size_t n, parameter_t value) - { - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(list_full)); - - // Smaller? - if (n < size()) - { - iterator i_start = end(); - std::advance(i_start, -difference_type(size() - n)); - erase(i_start, end()); - } - // Larger? - else if (n > size()) - { - insert(end(), n - size(), value); - } - } - - //************************************************************************* - /// Clears the list. - //************************************************************************* - void clear() - { - initialise(); - } - - //************************************************************************* - // 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; - } - } - } - - //************************************************************************* - /// 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) - { - if (empty()) - { - return; - } - - iterator i_item = begin(); - ++i_item; - iterator i_previous = begin(); - - while (i_item != end()) - { - if (isEqual(*i_previous, *i_item)) - { - i_item = erase(i_item); - } - else - { - i_previous = i_item; - ++i_item; - } - } - } - - //************************************************************************* - /// Splices from another list to this. - //************************************************************************* - void splice(iterator to, ilist& other) - { - if (&other != this) - { - insert(to, other.begin(), other.end()); - other.erase(other.begin(), other.end()); - } - } - - //************************************************************************* - /// Splices an element from another list to this. - //************************************************************************* - void splice(iterator to, ilist& other, iterator from) - { - if (&other == this) - { - // Internal move. - move(to, from); - } - else - { - // From another list. - insert(to, *from); - other.erase(from); - } - } - - //************************************************************************* - /// Splices a range of elements from another list to this. - //************************************************************************* - void splice(iterator to, ilist& other, iterator first, iterator last) - { - if (&other == this) - { - // Internal move. - move(to, first, last); - } - else - { - // From another list. - insert(to, first, last); - other.erase(first, last); - } - } - - //************************************************************************* - /// Merge another list into this one. Both lists should be sorted. - //************************************************************************* - void merge(ilist& other) - { - merge(other, std::less()); - } - - //************************************************************************* - /// Merge another list into this one. Both lists should be sorted. - //************************************************************************* - template - void merge(ilist& other, TCompare compare) - { - if (!other.empty()) - { -#if _DEBUG - ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted)); - ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted)); -#endif - - ilist::iterator other_begin = other.begin(); - ilist::iterator other_end = other.end(); - - ilist::iterator this_begin = begin(); - ilist::iterator this_end = end(); - - while ((this_begin != this_end) && (other_begin != other_end)) - { - // Find the place to insert. - while ((this_begin != this_end) && !(compare(*other_begin, *this_begin))) - { - ++this_begin; - } - - bool t = this_begin != this_end; - bool o = other_begin != other_end; - - // Insert. - if (this_begin != this_end) - { - while ((other_begin != other_end) && (compare(*other_begin, *this_begin))) - { - insert(this_begin, *other_begin); - ++other_begin; - - o = other_begin != other_end; - } - } - } - - // Any left over? - if ((this_begin == this_end) && (other_begin != other_end)) - { - insert(this_end, other_begin, other_end); - } - - other.clear(); - } - } - - //************************************************************************* - /// 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) - { - iterator i_left; - iterator i_right; - iterator i_node; - iterator i_head; - iterator i_tail; - int list_size = 1; - int number_of_merges; - int left_size; - int right_size; - - if (is_trivial_list()) - { - return; - } - - while (true) - { - i_left = begin(); - i_head = end(); - i_tail = end(); - - number_of_merges = 0; // Count the number of merges we do in this pass. - - while (i_left != end()) - { - ++number_of_merges; // There exists a merge to be done. - i_right = i_left; - left_size = 0; - - // Step 'list_size' places along from left - for (int i = 0; i < list_size; ++i) - { - ++left_size; - ++i_right; - - if (i_right == end()) - { - 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 && i_right != end())) - { - // 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. - i_node = i_right++; - --right_size; - } - else if (right_size == 0 || i_right == end()) - { - // Right is empty. The node must come from left. - i_node = i_left++; - --left_size; - } - else if (compare(*i_left, *i_right)) - { - // First node of left is lower or same. The node must come from left. - i_node = i_left++; - --left_size; - } - else - { - // First node of right is lower. The node must come from right. - i_node = i_right; - ++i_right; - --right_size; - } - - // Add the next node to the merged head. - if (i_head == end()) - { - join(*i_head.p_node, *i_node.p_node); - i_head = i_node; - i_tail = i_node; - } - else - { - join(*i_tail.p_node, *i_node.p_node); - i_tail = i_node; - } - - join(*i_tail.p_node, terminal_node); - } - - // Now left has stepped `list_size' places along, and right has too. - i_left = i_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; - } - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ilist& operator = (const ilist& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - ilist(etl::ipool& node_pool, size_t max_size_) - : list_base(node_pool, max_size_) - { - } - - //************************************************************************* - /// Initialise the list. - //************************************************************************* - void initialise() - { - if (!empty()) - { - node_t* p_first = terminal_node.next; - node_t* p_last = &terminal_node; - - while (p_first != p_last) - { - destroy_data_node(static_cast(*p_first)); // Destroy the current node. - p_first = p_first->next; // Move to the next node. - } - } - - join(terminal_node, terminal_node); - } - - private: - - //************************************************************************* - /// Moves an element from one position to another within the list. - /// Moves the element at position 'from' to the position before 'to'. - //************************************************************************* - void move(iterator to, iterator from) - { - if (from == to) - { - return; // Can't more to before yourself! - } - - node_t& from_node = *from.p_node; - node_t& to_node = *to.p_node; - - // Disconnect the node from the list. - join(*from_node.previous, *from_node.next); - - // Attach it to the new position. - join(*to_node.previous, from_node); - join(from_node, to_node); - } - - //************************************************************************* - /// Moves a range from one position to another within the list. - /// Moves a range at position 'first'/'last' to the position before 'to'. - //************************************************************************* - void move(iterator to, iterator first, iterator last) - { - if ((first == to) || (last == to)) - { - return; // Can't more to before yourself! - } - -#if defined(ETL_DEBUG) - // Check that we are not doing an illegal move! - for (const_iterator item = first; item != last; ++item) - { - ETL_ASSERT(item != to, ETL_ERROR(list_iterator)); - } -#endif - - node_t& first_node = *first.p_node; - node_t& last_node = *last.p_node; - node_t& to_node = *to.p_node; - node_t& final_node = *last_node.previous; - - // Disconnect the range from the list. - join(*first_node.previous, last_node); - - // Attach it to the new position. - join(*to_node.previous, first_node); - join(final_node, to_node); - } - - //************************************************************************* - /// Remove a node. - //************************************************************************* - void remove_node(node_t& node) - { - // Disconnect the node from the list. - join(*node.previous, *node.next); - - // Destroy the pool object. - destroy_data_node(static_cast(node)); - } - - //************************************************************************* - /// Allocate a data_node_t. - //************************************************************************* - data_node_t& allocate_data_node(parameter_t value) - { - data_node_t* p_data_node = p_node_pool->allocate(); - ::new (&(p_data_node->value)) T(value); - ++construct_count; - - return *p_data_node; - } - - //************************************************************************* - /// Destroy a data_node_t. - //************************************************************************* - void destroy_data_node(data_node_t& node) - { - node.value.~T(); - p_node_pool->release(&node); - --construct_count; - } - - // Disable copy construction. - ilist(const ilist&); - }; -} - -//************************************************************************* -/// 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 lexicographically 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 lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::ilist& lhs, const etl::ilist& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// 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 lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::ilist& lhs, const etl::ilist& rhs) -{ - return !(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 lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::ilist& lhs, const etl::ilist& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_ILIST_H__ - -#endif diff --git a/src/imap.h b/src/imap.h deleted file mode 100644 index 1bc48cdd..00000000 --- a/src/imap.h +++ /dev/null @@ -1,1695 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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. -******************************************************************************/ - -#ifndef __ETL_IMAP__ -#define __ETL_IMAP__ -#define __ETL_IN_IMAP_H__ - -#include -#include -#include -#include - -#include "nullptr.h" -#include "private/map_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "pool.h" -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::map types. - ///\ingroup map - //*************************************************************************** - template - class imap : public map_base - { - public: - - typedef TKey key_type; - typedef std::pair value_type; - typedef TMapped mapped_type; - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - /// How to compare two key elements. - //************************************************************************* - struct key_comp - { - bool operator ()(const key_type& key1, const key_type& key2) const - { - return key_compare()(key1, key2); - } - }; - - //************************************************************************* - /// How to compare two value elements. - //************************************************************************* - struct value_comp - { - bool operator ()(const value_type& value1, const value_type& value2) const - { - return key_compare()(value1.first, value2.first); - } - }; - - protected: - - //************************************************************************* - /// The data node element in the map. - //************************************************************************* - struct Data_Node : public Node - { - explicit Data_Node(value_type value) - : value(value) - { - } - - ~Data_Node() - { - - } - - value_type value; - }; - - /// Defines the key value parameter type - typedef typename parameter_type::type key_value_parameter_t; - - //************************************************************************* - /// How to compare node elements. - //************************************************************************* - bool node_comp(const Data_Node& node1, const Data_Node& node2) const - { - 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); - } - - private: - - /// The pool of data nodes used in the map. - ipool* p_node_pool; - - //************************************************************************* - /// Downcast a Node* to a Data_Node* - //************************************************************************* - static Data_Node* data_cast(Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a Node& to a Data_Node& - //************************************************************************* - static Data_Node& data_cast(Node& node) - { - return static_cast(node); - } - - //************************************************************************* - /// Downcast a const Node* to a const Data_Node* - //************************************************************************* - static const Data_Node* data_cast(const Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a const Node& to a const Data_Node& - //************************************************************************* - static const Data_Node& data_cast(const Node& node) - { - return static_cast(node); - } - - public: - - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class imap; - - iterator() - : p_map(nullptr) - , p_node(nullptr) - { - } - - iterator(imap& map) - : p_map(&map) - , p_node(nullptr) - { - } - - iterator(imap& map, Node* node) - : p_map(&map) - , p_node(node) - { - } - - iterator(const iterator& other) - : p_map(other.p_map) - , p_node(other.p_node) - { - } - - ~iterator() - { - } - - iterator& operator ++() - { - p_map->next_node(p_node); - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - p_map->next_node(p_node); - return temp; - } - - iterator& operator --() - { - p_map->prev_node(p_node); - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - p_map->prev_node(p_node); - return temp; - } - - iterator operator =(const iterator& other) - { - p_map = other.p_map; - p_node = other.p_node; - return *this; - } - - reference operator *() - { - return imap::data_cast(p_node)->value; - } - - const_reference operator *() const - { - return imap::data_cast(p_node)->value; - } - - pointer operator &() - { - return &(imap::data_cast(p_node)->value); - } - - const_pointer operator &() const - { - return &(imap::data_cast(p_node)->value); - } - - pointer operator ->() - { - return &(imap::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(imap::data_cast(p_node)->value); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.p_map == rhs.p_map && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - // Pointer to map associated with this iterator - imap* p_map; - - // Pointer to the current node for this iterator - Node* p_node; - }; - - friend class iterator; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class imap; - - const_iterator() - : p_map(nullptr) - , p_node(nullptr) - { - } - - const_iterator(const imap& map) - : p_map(&map) - , p_node(nullptr) - { - } - - const_iterator(const imap& map, const Node* node) - : p_map(&map) - , p_node(node) - { - } - - const_iterator(const typename imap::iterator& other) - : p_map(other.p_map) - , p_node(other.p_node) - { - } - - const_iterator(const const_iterator& other) - : p_map(other.p_map) - , p_node(other.p_node) - { - } - - ~const_iterator() - { - } - - const_iterator& operator ++() - { - p_map->next_node(p_node); - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - p_map->next_node(p_node); - return temp; - } - - const_iterator& operator --() - { - p_map->prev_node(p_node); - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - p_map->prev_node(p_node); - return temp; - } - - const_iterator operator =(const const_iterator& other) - { - p_map = other.p_map; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return imap::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return imap::data_cast(p_node)->value; - } - - const_pointer operator ->() const - { - return &(imap::data_cast(p_node)->value); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.p_map == rhs.p_map && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - // Pointer to map associated with this iterator - const imap* p_map; - - // Pointer to the current node for this iterator - const Node* p_node; - }; - - friend class const_iterator; - - 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 map. - //************************************************************************* - iterator begin() - { - return iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the beginning of the map. - //************************************************************************* - const_iterator begin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the map. - //************************************************************************* - iterator end() - { - return iterator(*this); - } - - //************************************************************************* - /// Gets the end of the map. - //************************************************************************* - const_iterator end() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the beginning of the map. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the map. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft))); - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - ///\param i The index. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& operator [](const key_value_parameter_t& key) - { - iterator i_element = find(key); - - if (!i_element.p_node) - { - // Doesn't exist, so create a new one. - i_element = insert(std::make_pair(key, mapped_type())).first; - } - - return i_element->second; - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::lookup_out_of_bounds if the key is not in the range. - ///\param i The index. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& at(const key_value_parameter_t& key) - { - iterator i_element = find(key); - - ETL_ASSERT(i_element.p_node != nullptr, ETL_ERROR(map_out_of_bounds)); - - return i_element->second; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::lookup_out_of_bounds if the key is not in the range. - ///\param i The index. - ///\return A const reference to the value at index 'key' - //********************************************************************* - const mapped_type& at(const key_value_parameter_t& key) const - { - const_iterator i_element = find(key); - - ETL_ASSERT(i_element.p_node != nullptr, ETL_ERROR(map_out_of_bounds)); - - return i_element->second; - } - - //********************************************************************* - /// Assigns values to the map. - /// If asserts or exceptions are enabled, emits map_full if the map does not have enough free space. - /// If asserts or exceptions are enabled, emits map_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { - initialise(); - insert(first, last); - } - - //************************************************************************* - /// Clears the map. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts the number of elements that contain the key specified. - ///\param key The key to search for. - ///\return 1 if element was found, 0 otherwise. - //********************************************************************* - size_type count(const key_value_parameter_t& key) const - { - return find_node(root_node, key) ? 1 : 0; - } - - //************************************************************************* - /// Returns two iterators with bounding (lower bound, upper bound) the key - /// provided - //************************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - return std::make_pair( - iterator(*this, find_lower_node(root_node, key)), - iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Returns two const iterators with bounding (lower bound, upper bound) - /// the key provided. - //************************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - return std::make_pair( - const_iterator(*this, find_lower_node(root_node, key)), - const_iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - void erase(iterator position) - { - // Remove the node by its key - erase((*position).first); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase(const_iterator position) - { - // Find the parent node to be removed - Node*& reference_node = find_node(root_node, position.p_node); - iterator next(*this, reference_node); - ++next; - - remove_node(root_node, (*position).first); - - return next; - } - - //************************************************************************* - // Erase the key specified. - //************************************************************************* - size_type erase(const key_value_parameter_t& key) - { - // Return 1 if key value was found and removed - return remove_node(root_node, key) ? 1 : 0; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(iterator first, iterator last) - { - iterator next; - while (first != last) - { - next = erase(const_iterator(first++)); - } - - return next; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - iterator next; - while (first != last) - { - next = erase(first++); - } - - return next; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(const key_value_parameter_t& key) - { - return iterator(*this, find_node(root_node, key)); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_node(root_node, key)); - } - - //********************************************************************* - /// Inserts a value to the map. - /// If asserts or exceptions are enabled, emits map_full if the map is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - bool inserted = false; - - ETL_ASSERT(!full(), ETL_ERROR(map_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - inserted = inserted_node == &node; - - // Insert node into tree and return iterator to new node location in tree - return std::make_pair(iterator(*this, inserted_node), inserted); - } - - //********************************************************************* - /// Inserts a value to the map starting at the position recommended. - /// If asserts or exceptions are enabled, emits map_full if the map is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator, const value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(map_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a value to the map starting at the position recommended. - /// If asserts or exceptions are enabled, emits map_full if the map is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator, const value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(map_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a range of values to the map. - /// If asserts or exceptions are enabled, emits map_full if the map does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go before the key provided or end() - /// if all keys are considered to go before the key provided. - ///\return An iterator pointing to the element not before key or end() - //********************************************************************* - iterator lower_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go before the key provided - /// or end() if all keys are considered to go before the key provided. - ///\return An const_iterator pointing to the element not before key or end() - //********************************************************************* - const_iterator lower_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go after the key provided or end() - /// if all keys are considered to go after the key provided. - ///\return An iterator pointing to the element after key or end() - //********************************************************************* - iterator upper_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_upper_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go after the key provided - /// or end() if all keys are considered to go after the key provided. - ///\return An const_iterator pointing to the element after key or end() - //********************************************************************* - const_iterator upper_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_upper_node(root_node, key)); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - imap& operator = (const imap& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - imap(ipool& node_pool, size_t max_size_) - : map_base(max_size_) - , p_node_pool(&node_pool) - { - } - - //************************************************************************* - /// Initialise the map. - //************************************************************************* - void initialise() - { - erase(begin(), end()); - } - - private: - - //************************************************************************* - /// Allocate a Data_Node. - //************************************************************************* - Data_Node& allocate_data_node(value_type value) - { - Data_Node& node = *p_node_pool->allocate(); - ::new (&node.value) const value_type(value); - ++construct_count; - return node; - } - - //************************************************************************* - /// Destroy a Data_Node. - //************************************************************************* - void destroy_data_node(Data_Node& node) - { - node.value.~value_type(); - p_node_pool->release(&node); - --construct_count; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - Node* find_node(Node* position, const key_value_parameter_t& key) - { - Node* found = position; - while (found) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = imap::data_cast(*found); - - // Compare the node value to the current position value - if (node_comp(key, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, key)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Node that matches the key provided was found, exit loop - break; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - const Node* find_node(const Node* position, const key_value_parameter_t& key) const - { - const Node* found = position; - while (found) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& found_data_node = imap::data_cast(*found); - - // Compare the node value to the current position value - if (node_comp(key, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, key)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Node that matches the key provided was found, exit loop - break; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the reference node matching the node provided - //************************************************************************* - Node*& find_node(Node*& position, const Node* node) - { - Node* found = position; - while (found) - { - if (found->children[kLeft] == node) - { - return found->children[kLeft]; - } - else if (found->children[kRight] == node) - { - return found->children[kRight]; - } - else - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = imap::data_cast(*found); - const Data_Node& data_node = imap::data_cast(*node); - - // Compare the node value to the current position value - if (node_comp(data_node, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, data_node)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Return position provided (it matches the node) - return position; - } - } - } - - // Return root node if nothing was found - return root_node; - } - - //************************************************************************* - /// Find the parent node that contains the node provided in its left or - /// right tree - //************************************************************************* - Node* find_parent_node(Node* position, const Node* node) - { - // Default to no parent node found - Node* found = nullptr; - - // If the position provided is the same as the node then there is no parent - if (position && node && position != node) - { - while (position) - { - // Is this position not the parent of the node we are looking for? - if (position->children[kLeft] != node && - position->children[kRight] != node) - { - // Downcast node and position to Data_Node references for key comparisons - const Data_Node& node_data_node = imap::data_cast(*node); - Data_Node& position_data_node = imap::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(node_data_node, position_data_node)) - { - // Keep looking for parent on the left - position = position->children[kLeft]; - } - else if (node_comp(position_data_node, node_data_node)) - { - // Keep looking for parent on the right - position = position->children[kRight]; - } - } - else - { - // Return the current position as the parent node found - found = position; - - // Parent node found, exit loop - break; - } - } - } - - // Return the parent node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the parent node that contains the node provided in its left or - /// right tree - //************************************************************************* - const Node* find_parent_node(const Node* position, const Node* node) const - { - // Default to no parent node found - const Node* found = nullptr; - - // If the position provided is the same as the node then there is no parent - if (position && node && position != node) - { - while (position) - { - // Is this position not the parent of the node we are looking for? - if (position->children[kLeft] != node && - position->children[kRight] != node) - { - // Downcast node and position to Data_Node references for key comparisons - const Data_Node& node_data_node = imap::data_cast(*node); - const Data_Node& position_data_node = imap::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(node_data_node, position_data_node)) - { - // Keep looking for parent on the left - position = position->children[kLeft]; - } - else if (node_comp(position_data_node, node_data_node)) - { - // Keep looking for parent on the right - position = position->children[kRight]; - } - } - else - { - // Return the current position as the parent node found - found = position; - - // Parent node found, exit loop - break; - } - } - } - - // Return the parent node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the node whose key is not considered to go before the key provided - //************************************************************************* - Node* find_lower_node(Node* position, const key_value_parameter_t& key) const - { - // Something at this position? keep going - Node* lower_node = position; - while (lower_node) - { - // Downcast lower node to Data_Node reference for key comparisons - Data_Node& data_node = imap::data_cast(*lower_node); - // Compare the key value to the current lower node key value - if (node_comp(key, data_node)) - { - if (lower_node->children[kLeft]) - { - lower_node = lower_node->children[kLeft]; - } - else - { - // Found lowest node - break; - } - } - else if (node_comp(data_node, key)) - { - lower_node = lower_node->children[kRight]; - } - else - { - // Found equal node - break; - } - } - - // Return the lower_node position found - return lower_node; - } - - //************************************************************************* - /// Find the node whose key is considered to go after the key provided - //************************************************************************* - Node* find_upper_node(Node* position, const key_value_parameter_t& key) const - { - // Keep track of parent of last upper node - Node* upper_node = nullptr; - // Start with position provided - Node* node = position; - while (node) - { - // Downcast position to Data_Node reference for key comparisons - Data_Node& data_node = imap::data_cast(*node); - // Compare the key value to the current upper node key value - if (node_comp(key, data_node)) - { - upper_node = node; - node = node->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - node = node->children[kRight]; - } - else if (node->children[kRight]) - { - upper_node = find_limit_node(node->children[kRight], kLeft); - break; - } - else - { - break; - } - } - - // Return the upper node position found (might be nullptr) - return upper_node; - } - - //************************************************************************* - /// Insert a node. - //************************************************************************* - Node* insert_node(Node*& position, Data_Node& node) - { - // Find the location where the node belongs - Node* found = position; - - // Was position provided not empty? then find where the node belongs - if (position) - { - // Find the critical parent node (default to nullptr) - Node* critical_parent_node = nullptr; - Node* critical_node = root_node; - - while (found) - { - // Search for critical weight node (all nodes whose weight factor - // is set to kNeither (balanced) - if (kNeither != found->weight) - { - critical_node = found; - } - - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = imap::data_cast(*found); - - // Is the node provided to the left of the current position? - if (node_comp(node, found_data_node)) - { - // Update direction taken to insert new node in parent node - found->dir = kLeft; - } - // Is the node provided to the right of the current position? - else if (node_comp(found_data_node, node)) - { - // Update direction taken to insert new node in parent node - found->dir = kRight; - } - else - { - // Update direction taken to insert new node in parent node - found->dir = kNeither; - - // Clear critical node value to skip weight step below - critical_node = nullptr; - - // Destroy the node provided (its a duplicate) - destroy_data_node(node); - - // Exit loop, duplicate node found - break; - } - - // Is there a child of this parent node? - if (found->children[found->dir]) - { - // Will this node be the parent of the next critical node whose - // weight factor is set to kNeither (balanced)? - if (kNeither != found->children[found->dir]->weight) - { - critical_parent_node = found; - } - - // Keep looking for empty spot to insert new node - found = found->children[found->dir]; - } - else - { - // Attatch node to right - attach_node(found->children[found->dir], node); - - // Return newly added node - found = found->children[found->dir]; - - // Exit loop - break; - } - } - - // Was a critical node found that should be checked for balance? - if (critical_node) - { - if (critical_parent_node == nullptr && critical_node == root_node) - { - balance_node(root_node); - } - else if (critical_parent_node == nullptr && critical_node == position) - { - balance_node(position); - } - else - { - balance_node(critical_parent_node->children[critical_parent_node->dir]); - } - } - } - else - { - // Attatch node to current position - attach_node(position, node); - - // Return newly added node at current position - found = position; - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the next node in sequence from the node provided - //************************************************************************* - void next_node(Node*&position) - { - 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 = 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 = 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 previous node in sequence from the node provided - //************************************************************************* - void prev_node(Node*&position) - { - // 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 = find_parent_node(root_node, position); - // 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 = find_parent_node(root_node, position); - // 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 - //************************************************************************* - Node* remove_node(Node*& position, const key_value_parameter_t& key) - { - // Step 1: Find the target node that matches the key provided, the - // replacement node (might be the same as target node), and the critical - // node to start rebalancing the tree from (up to the replacement node) - Node* found_parent = nullptr; - Node* found = nullptr; - Node* replace_parent = nullptr; - Node* replace = position; - Node* balance_parent = nullptr; - Node* balance = root_node; - while (replace) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& replace_data_node = imap::data_cast(*replace); - - // Compare the key provided to the replace data node key - if (node_comp(key, replace_data_node)) - { - // Update the direction to the target/replace node - replace->dir = kLeft; - } - else if (node_comp(replace_data_node, key)) - { - // Update the direction to the target/replace node - replace->dir = kRight; - } - else - { - // Update the direction to the replace node (target node found here) - replace->dir = replace->children[kLeft] ? kLeft : kRight; - - // Note the target node was found (and its parent) - found_parent = replace_parent; - found = replace; - } - // Replacement node found if its missing a child in the replace->dir - // value set above - if (replace->children[replace->dir] == nullptr) - { - // Exit loop once replace node is found (target might not have been) - break; - } - - // If replacement node weight is kNeither or we are taking the shorter - // path of replacement node and our sibling (on longer path) is - // balanced then we need to update the balance node to match this - // replacement node but all our ancestors will not require rebalancing - if ((replace->weight == kNeither) || - (replace->weight == (1 - replace->dir) && - replace->children[1 - replace->dir]->weight == kNeither)) - { - // Update balance node (and its parent) to replacement node - balance_parent = replace_parent; - balance = replace; - } - - // Keep searching for the replacement node - replace_parent = replace; - replace = replace->children[replace->dir]; - } - - // If target node was found, proceed with rebalancing and replacement - if (found) - { - // Step 2: Update weights from critical node to replacement parent node - while (balance) - { - if (balance->children[balance->dir] == nullptr) - { - break; - } - - if (balance->weight == kNeither) - { - balance->weight = 1 - balance->dir; - } - else if (balance->weight == balance->dir) - { - balance->weight = kNeither; - } - else - { - int weight = balance->children[1 - balance->dir]->weight; - // Perform a 3 node rotation if weight is same as balance->dir - if (weight == balance->dir) - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_3node(root_node, 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - else - { - rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - } - // Already balanced, rebalance and make it heavy in opposite - // direction of the node being removed - else if (weight == kNeither) - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - root_node->weight = balance->dir; - } - else - { - rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir); - balance_parent->children[balance_parent->dir]->weight = balance->dir; - } - // Update balance node weight in opposite direction of node removed - balance->weight = 1 - balance->dir; - } - // Rebalance and leave it balanced - else - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - } - else - { - rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir); - } - } - - // Is balance node the same as the target node found? then update - // its parent after the rotation performed above - if (balance == found) - { - if (balance_parent) - { - found_parent = balance_parent->children[balance_parent->dir]; - // Update dir since it is likely stale - found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight; - } - else - { - found_parent = root_node; - root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight; - } - } - } - - // Next balance node to consider - balance_parent = balance; - balance = balance->children[balance->dir]; - } // while(balance) - - // Step 3: Swap found node with replacement node - if (found_parent) - { - // Handle traditional case - detach_node(found_parent->children[found_parent->dir], - replace_parent->children[replace_parent->dir]); - } - // Handle root node removal - else - { - // Valid replacement node for root node being removed? - if (replace_parent) - { - detach_node(root_node, replace_parent->children[replace_parent->dir]); - } - else - { - // Target node and replacement node are both root node - detach_node(root_node, root_node); - } - } - - // Downcast found into data node - Data_Node& found_data_node = imap::data_cast(*found); - - // One less. - --current_size; - - // Destroy the node removed - destroy_data_node(found_data_node); - } // if(found) - - // Return node found (might be nullptr) - return found; - } - - // Disable copy construction. - imap(const imap&); - }; -} - -//*************************************************************************** -/// Equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator ==(const etl::imap& lhs, const etl::imap& rhs) -{ - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//*************************************************************************** -/// Not equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are not equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator !=(const etl::imap& lhs, const etl::imap& 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 lexicographically less than the -/// second, otherwise false. -//************************************************************************* -template -bool operator <(const etl::imap& lhs, const etl::imap& 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 lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::imap& lhs, const etl::imap& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// 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 lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::imap& lhs, const etl::imap& rhs) -{ - return !(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 lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::imap& lhs, const etl::imap& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_IMAP_H__ - -#endif diff --git a/src/imultimap.h b/src/imultimap.h deleted file mode 100644 index d9cc7084..00000000 --- a/src/imultimap.h +++ /dev/null @@ -1,1423 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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. -******************************************************************************/ - -#ifndef __ETL_IMULTIMAP__ -#define __ETL_IMULTIMAP__ -#define __ETL_IN_IMULTIMAP_H__ - -#include -#include -#include -#include - -#include "nullptr.h" -#include "private/multimap_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "pool.h" -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::multimap types. - ///\ingroup map - //*************************************************************************** - template - class imultimap : public multimap_base - { - public: - - typedef std::pair value_type; - typedef const TKey key_type; - typedef TMapped mapped_type; - typedef TKeyCompare key_compare; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - /// How to compare two key elements. - //************************************************************************* - struct key_comp - { - bool operator ()(const key_type& key1, const key_type& key2) const - { - return key_compare()(key1, key2); - } - }; - - //************************************************************************* - /// How to compare two value elements. - //************************************************************************* - struct value_comp - { - bool operator ()(const value_type& value1, const value_type& value2) const - { - return key_compare()(value1.first, value2.first); - } - }; - - protected: - - //************************************************************************* - /// The data node element in the multimap. - //************************************************************************* - struct Data_Node : public Node - { - explicit Data_Node(value_type value) - : value(value) - { - } - - value_type value; - }; - - /// Defines the key value parameter type - typedef typename parameter_type::type key_value_parameter_t; - - //************************************************************************* - /// How to compare node elements. - //************************************************************************* - bool node_comp(const Data_Node& node1, const Data_Node& node2) const - { - 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); - } - - private: - - /// The pool of data nodes used in the multimap. - ipool* p_node_pool; - - //************************************************************************* - /// Downcast a Node* to a Data_Node* - //************************************************************************* - static Data_Node* data_cast(Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a Node& to a Data_Node& - //************************************************************************* - static Data_Node& data_cast(Node& node) - { - return static_cast(node); - } - - //************************************************************************* - /// Downcast a const Node* to a const Data_Node* - //************************************************************************* - static const Data_Node* data_cast(const Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a const Node& to a const Data_Node& - //************************************************************************* - static const Data_Node& data_cast(const Node& node) - { - return static_cast(node); - } - - public: - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class imultimap; - - iterator() - : p_multimap(nullptr) - , p_node(nullptr) - { - } - - iterator(imultimap& multimap) - : p_multimap(&multimap) - , p_node(nullptr) - { - } - - iterator(imultimap& multimap, Node* node) - : p_multimap(&multimap) - , p_node(node) - { - } - - iterator(const iterator& other) - : p_multimap(other.p_multimap) - , p_node(other.p_node) - { - } - - ~iterator() - { - } - - iterator& operator ++() - { - p_multimap->next_node(p_node); - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - p_multimap->next_node(p_node); - return temp; - } - - iterator& operator --() - { - p_multimap->prev_node(p_node); - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - p_multimap->prev_node(p_node); - return temp; - } - - iterator operator =(const iterator& other) - { - p_multimap = other.p_multimap; - p_node = other.p_node; - return *this; - } - - reference operator *() - { - return imultimap::data_cast(p_node)->value; - } - - const_reference operator *() const - { - return imultimap::data_cast(p_node)->value; - } - - pointer operator &() - { - return &(imultimap::data_cast(p_node)->value); - } - - const_pointer operator &() const - { - return &(imultimap::data_cast(p_node)->value); - } - - pointer operator ->() - { - return &(imultimap::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(imultimap::data_cast(p_node)->value); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.p_multimap == rhs.p_multimap && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - // Pointer to multimap associated with this iterator - imultimap* p_multimap; - - // Pointer to the current node for this iterator - Node* p_node; - }; - friend class iterator; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class imultimap; - - const_iterator() - : p_multimap(nullptr) - , p_node(nullptr) - { - } - - const_iterator(const imultimap& multimap) - : p_multimap(&multimap) - , p_node(nullptr) - { - } - - const_iterator(const imultimap& multimap, const Node* node) - : p_multimap(&multimap) - , p_node(node) - { - } - - const_iterator(const typename imultimap::iterator& other) - : p_multimap(other.p_multimap) - , p_node(other.p_node) - { - } - - const_iterator(const const_iterator& other) - : p_multimap(other.p_multimap) - , p_node(other.p_node) - { - } - - ~const_iterator() - { - } - - const_iterator& operator ++() - { - p_multimap->next_node(p_node); - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - p_multimap->next_node(p_node); - return temp; - } - - const_iterator& operator --() - { - p_multimap->prev_node(p_node); - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - p_multimap->prev_node(p_node); - return temp; - } - - const_iterator operator =(const const_iterator& other) - { - p_multimap = other.p_multimap; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return imultimap::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return imultimap::data_cast(p_node)->value; - } - - const_pointer operator ->() const - { - return &(imultimap::data_cast(p_node)->value); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.p_multimap == rhs.p_multimap && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - // Pointer to multimap associated with this iterator - const imultimap* p_multimap; - - // Pointer to the current node for this iterator - const Node* p_node; - }; - friend class const_iterator; - - 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 multimap. - //************************************************************************* - iterator begin() - { - return iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the beginning of the multimap. - //************************************************************************* - const_iterator begin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the multimap. - //************************************************************************* - iterator end() - { - return iterator(*this); - } - - //************************************************************************* - /// Gets the end of the multimap. - //************************************************************************* - const_iterator end() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the beginning of the multimap. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the multimap. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft))); - } - - //********************************************************************* - /// Assigns values to the multimap. - /// If asserts or exceptions are enabled, emits map_full if the multimap does not have enough free space. - /// If asserts or exceptions are enabled, emits map_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { - initialise(); - insert(first, last); - } - - //************************************************************************* - /// Clears the multimap. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts the number of elements that contain the key specified. - ///\param key The key to search for. - ///\return 1 if element was found, 0 otherwise. - //********************************************************************* - size_type count(const key_value_parameter_t& key) const - { - return count_nodes(key); - } - - //************************************************************************* - /// Returns two iterators with bounding (lower bound, upper bound) the key - /// provided - //************************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - return std::make_pair( - iterator(*this, find_lower_node(root_node, key)), - iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Returns two const iterators with bounding (lower bound, upper bound) - /// the key provided. - //************************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - return std::make_pair( - const_iterator(*this, find_lower_node(root_node, key)), - const_iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - void erase(iterator position) - { - // Remove the node by its node specified in iterator position - (void)erase(const_iterator(position)); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase(const_iterator position) - { - // Cast const away from node to be removed. This is necessary because the - // STL definition of this method requires we provide the next node in the - // sequence as an iterator. - Node* node = const_cast(position.p_node); - iterator next(*this, node); - ++next; - - // Remove the non-const node provided - remove_node(node); - - return next; - } - - //************************************************************************* - // Erase the key specified. - //************************************************************************* - size_type erase(const key_value_parameter_t& key) - { - // Number of nodes removed - size_type count = 0; - const_iterator lower(*this, find_lower_node(root_node, key)); - const_iterator upper(*this, find_upper_node(root_node, key)); - while (lower != upper) - { - // Increment count for each node removed - ++count; - // Remove node using the other erase method - (void)erase(lower++); - } - - // Return the total count erased - return count; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(iterator first, iterator last) - { - iterator next; - while (first != last) - { - next = erase(const_iterator(first++)); - } - - return next; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - iterator next; - while (first != last) - { - next = erase(first++); - } - - return next; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(const key_value_parameter_t& key) - { - return iterator(*this, find_node(root_node, key)); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_node(root_node, key)); - } - - //********************************************************************* - /// Inserts a value to the multimap. - /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(multimap_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a value to the multimap starting at the position recommended. - /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator /*position*/, const value_type& value) - { - // Ignore position provided and just do a normal insert - return insert(value); - } - - //********************************************************************* - /// Inserts a value to the multimap starting at the position recommended. - /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator /*position*/, const value_type& value) - { - // Ignore position provided and just do a normal insert - return insert(value); - } - - //********************************************************************* - /// Inserts a range of values to the multimap. - /// If asserts or exceptions are enabled, emits map_full if the multimap does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go before the key provided or end() - /// if all keys are considered to go before the key provided. - ///\return An iterator pointing to the element not before key or end() - //********************************************************************* - iterator lower_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go before the key provided - /// or end() if all keys are considered to go before the key provided. - ///\return An const_iterator pointing to the element not before key or end() - //********************************************************************* - const_iterator lower_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go after the key provided or end() - /// if all keys are considered to go after the key provided. - ///\return An iterator pointing to the element after key or end() - //********************************************************************* - iterator upper_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_upper_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go after the key provided - /// or end() if all keys are considered to go after the key provided. - ///\return An const_iterator pointing to the element after key or end() - //********************************************************************* - const_iterator upper_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_upper_node(root_node, key)); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - imultimap& operator = (const imultimap& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - imultimap(ipool& node_pool, size_t max_size_) - : multimap_base(max_size_) - , p_node_pool(&node_pool) - { - } - - //************************************************************************* - /// Initialise the multimap. - //************************************************************************* - void initialise() - { - erase(begin(), end()); - } - - private: - - //************************************************************************* - /// Allocate a Data_Node. - //************************************************************************* - Data_Node& allocate_data_node(value_type value) - { - Data_Node& node = *p_node_pool->allocate(); - ::new (&node.value) const value_type(value); - ++construct_count; - return node; - } - - //************************************************************************* - /// Destroy a Data_Node. - //************************************************************************* - void destroy_data_node(Data_Node& node) - { - node.value.~value_type(); - p_node_pool->release(&node); - --construct_count; - } - - //************************************************************************* - /// Count the nodes that match the key provided - //************************************************************************* - size_type count_nodes(const key_value_parameter_t& key) const - { - // Number of nodes that match the key provided result - size_type result = 0; - - // Find lower and upper nodes for the key provided - const Node* lower = find_lower_node(root_node, key); - const Node* upper = find_upper_node(root_node, key); - - // Loop from lower node to upper node and find nodes that match - while (lower != upper) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& data_node = imultimap::data_cast(*lower); - - if (!node_comp(key, data_node) && !node_comp(data_node, key)) - { - // This node matches the key provided - ++result; - } - - // Move on to the next node - next_node(lower); - } - - // Return the number of nodes that match - return result; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - Node* find_node(Node* position, const key_value_parameter_t& key) const - { - Node* found = nullptr; - while (position) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& data_node = imultimap::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(key, data_node)) - { - // Keep searching for the node on the left - position = position->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - // Keep searching for the node on the right - position = position->children[kRight]; - } - else - { - // We found one, keep looking for more on the left - found = position; - position = position->children[kLeft]; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - const Node* find_node(const Node* position, const key_value_parameter_t& key) const - { - const Node* found = nullptr; - while (position) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& data_node = imultimap::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(key, data_node)) - { - // Keep searching for the node on the left - position = position->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - // Keep searching for the node on the right - position = position->children[kRight]; - } - else - { - // We found one, keep looking for more on the left - found = position; - position = position->children[kLeft]; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the node whose key is not considered to go before the key provided - //************************************************************************* - Node* find_lower_node(Node* position, const key_value_parameter_t& key) const - { - // Something at this position? keep going - Node* lower_node = nullptr; - while (position) - { - // Downcast lower node to Data_Node reference for key comparisons - Data_Node& data_node = imultimap::data_cast(*position); - // Compare the key value to the current lower node key value - if (node_comp(key, data_node)) - { - lower_node = position; - if (position->children[kLeft]) - { - position = position->children[kLeft]; - } - else - { - // Found lowest node - break; - } - } - else if (node_comp(data_node, key)) - { - position = position->children[kRight]; - } - else - { - // Make note of current position, but keep looking to left for more - lower_node = position; - position = position->children[kLeft]; - } - } - - // Return the lower_node position found - return lower_node; - } - - //************************************************************************* - /// Find the node whose key is considered to go after the key provided - //************************************************************************* - Node* find_upper_node(Node* position, const key_value_parameter_t& key) const - { - // Keep track of parent of last upper node - Node* upper_node = nullptr; - // Has an equal node been found? start with no - bool found = false; - while (position) - { - // Downcast position to Data_Node reference for key comparisons - Data_Node& data_node = imultimap::data_cast(*position); - // Compare the key value to the current upper node key value - if (node_comp(data_node, key)) - { - position = position->children[kRight]; - } - else if (node_comp(key, data_node)) - { - upper_node = position; - // If a node equal to key hasn't been found go left - if (!found && position->children[kLeft]) - { - position = position->children[kLeft]; - } - else - { - break; - } - } - else - { - // We found an equal item, break on next bigger item - found = true; - next_node(position); - } - } - - // Return the upper node position found (might be nullptr) - return upper_node; - } - - //************************************************************************* - /// Insert a node. - //************************************************************************* - Node* insert_node(Node*& position, Data_Node& node) - { - // Find the location where the node belongs - Node* found = position; - - // Was position provided not empty? then find where the node belongs - if (position) - { - // Find the critical parent node (default to nullptr) - Node* critical_parent_node = nullptr; - Node* critical_node = root_node; - - while (found) - { - // Search for critical weight node (all nodes whose weight factor - // is set to kNeither (balanced) - if (kNeither != found->weight) - { - critical_node = found; - } - - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = imultimap::data_cast(*found); - - // Is the node provided to the left of the current position? - if (node_comp(node, found_data_node)) - { - // Update direction taken to insert new node in parent node - found->dir = kLeft; - } - // Is the node provided to the right of the current position? - else if (node_comp(found_data_node, node)) - { - // Update direction taken to insert new node in parent node - found->dir = kRight; - } - else - { - // Update direction taken to insert new node in parent (and - // duplicate) node to the right. - found->dir = kRight; - } - - // Is there a child of this parent node? - if (found->children[found->dir]) - { - // Will this node be the parent of the next critical node whose - // weight factor is set to kNeither (balanced)? - if (kNeither != found->children[found->dir]->weight) - { - critical_parent_node = found; - } - - // Keep looking for empty spot to insert new node - found = found->children[found->dir]; - } - else - { - // Attach node as a child of the parent node found - attach_node(found, found->children[found->dir], node); - - // Return newly added node - found = found->children[found->dir]; - - // Exit loop - break; - } - } - - // Was a critical node found that should be checked for balance? - if (critical_node) - { - if (critical_parent_node == nullptr && critical_node == root_node) - { - balance_node(root_node); - } - else if (critical_parent_node == nullptr && critical_node == position) - { - balance_node(position); - } - else - { - balance_node(critical_parent_node->children[critical_parent_node->dir]); - } - } - } - else - { - // Attach node to current position (which is assumed to be root) - attach_node(nullptr, position, node); - - // Return newly added node at current position - found = position; - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Remove the node specified from somewhere starting at the position - /// provided - //************************************************************************* - void remove_node(Node* node) - { - // If valid found node was provided then proceed with steps 1 through 5 - if (node) - { - // Downcast found node provided to Data_Node class - Data_Node& data_node = imultimap::data_cast(*node); - - // Keep track of node as found node - Node* found = node; - - // Step 1: Mark path from node provided back to the root node using the - // internal temporary dir member value and using the parent pointer. This - // will allow us to avoid recursion in finding the node in a tree that - //might contain duplicate keys to be found. - while (node) - { - if (node->parent) - { - // Which direction does parent use to get to this node? - node->parent->dir = - node->parent->children[kLeft] == node ? kLeft : kRight; - - // Make this nodes parent the next node - node = node->parent; - } - else - { - // Root node found - break loop - break; - } - } - - // Step 2: Follow the path provided above until we reach the node - // provided and look for the balance node to start rebalancing the tree - // from (up to the replacement node that will be found in step 3) - Node* balance = root_node; - while (node) - { - // Did we reach the node provided originally (found) then go to step 3 - if (node == found) - { - // Update the direction towards a replacement node at the found node - node->dir = node->children[kLeft] ? kLeft : kRight; - - // Exit loop and proceed with step 3 - break; - } - else - { - // If this nodes weight is kNeither or we are taking the shorter path - // to the next node and our sibling (on longer path) is balanced then - // we need to update the balance node to this node but all our - // ancestors will not require rebalancing - if ((node->weight == kNeither) || - (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) - { - // Update balance node to this node - balance = node; - } - - // Keep searching for found in the direction provided in step 1 - node = node->children[node->dir]; - } - } - // The value for node should not be nullptr at this point otherwise - // step 1 failed to provide the correct path to found. Step 5 will fail - // (probably subtly) if node should be nullptr at this point - - // Step 3: Find the node (node should be equal to found at this point) - // to replace found with (might end up equal to found) while also - // continuing to update balance the same as in step 2 above. - while (node) - { - // Replacement node found if its missing a child in the replace->dir - // value set at the end of step 2 above - if (node->children[node->dir] == nullptr) - { - // Exit loop once node to replace found is determined - break; - } - - // If this nodes weight is kNeither or we are taking the shorter path - // to the next node and our sibling (on longer path) is balanced then - // we need to update the balance node to this node but all our - // ancestors will not require rebalancing - if ((node->weight == kNeither) || - (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) - { - // Update balance node to this node - balance = node; - } - - // Keep searching for replacement node in the direction specified above - node = node->children[node->dir]; - - // Downcast node to Data_Node class for comparison operations - Data_Node& replace_data_node = imultimap::data_cast(*node); - - // Compare the key provided to the replace data node key - if (node_comp(data_node, replace_data_node)) - { - // Update the direction to the replace node - node->dir = kLeft; - } - else if (node_comp(replace_data_node, data_node)) - { - // Update the direction to the replace node - node->dir = kRight; - } - else - { - // Update the direction to the replace node - node->dir = node->children[kLeft] ? kLeft : kRight; - } - } // while(node) - - // Step 4: Update weights from balance to parent of node determined - // in step 3 above rotating (2 or 3 node rotations) as needed. - while (balance) - { - // Break when balance node reaches the parent of replacement node - if (balance->children[balance->dir] == nullptr) - { - break; - } - - // If balance node is balanced already (kNeither) then just imbalance - // the node in the opposite direction of the node being removed - if (balance->weight == kNeither) - { - balance->weight = 1 - balance->dir; - } - // If balance node is imbalanced in the opposite direction of the - // node being removed then the node now becomes balanced - else if (balance->weight == balance->dir) - { - balance->weight = kNeither; - } - // Otherwise a rotation is required at this node - else - { - int weight = balance->children[1 - balance->dir]->weight; - // Perform a 3 node rotation if weight is same as balance->dir - if (weight == balance->dir) - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_3node(root_node, 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - else - { - rotate_3node(balance->parent->children[balance->parent->dir], 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - } - // Already balanced, rebalance and make it heavy in opposite - // direction of the node being removed - else if (weight == kNeither) - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - root_node->weight = balance->dir; - } - else - { - // Balance parent might change during rotate, keep local copy - // to old parent so its weight can be updated after the 2 node - // rotate is completed - Node* old_parent = balance->parent; - rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir); - old_parent->children[old_parent->dir]->weight = balance->dir; - } - // Update balance node weight in opposite direction of node removed - balance->weight = 1 - balance->dir; - } - // Rebalance and leave it balanced - else - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - } - else - { - rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir); - } - } - } - - // Next balance node to consider - balance = balance->children[balance->dir]; - } // while(balance) - - // Step 5: Swap found with node (replacement) - if (found->parent) - { - // Handle traditional case - detach_node(found->parent->children[found->parent->dir], - node->parent->children[node->parent->dir]); - } - // Handle root node removal - else - { - // Valid replacement node for root node being removed? - if (node->parent) - { - detach_node(root_node, node->parent->children[node->parent->dir]); - } - else - { - // Found node and replacement node are both root node - detach_node(root_node, root_node); - } - } - - // One less. - --current_size; - - // Destroy the node detached above - destroy_data_node(data_node); - } // if(found) - } - - // Disable copy construction. - imultimap(const imultimap&); - }; -} - -//*************************************************************************** -/// Equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator ==(const etl::imultimap& lhs, const etl::imultimap& rhs) -{ - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//*************************************************************************** -/// Not equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are not equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator !=(const etl::imultimap& lhs, const etl::imultimap& 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 lexicographically less than the -/// second, otherwise false. -//************************************************************************* -template -bool operator <(const etl::imultimap& lhs, const etl::imultimap& 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 lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::imultimap& lhs, const etl::imultimap& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// 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 lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::imultimap& lhs, const etl::imultimap& rhs) -{ - return !(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 lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::imultimap& lhs, const etl::imultimap& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_IMULTIMAP_H__ - -#endif diff --git a/src/imultiset.h b/src/imultiset.h deleted file mode 100644 index 632c7f91..00000000 --- a/src/imultiset.h +++ /dev/null @@ -1,1404 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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. -******************************************************************************/ - -#ifndef __ETL_IMULTISET__ -#define __ETL_IMULTISET__ -#define __ETL_IN_IMULTISET_H__ - -#include -#include -#include -#include - -#include "nullptr.h" -#include "private/multiset_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "pool.h" -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::multiset types. - ///\ingroup set - //*************************************************************************** - template - class imultiset : public multiset_base - { - public: - - typedef const T key_type; - typedef const T value_type; - typedef TCompare key_compare; - typedef TCompare value_compare; - typedef value_type& const_reference; - typedef value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - /// How to compare two key elements. - //************************************************************************* - struct key_comp - { - bool operator ()(key_type& key1, key_type& key2) const - { - return key_compare()(key1, key2); - } - }; - - //************************************************************************* - /// How to compare two value elements. - //************************************************************************* - struct value_comp - { - bool operator ()(value_type& value1, value_type& value2) const - { - return value_compare()(value1, value2); - } - }; - - protected: - - //************************************************************************* - /// The data node element in the multiset. - //************************************************************************* - struct Data_Node : public Node - { - explicit Data_Node(value_type value) - : value(value) - { - } - - value_type value; - }; - - /// Defines the key value parameter type - typedef typename parameter_type::type key_value_parameter_t; - - //************************************************************************* - /// How to compare node elements. - //************************************************************************* - bool node_comp(const Data_Node& node1, const Data_Node& node2) const - { - return key_compare()(node1.value, node2.value); - } - bool node_comp(const Data_Node& node, const key_value_parameter_t& key) const - { - return key_compare()(node.value, key); - } - bool node_comp(const key_value_parameter_t& key, const Data_Node& node) const - { - return key_compare()(key, node.value); - } - - private: - - /// The pool of data nodes used in the multiset. - ipool* p_node_pool; - - //************************************************************************* - /// Downcast a Node* to a Data_Node* - //************************************************************************* - static Data_Node* data_cast(Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a Node& to a Data_Node& - //************************************************************************* - static Data_Node& data_cast(Node& node) - { - return static_cast(node); - } - - //************************************************************************* - /// Downcast a const Node* to a const Data_Node* - //************************************************************************* - static const Data_Node* data_cast(const Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a const Node& to a const Data_Node& - //************************************************************************* - static const Data_Node& data_cast(const Node& node) - { - return static_cast(node); - } - - public: - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class imultiset; - - iterator() - : p_multiset(nullptr) - , p_node(nullptr) - { - } - - iterator(imultiset& multiset) - : p_multiset(&multiset) - , p_node(nullptr) - { - } - - iterator(imultiset& multiset, Node* node) - : p_multiset(&multiset) - , p_node(node) - { - } - - iterator(const iterator& other) - : p_multiset(other.p_multiset) - , p_node(other.p_node) - { - } - - ~iterator() - { - } - - iterator& operator ++() - { - p_multiset->next_node(p_node); - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - p_multiset->next_node(p_node); - return temp; - } - - iterator& operator --() - { - p_multiset->prev_node(p_node); - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - p_multiset->prev_node(p_node); - return temp; - } - - iterator operator =(const iterator& other) - { - p_multiset = other.p_multiset; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return imultiset::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return &(imultiset::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(imultiset::data_cast(p_node)->value); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.p_multiset == rhs.p_multiset && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - // Pointer to multiset associated with this iterator - imultiset* p_multiset; - - // Pointer to the current node for this iterator - Node* p_node; - }; - friend class iterator; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class imultiset; - - const_iterator() - : p_multiset(nullptr) - , p_node(nullptr) - { - } - - const_iterator(const imultiset& multiset) - : p_multiset(&multiset) - , p_node(nullptr) - { - } - - const_iterator(const imultiset& multiset, const Node* node) - : p_multiset(&multiset) - , p_node(node) - { - } - - const_iterator(const typename imultiset::iterator& other) - : p_multiset(other.p_multiset) - , p_node(other.p_node) - { - } - - const_iterator(const const_iterator& other) - : p_multiset(other.p_multiset) - , p_node(other.p_node) - { - } - - ~const_iterator() - { - } - - const_iterator& operator ++() - { - p_multiset->next_node(p_node); - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - p_multiset->next_node(p_node); - return temp; - } - - const_iterator& operator --() - { - p_multiset->prev_node(p_node); - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - p_multiset->prev_node(p_node); - return temp; - } - - const_iterator operator =(const const_iterator& other) - { - p_multiset = other.p_multiset; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return imultiset::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return imultiset::data_cast(p_node)->value; - } - - const_pointer operator ->() const - { - return &(imultiset::data_cast(p_node)->value); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.p_multiset == rhs.p_multiset && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - // Pointer to multiset associated with this iterator - const imultiset* p_multiset; - - // Pointer to the current node for this iterator - const Node* p_node; - }; - friend class const_iterator; - - 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 multiset. - //************************************************************************* - iterator begin() - { - return iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the beginning of the multiset. - //************************************************************************* - const_iterator begin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the multiset. - //************************************************************************* - iterator end() - { - return iterator(*this); - } - - //************************************************************************* - /// Gets the end of the multiset. - //************************************************************************* - const_iterator end() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the beginning of the multiset. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the multiset. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft))); - } - - //********************************************************************* - /// Assigns values to the multiset. - /// If asserts or exceptions are enabled, emits set_full if the multiset does not have enough free space. - /// If asserts or exceptions are enabled, emits set_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { - initialise(); - insert(first, last); - } - - //************************************************************************* - /// Clears the multiset. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts the number of elements that contain the key specified. - ///\param key The key to search for. - ///\return 1 if element was found, 0 otherwise. - //********************************************************************* - size_type count(const key_value_parameter_t& key) const - { - return count_nodes(key); - } - - //************************************************************************* - /// Returns two iterators with bounding (lower bound, upper bound) the key - /// provided - //************************************************************************* - std::pair equal_range(const value_type& key) - { - return std::make_pair( - iterator(*this, find_lower_node(root_node, key)), - iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Returns two const iterators with bounding (lower bound, upper bound) - /// the key provided. - //************************************************************************* - std::pair equal_range(const value_type& key) const - { - return std::make_pair( - const_iterator(*this, find_lower_node(root_node, key)), - const_iterator(*this, find_upper_node(root_node, key))); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - void erase(iterator position) - { - // Remove the node by its node specified in iterator position - (void)erase(const_iterator(position)); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase(const_iterator position) - { - // Cast const away from node to be removed. This is necessary because the - // STL definition of this method requires we provide the next node in the - // sequence as an iterator. - Node* node = const_cast(position.p_node); - iterator next(*this, node); - ++next; - - // Remove the non-const node provided - remove_node(node); - - return next; - } - - //************************************************************************* - // Erase the key specified. - //************************************************************************* - size_type erase(const key_value_parameter_t& key_value) - { - // Number of nodes removed - size_type count = 0; - const_iterator lower(*this, find_lower_node(root_node, key_value)); - const_iterator upper(*this, find_upper_node(root_node, key_value)); - while (lower != upper) - { - // Increment count for each node removed - ++count; - // Remove node using the other erase method - (void)erase(lower++); - } - - // Return the total count erased - return count; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(iterator first, iterator last) - { - iterator next; - while (first != last) - { - next = erase(const_iterator(first++)); - } - - return next; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - iterator next; - while (first != last) - { - next = erase(first++); - } - - return next; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(const key_value_parameter_t& key_value) - { - return iterator(*this, find_node(root_node, key_value)); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(const key_value_parameter_t& key_value) const - { - return const_iterator(*this, find_node(root_node, key_value)); - } - - //********************************************************************* - /// Inserts a value to the multiset. - /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(multiset_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a value to the multiset starting at the position recommended. - /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator /*position*/, const value_type& value) - { - // Ignore position provided and just do a normal insert - return insert(value); - } - - //********************************************************************* - /// Inserts a value to the multiset starting at the position recommended. - /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator /*position*/, const value_type& value) - { - // Ignore position provided and just do a normal insert - return insert(value); - } - - //********************************************************************* - /// Inserts a range of values to the multiset. - /// If asserts or exceptions are enabled, emits set_full if the multiset does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go before the key provided or end() - /// if all keys are considered to go before the key provided. - ///\return An iterator pointing to the element not before key or end() - //********************************************************************* - iterator lower_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go before the key provided - /// or end() if all keys are considered to go before the key provided. - ///\return An const_iterator pointing to the element not before key or end() - //********************************************************************* - const_iterator lower_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go after the key provided or end() - /// if all keys are considered to go after the key provided. - ///\return An iterator pointing to the element after key or end() - //********************************************************************* - iterator upper_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_upper_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go after the key provided - /// or end() if all keys are considered to go after the key provided. - ///\return An const_iterator pointing to the element after key or end() - //********************************************************************* - const_iterator upper_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_upper_node(root_node, key)); - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - imultiset& operator = (const imultiset& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - imultiset(ipool& node_pool, size_t max_size_) - : multiset_base(max_size_) - , p_node_pool(&node_pool) - { - } - - //************************************************************************* - /// Initialise the multiset. - //************************************************************************* - void initialise() - { - erase(begin(), end()); - } - - private: - - //************************************************************************* - /// Allocate a Data_Node. - //************************************************************************* - Data_Node& allocate_data_node(value_type value) - { - Data_Node& node = *p_node_pool->allocate(); - ::new ((void*)&node.value) value_type(value); - ++construct_count; - return node; - } - - //************************************************************************* - /// Destroy a Data_Node. - //************************************************************************* - void destroy_data_node(Data_Node& node) - { - node.value.~value_type(); - p_node_pool->release(&node); - --construct_count; - } - - //************************************************************************* - /// Count the nodes that match the key provided - //************************************************************************* - size_type count_nodes(const key_value_parameter_t& key) const - { - // Number of nodes that match the key provided result - size_type result = 0; - - // Find lower and upper nodes for the key provided - const Node* lower = find_lower_node(root_node, key); - const Node* upper = find_upper_node(root_node, key); - - // Loop from lower node to upper node and find nodes that match - while (lower != upper) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& data_node = imultiset::data_cast(*lower); - - if (!node_comp(key, data_node) && !node_comp(data_node, key)) - { - // This node matches the key provided - ++result; - } - - // Move on to the next node - next_node(lower); - } - - // Return the number of nodes that match - return result; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - Node* find_node(Node* position, const key_value_parameter_t& key) const - { - Node* found = nullptr; - while (position) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& data_node = imultiset::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(key, data_node)) - { - // Keep searching for the node on the left - position = position->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - // Keep searching for the node on the right - position = position->children[kRight]; - } - else - { - // We found one, keep looking for more on the left - found = position; - position = position->children[kLeft]; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - const Node* find_node(const Node* position, const key_value_parameter_t& key) const - { - const Node* found = nullptr; - while (position) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& data_node = imultiset::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(key, data_node)) - { - // Keep searching for the node on the left - position = position->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - // Keep searching for the node on the right - position = position->children[kRight]; - } - else - { - // We found one, keep looking for more on the left - found = position; - position = position->children[kLeft]; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the node whose key is not considered to go before the key provided - //************************************************************************* - Node* find_lower_node(Node* position, const key_value_parameter_t& key) const - { - // Something at this position? keep going - Node* lower_node = nullptr; - while (position) - { - // Downcast lower node to Data_Node reference for key comparisons - Data_Node& data_node = imultiset::data_cast(*position); - // Compare the key value to the current lower node key value - if (node_comp(key, data_node)) - { - lower_node = position; - if (position->children[kLeft]) - { - position = position->children[kLeft]; - } - else - { - // Found lowest node - break; - } - } - else if (node_comp(data_node, key)) - { - position = position->children[kRight]; - } - else - { - // Make note of current position, but keep looking to left for more - lower_node = position; - position = position->children[kLeft]; - } - } - - // Return the lower_node position found - return lower_node; - } - - //************************************************************************* - /// Find the node whose key is considered to go after the key provided - //************************************************************************* - Node* find_upper_node(Node* position, const key_value_parameter_t& key) const - { - // Keep track of parent of last upper node - Node* upper_node = nullptr; - // Has an equal node been found? start with no - bool found = false; - while (position) - { - // Downcast position to Data_Node reference for key comparisons - Data_Node& data_node = imultiset::data_cast(*position); - // Compare the key value to the current upper node key value - if (node_comp(data_node, key)) - { - position = position->children[kRight]; - } - else if (node_comp(key, data_node)) - { - upper_node = position; - // If a node equal to key hasn't been found go left - if (!found && position->children[kLeft]) - { - position = position->children[kLeft]; - } - else - { - break; - } - } - else - { - // We found an equal item, break on next bigger item - found = true; - next_node(position); - } - } - - // Return the upper node position found (might be nullptr) - return upper_node; - } - - //************************************************************************* - /// Insert a node. - //************************************************************************* - Node* insert_node(Node*& position, Data_Node& node) - { - // Find the location where the node belongs - Node* found = position; - - // Was position provided not empty? then find where the node belongs - if (position) - { - // Find the critical parent node (default to nullptr) - Node* critical_parent_node = nullptr; - Node* critical_node = root_node; - - while (found) - { - // Search for critical weight node (all nodes whose weight factor - // is set to kNeither (balanced) - if (kNeither != found->weight) - { - critical_node = found; - } - - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = imultiset::data_cast(*found); - - // Is the node provided to the left of the current position? - if (node_comp(node, found_data_node)) - { - // Update direction taken to insert new node in parent node - found->dir = kLeft; - } - // Is the node provided to the right of the current position? - else if (node_comp(found_data_node, node)) - { - // Update direction taken to insert new node in parent node - found->dir = kRight; - } - else - { - // Update direction taken to insert new node in parent (and - // duplicate) node to the right. - found->dir = kRight; - } - - // Is there a child of this parent node? - if (found->children[found->dir]) - { - // Will this node be the parent of the next critical node whose - // weight factor is set to kNeither (balanced)? - if (kNeither != found->children[found->dir]->weight) - { - critical_parent_node = found; - } - - // Keep looking for empty spot to insert new node - found = found->children[found->dir]; - } - else - { - // Attach node as a child of the parent node found - attach_node(found, found->children[found->dir], node); - - // Return newly added node - found = found->children[found->dir]; - - // Exit loop - break; - } - } - - // Was a critical node found that should be checked for balance? - if (critical_node) - { - if (critical_parent_node == nullptr && critical_node == root_node) - { - balance_node(root_node); - } - else if (critical_parent_node == nullptr && critical_node == position) - { - balance_node(position); - } - else - { - balance_node(critical_parent_node->children[critical_parent_node->dir]); - } - } - } - else - { - // Attatch node to current position (which is assumed to be root) - attach_node(nullptr, position, node); - - // Return newly added node at current position - found = position; - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Remove the node specified from somewhere starting at the position - /// provided - //************************************************************************* - void remove_node(Node* node) - { - // If valid found node was provided then proceed with steps 1 through 5 - if (node) - { - // Downcast found node provided to Data_Node class - Data_Node& data_node = imultiset::data_cast(*node); - - // Keep track of node as found node - Node* found = node; - - // Step 1: Mark path from node provided back to the root node using the - // internal temporary dir member value and using the parent pointer. This - // will allow us to avoid recursion in finding the node in a tree that - //might contain duplicate keys to be found. - while (node) - { - if (node->parent) - { - // Which direction does parent use to get to this node? - node->parent->dir = - node->parent->children[kLeft] == node ? kLeft : kRight; - - // Make this nodes parent the next node - node = node->parent; - } - else - { - // Root node found - break loop - break; - } - } - - // Step 2: Follow the path provided above until we reach the node - // provided and look for the balance node to start rebalancing the tree - // from (up to the replacement node that will be found in step 3) - Node* balance = root_node; - while (node) - { - // Did we reach the node provided originally (found) then go to step 3 - if (node == found) - { - // Update the direction towards a replacement node at the found node - node->dir = node->children[kLeft] ? kLeft : kRight; - - // Exit loop and proceed with step 3 - break; - } - else - { - // If this nodes weight is kNeither or we are taking the shorter path - // to the next node and our sibling (on longer path) is balanced then - // we need to update the balance node to this node but all our - // ancestors will not require rebalancing - if ((node->weight == kNeither) || - (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) - { - // Update balance node to this node - balance = node; - } - - // Keep searching for found in the direction provided in step 1 - node = node->children[node->dir]; - } - } - // The value for node should not be nullptr at this point otherwise - // step 1 failed to provide the correct path to found. Step 5 will fail - // (probably subtly) if node should be nullptr at this point - - // Step 3: Find the node (node should be equal to found at this point) - // to replace found with (might end up equal to found) while also - // continuing to update balance the same as in step 2 above. - while (node) - { - // Replacement node found if its missing a child in the replace->dir - // value set at the end of step 2 above - if (node->children[node->dir] == nullptr) - { - // Exit loop once node to replace found is determined - break; - } - - // If this nodes weight is kNeither or we are taking the shorter path - // to the next node and our sibling (on longer path) is balanced then - // we need to update the balance node to this node but all our - // ancestors will not require rebalancing - if ((node->weight == kNeither) || - (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) - { - // Update balance node to this node - balance = node; - } - - // Keep searching for replacement node in the direction specified above - node = node->children[node->dir]; - - // Downcast node to Data_Node class for comparison operations - Data_Node& replace_data_node = imultiset::data_cast(*node); - - // Compare the key provided to the replace data node key - if (node_comp(data_node, replace_data_node)) - { - // Update the direction to the replace node - node->dir = kLeft; - } - else if (node_comp(replace_data_node, data_node)) - { - // Update the direction to the replace node - node->dir = kRight; - } - else - { - // Update the direction to the replace node - node->dir = node->children[kLeft] ? kLeft : kRight; - } - } // while(node) - - // Step 4: Update weights from balance to parent of node determined - // in step 3 above rotating (2 or 3 node rotations) as needed. - while (balance) - { - // Break when balance node reaches the parent of replacement node - if (balance->children[balance->dir] == nullptr) - { - break; - } - - // If balance node is balanced already (kNeither) then just imbalance - // the node in the opposite direction of the node being removed - if (balance->weight == kNeither) - { - balance->weight = 1 - balance->dir; - } - // If balance node is imbalanced in the opposite direction of the - // node being removed then the node now becomes balanced - else if (balance->weight == balance->dir) - { - balance->weight = kNeither; - } - // Otherwise a rotation is required at this node - else - { - int weight = balance->children[1 - balance->dir]->weight; - // Perform a 3 node rotation if weight is same as balance->dir - if (weight == balance->dir) - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_3node(root_node, 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - else - { - rotate_3node(balance->parent->children[balance->parent->dir], 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - } - // Already balanced, rebalance and make it heavy in opposite - // direction of the node being removed - else if (weight == kNeither) - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - root_node->weight = balance->dir; - } - else - { - // Balance parent might change during rotate, keep local copy - // to old parent so its weight can be updated after the 2 node - // rotate is completed - Node* old_parent = balance->parent; - rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir); - old_parent->children[old_parent->dir]->weight = balance->dir; - } - // Update balance node weight in opposite direction of node removed - balance->weight = 1 - balance->dir; - } - // Rebalance and leave it balanced - else - { - // Is the root node being rebalanced (no parent) - if (balance->parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - } - else - { - rotate_2node(balance->parent->children[balance->parent->dir], 1 - balance->dir); - } - } - } - - // Next balance node to consider - balance = balance->children[balance->dir]; - } // while(balance) - - // Step 5: Swap found with node (replacement) - if (found->parent) - { - // Handle traditional case - detach_node(found->parent->children[found->parent->dir], - node->parent->children[node->parent->dir]); - } - // Handle root node removal - else - { - // Valid replacement node for root node being removed? - if (node->parent) - { - detach_node(root_node, node->parent->children[node->parent->dir]); - } - else - { - // Found node and replacement node are both root node - detach_node(root_node, root_node); - } - } - - // One less. - --current_size; - - // Destroy the node detached above - destroy_data_node(data_node); - } // if(found) - } - - // Disable copy construction. - imultiset(const imultiset&); - }; -} - -//*************************************************************************** -/// Equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator ==(const etl::imultiset& lhs, const etl::imultiset& rhs) -{ - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//*************************************************************************** -/// Not equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are not equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator !=(const etl::imultiset& lhs, const etl::imultiset& 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 lexicographically less than the -/// second, otherwise false. -//************************************************************************* -template -bool operator <(const etl::imultiset& lhs, const etl::imultiset& 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 lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::imultiset& lhs, const etl::imultiset& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// 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 lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::imultiset& lhs, const etl::imultiset& rhs) -{ - return !(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 lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::imultiset& lhs, const etl::imultiset& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_IMULTISET_H__ - -#endif diff --git a/src/ipool.h b/src/ipool.h deleted file mode 100644 index 18a196ea..00000000 --- a/src/ipool.h +++ /dev/null @@ -1,305 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IPOOL__ -#define __ETL_IPOOL__ -#define __ETL_IN_IPOOL_H__ - -#include - -#include "platform.h" -#include "nullptr.h" -#include "alignment.h" -#include "error_handler.h" - -#include - -#undef ETL_FILE -#define ETL_FILE "11" - -namespace etl -{ - //*************************************************************************** - /// The base class for pool exceptions. - ///\ingroup pool - //*************************************************************************** - class pool_exception : public exception - { - public: - - pool_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - {} - }; - - //*************************************************************************** - /// The exception thrown when the pool has no more free items. - ///\ingroup pool - //*************************************************************************** - class pool_no_allocation : public pool_exception - { - public: - - explicit pool_no_allocation(string_type file_name, numeric_type line_number) - : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name, line_number) - {} - }; - - //*************************************************************************** - /// The exception thrown when an object is released which does not belong to the pool. - ///\ingroup pool - //*************************************************************************** - class pool_object_not_in_pool : public pool_exception - { - public: - - pool_object_not_in_pool(string_type file_name, numeric_type line_number) - : pool_exception(ETL_ERROR_TEXT("pool:notinpool", ETL_FILE"B"), file_name, line_number) - {} - }; - - //*************************************************************************** - ///\ingroup pool - //*************************************************************************** - class ipool - { - public: - - typedef size_t size_type; - - //************************************************************************* - /// Allocate an object from the pool. - /// Uses the default constructor. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. - //************************************************************************* - template - T* allocate() - { - return reinterpret_cast(allocate_item()); - } - - //************************************************************************* - /// Release an object in the pool. - /// If asserts or exceptions are enabled and the object does not belong to this - /// pool then an etl::pool_object_not_in_pool is thrown. - /// \param p_object A pointer to the object to be released. - //************************************************************************* - void release(const void* p_object) - { - release_item((char*)p_object); - } - - //************************************************************************* - /// Release all objects in the pool. - //************************************************************************* - void release_all() - { - items_allocated = 0; - items_initialised = 0; - p_next = p_buffer; - } - - //************************************************************************* - /// Check to see if the object belongs to the pool. - /// \param p_object A pointer to the object to be checked. - /// \return true<\b> if it does, otherwise false - //************************************************************************* - //template - bool is_in_pool(const void* p_object) const - { - return is_item_in_pool((const char*)p_object); - } - - //************************************************************************* - /// Returns the maximum number of items in the pool. - //************************************************************************* - size_t max_items() const - { - return MAX_ITEMS; - } - - //************************************************************************* - /// Returns the number of free items in the pool. - //************************************************************************* - size_t available() const - { - return MAX_ITEMS - items_allocated; - } - - //************************************************************************* - /// Returns the number of allocated items in the pool. - //************************************************************************* - size_t size() const - { - return items_allocated; - } - - //************************************************************************* - /// Checks to see if there are no allocated items in the pool. - /// \return true if there are none allocated. - //************************************************************************* - bool empty() const - { - return items_allocated == 0; - } - - //************************************************************************* - /// Checks to see if there are no free items in the pool. - /// \return true if there are none free. - //************************************************************************* - bool full() const - { - return items_allocated == MAX_ITEMS; - } - - protected: - - //************************************************************************* - /// Constructor - //************************************************************************* - ipool(char* p_buffer_, uint32_t item_size, uint32_t max_items) - : p_buffer(p_buffer_), - p_next(p_buffer_), - items_allocated(0), - items_initialised(0), - ITEM_SIZE(item_size), - MAX_ITEMS(max_items) - { - } - - private: - - //************************************************************************* - /// Allocate an item from the pool. - //************************************************************************* - char* allocate_item() - { - char* p_value = nullptr; - - // Any free space left? - if (items_allocated < MAX_ITEMS) - { - // Initialise another one if necessary. - if (items_initialised < MAX_ITEMS) - { - uintptr_t p = reinterpret_cast(p_buffer + (items_initialised * ITEM_SIZE)); - *reinterpret_cast(p) = p + ITEM_SIZE; - ++items_initialised; - } - - // Get the address of new allocated item. - p_value = p_next; - - ++items_allocated; - if (items_allocated != MAX_ITEMS) - { - // Set up the pointer to the next free item - p_next = *reinterpret_cast(p_next); - } - else - { - // No more left! - p_next = nullptr; - } - } - else - { - ETL_ASSERT(false, ETL_ERROR(etl::pool_no_allocation)); - } - - return p_value; - } - - //************************************************************************* - /// Release an item back to the pool. - //************************************************************************* - void release_item(char* p_value) - { - // Does it belong to us? - ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool)); - - if (p_next != nullptr) - { - // Point it to the current free item. - *(uintptr_t*)p_value = reinterpret_cast(p_next); - } - else - { - // This is the only free item. - *((uintptr_t*)p_value) = 0; - } - - p_next = p_value; - - --items_allocated; - } - - //************************************************************************* - /// Check if the item belongs to this pool. - //************************************************************************* - bool is_item_in_pool(const char* p) const - { - // Within the range of the buffer? - intptr_t distance = p - p_buffer; - bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_ITEMS) - ITEM_SIZE)); - - // Modulus and division can be slow on some architectures, so only do this in debug. -#if defined(ETL_DEBUG) - // Is the address on a valid object boundary? - bool is_valid_address = ((distance % ITEM_SIZE) == 0); -#else - bool is_valid_address = true; -#endif - - return is_within_range && is_valid_address; - } - - // Disable copy construction and assignment. - ipool(const ipool&); - ipool& operator =(const ipool&); - - char* p_buffer; - char* p_next; - - uint32_t items_allocated; ///< The number of items allocated. - uint32_t items_initialised; ///< The number of items initialised. - - const uint32_t ITEM_SIZE; ///< The size of allocated items. - const uint32_t MAX_ITEMS; ///< The maximum number of objects that can be allocated. - }; -} - -#undef ETL_FILE - -#undef __ETL_IN_IPOOL_H__ - -#endif - diff --git a/src/ipriority_queue.h b/src/ipriority_queue.h deleted file mode 100644 index b00bd5f7..00000000 --- a/src/ipriority_queue.h +++ /dev/null @@ -1,273 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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. -******************************************************************************/ - -#ifndef __ETL_IPRIORITY_QUEUE__ -#define __ETL_IPRIORITY_QUEUE__ - -#include -#include - -#include "platform.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "error_handler.h" -#include "exception.h" - -#undef ETL_FILE -#define ETL_FILE "12" - -namespace etl -{ - //*************************************************************************** - /// The base class for priority_queue exceptions. - ///\ingroup queue - //*************************************************************************** - class priority_queue_exception : public exception - { - public: - - priority_queue_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The exception thrown when the queue is full. - ///\ingroup queue - //*************************************************************************** - class priority_queue_full : public priority_queue_exception - { - public: - - priority_queue_full(string_type file_name, numeric_type line_number) - : priority_queue_exception(ETL_ERROR_TEXT("priority_queue:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The priority queue iterator exception on reversed iterators - ///\ingroup queue - //*************************************************************************** - class priority_queue_iterator : public priority_queue_exception - { - public: - - priority_queue_iterator(string_type file_name, numeric_type line_number) - : priority_queue_exception(ETL_ERROR_TEXT("priority_queue:iterator", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup queue - ///\brief This is the base for all priority queues that contain a particular type. - ///\details Normally a reference to this type will be taken from a derived queue. - /// The TContainer specified must provide the front, push_back, pop_back, and - /// assign methods to work correctly with priority_queue. - ///\code - /// etl::priority_queue myPriorityQueue; - /// etl::ipriority_queue& iQueue = myPriorityQueue; - ///\endcode - /// \warning This priority queue cannot be used for concurrent access from - /// multiple threads. - /// \tparam T The type of value that the queue holds. - /// \tparam TContainer to hold the T queue values - /// \tparam TCompare to use in comparing T values - //*************************************************************************** - template - class ipriority_queue - { - public: - - typedef T value_type; ///< The type stored in the queue. - typedef TContainer container_type; ///< The container type used for priority queue. - typedef TCompare compare_type; ///< The comparison type. - typedef T& reference; ///< A reference to the type used in the queue. - typedef const T& const_reference; ///< A const reference to the type used in the queue. - typedef typename TContainer::size_type size_type; ///< The type used for determining the size of the queue. - typedef typename std::iterator_traits::difference_type difference_type; - - private: - - typedef typename parameter_type::type parameter_t; - - public: - - //************************************************************************* - /// Gets a reference to the highest priority value in the priority queue.
- /// \return A reference to the highest priority value in the priority queue. - //************************************************************************* - reference top() - { - return container.front(); - } - - //************************************************************************* - /// Gets a const reference to the highest priority value in the priority queue.
- /// \return A const reference to the highest priority value in the priority queue. - //************************************************************************* - const_reference top() const - { - return container.front(); - } - - //************************************************************************* - /// Adds a value to the queue. - /// If asserts or exceptions are enabled, throws an etl::priority_queue_full - /// is the priority queue is already full, otherwise does nothing if full. - ///\param value The value to push to the queue. - //************************************************************************* - void push(parameter_t value) - { - ETL_ASSERT(!full(), ETL_ERROR(priority_queue_full)); - - // Put element at end - container.push_back(value); - // Make elements in container into heap - std::push_heap(container.begin(), container.end(), TCompare()); - } - - //************************************************************************* - /// Assigns values to the priority queue. - /// If asserts or exceptions are enabled, emits priority_queue_full if - /// priority queue does not have enough free space. - /// If asserts or exceptions are enabled, emits priority_iterator if the - /// iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //************************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(priority_queue_iterator)); - ETL_ASSERT(static_cast(count) <= max_size(), ETL_ERROR(priority_queue_full)); -#endif - - clear(); - container.assign(first, last); - std::make_heap(container.begin(), container.end(), TCompare()); - } - - //************************************************************************* - /// Removes the oldest value from the back of the priority queue. - /// Does nothing if the priority queue is already empty. - //************************************************************************* - void pop() - { - // Move largest element to end - std::pop_heap(container.begin(), container.end(), TCompare()); - // Actually remove largest element at end - container.pop_back(); - } - - //************************************************************************* - /// Returns the current number of items in the priority queue. - //************************************************************************* - size_type size() const - { - return container.size(); - } - - //************************************************************************* - /// Returns the maximum number of items that can be queued. - //************************************************************************* - size_type max_size() const - { - return container.max_size(); - } - - //************************************************************************* - /// Checks to see if the priority queue is empty. - /// \return true if the queue is empty, otherwise false - //************************************************************************* - bool empty() const - { - return container.empty(); - } - - //************************************************************************* - /// Checks to see if the priority queue is full. - /// \return true if the priority queue is full, otherwise false - //************************************************************************* - bool full() const - { - return container.size() == container.max_size(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return container.max_size() - container.size(); - } - - //************************************************************************* - /// Clears the queue to the empty state. - //************************************************************************* - void clear() - { - container.clear(); - } - - protected: - - //************************************************************************* - /// Make this a clone of the supplied priority queue - //************************************************************************* - void clone(const ipriority_queue& other) - { - assign(other.container.cbegin(), other.container.cend()); - } - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - ipriority_queue() - { - } - - private: - - // Disable copy construction. - ipriority_queue(const ipriority_queue&); - - /// The container specified at instantiation of the priority_queue - TContainer container; - }; -} - -#undef ETL_FILE -#endif diff --git a/src/iqueue.h b/src/iqueue.h deleted file mode 100644 index 952484b4..00000000 --- a/src/iqueue.h +++ /dev/null @@ -1,229 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IQUEUE__ -#define __ETL_IQUEUE__ -#define __ETL_IN_IQUEUE_H__ - -#include - -#include "private/queue_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "error_handler.h" - -namespace etl -{ - //*************************************************************************** - ///\ingroup queue - ///\brief This is the base for all queues that contain a particular type. - ///\details Normally a reference to this type will be taken from a derived queue. - ///\code - /// etl::queue myQueue; - /// etl::iqueue& iQueue = myQueue; - ///\endcode - /// \warning This queue cannot be used for concurrent access from multiple threads. - /// \tparam T The type of value that the queue holds. - //*************************************************************************** - template - class iqueue : public queue_base - { - public: - - typedef T value_type; ///< The type stored in the queue. - typedef T& reference; ///< A reference to the type used in the queue. - typedef const T& const_reference; ///< A const reference to the type used in the queue. - typedef T* pointer; ///< A pointer to the type used in the queue. - typedef const T* const_pointer; ///< A const pointer to the type used in the queue. - typedef queue_base::size_type size_type; ///< The type used for determining the size of the queue. - - private: - - typedef typename parameter_type::type parameter_t; - - public: - - //************************************************************************* - /// Gets a reference to the value at the front of the queue.
- /// \return A reference to the value at the front of the queue. - //************************************************************************* - reference front() - { - return p_buffer[out]; - } - - //************************************************************************* - /// Gets a const reference to the value at the front of the queue.
- /// \return A const reference to the value at the front of the queue. - //************************************************************************* - const_reference front() const - { - return p_buffer[out]; - } - - //************************************************************************* - /// Gets a reference to the value at the back of the queue.
- /// \return A reference to the value at the back of the queue. - //************************************************************************* - reference back() - { - return p_buffer[in == 0 ? MAX_SIZE - 1 : in - 1]; - } - - //************************************************************************* - /// Gets a const reference to the value at the back of the queue.
- /// \return A const reference to the value at the back of the queue. - //************************************************************************* - const_reference back() const - { - return p_buffer[in == 0 ? MAX_SIZE - 1 : in - 1]; - } - - //************************************************************************* - /// Adds a value to the queue. - /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full, - /// otherwise does nothing if full. - ///\param value The value to push to the queue. - //************************************************************************* - void push(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(queue_full)); -#endif - ::new (&p_buffer[in]) T(value); - in = (in == (MAX_SIZE - 1)) ? 0 : in + 1; - ++current_size; - ++construct_count; - } - - //************************************************************************* - /// Allows a possibly more efficient 'push' by moving to the next input value - /// and returning a reference to it. - /// This may eliminate a copy by allowing direct construction in-place.
- /// If asserts or exceptions are enabled, throws an etl::queue_full is the queue is already full, - /// otherwise does nothing if full. - /// \return A reference to the position to 'push' to. - //************************************************************************* - reference push() - { - const size_type next = in; - -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(queue_full)); -#endif - ::new (&p_buffer[in]) T(); - in = (in == (MAX_SIZE - 1)) ? 0 : in + 1; - ++current_size; - ++construct_count; - - return p_buffer[next]; - } - - //************************************************************************* - /// Clears the queue to the empty state. - //************************************************************************* - void clear() - { - while (current_size > 0) - { - p_buffer[out].~T(); - out = (out == (MAX_SIZE - 1)) ? 0 : out + 1; - --current_size; - --construct_count; - } - - in = 0; - out = 0; - } - - //************************************************************************* - /// Removes the oldest value from the back of the queue. - /// Does nothing if the queue is already empty. - //************************************************************************* - void pop() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(queue_empty)); -#endif - p_buffer[out].~T(); - out = (out == (MAX_SIZE - 1)) ? 0 : out + 1; - --current_size; - --construct_count; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iqueue& operator = (const iqueue& rhs) - { - if (&rhs != this) - { - clone(rhs); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Make this a clone of the supplied queue - //************************************************************************* - void clone(const iqueue& other) - { - size_t index = other.out; - - for (size_t i = 0; i < other.size(); ++i) - { - push(other.p_buffer[index]); - index = (index == (MAX_SIZE - 1)) ? 0 : index + 1; - } - } - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - iqueue(T* p_buffer, size_type max_size) - : queue_base(max_size), - p_buffer(p_buffer) - { - } - - private: - - // Disable copy construction. - iqueue(const iqueue&); - - T* p_buffer; ///< The internal buffer. - }; -} - -#undef __ETL_IN_IQUEUE_H__ -#endif diff --git a/src/iset.h b/src/iset.h deleted file mode 100644 index d84b51ba..00000000 --- a/src/iset.h +++ /dev/null @@ -1,1621 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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. -******************************************************************************/ - -#ifndef __ETL_ISET__ -#define __ETL_ISET__ -#define __ETL_IN_ISET_H__ - -#include -#include -#include -#include - -#include "nullptr.h" -#include "private/set_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "pool.h" -#include "platform.h" - -#ifdef ETL_COMPILER_MICROSOFT -#undef min -#endif - -namespace etl -{ - //*************************************************************************** - /// A templated base for all etl::set types. - ///\ingroup set - //*************************************************************************** - template - class iset : public set_base - { - public: - - typedef const T key_type; - typedef const T value_type; - typedef TCompare key_compare; - typedef TCompare value_compare; - typedef value_type& const_reference; - typedef value_type* const_pointer; - typedef size_t size_type; - - //************************************************************************* - /// How to compare two key elements. - //************************************************************************* - struct key_comp - { - bool operator ()(key_type& key1, key_type& key2) const - { - return key_compare()(key1, key2); - } - }; - - //************************************************************************* - /// How to compare two value elements. - //************************************************************************* - struct value_comp - { - bool operator ()(value_type& value1, value_type& value2) const - { - return value_compare()(value1, value2); - } - }; - - protected: - - //************************************************************************* - /// The data node element in the set. - //************************************************************************* - struct Data_Node : public Node - { - explicit Data_Node(value_type value) - : value(value) - { - } - - value_type value; - }; - - /// Defines the key value parameter type - typedef typename parameter_type::type key_value_parameter_t; - - //************************************************************************* - /// How to compare node elements. - //************************************************************************* - bool node_comp(const Data_Node& node1, const Data_Node& node2) const - { - return key_compare()(node1.value, node2.value); - } - bool node_comp(const Data_Node& node, const key_value_parameter_t& key) const - { - return key_compare()(node.value, key); - } - bool node_comp(const key_value_parameter_t& key, const Data_Node& node) const - { - return key_compare()(key, node.value); - } - - private: - - /// The pool of data nodes used in the set. - etl::ipool* p_node_pool; - - //************************************************************************* - /// Downcast a Node* to a Data_Node* - //************************************************************************* - static Data_Node* data_cast(Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a Node& to a Data_Node& - //************************************************************************* - static Data_Node& data_cast(Node& node) - { - return static_cast(node); - } - - //************************************************************************* - /// Downcast a const Node* to a const Data_Node* - //************************************************************************* - static const Data_Node* data_cast(const Node* p_node) - { - return static_cast(p_node); - } - - //************************************************************************* - /// Downcast a const Node& to a const Data_Node& - //************************************************************************* - static const Data_Node& data_cast(const Node& node) - { - return static_cast(node); - } - - public: - //************************************************************************* - /// iterator. - //************************************************************************* - class iterator : public std::iterator - { - public: - - friend class iset; - - iterator() - : p_set(nullptr) - , p_node(nullptr) - { - } - - iterator(iset& set) - : p_set(&set) - , p_node(nullptr) - { - } - - iterator(iset& set, Node* node) - : p_set(&set) - , p_node(node) - { - } - - iterator(const iterator& other) - : p_set(other.p_set) - , p_node(other.p_node) - { - } - - ~iterator() - { - } - - iterator& operator ++() - { - p_set->next_node(p_node); - return *this; - } - - iterator operator ++(int) - { - iterator temp(*this); - p_set->next_node(p_node); - return temp; - } - - iterator& operator --() - { - p_set->prev_node(p_node); - return *this; - } - - iterator operator --(int) - { - iterator temp(*this); - p_set->prev_node(p_node); - return temp; - } - - iterator operator =(const iterator& other) - { - p_set = other.p_set; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return iset::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return &(iset::data_cast(p_node)->value); - } - - const_pointer operator ->() const - { - return &(iset::data_cast(p_node)->value); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - // Pointer to set associated with this iterator - iset* p_set; - - // Pointer to the current node for this iterator - Node* p_node; - }; - friend class iterator; - - //************************************************************************* - /// const_iterator - //************************************************************************* - class const_iterator : public std::iterator - { - public: - - friend class iset; - - const_iterator() - : p_set(nullptr) - , p_node(nullptr) - { - } - - const_iterator(const iset& set) - : p_set(&set) - , p_node(nullptr) - { - } - - const_iterator(const iset& set, const Node* node) - : p_set(&set) - , p_node(node) - { - } - - const_iterator(const typename iset::iterator& other) - : p_set(other.p_set) - , p_node(other.p_node) - { - } - - const_iterator(const const_iterator& other) - : p_set(other.p_set) - , p_node(other.p_node) - { - } - - ~const_iterator() - { - } - - const_iterator& operator ++() - { - p_set->next_node(p_node); - return *this; - } - - const_iterator operator ++(int) - { - const_iterator temp(*this); - p_set->next_node(p_node); - return temp; - } - - const_iterator& operator --() - { - p_set->prev_node(p_node); - return *this; - } - - const_iterator operator --(int) - { - const_iterator temp(*this); - p_set->prev_node(p_node); - return temp; - } - - const_iterator operator =(const const_iterator& other) - { - p_set = other.p_set; - p_node = other.p_node; - return *this; - } - - const_reference operator *() const - { - return iset::data_cast(p_node)->value; - } - - const_pointer operator &() const - { - return iset::data_cast(p_node)->value; - } - - const_pointer operator ->() const - { - return &(iset::data_cast(p_node)->value); - } - - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.p_set == rhs.p_set && lhs.p_node == rhs.p_node; - } - - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - // Pointer to set associated with this iterator - const iset* p_set; - - // Pointer to the current node for this iterator - const Node* p_node; - }; - friend class const_iterator; - - typedef typename std::iterator_traits::difference_type difference_type; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iset& operator = (const iset& rhs) - { - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the beginning of the set. - //************************************************************************* - iterator begin() - { - return iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the beginning of the set. - //************************************************************************* - const_iterator begin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the set. - //************************************************************************* - iterator end() - { - return iterator(*this); - } - - //************************************************************************* - /// Gets the end of the set. - //************************************************************************* - const_iterator end() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the beginning of the set. - //************************************************************************* - const_iterator cbegin() const - { - return const_iterator(*this, find_limit_node(root_node, kLeft)); - } - - //************************************************************************* - /// Gets the end of the set. - //************************************************************************* - const_iterator cend() const - { - return const_iterator(*this); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - reverse_iterator rend() - { - return reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(iterator(*this, find_limit_node(root_node, kLeft))); - } - - //************************************************************************* - /// Gets the reverse beginning of the list. - //************************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(const_iterator(*this)); - } - - //************************************************************************* - /// Gets the reverse end of the list. - //************************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(const_iterator(*this, find_limit_node(root_node, kLeft))); - } - - //********************************************************************* - /// Assigns values to the set. - /// If asserts or exceptions are enabled, emits set_full if the set does not have enough free space. - /// If asserts or exceptions are enabled, emits set_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { - initialise(); - insert(first, last); - } - - //************************************************************************* - /// Clears the set. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts the number of elements that contain the key specified. - ///\param key The key to search for. - ///\return 1 if element was found, 0 otherwise. - //********************************************************************* - size_type count(const key_value_parameter_t& key) const - { - return find_node(root_node, key) ? 1 : 0; - } - - //************************************************************************* - /// Returns two iterators with bounding (lower bound, upper bound) the - /// value provided - //************************************************************************* - std::pair equal_range(const value_type& value) - { - return std::make_pair( - iterator(*this, find_lower_node(root_node, value)), - iterator(*this, find_upper_node(root_node, value))); - } - - //************************************************************************* - /// Returns two const iterators with bounding (lower bound, upper bound) - /// the value provided. - //************************************************************************* - std::pair equal_range(const value_type& value) const - { - return std::make_pair( - const_iterator(*this, find_lower_node(root_node, value)), - const_iterator(*this, find_upper_node(root_node, value))); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - void erase(iterator position) - { - // Remove the node by its key - erase((*position)); - } - - //************************************************************************* - /// Erases the value at the specified position. - //************************************************************************* - iterator erase(const_iterator position) - { - // Find the parent node to be removed - Node*& reference_node = find_node(root_node, position.p_node); - iterator next(*this, reference_node); - ++next; - - remove_node(root_node, (*position)); - - return next; - } - - //************************************************************************* - // Erase the key specified. - //************************************************************************* - size_type erase(const key_value_parameter_t& key_value) - { - // Return 1 if key value was found and removed - return remove_node(root_node, key_value) ? 1 : 0; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(iterator first, iterator last) - { - iterator next; - while (first != last) - { - next = erase(const_iterator(first++)); - } - - return next; - } - - //************************************************************************* - /// Erases a range of elements. - //************************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - iterator next; - while (first != last) - { - next = erase(first++); - } - - return next; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - iterator find(const key_value_parameter_t& key_value) - { - return iterator(*this, find_node(root_node, key_value)); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator pointing to the element or end() if not found. - //********************************************************************* - const_iterator find(const key_value_parameter_t& key_value) const - { - return const_iterator(*this, find_node(root_node, key_value)); - } - - //********************************************************************* - /// Inserts a value to the set. - /// If asserts or exceptions are enabled, emits set_full if the set is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - bool inserted = false; - - ETL_ASSERT(!full(), ETL_ERROR(set_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - inserted = inserted_node == &node; - - // Insert node into tree and return iterator to new node location in tree - return std::make_pair(iterator(*this, inserted_node), inserted); - } - - //********************************************************************* - /// Inserts a value to the set starting at the position recommended. - /// If asserts or exceptions are enabled, emits set_full if the set is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator, value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(set_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a value to the set starting at the position recommended. - /// If asserts or exceptions are enabled, emits set_full if the set is already full. - ///\param position The position that would precede the value to insert. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator, value_type& value) - { - // Default to no inserted node - Node* inserted_node = nullptr; - - ETL_ASSERT(!full(), ETL_ERROR(set_full)); - - // Get next available free node - Data_Node& node = allocate_data_node(value); - - // Obtain the inserted node (might be nullptr if node was a duplicate) - inserted_node = insert_node(root_node, node); - - // Insert node into tree and return iterator to new node location in tree - return iterator(*this, inserted_node); - } - - //********************************************************************* - /// Inserts a range of values to the set. - /// If asserts or exceptions are enabled, emits set_full if the set does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go before the key provided or end() - /// if all keys are considered to go before the key provided. - ///\return An iterator pointing to the element not before key or end() - //********************************************************************* - iterator lower_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go before the key provided - /// or end() if all keys are considered to go before the key provided. - ///\return An const_iterator pointing to the element not before key or end() - //********************************************************************* - const_iterator lower_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_lower_node(root_node, key)); - } - - //********************************************************************* - /// Returns an iterator pointing to the first element in the container - /// whose key is not considered to go after the key provided or end() - /// if all keys are considered to go after the key provided. - ///\return An iterator pointing to the element after key or end() - //********************************************************************* - iterator upper_bound(const key_value_parameter_t& key) - { - return iterator(*this, find_upper_node(root_node, key)); - } - - //********************************************************************* - /// Returns a const_iterator pointing to the first element in the - /// container whose key is not considered to go after the key provided - /// or end() if all keys are considered to go after the key provided. - ///\return An const_iterator pointing to the element after key or end() - //********************************************************************* - const_iterator upper_bound(const key_value_parameter_t& key) const - { - return const_iterator(*this, find_upper_node(root_node, key)); - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - iset(ipool& node_pool, size_t max_size_) - : set_base(max_size_) - , p_node_pool(&node_pool) - { - } - - //************************************************************************* - /// Initialise the set. - //************************************************************************* - void initialise() - { - erase(begin(), end()); - } - - private: - - //************************************************************************* - /// Allocate a Data_Node. - //************************************************************************* - Data_Node& allocate_data_node(value_type value) - { - Data_Node& node = *p_node_pool->allocate(); - ::new ((void*)&node.value) value_type(value); - ++construct_count; - return node; - } - - //************************************************************************* - /// Destroy a Data_Node. - //************************************************************************* - void destroy_data_node(Data_Node& node) - { - node.value.~value_type(); - p_node_pool->release(&node); - --construct_count; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - Node* find_node(Node* position, const key_value_parameter_t& key) - { - Node* found = position; - while (found) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = iset::data_cast(*found); - - // Compare the node value to the current position value - if (node_comp(key, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, key)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Node that matches the key provided was found, exit loop - break; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the value matching the node provided - //************************************************************************* - const Node* find_node(const Node* position, const key_value_parameter_t& key) const - { - const Node* found = position; - while (found) - { - // Downcast found to Data_Node class for comparison and other operations - const Data_Node& found_data_node = iset::data_cast(*found); - - // Compare the node value to the current position value - if (node_comp(key, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, key)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Node that matches the key provided was found, exit loop - break; - } - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the reference node matching the node provided - //************************************************************************* - Node*& find_node(Node*& position, const Node* node) - { - Node* found = position; - while (found) - { - if (found->children[kLeft] == node) - { - return found->children[kLeft]; - } - else if (found->children[kRight] == node) - { - return found->children[kRight]; - } - else - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = iset::data_cast(*found); - const Data_Node& data_node = iset::data_cast(*node); - - // Compare the node value to the current position value - if (node_comp(data_node, found_data_node)) - { - // Keep searching for the node on the left - found = found->children[kLeft]; - } - else if (node_comp(found_data_node, data_node)) - { - // Keep searching for the node on the right - found = found->children[kRight]; - } - else - { - // Return position provided (it matches the node) - return position; - } - } - } - - // Return root node if nothing was found - return root_node; - } - - //************************************************************************* - /// Find the parent node that contains the node provided in its left or - /// right tree - //************************************************************************* - Node* find_parent_node(Node* position, const Node* node) - { - // Default to no parent node found - Node* found = nullptr; - - // If the position provided is the same as the node then there is no parent - if (position && node && position != node) - { - while (position) - { - // Is this position not the parent of the node we are looking for? - if (position->children[kLeft] != node && - position->children[kRight] != node) - { - // Downcast node and position to Data_Node references for key comparisons - const Data_Node& node_data_node = iset::data_cast(*node); - Data_Node& position_data_node = iset::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(node_data_node, position_data_node)) - { - // Keep looking for parent on the left - position = position->children[kLeft]; - } - else if (node_comp(position_data_node, node_data_node)) - { - // Keep looking for parent on the right - position = position->children[kRight]; - } - } - else - { - // Return the current position as the parent node found - found = position; - - // Parent node found, exit loop - break; - } - } - } - - // Return the parent node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the parent node that contains the node provided in its left or - /// right tree - //************************************************************************* - const Node* find_parent_node(const Node* position, const Node* node) const - { - // Default to no parent node found - const Node* found = nullptr; - - // If the position provided is the same as the node then there is no parent - if (position && node && position != node) - { - while (position) - { - // Is this position not the parent of the node we are looking for? - if (position->children[kLeft] != node && - position->children[kRight] != node) - { - // Downcast node and position to Data_Node references for key comparisons - const Data_Node& node_data_node = iset::data_cast(*node); - const Data_Node& position_data_node = iset::data_cast(*position); - // Compare the node value to the current position value - if (node_comp(node_data_node, position_data_node)) - { - // Keep looking for parent on the left - position = position->children[kLeft]; - } - else if (node_comp(position_data_node, node_data_node)) - { - // Keep looking for parent on the right - position = position->children[kRight]; - } - } - else - { - // Return the current position as the parent node found - found = position; - - // Parent node found, exit loop - break; - } - } - } - - // Return the parent node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the node whose key is not considered to go before the key provided - //************************************************************************* - Node* find_lower_node(Node* position, const key_value_parameter_t& key) const - { - // Something at this position? keep going - Node* lower_node = position; - while (lower_node) - { - // Downcast lower node to Data_Node reference for key comparisons - Data_Node& data_node = iset::data_cast(*lower_node); - // Compare the key value to the current lower node key value - if (node_comp(key, data_node)) - { - if (lower_node->children[kLeft]) - { - lower_node = lower_node->children[kLeft]; - } - else - { - // Found lowest node - break; - } - } - else if (node_comp(data_node, key)) - { - lower_node = lower_node->children[kRight]; - } - else - { - // Found equal node - break; - } - } - - // Return the lower_node position found - return lower_node; - } - - //************************************************************************* - /// Find the node whose key is considered to go after the key provided - //************************************************************************* - Node* find_upper_node(Node* position, const key_value_parameter_t& key) const - { - // Keep track of parent of last upper node - Node* upper_node = nullptr; - // Start with position provided - Node* node = position; - while (node) - { - // Downcast position to Data_Node reference for key comparisons - Data_Node& data_node = iset::data_cast(*node); - // Compare the key value to the current upper node key value - if (node_comp(key, data_node)) - { - upper_node = node; - node = node->children[kLeft]; - } - else if (node_comp(data_node, key)) - { - node = node->children[kRight]; - } - else if (node->children[kRight]) - { - upper_node = find_limit_node(node->children[kRight], kLeft); - break; - } - else - { - break; - } - } - - // Return the upper node position found (might be nullptr) - return upper_node; - } - - //************************************************************************* - /// Insert a node. - //************************************************************************* - Node* insert_node(Node*& position, Data_Node& node) - { - // Find the location where the node belongs - Node* found = position; - - // Was position provided not empty? then find where the node belongs - if (position) - { - // Find the critical parent node (default to nullptr) - Node* critical_parent_node = nullptr; - Node* critical_node = root_node; - - while (found) - { - // Search for critical weight node (all nodes whose weight factor - // is set to kNeither (balanced) - if (kNeither != found->weight) - { - critical_node = found; - } - - // Downcast found to Data_Node class for comparison and other operations - Data_Node& found_data_node = iset::data_cast(*found); - - // Is the node provided to the left of the current position? - if (node_comp(node, found_data_node)) - { - // Update direction taken to insert new node in parent node - found->dir = kLeft; - } - // Is the node provided to the right of the current position? - else if (node_comp(found_data_node, node)) - { - // Update direction taken to insert new node in parent node - found->dir = kRight; - } - else - { - // Update direction taken to insert new node in parent node - found->dir = kNeither; - - // Clear critical node value to skip weight step below - critical_node = nullptr; - - // Destroy the node provided (its a duplicate) - destroy_data_node(node); - - // Exit loop, duplicate node found - break; - } - - // Is there a child of this parent node? - if (found->children[found->dir]) - { - // Will this node be the parent of the next critical node whose - // weight factor is set to kNeither (balanced)? - if (kNeither != found->children[found->dir]->weight) - { - critical_parent_node = found; - } - - // Keep looking for empty spot to insert new node - found = found->children[found->dir]; - } - else - { - // Attatch node to right - attach_node(found->children[found->dir], node); - - // Return newly added node - found = found->children[found->dir]; - - // Exit loop - break; - } - } - - // Was a critical node found that should be checked for balance? - if (critical_node) - { - if (critical_parent_node == nullptr && critical_node == root_node) - { - balance_node(root_node); - } - else if (critical_parent_node == nullptr && critical_node == position) - { - balance_node(position); - } - else - { - balance_node(critical_parent_node->children[critical_parent_node->dir]); - } - } - } - else - { - // Attatch node to current position - attach_node(position, node); - - // Return newly added node at current position - found = position; - } - - // Return the node found (might be nullptr) - return found; - } - - //************************************************************************* - /// Find the next node in sequence from the node provided - //************************************************************************* - void next_node(Node*&position) - { - 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 = 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 = 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 previous node in sequence from the node provided - //************************************************************************* - void prev_node(Node*&position) - { - // 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 = find_parent_node(root_node, position); - // 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 = find_parent_node(root_node, position); - // 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 - //************************************************************************* - Node* remove_node(Node*& position, const key_value_parameter_t& key) - { - // Step 1: Find the target node that matches the key provided, the - // replacement node (might be the same as target node), and the critical - // node to start rebalancing the tree from (up to the replacement node) - Node* found_parent = nullptr; - Node* found = nullptr; - Node* replace_parent = nullptr; - Node* replace = position; - Node* balance_parent = nullptr; - Node* balance = root_node; - while (replace) - { - // Downcast found to Data_Node class for comparison and other operations - Data_Node& replace_data_node = iset::data_cast(*replace); - - // Compare the key provided to the replace data node key - if (node_comp(key, replace_data_node)) - { - // Update the direction to the target/replace node - replace->dir = kLeft; - } - else if (node_comp(replace_data_node, key)) - { - // Update the direction to the target/replace node - replace->dir = kRight; - } - else - { - // Update the direction to the replace node (target node found here) - replace->dir = replace->children[kLeft] ? kLeft : kRight; - - // Note the target node was found (and its parent) - found_parent = replace_parent; - found = replace; - } - // Replacement node found if its missing a child in the replace->dir - // value set above - if (replace->children[replace->dir] == nullptr) - { - // Exit loop once replace node is found (target might not have been) - break; - } - - // If replacement node weight is kNeither or we are taking the shorter - // path of replacement node and our sibling (on longer path) is - // balanced then we need to update the balance node to match this - // replacement node but all our ancestors will not require rebalancing - if ((replace->weight == kNeither) || - (replace->weight == (1 - replace->dir) && - replace->children[1 - replace->dir]->weight == kNeither)) - { - // Update balance node (and its parent) to replacement node - balance_parent = replace_parent; - balance = replace; - } - - // Keep searching for the replacement node - replace_parent = replace; - replace = replace->children[replace->dir]; - } - - // If target node was found, proceed with rebalancing and replacement - if (found) - { - // Step 2: Update weights from critical node to replacement parent node - while (balance) - { - if (balance->children[balance->dir] == nullptr) - { - break; - } - - if (balance->weight == kNeither) - { - balance->weight = 1 - balance->dir; - } - else if (balance->weight == balance->dir) - { - balance->weight = kNeither; - } - else - { - int weight = balance->children[1 - balance->dir]->weight; - // Perform a 3 node rotation if weight is same as balance->dir - if (weight == balance->dir) - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_3node(root_node, 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - else - { - rotate_3node(balance_parent->children[balance_parent->dir], 1 - balance->dir, - balance->children[1 - balance->dir]->children[balance->dir]->weight); - } - } - // Already balanced, rebalance and make it heavy in opposite - // direction of the node being removed - else if (weight == kNeither) - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - root_node->weight = balance->dir; - } - else - { - rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir); - balance_parent->children[balance_parent->dir]->weight = balance->dir; - } - // Update balance node weight in opposite direction of node removed - balance->weight = 1 - balance->dir; - } - // Rebalance and leave it balanced - else - { - // Is the root node being rebalanced (no parent) - if (balance_parent == nullptr) - { - rotate_2node(root_node, 1 - balance->dir); - } - else - { - rotate_2node(balance_parent->children[balance_parent->dir], 1 - balance->dir); - } - } - - // Is balance node the same as the target node found? then update - // its parent after the rotation performed above - if (balance == found) - { - if (balance_parent) - { - found_parent = balance_parent->children[balance_parent->dir]; - // Update dir since it is likely stale - found_parent->dir = found_parent->children[kLeft] == found ? kLeft : kRight; - } - else - { - found_parent = root_node; - root_node->dir = root_node->children[kLeft] == found ? kLeft : kRight; - } - } - } - - // Next balance node to consider - balance_parent = balance; - balance = balance->children[balance->dir]; - } // while(balance) - - // Step 3: Swap found node with replacement node - if (found_parent) - { - // Handle traditional case - detach_node(found_parent->children[found_parent->dir], - replace_parent->children[replace_parent->dir]); - } - // Handle root node removal - else - { - // Valid replacement node for root node being removed? - if (replace_parent) - { - detach_node(root_node, replace_parent->children[replace_parent->dir]); - } - else - { - // Target node and replacement node are both root node - detach_node(root_node, root_node); - } - } - - // Downcast found into data node - Data_Node& found_data_node = iset::data_cast(*found); - - // One less. - --current_size; - - // Destroy the node removed - destroy_data_node(found_data_node); - } // if(found) - - // Return node found (might be nullptr) - return found; - } - - // Disable copy construction. - iset(const iset&); - }; -} - -//*************************************************************************** -/// Equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator ==(const etl::iset& lhs, const etl::iset& rhs) -{ - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//*************************************************************************** -/// Not equal operator. -///\param lhs Reference to the first lookup. -///\param rhs Reference to the second lookup. -///\return true if the arrays are not equal, otherwise false -///\ingroup lookup -//*************************************************************************** -template -bool operator !=(const etl::iset& lhs, const etl::iset& 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 lexicographically less than the -/// second, otherwise false. -//************************************************************************* -template -bool operator <(const etl::iset& lhs, const etl::iset& 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 lexicographically greater than the -/// second, otherwise false. -//************************************************************************* -template -bool operator >(const etl::iset& lhs, const etl::iset& rhs) -{ - return (rhs < lhs); -} - -//************************************************************************* -/// 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 lexicographically less than or equal -/// to the second, otherwise false. -//************************************************************************* -template -bool operator <=(const etl::iset& lhs, const etl::iset& rhs) -{ - return !(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 lexicographically greater than or -/// equal to the second, otherwise false. -//************************************************************************* -template -bool operator >=(const etl::iset& lhs, const etl::iset& rhs) -{ - return !(lhs < rhs); -} - -#ifdef ETL_COMPILER_MICROSOFT -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#undef __ETL_IN_ISET_H__ - -#endif diff --git a/src/istack.h b/src/istack.h deleted file mode 100644 index 432fa615..00000000 --- a/src/istack.h +++ /dev/null @@ -1,201 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_ISTACK__ -#define __ETL_ISTACK__ -#define __ETL_IN_ISTACK_H__ - -#include - -#include "private/stack_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "error_handler.h" - -namespace etl -{ - //*************************************************************************** - ///\ingroup stack - ///\brief This is the base for all stacks that contain a particular type. - ///\details Normally a reference to this type will be taken from a derived stack. - ///\code - /// etl::stack myQueue; - /// etl::istack& iQueue = myQueue; - ///\endcode - /// \warning This stack cannot be used for concurrent access from multiple threads. - /// \tparam T The type of value that the stack holds. - //*************************************************************************** - template - class istack : public stack_base - { - public: - - typedef T value_type; ///< The type stored in the stack. - typedef T& reference; ///< A reference to the type used in the stack. - typedef const T& const_reference; ///< A const reference to the type used in the stack. - typedef T* pointer; ///< A pointer to the type used in the stack. - typedef const T* const_pointer; ///< A const pointer to the type used in the stack. - typedef stack_base::size_type size_type; ///< The type used for determining the size of the stack. - - private: - - typedef typename parameter_type::type parameter_t; - - public: - - //************************************************************************* - /// Gets a reference to the value at the top of the stack.
- /// \return A reference to the value at the top of the stack. - //************************************************************************* - reference top() - { - return p_buffer[top_index]; - } - - //************************************************************************* - /// Adds a value to the stack. - /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. - ///\param value The value to push to the stack. - //************************************************************************* - void push(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(stack_full)); -#endif - top_index = current_size++; - ::new (&p_buffer[top_index]) T(value); - ++construct_count; - } - - //************************************************************************* - /// Allows a possibly more efficient 'push' by moving to the next input value - /// and returning a reference to it. - /// This may eliminate a copy by allowing direct construction in-place.
- /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. - /// \return A reference to the position to 'push' to. - //************************************************************************* - reference push() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!full(), ETL_ERROR(stack_full)); -#endif - top_index = current_size++; - ::new (&p_buffer[top_index]) T(); - ++construct_count; - - return p_buffer[top_index]; - } - - //************************************************************************* - /// Gets a const reference to the value at the top of the stack.
- /// \return A const reference to the value at the top of the stack. - //************************************************************************* - const_reference top() const - { - return p_buffer[top_index]; - } - - //************************************************************************* - /// Clears the stack to the empty state. - //************************************************************************* - void clear() - { - while (current_size > 0) - { - p_buffer[top_index].~T(); - --top_index; - --current_size; - --construct_count; - } - } - - //************************************************************************* - /// Removes the oldest item from the top of the stack. - /// Does nothing if the stack is already empty. - //************************************************************************* - void pop() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(stack_empty)); -#endif - p_buffer[top_index].~T(); - --top_index; - --current_size; - --construct_count; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - istack& operator = (const istack& rhs) - { - if (&rhs != this) - { - clone(rhs); - } - - return *this; - } - - protected: - - //************************************************************************* - /// Make this a clone of the supplied stack - //************************************************************************* - void clone(const istack& other) - { - size_t index = 0; - - for (size_t i = 0; i < other.size(); ++i) - { - push(other.p_buffer[index++]); - } - } - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - istack(T* p_buffer, size_type max_size) - : stack_base(max_size), - p_buffer(p_buffer) - { - } - - private: - - // Disable copy construction. - istack(const istack&); - - T* p_buffer; ///< The internal buffer. - }; -} - -#undef __ETL_IN_ISTACK_H__ -#endif diff --git a/src/iunordered_map.h b/src/iunordered_map.h deleted file mode 100644 index b8ca29e3..00000000 --- a/src/iunordered_map.h +++ /dev/null @@ -1,1308 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_IUNORDERED_MAP__ -#define __ETL_IUNORDERED_MAP__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "hash.h" -#include "nullptr.h" -#include "pool.h" -#include "vector.h" -#include "error_handler.h" -#include "intrusive_forward_list.h" -#include "exception.h" -#include "error_handler.h" -#include "debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "16" - -namespace etl -{ - //*************************************************************************** - /// Exception for the unordered_map. - ///\ingroup unordered_map - //*************************************************************************** - class unordered_map_exception : public exception - { - public: - - unordered_map_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the unordered_map. - ///\ingroup unordered_map - //*************************************************************************** - class unordered_map_full : public unordered_map_exception - { - public: - - unordered_map_full(string_type file_name, numeric_type line_number) - : unordered_map_exception(ETL_ERROR_TEXT("unordered_map:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Out of range exception for the unordered_map. - ///\ingroup unordered_map - //*************************************************************************** - class unordered_map_out_of_range : public unordered_map_exception - { - public: - - unordered_map_out_of_range(string_type file_name, numeric_type line_number) - : unordered_map_exception(ETL_ERROR_TEXT("unordered_map:range", ETL_FILE"B"), file_name, line_number) - {} - }; - - //*************************************************************************** - /// Iterator exception for the unordered_map. - ///\ingroup unordered_map - //*************************************************************************** - class unordered_map_iterator : public unordered_map_exception - { - public: - - unordered_map_iterator(string_type file_name, numeric_type line_number) - : unordered_map_exception(ETL_ERROR_TEXT("unordered_map:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for specifically sized unordered_map. - /// Can be used as a reference type for all unordered_map containing a specific type. - ///\ingroup unordered_map - //*************************************************************************** - template , typename TKeyEqual = std::equal_to > - class iunordered_map - { - public: - - typedef std::pair value_type; - - typedef TKey key_type; - typedef T mapped_type; - typedef THash hasher; - typedef TKeyEqual key_equal; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - - typedef typename parameter_type::type key_value_parameter_t; - - typedef etl::forward_link<0> link_t; // Default link. - - // The nodes that store the elements. - struct node_t : public link_t - { - node_t(const value_type& key_value_pair) - : key_value_pair(key_value_pair) - { - } - - value_type key_value_pair; - }; - - private: - - typedef etl::intrusive_forward_list bucket_t; - typedef etl::ipool pool_t; - - public: - - // Local iterators iterate over one bucket. - typedef typename bucket_t::iterator local_iterator; - typedef typename bucket_t::const_iterator local_const_iterator; - - //********************************************************************* - class iterator : public std::iterator - { - public: - - typedef typename iunordered_map::value_type value_type; - typedef typename iunordered_map::key_type key_type; - typedef typename iunordered_map::mapped_type mapped_type; - typedef typename iunordered_map::hasher hasher; - typedef typename iunordered_map::key_equal key_equal; - typedef typename iunordered_map::reference reference; - typedef typename iunordered_map::const_reference const_reference; - typedef typename iunordered_map::pointer pointer; - typedef typename iunordered_map::const_pointer const_pointer; - typedef typename iunordered_map::size_type size_type; - - friend class iunordered_map; - - //********************************* - iterator() - { - } - - //********************************* - iterator(const iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - iterator operator ++(int) - { - iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - iterator operator =(const iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - std::pair operator *() - { - return inode->key_value_pair; - } - - //********************************* - const_reference operator *() const - { - return inode->key_value_pair; - } - - //********************************* - pointer operator &() - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key_value_pair); - } - - //********************************* - pointer operator ->() - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key_value_pair); - } - - //********************************* - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t* get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - //********************************************************************* - class const_iterator : public std::iterator - { - public: - - typedef typename iunordered_map::value_type value_type; - typedef typename iunordered_map::key_type key_type; - typedef typename iunordered_map::mapped_type mapped_type; - typedef typename iunordered_map::hasher hasher; - typedef typename iunordered_map::key_equal key_equal; - typedef typename iunordered_map::reference reference; - typedef typename iunordered_map::const_reference const_reference; - typedef typename iunordered_map::pointer pointer; - typedef typename iunordered_map::const_pointer const_pointer; - typedef typename iunordered_map::size_type size_type; - - friend class iunordered_map; - friend class iterator; - - //********************************* - const_iterator() - { - } - - //********************************* - const_iterator(const typename iunordered_map::iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator(const const_iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - const_iterator operator ++(int) - { - const_iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - const_iterator operator =(const const_iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - const_reference operator *() const - { - return inode->key_value_pair; - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key_value_pair); - } - - //********************************* - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const const_iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t* get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_map. - ///\return An iterator to the beginning of the unordered_map. - //********************************************************************* - iterator begin() - { - return iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_map. - ///\return A const iterator to the beginning of the unordered_map. - //********************************************************************* - const_iterator begin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_map. - ///\return A const iterator to the beginning of the unordered_map. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_map bucket. - ///\return An iterator to the beginning of the unordered_map bucket. - //********************************************************************* - local_iterator begin(size_t i) - { - return (*pbuckets)[i].begin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_map bucket. - ///\return A const iterator to the beginning of the unordered_map bucket. - //********************************************************************* - local_const_iterator begin(size_t i) const - { - return (*pbuckets)[i].cbegin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_map bucket. - ///\return A const iterator to the beginning of the unordered_map bucket. - //********************************************************************* - local_const_iterator cbegin(size_t i) const - { - return (*pbuckets)[i].cbegin(); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_map. - ///\return An iterator to the end of the unordered_map. - //********************************************************************* - iterator end() - { - return iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_map. - ///\return A const iterator to the end of the unordered_map. - //********************************************************************* - const_iterator end() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_map. - ///\return A const iterator to the end of the unordered_map. - //********************************************************************* - const_iterator cend() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_map bucket. - ///\return An iterator to the end of the unordered_map bucket. - //********************************************************************* - local_iterator end(size_t i) - { - return (*pbuckets)[i].end(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_map bucket. - ///\return A const iterator to the end of the unordered_map bucket. - //********************************************************************* - local_const_iterator end(size_t i) const - { - return (*pbuckets)[i].cend(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_map bucket. - ///\return A const iterator to the end of the unordered_map bucket. - //********************************************************************* - local_const_iterator cend(size_t i) const - { - return (*pbuckets)[i].cend(); - } - - //********************************************************************* - /// Returns the bucket index for the key. - ///\return The bucket index for the key. - //********************************************************************* - size_type bucket(key_value_parameter_t key) const - { - return key_hash_function(key) % number_of_buckets; - } - - //********************************************************************* - /// Returns the size of the bucket key. - ///\return The bucket size of the bucket key. - //********************************************************************* - size_type bucket_size(key_value_parameter_t key) const - { - size_t index = bucket(key); - - return std::distance((*pbuckets)[index].begin(), (*pbuckets)[index].end()); - } - - //********************************************************************* - /// Returns the maximum number of the buckets the container can hold. - ///\return The maximum number of the buckets the container can hold. - //********************************************************************* - size_type max_bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Returns the number of the buckets the container holds. - ///\return The number of the buckets the container holds. - //********************************************************************* - size_type bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - ///\param key The key. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& operator [](key_value_parameter_t key) - { - // Find the bucket. - bucket_t* pbucket = pbuckets + bucket(key); - - // Find the first node in the bucket. - local_iterator inode = pbucket->begin(); - - // Walk the list looking for the right one. - while (inode != pbucket->end()) - { - // Equal keys? - if (key_equal_function(key, inode->key_value_pair.first)) - { - // Found a match. - return inode->key_value_pair.second; - } - else - { - ++inode; - } - } - - // Doesn't exist, so add a new one. - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key_value_pair) value_type(key, T()); - ++construct_count; - - pbucket->insert_after(pbucket->before_begin(), node); - - return pbucket->begin()->key_value_pair.second; - } - - //********************************************************************* - /// Returns a reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::unordered_map_out_of_range if the key is not in the range. - ///\param key The key. - ///\return A reference to the value at index 'key' - //********************************************************************* - mapped_type& at(key_value_parameter_t key) - { - // Find the bucket. - bucket_t* pbucket = pbuckets + bucket(key); - - // Find the first node in the bucket. - local_iterator inode = pbucket->begin(); - - // Walk the list looking for the right one. - while (inode != pbucket->end()) - { - // Equal keys? - if (key_equal_function(key, inode->key_value_pair.first)) - { - // Found a match. - return inode->key_value_pair.second; - } - else - { - ++inode; - } - } - - // Doesn't exist. - ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range)); - - return begin()->second; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'key' - /// If asserts or exceptions are enabled, emits an etl::unordered_map_out_of_range if the key is not in the range. - ///\param key The key. - ///\return A const reference to the value at index 'key' - //********************************************************************* - const mapped_type& at(key_value_parameter_t key) const - { - // Find the bucket. - bucket_t* pbucket = pbuckets + bucket(key); - - // Find the first node in the bucket. - local_iterator inode = pbucket->begin(); - - // Walk the list looking for the right one. - while (inode != pbucket->end()) - { - // Equal keys? - if (key_equal_function(key, inode->key_value_pair.first)) - { - // Found a match. - return inode->key_value_pair.second; - } - else - { - ++inode; - } - } - - // Doesn't exist. - ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range)); - - return begin()->second; - } - - //********************************************************************* - /// Assigns values to the unordered_map. - /// If asserts or exceptions are enabled, emits unordered_map_full if the unordered_map does not have enough free space. - /// If asserts or exceptions are enabled, emits unordered_map_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(unordered_map_iterator)); - ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_map_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the unordered_map. - /// If asserts or exceptions are enabled, emits unordered_map_full if the unordered_map is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& key_value_pair) - { - std::pair result(end(), false); - - ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full)); - - const key_type& key = key_value_pair.first; - const mapped_type& mapped = key_value_pair.second; - - // Get the hash index. - size_t index = bucket(key); - - // Get the bucket & bucket iterator. - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - size_t s = pbuckets->size(); - - // The first one in the bucket? - if (bucket.empty()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key_value_pair) value_type(key_value_pair); - ++construct_count; - - // Just add the pointer to the bucket; - bucket.insert_after(bucket.before_begin(), node); - - result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin()); - result.second = true; - - adjust_first_last_markers(pbucket); - } - else - { - // Step though the bucket looking for a place to insert. - local_iterator inode_previous = bucket.before_begin(); - local_iterator inode = bucket.begin(); - - while (inode != bucket.end()) - { - // Do we already have this key? - if (inode->key_value_pair.first == key) - { - break; - } - - ++inode_previous; - ++inode; - } - - // Not already there? - if (inode == bucket.end()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key_value_pair) value_type(key_value_pair); - ++construct_count; - - // Add the node to the end of the bucket; - bucket.insert_after(inode_previous, node); - ++inode_previous; - - result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous); - result.second = true; - } - } - - return result; - } - - //********************************************************************* - /// Inserts a value to the unordered_map. - /// If asserts or exceptions are enabled, emits unordered_map_full if the unordered_map is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, const value_type& key_value_pair) - { - return insert(key_value_pair).first; - } - - //********************************************************************* - /// Inserts a range of values to the unordered_map. - /// If asserts or exceptions are enabled, emits unordered_map_full if the unordered_map does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - size_t count = 0; - size_t index = bucket(key); - - bucket_t& bucket = pbuckets[index]; - - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = bucket.begin(); - - // Search for the key, if we have it. - while ((icurrent != bucket.end()) && (icurrent->key_value_pair.first != key)) - { - ++iprevious; - ++icurrent; - } - - // Did we find it? - if (icurrent != bucket.end()) - { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - count = 1; - --construct_count; - } - - return count; - } - - //********************************************************************* - /// Erases an element. - ///\param ielement Iterator to the element. - //********************************************************************* - iterator erase(const_iterator ielement) - { - // Make a note of the next one. - iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator()); - ++inext; - - bucket_t& bucket = ielement.get_bucket(); - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = ielement.get_local_iterator(); - - // Find the node previous to the one we're interested in. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - return inext; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed to by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator()); - - // Get the starting point. - bucket_t* pbucket = first.get_bucket_list_iterator(); - local_iterator iprevious = pbucket->before_begin(); - local_iterator icurrent = first.get_local_iterator(); - local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent. - - // Find the node previous to the first one. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - while (icurrent != iend) - { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - icurrent = inext; - - // Are we there yet? - if (icurrent != iend) - { - // At the end of this bucket? - if ((icurrent == pbucket->end())) - { - // Find the next non-empty one. - do - { - ++pbucket; - } while (pbucket->empty()); - - iprevious = pbucket->before_begin(); - icurrent = pbucket->begin(); - } - } - } - - return result; - } - - //************************************************************************* - /// Clears the unordered_map. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - return (find(key) == end()) ? 0 : 1; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - iterator find(key_value_parameter_t key) - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key_value_pair.first)) - { - return iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key_value_pair.first)) - { - return iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return An iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - iterator first = find(key); - iterator last = first; - - if (last != end()) - { - ++last; - } - - return std::pair(first, last); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return A const iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - } - - return std::pair(first, last); - } - - //************************************************************************* - /// Gets the size of the unordered_map. - //************************************************************************* - size_type size() const - { - return pnodepool->size(); - } - - //************************************************************************* - /// Gets the maximum possible size of the unordered_map. - //************************************************************************* - size_type max_size() const - { - return pnodepool->max_items(); - } - - //************************************************************************* - /// Checks to see if the unordered_map is empty. - //************************************************************************* - bool empty() const - { - return pnodepool->empty(); - } - - //************************************************************************* - /// Checks to see if the unordered_map is full. - //************************************************************************* - bool full() const - { - return pnodepool->full(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return pnodepool->available(); - } - - //************************************************************************* - /// Returns the load factor = size / bucket_count. - ///\return The load factor = size / bucket_count. - //************************************************************************* - float load_factor() const - { - return static_cast(size()) / static_cast(bucket_count()); - } - - //************************************************************************* - /// Returns the function that hashes the keys. - ///\return The function that hashes the keys.. - //************************************************************************* - hasher hash_function() const - { - return key_hash_function; - } - - //************************************************************************* - /// Returns the function that compares the keys. - ///\return The function that compares the keys.. - //************************************************************************* - key_equal key_eq() const - { - return key_equal_function; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iunordered_map& operator = (const iunordered_map& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iunordered_map(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets) - : pnodepool(&node_pool), - pbuckets(pbuckets_), - number_of_buckets(number_of_buckets) - { - } - - //********************************************************************* - /// Initialise the unordered_map. - //********************************************************************* - void initialise() - { - if (!empty()) - { - // For each bucket... - for (size_t i = 0; i < number_of_buckets; ++i) - { - bucket_t& bucket = pbuckets[i]; - - if (!bucket.empty()) - { - // For each item in the bucket... - local_iterator it = bucket.begin(); - - while (it != bucket.end()) - { - // Destroy the value contents. - it->key_value_pair.~value_type(); - --construct_count; - - ++it; - } - - // Now it's safe to clear the bucket. - bucket.clear(); - } - } - - // Now it's safe to clear the entire pool in one go. - pnodepool->release_all(); - } - - first = pbuckets; - last = first; - } - - private: - - //********************************************************************* - /// Adjust the first and last markers according to the new entry. - //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) - { - if (pbucket < first) - { - first = pbucket; - } - else if (pbucket > last) - { - last = pbucket; - } - } - - // Disable copy construction. - iunordered_map(const iunordered_map&); - - /// The pool of data nodes used in the list. - pool_t* pnodepool; - - /// The bucket list. - bucket_t* pbuckets; - - /// The number of buckets. - const size_t number_of_buckets; - - /// The first and last pointers to buckets with values. - bucket_t* first; - bucket_t* last; - - /// The function that creates the hashes. - hasher key_hash_function; - - /// The function that compares the keys for equality. - key_equal key_equal_function; - - /// For library debugging purposes only. - etl::debug_count construct_count; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first unordered_map. - ///\param rhs Reference to the second unordered_map. - ///\return true if the arrays are equal, otherwise false - ///\ingroup unordered_map - //*************************************************************************** - template - bool operator ==(const etl::iunordered_map& lhs, const etl::iunordered_map& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first unordered_map. - ///\param rhs Reference to the second unordered_map. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup unordered_map - //*************************************************************************** - template - bool operator !=(const etl::iunordered_map& lhs, const etl::iunordered_map& rhs) - { - return !(lhs == rhs); - } -} - -#undef ETL_FILE -#endif diff --git a/src/iunordered_multimap.h b/src/iunordered_multimap.h deleted file mode 100644 index 52be139e..00000000 --- a/src/iunordered_multimap.h +++ /dev/null @@ -1,1219 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_IUNORDERED_MULTIMAP__ -#define __ETL_IUNORDERED_MULTIMAP__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "hash.h" -#include "nullptr.h" -#include "pool.h" -#include "vector.h" -#include "error_handler.h" -#include "intrusive_forward_list.h" -#include "exception.h" -#include "error_handler.h" -#include "debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "25" - -namespace etl -{ - //*************************************************************************** - /// Exception for the unordered_multimap. - ///\ingroup unordered_multimap - //*************************************************************************** - class unordered_multimap_exception : public exception - { - public: - - unordered_multimap_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the unordered_multimap. - ///\ingroup unordered_multimap - //*************************************************************************** - class unordered_multimap_full : public unordered_multimap_exception - { - public: - - unordered_multimap_full(string_type file_name, numeric_type line_number) - : unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Out of range exception for the unordered_multimap. - ///\ingroup unordered_multimap - //*************************************************************************** - class unordered_multimap_out_of_range : public unordered_multimap_exception - { - public: - - unordered_multimap_out_of_range(string_type file_name, numeric_type line_number) - : unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:range", ETL_FILE"B"), file_name, line_number) - {} - }; - - //*************************************************************************** - /// Iterator exception for the unordered_multimap. - ///\ingroup unordered_multimap - //*************************************************************************** - class unordered_multimap_iterator : public unordered_multimap_exception - { - public: - - unordered_multimap_iterator(string_type file_name, numeric_type line_number) - : unordered_multimap_exception(ETL_ERROR_TEXT("unordered_multimap:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for specifically sized unordered_multimap. - /// Can be used as a reference type for all unordered_multimap containing a specific type. - ///\ingroup unordered_multimap - //*************************************************************************** - template , typename TKeyEqual = std::equal_to > - class iunordered_multimap - { - public: - - typedef std::pair value_type; - - typedef TKey key_type; - typedef T mapped_type; - typedef THash hasher; - typedef TKeyEqual key_equal; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - - typedef typename parameter_type::type key_value_parameter_t; - - typedef etl::forward_link<0> link_t; // Default link. - - // The nodes that store the elements. - struct node_t : public link_t - { - node_t(const value_type& key_value_pair) - : key_value_pair(key_value_pair) - { - } - - value_type key_value_pair; - }; - - private: - - typedef etl::intrusive_forward_list bucket_t; - typedef etl::ipool pool_t; - - public: - - // Local iterators iterate over one bucket. - typedef typename bucket_t::iterator local_iterator; - typedef typename bucket_t::const_iterator local_const_iterator; - - //********************************************************************* - class iterator : public std::iterator - { - public: - - typedef typename iunordered_multimap::value_type value_type; - typedef typename iunordered_multimap::key_type key_type; - typedef typename iunordered_multimap::mapped_type mapped_type; - typedef typename iunordered_multimap::hasher hasher; - typedef typename iunordered_multimap::key_equal key_equal; - typedef typename iunordered_multimap::reference reference; - typedef typename iunordered_multimap::const_reference const_reference; - typedef typename iunordered_multimap::pointer pointer; - typedef typename iunordered_multimap::const_pointer const_pointer; - typedef typename iunordered_multimap::size_type size_type; - - friend class iunordered_multimap; - - //********************************* - iterator() - { - } - - //********************************* - iterator(const iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - iterator operator ++(int) - { - iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - iterator operator =(const iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - std::pair operator *() - { - return inode->key_value_pair; - } - - //********************************* - const_reference operator *() const - { - return inode->key_value_pair; - } - - //********************************* - pointer operator &() - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key_value_pair); - } - - //********************************* - pointer operator ->() - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key_value_pair); - } - - //********************************* - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - //********************************************************************* - class const_iterator : public std::iterator - { - public: - - typedef typename iunordered_multimap::value_type value_type; - typedef typename iunordered_multimap::key_type key_type; - typedef typename iunordered_multimap::mapped_type mapped_type; - typedef typename iunordered_multimap::hasher hasher; - typedef typename iunordered_multimap::key_equal key_equal; - typedef typename iunordered_multimap::reference reference; - typedef typename iunordered_multimap::const_reference const_reference; - typedef typename iunordered_multimap::pointer pointer; - typedef typename iunordered_multimap::const_pointer const_pointer; - typedef typename iunordered_multimap::size_type size_type; - - friend class iunordered_multimap; - friend class iterator; - - //********************************* - const_iterator() - { - } - - //********************************* - const_iterator(const typename iunordered_multimap::iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator(const const_iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - const_iterator operator ++(int) - { - const_iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - const_iterator operator =(const const_iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - const_reference operator *() const - { - return inode->key_value_pair; - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key_value_pair); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key_value_pair); - } - - //********************************* - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const const_iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_multimap. - ///\return An iterator to the beginning of the unordered_multimap. - //********************************************************************* - iterator begin() - { - return iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multimap. - ///\return A const iterator to the beginning of the unordered_multimap. - //********************************************************************* - const_iterator begin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multimap. - ///\return A const iterator to the beginning of the unordered_multimap. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_multimap bucket. - ///\return An iterator to the beginning of the unordered_multimap bucket. - //********************************************************************* - local_iterator begin(size_t i) - { - return pbuckets[i].begin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multimap bucket. - ///\return A const iterator to the beginning of the unordered_multimap bucket. - //********************************************************************* - local_const_iterator begin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multimap bucket. - ///\return A const iterator to the beginning of the unordered_multimap bucket. - //********************************************************************* - local_const_iterator cbegin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_multimap. - ///\return An iterator to the end of the unordered_multimap. - //********************************************************************* - iterator end() - { - return iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multimap. - ///\return A const iterator to the end of the unordered_multimap. - //********************************************************************* - const_iterator end() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multimap. - ///\return A const iterator to the end of the unordered_multimap. - //********************************************************************* - const_iterator cend() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_multimap bucket. - ///\return An iterator to the end of the unordered_multimap bucket. - //********************************************************************* - local_iterator end(size_t i) - { - return pbuckets[i].end(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multimap bucket. - ///\return A const iterator to the end of the unordered_multimap bucket. - //********************************************************************* - local_const_iterator end(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multimap bucket. - ///\return A const iterator to the end of the unordered_multimap bucket. - //********************************************************************* - local_const_iterator cend(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns the bucket index for the key. - ///\return The bucket index for the key. - //********************************************************************* - size_type bucket(key_value_parameter_t key) const - { - return key_hash_function(key) % number_of_buckets; - } - - //********************************************************************* - /// Returns the size of the bucket key. - ///\return The bucket size of the bucket key. - //********************************************************************* - size_type bucket_size(key_value_parameter_t key) const - { - size_t index = bucket(key); - - return std::distance(pbuckets[index].begin(), pbuckets[index].end()); - } - - //********************************************************************* - /// Returns the maximum number of the buckets the container can hold. - ///\return The maximum number of the buckets the container can hold. - //********************************************************************* - size_type max_bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Returns the number of the buckets the container holds. - ///\return The number of the buckets the container holds. - //********************************************************************* - size_type bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Assigns values to the unordered_multimap. - /// If asserts or exceptions are enabled, emits unordered_multimap_full if the unordered_multimap does not have enough free space. - /// If asserts or exceptions are enabled, emits unordered_multimap_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(unordered_multimap_iterator)); - ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_multimap_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the unordered_multimap. - /// If asserts or exceptions are enabled, emits unordered_multimap_full if the unordered_multimap is already full. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const value_type& key_value_pair) - { - iterator result = end(); - - ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full)); - - const key_type& key = key_value_pair.first; - const mapped_type& mapped = key_value_pair.second; - - // Get the hash index. - size_t index = bucket(key); - - // Get the bucket & bucket iterator. - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // The first one in the bucket? - if (bucket.empty()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key_value_pair) value_type(key_value_pair); - ++construct_count; - - // Just add the pointer to the bucket; - bucket.insert_after(bucket.before_begin(), node); - - result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin()); - - adjust_first_last_markers(pbucket); - } - else - { - // Step though the bucket looking for a place to insert. - local_iterator inode_previous = bucket.before_begin(); - local_iterator inode = bucket.begin(); - - while (inode != bucket.end()) - { - // Do we already have this key? - if (inode->key_value_pair.first == key) - { - break; - } - - ++inode_previous; - ++inode; - } - - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key_value_pair) value_type(key_value_pair); - ++construct_count; - - // Add the node to the end of the bucket; - bucket.insert_after(inode_previous, node); - ++inode_previous; - - result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous); - } - - return result; - } - - //********************************************************************* - /// Inserts a value to the unordered_multimap. - /// If asserts or exceptions are enabled, emits unordered_multimap_full if the unordered_multimap is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, const value_type& key_value_pair) - { - return insert(key_value_pair); - } - - //********************************************************************* - /// Inserts a range of values to the unordered_multimap. - /// If asserts or exceptions are enabled, emits unordered_multimap_full if the unordered_multimap does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - size_t count = 0; - size_t bucket_id = bucket(key); - - bucket_t& bucket = pbuckets[bucket_id]; - - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = bucket.begin(); - - while (icurrent != bucket.end()) - { - if (icurrent->key_value_pair.first == key) - { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - ++count; - icurrent = iprevious; - --construct_count; - } - else - { - ++iprevious; - } - - ++icurrent; - } - - return count; - } - - //********************************************************************* - /// Erases an element. - ///\param ielement Iterator to the element. - //********************************************************************* - iterator erase(const_iterator ielement) - { - // Make a note of the next one. - iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator()); - ++inext; - - bucket_t& bucket = ielement.get_bucket(); - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = ielement.get_local_iterator(); - - // Find the node previous to the one we're interested in. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - return inext; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed to by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator()); - - // Get the starting point. - bucket_t* pbucket = first.get_bucket_list_iterator(); - local_iterator iprevious = pbucket->before_begin(); - local_iterator icurrent = first.get_local_iterator(); - local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent. - - // Find the node previous to the first one. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - while (icurrent != iend) - { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - icurrent = inext; - - // Are we there yet? - if (icurrent != iend) - { - // At the end of this bucket? - if ((icurrent == pbucket->end())) - { - // Find the next non-empty one. - do - { - ++pbucket; - } while (pbucket->empty()); - - iprevious = pbucket->before_begin(); - icurrent = pbucket->begin(); - } - } - } - - return result; - } - - //************************************************************************* - /// Clears the unordered_multimap. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - size_t n = 0; - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - ++n; - - while ((last != end()) && (key == last->first)) - { - ++last; - ++n; - } - } - - return n; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - iterator find(key_value_parameter_t key) - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key_value_pair.first)) - { - return iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key_value_pair.first)) - { - return const_iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return An iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - iterator first = find(key); - iterator last = first; - - if (last != end()) - { - ++last; - - while ((last != end()) && (key == last->first)) - { - ++last; - } - } - - return std::pair(first, last); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return A const iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - - while ((last != end()) && (key == last->first)) - { - ++last; - } - } - - return std::pair(first, last); - } - - //************************************************************************* - /// Gets the size of the unordered_multimap. - //************************************************************************* - size_type size() const - { - return pnodepool->size(); - } - - //************************************************************************* - /// Gets the maximum possible size of the unordered_multimap. - //************************************************************************* - size_type max_size() const - { - return pnodepool->max_items(); - } - - //************************************************************************* - /// Checks to see if the unordered_multimap is empty. - //************************************************************************* - bool empty() const - { - return pnodepool->empty(); - } - - //************************************************************************* - /// Checks to see if the unordered_multimap is full. - //************************************************************************* - bool full() const - { - return pnodepool->full(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return pnodepool->available(); - } - - //************************************************************************* - /// Returns the load factor = size / bucket_count. - ///\return The load factor = size / bucket_count. - //************************************************************************* - float load_factor() const - { - return static_cast(size()) / static_cast(bucket_count()); - } - - //************************************************************************* - /// Returns the function that hashes the keys. - ///\return The function that hashes the keys.. - //************************************************************************* - hasher hash_function() const - { - return key_hash_function; - } - - //************************************************************************* - /// Returns the function that compares the keys. - ///\return The function that compares the keys.. - //************************************************************************* - key_equal key_eq() const - { - return key_equal_function; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iunordered_multimap& operator = (const iunordered_multimap& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iunordered_multimap(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets) - : pnodepool(&node_pool), - pbuckets(pbuckets_), - number_of_buckets(number_of_buckets) - { - } - - //********************************************************************* - /// Initialise the unordered_multimap. - //********************************************************************* - void initialise() - { - if (!empty()) - { - // For each bucket... - for (size_t i = 0; i < number_of_buckets; ++i) - { - bucket_t& bucket = pbuckets[i]; - - if (!bucket.empty()) - { - // For each item in the bucket... - local_iterator it = bucket.begin(); - - while (it != bucket.end()) - { - // Destroy the value contents. - it->key_value_pair.~value_type(); - ++it; - --construct_count; - } - - // Now it's safe to clear the bucket. - bucket.clear(); - } - } - - // Now it's safe to clear the entire pool in one go. - pnodepool->release_all(); - } - - first = pbuckets; - last = first; - } - - private: - - //********************************************************************* - /// Adjust the first and last markers according to the new entry. - //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) - { - if (pbucket < first) - { - first = pbucket; - } - else if (pbucket > last) - { - last = pbucket; - } - } - - // Disable copy construction. - iunordered_multimap(const iunordered_multimap&); - - /// The pool of data nodes used in the list. - pool_t* pnodepool; - - /// The bucket list. - bucket_t* pbuckets; - - /// The number of buckets. - const size_t number_of_buckets; - - /// The first and last iterators to buckets with values. - bucket_t* first; - bucket_t* last; - - /// The function that creates the hashes. - hasher key_hash_function; - - /// The function that compares the keys for equality. - key_equal key_equal_function; - - /// For library debugging purposes only. - etl::debug_count construct_count; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first unordered_multimap. - ///\param rhs Reference to the second unordered_multimap. - ///\return true if the arrays are equal, otherwise false - ///\ingroup unordered_multimap - //*************************************************************************** - template - bool operator ==(const etl::iunordered_multimap& lhs, const etl::iunordered_multimap& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first unordered_multimap. - ///\param rhs Reference to the second unordered_multimap. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup unordered_multimap - //*************************************************************************** - template - bool operator !=(const etl::iunordered_multimap& lhs, const etl::iunordered_multimap& rhs) - { - return !(lhs == rhs); - } -} - -#undef ETL_FILE -#endif diff --git a/src/iunordered_multiset.h b/src/iunordered_multiset.h deleted file mode 100644 index 4270b337..00000000 --- a/src/iunordered_multiset.h +++ /dev/null @@ -1,1213 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_IUNORDERED_MULTISET__ -#define __ETL_IUNORDERED_MULTISET__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "hash.h" -#include "nullptr.h" -#include "pool.h" -#include "vector.h" -#include "error_handler.h" -#include "intrusive_forward_list.h" -#include "exception.h" -#include "error_handler.h" -#include "debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "26" - -namespace etl -{ - //*************************************************************************** - /// Exception for the unordered_multiset. - ///\ingroup unordered_multiset - //*************************************************************************** - class unordered_multiset_exception : public exception - { - public: - - unordered_multiset_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the unordered_multiset. - ///\ingroup unordered_multiset - //*************************************************************************** - class unordered_multiset_full : public unordered_multiset_exception - { - public: - - unordered_multiset_full(string_type file_name, numeric_type line_number) - : unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Out of range exception for the unordered_multiset. - ///\ingroup unordered_multiset - //*************************************************************************** - class unordered_multiset_out_of_range : public unordered_multiset_exception - { - public: - - unordered_multiset_out_of_range(string_type file_name, numeric_type line_number) - : unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:range", ETL_FILE"B"), file_name, line_number) - {} - }; - - //*************************************************************************** - /// Iterator exception for the unordered_multiset. - ///\ingroup unordered_multiset - //*************************************************************************** - class unordered_multiset_iterator : public unordered_multiset_exception - { - public: - - unordered_multiset_iterator(string_type file_name, numeric_type line_number) - : unordered_multiset_exception(ETL_ERROR_TEXT("unordered_multiset:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for specifically sized unordered_multiset. - /// Can be used as a reference type for all unordered_multiset containing a specific type. - ///\ingroup unordered_multiset - //*************************************************************************** - template , typename TKeyEqual = std::equal_to > - class iunordered_multiset - { - public: - - typedef TKey value_type; - typedef TKey key_type; - typedef THash hasher; - typedef TKeyEqual key_equal; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - typedef typename parameter_type::type key_value_parameter_t; - - typedef etl::forward_link<0> link_t; - - // The nodes that store the elements. - struct node_t : public link_t - { - node_t(const value_type& key) - : key(key) - { - } - - value_type key; - }; - - private: - - typedef etl::intrusive_forward_list bucket_t; - typedef etl::ipool pool_t; - - public: - - // Local iterators iterate over one bucket. - typedef typename bucket_t::iterator local_iterator; - typedef typename bucket_t::const_iterator local_const_iterator; - - //********************************************************************* - class iterator : public std::iterator - { - public: - - typedef typename iunordered_multiset::value_type value_type; - typedef typename iunordered_multiset::key_type key_type; - typedef typename iunordered_multiset::hasher hasher; - typedef typename iunordered_multiset::key_equal key_equal; - typedef typename iunordered_multiset::reference reference; - typedef typename iunordered_multiset::const_reference const_reference; - typedef typename iunordered_multiset::pointer pointer; - typedef typename iunordered_multiset::const_pointer const_pointer; - typedef typename iunordered_multiset::size_type size_type; - - friend class iunordered_multiset; - - //********************************* - iterator() - { - } - - //********************************* - iterator(const iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - iterator operator ++(int) - { - iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - iterator operator =(const iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - reference operator *() - { - return inode->key; - } - - //********************************* - const_reference operator *() const - { - return inode->key; - } - - //********************************* - pointer operator &() - { - return &(inode->key); - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key); - } - - //********************************* - pointer operator ->() - { - return &(inode->key); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key); - } - - //********************************* - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - //********************************************************************* - class const_iterator : public std::iterator - { - public: - - typedef typename iunordered_multiset::value_type value_type; - typedef typename iunordered_multiset::key_type key_type; - typedef typename iunordered_multiset::hasher hasher; - typedef typename iunordered_multiset::key_equal key_equal; - typedef typename iunordered_multiset::reference reference; - typedef typename iunordered_multiset::const_reference const_reference; - typedef typename iunordered_multiset::pointer pointer; - typedef typename iunordered_multiset::const_pointer const_pointer; - typedef typename iunordered_multiset::size_type size_type; - - friend class iunordered_multiset; - friend class iterator; - - //********************************* - const_iterator() - { - } - - //********************************* - const_iterator(const typename iunordered_multiset::iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator(const const_iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - const_iterator operator ++(int) - { - const_iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - const_iterator operator =(const const_iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - const_reference operator *() const - { - return inode->key; - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key); - } - - //********************************* - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const const_iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_multiset. - ///\return An iterator to the beginning of the unordered_multiset. - //********************************************************************* - iterator begin() - { - return iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multiset. - ///\return A const iterator to the beginning of the unordered_multiset. - //********************************************************************* - const_iterator begin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multiset. - ///\return A const iterator to the beginning of the unordered_multiset. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator((pbuckets + number_of_buckets), first, first->begin()); - } - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_multiset bucket. - ///\return An iterator to the beginning of the unordered_multiset bucket. - //********************************************************************* - local_iterator begin(size_t i) - { - return pbuckets[i].begin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multiset bucket. - ///\return A const iterator to the beginning of the unordered_multiset bucket. - //********************************************************************* - local_const_iterator begin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_multiset bucket. - ///\return A const iterator to the beginning of the unordered_multiset bucket. - //********************************************************************* - local_const_iterator cbegin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_multiset. - ///\return An iterator to the end of the unordered_multiset. - //********************************************************************* - iterator end() - { - return iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multiset. - ///\return A const iterator to the end of the unordered_multiset. - //********************************************************************* - const_iterator end() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multiset. - ///\return A const iterator to the end of the unordered_multiset. - //********************************************************************* - const_iterator cend() const - { - return const_iterator((pbuckets + number_of_buckets), last, last->end()); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_multiset bucket. - ///\return An iterator to the end of the unordered_multiset bucket. - //********************************************************************* - local_iterator end(size_t i) - { - return pbuckets[i].end(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multiset bucket. - ///\return A const iterator to the end of the unordered_multiset bucket. - //********************************************************************* - local_const_iterator end(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_multiset bucket. - ///\return A const iterator to the end of the unordered_multiset bucket. - //********************************************************************* - local_const_iterator cend(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns the bucket index for the key. - ///\return The bucket index for the key. - //********************************************************************* - size_type bucket(key_value_parameter_t key) const - { - return key_hash_function(key) % number_of_buckets; - } - - //********************************************************************* - /// Returns the size of the bucket key. - ///\return The bucket size of the bucket key. - //********************************************************************* - size_type bucket_size(key_value_parameter_t key) const - { - size_t index = bucket(key); - - return std::distance(pbuckets[index].begin(), pbuckets[index].end()); - } - - //********************************************************************* - /// Returns the maximum number of the buckets the container can hold. - ///\return The maximum number of the buckets the container can hold. - //********************************************************************* - size_type max_bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Returns the number of the buckets the container holds. - ///\return The number of the buckets the container holds. - //********************************************************************* - size_type bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Assigns values to the unordered_multiset. - /// If asserts or exceptions are enabled, emits unordered_multiset_full if the unordered_multiset does not have enough free space. - /// If asserts or exceptions are enabled, emits unordered_multiset_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(unordered_multiset_iterator)); - ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_multiset_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the unordered_multiset. - /// If asserts or exceptions are enabled, emits unordered_multiset_full if the unordered_multiset is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& key) - { - std::pair result(end(), false); - - ETL_ASSERT(!full(), ETL_ERROR(unordered_multiset_full)); - - // Get the hash index. - size_t index = bucket(key); - - // Get the bucket & bucket iterator. - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // The first one in the bucket? - if (bucket.empty()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key) value_type(key); - ++construct_count; - - // Just add the pointer to the bucket; - bucket.insert_after(bucket.before_begin(), node); - - result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin()); - result.second = true; - - adjust_first_last_markers(pbucket); - } - else - { - // Step though the bucket looking for a place to insert. - local_iterator inode_previous = bucket.before_begin(); - local_iterator inode = bucket.begin(); - - while (inode != bucket.end()) - { - // Do we already have this key? - if (inode->key == key) - { - break; - } - - ++inode_previous; - ++inode; - } - - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key) value_type(key); - ++construct_count; - - // Add the node to the end of the bucket; - bucket.insert_after(inode_previous, node); - ++inode_previous; - - result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous); - result.second = true; - } - - return result; - } - - //********************************************************************* - /// Inserts a value to the unordered_multiset. - /// If asserts or exceptions are enabled, emits unordered_multiset_full if the unordered_multiset is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, const value_type& key) - { - return insert(key).first; - } - - //********************************************************************* - /// Inserts a range of values to the unordered_multiset. - /// If asserts or exceptions are enabled, emits unordered_multiset_full if the unordered_multiset does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - size_t count = 0; - size_t bucket_id = bucket(key); - - bucket_t& bucket = pbuckets[bucket_id]; - - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = bucket.begin(); - - while (icurrent != bucket.end()) - { - if (icurrent->key == key) - { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - ++count; - icurrent = iprevious; - --construct_count; - } - else - { - ++iprevious; - } - - ++icurrent; - } - - return count; - } - - //********************************************************************* - /// Erases an element. - ///\param ielement Iterator to the element. - //********************************************************************* - iterator erase(const_iterator ielement) - { - // Make a note of the next one. - iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator()); - ++inext; - - bucket_t& bucket = ielement.get_bucket(); - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = ielement.get_local_iterator(); - - // Find the node previous to the one we're interested in. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - return inext; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed to by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator()); - - // Get the starting point. - bucket_t* pbucket = first.get_bucket_list_iterator(); - local_iterator iprevious = pbucket->before_begin(); - local_iterator icurrent = first.get_local_iterator(); - local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent. - - // Find the node previous to the first one. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - while (icurrent != iend) - { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - icurrent = inext; - - // Are we there yet? - if (icurrent != iend) - { - // At the end of this bucket? - if ((icurrent == pbucket->end())) - { - // Find the next non-empty one. - do - { - ++pbucket; - } while (pbucket->empty()); - - iprevious = pbucket->before_begin(); - icurrent = pbucket->begin(); - } - } - } - - return result; - } - - //************************************************************************* - /// Clears the unordered_multiset. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - size_t n = 0; - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - ++n; - - while ((last != end()) && (key == *last)) - { - ++last; - ++n; - } - } - - return n; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - iterator find(key_value_parameter_t key) - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key)) - { - return iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key)) - { - return iterator((pbuckets + number_of_buckets), pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return An iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - iterator first = find(key); - iterator last = first; - - if (last != end()) - { - ++last; - - while ((last != end()) && (key == *last)) - { - ++last; - } - } - - return std::pair(first, last); - } - - //********************************************************************* - /// Returns a range containing all elements with key key in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return A const iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - - while ((last != end()) && (key == *last)) - { - ++last; - } - } - - return std::pair(first, last); - } - - //************************************************************************* - /// Gets the size of the unordered_multiset. - //************************************************************************* - size_type size() const - { - return pnodepool->size(); - } - - //************************************************************************* - /// Gets the maximum possible size of the unordered_multiset. - //************************************************************************* - size_type max_size() const - { - return pnodepool->max_items(); - } - - //************************************************************************* - /// Checks to see if the unordered_multiset is empty. - //************************************************************************* - bool empty() const - { - return pnodepool->empty(); - } - - //************************************************************************* - /// Checks to see if the unordered_multiset is full. - //************************************************************************* - bool full() const - { - return pnodepool->full(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return pnodepool->available(); - } - - //************************************************************************* - /// Returns the load factor = size / bucket_count. - ///\return The load factor = size / bucket_count. - //************************************************************************* - float load_factor() const - { - return static_cast(size()) / static_cast(bucket_count()); - } - - //************************************************************************* - /// Returns the function that hashes the keys. - ///\return The function that hashes the keys.. - //************************************************************************* - hasher hash_function() const - { - return key_hash_function; - } - - //************************************************************************* - /// Returns the function that compares the keys. - ///\return The function that compares the keys.. - //************************************************************************* - key_equal key_eq() const - { - return key_equal_function; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iunordered_multiset& operator = (const iunordered_multiset& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iunordered_multiset(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets) - : pnodepool(&node_pool), - pbuckets(pbuckets_), - number_of_buckets(number_of_buckets) - { - } - - //********************************************************************* - /// Initialise the unordered_multiset. - //********************************************************************* - void initialise() - { - if (!empty()) - { - // For each bucket... - for (size_t i = 0; i < number_of_buckets; ++i) - { - bucket_t& bucket = pbuckets[i]; - - if (!bucket.empty()) - { - // For each item in the bucket... - local_iterator it = bucket.begin(); - - while (it != bucket.end()) - { - // Destroy the value contents. - it->key.~value_type(); - ++it; - --construct_count; - } - - // Now it's safe to clear the bucket. - bucket.clear(); - } - } - - // Now it's safe to clear the entire pool in one go. - pnodepool->release_all(); - } - - first = pbuckets; - last = first; - } - - private: - - //********************************************************************* - /// Adjust the first and last markers according to the new entry. - //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) - { - if (pbucket < first) - { - first = pbucket; - } - else if (pbucket > last) - { - last = pbucket; - } - } - - // Disable copy construction. - iunordered_multiset(const iunordered_multiset&); - - /// The pool of data nodes used in the list. - pool_t* pnodepool; - - /// The bucket list. - bucket_t* pbuckets; - - /// The number of buckets. - const size_t number_of_buckets; - - /// The first and last iterators to buckets with values. - bucket_t* first; - bucket_t* last; - - /// The function that creates the hashes. - hasher key_hash_function; - - /// The function that compares the keys for equality. - key_equal key_equal_function; - - /// For library debugging purposes only. - etl::debug_count construct_count; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first unordered_multiset. - ///\param rhs Reference to the second unordered_multiset. - ///\return true if the arrays are equal, otherwise false - ///\ingroup unordered_multiset - //*************************************************************************** - template - bool operator ==(const etl::iunordered_multiset& lhs, const etl::iunordered_multiset& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first unordered_multiset. - ///\param rhs Reference to the second unordered_multiset. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup unordered_multiset - //*************************************************************************** - template - bool operator !=(const etl::iunordered_multiset& lhs, const etl::iunordered_multiset& rhs) - { - return !(lhs == rhs); - } -} - -#undef ETL_FILE -#endif diff --git a/src/iunordered_set.h b/src/iunordered_set.h deleted file mode 100644 index a4ef7391..00000000 --- a/src/iunordered_set.h +++ /dev/null @@ -1,1189 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_IUNORDERED_SET__ -#define __ETL_IUNORDERED_SET__ - -#include -#include -#include -#include -#include - -#include "platform.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "hash.h" -#include "nullptr.h" -#include "pool.h" -#include "vector.h" -#include "error_handler.h" -#include "intrusive_forward_list.h" -#include "exception.h" -#include "error_handler.h" -#include "debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "23" - -namespace etl -{ - //*************************************************************************** - /// Exception for the unordered_set. - ///\ingroup unordered_set - //*************************************************************************** - class unordered_set_exception : public exception - { - public: - - unordered_set_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the unordered_set. - ///\ingroup unordered_set - //*************************************************************************** - class unordered_set_full : public unordered_set_exception - { - public: - - unordered_set_full(string_type file_name, numeric_type line_number) - : unordered_set_exception(ETL_ERROR_TEXT("unordered_set:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Out of range exception for the unordered_set. - ///\ingroup unordered_set - //*************************************************************************** - class unordered_set_out_of_range : public unordered_set_exception - { - public: - - unordered_set_out_of_range(string_type file_name, numeric_type line_number) - : unordered_set_exception(ETL_ERROR_TEXT("unordered_set:range", ETL_FILE"B"), file_name, line_number) - {} - }; - - //*************************************************************************** - /// Iterator exception for the unordered_set. - ///\ingroup unordered_set - //*************************************************************************** - class unordered_set_iterator : public unordered_set_exception - { - public: - - unordered_set_iterator(string_type file_name, numeric_type line_number) - : unordered_set_exception(ETL_ERROR_TEXT("unordered_set:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for specifically sized unordered_set. - /// Can be used as a reference type for all unordered_set containing a specific type. - ///\ingroup unordered_set - //*************************************************************************** - template , typename TKeyEqual = std::equal_to > - class iunordered_set - { - public: - - typedef TKey value_type; - typedef TKey key_type; - typedef THash hasher; - typedef TKeyEqual key_equal; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef size_t size_type; - - typedef typename parameter_type::type key_value_parameter_t; - - typedef etl::forward_link<0> link_t; - - // The nodes that store the elements. - struct node_t : public link_t - { - node_t(const value_type& key) - : key(key) - { - } - - value_type key; - }; - - private: - - typedef etl::intrusive_forward_list bucket_t; - typedef etl::ipool pool_t; - - public: - - // Local iterators iterate over one bucket. - typedef typename bucket_t::iterator local_iterator; - typedef typename bucket_t::const_iterator local_const_iterator; - - //********************************************************************* - class iterator : public std::iterator - { - public: - - typedef typename iunordered_set::value_type value_type; - typedef typename iunordered_set::key_type key_type; - typedef typename iunordered_set::hasher hasher; - typedef typename iunordered_set::key_equal key_equal; - typedef typename iunordered_set::reference reference; - typedef typename iunordered_set::const_reference const_reference; - typedef typename iunordered_set::pointer pointer; - typedef typename iunordered_set::const_pointer const_pointer; - typedef typename iunordered_set::size_type size_type; - - friend class iunordered_set; - - //********************************* - iterator() - { - } - - //********************************* - iterator(const iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - iterator operator ++(int) - { - iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - iterator operator =(const iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - reference operator *() - { - return inode->key; - } - - //********************************* - const_reference operator *() const - { - return inode->key; - } - - //********************************* - pointer operator &() - { - return &(inode->key); - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key); - } - - //********************************* - pointer operator ->() - { - return &(inode->key); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key); - } - - //********************************* - friend bool operator == (const iterator& lhs, const iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const iterator& lhs, const iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - //********************************************************************* - class const_iterator : public std::iterator - { - public: - - typedef typename iunordered_set::value_type value_type; - typedef typename iunordered_set::key_type key_type; - typedef typename iunordered_set::hasher hasher; - typedef typename iunordered_set::key_equal key_equal; - typedef typename iunordered_set::reference reference; - typedef typename iunordered_set::const_reference const_reference; - typedef typename iunordered_set::pointer pointer; - typedef typename iunordered_set::const_pointer const_pointer; - typedef typename iunordered_set::size_type size_type; - - friend class iunordered_set; - friend class iterator; - - //********************************* - const_iterator() - { - } - - //********************************* - const_iterator(const typename iunordered_set::iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator(const const_iterator& other) - : pbuckets_end(other.pbuckets_end), - pbucket(other.pbucket), - inode(other.inode) - { - } - - //********************************* - const_iterator& operator ++() - { - ++inode; - - // The end of this node list? - if (inode == pbucket->end()) - { - // Search for the next non-empty bucket. - - ++pbucket; - while ((pbucket != pbuckets_end) && (pbucket->empty())) - { - ++pbucket; - } - - // If not past the end, get the first node in the bucket. - if (pbucket != pbuckets_end) - { - inode = pbucket->begin(); - } - } - - return *this; - } - - //********************************* - const_iterator operator ++(int) - { - const_iterator temp(*this); - operator++(); - return temp; - } - - //********************************* - const_iterator operator =(const const_iterator& other) - { - pbuckets_end = other.pbuckets_end; - pbucket = other.pbucket; - inode = other.inode; - return *this; - } - - //********************************* - const_reference operator *() const - { - return inode->key; - } - - //********************************* - const_pointer operator &() const - { - return &(inode->key); - } - - //********************************* - const_pointer operator ->() const - { - return &(inode->key); - } - - //********************************* - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) - { - return lhs.compare(rhs); - } - - //********************************* - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) - { - return !(lhs == rhs); - } - - private: - - //********************************* - const_iterator(bucket_t* pbuckets_end, bucket_t* pbucket, local_iterator inode) - : pbuckets_end(pbuckets_end), - pbucket(pbucket), - inode(inode) - { - } - - //********************************* - bool compare(const const_iterator& rhs) const - { - return rhs.inode == inode; - } - - //********************************* - bucket_t& get_bucket() - { - return *pbucket; - } - - //********************************* - bucket_t*& get_bucket_list_iterator() - { - return pbucket; - } - - //********************************* - local_iterator get_local_iterator() - { - return inode; - } - - bucket_t* pbuckets_end; - bucket_t* pbucket; - local_iterator inode; - }; - - typedef typename std::iterator_traits::difference_type difference_type; - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_set. - ///\return An iterator to the beginning of the unordered_set. - //********************************************************************* - iterator begin() - { - return iterator(pbuckets + number_of_buckets, first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_set. - ///\return A const iterator to the beginning of the unordered_set. - //********************************************************************* - const_iterator begin() const - { - return const_iterator(pbuckets + number_of_buckets, first, first->begin()); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_set. - ///\return A const iterator to the beginning of the unordered_set. - //********************************************************************* - const_iterator cbegin() const - { - return const_iterator(pbuckets + number_of_buckets, first, first->begin()); - } - - //********************************************************************* - /// Returns an iterator to the beginning of the unordered_set bucket. - ///\return An iterator to the beginning of the unordered_set bucket. - //********************************************************************* - local_iterator begin(size_t i) - { - return pbuckets[i].begin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_set bucket. - ///\return A const iterator to the beginning of the unordered_set bucket. - //********************************************************************* - local_const_iterator begin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the unordered_set bucket. - ///\return A const iterator to the beginning of the unordered_set bucket. - //********************************************************************* - local_const_iterator cbegin(size_t i) const - { - return pbuckets[i].cbegin(); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_set. - ///\return An iterator to the end of the unordered_set. - //********************************************************************* - iterator end() - { - return iterator(pbuckets + number_of_buckets, last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_set. - ///\return A const iterator to the end of the unordered_set. - //********************************************************************* - const_iterator end() const - { - return const_iterator(pbuckets + number_of_buckets, last, last->end()); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_set. - ///\return A const iterator to the end of the unordered_set. - //********************************************************************* - const_iterator cend() const - { - return const_iterator(pbuckets + number_of_buckets, last, last->end()); - } - - //********************************************************************* - /// Returns an iterator to the end of the unordered_set bucket. - ///\return An iterator to the end of the unordered_set bucket. - //********************************************************************* - local_iterator end(size_t i) - { - return pbuckets[i].end(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_set bucket. - ///\return A const iterator to the end of the unordered_set bucket. - //********************************************************************* - local_const_iterator end(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns a const_iterator to the end of the unordered_set bucket. - ///\return A const iterator to the end of the unordered_set bucket. - //********************************************************************* - local_const_iterator cend(size_t i) const - { - return pbuckets[i].cend(); - } - - //********************************************************************* - /// Returns the bucket index for the key. - ///\return The bucket index for the key. - //********************************************************************* - size_type bucket(key_value_parameter_t key) const - { - return key_hash_function(key) % number_of_buckets; - } - - //********************************************************************* - /// Returns the size of the bucket key. - ///\return The bucket size of the bucket key. - //********************************************************************* - size_type bucket_size(key_value_parameter_t key) const - { - size_t index = bucket(key); - - return std::distance(pbuckets[index].begin(), pbuckets[index].end()); - } - - //********************************************************************* - /// Returns the maximum number of the buckets the container can hold. - ///\return The maximum number of the buckets the container can hold. - //********************************************************************* - size_type max_bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Returns the number of the buckets the container holds. - ///\return The number of the buckets the container holds. - //********************************************************************* - size_type bucket_count() const - { - return number_of_buckets; - } - - //********************************************************************* - /// Assigns values to the unordered_set. - /// If asserts or exceptions are enabled, emits unordered_set_full if the unordered_set does not have enough free space. - /// If asserts or exceptions are enabled, emits unordered_set_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(count >= 0, ETL_ERROR(unordered_set_iterator)); - ETL_ASSERT(size_t(count) <= max_size() , ETL_ERROR(unordered_set_full)); -#endif - - clear(); - - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Inserts a value to the unordered_set. - /// If asserts or exceptions are enabled, emits unordered_set_full if the unordered_set is already full. - ///\param value The value to insert. - //********************************************************************* - std::pair insert(const value_type& key) - { - std::pair result(end(), false); - - ETL_ASSERT(!full(), ETL_ERROR(unordered_set_full)); - - // Get the hash index. - size_t index = bucket(key); - - // Get the bucket & bucket iterator. - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // The first one in the bucket? - if (bucket.empty()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key) value_type(key); - ++construct_count; - - // Just add the pointer to the bucket; - bucket.insert_after(bucket.before_begin(), node); - - result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin()); - result.second = true; - - adjust_first_last_markers(pbucket); - } - else - { - // Step though the bucket looking for a place to insert. - local_iterator inode_previous = bucket.before_begin(); - local_iterator inode = bucket.begin(); - - while (inode != bucket.end()) - { - // Do we already have this key? - if (inode->key == key) - { - break; - } - - ++inode_previous; - ++inode; - } - - // Not already there? - if (inode == bucket.end()) - { - // Get a new node. - node_t& node = *pnodepool->allocate(); - ::new (&node.key) value_type(key); - ++construct_count; - - // Add the node to the end of the bucket; - bucket.insert_after(inode_previous, node); - ++inode_previous; - - result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous); - result.second = true; - } - } - - return result; - } - - //********************************************************************* - /// Inserts a value to the unordered_set. - /// If asserts or exceptions are enabled, emits unordered_set_full if the unordered_set is already full. - ///\param position The position to insert at. - ///\param value The value to insert. - //********************************************************************* - iterator insert(const_iterator position, const value_type& key) - { - return insert(key).first; - } - - //********************************************************************* - /// Inserts a range of values to the unordered_set. - /// If asserts or exceptions are enabled, emits unordered_set_full if the unordered_set does not have enough free space. - ///\param position The position to insert at. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - void insert(TIterator first, TIterator last) - { - while (first != last) - { - insert(*first++); - } - } - - //********************************************************************* - /// Erases an element. - ///\param key The key to erase. - ///\return The number of elements erased. 0 or 1. - //********************************************************************* - size_t erase(key_value_parameter_t key) - { - size_t count = 0; - size_t index = bucket(key); - - bucket_t& bucket = pbuckets[index]; - - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = bucket.begin(); - - // Search for the key, if we have it. - while ((icurrent != bucket.end()) && (icurrent->key != key)) - { - ++iprevious; - ++icurrent; - } - - // Did we find it? - if (icurrent != bucket.end()) - { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - count = 1; - --construct_count; - } - - return count; - } - - //********************************************************************* - /// Erases an element. - ///\param ielement Iterator to the element. - //********************************************************************* - iterator erase(const_iterator ielement) - { - // Make a note of the next one. - iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator()); - ++inext; - - bucket_t& bucket = ielement.get_bucket(); - local_iterator iprevious = bucket.before_begin(); - local_iterator icurrent = ielement.get_local_iterator(); - - // Find the node previous to the one we're interested in. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - return inext; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed to by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - //********************************************************************* - iterator erase(const_iterator first, const_iterator last) - { - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last.get_bucket_list_iterator(), last.get_local_iterator()); - - // Get the starting point. - bucket_t* pbucket = first.get_bucket_list_iterator(); - local_iterator iprevious = pbucket->before_begin(); - local_iterator icurrent = first.get_local_iterator(); - local_iterator iend = last.get_local_iterator(); // Note: May not be in the same bucket as icurrent. - - // Find the node previous to the first one. - while (iprevious->etl_next != &*icurrent) - { - ++iprevious; - } - - while (icurrent != iend) - { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - --construct_count; - - icurrent = inext; - - // Are we there yet? - if (icurrent != iend) - { - // At the end of this bucket? - if ((icurrent == pbucket->end())) - { - // Find the next non-empty one. - do - { - ++pbucket; - } while (pbucket->empty()); - - iprevious = pbucket->before_begin(); - icurrent = pbucket->begin(); - } - } - } - - return result; - } - - //************************************************************************* - /// Clears the unordered_set. - //************************************************************************* - void clear() - { - initialise(); - } - - //********************************************************************* - /// Counts an element. - ///\param key The key to search for. - ///\return 1 if the key exists, otherwise 0. - //********************************************************************* - size_t count(key_value_parameter_t key) const - { - return (find(key) == end()) ? 0 : 1; - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - iterator find(key_value_parameter_t key) - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key)) - { - return iterator(pbuckets + number_of_buckets, pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Finds an element. - ///\param key The key to search for. - ///\return An iterator to the element if the key exists, otherwise end(). - //********************************************************************* - const_iterator find(key_value_parameter_t key) const - { - size_t index = bucket(key); - - bucket_t* pbucket = pbuckets + index; - bucket_t& bucket = *pbucket; - - // Is the bucket not empty? - if (!bucket.empty()) - { - // Step though the list until we find the end or an equivalent key. - local_iterator inode = bucket.begin(); - local_iterator iend = bucket.end(); - - while (inode != iend) - { - // Do we have this one? - if (key_equal_function(key, inode->key)) - { - return iterator(pbuckets + number_of_buckets, pbucket, inode); - } - - ++inode; - } - } - - return end(); - } - - //********************************************************************* - /// Returns a range containing all elements with key 'key' in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return An iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) - { - iterator first = find(key); - iterator last = first; - - if (last != end()) - { - ++last; - } - - return std::pair(first, last); - } - - //********************************************************************* - /// Returns a range containing all elements with key 'key' in the container. - /// The range is defined by two iterators, the first pointing to the first - /// element of the wanted range and the second pointing past the last - /// element of the range. - ///\param key The key to search for. - ///\return A const iterator pair to the range of elements if the key exists, otherwise end(). - //********************************************************************* - std::pair equal_range(const key_value_parameter_t& key) const - { - const_iterator first = find(key); - const_iterator last = first; - - if (last != end()) - { - ++last; - } - - return std::pair(first, last); - } - - //************************************************************************* - /// Gets the size of the unordered_set. - //************************************************************************* - size_type size() const - { - return pnodepool->size(); - } - - //************************************************************************* - /// Gets the maximum possible size of the unordered_set. - //************************************************************************* - size_type max_size() const - { - return pnodepool->max_items(); - } - - //************************************************************************* - /// Checks to see if the unordered_set is empty. - //************************************************************************* - bool empty() const - { - return pnodepool->empty(); - } - - //************************************************************************* - /// Checks to see if the unordered_set is full. - //************************************************************************* - bool full() const - { - return pnodepool->full(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return pnodepool->available(); - } - - //************************************************************************* - /// Returns the load factor = size / bucket_count. - ///\return The load factor = size / bucket_count. - //************************************************************************* - float load_factor() const - { - return static_cast(size()) / static_cast(bucket_count()); - } - - //************************************************************************* - /// Returns the function that hashes the keys. - ///\return The function that hashes the keys.. - //************************************************************************* - hasher hash_function() const - { - return key_hash_function; - } - - //************************************************************************* - /// Returns the function that compares the keys. - ///\return The function that compares the keys.. - //************************************************************************* - key_equal key_eq() const - { - return key_equal_function; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - iunordered_set& operator = (const iunordered_set& rhs) - { - // Skip if doing self assignment - if (this != &rhs) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - iunordered_set(pool_t& node_pool, bucket_t* pbuckets_, size_t number_of_buckets) - : pnodepool(&node_pool), - pbuckets(pbuckets_), - number_of_buckets(number_of_buckets) - { - } - - //********************************************************************* - /// Initialise the unordered_set. - //********************************************************************* - void initialise() - { - if (!empty()) - { - // For each bucket... - for (size_t i = 0; i < number_of_buckets; ++i) - { - bucket_t& bucket = pbuckets[i]; - - if (!bucket.empty()) - { - // For each item in the bucket... - local_iterator it = bucket.begin(); - - while (it != bucket.end()) - { - // Destroy the value contents. - it->key.~value_type(); - ++it; - --construct_count; - } - - // Now it's safe to clear the bucket. - bucket.clear(); - } - } - - // Now it's safe to clear the entire pool in one go. - pnodepool->release_all(); - } - - first = pbuckets; - last = first; - } - - private: - - //********************************************************************* - /// Adjust the first and last markers according to the new entry. - //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) - { - if (pbucket < first) - { - first = pbucket; - } - else if (pbucket > last) - { - last = pbucket; - } - } - - // Disable copy construction. - iunordered_set(const iunordered_set&); - - /// The pool of data nodes used in the list. - pool_t* pnodepool; - - /// The bucket list. - bucket_t* pbuckets; - - /// The number of buckets. - const size_t number_of_buckets; - - /// The first and last iterators to buckets with values. - bucket_t* first; - bucket_t* last; - - /// The function that creates the hashes. - hasher key_hash_function; - - /// The function that compares the keys for equality. - key_equal key_equal_function; - - /// For library debugging purposes only. - etl::debug_count construct_count; - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first unordered_set. - ///\param rhs Reference to the second unordered_set. - ///\return true if the arrays are equal, otherwise false - ///\ingroup unordered_set - //*************************************************************************** - template - bool operator ==(const etl::iunordered_set& lhs, const etl::iunordered_set& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first unordered_set. - ///\param rhs Reference to the second unordered_set. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup unordered_set - //*************************************************************************** - template - bool operator !=(const etl::iunordered_set& lhs, const etl::iunordered_set& rhs) - { - return !(lhs == rhs); - } -} - -#undef ETL_FILE -#endif diff --git a/src/ivector.h b/src/ivector.h deleted file mode 100644 index 056ebd7c..00000000 --- a/src/ivector.h +++ /dev/null @@ -1,953 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IVECTOR__ -#define __ETL_IVECTOR__ -#define __ETL_IN_IVECTOR_H__ - -#include -#include -#include -#include - -#include "platform.h" -#include "algorithm.h" -#include "private/vector_base.h" -#include "type_traits.h" -#include "parameter_type.h" -#include "error_handler.h" -#include "memory.h" - -#ifdef ETL_COMPILER_GCC -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif - -namespace etl -{ - //*************************************************************************** - /// The base class for specifically sized vectors. - /// Can be used as a reference type for all vectors containing a specific type. - ///\ingroup vector - //*************************************************************************** - template - class ivector : public vector_base - { - public: - - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; - typedef T* iterator; - typedef const T* const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef size_t size_type; - typedef typename std::iterator_traits::difference_type difference_type; - - protected: - - typedef typename parameter_type::type parameter_t; - - public: - - //********************************************************************* - /// Returns an iterator to the beginning of the vector. - ///\return An iterator to the beginning of the vector. - //********************************************************************* - iterator begin() - { - return p_buffer; - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator begin() const - { - return p_buffer; - } - - //********************************************************************* - /// Returns an iterator to the end of the vector. - ///\return An iterator to the end of the vector. - //********************************************************************* - iterator end() - { - return p_end; - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator end() const - { - return p_end; - } - - //********************************************************************* - /// Returns a const_iterator to the beginning of the vector. - ///\return A const iterator to the beginning of the vector. - //********************************************************************* - const_iterator cbegin() const - { - return p_buffer; - } - - //********************************************************************* - /// Returns a const_iterator to the end of the vector. - ///\return A const iterator to the end of the vector. - //********************************************************************* - const_iterator cend() const - { - return p_end; - } - - //********************************************************************* - /// Returns an reverse iterator to the reverse beginning of the vector. - ///\return Iterator to the reverse beginning of the vector. - //********************************************************************* - reverse_iterator rbegin() - { - return reverse_iterator(end()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(end()); - } - - //********************************************************************* - /// Returns a reverse iterator to the end + 1 of the vector. - ///\return Reverse iterator to the end + 1 of the vector. - //********************************************************************* - reverse_iterator rend() - { - return reverse_iterator(begin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator rend() const - { - return const_reverse_iterator(begin()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the reverse beginning of the vector. - ///\return Const reverse iterator to the reverse beginning of the vector. - //********************************************************************* - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(cend()); - } - - //********************************************************************* - /// Returns a const reverse iterator to the end + 1 of the vector. - ///\return Const reverse iterator to the end + 1 of the vector. - //********************************************************************* - const_reverse_iterator crend() const - { - return const_reverse_iterator(cbegin()); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - //********************************************************************* - void resize(size_t new_size) - { - resize(new_size, T()); - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default constructed value. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - resize(size_t new_size, T value) - { - ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full)); - - const size_t current_size = size(); - size_t delta = (current_size < new_size) ? new_size - current_size : current_size - new_size; - - if (current_size < new_size) - { - std::fill_n(p_end, delta, value); -#if defined(ETL_DEBUG) - construct_count += delta; -#endif - } - else - { - p_end -= delta; -#if defined(ETL_DEBUG) - construct_count -= delta; -#endif - } - - p_end = p_buffer + new_size; - } - - //********************************************************************* - /// Resizes the vector. - /// If asserts or exceptions are enabled and the new size is larger than the - /// maximum then a vector_full is thrown. - ///\param new_size The new size. - ///\param value The value to fill new elements with. Default = default constructed value. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - resize(size_t new_size, T value) - { - ETL_ASSERT(new_size <= MAX_SIZE, ETL_ERROR(vector_full)); - - const size_t current_size = size(); - size_t delta = (current_size < new_size) ? new_size - current_size : current_size - new_size; - - if (current_size < new_size) - { - etl::uninitialized_fill_n(p_end, delta, value); -#if defined(ETL_DEBUG) - construct_count += delta; -#endif - } - else - { - etl::destroy_n(p_end - delta, delta); -#if defined(ETL_DEBUG) - construct_count -= delta; -#endif - } - - p_end = p_buffer + new_size; - } - - //********************************************************************* - /// Does nothing. - //********************************************************************* - void reserve(size_t) - { - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference operator [](size_t i) - { - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference operator [](size_t i) const - { - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range. - ///\param i The index. - ///\return A reference to the value at index 'i' - //********************************************************************* - reference at(size_t i) - { - ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds)); - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a const reference to the value at index 'i' - /// If asserts or exceptions are enabled, emits an etl::vector_out_of_bounds if the index is out of range. - ///\param i The index. - ///\return A const reference to the value at index 'i' - //********************************************************************* - const_reference at(size_t i) const - { - ETL_ASSERT(i < size(), ETL_ERROR(vector_out_of_bounds)); - return p_buffer[i]; - } - - //********************************************************************* - /// Returns a reference to the first element. - ///\return A reference to the first element. - //********************************************************************* - reference front() - { - return *p_buffer; - } - - //********************************************************************* - /// Returns a const reference to the first element. - ///\return A const reference to the first element. - //********************************************************************* - const_reference front() const - { - return *p_buffer; - } - - //********************************************************************* - /// Returns a reference to the last element. - ///\return A reference to the last element. - //********************************************************************* - reference back() - { - return *(p_end - 1); - } - - //********************************************************************* - /// Returns a const reference to the last element. - ///\return A const reference to the last element. - //********************************************************************* - const_reference back() const - { - return *(p_end - 1); - } - - //********************************************************************* - /// Returns a pointer to the beginning of the vector data. - ///\return A pointer to the beginning of the vector data. - //********************************************************************* - pointer data() - { - return p_buffer; - } - - //********************************************************************* - /// Returns a const pointer to the beginning of the vector data. - ///\return A const pointer to the beginning of the vector data. - //********************************************************************* - const_pointer data() const - { - return p_buffer; - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - /// If asserts or exceptions are enabled, emits vector_iterator if the iterators are reversed. - ///\param first The iterator to the first element. - ///\param last The iterator to the last element + 1. - //********************************************************************* - template - void assign(TIterator first, TIterator last) - { -#if defined(ETL_DEBUG) - difference_type count = std::distance(first, last); - ETL_ASSERT(static_cast(count) <= MAX_SIZE, ETL_ERROR(vector_full)); -#endif - - initialise(); - -#if defined(ETL_DEBUG) - p_end = etl::uninitialized_copy(first, last, p_buffer, construct_count); -#else - p_end = etl::uninitialized_copy(first, last, p_buffer); -#endif - } - - //********************************************************************* - /// Assigns values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - ///\param n The number of elements to add. - ///\param value The value to insert for each element. - //********************************************************************* - void assign(size_t n, parameter_t value) - { - ETL_ASSERT(n <= MAX_SIZE, ETL_ERROR(vector_full)); - - initialise(); - -#if defined(ETL_DEBUG) - p_end = etl::uninitialized_fill_n(p_buffer, n, value, construct_count); -#else - p_end = etl::uninitialized_fill_n(p_buffer, n, value); -#endif - } - - //************************************************************************* - /// Clears the vector. - //************************************************************************* - void clear() - { - initialise(); - } - - //************************************************************************* - /// Increases the size of the vector by one, but does not initialise the new element. - /// If asserts or exceptions are enabled, throws a vector_full if the vector is already full. - //************************************************************************* - void push_back() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full)); -#endif - - create_back(); - } - - //********************************************************************* - /// Inserts a value at the end of the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. - ///\param value The value to add. - //********************************************************************* - void push_back(parameter_t value) - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(size() != MAX_SIZE, ETL_ERROR(vector_full)); -#endif - create_back(value); - } - - //************************************************************************* - /// Removes an element from the end of the vector. - /// Does nothing if the vector is empty. - //************************************************************************* - void pop_back() - { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(size() > 0, ETL_ERROR(vector_empty)); -#endif - destroy_back(); - } - - //********************************************************************* - /// Inserts a value to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector is already full. - ///\param position The position to insert before. - ///\param value The value to insert. - //********************************************************************* - iterator insert(iterator position, parameter_t value) - { - ETL_ASSERT(size() + 1 <= MAX_SIZE, ETL_ERROR(vector_full)); - - if (position == end()) - { - create_back(value); - } - else - { - create_back(back()); - std::copy_backward(position, p_end - 1, p_end); - *position = value; - } - - return position; - } - - //********************************************************************* - /// Inserts 'n' values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - ///\param position The position to insert before. - ///\param n The number of elements to add. - ///\param value The value to insert. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - insert(iterator position, size_t n, parameter_t value) - { - ETL_ASSERT((size() + n) <= MAX_SIZE, ETL_ERROR(vector_full)); - - std::copy_backward(position, p_end, p_end + n); - std::fill_n(position, n, value); - - construct_count += n; - p_end += n; - } - - //********************************************************************* - /// Inserts 'n' values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - ///\param position The position to insert before. - ///\param n The number of elements to add. - ///\param value The value to insert. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - insert(iterator position, size_t n, parameter_t value) - { - ETL_ASSERT((size() + n) <= MAX_SIZE, ETL_ERROR(vector_full)); - - size_t insert_n = n; - size_t insert_begin = std::distance(begin(), position); - size_t insert_end = insert_begin + insert_n; - - // Copy old data. - size_t copy_old_n; - size_t construct_old_n; - iterator p_construct_old; - - if (insert_end > size()) - { - copy_old_n = 0; - construct_old_n = size() - insert_begin; - p_construct_old = p_buffer + insert_end; - } - else - { - copy_old_n = size() - insert_begin - insert_n; - construct_old_n = insert_n; - p_construct_old = p_end; - } - - size_t copy_new_n = construct_old_n; - size_t construct_new_n = insert_n - copy_new_n; - -#if defined(ETL_DEBUG) - // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old, construct_count); - - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); - - // Construct new. - etl::uninitialized_fill_n(p_end, construct_new_n, value, construct_count); - - // Copy new. - std::fill_n(p_buffer + insert_begin, copy_new_n, value); -#else - // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); - - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); - - // Construct new. - etl::uninitialized_fill_n(p_end, construct_new_n, value); - - // Copy new. - std::fill_n(p_buffer + insert_begin, copy_new_n, value); -#endif - - p_end += n; - } - - //********************************************************************* - /// Inserts a range of values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - /// For fundamental and pointer types. - ///\param position The position to insert before. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - insert(iterator position, TIterator first, TIterator last) - { - size_t count = std::distance(first, last); - - ETL_ASSERT((size() + count) <= MAX_SIZE, ETL_ERROR(vector_full)); - - construct_count += count; - - if (position == end()) - { - p_end = std::copy(first, last, p_end); - } - else - { - std::copy_backward(position, p_end, p_end + count); - std::copy(first, last, position); - p_end += count; - } - } - - //********************************************************************* - /// Inserts a range of values to the vector. - /// If asserts or exceptions are enabled, emits vector_full if the vector does not have enough free space. - /// For fundamental and pointer types. - ///\param position The position to insert before. - ///\param first The first element to add. - ///\param last The last + 1 element to add. - //********************************************************************* - template - typename etl::enable_if::value, void>::type - insert(iterator position, TIterator first, TIterator last) - { - size_t count = std::distance(first, last); - - ETL_ASSERT((size() + count) <= MAX_SIZE, ETL_ERROR(vector_full)); - - size_t insert_n = count; - size_t insert_begin = std::distance(begin(), position); - size_t insert_end = insert_begin + insert_n; - - // Copy old data. - size_t copy_old_n; - size_t construct_old_n; - iterator p_construct_old; - - if (insert_end > size()) - { - copy_old_n = 0; - construct_old_n = size() - insert_begin; - p_construct_old = p_buffer + insert_end; - } - else - { - copy_old_n = size() - insert_begin - insert_n; - construct_old_n = insert_n; - p_construct_old = p_end; - } - - size_t copy_new_n = construct_old_n; - size_t construct_new_n = insert_n - copy_new_n; - -#if defined(ETL_DEBUG) - // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old, construct_count); - - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); - - // Construct new. - etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end, construct_count); - - // Copy new. - etl::copy_n(first, copy_new_n, p_buffer + insert_begin); -#else - // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); - - // Copy old. - etl::copy_n(p_buffer + insert_begin, copy_old_n, p_buffer + insert_end); - - // Construct new. - etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end); - - // Copy new. - etl::copy_n(first, copy_new_n, p_buffer + insert_begin); -#endif - - p_end += count; - } - - //********************************************************************* - /// Erases an element. - ///\param i_element Iterator to the element. - ///\return An iterator pointing to the element that followed the erased element. - //********************************************************************* - iterator erase(iterator i_element) - { - std::copy(i_element + 1, end(), i_element); - destroy_back(); - - return i_element; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased element. - //********************************************************************* - template - typename etl::enable_if::value, iterator>::type - erase(iterator first, iterator last) - { - if (first == begin() && last == end()) - { - clear(); - } - else - { - std::copy(last, end(), first); - size_t n_delete = std::distance(first, last); - construct_count -= n_delete; - p_end -= n_delete; - } - - return first; - } - - //********************************************************************* - /// Erases a range of elements. - /// The range includes all the elements between first and last, including the - /// element pointed by first, but not the one pointed by last. - ///\param first Iterator to the first element. - ///\param last Iterator to the last element. - ///\return An iterator pointing to the element that followed the erased element. - //********************************************************************* - template - typename etl::enable_if::value, iterator>::type - erase(iterator first, iterator last) - { - if (first == begin() && last == end()) - { - clear(); - } - else - { - std::copy(last, end(), first); - size_t n_delete = std::distance(first, last); - - // Destroy the elements left over at the end. -#if defined(ETL_DEBUG) - etl::destroy(p_end - n_delete, p_end, construct_count); -#else - etl::destroy(p_end - n_delete, p_end); -#endif - p_end -= n_delete; - } - - return first; - } - - //************************************************************************* - /// Assignment operator. - //************************************************************************* - ivector& operator = (const ivector& rhs) - { - if (&rhs != this) - { - assign(rhs.cbegin(), rhs.cend()); - } - - return *this; - } - - //************************************************************************* - /// Gets the current size of the vector. - ///\return The current size of the vector. - //************************************************************************* - size_type size() const - { - return size_t(p_end - p_buffer); - } - - //************************************************************************* - /// Checks the 'empty' state of the vector. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return (p_end == p_buffer); - } - - //************************************************************************* - /// Checks the 'full' state of the vector. - ///\return true if full. - //************************************************************************* - bool full() const - { - return size() == MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - protected: - - //********************************************************************* - /// Constructor. - //********************************************************************* - ivector(T* p_buffer_, size_t MAX_SIZE) - : vector_base(MAX_SIZE), - p_buffer(p_buffer_), - p_end(p_buffer_) - { - } - - //********************************************************************* - /// Initialise the vector. - //********************************************************************* - void initialise() - { -#if defined(ETL_DEBUG) - etl::destroy(p_buffer, p_end, construct_count); -#else - etl::destroy(p_buffer, p_end); -#endif - - p_end = p_buffer; - } - - private: - - pointer p_buffer; ///< Pointer to the start of the buffer. - pointer p_end; ///< Pointer to one past the last element in the buffer. - - //********************************************************************* - /// Create a new element with a default value at the back. - //********************************************************************* - inline void create_back() - { -#if defined(ETL_DEBUG) - etl::create_value_at(p_end, construct_count); -#else - etl::create_value_at(p_end); -#endif - ++p_end; - } - - //********************************************************************* - /// Create a new element with a value at the back - //********************************************************************* - inline void create_back(parameter_t value) - { -#if defined(ETL_DEBUG) - etl::create_copy_at(p_end, value, construct_count); -#else - etl::create_copy_at(p_end, value); -#endif - ++p_end; - } - - //********************************************************************* - /// Destroy an element at the back. - //********************************************************************* - inline void destroy_back() - { - --p_end; - -#if defined(ETL_DEBUG) - etl::destroy_at(p_end, construct_count); -#else - etl::destroy_at(p_end); -#endif - } - - // Disable copy construction. - ivector(const ivector&); - }; - - //*************************************************************************** - /// Equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the arrays are equal, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator ==(const etl::ivector& lhs, const etl::ivector& rhs) - { - return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - //*************************************************************************** - /// Not equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the arrays are not equal, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator !=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return !(lhs == rhs); - } - - //*************************************************************************** - /// Less than operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically less than the second, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator <(const etl::ivector& lhs, const etl::ivector& rhs) - { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); - } - - //*************************************************************************** - /// Greater than operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically greater than the second, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator >(const etl::ivector& lhs, const etl::ivector& rhs) - { - return (rhs < lhs); - } - - //*************************************************************************** - /// Less than or equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically less than or equal to the second, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator <=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return !(lhs > rhs); - } - - //*************************************************************************** - /// Greater than or equal operator. - ///\param lhs Reference to the first vector. - ///\param rhs Reference to the second vector. - ///\return true if the first vector is lexicographically greater than or equal to the second, otherwise false - ///\ingroup vector - //*************************************************************************** - template - bool operator >=(const etl::ivector& lhs, const etl::ivector& rhs) - { - return !(lhs < rhs); - } -} - -#include "private/ivectorpointer.h" - -#undef __ETL_IN_IVECTOR_H__ -#endif diff --git a/src/private/deque_base.h b/src/private/deque_base.h deleted file mode 100644 index cd6fe64e..00000000 --- a/src/private/deque_base.h +++ /dev/null @@ -1,181 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IN_IDEQUE_H__ -#error This header is a private element of etl::deque & etl::ideque -#endif - -#ifndef __ETL_DEQUE_BASE__ -#define __ETL_DEQUE_BASE__ - -#include - -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "1" - -namespace etl -{ - //*************************************************************************** - /// Exception base for deques - ///\ingroup deque - //*************************************************************************** - class deque_exception : public exception - { - public: - - deque_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Deque full exception. - ///\ingroup deque - //*************************************************************************** - class deque_full : public deque_exception - { - public: - - deque_full(string_type file_name, numeric_type line_number) - : deque_exception(ETL_ERROR_TEXT("deque:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Deque empty exception. - ///\ingroup deque - //*************************************************************************** - class deque_empty : public deque_exception - { - public: - - deque_empty(string_type file_name, numeric_type line_number) - : deque_exception(ETL_ERROR_TEXT("deque:empty", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Deque out of bounds exception. - ///\ingroup deque - //*************************************************************************** - class deque_out_of_bounds : public deque_exception - { - public: - - deque_out_of_bounds(string_type file_name, numeric_type line_number) - : deque_exception(ETL_ERROR_TEXT("deque:bounds", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for all templated deque types. - ///\ingroup deque - //*************************************************************************** - class deque_base - { - public: - - typedef size_t size_type; - - //************************************************************************* - /// Gets the current size of the deque. - ///\return The current size of the deque. - //************************************************************************* - size_type size() const - { - return current_size; - } - - //************************************************************************* - /// Checks the 'empty' state of the deque. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return (current_size == 0); - } - - //************************************************************************* - /// Checks the 'full' state of the deque. - ///\return true if full. - //************************************************************************* - bool full() const - { - return current_size == MAX_SIZE; - } - - //************************************************************************* - /// Returns the maximum possible size of the deque. - ///\return The maximum size of the deque. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - deque_base(size_t max_size, size_t buffer_size) - : current_size(0), - MAX_SIZE(max_size), - BUFFER_SIZE(buffer_size) - { - } - - size_type current_size; ///< The current number of elements in the deque. - const size_type MAX_SIZE; ///< The maximum number of elements in the deque. - const size_type BUFFER_SIZE; ///< The number of elements in the buffer. - etl::debug_count construct_count; ///< Internal debugging. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/flat_map_base.h b/src/private/flat_map_base.h deleted file mode 100644 index 420ad2a9..00000000 --- a/src/private/flat_map_base.h +++ /dev/null @@ -1,110 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IN_IFLAT_MAP_H__ -#error This header is a private element of etl::flat_map & etl::iflat_map -#endif - -#ifndef __ETL_FLAT_MAP_BASE__ -#define __ETL_FLAT_MAP_BASE__ - -#include - -#include "../exception.h" -#include "../ivector.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "2" - -namespace etl -{ - //*************************************************************************** - ///\ingroup flat_map - /// Exception base for flat_maps - //*************************************************************************** - class flat_map_exception : public exception - { - public: - - flat_map_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_map - /// Vector full exception. - //*************************************************************************** - class flat_map_full : public flat_map_exception - { - public: - - flat_map_full(string_type file_name, numeric_type line_number) - : flat_map_exception(ETL_ERROR_TEXT("flat_map: full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_map - /// Vector out of bounds exception. - //*************************************************************************** - class flat_map_out_of_bounds : public flat_map_exception - { - public: - - flat_map_out_of_bounds(string_type file_name, numeric_type line_number) - : flat_map_exception(ETL_ERROR_TEXT("flat_map:bounds", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_map - /// The base class for all templated flat_map types. - //*************************************************************************** - class flat_map_base - { - public: - - typedef size_t size_type; - - protected: - - etl::debug_count construct_count; ///< Internal debugging. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/flat_multimap_base.h b/src/private/flat_multimap_base.h deleted file mode 100644 index 3b65031c..00000000 --- a/src/private/flat_multimap_base.h +++ /dev/null @@ -1,94 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IN_IFLAT_MULTIMAP_H__ -#error This header is a private element of etl::flat_multimap & etl::iflat_multimap -#endif - -#ifndef __ETL_FLAT_MULTIMAP_BASE__ -#define __ETL_FLAT_MULTIMAP_BASE__ - -#include - -#include "../exception.h" -#include "../ivector.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "3" - -namespace etl -{ - //*************************************************************************** - ///\ingroup flat_multimap - /// Exception base for flat_multimaps - //*************************************************************************** - class flat_multimap_exception : public exception - { - public: - - flat_multimap_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_multimap - /// Vector full exception. - //*************************************************************************** - class flat_multimap_full : public flat_multimap_exception - { - public: - - flat_multimap_full(string_type file_name, numeric_type line_number) - : flat_multimap_exception(ETL_ERROR_TEXT("flat_multimap:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_multimap - /// The base class for all templated flat_multimap types. - //*************************************************************************** - class flat_multimap_base - { - public: - - typedef size_t size_type; - - protected: - - etl::debug_count construct_count; - }; -} - -#endif diff --git a/src/private/flat_multiset_base.h b/src/private/flat_multiset_base.h deleted file mode 100644 index b2408b15..00000000 --- a/src/private/flat_multiset_base.h +++ /dev/null @@ -1,105 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IN_IFLAT_MULTISET_H__ -#error This header is a private element of etl::flat_multiset & etl::iflat_multiset -#endif - -#ifndef __ETL_FLAT_MULTISET_BASE__ -#define __ETL_FLAT_MULTISET_BASE__ - -#include - -#include "../exception.h" -#include "../ivector.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "4" - -namespace etl -{ - //*************************************************************************** - ///\ingroup flat_multiset - /// Exception base for flat_multisets - //*************************************************************************** - class flat_multiset_exception : public exception - { - public: - - flat_multiset_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_multiset - /// Flat multiset full exception. - //*************************************************************************** - class flat_multiset_full : public flat_multiset_exception - { - public: - - flat_multiset_full(string_type file_name, numeric_type line_number) - : flat_multiset_exception(ETL_ERROR_TEXT("flat_multiset:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_multiset - /// The base class for all templated flat_multiset types. - //*************************************************************************** - class flat_multiset_base - { - public: - - typedef size_t size_type; - - protected: - - protected: - - etl::debug_count construct_count; - - //************************************************************************* - /// Constructor. - //************************************************************************* - flat_multiset_base() - { - } - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/flat_set_base.h b/src/private/flat_set_base.h deleted file mode 100644 index 33deaf5a..00000000 --- a/src/private/flat_set_base.h +++ /dev/null @@ -1,109 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IN_IFLAT_SET_H__ -#error This header is a private element of etl::flat_set & etl::iflat_set -#endif - -#ifndef __ETL_FLAT_SET_BASE__ -#define __ETL_FLAT_SET_BASE__ - -#include - -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "5" - -namespace etl -{ - //*************************************************************************** - ///\ingroup flat_set - /// Exception base for flat_sets - //*************************************************************************** - class flat_set_exception : public exception - { - public: - - flat_set_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_set - /// Vector full exception. - //*************************************************************************** - class flat_set_full : public flat_set_exception - { - public: - - flat_set_full(string_type file_name, numeric_type line_number) - : flat_set_exception(ETL_ERROR_TEXT("flat_set:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_set - /// Vector iterator exception. - //*************************************************************************** - class flat_set_iterator : public flat_set_exception - { - public: - - flat_set_iterator(string_type file_name, numeric_type line_number) - : flat_set_exception(ETL_ERROR_TEXT("flat_set:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup flat_set - /// The base class for all templated flat_set types. - //*************************************************************************** - class flat_set_base - { - public: - - typedef size_t size_type; - - protected: - - etl::debug_count construct_count; - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/forward_list_base.h b/src/private/forward_list_base.h deleted file mode 100644 index 9364a9b7..00000000 --- a/src/private/forward_list_base.h +++ /dev/null @@ -1,260 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IN_IFORWARD_LIST_H__ -#error This header is a private element of etl::forward_list & etl::iforward_list -#endif - -#ifndef __ETL_LIST_BASE__ -#define __ETL_LIST_BASE__ - -#include -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "6" - -namespace etl -{ - //*************************************************************************** - /// Exception for the forward_list. - ///\ingroup forward_list - //*************************************************************************** - class forward_list_exception : public exception - { - public: - - forward_list_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the forward_list. - ///\ingroup forward_list - //*************************************************************************** - class forward_list_full : public forward_list_exception - { - public: - - forward_list_full(string_type file_name, numeric_type line_number) - : forward_list_exception(ETL_ERROR_TEXT("forward_list:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Empty exception for the forward_list. - ///\ingroup forward_list - //*************************************************************************** - class forward_list_empty : public forward_list_exception - { - public: - - forward_list_empty(string_type file_name, numeric_type line_number) - : forward_list_exception(ETL_ERROR_TEXT("forward_list:empty", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the forward_list. - ///\ingroup forward_list - //*************************************************************************** - class forward_list_iterator : public forward_list_exception - { - public: - - forward_list_iterator(string_type file_name, numeric_type line_number) - : forward_list_exception(ETL_ERROR_TEXT("forward_list:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for all forward_lists. - ///\ingroup forward_list - //*************************************************************************** - class forward_list_base - { - protected: - - //************************************************************************* - /// The node element in the forward_list. - //************************************************************************* - struct node_t - { - node_t() - : next(nullptr) - { - } - - node_t* next; - }; - - public: - - typedef size_t size_type; ///< The type used for determining the size of forward_list. - - //************************************************************************* - /// Gets the size of the forward_list. - //************************************************************************* - size_type size() const - { - return p_node_pool->size(); - } - - //************************************************************************* - /// Gets the maximum possible size of the forward_list. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Checks to see if the forward_list is empty. - //************************************************************************* - bool empty() const - { - return p_node_pool->empty(); - } - - //************************************************************************* - /// Checks to see if the forward_list is full. - //************************************************************************* - bool full() const - { - return p_node_pool->full(); - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return p_node_pool->available(); - } - - //************************************************************************* - /// Reverses the forward_list. - //************************************************************************* - void reverse() - { - if (is_trivial_list()) - { - return; - } - - node_t* p_last = &start_node; - node_t* p_current = p_last->next; - node_t* 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: - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - forward_list_base(etl::ipool& node_pool, size_type max_size) - : p_node_pool(&node_pool), - MAX_SIZE(max_size) - { - } - - //************************************************************************* - /// 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; - } - - //************************************************************************* - /// Insert a node. - //************************************************************************* - inline void insert_node_after(node_t& position, node_t& node) - { - // Connect to the forward_list. - join(&node, position.next); - join(&position, &node); - } - - //************************************************************************* - /// Is the forward_list a trivial length? - //************************************************************************* - bool is_trivial_list() const - { - return (size() < 2); - } - - //************************************************************************* - /// Join two nodes. - //************************************************************************* - void join(node_t* left, node_t* right) - { - left->next = right; - } - - node_t start_node; ///< The node that acts as the forward_list start. - etl::ipool* p_node_pool; ///< The pool of data nodes used in the list. - const size_type MAX_SIZE; ///< The maximum size of the forward_list. - etl::debug_count construct_count; ///< Internal debugging. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/list_base.h b/src/private/list_base.h deleted file mode 100644 index 2b3ca1e1..00000000 --- a/src/private/list_base.h +++ /dev/null @@ -1,305 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_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 "pool.h" -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "7" - -namespace etl -{ - //*************************************************************************** - /// Exception for the list. - ///\ingroup list - //*************************************************************************** - class list_exception : public exception - { - public: - - list_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the list. - ///\ingroup list - //*************************************************************************** - class list_full : public list_exception - { - public: - - list_full(string_type file_name, numeric_type line_number) - : list_exception(ETL_ERROR_TEXT("list:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Empty exception for the list. - ///\ingroup list - //*************************************************************************** - class list_empty : public list_exception - { - public: - - list_empty(string_type file_name, numeric_type line_number) - : list_exception(ETL_ERROR_TEXT("list:empty", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the list. - ///\ingroup list - //*************************************************************************** - class list_iterator : public list_exception - { - public: - - list_iterator(string_type file_name, numeric_type line_number) - : list_exception(ETL_ERROR_TEXT("list:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Unsorted exception for the list. - ///\ingroup list - //*************************************************************************** - class list_unsorted : public list_exception - { - public: - - list_unsorted(string_type file_name, numeric_type line_number) - : list_exception(ETL_ERROR_TEXT("list:unsorted", ETL_FILE"D"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// 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. - - //************************************************************************* - /// The node element in the list. - //************************************************************************* - struct node_t - { - //*********************************************************************** - /// Constructor - //*********************************************************************** - node_t() - : previous(nullptr), - next(nullptr) - { - } - - //*********************************************************************** - /// Reverses the previous & next pointers. - //*********************************************************************** - inline void reverse() - { - std::swap(previous, next); - } - - node_t* previous; - node_t* next; - }; - - //************************************************************************* - /// Reverses the list. - //************************************************************************* - void reverse() - { - if (is_trivial_list()) - { - return; - } - - node_t* p_node = terminal_node.next; - - while (p_node != &terminal_node) - { - node_t* p_temp = p_node->previous; - p_node->previous = p_node->next; - p_node->next = p_temp; - p_node = p_node->previous; - } - - // Terminal node. - node_t* p_temp = p_node->previous; - p_node->previous = p_node->next; - p_node->next = p_temp; - p_node = p_node->previous; - } - - //************************************************************************* - /// Gets the maximum possible size of the list. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Gets the size of the list. - //************************************************************************* - size_type size() const - { - return p_node_pool->size(); - } - - //************************************************************************* - /// Checks to see if the list is empty. - //************************************************************************* - bool empty() const - { - return p_node_pool->empty(); - } - - //************************************************************************* - /// Checks to see if the list is full. - //************************************************************************* - bool full() const - { - return p_node_pool->size() == MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - //************************************************************************* - /// Is the list a trivial length? - //************************************************************************* - bool is_trivial_list() const - { - return (size() < 2); - } - - - protected: - - //************************************************************************* - /// Get the head node. - //************************************************************************* - node_t& get_head() - { - return *terminal_node.next; - } - - //************************************************************************* - /// Get the head node. - //************************************************************************* - const node_t& get_head() const - { - return *terminal_node.next; - } - - //************************************************************************* - /// Get the tail node. - //************************************************************************* - node_t& get_tail() - { - return *terminal_node.previous; - } - - //************************************************************************* - /// Get the tail node. - //************************************************************************* - const node_t& get_tail() const - { - return *terminal_node.previous; - } - - //************************************************************************* - /// Insert a node before 'position'. - //************************************************************************* - void insert_node(node_t& position, node_t& node) - { - // Connect to the list. - join(*position.previous, node); - join(node, position); - } - - //************************************************************************* - /// Join two nodes. - //************************************************************************* - void join(node_t& left, node_t& right) - { - left.next = &right; - right.previous = &left; - } - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - list_base(etl::ipool& node_pool, - size_type max_size) - : p_node_pool(&node_pool), - MAX_SIZE(max_size) - - { - } - - etl::ipool* p_node_pool; ///< The pool of data nodes used in the list. - node_t terminal_node; ///< The node that acts as the list start and end. - const size_type MAX_SIZE; ///< The maximum size of the list. - etl::debug_count construct_count; ///< Internal debugging. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/map_base.h b/src/private/map_base.h deleted file mode 100644 index d10df500..00000000 --- a/src/private/map_base.h +++ /dev/null @@ -1,434 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_IMAP_H__) -#error This header is a private element of etl::map & etl::imap -#endif - -#ifndef __ETL_MAP_BASE__ -#define __ETL_MAP_BASE__ - -#include -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "8" - -namespace etl -{ - //*************************************************************************** - /// Exception for the map. - ///\ingroup map - //*************************************************************************** - class map_exception : public exception - { - public: - - map_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the map. - ///\ingroup map - //*************************************************************************** - class map_full : public map_exception - { - public: - - map_full(string_type file_name, numeric_type line_number) - : map_exception("map:full", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Map out of bounds exception. - ///\ingroup map - //*************************************************************************** - class map_out_of_bounds : public map_exception - { - public: - - map_out_of_bounds(string_type file_name, numeric_type line_number) - : map_exception("map:bounds", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the map. - ///\ingroup map - //*************************************************************************** - class map_iterator : public map_exception - { - public: - - map_iterator(string_type file_name, numeric_type line_number) - : map_exception("map:iterator", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for all maps. - ///\ingroup map - //*************************************************************************** - class map_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: - - enum - { - kLeft = 0, - kRight = 1, - kNeither = 2 - }; - - //************************************************************************* - /// The node element in the map. - //************************************************************************* - struct Node - { - //*********************************************************************** - /// Constructor - //*********************************************************************** - Node() : - weight(uint_least8_t(kNeither)), - dir(uint_least8_t(kNeither)) - { - } - - ~Node() - { - - } - - //*********************************************************************** - /// Marks the node as a leaf. - //*********************************************************************** - void mark_as_leaf() - { - weight = uint_least8_t(kNeither); - dir = uint_least8_t(kNeither); - children[0] = nullptr; - children[1] = nullptr; - } - - Node* children[2]; - uint_least8_t weight; - uint_least8_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 (uint_least8_t(kNeither) != weight_node->dir) - { - // Does this insert balance the previous weight factor value? - if (weight_node->weight == 1 - weight_node->dir) - { - weight_node->weight = uint_least8_t(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 (uint_least8_t(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 = uint_least8_t(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, uint_least8_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 = uint_least8_t(kNeither); - // Newly detached right now becomes current position - position = new_root; - // Clear weight factor from new root - position->weight = uint_least8_t(kNeither); - } - - //************************************************************************* - /// Rotate three nodes at the position provided the to balance the tree - //************************************************************************* - void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_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 != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(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 != uint_least8_t(kNeither) && third == dir ? 1 - dir : uint_least8_t(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 = uint_least8_t(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. - etl::debug_count construct_count; - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/multimap_base.h b/src/private/multimap_base.h deleted file mode 100644 index 845d6241..00000000 --- a/src/private/multimap_base.h +++ /dev/null @@ -1,588 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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 -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "9" - -namespace etl -{ - //*************************************************************************** - /// Exception for the map. - ///\ingroup map - //*************************************************************************** - class multimap_exception : public exception - { - public: - - multimap_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the map. - ///\ingroup map - //*************************************************************************** - class multimap_full : public multimap_exception - { - public: - - multimap_full(string_type file_name, numeric_type line_number) - : multimap_exception("multimap:full", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Map out of bounds exception. - ///\ingroup map - //*************************************************************************** - class multimap_out_of_bounds : public multimap_exception - { - public: - - multimap_out_of_bounds(string_type file_name, numeric_type line_number) - : multimap_exception("multimap:bounds", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the map. - ///\ingroup map - //*************************************************************************** - class multimap_iterator : public multimap_exception - { - public: - - multimap_iterator(string_type file_name, numeric_type line_number) - : multimap_exception("multimap:iterator", file_name, line_number) - { - } - }; - - //*************************************************************************** - /// 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 uint_least8_t kLeft = 0; - static const uint_least8_t kRight = 1; - static const uint_least8_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]; - uint_least8_t weight; - uint_least8_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, uint_least8_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, uint_least8_t dir, uint_least8_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. - etl::debug_count construct_count; - }; -} - -#endif diff --git a/src/private/multiset_base.h b/src/private/multiset_base.h deleted file mode 100644 index d7573d65..00000000 --- a/src/private/multiset_base.h +++ /dev/null @@ -1,589 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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 -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "10" - -namespace etl -{ - //*************************************************************************** - /// Exception for the set. - ///\ingroup set - //*************************************************************************** - class multiset_exception : public exception - { - public: - - multiset_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the set. - ///\ingroup set - //*************************************************************************** - class multiset_full : public multiset_exception - { - public: - - multiset_full(string_type file_name, numeric_type line_number) - : multiset_exception(ETL_ERROR_TEXT("multiset:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Map out of bounds exception. - ///\ingroup set - //*************************************************************************** - class multiset_out_of_bounds : public multiset_exception - { - public: - - multiset_out_of_bounds(string_type file_name, numeric_type line_number) - : multiset_exception(ETL_ERROR_TEXT("multiset:bounds", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the set. - ///\ingroup set - //*************************************************************************** - class multiset_iterator : public multiset_exception - { - public: - - multiset_iterator(string_type file_name, numeric_type line_number) - : multiset_exception(ETL_ERROR_TEXT("multiset:iterator", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// 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 uint_least8_t kLeft = 0; - static const uint_least8_t kRight = 1; - static const uint_least8_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]; - uint_least8_t weight; - uint_least8_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, uint_least8_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, uint_least8_t dir, uint_least8_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. - etl::debug_count construct_count; - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/queue_base.h b/src/private/queue_base.h deleted file mode 100644 index 78627097..00000000 --- a/src/private/queue_base.h +++ /dev/null @@ -1,167 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_IN_IQUEUE_H__ -#error This header is a private element of etl::queue & etl::iqueue -#endif - -#ifndef __ETL_QUEUE_BASE__ -#define __ETL_QUEUE_BASE__ - -#include - -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#undef ETL_FILE -#define ETL_FILE "13" - -namespace etl -{ - //*************************************************************************** - /// The base class for queue exceptions. - ///\ingroup queue - //*************************************************************************** - class queue_exception : public exception - { - public: - - queue_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The exception thrown when the queue is full. - ///\ingroup queue - //*************************************************************************** - class queue_full : public queue_exception - { - public: - - queue_full(string_type file_name, numeric_type line_number) - : queue_exception(ETL_ERROR_TEXT("queue:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The exception thrown when the queue is empty. - ///\ingroup queue - //*************************************************************************** - class queue_empty : public queue_exception - { - public: - - queue_empty(string_type file_name, numeric_type line_number) - : queue_exception(ETL_ERROR_TEXT("queue:empty", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for all queues. - ///\ingroup queue - //*************************************************************************** - class queue_base - { - public: - - typedef size_t size_type; ///< The type used for determining the size of queue. - - //************************************************************************* - /// Returns the current number of items in the queue. - //************************************************************************* - size_type size() const - { - return current_size; - } - - //************************************************************************* - /// Returns the maximum number of items that can be queued. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Checks to see if the queue is empty. - /// \return true if the queue is empty, otherwise false - //************************************************************************* - bool empty() const - { - return current_size == 0; - } - - //************************************************************************* - /// Checks to see if the queue is full. - /// \return true if the queue is full, otherwise false - //************************************************************************* - bool full() const - { - return current_size == MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - protected: - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - queue_base(size_type max_size) - : in(0), - out(0), - current_size(0), - MAX_SIZE(max_size) - { - } - - size_type in; ///< Where to input new data. - size_type out; ///< Where to get the oldest data. - size_type current_size; ///< The number of items in the queue. - const size_type MAX_SIZE; ///< The maximum number of items in the queue. - etl::debug_count construct_count; ///< For internal debugging purposes. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/set_base.h b/src/private/set_base.h deleted file mode 100644 index 0fa929dd..00000000 --- a/src/private/set_base.h +++ /dev/null @@ -1,429 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -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_ISET_H__) -#error This header is a private element of etl::set & etl::iset -#endif - -#ifndef __ETL_SET_BASE__ -#define __ETL_SET_BASE__ - -#include -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#define ETL_FILE "14" - -namespace etl -{ - //*************************************************************************** - /// Exception for the set. - ///\ingroup set - //*************************************************************************** - class set_exception : public exception - { - public: - - set_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Full exception for the set. - ///\ingroup set - //*************************************************************************** - class set_full : public set_exception - { - public: - - set_full(string_type file_name, numeric_type line_number) - : set_exception(ETL_ERROR_TEXT("set:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Map out of bounds exception. - ///\ingroup set - //*************************************************************************** - class set_out_of_bounds : public set_exception - { - public: - - set_out_of_bounds(string_type file_name, numeric_type line_number) - : set_exception(ETL_ERROR_TEXT("set:bounds", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// Iterator exception for the set. - ///\ingroup set - //*************************************************************************** - class set_iterator : public set_exception - { - public: - - set_iterator(string_type file_name, numeric_type line_number) - : set_exception(ETL_ERROR_TEXT("set:iterator problem", ETL_FILE"C"), file_name, line_number) - { - } - }; - - //*************************************************************************** - /// The base class for all sets. - ///\ingroup set - //*************************************************************************** - class set_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: - - enum - { - kLeft = 0, - kRight = 1, - 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]; - uint_least8_t weight; - uint_least8_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 (uint_least8_t(kNeither) != weight_node->dir) - { - // Does this insert balance the previous weight factor value? - if (weight_node->weight == 1 - weight_node->dir) - { - weight_node->weight = uint_least8_t(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 (uint_least8_t(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 = uint_least8_t(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, uint_least8_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 = uint_least8_t(kNeither); - // Newly detached right now becomes current position - position = new_root; - // Clear weight factor from new root - position->weight = uint_least8_t(kNeither); - } - - //************************************************************************* - /// Rotate three nodes at the position provided the to balance the tree - //************************************************************************* - void rotate_3node(Node*& position, uint_least8_t dir, uint_least8_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 != uint_least8_t(kNeither) && third != dir ? dir : uint_least8_t(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 != uint_least8_t(kNeither) && third == dir ? 1 - dir : uint_least8_t(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 = uint_least8_t(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. - etl::debug_count construct_count; - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/stack_base.h b/src/private/stack_base.h deleted file mode 100644 index 60807a30..00000000 --- a/src/private/stack_base.h +++ /dev/null @@ -1,165 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -Permission is hereby granted, free of charge, to any person obtatoptopg a copy -of this software and associated documentation files(the "Software"), to deal -top the Software withtop restriction, topcludtopg withtop 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 followtopg conditions : - -The above copyright notice and this permission notice shall be included top 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_ISTACK_H__ -#error This header is a private element of etl::stack & etl::istack -#endif - -#ifndef __ETL_STACK_BASE__ -#define __ETL_STACK_BASE__ - -#include - -#include "../exception.h" -#include "../error_handler.h" -#include "../debug_count.h" - -#define ETL_FILE "15" - -namespace etl -{ - //*************************************************************************** - ///\ingroup stack - /// The base class for stack exceptions. - //*************************************************************************** - class stack_exception : public exception - { - public: - - stack_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup stack - /// The exception thrown when the stack is full. - //*************************************************************************** - class stack_full : public stack_exception - { - public: - - stack_full(string_type file_name, numeric_type line_number) - : stack_exception(ETL_ERROR_TEXT("stack:full", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup stack - /// The exception thrown when the stack is empty. - //*************************************************************************** - class stack_empty : public stack_exception - { - public: - - stack_empty(string_type file_name, numeric_type line_number) - : stack_exception(ETL_ERROR_TEXT("stack:empty", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup stack - /// A fixed capacity stack written in the STL style. - /// \warntopg This stack cannot be used for concurrent access from multiple threads. - //*************************************************************************** - class stack_base - { - public: - - typedef size_t size_type; ///< The type used for determining the size of stack. - - //************************************************************************* - /// Checks to see if the stack is empty. - /// \return true if the stack is empty, otherwise false - //************************************************************************* - bool empty() const - { - return current_size == 0; - } - - //************************************************************************* - /// Checks to see if the stack is full. - /// \return true if the stack is full, otherwise false - //************************************************************************* - bool full() const - { - return current_size == MAX_SIZE; - } - - //************************************************************************* - /// Returns the current number of items top the stack. - //************************************************************************* - size_type size() const - { - return current_size; - } - - //************************************************************************* - /// Returns the maximum number of items that can be stacked. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - protected: - - //************************************************************************* - /// The constructor that is called from derived classes. - //************************************************************************* - stack_base(size_type max_size) - : top_index(0), - current_size(0), - MAX_SIZE(max_size) - { - } - - size_type top_index; ///< The index of the top of the stack. - size_type current_size; ///< The number of items in the stack. - const size_type MAX_SIZE; ///< The maximum number of items in the stack. - etl::debug_count construct_count; ///< For internal debugging purposes. - }; -} - -#undef ETL_FILE - -#endif diff --git a/src/private/string_base.h b/src/private/string_base.h deleted file mode 100644 index 98f15131..00000000 --- a/src/private/string_base.h +++ /dev/null @@ -1,220 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -http://www.etlcpp.com - -Copyright(c) 2016 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -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_ISTRING_H__ -#error This header is a private element of etl::string & etl::istring -#endif - -#ifndef __ETL_STRING_BASE__ -#define __ETL_STRING_BASE__ - -#include - -#include "../platform.h" -#include "../integral_limits.h" -#include "../exception.h" -#include "../error_handler.h" - -#define ETL_FILE "27" - -#ifdef ETL_COMPILER_MICROSOFT -#undef max -#endif - -namespace etl -{ - //*************************************************************************** - ///\ingroup string - /// Exception base for strings - //*************************************************************************** - class string_exception : public exception - { - public: - - string_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup string - /// String empty exception. - //*************************************************************************** - class string_empty : public string_exception - { - public: - - string_empty(string_type file_name, numeric_type line_number) - : string_exception(ETL_ERROR_TEXT("string:empty", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup string - /// String out of bounds exception. - //*************************************************************************** - class string_out_of_bounds : public string_exception - { - public: - - string_out_of_bounds(string_type file_name, numeric_type line_number) - : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_FILE"B"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup string - /// String iterator exception. - //*************************************************************************** - class string_iterator : public string_exception - { - public: - - string_iterator(string_type file_name, numeric_type line_number) - : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"D"), file_name, line_number) - { - } - }; - - //*************************************************************************** - ///\ingroup string - /// The base class for all templated string types. - //*************************************************************************** - class string_base - { - public: - - typedef size_t size_type; - - enum - { - npos = etl::integral_limits::max - }; - - //************************************************************************* - /// Gets the current size of the string. - ///\return The current size of the string. - //************************************************************************* - size_type size() const - { - return current_size; - } - - //************************************************************************* - /// Gets the current size of the string. - ///\return The current size of the string. - //************************************************************************* - size_type length() const - { - return current_size; - } - - //************************************************************************* - /// Checks the 'empty' state of the string. - ///\return true if empty. - //************************************************************************* - bool empty() const - { - return (current_size == 0); - } - - //************************************************************************* - /// Checks the 'full' state of the string. - ///\return true if full. - //************************************************************************* - bool full() const - { - return current_size == MAX_SIZE; - } - - //************************************************************************* - /// Returns the capacity of the string. - ///\return The capacity of the string. - //************************************************************************* - size_type capacity() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the maximum possible size of the string. - ///\return The maximum size of the string. - //************************************************************************* - size_type max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the remaining capacity. - ///\return The remaining capacity. - //************************************************************************* - size_t available() const - { - return max_size() - size(); - } - - //************************************************************************* - /// Returns whether the string was truncated by the lat operation. - ///\return Whether the string was truncated by the lat operation. - //************************************************************************* - size_t truncated() const - { - return is_truncated; - } - - protected: - - //************************************************************************* - /// Constructor. - //************************************************************************* - string_base(size_t max_size) - : is_truncated(false), - current_size(0), - MAX_SIZE(max_size) - { - } - - bool is_truncated; ///< Set to true if the operation truncated the string. - size_type current_size; ///< The current number of elements in the string. - const size_type MAX_SIZE; ///< The maximum number of elements in the string. - }; -} - -#ifdef ETL_COMPILER_MICROSOFT -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#undef ETL_FILE - -#endif