diff --git a/flat_map.h b/flat_map.h new file mode 100644 index 00000000..8c60f75a --- /dev/null +++ b/flat_map.h @@ -0,0 +1,105 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_FLAT_MAP__ +#define __ETL_FLAT_MAP__ + +#include +#include +#include + +#include "iflat_map.h" +#include "vector.h" + +//***************************************************************************** +///\defgroup flat_map flat_map +/// A flat_map table with the capacity defined at compile time. +/// Has insertion of O(N) and flat_map of O(logN) +/// Duplicate entries and not allowed. +///\note Uses a predefined array, so MAX_SIZE_ elements will be always be constructed. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + template > + //*************************************************************************** + /// A flat_map implementation that uses a fixed size buffer. + ///\note Uses a predefined array, so MAX_SIZE_ elements will be always be constructed. + ///\tparam T The element type. + ///\tparam MAX_SIZE_ The maximum number of elements that can be stored. + ///\ingroup flat_map + //*************************************************************************** + class flat_map : public iflat_map + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + //************************************************************************* + /// Constructor. + //************************************************************************* + flat_map() + : iflat_map(buffer) + { + } + + //************************************************************************* + /// Constructor, from an iterator range. + ///\tparam TIterator The iterator type. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //************************************************************************* + template + flat_map(TIterator first, TIterator last) + : iflat_map(buffer) + { + iflat_map::insert(first, last); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + flat_map& operator = (const flat_map& rhs) + { + if (&rhs != this) + { + iflat_map::clear(); + iflat_map::insert(rhs.cbegin(), rhs.cend()); + } + + return *this; + } + + private: + + etl::vector::value_type, MAX_SIZE> buffer; /// + +#include "exception.h" +#include "ivector.h" + +#ifndef ETL_THROW_EXCEPTIONS +#include "error_handler.h" +#endif + +namespace etl +{ + //*************************************************************************** + ///\ingroup flat_map + /// Exception base for flat_maps + //*************************************************************************** + class flat_map_exception : public exception + { + public: + + flat_map_exception(const char* what) + : exception(what) + { + } + }; + + //*************************************************************************** + ///\ingroup flat_map + /// Vector full exception. + //*************************************************************************** + class flat_map_full : public flat_map_exception + { + public: + + flat_map_full() + : flat_map_exception("flat_map: full") + { + } + }; + + //*************************************************************************** + ///\ingroup flat_map + /// Vector out of bounds exception. + //*************************************************************************** + class flat_map_out_of_bounds : public flat_map_exception + { + public: + + flat_map_out_of_bounds() + : flat_map_exception("flat_map: out of bounds") + { + } + }; + + //*************************************************************************** + ///\ingroup flat_map + /// Vector iterator exception. + //*************************************************************************** + class flat_map_iterator : public flat_map_exception + { + public: + + flat_map_iterator() + : flat_map_exception("flat_map: iterator error") + { + } + }; + + //*************************************************************************** + ///\ingroup flat_map + /// The base class for all templated flat_map types. + //*************************************************************************** + class flat_map_base + { + public: + + typedef size_t size_type; + + //************************************************************************* + /// Gets the current size of the flat_map. + ///\return The current size of the flat_map. + //************************************************************************* + size_type size() const + { + return vbase.size(); + } + + //************************************************************************* + /// Checks the 'empty' state of the flat_map. + ///\return true if empty. + //************************************************************************* + bool empty() const + { + return vbase.empty(); + } + + //************************************************************************* + /// Checks the 'full' state of the flat_map. + ///\return true if full. + //************************************************************************* + bool full() const + { + return vbase.full(); + } + + //************************************************************************* + /// Returns the capacity of the flat_map. + ///\return The capacity of the flat_map. + //************************************************************************* + size_type capacity() const + { + return vbase.capacity(); + } + + //************************************************************************* + /// Returns the maximum possible size of the flat_map. + ///\return The maximum size of the flat_map. + //************************************************************************* + size_type max_size() const + { + return vbase.max_size(); + } + + //************************************************************************* + /// Returns the remaining capacity. + ///\return The remaining capacity. + //************************************************************************* + size_t available() const + { + return vbase.available(); + } + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + flat_map_base(vector_base& vbase) + : vbase(vbase) + { + } + + vector_base& vbase; + }; +} + +#endif diff --git a/iflat_map.h b/iflat_map.h new file mode 100644 index 00000000..b80df919 --- /dev/null +++ b/iflat_map.h @@ -0,0 +1,471 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_IFLAT_MAP__ +#define __ETL_IFLAT_MAP__ +#define __ETL_IN_IFLAT_MAP_H__ + +#include +#include +#include +#include +#include + +#include "flat_map_base.h" +#include "type_traits.h" +#include "parameter_type.h" +#include "ivector.h" + +#ifndef ETL_THROW_EXCEPTIONS +#include "error_handler.h" +#endif + +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 buffer_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 typename buffer_t::iterator iterator; + typedef typename buffer_t::const_iterator const_iterator; + typedef typename buffer_t::reverse_iterator reverse_iterator; + typedef typename buffer_t::const_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 key_value_parameter_t; + + //************************************************************************* + /// How to compare elements. + //************************************************************************* + struct compare_element + { + bool operator ()(const value_type& value1, const value_type& value2) const + { + return key_compare()(value1.first, value2.first); + } + }; + + public: + + //********************************************************************* + /// Assignment operator. + /// The source flat_map can be larger than the destination, but + /// only the elements that will fit in the destination will be copied. + ///\param other The other flat_map. + //********************************************************************* + iflat_map& operator = (iflat_map& other) + { + buffer.operator=(other.buffer); + + return *this; + } + + //********************************************************************* + /// Returns an iterator to the beginning of the flat_map. + ///\return An iterator to the beginning of the flat_map. + //********************************************************************* + iterator begin() + { + return buffer.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 buffer.begin(); + } + + //********************************************************************* + /// Returns an iterator to the end of the flat_map. + ///\return An iterator to the end of the flat_map. + //********************************************************************* + iterator end() + { + return buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 buffer.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 = std::lower_bound(begin(), end(), value_type(key, TMapped()), compare_element()); + + if (i_element->first != key) + { + // Doesn't exist, so create a new one. + i_element = insert(std::make_pair(key, mapped_type())); + } + + return i_element->second; + } + + //********************************************************************* + /// Returns a reference to the value at index 'key' + /// If ETL_THROW_EXCEPTIONS is defined, 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 = std::lower_bound(begin(), end(), value_type(key, TMapped()), compare_element()); + + if (i_element == end()) + { + // Doesn't exist. +#if ETL_THROW_EXCEPTIONS + throw flat_map_out_of_bounds(); +#else + error_handler::error(flat_map_out_of_bounds()); + +#endif + } + + return i_element->second; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'key' + /// If ETL_THROW_EXCEPTIONS is defined, 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 + { + typename buffer_t::const_iterator i_element = std::lower_bound(begin(), end(), value_type(key, TMapped()), compare_element()); + + if (i_element == end()) + { + // Doesn't exist. +#if ETL_THROW_EXCEPTIONS + throw flat_map_out_of_bounds(); +#else + error_handler::error(flat_map_out_of_bounds()); + +#endif + } + + return i_element->second; + } + + //********************************************************************* + /// Assigns values to the flat_map. + /// If ETL_THROW_EXCEPTIONS is defined, emits flat_map_full if the flat_map does not have enough free space. + /// If ETL_THROW_EXCEPTIONS is defined, emits flat_map_iterator if the iterators are reversed. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //********************************************************************* + template + void assign(TIterator first, TIterator last) + { + clear(); + + while (first != last) + { + insert(*first++); + } + } + + //********************************************************************* + /// Inserts a value to the flat_map. + /// If ETL_THROW_EXCEPTIONS is defined, 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(const value_type& value) + { + iterator i_element = std::lower_bound(begin(), end(), value, compare_element()); + + if (i_element == end()) + { + // At the end. + if (buffer.full()) + { +#ifdef ETL_THROW_EXCEPTIONS + throw flat_map_full(); +#else + error_handler::error(flat_map_full()); +#endif + } + else + { + buffer.push_back(value); + } + } + else + { + // Not at the end. + // Existing element? + if (value.first == i_element->first) + { + // Yes. + i_element->second = value.second; + } + else + { + // A new one. + if (buffer.full()) + { +#ifdef ETL_THROW_EXCEPTIONS + throw flat_map_full(); +#else + error_handler::error(flat_map_full()); +#endif + } + else + { + buffer.insert(i_element, value); + } + } + } + + return i_element; + } + + //********************************************************************* + /// Inserts a range of values to the flat_map. + /// If ETL_THROW_EXCEPTIONS is defined, emits flat_map_full if the flat_map does not have enough free space. + ///\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 i_element Iterator to the element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator i_element) + { + return buffer.erase(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) + { + return buffer.erase(first, last); + } + + //************************************************************************* + /// Clears the flat_map. + //************************************************************************* + void clear() + { + buffer.clear(); + } + + //********************************************************************* + /// 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) + { + return std::lower_bound(begin(), end(), value_type(key, TMapped()), compare_element()); + } + + //********************************************************************* + /// 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 + { + return std::lower_bound(begin(), end(), value_type(key, TMapped()), compare_element()); + } + + protected: + + //********************************************************************* + /// Constructor. + //********************************************************************* + iflat_map(buffer_t& buffer) + : flat_map_base(buffer), + buffer(buffer) + { + } + + private: + + buffer_t& buffer; + }; + + //*************************************************************************** + /// 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