mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
whoops
This commit is contained in:
parent
fb9c56432a
commit
f965ed1f43
@ -3,3 +3,72 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Type>
|
||||
INLINE pallocator_single<Type>::
|
||||
pallocator_single(TypeHandle type_handle) throw() :
|
||||
_type_handle(type_handle)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE TYPENAME pallocator_single<Type>::pointer pallocator_single<Type>::
|
||||
allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
|
||||
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
||||
// This doesn't support allocating arrays.
|
||||
assert(n == 1);
|
||||
return StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_single<Type>::
|
||||
deallocate(TYPENAME pallocator_single<Type>::pointer p, TYPENAME pallocator_single<Type>::size_type) {
|
||||
TAU_PROFILE("pallocator_single:deallocate()", " ", TAU_USER);
|
||||
StaticDeletedChain<Type>::deallocate(p, _type_handle);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE pallocator_array<Type>::
|
||||
pallocator_array(TypeHandle type_handle) throw() :
|
||||
_type_handle(type_handle)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE TYPENAME pallocator_array<Type>::pointer pallocator_array<Type>::
|
||||
allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
|
||||
TAU_PROFILE("pallocator_array:allocate()", " ", TAU_USER);
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size_t alloc_size = n * sizeof(Type);
|
||||
// We also need to store the total number of bytes we allocated.
|
||||
alloc_size += sizeof(size_t);
|
||||
_type_handle.inc_memory_usage(TypeHandle::MC_array, (int)alloc_size);
|
||||
void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
|
||||
*((size_t *)ptr) = alloc_size;
|
||||
return (TYPENAME pallocator_array<Type>::pointer)(((size_t *)ptr) + 1);
|
||||
#else
|
||||
return (TYPENAME pallocator_array<Type>::pointer)malloc(n * sizeof(Type));
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_array<Type>::
|
||||
deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::size_type) {
|
||||
TAU_PROFILE("pallocator_array:deallocate()", " ", TAU_USER);
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// Now we need to recover the total number of bytes.
|
||||
size_t alloc_size = *(((size_t *)p) - 1);
|
||||
_type_handle.dec_memory_usage(TypeHandle::MC_array, (int)alloc_size);
|
||||
PANDA_FREE_ARRAY(((size_t *)p) - 1);
|
||||
#else
|
||||
free(p);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
@ -3,3 +3,100 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_get_typehandle
|
||||
// Description: Returns the TypeHandle associated with the type of
|
||||
// the parameter, if it can be determined. This is a
|
||||
// support function for _dcast, below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE TypeHandle
|
||||
_dcast_get_typehandle(WantType *) {
|
||||
TAU_PROFILE("_dcast_get_typehandle()", " ", TAU_USER);
|
||||
TypeHandle handle = WantType::get_class_type();
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (handle == TypeHandle::none()) {
|
||||
// This type handle is unregistered. Oops!
|
||||
WantType::init_type();
|
||||
handle = WantType::get_class_type();
|
||||
express_cat->warning()
|
||||
<< "Type " << handle << " was unregistered!\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on non-const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast(WantType *, TypedObject *ptr) {
|
||||
#ifdef DO_DCAST
|
||||
TAU_PROFILE("_dcast()", " ", TAU_USER);
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
if (!_dcast_verify(want_handle, sizeof(WantType), ptr)) {
|
||||
return (WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast(WantType *, const TypedObject *ptr) {
|
||||
#ifdef DO_DCAST
|
||||
TAU_PROFILE("_dcast()", " ", TAU_USER);
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
if (!_dcast_verify(want_handle, sizeof(WantType), ptr)) {
|
||||
return (const WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (const WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_ref
|
||||
// Description: Similar to the above, with a pointer reference as the
|
||||
// first parameter. Just for fiddly compiler reasons;
|
||||
// the reference isn't used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast_ref(WantType *&, TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast_ref(WantType *&, const TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
@ -3,3 +3,407 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::insert_unique
|
||||
// Access: Public
|
||||
// Description: Inserts the indicated key into the ordered vector.
|
||||
// The iterator is a hint to the expected position; if
|
||||
// this is correct, the insert operation is likely to be
|
||||
// faster. The return value is the iterator referencing
|
||||
// the new element.
|
||||
//
|
||||
// This flavor of insert does not allow multiple copies
|
||||
// of the same key to be inserted. If the key is
|
||||
// already present, it is not inserted, and the iterator
|
||||
// referencing the original value is returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::ITERATOR ordered_vector<Key, Compare>::
|
||||
insert_unique(TYPENAME ordered_vector<Key, Compare>::ITERATOR position,
|
||||
const TYPENAME ordered_vector<Key, Compare>::VALUE_TYPE &key) {
|
||||
TAU_PROFILE("ordered_vector::insert_unique(iterator, const value_type &)", " ", TAU_USER);
|
||||
if (position != end()) {
|
||||
// If we're not inserting at the end, the element we're
|
||||
// inserting before should not lexicographically precede this one.
|
||||
if (_compare(*position, key)) {
|
||||
return insert_unique(key).first;
|
||||
|
||||
} else if (!_compare(key, *position)) {
|
||||
// Oops, !(*position < key) and !(key < *position). That means
|
||||
// they're equivalent, and we shouldn't insert a new one.
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
if (position != begin()) {
|
||||
// If we're not inserting at the beginning, this element should
|
||||
// not lexicographically precede the one we're inserting after.
|
||||
if (_compare(key, *(position - 1))) {
|
||||
return insert_unique(key).first;
|
||||
|
||||
} else if (!_compare(*(position - 1), key)) {
|
||||
// Once again, they're equivalent.
|
||||
return position - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we may insert where the caller requested.
|
||||
ITERATOR result = _vector.insert(position, key);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::insert_nonunique
|
||||
// Access: Public
|
||||
// Description: Inserts the indicated key into the ordered vector.
|
||||
// The iterator is a hint to the expected position; if
|
||||
// this is correct, the insert operation is likely to be
|
||||
// faster. The return value is the iterator referencing
|
||||
// the new element.
|
||||
//
|
||||
// This flavor of insert allows multiple copies of the
|
||||
// same key to be inserted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::ITERATOR ordered_vector<Key, Compare>::
|
||||
insert_nonunique(TYPENAME ordered_vector<Key, Compare>::ITERATOR position,
|
||||
const TYPENAME ordered_vector<Key, Compare>::VALUE_TYPE &key) {
|
||||
TAU_PROFILE("ordered_vector::insert_nonunique(iterator, const value_type &)", " ", TAU_USER);
|
||||
if (position != end()) {
|
||||
// If we're not inserting at the end, the element we're
|
||||
// inserting before should not lexicographically precede this one.
|
||||
if (_compare(*position, key)) {
|
||||
return insert_nonunique(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (position != begin()) {
|
||||
// If we're not inserting at the beginning, this element should
|
||||
// not lexicographically precede the one we're inserting after.
|
||||
if (_compare(key, *(position - 1))) {
|
||||
return insert_nonunique(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we may insert where the caller requested.
|
||||
ITERATOR result = _vector.insert(position, key);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::verify_list_unique
|
||||
// Access: Public
|
||||
// Description: Ensures that the indicated range of elements is
|
||||
// sorted correctly. Returns true if this is the case;
|
||||
// otherwise, returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
bool ordered_vector<Key, Compare>::
|
||||
verify_list_unique() const {
|
||||
TAU_PROFILE("ordered_vector::verify_list_unique()", " ", TAU_USER);
|
||||
if (!empty()) {
|
||||
CONST_ITERATOR prev = begin();
|
||||
CONST_ITERATOR i = begin();
|
||||
++i;
|
||||
while (i < end()) {
|
||||
bool ordered_correctly = _compare(*prev, *i);
|
||||
if (!ordered_correctly) {
|
||||
return true;
|
||||
}
|
||||
prev = i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::verify_list_nonunique
|
||||
// Access: Public
|
||||
// Description: Ensures that the indicated range of elements is
|
||||
// sorted correctly. Returns true if this is the case;
|
||||
// otherwise, returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
bool ordered_vector<Key, Compare>::
|
||||
verify_list_nonunique() const {
|
||||
TAU_PROFILE("ordered_vector::verify_list_nonunique()", " ", TAU_USER);
|
||||
if (!empty()) {
|
||||
CONST_ITERATOR prev = begin();
|
||||
CONST_ITERATOR i = begin();
|
||||
++i;
|
||||
while (i < end()) {
|
||||
bool ordered_correctly = !_compare(*i, *prev);
|
||||
if (!ordered_correctly) {
|
||||
return true;
|
||||
}
|
||||
prev = i;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_find_insert_position
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of
|
||||
// find_insert_position().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::ITERATOR ordered_vector<Key, Compare>::
|
||||
r_find_insert_position(TYPENAME ordered_vector<Key, Compare>::ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::ITERATOR last,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) {
|
||||
if (first == last) {
|
||||
// The list is empty; the insert position is the last of the list.
|
||||
return last;
|
||||
}
|
||||
|
||||
ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, last);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// Insert before the center.
|
||||
return r_find_insert_position(first, center, key);
|
||||
|
||||
} else {
|
||||
// Insert after the center.
|
||||
return r_find_insert_position(center + 1, last, key);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_find
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of find().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR ordered_vector<Key, Compare>::
|
||||
r_find(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR not_found,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return not_found;
|
||||
}
|
||||
|
||||
CONST_ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, last);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_find(first, center, not_found, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_find(center + 1, last, not_found, key);
|
||||
|
||||
} else {
|
||||
// Here it is!
|
||||
return center;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_find_particular
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of find_particular().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR ordered_vector<Key, Compare>::
|
||||
r_find_particular(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR not_found,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return not_found;
|
||||
}
|
||||
|
||||
CONST_ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, last);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_find_particular(first, center, not_found, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_find_particular(center + 1, last, not_found, key);
|
||||
|
||||
} else {
|
||||
// The center's sort matches the key's sort. It could be either
|
||||
// before or after the center. First try after.
|
||||
CONST_ITERATOR i = center;
|
||||
while (i < last && !_compare(key, *i)) {
|
||||
if ((*i) == key) {
|
||||
return i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
// No, try before.
|
||||
i = center;
|
||||
--i;
|
||||
while (i >= first && !_compare(key, *i)) {
|
||||
if ((*i) == key) {
|
||||
return i;
|
||||
}
|
||||
--i;
|
||||
}
|
||||
|
||||
// No such key!
|
||||
return not_found;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_count
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of count().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::SIZE_TYPE ordered_vector<Key, Compare>::
|
||||
r_count(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
typedef pair<TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR, TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR> pair_type;
|
||||
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return 0;
|
||||
}
|
||||
|
||||
CONST_ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, 0);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_count(first, center, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_count(center + 1, last, key);
|
||||
|
||||
} else {
|
||||
// The center matches the key; the range is here.
|
||||
size_type lower = r_count(first, center, key);
|
||||
size_type upper = r_count(center + 1, last, key);
|
||||
return lower + 1 + upper;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_lower_bound
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of lower_bound().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR ordered_vector<Key, Compare>::
|
||||
r_lower_bound(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return last;
|
||||
}
|
||||
|
||||
CONST_ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, last);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_lower_bound(first, center, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_lower_bound(center + 1, last, key);
|
||||
|
||||
} else {
|
||||
// The center matches the key; thus, the first element not less
|
||||
// than key is at or before the center.
|
||||
return r_lower_bound(first, center, key);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_upper_bound
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of upper_bound().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR ordered_vector<Key, Compare>::
|
||||
r_upper_bound(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return last;
|
||||
}
|
||||
|
||||
const_iterator center = first + (last - first) / 2;
|
||||
nassertr(center < last, last);
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_upper_bound(first, center, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_upper_bound(center + 1, last, key);
|
||||
|
||||
} else {
|
||||
// The center matches the key; thus, the first element greater
|
||||
// than key is after the center.
|
||||
return r_upper_bound(center + 1, last, key);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::r_equal_range
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of equal_range().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare>
|
||||
pair<TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR, TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR> ordered_vector<Key, Compare>::
|
||||
r_equal_range(TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR first,
|
||||
TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR last,
|
||||
const TYPENAME ordered_vector<Key, Compare>::KEY_TYPE &key) const {
|
||||
typedef pair<TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR, TYPENAME ordered_vector<Key, Compare>::CONST_ITERATOR> pair_type;
|
||||
|
||||
if (first == last) {
|
||||
// The list is empty; the key is not on the list.
|
||||
return pair_type(last, last);
|
||||
}
|
||||
|
||||
CONST_ITERATOR center = first + (last - first) / 2;
|
||||
nassertr(center < last, pair_type(last, last));
|
||||
|
||||
if (_compare(key, *center)) {
|
||||
// It must be before the center.
|
||||
return r_equal_range(first, center, key);
|
||||
|
||||
} else if (_compare(*center, key)) {
|
||||
// It must be after the center.
|
||||
return r_equal_range(center + 1, last, key);
|
||||
|
||||
} else {
|
||||
// The center matches the key; the range is here.
|
||||
CONST_ITERATOR lower = r_lower_bound(first, center, key);
|
||||
CONST_ITERATOR upper = r_upper_bound(center + 1, last, key);
|
||||
return pair_type(lower, upper);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user