568 lines
22 KiB
C
568 lines
22 KiB
C
|
/*
|
||
|
Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without
|
||
|
modification, are permitted provided that the following conditions
|
||
|
are met:
|
||
|
|
||
|
1. Redistributions of source code must retain the above copyright
|
||
|
notice, this list of conditions and the following disclaimer.
|
||
|
2. Redistributions in binary form must reproduce the above copyright
|
||
|
notice, this list of conditions and the following disclaimer in the
|
||
|
documentation and/or other materials provided with the distribution.
|
||
|
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
|
||
|
its contributors may be used to endorse or promote products derived
|
||
|
from this software without specific prior written permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
|
||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// EASTL/set.h
|
||
|
//
|
||
|
// Copyright (c) 2005, Electronic Arts. All rights reserved.
|
||
|
// Written by Paul Pedriana.
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef EASTL_SET_H
|
||
|
#define EASTL_SET_H
|
||
|
|
||
|
|
||
|
|
||
|
#include <EASTL/internal/config.h>
|
||
|
#include <EASTL/internal/red_black_tree.h>
|
||
|
#include <EASTL/functional.h>
|
||
|
#include <EASTL/utility.h>
|
||
|
|
||
|
|
||
|
|
||
|
namespace eastl
|
||
|
{
|
||
|
|
||
|
/// EASTL_SET_DEFAULT_NAME
|
||
|
///
|
||
|
/// Defines a default container name in the absence of a user-provided name.
|
||
|
///
|
||
|
#ifndef EASTL_SET_DEFAULT_NAME
|
||
|
#define EASTL_SET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " set" // Unless the user overrides something, this is "EASTL set".
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/// EASTL_MULTISET_DEFAULT_NAME
|
||
|
///
|
||
|
/// Defines a default container name in the absence of a user-provided name.
|
||
|
///
|
||
|
#ifndef EASTL_MULTISET_DEFAULT_NAME
|
||
|
#define EASTL_MULTISET_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " multiset" // Unless the user overrides something, this is "EASTL multiset".
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/// EASTL_SET_DEFAULT_ALLOCATOR
|
||
|
///
|
||
|
#ifndef EASTL_SET_DEFAULT_ALLOCATOR
|
||
|
#define EASTL_SET_DEFAULT_ALLOCATOR allocator_type(EASTL_SET_DEFAULT_NAME)
|
||
|
#endif
|
||
|
|
||
|
/// EASTL_MULTISET_DEFAULT_ALLOCATOR
|
||
|
///
|
||
|
#ifndef EASTL_MULTISET_DEFAULT_ALLOCATOR
|
||
|
#define EASTL_MULTISET_DEFAULT_ALLOCATOR allocator_type(EASTL_MULTISET_DEFAULT_NAME)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/// set
|
||
|
///
|
||
|
/// Implements a canonical set.
|
||
|
///
|
||
|
/// The large majority of the implementation of this class is found in the rbtree
|
||
|
/// base class. We control the behaviour of rbtree via template parameters.
|
||
|
///
|
||
|
/// Note that the 'bMutableIterators' template parameter to rbtree is set to false.
|
||
|
/// This means that set::iterator is const and the same as set::const_iterator.
|
||
|
/// This is by design and it follows the C++ standard defect report recommendation.
|
||
|
/// If the user wants to modify a container element, the user needs to either use
|
||
|
/// mutable data members or use const_cast on the iterator's data member. Both of
|
||
|
/// these solutions are recommended by the C++ standard defect report.
|
||
|
/// To consider: Expose the bMutableIterators template policy here at the set level
|
||
|
/// so the user can have non-const set iterators via a template parameter.
|
||
|
///
|
||
|
/// Pool allocation
|
||
|
/// If you want to make a custom memory pool for a set container, your pool
|
||
|
/// needs to contain items of type set::node_type. So if you have a memory
|
||
|
/// pool that has a constructor that takes the size of pool items and the
|
||
|
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||
|
/// the Allocator interface):
|
||
|
/// typedef set<Widget, less<Widget>, MemoryPool> WidgetSet; // Delare your WidgetSet type.
|
||
|
/// MemoryPool myPool(sizeof(WidgetSet::node_type), 100); // Make a pool of 100 Widget nodes.
|
||
|
/// WidgetSet mySet(&myPool); // Create a map that uses the pool.
|
||
|
///
|
||
|
template <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||
|
class set
|
||
|
: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true>
|
||
|
{
|
||
|
public:
|
||
|
typedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, true> base_type;
|
||
|
typedef set<Key, Compare, Allocator> this_type;
|
||
|
typedef typename base_type::size_type size_type;
|
||
|
typedef typename base_type::value_type value_type;
|
||
|
typedef typename base_type::iterator iterator;
|
||
|
typedef typename base_type::const_iterator const_iterator;
|
||
|
typedef typename base_type::reverse_iterator reverse_iterator;
|
||
|
typedef typename base_type::const_reverse_iterator const_reverse_iterator;
|
||
|
typedef typename base_type::allocator_type allocator_type;
|
||
|
// Other types are inherited from the base class.
|
||
|
|
||
|
using base_type::begin;
|
||
|
using base_type::end;
|
||
|
using base_type::find;
|
||
|
using base_type::lower_bound;
|
||
|
using base_type::upper_bound;
|
||
|
using base_type::mCompare;
|
||
|
|
||
|
public:
|
||
|
set(const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);
|
||
|
set(const Compare& compare, const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR);
|
||
|
set(const this_type& x);
|
||
|
|
||
|
template <typename Iterator>
|
||
|
set(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.
|
||
|
|
||
|
public:
|
||
|
size_type erase(const Key& k);
|
||
|
iterator erase(iterator position);
|
||
|
iterator erase(iterator first, iterator last);
|
||
|
|
||
|
reverse_iterator erase(reverse_iterator position);
|
||
|
reverse_iterator erase(reverse_iterator first, reverse_iterator last);
|
||
|
|
||
|
size_type count(const Key& k) const;
|
||
|
|
||
|
eastl::pair<iterator, iterator> equal_range(const Key& k);
|
||
|
eastl::pair<const_iterator, const_iterator> equal_range(const Key& k) const;
|
||
|
|
||
|
}; // set
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/// multiset
|
||
|
///
|
||
|
/// Implements a canonical multiset.
|
||
|
///
|
||
|
/// The large majority of the implementation of this class is found in the rbtree
|
||
|
/// base class. We control the behaviour of rbtree via template parameters.
|
||
|
///
|
||
|
/// See notes above in 'set' regarding multable iterators.
|
||
|
///
|
||
|
/// Pool allocation
|
||
|
/// If you want to make a custom memory pool for a multiset container, your pool
|
||
|
/// needs to contain items of type multiset::node_type. So if you have a memory
|
||
|
/// pool that has a constructor that takes the size of pool items and the
|
||
|
/// count of pool items, you would do this (assuming that MemoryPool implements
|
||
|
/// the Allocator interface):
|
||
|
/// typedef multiset<Widget, less<Widget>, MemoryPool> WidgetSet; // Delare your WidgetSet type.
|
||
|
/// MemoryPool myPool(sizeof(WidgetSet::node_type), 100); // Make a pool of 100 Widget nodes.
|
||
|
/// WidgetSet mySet(&myPool); // Create a map that uses the pool.
|
||
|
///
|
||
|
template <typename Key, typename Compare = eastl::less<Key>, typename Allocator = EASTLAllocatorType>
|
||
|
class multiset
|
||
|
: public rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false>
|
||
|
{
|
||
|
public:
|
||
|
typedef rbtree<Key, Key, Compare, Allocator, eastl::use_self<Key>, false, false> base_type;
|
||
|
typedef multiset<Key, Compare, Allocator> this_type;
|
||
|
typedef typename base_type::size_type size_type;
|
||
|
typedef typename base_type::value_type value_type;
|
||
|
typedef typename base_type::iterator iterator;
|
||
|
typedef typename base_type::const_iterator const_iterator;
|
||
|
typedef typename base_type::reverse_iterator reverse_iterator;
|
||
|
typedef typename base_type::const_reverse_iterator const_reverse_iterator;
|
||
|
typedef typename base_type::allocator_type allocator_type;
|
||
|
// Other types are inherited from the base class.
|
||
|
|
||
|
using base_type::begin;
|
||
|
using base_type::end;
|
||
|
using base_type::find;
|
||
|
using base_type::lower_bound;
|
||
|
using base_type::upper_bound;
|
||
|
using base_type::mCompare;
|
||
|
|
||
|
public:
|
||
|
multiset(const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);
|
||
|
multiset(const Compare& compare, const allocator_type& allocator = EASTL_MULTISET_DEFAULT_ALLOCATOR);
|
||
|
multiset(const this_type& x);
|
||
|
|
||
|
template <typename Iterator>
|
||
|
multiset(Iterator itBegin, Iterator itEnd); // allocator arg removed because VC7.1 fails on the default arg. To do: Make a second version of this function without a default arg.
|
||
|
|
||
|
public:
|
||
|
size_type erase(const Key& k);
|
||
|
iterator erase(iterator position);
|
||
|
iterator erase(iterator first, iterator last);
|
||
|
|
||
|
reverse_iterator erase(reverse_iterator position);
|
||
|
reverse_iterator erase(reverse_iterator first, reverse_iterator last);
|
||
|
|
||
|
size_type count(const Key& k) const;
|
||
|
|
||
|
eastl::pair<iterator, iterator> equal_range(const Key& k);
|
||
|
eastl::pair<const_iterator, const_iterator> equal_range(const Key& k) const;
|
||
|
|
||
|
/// equal_range_small
|
||
|
/// This is a special version of equal_range which is optimized for the
|
||
|
/// case of there being few or no duplicated keys in the tree.
|
||
|
eastl::pair<iterator, iterator> equal_range_small(const Key& k);
|
||
|
eastl::pair<const_iterator, const_iterator> equal_range_small(const Key& k) const;
|
||
|
|
||
|
}; // multiset
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
// set
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline set<Key, Compare, Allocator>::set(const allocator_type& allocator)
|
||
|
: base_type(allocator)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline set<Key, Compare, Allocator>::set(const Compare& compare, const allocator_type& allocator)
|
||
|
: base_type(compare, allocator)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline set<Key, Compare, Allocator>::set(const this_type& x)
|
||
|
: base_type(x)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
template <typename Iterator>
|
||
|
inline set<Key, Compare, Allocator>::set(Iterator itBegin, Iterator itEnd)
|
||
|
: base_type(itBegin, itEnd, Compare(), EASTL_SET_DEFAULT_ALLOCATOR)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::size_type
|
||
|
set<Key, Compare, Allocator>::erase(const Key& k)
|
||
|
{
|
||
|
const iterator it(find(k));
|
||
|
|
||
|
if(it != end()) // If it exists...
|
||
|
{
|
||
|
base_type::erase(it);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::iterator
|
||
|
set<Key, Compare, Allocator>::erase(iterator position)
|
||
|
{
|
||
|
// We need to provide this version because we override another version
|
||
|
// and C++ hiding rules would make the base version of this hidden.
|
||
|
return base_type::erase(position);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::iterator
|
||
|
set<Key, Compare, Allocator>::erase(iterator first, iterator last)
|
||
|
{
|
||
|
// We need to provide this version because we override another version
|
||
|
// and C++ hiding rules would make the base version of this hidden.
|
||
|
return base_type::erase(first, last);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::size_type
|
||
|
set<Key, Compare, Allocator>::count(const Key& k) const
|
||
|
{
|
||
|
const const_iterator it(find(k));
|
||
|
return (it != end()) ? (size_type)1 : (size_type)0;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::reverse_iterator
|
||
|
set<Key, Compare, Allocator>::erase(reverse_iterator position)
|
||
|
{
|
||
|
return reverse_iterator(erase((++position).base()));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename set<Key, Compare, Allocator>::reverse_iterator
|
||
|
set<Key, Compare, Allocator>::erase(reverse_iterator first, reverse_iterator last)
|
||
|
{
|
||
|
// Version which erases in order from first to last.
|
||
|
// difference_type i(first.base() - last.base());
|
||
|
// while(i--)
|
||
|
// first = erase(first);
|
||
|
// return first;
|
||
|
|
||
|
// Version which erases in order from last to first, but is slightly more efficient:
|
||
|
return reverse_iterator(erase((++last).base(), (++first).base()));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename set<Key, Compare, Allocator>::iterator,
|
||
|
typename set<Key, Compare, Allocator>::iterator>
|
||
|
set<Key, Compare, Allocator>::equal_range(const Key& k)
|
||
|
{
|
||
|
// The resulting range will either be empty or have one element,
|
||
|
// so instead of doing two tree searches (one for lower_bound and
|
||
|
// one for upper_bound), we do just lower_bound and see if the
|
||
|
// result is a range of size zero or one.
|
||
|
const iterator itLower(lower_bound(k));
|
||
|
|
||
|
if((itLower == end()) || mCompare(k, *itLower)) // If at the end or if (k is < itLower)...
|
||
|
return eastl::pair<iterator, iterator>(itLower, itLower);
|
||
|
|
||
|
iterator itUpper(itLower);
|
||
|
return eastl::pair<iterator, iterator>(itLower, ++itUpper);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename set<Key, Compare, Allocator>::const_iterator,
|
||
|
typename set<Key, Compare, Allocator>::const_iterator>
|
||
|
set<Key, Compare, Allocator>::equal_range(const Key& k) const
|
||
|
{
|
||
|
// See equal_range above for comments.
|
||
|
const const_iterator itLower(lower_bound(k));
|
||
|
|
||
|
if((itLower == end()) || mCompare(k, *itLower)) // If at the end or if (k is < itLower)...
|
||
|
return eastl::pair<const_iterator, const_iterator>(itLower, itLower);
|
||
|
|
||
|
const_iterator itUpper(itLower);
|
||
|
return eastl::pair<const_iterator, const_iterator>(itLower, ++itUpper);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
// multiset
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline multiset<Key, Compare, Allocator>::multiset(const allocator_type& allocator)
|
||
|
: base_type(allocator)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline multiset<Key, Compare, Allocator>::multiset(const Compare& compare, const allocator_type& allocator)
|
||
|
: base_type(compare, allocator)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline multiset<Key, Compare, Allocator>::multiset(const this_type& x)
|
||
|
: base_type(x)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
template <typename Iterator>
|
||
|
inline multiset<Key, Compare, Allocator>::multiset(Iterator itBegin, Iterator itEnd)
|
||
|
: base_type(itBegin, itEnd, Compare(), EASTL_MULTISET_DEFAULT_ALLOCATOR)
|
||
|
{
|
||
|
// Empty
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::size_type
|
||
|
multiset<Key, Compare, Allocator>::erase(const Key& k)
|
||
|
{
|
||
|
const eastl::pair<iterator, iterator> range(equal_range(k));
|
||
|
const size_type n = (size_type)eastl::distance(range.first, range.second);
|
||
|
base_type::erase(range.first, range.second);
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::iterator
|
||
|
multiset<Key, Compare, Allocator>::erase(iterator position)
|
||
|
{
|
||
|
// We need to provide this version because we override another version
|
||
|
// and C++ hiding rules would make the base version of this hidden.
|
||
|
return base_type::erase(position);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::iterator
|
||
|
multiset<Key, Compare, Allocator>::erase(iterator first, iterator last)
|
||
|
{
|
||
|
// We need to provide this version because we override another version
|
||
|
// and C++ hiding rules would make the base version of this hidden.
|
||
|
return base_type::erase(first, last);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::size_type
|
||
|
multiset<Key, Compare, Allocator>::count(const Key& k) const
|
||
|
{
|
||
|
const eastl::pair<const_iterator, const_iterator> range(equal_range(k));
|
||
|
return (size_type)eastl::distance(range.first, range.second);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::reverse_iterator
|
||
|
multiset<Key, Compare, Allocator>::erase(reverse_iterator position)
|
||
|
{
|
||
|
return reverse_iterator(erase((++position).base()));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline typename multiset<Key, Compare, Allocator>::reverse_iterator
|
||
|
multiset<Key, Compare, Allocator>::erase(reverse_iterator first, reverse_iterator last)
|
||
|
{
|
||
|
// Version which erases in order from first to last.
|
||
|
// difference_type i(first.base() - last.base());
|
||
|
// while(i--)
|
||
|
// first = erase(first);
|
||
|
// return first;
|
||
|
|
||
|
// Version which erases in order from last to first, but is slightly more efficient:
|
||
|
return reverse_iterator(erase((++last).base(), (++first).base()));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,
|
||
|
typename multiset<Key, Compare, Allocator>::iterator>
|
||
|
multiset<Key, Compare, Allocator>::equal_range(const Key& k)
|
||
|
{
|
||
|
// There are multiple ways to implement equal_range. The implementation mentioned
|
||
|
// in the C++ standard and which is used by most (all?) commercial STL implementations
|
||
|
// is this:
|
||
|
// return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||
|
//
|
||
|
// This does two tree searches -- one for the lower bound and one for the
|
||
|
// upper bound. This works well for the case whereby you have a large container
|
||
|
// and there are lots of duplicated values. We provide an alternative version
|
||
|
// of equal_range called equal_range_small for cases where the user is confident
|
||
|
// that the number of duplicated items is only a few.
|
||
|
|
||
|
return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator,
|
||
|
typename multiset<Key, Compare, Allocator>::const_iterator>
|
||
|
multiset<Key, Compare, Allocator>::equal_range(const Key& k) const
|
||
|
{
|
||
|
// See comments above in the non-const version of equal_range.
|
||
|
return eastl::pair<iterator, iterator>(lower_bound(k), upper_bound(k));
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename multiset<Key, Compare, Allocator>::iterator,
|
||
|
typename multiset<Key, Compare, Allocator>::iterator>
|
||
|
multiset<Key, Compare, Allocator>::equal_range_small(const Key& k)
|
||
|
{
|
||
|
// We provide alternative version of equal_range here which works faster
|
||
|
// for the case where there are at most small number of potential duplicated keys.
|
||
|
const iterator itLower(lower_bound(k));
|
||
|
iterator itUpper(itLower);
|
||
|
|
||
|
while((itUpper != end()) && !mCompare(k, itUpper.mpNode->mValue))
|
||
|
++itUpper;
|
||
|
|
||
|
return eastl::pair<iterator, iterator>(itLower, itUpper);
|
||
|
}
|
||
|
|
||
|
|
||
|
template <typename Key, typename Compare, typename Allocator>
|
||
|
inline eastl::pair<typename multiset<Key, Compare, Allocator>::const_iterator,
|
||
|
typename multiset<Key, Compare, Allocator>::const_iterator>
|
||
|
multiset<Key, Compare, Allocator>::equal_range_small(const Key& k) const
|
||
|
{
|
||
|
// We provide alternative version of equal_range here which works faster
|
||
|
// for the case where there are at most small number of potential duplicated keys.
|
||
|
const const_iterator itLower(lower_bound(k));
|
||
|
const_iterator itUpper(itLower);
|
||
|
|
||
|
while((itUpper != end()) && !mCompare(k, *itUpper))
|
||
|
++itUpper;
|
||
|
|
||
|
return eastl::pair<const_iterator, const_iterator>(itLower, itUpper);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
} // namespace eastl
|
||
|
|
||
|
|
||
|
#endif // Header include guard
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|