385 lines
16 KiB
C++
385 lines
16 KiB
C++
/**
|
|
* 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."
|
|
*
|
|
* @file pointerToArray.h
|
|
* @author drose
|
|
* @date 1999-01-14
|
|
*/
|
|
|
|
#ifndef POINTERTOARRAY_H
|
|
#define POINTERTOARRAY_H
|
|
|
|
/*
|
|
* This file defines the classes PointerToArray and ConstPointerToArray (and
|
|
* their abbreviations, PTA and CPTA), which are extensions to the PointerTo
|
|
* class that support reference-counted arrays.
|
|
*
|
|
* You may think of a PointerToArray as the same thing as a traditional
|
|
* C-style array. However, it actually stores a pointer to an STL vector,
|
|
* which is then reference-counted. Thus, most vector operations may be
|
|
* applied directly to a PointerToArray object, including dynamic resizing via
|
|
* push_back() and pop_back().
|
|
*
|
|
* Unlike the PointerTo class, the PointerToArray may store pointers to any
|
|
* kind of object, not just those derived from ReferenceCount.
|
|
*
|
|
* Like PointerTo and ConstPointerTo, the macro abbreviations PTA and CPTA are
|
|
* defined for convenience.
|
|
*
|
|
* Some examples of syntax: instead of:
|
|
*
|
|
* PTA(int) array(10); int *array = new int[10];
|
|
* memset(array, 0, sizeof(int) * 10); memset(array, 0, sizeof(int) * 10);
|
|
* array[i] = array[i+1]; array[i] = array[i+1];
|
|
* num_elements = array.size(); (no equivalent)
|
|
*
|
|
* PTA(int) copy = array; int *copy = array;
|
|
*
|
|
* Note that in the above example, unlike an STL vector (but like a C-style
|
|
* array), assigning a PointerToArray object from another simply copies the
|
|
* pointer, and does not copy individual elements. (Of course, reference
|
|
* counts are adjusted appropriately.) If you actually wanted an
|
|
* element-by-element copy of the array, you would do this:
|
|
*
|
|
* PTA(int) copy(0); // Create a pointer to an empty vector.
|
|
* copy.v() = array.v(); // v() is the STL vector itself.
|
|
*
|
|
* The (0) parameter to the constructor in the above example is crucial. When
|
|
* a numeric length parameter, such as zero, is given to the constructor, it
|
|
* means to define a new STL vector with that number of elements initially in
|
|
* it. If no parameter is given, on the other hand, it means the
|
|
* PointerToArray should point to nothing--no STL vector is created. This is
|
|
* equivalent to a C array that points to NULL.
|
|
*/
|
|
|
|
#include "pandabase.h"
|
|
|
|
#include "pointerToArrayBase.h"
|
|
|
|
#if (defined(WIN32_VC) || defined(WIN64_VC)) && !defined(__INTEL_COMPILER)
|
|
// disable mysterious MSVC warning for static inline PTA::empty_array method
|
|
// need to chk if vc 7.0 still has this problem, would like to keep it enabled
|
|
#pragma warning (disable : 4506)
|
|
#endif
|
|
|
|
template <class Element>
|
|
class ConstPointerToArray;
|
|
|
|
/**
|
|
* A special kind of PointerTo that stores an array of the indicated element
|
|
* type, instead of a single element. This is actually implemented as an STL
|
|
* vector, using the RefCountObj class to wrap it up with a reference count.
|
|
*
|
|
* We actually inherit from NodeRefCountObj these days, which adds node_ref()
|
|
* and node_unref() to the standard ref() and unref(). This is particularly
|
|
* useful for GeomVertexArrayData; other classes may or may not find this
|
|
* additional counter useful, but since it adds relatively little overhead
|
|
* (compared with what is presumably a largish array), we go ahead and add it
|
|
* here, even though it is inherited by many different parts of the system
|
|
* that may not use it.
|
|
*/
|
|
template <class Element>
|
|
class PointerToArray : public PointerToArrayBase<Element> {
|
|
public:
|
|
// By hiding this template from interrogate, we would improve compile-time
|
|
// speed and memory utilization. However, we do want to export a minimal
|
|
// subset of this class. So we define just the exportable interface here.
|
|
#ifdef CPPPARSER
|
|
PUBLISHED:
|
|
typedef typename pvector<Element>::size_type size_type;
|
|
INLINE PointerToArray(TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE static PointerToArray<Element> empty_array(size_type n, TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE PointerToArray(const PointerToArray<Element> ©);
|
|
|
|
EXTENSION(PointerToArray(PyObject *self, PyObject *source));
|
|
|
|
INLINE void clear();
|
|
|
|
INLINE size_type size() const;
|
|
INLINE void push_back(const Element &x);
|
|
INLINE void pop_back();
|
|
INLINE const Element &get_element(size_type n) const;
|
|
INLINE void set_element(size_type n, const Element &value);
|
|
EXTENSION(const Element &__getitem__(size_type n) const);
|
|
EXTENSION(void __setitem__(size_type n, const Element &value));
|
|
EXTENSION(PyObject *get_data() const);
|
|
EXTENSION(void set_data(PyObject *data));
|
|
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
|
INLINE void set_subdata(size_type n, size_type count, const std::string &data);
|
|
INLINE int get_ref_count() const;
|
|
INLINE int get_node_ref_count() const;
|
|
|
|
INLINE size_t count(const Element &) const;
|
|
|
|
#ifdef HAVE_PYTHON
|
|
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags));
|
|
EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
|
|
#endif
|
|
|
|
#else // CPPPARSER
|
|
// This is the actual, complete interface.
|
|
typedef typename PointerToArrayBase<Element>::To To;
|
|
typedef typename pvector<Element>::value_type value_type;
|
|
typedef typename pvector<Element>::reference reference;
|
|
typedef typename pvector<Element>::const_reference const_reference;
|
|
typedef typename pvector<Element>::iterator iterator;
|
|
typedef typename pvector<Element>::const_iterator const_iterator;
|
|
typedef typename pvector<Element>::reverse_iterator reverse_iterator;
|
|
typedef typename pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
|
typedef typename pvector<Element>::difference_type difference_type;
|
|
typedef typename pvector<Element>::size_type size_type;
|
|
|
|
public:
|
|
INLINE PointerToArray(TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE static PointerToArray<Element> empty_array(size_type n, TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE PointerToArray(const Element *begin, const Element *end, TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE PointerToArray(const PointerToArray<Element> ©);
|
|
INLINE PointerToArray(PointerToArray<Element> &&from) noexcept;
|
|
INLINE explicit PointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
|
|
|
|
public:
|
|
// Duplicating the interface of vector. The following member functions are
|
|
// all const, because they do not reassign the pointer--they operate only
|
|
// within the vector itself, which is non-const in this class.
|
|
|
|
INLINE iterator begin() const;
|
|
INLINE iterator end() const;
|
|
INLINE typename PointerToArray<Element>::reverse_iterator rbegin() const;
|
|
INLINE typename PointerToArray<Element>::reverse_iterator rend() const;
|
|
|
|
// Equality and comparison operators are pointerwise for PointerToArrays,
|
|
// not elementwise as in vector.
|
|
INLINE size_type size() const;
|
|
INLINE size_type max_size() const;
|
|
INLINE bool empty() const;
|
|
|
|
INLINE void clear();
|
|
|
|
// Functions specific to vectors.
|
|
INLINE void reserve(size_type n);
|
|
INLINE void resize(size_type n);
|
|
INLINE size_type capacity() const;
|
|
INLINE reference front() const;
|
|
INLINE reference back() const;
|
|
INLINE iterator insert(iterator position, const Element &x);
|
|
INLINE void insert(iterator position, size_type n, const Element &x);
|
|
|
|
// We don't define the insert() method that accepts a pair of iterators to
|
|
// copy from. That's problematic because of the whole member template
|
|
// thing. If you really need this, use pta.v().insert(...); if you're doing
|
|
// this on a vector that has to be exported from the DLL, you should use
|
|
// insert_into_vector(pta.v(), ...).
|
|
|
|
INLINE void erase(iterator position);
|
|
INLINE void erase(iterator first, iterator last);
|
|
|
|
#if !defined(WIN32_VC) && !defined (WIN64_VC)
|
|
INLINE reference operator [](size_type n) const;
|
|
INLINE reference operator [](int n) const;
|
|
#endif
|
|
|
|
INLINE void push_back(const Element &x);
|
|
INLINE void pop_back();
|
|
INLINE void make_empty();
|
|
|
|
INLINE operator Element *() const;
|
|
INLINE Element *p() const;
|
|
INLINE pvector<Element> &v() const;
|
|
INLINE ReferenceCountedVector<Element> *v0() const;
|
|
|
|
// Methods to help out Python and other high-level languages.
|
|
INLINE const Element &get_element(size_type n) const;
|
|
INLINE void set_element(size_type n, const Element &value);
|
|
INLINE std::string get_data() const;
|
|
INLINE void set_data(const std::string &data);
|
|
INLINE std::string get_subdata(size_type n, size_type count) const;
|
|
INLINE void set_subdata(size_type n, size_type count, const std::string &data);
|
|
|
|
// These functions are only to be used in Reading through BamReader. They
|
|
// are designed to work in pairs, so that you register what is returned by
|
|
// get_void_ptr with BamReader and when you are setting another PTA with
|
|
// what is returned by BamReader, you set it with set_void_ptr. If you used
|
|
// the provided macro of READ_PTA, this is done for you. So you should
|
|
// never call these functions directly
|
|
INLINE void *get_void_ptr() const;
|
|
INLINE void set_void_ptr(void* p);
|
|
|
|
INLINE int get_ref_count() const;
|
|
INLINE void ref() const;
|
|
INLINE bool unref() const;
|
|
|
|
INLINE int get_node_ref_count() const;
|
|
INLINE void node_ref() const;
|
|
INLINE bool node_unref() const;
|
|
|
|
INLINE size_t count(const Element &) const;
|
|
|
|
#endif // CPPPARSER
|
|
|
|
public:
|
|
// Reassignment is by pointer, not memberwise as with a vector.
|
|
INLINE PointerToArray<Element> &
|
|
operator = (ReferenceCountedVector<Element> *ptr);
|
|
INLINE PointerToArray<Element> &
|
|
operator = (const PointerToArray<Element> ©);
|
|
INLINE PointerToArray<Element> &
|
|
operator = (PointerToArray<Element> &&from) noexcept;
|
|
|
|
private:
|
|
TypeHandle _type_handle;
|
|
|
|
// This static empty array is kept around just so we can return something
|
|
// meaningful when begin() or end() is called and we have a NULL pointer.
|
|
// It might not be shared properly between different .so's, since it's a
|
|
// static member of a template class, but we don't really care.
|
|
static pvector<Element> _empty_array;
|
|
|
|
friend class ConstPointerToArray<Element>;
|
|
};
|
|
|
|
/**
|
|
* Similar to PointerToArray, except that its contents may not be modified.
|
|
*/
|
|
template <class Element>
|
|
class ConstPointerToArray : public PointerToArrayBase<Element> {
|
|
public:
|
|
INLINE ConstPointerToArray(TypeHandle type_handle = get_type_handle(Element));
|
|
|
|
// By hiding this template from interrogate, we would improve compile-time
|
|
// speed and memory utilization. However, we do want to export a minimal
|
|
// subset of this class. So we define just the exportable interface here.
|
|
#ifdef CPPPARSER
|
|
PUBLISHED:
|
|
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
|
INLINE ConstPointerToArray(const ConstPointerToArray<Element> ©);
|
|
|
|
INLINE void clear();
|
|
|
|
typedef typename pvector<Element>::size_type size_type;
|
|
INLINE size_type size() const;
|
|
INLINE const Element &get_element(size_type n) const;
|
|
EXTENSION(const Element &__getitem__(size_type n) const);
|
|
EXTENSION(PyObject *get_data() const);
|
|
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
|
INLINE int get_ref_count() const;
|
|
INLINE int get_node_ref_count() const;
|
|
|
|
INLINE size_t count(const Element &) const;
|
|
|
|
#ifdef HAVE_PYTHON
|
|
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
|
EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
|
|
#endif
|
|
|
|
#else // CPPPARSER
|
|
// This is the actual, complete interface.
|
|
typedef typename PointerToArrayBase<Element>::To To;
|
|
typedef typename pvector<Element>::value_type value_type;
|
|
typedef typename pvector<Element>::const_reference reference;
|
|
typedef typename pvector<Element>::const_reference const_reference;
|
|
typedef typename pvector<Element>::const_iterator iterator;
|
|
typedef typename pvector<Element>::const_iterator const_iterator;
|
|
#if defined(WIN32_VC) || defined(WIN64_VC)
|
|
// VC++ seems to break the const_reverse_iterator definition somehow.
|
|
typedef typename pvector<Element>::reverse_iterator reverse_iterator;
|
|
#else
|
|
typedef typename pvector<Element>::const_reverse_iterator reverse_iterator;
|
|
#endif
|
|
typedef typename pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
|
typedef typename pvector<Element>::difference_type difference_type;
|
|
typedef typename pvector<Element>::size_type size_type;
|
|
|
|
INLINE ConstPointerToArray(const Element *begin, const Element *end, TypeHandle type_handle = get_type_handle(Element));
|
|
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
|
INLINE ConstPointerToArray(const ConstPointerToArray<Element> ©);
|
|
INLINE ConstPointerToArray(PointerToArray<Element> &&from) noexcept;
|
|
INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) noexcept;
|
|
INLINE explicit ConstPointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
|
|
|
|
// Duplicating the interface of vector.
|
|
|
|
INLINE iterator begin() const;
|
|
INLINE iterator end() const;
|
|
INLINE typename ConstPointerToArray<Element>::reverse_iterator rbegin() const;
|
|
INLINE typename ConstPointerToArray<Element>::reverse_iterator rend() const;
|
|
|
|
// Equality and comparison operators are pointerwise for PointerToArrays,
|
|
// not elementwise as in vector.
|
|
|
|
INLINE size_type size() const;
|
|
INLINE size_type max_size() const;
|
|
INLINE bool empty() const;
|
|
|
|
INLINE void clear();
|
|
|
|
// Functions specific to vectors.
|
|
INLINE size_type capacity() const;
|
|
INLINE reference front() const;
|
|
INLINE reference back() const;
|
|
|
|
#if !defined(WIN32_VC) && !defined(WIN64_VC)
|
|
INLINE reference operator [](size_type n) const;
|
|
INLINE reference operator [](int n) const;
|
|
#endif
|
|
|
|
INLINE operator const Element *() const;
|
|
INLINE const Element *p() const;
|
|
INLINE const pvector<Element> &v() const;
|
|
INLINE const ReferenceCountedVector<Element> *v0() const;
|
|
INLINE PointerToArray<Element> cast_non_const() const;
|
|
|
|
// Methods to help out Python and other high-level languages.
|
|
INLINE const Element &get_element(size_type n) const;
|
|
INLINE std::string get_data() const;
|
|
INLINE std::string get_subdata(size_type n, size_type count) const;
|
|
|
|
INLINE int get_ref_count() const;
|
|
INLINE void ref() const;
|
|
INLINE bool unref() const;
|
|
|
|
INLINE int get_node_ref_count() const;
|
|
INLINE void node_ref() const;
|
|
INLINE bool node_unref() const;
|
|
|
|
INLINE size_t count(const Element &) const;
|
|
|
|
#endif // CPPPARSER
|
|
|
|
public:
|
|
// Reassignment is by pointer, not memberwise as with a vector.
|
|
INLINE ConstPointerToArray<Element> &
|
|
operator = (ReferenceCountedVector<Element> *ptr);
|
|
INLINE ConstPointerToArray<Element> &
|
|
operator = (const PointerToArray<Element> ©);
|
|
INLINE ConstPointerToArray<Element> &
|
|
operator = (const ConstPointerToArray<Element> ©);
|
|
INLINE ConstPointerToArray<Element> &
|
|
operator = (PointerToArray<Element> &&from) noexcept;
|
|
INLINE ConstPointerToArray<Element> &
|
|
operator = (ConstPointerToArray<Element> &&from) noexcept;
|
|
|
|
private:
|
|
TypeHandle _type_handle;
|
|
|
|
// This static empty array is kept around just so we can return something
|
|
// meangful when begin() or end() is called and we have a NULL pointer. It
|
|
// might not be shared properly between different .so's, since it's a static
|
|
// member of a template class, but we don't really care.
|
|
static pvector<Element> _empty_array;
|
|
|
|
friend class PointerToArray<Element>;
|
|
};
|
|
|
|
// And the brevity macros.
|
|
#define PTA(type) PointerToArray< type >
|
|
#define CPTA(type) ConstPointerToArray< type >
|
|
|
|
#include "pointerToArray.I"
|
|
|
|
#endif // HAVE_POINTERTOARRAY_H
|