David Rose 17 years ago
parent
commit
f965ed1f43
3 changed files with 570 additions and 0 deletions
  1. 69 0
      dtool/src/dtoolbase/pallocator.T
  2. 97 0
      panda/src/express/dcast.T
  3. 404 0
      panda/src/express/ordered_vector.T

+ 69 - 0
dtool/src/dtoolbase/pallocator.T

@@ -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
+}

+ 97 - 0
panda/src/express/dcast.T

@@ -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);
+}

+ 404 - 0
panda/src/express/ordered_vector.T

@@ -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);
+  }
+}