mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-26 20:38:45 +08:00
#957 Support heterogenous lookup for maps
This commit is contained in:
parent
d0a9d696fe
commit
4a1712b733
@ -52,6 +52,8 @@ SOFTWARE.
|
||||
#include "placement_new.h"
|
||||
#include "initializer_list.h"
|
||||
|
||||
#include "private/comparator_is_transparent.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//*****************************************************************************
|
||||
@ -599,6 +601,18 @@ namespace etl
|
||||
return key_hash_function(key) % number_of_buckets;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************************************
|
||||
/// Returns the bucket index for the key.
|
||||
///\return The bucket index for the key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type get_bucket_index(const K& key) const
|
||||
{
|
||||
return key_hash_function(key) % number_of_buckets;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the size of the bucket key.
|
||||
///\return The bucket size of the bucket key.
|
||||
@ -610,6 +624,20 @@ namespace etl
|
||||
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************************************
|
||||
/// Returns the size of the bucket key.
|
||||
///\return The bucket size of the bucket key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type bucket_size(const K& key) const
|
||||
{
|
||||
size_t index = bucket(key);
|
||||
|
||||
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the maximum number of the buckets the container can hold.
|
||||
///\return The maximum number of the buckets the container can hold.
|
||||
@ -716,6 +744,52 @@ namespace etl
|
||||
return pbucket->begin()->key_value_pair.second;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns a reference to the value at index 'key'
|
||||
///\param key The key.
|
||||
///\return A reference to the value at index 'key'
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
mapped_reference operator [](const K& key)
|
||||
{
|
||||
// Find the bucket.
|
||||
bucket_t* pbucket = pbuckets + get_bucket_index(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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Doesn't exist, so add a new one.
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type();
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
pbucket->insert_after(pbucket->before_begin(), *node);
|
||||
|
||||
adjust_first_last_markers_after_insert(pbucket);
|
||||
|
||||
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.
|
||||
@ -786,6 +860,82 @@ namespace etl
|
||||
return begin()->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'
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
mapped_reference at(const K& key)
|
||||
{
|
||||
// Find the bucket.
|
||||
bucket_t* pbucket = pbuckets + get_bucket_index(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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************************************
|
||||
/// 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'
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
const_mapped_reference at(const K& key) const
|
||||
{
|
||||
// Find the bucket.
|
||||
bucket_t* pbucket = pbuckets + get_bucket_index(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;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// 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.
|
||||
@ -1040,6 +1190,41 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
///\return The number of elements erased. 0 or 1.
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t erase(const K& key)
|
||||
{
|
||||
size_t n = 0UL;
|
||||
size_t index = get_bucket_index(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()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
|
||||
{
|
||||
++iprevious;
|
||||
++icurrent;
|
||||
}
|
||||
|
||||
// Did we find it?
|
||||
if (icurrent != bucket.end())
|
||||
{
|
||||
delete_data_node(iprevious, icurrent, bucket);
|
||||
n = 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param ielement Iterator to the element.
|
||||
@ -1141,6 +1326,19 @@ namespace etl
|
||||
return (find(key) == end()) ? 0 : 1;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Counts an element.
|
||||
///\param key The key to search for.
|
||||
///\return 1 if the key exists, otherwise 0.
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t count(const K& key) const
|
||||
{
|
||||
return (find(key) == end()) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
@ -1209,6 +1407,80 @@ namespace etl
|
||||
return end();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
///\return An iterator to the element if the key exists, otherwise end().
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
iterator find(const K& key)
|
||||
{
|
||||
size_t index = get_bucket_index(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();
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
///\return An iterator to the element if the key exists, otherwise end().
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
const_iterator find(const K& key) const
|
||||
{
|
||||
size_t index = get_bucket_index(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();
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// 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
|
||||
@ -1251,6 +1523,54 @@ namespace etl
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
|
||||
{
|
||||
iterator f = find(key);
|
||||
iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<iterator, iterator>(f, l);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
|
||||
{
|
||||
const_iterator f = find(key);
|
||||
const_iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the size of the unordered_map.
|
||||
//*************************************************************************
|
||||
|
||||
@ -52,6 +52,8 @@ SOFTWARE.
|
||||
#include "placement_new.h"
|
||||
#include "initializer_list.h"
|
||||
|
||||
#include "private/comparator_is_transparent.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//*****************************************************************************
|
||||
@ -597,6 +599,16 @@ namespace etl
|
||||
return key_hash_function(key) % number_of_buckets;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the bucket index for the key.
|
||||
///\return The bucket index for the key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type get_bucket_index(const K& 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.
|
||||
@ -608,6 +620,18 @@ namespace etl
|
||||
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the size of the bucket key.
|
||||
///\return The bucket size of the bucket key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type bucket_size(const K& key) const
|
||||
{
|
||||
size_t index = bucket(key);
|
||||
|
||||
return etl::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.
|
||||
@ -868,6 +892,41 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
///\return The number of elements erased.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t erase(const K& key)
|
||||
{
|
||||
size_t n = 0UL;
|
||||
size_t bucket_id = get_bucket_index(key);
|
||||
|
||||
bucket_t& bucket = pbuckets[bucket_id];
|
||||
|
||||
local_iterator iprevious = bucket.before_begin();
|
||||
local_iterator icurrent = bucket.begin();
|
||||
|
||||
while (icurrent != bucket.end())
|
||||
{
|
||||
if (key_equal_function(icurrent->key_value_pair.first, key))
|
||||
{
|
||||
delete_data_node(iprevious, icurrent, bucket);
|
||||
++n;
|
||||
icurrent = iprevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
++iprevious;
|
||||
}
|
||||
|
||||
++icurrent;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param ielement Iterator to the element.
|
||||
@ -985,6 +1044,33 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Counts an element.
|
||||
///\param key The key to search for.
|
||||
///\return 1 if the key exists, otherwise 0.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t count(const K& key) const
|
||||
{
|
||||
size_t n = 0UL;
|
||||
const_iterator f = find(key);
|
||||
const_iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
++n;
|
||||
|
||||
while ((l != end()) && key_equal_function(key, l->first))
|
||||
{
|
||||
++l;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
@ -1053,6 +1139,76 @@ namespace etl
|
||||
return end();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
///\return An iterator to the element if the key exists, otherwise end().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
iterator find(const K& key)
|
||||
{
|
||||
size_t index = get_bucket_index(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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
const_iterator find(const K& key) const
|
||||
{
|
||||
size_t index = get_bucket_index(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
|
||||
@ -1105,6 +1261,60 @@ namespace etl
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
|
||||
{
|
||||
iterator f = find(key);
|
||||
iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
|
||||
while ((l != end()) && key_equal_function(key, l->first))
|
||||
{
|
||||
++l;
|
||||
}
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<iterator, iterator>(f, l);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
|
||||
{
|
||||
const_iterator f = find(key);
|
||||
const_iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
|
||||
while ((l != end()) && key_equal_function(key, l->first))
|
||||
{
|
||||
++l;
|
||||
}
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the size of the unordered_multimap.
|
||||
//*************************************************************************
|
||||
|
||||
@ -51,6 +51,8 @@ SOFTWARE.
|
||||
#include "placement_new.h"
|
||||
#include "initializer_list.h"
|
||||
|
||||
#include "private/comparator_is_transparent.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//*****************************************************************************
|
||||
@ -588,6 +590,16 @@ namespace etl
|
||||
return key_hash_function(key) % number_of_buckets;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the bucket index for the key.
|
||||
///\return The bucket index for the key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type get_bucket_index(const K& 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.
|
||||
@ -599,6 +611,18 @@ namespace etl
|
||||
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the size of the bucket key.
|
||||
///\return The bucket size of the bucket key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type bucket_size(const K& key) const
|
||||
{
|
||||
size_t index = bucket(key);
|
||||
|
||||
return etl::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.
|
||||
@ -712,6 +736,77 @@ namespace etl
|
||||
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 value The value to insert.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<iterator, bool> insert(const K& key)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multiset_full));
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(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 = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(key);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
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 (key_equal_function(inode->key, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(key);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the unordered_multiset.
|
||||
@ -846,6 +941,41 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
///\return The number of elements erased. 0 or 1.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t erase(const K& key)
|
||||
{
|
||||
size_t n = 0UL;
|
||||
size_t bucket_id = get_bucket_index(key);
|
||||
|
||||
bucket_t& bucket = pbuckets[bucket_id];
|
||||
|
||||
local_iterator iprevious = bucket.before_begin();
|
||||
local_iterator icurrent = bucket.begin();
|
||||
|
||||
while (icurrent != bucket.end())
|
||||
{
|
||||
if (key_equal_function(icurrent->key, key))
|
||||
{
|
||||
delete_data_node(iprevious, icurrent, bucket);
|
||||
++n;
|
||||
icurrent = iprevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
++iprevious;
|
||||
}
|
||||
|
||||
++icurrent;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param ielement Iterator to the element.
|
||||
@ -963,6 +1093,33 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Counts an element.
|
||||
///\param key The key to search for.
|
||||
///\return 1 if the key exists, otherwise 0.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t count(const K& key) const
|
||||
{
|
||||
size_t n = 0UL;
|
||||
const_iterator f = find(key);
|
||||
const_iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
++n;
|
||||
|
||||
while ((l != end()) && key_equal_function(key, *l))
|
||||
{
|
||||
++l;
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
@ -1031,6 +1188,76 @@ namespace etl
|
||||
return end();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
///\return An iterator to the element if the key exists, otherwise end().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
iterator find(const K& key)
|
||||
{
|
||||
size_t index = get_bucket_index(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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
const_iterator find(const K& key) const
|
||||
{
|
||||
size_t index = get_bucket_index(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
|
||||
|
||||
@ -52,6 +52,8 @@ SOFTWARE.
|
||||
#include "placement_new.h"
|
||||
#include "initializer_list.h"
|
||||
|
||||
#include "private/comparator_is_transparent.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//*****************************************************************************
|
||||
@ -589,6 +591,16 @@ namespace etl
|
||||
return key_hash_function(key) % number_of_buckets;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the bucket index for the key.
|
||||
///\return The bucket index for the key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type get_bucket_index(const K& 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.
|
||||
@ -600,6 +612,18 @@ namespace etl
|
||||
return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns the size of the bucket key.
|
||||
///\return The bucket size of the bucket key.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_type bucket_size(const K& key) const
|
||||
{
|
||||
size_t index = bucket(key);
|
||||
|
||||
return etl::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.
|
||||
@ -730,6 +754,94 @@ namespace etl
|
||||
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 value The value to insert.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<iterator, bool> insert(const K& key)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
if (full())
|
||||
{
|
||||
iterator iter = find(key);
|
||||
if (iter == end())
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.first = iter;
|
||||
result.second = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(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 = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(key);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
|
||||
result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
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 (key_equal_function(inode->key, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Not already there?
|
||||
if (inode == bucket.end())
|
||||
{
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(key);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the unordered_set.
|
||||
@ -892,6 +1004,39 @@ namespace etl
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
///\return The number of elements erased. 0 or 1.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t erase(const K& key)
|
||||
{
|
||||
size_t n = 0UL;
|
||||
size_t index = get_bucket_index(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()) && (!key_equal_function(icurrent->key, key)))
|
||||
{
|
||||
++iprevious;
|
||||
++icurrent;
|
||||
}
|
||||
|
||||
// Did we find it?
|
||||
if (icurrent != bucket.end())
|
||||
{
|
||||
delete_data_node(iprevious, icurrent, bucket);
|
||||
n = 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param ielement Iterator to the element.
|
||||
@ -993,6 +1138,17 @@ namespace etl
|
||||
return (find(key) == end()) ? 0 : 1;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Counts an element.
|
||||
///\param key The key to search for.
|
||||
///\return 1 if the key exists, otherwise 0.
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
size_t count(const K& key) const
|
||||
{
|
||||
return (find(key) == end()) ? 0 : 1;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
@ -1061,6 +1217,76 @@ namespace etl
|
||||
return end();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Finds an element.
|
||||
///\param key The key to search for.
|
||||
///\return An iterator to the element if the key exists, otherwise end().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
iterator find(const K& key)
|
||||
{
|
||||
size_t index = get_bucket_index(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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
const_iterator find(const K& key) const
|
||||
{
|
||||
size_t index = get_bucket_index(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
|
||||
@ -1103,6 +1329,50 @@ namespace etl
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<iterator, iterator> equal_range(const K& key)
|
||||
{
|
||||
iterator f = find(key);
|
||||
iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<iterator, iterator>(f, l);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// 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().
|
||||
//*********************************************************************
|
||||
template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
|
||||
ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const K& key) const
|
||||
{
|
||||
const_iterator f = find(key);
|
||||
const_iterator l = f;
|
||||
|
||||
if (l != end())
|
||||
{
|
||||
++l;
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the size of the unordered_set.
|
||||
//*************************************************************************
|
||||
|
||||
@ -130,6 +130,25 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct transparent_hash
|
||||
{
|
||||
typedef int is_transparent;
|
||||
|
||||
size_t operator ()(const char* s) const
|
||||
{
|
||||
size_t sum = 0U;
|
||||
size_t length = etl::strlen(s);
|
||||
|
||||
return std::accumulate(s, s + length, sum);
|
||||
}
|
||||
|
||||
size_t operator ()(const std::string& text) const
|
||||
{
|
||||
return std::accumulate(text.begin(), text.end(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
typedef TestDataDC<std::string> DC;
|
||||
typedef TestDataNDC<std::string> NDC;
|
||||
|
||||
@ -204,17 +223,19 @@ namespace
|
||||
typedef etl::unordered_map<std::string, DC, SIZE, SIZE / 2, simple_hash> DataDC;
|
||||
typedef etl::unordered_map<std::string, NDC, SIZE, SIZE / 2, simple_hash> DataNDC;
|
||||
typedef etl::iunordered_map<std::string, NDC, simple_hash> IDataNDC;
|
||||
typedef etl::unordered_map<std::string, NDC, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataNDCTransparent;
|
||||
typedef etl::unordered_map<std::string, DC, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataDCTransparent;
|
||||
|
||||
NDC N0 = NDC("A");
|
||||
NDC N1 = NDC("B");
|
||||
NDC N2 = NDC("C");
|
||||
NDC N3 = NDC("D");
|
||||
NDC N4 = NDC("E");
|
||||
NDC N5 = NDC("F");
|
||||
NDC N6 = NDC("G");
|
||||
NDC N7 = NDC("H");
|
||||
NDC N8 = NDC("I");
|
||||
NDC N9 = NDC("J");
|
||||
NDC N0 = NDC("A");
|
||||
NDC N1 = NDC("B");
|
||||
NDC N2 = NDC("C");
|
||||
NDC N3 = NDC("D");
|
||||
NDC N4 = NDC("E");
|
||||
NDC N5 = NDC("F");
|
||||
NDC N6 = NDC("G");
|
||||
NDC N7 = NDC("H");
|
||||
NDC N8 = NDC("I");
|
||||
NDC N9 = NDC("J");
|
||||
NDC N10 = NDC("K");
|
||||
NDC N11 = NDC("L");
|
||||
NDC N12 = NDC("M");
|
||||
@ -226,16 +247,16 @@ namespace
|
||||
NDC N18 = NDC("S");
|
||||
NDC N19 = NDC("T");
|
||||
|
||||
DC M0 = DC("A");
|
||||
DC M1 = DC("B");
|
||||
DC M2 = DC("C");
|
||||
DC M3 = DC("D");
|
||||
DC M4 = DC("E");
|
||||
DC M5 = DC("F");
|
||||
DC M6 = DC("G");
|
||||
DC M7 = DC("H");
|
||||
DC M8 = DC("I");
|
||||
DC M9 = DC("J");
|
||||
DC M0 = DC("A");
|
||||
DC M1 = DC("B");
|
||||
DC M2 = DC("C");
|
||||
DC M3 = DC("D");
|
||||
DC M4 = DC("E");
|
||||
DC M5 = DC("F");
|
||||
DC M6 = DC("G");
|
||||
DC M7 = DC("H");
|
||||
DC M8 = DC("I");
|
||||
DC M9 = DC("J");
|
||||
DC M10 = DC("K");
|
||||
DC M11 = DC("L");
|
||||
DC M12 = DC("M");
|
||||
@ -247,26 +268,47 @@ namespace
|
||||
DC M18 = DC("S");
|
||||
DC M19 = DC("T");
|
||||
|
||||
const char* K0 = "FF"; // 0
|
||||
const char* K1 = "FG"; // 1
|
||||
const char* K2 = "FH"; // 2
|
||||
const char* K3 = "FI"; // 3
|
||||
const char* K4 = "FJ"; // 4
|
||||
const char* K5 = "FK"; // 5
|
||||
const char* K6 = "FL"; // 6
|
||||
const char* K7 = "FM"; // 7
|
||||
const char* K8 = "FN"; // 8
|
||||
const char* K9 = "FO"; // 9
|
||||
const char* K10 = "FP"; // 0
|
||||
const char* K11 = "FQ"; // 1
|
||||
const char* K12 = "FR"; // 2
|
||||
const char* K13 = "FS"; // 3
|
||||
const char* K14 = "FT"; // 4
|
||||
const char* K15 = "FU"; // 5
|
||||
const char* K16 = "FV"; // 6
|
||||
const char* K17 = "FW"; // 7
|
||||
const char* K18 = "FX"; // 8
|
||||
const char* K19 = "FY"; // 9
|
||||
const char* CK0 = "FF"; // 0
|
||||
const char* CK1 = "FG"; // 1
|
||||
const char* CK2 = "FH"; // 2
|
||||
const char* CK3 = "FI"; // 3
|
||||
const char* CK4 = "FJ"; // 4
|
||||
const char* CK5 = "FK"; // 5
|
||||
const char* CK6 = "FL"; // 6
|
||||
const char* CK7 = "FM"; // 7
|
||||
const char* CK8 = "FN"; // 8
|
||||
const char* CK9 = "FO"; // 9
|
||||
const char* CK10 = "FP"; // 0
|
||||
const char* CK11 = "FQ"; // 1
|
||||
const char* CK12 = "FR"; // 2
|
||||
const char* CK13 = "FS"; // 3
|
||||
const char* CK14 = "FT"; // 4
|
||||
const char* CK15 = "FU"; // 5
|
||||
const char* CK16 = "FV"; // 6
|
||||
const char* CK17 = "FW"; // 7
|
||||
const char* CK18 = "FX"; // 8
|
||||
const char* CK19 = "FY"; // 9
|
||||
|
||||
std::string K0 = CK0; // 0
|
||||
std::string K1 = CK1; // 1
|
||||
std::string K2 = CK2; // 2
|
||||
std::string K3 = CK3; // 3
|
||||
std::string K4 = CK4; // 4
|
||||
std::string K5 = CK5; // 5
|
||||
std::string K6 = CK6; // 6
|
||||
std::string K7 = CK7; // 7
|
||||
std::string K8 = CK8; // 8
|
||||
std::string K9 = CK9; // 9
|
||||
std::string K10 = CK10; // 0
|
||||
std::string K11 = CK11; // 1
|
||||
std::string K12 = CK12; // 2
|
||||
std::string K13 = CK13; // 3
|
||||
std::string K14 = CK14; // 4
|
||||
std::string K15 = CK15; // 5
|
||||
std::string K16 = CK16; // 6
|
||||
std::string K17 = CK17; // 7
|
||||
std::string K18 = CK18; // 8
|
||||
std::string K19 = CK19; // 9
|
||||
|
||||
std::string K[] = { K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19 };
|
||||
|
||||
@ -502,6 +544,23 @@ namespace
|
||||
CHECK_EQUAL(M9, data[K9]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_index_read_using_transparent_comparator_and_hasher)
|
||||
{
|
||||
DataDCTransparent data(initial_data_dc.begin(), initial_data_dc.end());
|
||||
|
||||
CHECK_EQUAL(M0, data[CK0]);
|
||||
CHECK_EQUAL(M1, data[CK1]);
|
||||
CHECK_EQUAL(M2, data[CK2]);
|
||||
CHECK_EQUAL(M3, data[CK3]);
|
||||
CHECK_EQUAL(M4, data[CK4]);
|
||||
CHECK_EQUAL(M5, data[CK5]);
|
||||
CHECK_EQUAL(M6, data[CK6]);
|
||||
CHECK_EQUAL(M7, data[CK7]);
|
||||
CHECK_EQUAL(M8, data[CK8]);
|
||||
CHECK_EQUAL(M9, data[CK9]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_index_write)
|
||||
{
|
||||
@ -530,6 +589,34 @@ namespace
|
||||
CHECK_EQUAL(M0, data[K9]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_index_write_using_transparent_comparator_and_hasher)
|
||||
{
|
||||
DataDCTransparent data(initial_data_dc.begin(), initial_data_dc.end());
|
||||
|
||||
data[CK0] = M9;
|
||||
data[CK1] = M8;
|
||||
data[CK2] = M7;
|
||||
data[CK3] = M6;
|
||||
data[CK4] = M5;
|
||||
data[CK5] = M4;
|
||||
data[CK6] = M3;
|
||||
data[CK7] = M2;
|
||||
data[CK8] = M1;
|
||||
data[CK9] = M0;
|
||||
|
||||
CHECK_EQUAL(M9, data[CK0]);
|
||||
CHECK_EQUAL(M8, data[CK1]);
|
||||
CHECK_EQUAL(M7, data[CK2]);
|
||||
CHECK_EQUAL(M6, data[CK3]);
|
||||
CHECK_EQUAL(M5, data[CK4]);
|
||||
CHECK_EQUAL(M4, data[CK5]);
|
||||
CHECK_EQUAL(M3, data[CK6]);
|
||||
CHECK_EQUAL(M2, data[CK7]);
|
||||
CHECK_EQUAL(M1, data[CK8]);
|
||||
CHECK_EQUAL(M0, data[CK9]);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_at)
|
||||
{
|
||||
@ -547,6 +634,23 @@ namespace
|
||||
CHECK_EQUAL(data.at(K9), N9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_at_using_transparent_comparator_and_hasher)
|
||||
{
|
||||
DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_EQUAL(data.at(CK0), N0);
|
||||
CHECK_EQUAL(data.at(CK1), N1);
|
||||
CHECK_EQUAL(data.at(CK2), N2);
|
||||
CHECK_EQUAL(data.at(CK3), N3);
|
||||
CHECK_EQUAL(data.at(CK4), N4);
|
||||
CHECK_EQUAL(data.at(CK5), N5);
|
||||
CHECK_EQUAL(data.at(CK6), N6);
|
||||
CHECK_EQUAL(data.at(CK7), N7);
|
||||
CHECK_EQUAL(data.at(CK8), N8);
|
||||
CHECK_EQUAL(data.at(CK9), N9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_at_const)
|
||||
{
|
||||
@ -564,6 +668,23 @@ namespace
|
||||
CHECK_EQUAL(data.at(K9), N9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_at_const_using_transparent_comparator_and_hasher)
|
||||
{
|
||||
const DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_EQUAL(data.at(CK0), N0);
|
||||
CHECK_EQUAL(data.at(CK1), N1);
|
||||
CHECK_EQUAL(data.at(CK2), N2);
|
||||
CHECK_EQUAL(data.at(CK3), N3);
|
||||
CHECK_EQUAL(data.at(CK4), N4);
|
||||
CHECK_EQUAL(data.at(CK5), N5);
|
||||
CHECK_EQUAL(data.at(CK6), N6);
|
||||
CHECK_EQUAL(data.at(CK7), N7);
|
||||
CHECK_EQUAL(data.at(CK8), N8);
|
||||
CHECK_EQUAL(data.at(CK9), N9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assign_range)
|
||||
{
|
||||
@ -687,6 +808,23 @@ namespace
|
||||
CHECK(!data.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
size_t count = data.erase(CK5);
|
||||
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
DataNDCTransparent::iterator idata = data.find(CK5);
|
||||
CHECK(idata == data.end());
|
||||
|
||||
// Test that erase really does erase from the pool.
|
||||
CHECK(!data.full());
|
||||
CHECK(!data.empty());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_single_iterator)
|
||||
{
|
||||
@ -837,6 +975,18 @@ namespace
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_count_key_using_transparent_comparator)
|
||||
{
|
||||
DataNDC data(initial_data.begin(), initial_data.end());
|
||||
|
||||
size_t count = data.count(CK5);
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
count = data.count(CK12);
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||
{
|
||||
@ -863,6 +1013,32 @@ namespace
|
||||
CHECK_EQUAL(result.first->first, K9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
ETL_OR_STD::pair<DataNDCTransparent::iterator, DataNDCTransparent::iterator> result;
|
||||
|
||||
result = data.equal_range("FF");
|
||||
CHECK(result.first == data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FF");
|
||||
|
||||
result = data.equal_range("FJ");
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FJ");
|
||||
|
||||
result = data.equal_range("FO");
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second == data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FO");
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range_const)
|
||||
{
|
||||
@ -889,6 +1065,32 @@ namespace
|
||||
CHECK_EQUAL(result.first->first, K9);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range_const_using_transparent_comparator)
|
||||
{
|
||||
const DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
ETL_OR_STD::pair<DataNDCTransparent::const_iterator, DataNDCTransparent::const_iterator> result;
|
||||
|
||||
result = data.equal_range("FF");
|
||||
CHECK(result.first == data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FF");
|
||||
|
||||
result = data.equal_range("FJ");
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FJ");
|
||||
|
||||
result = data.equal_range("FO");
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second == data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, "FO");
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal)
|
||||
{
|
||||
|
||||
@ -85,6 +85,25 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
struct transparent_hash
|
||||
{
|
||||
typedef int is_transparent;
|
||||
|
||||
size_t operator ()(const char* s) const
|
||||
{
|
||||
size_t sum = 0U;
|
||||
size_t length = etl::strlen(s);
|
||||
|
||||
return std::accumulate(s, s + length, sum);
|
||||
}
|
||||
|
||||
size_t operator ()(const std::string& text) const
|
||||
{
|
||||
return std::accumulate(text.begin(), text.end(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
typedef TestDataDC<std::string> DC;
|
||||
typedef TestDataNDC<std::string> NDC;
|
||||
|
||||
@ -175,6 +194,8 @@ namespace
|
||||
typedef etl::unordered_multimap<std::string, DC, SIZE, SIZE / 2, simple_hash> DataDC;
|
||||
typedef etl::unordered_multimap<std::string, NDC, SIZE, SIZE / 2, simple_hash> DataNDC;
|
||||
typedef etl::iunordered_multimap<std::string, NDC, simple_hash> IDataNDC;
|
||||
typedef etl::unordered_multimap<std::string, NDC, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataNDCTransparent;
|
||||
typedef etl::unordered_multimap<std::string, DC, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataDCTransparent;
|
||||
|
||||
using ItemM = TestDataM<int>;
|
||||
using DataM = etl::unordered_multimap<std::string, ItemM, SIZE, SIZE, std::hash<std::string>>;
|
||||
@ -200,26 +221,47 @@ namespace
|
||||
NDC N18 = NDC("S");
|
||||
NDC N19 = NDC("T");
|
||||
|
||||
const char* K0 = "FF"; // 0
|
||||
const char* K1 = "FG"; // 1
|
||||
const char* K2 = "FH"; // 2
|
||||
const char* K3 = "FI"; // 3
|
||||
const char* K4 = "FJ"; // 4
|
||||
const char* K5 = "FK"; // 5
|
||||
const char* K6 = "FL"; // 6
|
||||
const char* K7 = "FM"; // 7
|
||||
const char* K8 = "FN"; // 8
|
||||
const char* K9 = "FO"; // 9
|
||||
const char* K10 = "FP"; // 0
|
||||
const char* K11 = "FQ"; // 1
|
||||
const char* K12 = "FR"; // 2
|
||||
const char* K13 = "FS"; // 3
|
||||
const char* K14 = "FT"; // 4
|
||||
const char* K15 = "FU"; // 5
|
||||
const char* K16 = "FV"; // 6
|
||||
const char* K17 = "FW"; // 7
|
||||
const char* K18 = "FX"; // 8
|
||||
const char* K19 = "FY"; // 9
|
||||
const char* CK0 = "FF"; // 0
|
||||
const char* CK1 = "FG"; // 1
|
||||
const char* CK2 = "FH"; // 2
|
||||
const char* CK3 = "FI"; // 3
|
||||
const char* CK4 = "FJ"; // 4
|
||||
const char* CK5 = "FK"; // 5
|
||||
const char* CK6 = "FL"; // 6
|
||||
const char* CK7 = "FM"; // 7
|
||||
const char* CK8 = "FN"; // 8
|
||||
const char* CK9 = "FO"; // 9
|
||||
const char* CK10 = "FP"; // 0
|
||||
const char* CK11 = "FQ"; // 1
|
||||
const char* CK12 = "FR"; // 2
|
||||
const char* CK13 = "FS"; // 3
|
||||
const char* CK14 = "FT"; // 4
|
||||
const char* CK15 = "FU"; // 5
|
||||
const char* CK16 = "FV"; // 6
|
||||
const char* CK17 = "FW"; // 7
|
||||
const char* CK18 = "FX"; // 8
|
||||
const char* CK19 = "FY"; // 9
|
||||
|
||||
std::string K0 = CK0; // 0
|
||||
std::string K1 = CK1; // 1
|
||||
std::string K2 = CK2; // 2
|
||||
std::string K3 = CK3; // 3
|
||||
std::string K4 = CK4; // 4
|
||||
std::string K5 = CK5; // 5
|
||||
std::string K6 = CK6; // 6
|
||||
std::string K7 = CK7; // 7
|
||||
std::string K8 = CK8; // 8
|
||||
std::string K9 = CK9; // 9
|
||||
std::string K10 = CK10; // 0
|
||||
std::string K11 = CK11; // 1
|
||||
std::string K12 = CK12; // 2
|
||||
std::string K13 = CK13; // 3
|
||||
std::string K14 = CK14; // 4
|
||||
std::string K15 = CK15; // 5
|
||||
std::string K16 = CK16; // 6
|
||||
std::string K17 = CK17; // 7
|
||||
std::string K18 = CK18; // 8
|
||||
std::string K19 = CK19; // 9
|
||||
|
||||
std::string K[] = { K0, K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19 };
|
||||
|
||||
@ -572,6 +614,26 @@ namespace
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(equal_data.begin(), equal_data.end());
|
||||
|
||||
size_t count = data.erase("FP");
|
||||
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
DataNDCTransparent::iterator idata = data.find("FP");
|
||||
CHECK(idata == data.end());
|
||||
|
||||
count = data.erase("FQ");
|
||||
|
||||
CHECK_EQUAL(3U, count);
|
||||
|
||||
idata = data.find("FQ");
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_single_iterator)
|
||||
{
|
||||
@ -717,7 +779,6 @@ namespace
|
||||
CHECK_EQUAL(data.size(), size_t(0));
|
||||
}
|
||||
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_count_key)
|
||||
{
|
||||
@ -733,6 +794,31 @@ namespace
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_count_key_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(equal_data.begin(), equal_data.end());
|
||||
|
||||
size_t count = data.count(K10);
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
count = data.count(K11);
|
||||
CHECK_EQUAL(3U, count);
|
||||
|
||||
count = data.count(K1);
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find)
|
||||
{
|
||||
DataNDC data(initial_data.begin(), initial_data.end());
|
||||
|
||||
DataNDC::iterator idata = data.find(K3);
|
||||
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find_const)
|
||||
{
|
||||
@ -743,6 +829,26 @@ namespace
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
DataNDCTransparent::iterator idata = data.find(CK3);
|
||||
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find_const_using_transparent_comparator)
|
||||
{
|
||||
const DataNDCTransparent data(initial_data.begin(), initial_data.end());
|
||||
|
||||
DataNDCTransparent::const_iterator idata = data.find(CK3);
|
||||
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||
{
|
||||
@ -795,6 +901,58 @@ namespace
|
||||
CHECK_EQUAL(result.first->first, K12);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range_using_transparent_comparator)
|
||||
{
|
||||
DataNDCTransparent data(equal_data.begin(), equal_data.end());
|
||||
|
||||
ETL_OR_STD::pair<DataNDCTransparent::iterator, DataNDCTransparent::iterator> result;
|
||||
|
||||
result = data.equal_range(CK10);
|
||||
CHECK(result.first == data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, CK10);
|
||||
|
||||
result = data.equal_range(CK11);
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 3);
|
||||
CHECK_EQUAL(result.first->first, CK11);
|
||||
|
||||
result = data.equal_range(CK12);
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second == data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, CK12);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range_const_using_transparent_comparator)
|
||||
{
|
||||
const DataNDCTransparent data(equal_data.begin(), equal_data.end());
|
||||
|
||||
ETL_OR_STD::pair<DataNDCTransparent::const_iterator, DataNDCTransparent::const_iterator> result;
|
||||
|
||||
result = data.equal_range(CK10);
|
||||
CHECK(result.first == data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, CK10);
|
||||
|
||||
result = data.equal_range(CK11);
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second != data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 3);
|
||||
CHECK_EQUAL(result.first->first, CK11);
|
||||
|
||||
result = data.equal_range(CK12);
|
||||
CHECK(result.first != data.begin());
|
||||
CHECK(result.second == data.end());
|
||||
CHECK_EQUAL(std::distance(result.first, result.second), 1);
|
||||
CHECK_EQUAL(result.first->first, CK12);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal)
|
||||
{
|
||||
|
||||
@ -135,6 +135,22 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct transparent_hash
|
||||
{
|
||||
typedef int is_transparent;
|
||||
|
||||
size_t operator ()(const char* s) const
|
||||
{
|
||||
return std::accumulate(s, s + etl::strlen(s), 0);
|
||||
}
|
||||
|
||||
size_t operator ()(const std::string& s) const
|
||||
{
|
||||
return std::accumulate(s.begin(), s.end(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
SUITE(test_unordered_multiset)
|
||||
{
|
||||
static const size_t SIZE = 10;
|
||||
@ -165,26 +181,49 @@ namespace
|
||||
typedef etl::unordered_multiset<NDC, SIZE, SIZE / 2, simple_hash> DataNDC;
|
||||
typedef etl::iunordered_multiset<NDC, simple_hash> IDataNDC;
|
||||
|
||||
NDC N0 = NDC("FF");
|
||||
NDC N1 = NDC("FG");
|
||||
NDC N2 = NDC("FH");
|
||||
NDC N3 = NDC("FI");
|
||||
NDC N4 = NDC("FJ");
|
||||
NDC N5 = NDC("FK");
|
||||
NDC N6 = NDC("FL");
|
||||
NDC N7 = NDC("FM");
|
||||
NDC N8 = NDC("FN");
|
||||
NDC N9 = NDC("FO");
|
||||
NDC N10 = NDC("FP");
|
||||
NDC N11 = NDC("FQ");
|
||||
NDC N12 = NDC("FR");
|
||||
NDC N13 = NDC("FS");
|
||||
NDC N14 = NDC("FT");
|
||||
NDC N15 = NDC("FU");
|
||||
NDC N16 = NDC("FV");
|
||||
NDC N17 = NDC("FW");
|
||||
NDC N18 = NDC("FX");
|
||||
NDC N19 = NDC("FY");
|
||||
typedef etl::unordered_multiset<std::string, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataTransparent;
|
||||
|
||||
const char* CK0 = "FF"; // 0
|
||||
const char* CK1 = "FG"; // 1
|
||||
const char* CK2 = "FH"; // 2
|
||||
const char* CK3 = "FI"; // 3
|
||||
const char* CK4 = "FJ"; // 4
|
||||
const char* CK5 = "FK"; // 5
|
||||
const char* CK6 = "FL"; // 6
|
||||
const char* CK7 = "FM"; // 7
|
||||
const char* CK8 = "FN"; // 8
|
||||
const char* CK9 = "FO"; // 9
|
||||
const char* CK10 = "FP"; // 0
|
||||
const char* CK11 = "FQ"; // 1
|
||||
const char* CK12 = "FR"; // 2
|
||||
const char* CK13 = "FS"; // 3
|
||||
const char* CK14 = "FT"; // 4
|
||||
const char* CK15 = "FU"; // 5
|
||||
const char* CK16 = "FV"; // 6
|
||||
const char* CK17 = "FW"; // 7
|
||||
const char* CK18 = "FX"; // 8
|
||||
const char* CK19 = "FY"; // 9
|
||||
|
||||
NDC N0 = NDC(CK0);
|
||||
NDC N1 = NDC(CK1);
|
||||
NDC N2 = NDC(CK2);
|
||||
NDC N3 = NDC(CK3);
|
||||
NDC N4 = NDC(CK4);
|
||||
NDC N5 = NDC(CK5);
|
||||
NDC N6 = NDC(CK6);
|
||||
NDC N7 = NDC(CK7);
|
||||
NDC N8 = NDC(CK8);
|
||||
NDC N9 = NDC(CK9);
|
||||
NDC N10 = NDC(CK10);
|
||||
NDC N11 = NDC(CK11);
|
||||
NDC N12 = NDC(CK12);
|
||||
NDC N13 = NDC(CK13);
|
||||
NDC N14 = NDC(CK14);
|
||||
NDC N15 = NDC(CK15);
|
||||
NDC N16 = NDC(CK16);
|
||||
NDC N17 = NDC(CK17);
|
||||
NDC N18 = NDC(CK18);
|
||||
NDC N19 = NDC(CK19);
|
||||
|
||||
std::vector<NDC> initial_data;
|
||||
std::vector<NDC> excess_data;
|
||||
@ -394,6 +433,24 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assign_range_using_transparent_comparator)
|
||||
{
|
||||
std::array<const char*, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data;
|
||||
|
||||
data.assign(initial.begin(), initial.end());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
for (size_t i = 0UL; i < 8; ++i)
|
||||
{
|
||||
idata = data.find(initial[i]);
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value)
|
||||
{
|
||||
@ -431,6 +488,38 @@ namespace
|
||||
CHECK(*idata == N11);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_using_transparent_comparator)
|
||||
{
|
||||
DataTransparent data;
|
||||
|
||||
data.insert(CK0); // Inserted
|
||||
data.insert(CK2); // Inserted
|
||||
data.insert(CK1); // Inserted
|
||||
data.insert(CK11); // Duplicate hash. Inserted
|
||||
data.insert(CK3); // Inserted
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
idata = data.find(CK0);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK0);
|
||||
|
||||
idata = data.find(CK1);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK1);
|
||||
|
||||
idata = data.find(CK2);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK2);
|
||||
|
||||
idata = data.find(CK11);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK11);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_excess)
|
||||
{
|
||||
@ -453,6 +542,24 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_range_using_transparent_comparator)
|
||||
{
|
||||
std::array<const char*, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data;
|
||||
|
||||
data.insert(initial.begin(), initial.end());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
for (size_t i = 0UL; i < 8; ++i)
|
||||
{
|
||||
idata = data.find(initial[i]);
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_range_excess)
|
||||
{
|
||||
@ -505,6 +612,21 @@ namespace
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key_using_transparent_comparator)
|
||||
{
|
||||
std::array<std::string, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data(initial.begin(), initial.end());
|
||||
|
||||
size_t count = data.erase("CC");
|
||||
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
DataTransparent::iterator idata = data.find("CC");
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_single_iterator)
|
||||
{
|
||||
@ -665,6 +787,20 @@ namespace
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_count_key_using_transparent_comparator)
|
||||
{
|
||||
std::array<std::string, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data(initial.begin(), initial.end());
|
||||
|
||||
size_t count = data.count("CC");
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
count = data.count("II");
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_find_const)
|
||||
{
|
||||
|
||||
@ -135,6 +135,22 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
struct transparent_hash
|
||||
{
|
||||
typedef int is_transparent;
|
||||
|
||||
size_t operator ()(const char* s) const
|
||||
{
|
||||
return std::accumulate(s, s + etl::strlen(s), 0);
|
||||
}
|
||||
|
||||
size_t operator ()(const std::string& s) const
|
||||
{
|
||||
return std::accumulate(s.begin(), s.end(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
SUITE(test_unordered_set)
|
||||
{
|
||||
@ -165,27 +181,49 @@ namespace
|
||||
typedef etl::unordered_set<DC, SIZE, SIZE / 2, simple_hash> DataDC;
|
||||
typedef etl::unordered_set<NDC, SIZE, SIZE / 2, simple_hash> DataNDC;
|
||||
typedef etl::iunordered_set<NDC, simple_hash> IDataNDC;
|
||||
typedef etl::unordered_set<std::string, SIZE, SIZE / 2, transparent_hash, etl::equal_to<>> DataTransparent;
|
||||
|
||||
NDC N0 = NDC("FF");
|
||||
NDC N1 = NDC("FG");
|
||||
NDC N2 = NDC("FH");
|
||||
NDC N3 = NDC("FI");
|
||||
NDC N4 = NDC("FJ");
|
||||
NDC N5 = NDC("FK");
|
||||
NDC N6 = NDC("FL");
|
||||
NDC N7 = NDC("FM");
|
||||
NDC N8 = NDC("FN");
|
||||
NDC N9 = NDC("FO");
|
||||
NDC N10 = NDC("FP");
|
||||
NDC N11 = NDC("FQ");
|
||||
NDC N12 = NDC("FR");
|
||||
NDC N13 = NDC("FS");
|
||||
NDC N14 = NDC("FT");
|
||||
NDC N15 = NDC("FU");
|
||||
NDC N16 = NDC("FV");
|
||||
NDC N17 = NDC("FW");
|
||||
NDC N18 = NDC("FX");
|
||||
NDC N19 = NDC("FY");
|
||||
const char* CK0 = "FF"; // 0
|
||||
const char* CK1 = "FG"; // 1
|
||||
const char* CK2 = "FH"; // 2
|
||||
const char* CK3 = "FI"; // 3
|
||||
const char* CK4 = "FJ"; // 4
|
||||
const char* CK5 = "FK"; // 5
|
||||
const char* CK6 = "FL"; // 6
|
||||
const char* CK7 = "FM"; // 7
|
||||
const char* CK8 = "FN"; // 8
|
||||
const char* CK9 = "FO"; // 9
|
||||
const char* CK10 = "FP"; // 0
|
||||
const char* CK11 = "FQ"; // 1
|
||||
const char* CK12 = "FR"; // 2
|
||||
const char* CK13 = "FS"; // 3
|
||||
const char* CK14 = "FT"; // 4
|
||||
const char* CK15 = "FU"; // 5
|
||||
const char* CK16 = "FV"; // 6
|
||||
const char* CK17 = "FW"; // 7
|
||||
const char* CK18 = "FX"; // 8
|
||||
const char* CK19 = "FY"; // 9
|
||||
|
||||
NDC N0 = NDC(CK0);
|
||||
NDC N1 = NDC(CK1);
|
||||
NDC N2 = NDC(CK2);
|
||||
NDC N3 = NDC(CK3);
|
||||
NDC N4 = NDC(CK4);
|
||||
NDC N5 = NDC(CK5);
|
||||
NDC N6 = NDC(CK6);
|
||||
NDC N7 = NDC(CK7);
|
||||
NDC N8 = NDC(CK8);
|
||||
NDC N9 = NDC(CK9);
|
||||
NDC N10 = NDC(CK10);
|
||||
NDC N11 = NDC(CK11);
|
||||
NDC N12 = NDC(CK12);
|
||||
NDC N13 = NDC(CK13);
|
||||
NDC N14 = NDC(CK14);
|
||||
NDC N15 = NDC(CK15);
|
||||
NDC N16 = NDC(CK16);
|
||||
NDC N17 = NDC(CK17);
|
||||
NDC N18 = NDC(CK18);
|
||||
NDC N19 = NDC(CK19);
|
||||
|
||||
std::vector<NDC> initial_data;
|
||||
std::vector<NDC> excess_data;
|
||||
@ -378,6 +416,24 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_assign_range_using_transparent_comparator)
|
||||
{
|
||||
std::array<const char*, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data;
|
||||
|
||||
data.assign(initial.begin(), initial.end());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
for (size_t i = 0UL; i < 8; ++i)
|
||||
{
|
||||
idata = data.find(initial[i]);
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value)
|
||||
{
|
||||
@ -409,6 +465,38 @@ namespace
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == N11);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_using_transparent_comparator)
|
||||
{
|
||||
DataTransparent data;
|
||||
|
||||
data.insert(CK0); // Inserted
|
||||
data.insert(CK2); // Inserted
|
||||
data.insert(CK1); // Inserted
|
||||
data.insert(CK11); // Duplicate hash. Inserted
|
||||
data.insert(CK3); // Inserted
|
||||
|
||||
CHECK_EQUAL(5U, data.size());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
idata = data.find(CK0);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK0);
|
||||
|
||||
idata = data.find(CK1);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK1);
|
||||
|
||||
idata = data.find(CK2);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK2);
|
||||
|
||||
idata = data.find(CK11);
|
||||
CHECK(idata != data.end());
|
||||
CHECK(*idata == CK11);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_excess)
|
||||
@ -432,6 +520,24 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_range_using_transparent_comparator)
|
||||
{
|
||||
std::array<const char*, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data;
|
||||
|
||||
data.insert(initial.begin(), initial.end());
|
||||
|
||||
DataTransparent::iterator idata;
|
||||
|
||||
for (size_t i = 0UL; i < 8; ++i)
|
||||
{
|
||||
idata = data.find(initial[i]);
|
||||
CHECK(idata != data.end());
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_range_excess)
|
||||
{
|
||||
@ -508,6 +614,21 @@ namespace
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key_using_transparent_comparator)
|
||||
{
|
||||
std::array<std::string, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data(initial.begin(), initial.end());
|
||||
|
||||
size_t count = data.erase("CC");
|
||||
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
DataTransparent::iterator idata = data.find("CC");
|
||||
CHECK(idata == data.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_single_iterator)
|
||||
{
|
||||
@ -665,6 +786,20 @@ namespace
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_count_key_using_transparent_comparator)
|
||||
{
|
||||
std::array<std::string, 8> initial = { "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH" };
|
||||
|
||||
DataTransparent data(initial.begin(), initial.end());
|
||||
|
||||
size_t count = data.count("CC");
|
||||
CHECK_EQUAL(1U, count);
|
||||
|
||||
count = data.count("II");
|
||||
CHECK_EQUAL(0U, count);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user