Forráskód Böngészése

add ordered_vector

David Rose 24 éve
szülő
commit
4104622e79

+ 18 - 2
panda/src/putil/Sources.pp

@@ -28,6 +28,7 @@
      lineStream.h lineStreamBuf.I lineStreamBuf.h \
      modifierButtons.I modifierButtons.h mouseButton.h \
      mouseData.h nameUniquifier.I nameUniquifier.h \
+     ordered_vector.h ordered_vector.I ordered_vector.T \
      pta_double.h \
      pta_float.h pta_int.h \
      string_utils.I string_utils.N string_utils.h \
@@ -48,7 +49,9 @@
      ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \
      keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \
      modifierButtons.cxx mouseButton.cxx mouseData.cxx \
-     nameUniquifier.cxx pta_double.cxx pta_float.cxx \
+     nameUniquifier.cxx \
+     ordered_vector.cxx \
+     pta_double.cxx pta_float.cxx \
      pta_int.cxx pta_ushort.cxx \
      string_utils.cxx timedCycle.cxx typedWritable.cxx \
      typedWritableReferenceCount.cxx updateSeq.cxx \
@@ -75,7 +78,9 @@
     ioPtaDatagramShort.h iterator_types.h keyboardButton.h lineStream.I \
     lineStream.h lineStreamBuf.I lineStreamBuf.h modifierButtons.I \
     modifierButtons.h mouseButton.h mouseData.h nameUniquifier.I \
-    nameUniquifier.h pta_double.h \
+    nameUniquifier.h \
+    ordered_vector.h ordered_vector.I ordered_vector.T \
+    pta_double.h \
     pta_float.h pta_int.h pta_ushort.h string_utils.I \
     string_utils.h timedCycle.I timedCycle.h typedWritable.I \
     typedWritable.h typedWritableReferenceCount.I \
@@ -134,3 +139,14 @@
     test_linestream.cxx
 
 #end test_bin_target
+
+#begin test_bin_target
+  #define TARGET test_ordered_vector
+
+  #define SOURCES \
+    test_ordered_vector.cxx
+
+  #define LOCAL_LIBS $[LOCAL_LIBS] putil
+  #define OTHER_LIBS $[OTHER_LIBS] pystub
+
+#end test_bin_target

+ 2 - 0
panda/src/putil/config_util.cxx

@@ -71,6 +71,8 @@ ConfigureFn(config_util) {
 
 //const bool track_memory_usage = config_util.GetBool("track-memory-usage", false);
 
+const bool paranoid_ordered_vector = config_util.GetBool("paranoid-ordered-vector", false);
+
 DSearchPath &
 get_model_path() {
   static DSearchPath *model_path = NULL;

+ 2 - 0
panda/src/putil/config_util.h

@@ -36,6 +36,8 @@ NotifyCategoryDecl(bam, EXPCL_PANDA, EXPTP_PANDA);
 
 //extern EXPCL_PANDA const bool track_memory_usage;
 
+extern EXPCL_PANDA const bool paranoid_ordered_vector;
+
 // These are functions instead of constant variables because they are
 // computed based on the concatenation of all appearances of the
 // corresponding variable in the config files.

+ 594 - 0
panda/src/putil/ordered_vector.I

@@ -0,0 +1,594 @@
+// Filename: ordered_vector.I
+// Created by:  drose (20Feb02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::
+ordered_vector(const Compare &compare) :
+  _compare(compare)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::
+ordered_vector(const ordered_vector<Key, Compare> &copy) :
+  _compare(copy._compare),
+  _vector(copy._vector)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare> &ordered_vector<Key, Compare>::
+operator = (const ordered_vector<Key, Compare> &copy) {
+  _compare = copy._compare;
+  _vector = copy._vector;
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::
+~ordered_vector() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::begin
+//       Access: Public
+//  Description: Returns the iterator that marks the first element in
+//               the ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+begin() {
+  return _vector.begin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::end
+//       Access: Public
+//  Description: Returns the iterator that marks the end of the
+//               ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+end() {
+  return _vector.end();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::rbegin
+//       Access: Public
+//  Description: Returns the iterator that marks the first element in
+//               the ordered vector, when viewed in reverse order.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::reverse_iterator ordered_vector<Key, Compare>::
+rbegin() {
+  return _vector.rbegin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::rend
+//       Access: Public
+//  Description: Returns the iterator that marks the end of the
+//               ordered vector, when viewed in reverse order.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::reverse_iterator ordered_vector<Key, Compare>::
+rend() {
+  return _vector.rend();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::begin
+//       Access: Public
+//  Description: Returns the iterator that marks the first element in
+//               the ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+begin() const {
+  return _vector.begin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::end
+//       Access: Public
+//  Description: Returns the iterator that marks the end of the
+//               ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+end() const {
+  return _vector.end();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::rbegin
+//       Access: Public
+//  Description: Returns the iterator that marks the first element in
+//               the ordered vector, when viewed in reverse order.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_reverse_iterator ordered_vector<Key, Compare>::
+rbegin() const {
+  return _vector.rbegin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::rend
+//       Access: Public
+//  Description: Returns the iterator that marks the end of the
+//               ordered vector, when viewed in reverse order.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_reverse_iterator ordered_vector<Key, Compare>::
+rend() const {
+  return _vector.rend();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::size
+//       Access: Public
+//  Description: Returns the number of elements in the ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::size_type ordered_vector<Key, Compare>::
+size() const {
+  return _vector.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::max_size
+//       Access: Public
+//  Description: Returns the maximum number of elements that can
+//               possibly be stored in an ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::size_type ordered_vector<Key, Compare>::
+max_size() const {
+  return _vector.max_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::empty
+//       Access: Public
+//  Description: Returns true if the ordered vector is empty, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+empty() const {
+  return _vector.max_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator == 
+//       Access: Public
+//  Description: Returns true if the two ordered vectors are
+//               memberwise equivalent, false otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator == (const ordered_vector<Key, Compare> &other) const {
+  return _vector == other._vector;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator != 
+//       Access: Public
+//  Description: Returns true if the two ordered vectors are not
+//               memberwise equivalent, false if they are.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator != (const ordered_vector<Key, Compare> &other) const {
+  return _vector != other._vector;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator <
+//       Access: Public
+//  Description: Returns true if this ordered vector sorts
+//               lexicographically before the other one, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator < (const ordered_vector<Key, Compare> &other) const {
+  return _vector < other._vector;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator >
+//       Access: Public
+//  Description: Returns true if this ordered vector sorts
+//               lexicographically after the other one, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator > (const ordered_vector<Key, Compare> &other) const {
+  return _vector > other._vector;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator <=
+//       Access: Public
+//  Description: Returns true if this ordered vector sorts
+//               lexicographically before the other one or is
+//               equivalent, false otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator <= (const ordered_vector<Key, Compare> &other) const {
+  return _vector <= other._vector;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::operator >=
+//       Access: Public
+//  Description: Returns true if this ordered vector sorts
+//               lexicographically after the other one or is
+//               equivalent, false otherwise.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+operator >= (const ordered_vector<Key, Compare> &other) const {
+  return _vector >= other._vector;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::insert
+//       Access: Public
+//  Description: Inserts the indicated key into the ordered vector, at
+//               the appropriate place.  If there are already elements
+//               sorting equivalent to the key in the vector, the new
+//               value is inserted following them.  The return value
+//               is the iterator referencing the new element.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+insert(const ordered_vector<Key, Compare>::value_type &key) {
+  iterator position = find_insert_position(begin(), end(), key);
+  nassertr(position >= begin() && position <= end(), end());
+
+  iterator result = _vector.insert(position, key);
+  verify_list();
+  return result;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::erase, with iterator
+//       Access: Public
+//  Description: Removes the element indicated by the given iterator,
+//               and returns the next sequential iterator.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+erase(ordered_vector<Key, Compare>::iterator position) {
+  size_type count = position - begin();
+  _vector.erase(position);
+  return begin() + count;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::erase, with key
+//       Access: Public
+//  Description: Removes all elements matching the indicated key;
+//               returns the number of elements removed.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::size_type ordered_vector<Key, Compare>::
+erase(const ordered_vector<Key, Compare>::key_type &key) {
+  pair<iterator, iterator> result = equal_range(key);
+  size_type count = result.second - result.first;
+  erase(result.first, result.second);
+  return count;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::erase, a range
+//       Access: Public
+//  Description: Removes all elements indicated by the given iterator
+//               range.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE void ordered_vector<Key, Compare>::
+erase(ordered_vector<Key, Compare>::iterator first,
+      ordered_vector<Key, Compare>::iterator last) {
+  _vector.erase(first, last);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::clear
+//       Access: Public
+//  Description: Removes all elements from the ordered vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE void ordered_vector<Key, Compare>::
+clear() {
+  _vector.erase(_vector.begin(), _vector.end());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::find
+//       Access: Public
+//  Description: Searches for an element with the indicated key and
+//               returns its iterator if it is found, or end() if it
+//               is not.  If there are multiple elements matching the
+//               key, the particular iterator returned is not defined.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+find(const ordered_vector<Key, Compare>::key_type &key) {
+  return (iterator)r_find(begin(), end(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::find
+//       Access: Public
+//  Description: Searches for an element with the indicated key and
+//               returns its iterator if it is found, or end() if it
+//               is not.  If there are multiple elements matching the
+//               key, the particular iterator returned is not defined.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+find(const ordered_vector<Key, Compare>::key_type &key) const {
+  return r_find(begin(), end(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::find_particular
+//       Access: Public
+//  Description: Searches for a particular element and returns its
+//               iterator if it is found, or end() if it is not.
+//
+//               First, the Compare function is used to narrow down
+//               the range of elements the element might be located
+//               within; then the element is compared elementwise, via
+//               ==, until the exact matching element is found.  If
+//               multiple matches exist within the vector, the
+//               particular iterator returned is not defined.
+//
+//               The assumption is that == implies !Compare(a, b) and
+//               !Compare(b, a), but not necessarily the converse.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+find_particular(const ordered_vector<Key, Compare>::key_type &key) {
+  return (iterator)r_find_particular(begin(), end(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::find_particular
+//       Access: Public
+//  Description: Searches for a particular element and returns its
+//               iterator if it is found, or end() if it is not.
+//
+//               First, the Compare function is used to narrow down
+//               the range of elements the element might be located
+//               within; then the element is compared elementwise, via
+//               ==, until the exact matching element is found.  If
+//               multiple matches exist within the vector, the
+//               particular iterator returned is not defined./
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+find_particular(const ordered_vector<Key, Compare>::key_type &key) const {
+  return r_find_particular(begin(), end(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::count
+//       Access: Public
+//  Description: Returns the number of elements that sort equivalent
+//               to the key that are in the vector.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::size_type ordered_vector<Key, Compare>::
+count(const key_type &key) const {
+  return r_count(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::lower_bound
+//       Access: Public
+//  Description: Returns the iterator for the first element not less
+//               than key, or end() if all elements are less than key.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+lower_bound(const ordered_vector<Key, Compare>::key_type &key) {
+  return (iterator)r_lower_bound(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::lower_bound
+//       Access: Public
+//  Description: Returns the iterator for the first element not less
+//               than key, or end() if all elements are less than key.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+lower_bound(const ordered_vector<Key, Compare>::key_type &key) const {
+  return r_lower_bound(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::upper_bound
+//       Access: Public
+//  Description: Returns the iterator for the first element greater
+//               than key, or end() if no element is greater than
+//               key.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+upper_bound(const ordered_vector<Key, Compare>::key_type &key) {
+  return (iterator)r_upper_bound(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::upper_bound
+//       Access: Public
+//  Description: Returns the iterator for the first element greater
+//               than key, or end() if no element is greater than
+//               key.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+upper_bound(const ordered_vector<Key, Compare>::key_type &key) const {
+  return r_upper_bound(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::equal_range
+//       Access: Public
+//  Description: Returns the pair (lower_bound(key), upper_bound(key)).
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE pair<ordered_vector<Key, Compare>::iterator, ordered_vector<Key, Compare>::iterator> ordered_vector<Key, Compare>::
+equal_range(const ordered_vector<Key, Compare>::key_type &key) {
+  pair<ordered_vector<Key, Compare>::const_iterator, ordered_vector<Key, Compare>::const_iterator> result;
+  result = r_equal_range(begin(), end(), key);
+  return pair<ordered_vector<Key, Compare>::iterator, ordered_vector<Key, Compare>::iterator>((iterator)result.first, (iterator)result.second);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::equal_range
+//       Access: Public
+//  Description: Returns the pair (lower_bound(key), upper_bound(key)).
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE pair<ordered_vector<Key, Compare>::const_iterator, ordered_vector<Key, Compare>::const_iterator> ordered_vector<Key, Compare>::
+equal_range(const ordered_vector<Key, Compare>::key_type &key) const {
+  return r_equal_range(begin(), end(), key);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::swap
+//       Access: Public
+//  Description: Exchanges the contents of this vector and the other
+//               vector, in constant time (e.g., with a pointer swap).
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE void ordered_vector<Key, Compare>::
+swap(ordered_vector<Key, Compare> &copy) {
+  _vector.swap(copy._vector);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::reserve
+//       Access: Public
+//  Description: Informs the vector of a planned change in size;
+//               ensures that the capacity of the vector is greater
+//               than or equal to n.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE void ordered_vector<Key, Compare>::
+reserve(ordered_vector<Key, Compare>::size_type n) {
+  _vector.reserve(n);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::sort
+//       Access: Public
+//  Description: Ensures that the vector is properly sorted after a
+//               potentially damaging operation.  This should not
+//               normally need to be called, unless the user has
+//               written to the vector using the non-const iterators.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE void ordered_vector<Key, Compare>::
+sort() {
+  ::sort(begin(), end(), _compare);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::find_insert_position
+//       Access: Private
+//  Description: Searches for the appropriate place in the ordered
+//               vector to insert the indicated key, and returns the
+//               corresponding iterator.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+find_insert_position(ordered_vector<Key, Compare>::iterator first,
+                     ordered_vector<Key, Compare>::iterator last,
+                     const ordered_vector<Key, Compare>::key_type &key) {
+  iterator result = r_find_insert_position(first, last, key);
+
+#ifndef NDEBUG
+  // Verify the result.
+  if (paranoid_ordered_vector) {
+    // If there is a node before the indicated position, this node
+    // must not precede it lexicograpically.
+    if (first < result) {
+      nassertr(!_compare(key, *(result - 1)), result);
+    }
+    // If there is a node after the indicated position, it must not
+    // precede this node lexicographically.
+    if (result < last) {
+      nassertr(!_compare(*(result), key), result);
+    }
+  }
+#endif
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::verify_list
+//       Access: Private
+//  Description: Ensures that the indicated range of elements is
+//               sorted correctly, if paranoid_ordered_vector is set.
+//               Generates an assertion failure (and returns false) if
+//               this is not the case; otherwise, returns true.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+INLINE bool ordered_vector<Key, Compare>::
+verify_list() {
+#ifndef NDEBUG
+  if (paranoid_ordered_vector) {
+    return verify_list_impl(begin(), end());
+  }
+#endif
+  return true;
+}

+ 331 - 0
panda/src/putil/ordered_vector.T

@@ -0,0 +1,331 @@
+// Filename: ordered_vector.T
+// Created by:  drose (20Feb02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::insert
+//       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.
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+insert(ordered_vector<Key, Compare>::iterator position, 
+       const ordered_vector<Key, Compare>::value_type &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(key);
+    }
+  }
+
+  if (position != end()) {
+    // If we're not inserting at the beginning, the element we're
+    // inserting before should not lexicographically precede this one.
+    if (_compare(*position, key)) {
+      return insert(key);
+    }
+  }
+
+  // Otherwise, we may insert where the caller requested.
+  iterator result = _vector.insert(position, key);
+  verify_list();
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::r_find_insert_position
+//       Access: Private
+//  Description: The recursive implementation of
+//               find_insert_position().
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+ordered_vector<Key, Compare>::iterator ordered_vector<Key, Compare>::
+r_find_insert_position(ordered_vector<Key, Compare>::iterator first,
+                       ordered_vector<Key, Compare>::iterator last,
+                       const 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>
+ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+r_find(ordered_vector<Key, Compare>::const_iterator first,
+       ordered_vector<Key, Compare>::const_iterator last,
+       ordered_vector<Key, Compare>::const_iterator not_found,
+       const 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>
+ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+r_find_particular(ordered_vector<Key, Compare>::const_iterator first,
+                  ordered_vector<Key, Compare>::const_iterator last,
+                  ordered_vector<Key, Compare>::const_iterator not_found,
+                  const 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>
+ordered_vector<Key, Compare>::size_type ordered_vector<Key, Compare>::
+r_count(ordered_vector<Key, Compare>::const_iterator first,
+        ordered_vector<Key, Compare>::const_iterator last,
+        const ordered_vector<Key, Compare>::key_type &key) const {
+  typedef pair<ordered_vector<Key, Compare>::const_iterator, 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>
+ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+r_lower_bound(ordered_vector<Key, Compare>::const_iterator first,
+              ordered_vector<Key, Compare>::const_iterator last,
+              const 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>
+ordered_vector<Key, Compare>::const_iterator ordered_vector<Key, Compare>::
+r_upper_bound(ordered_vector<Key, Compare>::const_iterator first,
+              ordered_vector<Key, Compare>::const_iterator last,
+              const 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<ordered_vector<Key, Compare>::const_iterator, ordered_vector<Key, Compare>::const_iterator> ordered_vector<Key, Compare>::
+r_equal_range(ordered_vector<Key, Compare>::const_iterator first,
+              ordered_vector<Key, Compare>::const_iterator last,
+              const ordered_vector<Key, Compare>::key_type &key) const {
+  typedef pair<ordered_vector<Key, Compare>::const_iterator, 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);
+  }
+}
+
+#ifndef NDEBUG
+////////////////////////////////////////////////////////////////////
+//     Function: ordered_vector::verify_list_impl
+//       Access: Private
+//  Description: The non-inline implementation of verify_list().
+////////////////////////////////////////////////////////////////////
+template<class Key, class Compare>
+bool ordered_vector<Key, Compare>::
+verify_list_impl(ordered_vector<Key, Compare>::iterator first, 
+                 ordered_vector<Key, Compare>::iterator last) {
+  if (first < last) {
+    iterator prev = first;
+    iterator i = first;
+    ++i;
+    while (i < last) {
+      bool ordered_correctly = !_compare(*i, *prev);
+      nassertr(ordered_correctly, false);
+      prev = i;
+      ++i;
+    }
+  }
+  return true;
+}
+#endif  // NDEBUG

+ 19 - 0
panda/src/putil/ordered_vector.cxx

@@ -0,0 +1,19 @@
+// Filename: ordered_vector.cxx
+// Created by:  drose (20Feb02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ordered_vector.h"

+ 160 - 0
panda/src/putil/ordered_vector.h

@@ -0,0 +1,160 @@
+// Filename: ordered_vector.h
+// Created by:  drose (20Feb02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ORDERED_VECTOR_H
+#define ORDERED_VECTOR_H
+
+#include "pandabase.h"
+#include "config_util.h"
+
+#include "pvector.h"
+#include "pset.h"
+#include <algorithm>
+
+////////////////////////////////////////////////////////////////////
+//       Class : ordered_vector
+// Description : This template class presents an interface similar to
+//               the STL multiset, but it is implemented using a vector
+//               that is kept always in sorted order.
+//
+//               This allows the ordered_vector to maintain stability
+//               of order between elements that sort equally: they are
+//               stored in the order in which they were added, from
+//               back to front.
+////////////////////////////////////////////////////////////////////
+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 Vector::iterator iterator;
+  typedef Vector::const_iterator const_iterator;
+  typedef Vector::reverse_iterator reverse_iterator;
+  typedef Vector::const_reverse_iterator const_reverse_iterator;
+
+  typedef Vector::difference_type difference_type;
+  typedef Vector::size_type size_type;
+
+public:
+  // Constructors.  We don't implement the whole slew of STL
+  // constructors here yet.
+  INLINE ordered_vector(const Compare &compare = Compare());
+  INLINE ordered_vector(const ordered_vector<Key, Compare> &copy);
+  INLINE ordered_vector<Key, Compare> &operator = (const ordered_vector<Key, Compare> &copy);
+  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;
+
+  // 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(iterator position, const value_type &key);
+  INLINE iterator insert(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();
+
+private:
+  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;
+  INLINE bool verify_list();
+
+#ifndef NDEBUG
+  bool verify_list_impl(iterator first, iterator last);
+#endif
+
+  Compare _compare;
+  Vector _vector;
+};
+
+#include "ordered_vector.I"
+#include "ordered_vector.T"
+
+#endif

+ 1 - 0
panda/src/putil/putil_composite2.cxx

@@ -1,5 +1,6 @@
 
 #include "nameUniquifier.cxx"
+#include "ordered_vector.cxx"
 #include "pta_double.cxx"
 #include "pta_float.cxx"
 #include "pta_int.cxx"

+ 84 - 0
panda/src/putil/test_ordered_vector.cxx

@@ -0,0 +1,84 @@
+// Filename: test_ordered_vector.cxx
+// Created by:  drose (20Feb02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ordered_vector.h"
+
+typedef ordered_vector<int> myvec;
+
+void
+search(myvec &v, int element) {
+  pair<myvec::const_iterator, myvec::const_iterator> result;
+  
+  result = v.equal_range(element);
+  size_t count = v.count(element);
+
+  cerr << element << " bounded by " << result.first - v.begin() << " and " 
+       << result.second - v.begin() << "; " << count << " total.\n";
+}
+
+int
+main(int argc, char *argv[]) {
+  myvec a, b;
+
+  myvec::iterator mi;
+  mi = a.insert(a.end(), 3);
+  mi = a.insert(mi, 5);
+  mi = a.insert(mi, 4);
+  mi = a.insert(mi, 4);
+  mi = a.insert(mi, 2);
+  mi = a.insert(mi, 5);
+  mi = a.insert(mi, 2);
+
+  a.swap(b);
+
+  cerr << b.size() << " elements:\n";
+
+  myvec::iterator bi;
+  for (bi = b.begin(); bi != b.end(); ++bi) {
+    cerr << *bi << " ";
+  }
+  cerr << "\n";
+
+  search(b, 1);
+  search(b, 2);
+  search(b, 3);
+  search(b, 4);
+  search(b, 5);
+  search(b, 6);
+
+  cerr << "Removing 4:\n";
+  size_t count = b.erase(4);
+  cerr << "Removed " << count << "\n";
+
+
+  cerr << b.size() << " elements:\n";
+
+  for (bi = b.begin(); bi != b.end(); ++bi) {
+    cerr << *bi << " ";
+  }
+  cerr << "\n";
+
+  search(b, 1);
+  search(b, 2);
+  search(b, 3);
+  search(b, 4);
+  search(b, 5);
+  search(b, 6);
+
+  return (0);
+}