328 lines
13 KiB
C++
328 lines
13 KiB
C++
// Filename: ordered_vector.h
|
|
// Created by: drose (20Feb02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef ORDERED_VECTOR_H
|
|
#define ORDERED_VECTOR_H
|
|
#ifdef CPPPARSER // hack around this for interigate...
|
|
//****** HACK allert ***
|
|
// this code is intended to tell interigate to not expand this class definition past basic names
|
|
// It drops the interigate memory foot pront and user time by a bunch
|
|
// on pc cygwin from 3 minutes to 17 seconds ?? really need to explore interigate to figure out what is
|
|
// going on ..
|
|
//
|
|
template<class Key, class Compare = less<int> > class ov_multiset
|
|
{
|
|
};
|
|
|
|
template<class Key, class Compare = less<int> > class ov_set
|
|
{
|
|
};
|
|
|
|
template<class Key, class Compare = less<int> > class ordered_vector
|
|
{
|
|
};
|
|
|
|
#else // cppparser
|
|
|
|
|
|
#include "pandabase.h"
|
|
|
|
#include "pvector.h"
|
|
#include "pset.h"
|
|
#include "pnotify.h"
|
|
#include <algorithm>
|
|
|
|
// There are some inheritance issues with template classes and typedef
|
|
// names. Template classes that inherit typedef names from their base
|
|
// class, which is also a template class, may confuse the typedef
|
|
// names with globally scoped template names. In particular, the
|
|
// local "iterator" type is easily confused with the std::iterator
|
|
// template class.
|
|
|
|
// To work around this problem, as well as a problem in gcc 2.95.3
|
|
// with value_type etc. not inheriting properly (even though we
|
|
// explicitly typedef them in the derived class), we rename the
|
|
// questionable typedefs here so that they no longer conflict with the
|
|
// global template classes.
|
|
|
|
#define KEY_TYPE key_type_0
|
|
#define VALUE_TYPE value_type_0
|
|
#define REFERENCE reference_0
|
|
#define CONST_REFERENCE const_reference_0
|
|
#define KEY_COMPARE key_compare_0
|
|
#define VALUE_COMPARE value_compare_0
|
|
#define ITERATOR iterator_0
|
|
#define CONST_ITERATOR const_iterator_0
|
|
#define REVERSE_ITERATOR reverse_iterator_0
|
|
#define CONST_REVERSE_ITERATOR const_reverse_iterator_0
|
|
#define DIFFERENCE_TYPE difference_type_0
|
|
#define SIZE_TYPE size_type_0
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Class : ordered_vector
|
|
// Description : This template class presents an interface similar to
|
|
// the STL set or multiset (and ov_set and ov_multiset
|
|
// are implemented specifically, below), but it is
|
|
// implemented using a vector that is kept always in
|
|
// sorted order.
|
|
//
|
|
// In most cases, an ov_set or ov_multiset may be
|
|
// dropped in transparently in place of a set or
|
|
// multiset, but the implementation difference has a few
|
|
// implications:
|
|
//
|
|
// (1) The ov_multiset will maintain stability of order
|
|
// between elements that sort equally: they are stored
|
|
// in the order in which they were added, from back to
|
|
// front.
|
|
//
|
|
// (2) Insert and erase operations into the middle of
|
|
// the set can be slow, just as inserting into the
|
|
// middle of a vector can be slow. In fact, building up
|
|
// an ov_set by inserting elements one at a time is an
|
|
// n^2 operation. On the other hand, building up an
|
|
// ov_set by adding elements to the end, one at time, is
|
|
// somewhat faster than building up a traditional set;
|
|
// and you can even add unsorted elements with
|
|
// push_back() and then call sort() when you're done,
|
|
// for a log(n) operation.
|
|
//
|
|
// (3) Iterators may not be valid for the life of the
|
|
// ordered_vector. If the vector reallocates itself,
|
|
// all iterators are invalidated.
|
|
//
|
|
// (4) Random access into the set is easy with the []
|
|
// operator.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class Key, class Compare = less<Key> >
|
|
class ordered_vector {
|
|
private:
|
|
typedef pvector<Key> Vector;
|
|
|
|
public:
|
|
// Typedefs
|
|
typedef Key KEY_TYPE;
|
|
typedef Key VALUE_TYPE;
|
|
typedef Key &REFERENCE;
|
|
typedef const Key &CONST_REFERENCE;
|
|
typedef Compare KEY_COMPARE;
|
|
typedef Compare VALUE_COMPARE;
|
|
|
|
// Be careful when using the non-const iterators that you do not
|
|
// disturb the sorted order of the vector, or that if you do, you
|
|
// call sort() when you are done.
|
|
typedef TYPENAME Vector::iterator ITERATOR;
|
|
typedef TYPENAME Vector::const_iterator CONST_ITERATOR;
|
|
typedef TYPENAME Vector::reverse_iterator REVERSE_ITERATOR;
|
|
typedef TYPENAME Vector::const_reverse_iterator CONST_REVERSE_ITERATOR;
|
|
|
|
typedef TYPENAME Vector::difference_type DIFFERENCE_TYPE;
|
|
typedef TYPENAME Vector::size_type SIZE_TYPE;
|
|
|
|
// Since the #define symbols do not actually expand to the correct
|
|
// names, we have to re-typedef them so callers can reference them
|
|
// by their correct, lowercase names.
|
|
typedef KEY_TYPE key_type;
|
|
typedef VALUE_TYPE value_type;
|
|
typedef REFERENCE reference;
|
|
typedef CONST_REFERENCE const_reference;
|
|
typedef KEY_COMPARE key_compare;
|
|
typedef VALUE_COMPARE value_compare;
|
|
typedef ITERATOR iterator;
|
|
typedef CONST_ITERATOR const_iterator;
|
|
typedef REVERSE_ITERATOR reverse_iterator;
|
|
typedef CONST_REVERSE_ITERATOR const_reverse_iterator;
|
|
typedef DIFFERENCE_TYPE difference_type;
|
|
typedef SIZE_TYPE size_type;
|
|
|
|
public:
|
|
// Constructors. We don't implement the whole slew of STL
|
|
// constructors here yet.
|
|
INLINE ordered_vector(TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ordered_vector(const Compare &compare,
|
|
TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ordered_vector(const ordered_vector<Key, Compare> ©);
|
|
INLINE ordered_vector<Key, Compare> &operator = (const ordered_vector<Key, Compare> ©);
|
|
INLINE ~ordered_vector();
|
|
|
|
// Iterator access.
|
|
INLINE ITERATOR begin();
|
|
INLINE ITERATOR end();
|
|
INLINE REVERSE_ITERATOR rbegin();
|
|
INLINE REVERSE_ITERATOR rend();
|
|
|
|
INLINE CONST_ITERATOR begin() const;
|
|
INLINE CONST_ITERATOR end() const;
|
|
INLINE CONST_REVERSE_ITERATOR rbegin() const;
|
|
INLINE CONST_REVERSE_ITERATOR rend() const;
|
|
|
|
// Random access.
|
|
INLINE reference operator [] (SIZE_TYPE n);
|
|
INLINE const_reference operator [] (SIZE_TYPE n) const;
|
|
|
|
// Size information.
|
|
INLINE SIZE_TYPE size() const;
|
|
INLINE SIZE_TYPE max_size() const;
|
|
INLINE bool empty() const;
|
|
|
|
// Equivalence and lexicographical comparisons.
|
|
INLINE bool operator == (const ordered_vector<Key, Compare> &other) const;
|
|
INLINE bool operator != (const ordered_vector<Key, Compare> &other) const;
|
|
|
|
INLINE bool operator < (const ordered_vector<Key, Compare> &other) const;
|
|
INLINE bool operator > (const ordered_vector<Key, Compare> &other) const;
|
|
INLINE bool operator <= (const ordered_vector<Key, Compare> &other) const;
|
|
INLINE bool operator >= (const ordered_vector<Key, Compare> &other) const;
|
|
|
|
// Insert operations.
|
|
ITERATOR insert_unique(ITERATOR position, const VALUE_TYPE &key);
|
|
ITERATOR insert_nonunique(ITERATOR position, const VALUE_TYPE &key);
|
|
INLINE pair<ITERATOR, bool> insert_unique(const VALUE_TYPE &key);
|
|
INLINE ITERATOR insert_nonunique(const VALUE_TYPE &key);
|
|
INLINE ITERATOR insert_unverified(ITERATOR position, const VALUE_TYPE &key);
|
|
|
|
// Erase operations.
|
|
INLINE ITERATOR erase(ITERATOR position);
|
|
INLINE SIZE_TYPE erase(const KEY_TYPE &key);
|
|
INLINE void erase(ITERATOR first, ITERATOR last);
|
|
INLINE void clear();
|
|
|
|
// Find operations.
|
|
INLINE ITERATOR find(const KEY_TYPE &key);
|
|
INLINE CONST_ITERATOR find(const KEY_TYPE &key) const;
|
|
INLINE ITERATOR find_particular(const KEY_TYPE &key);
|
|
INLINE CONST_ITERATOR find_particular(const KEY_TYPE &key) const;
|
|
INLINE SIZE_TYPE count(const KEY_TYPE &key) const;
|
|
|
|
INLINE ITERATOR lower_bound(const KEY_TYPE &key);
|
|
INLINE CONST_ITERATOR lower_bound(const KEY_TYPE &key) const;
|
|
INLINE ITERATOR upper_bound(const KEY_TYPE &key);
|
|
INLINE CONST_ITERATOR upper_bound(const KEY_TYPE &key) const;
|
|
INLINE pair<ITERATOR, ITERATOR> equal_range(const KEY_TYPE &key);
|
|
INLINE pair<CONST_ITERATOR, CONST_ITERATOR> equal_range(const KEY_TYPE &key) const;
|
|
|
|
// Special operations.
|
|
INLINE void swap(ordered_vector<Key, Compare> &other);
|
|
INLINE void reserve(SIZE_TYPE n);
|
|
INLINE void sort_unique();
|
|
INLINE void sort_nonunique();
|
|
bool verify_list_unique() const;
|
|
bool verify_list_nonunique() const;
|
|
|
|
INLINE void push_back(const VALUE_TYPE &key);
|
|
INLINE void pop_back();
|
|
|
|
private:
|
|
INLINE ITERATOR nci(CONST_ITERATOR i);
|
|
INLINE ITERATOR find_insert_position(ITERATOR first, ITERATOR last,
|
|
const KEY_TYPE &key);
|
|
ITERATOR r_find_insert_position(ITERATOR first, ITERATOR last,
|
|
const KEY_TYPE &key);
|
|
CONST_ITERATOR r_find(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
CONST_ITERATOR not_found,
|
|
const KEY_TYPE &key) const;
|
|
CONST_ITERATOR r_find_particular(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
CONST_ITERATOR not_found,
|
|
const KEY_TYPE &key) const;
|
|
SIZE_TYPE r_count(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
const KEY_TYPE &key) const;
|
|
CONST_ITERATOR r_lower_bound(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
const KEY_TYPE &key) const;
|
|
CONST_ITERATOR r_upper_bound(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
const KEY_TYPE &key) const;
|
|
pair<CONST_ITERATOR, CONST_ITERATOR>
|
|
r_equal_range(CONST_ITERATOR first, CONST_ITERATOR last,
|
|
const KEY_TYPE &key) const;
|
|
|
|
// This function object is used in sort_unique(). It returns true
|
|
// if two consecutive sorted elements are equivalent.
|
|
class EquivalentTest {
|
|
public:
|
|
// For some reason, VC++ won't allow us to define these bodies
|
|
// outside the class; they must be defined here. The error
|
|
// message is C3206: "member functions of nested classes of a
|
|
// template class cannot be defined outside the class".
|
|
INLINE EquivalentTest(const Compare &compare) :
|
|
_compare(compare) { }
|
|
INLINE bool operator () (const KEY_TYPE &a, const KEY_TYPE &b) {
|
|
nassertr(!_compare(b, a), false);
|
|
return !_compare(a, b);
|
|
}
|
|
|
|
Compare _compare;
|
|
};
|
|
|
|
Compare _compare;
|
|
Vector _vector;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Class : ov_set
|
|
// Description : A specialization of ordered_vector that emulates a
|
|
// standard STL set: one copy of each element is
|
|
// allowed.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class Key, class Compare = less<Key> >
|
|
class ov_set : public ordered_vector<Key, Compare> {
|
|
public:
|
|
typedef TYPENAME ordered_vector<Key, Compare>::ITERATOR ITERATOR;
|
|
typedef TYPENAME ordered_vector<Key, Compare>::VALUE_TYPE VALUE_TYPE;
|
|
|
|
INLINE ov_set(TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ov_set(const Compare &compare,
|
|
TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ov_set(const ov_set<Key, Compare> ©);
|
|
INLINE ov_set<Key, Compare> &operator = (const ov_set<Key, Compare> ©);
|
|
|
|
INLINE ITERATOR insert(ITERATOR position, const VALUE_TYPE &key0);
|
|
INLINE pair<ITERATOR, bool> insert(const VALUE_TYPE &key0);
|
|
|
|
INLINE void sort();
|
|
INLINE bool verify_list() const;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Class : ov_multiset
|
|
// Description : A specialization of ordered_vector that emulates a
|
|
// standard STL set: many copies of each element are
|
|
// allowed.
|
|
////////////////////////////////////////////////////////////////////
|
|
template<class Key, class Compare = less<Key> >
|
|
class ov_multiset : public ordered_vector<Key, Compare> {
|
|
public:
|
|
typedef TYPENAME ordered_vector<Key, Compare>::ITERATOR ITERATOR;
|
|
typedef TYPENAME ordered_vector<Key, Compare>::VALUE_TYPE VALUE_TYPE;
|
|
|
|
INLINE ov_multiset(TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ov_multiset(const Compare &compare,
|
|
TypeHandle type_handle = ov_set_type_handle);
|
|
INLINE ov_multiset(const ov_multiset<Key, Compare> ©);
|
|
INLINE ov_multiset<Key, Compare> &operator = (const ov_multiset<Key, Compare> ©);
|
|
|
|
INLINE ITERATOR insert(ITERATOR position, const VALUE_TYPE &key);
|
|
INLINE ITERATOR insert(const VALUE_TYPE &key);
|
|
|
|
INLINE void sort();
|
|
INLINE bool verify_list() const;
|
|
};
|
|
|
|
#include "ordered_vector.I"
|
|
#include "ordered_vector.T"
|
|
#endif // cppparser ..
|
|
#endif
|