1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkBuffer.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkBuffer
17  * @brief   internal storage class used by vtkSOADataArrayTemplate,
18  * vtkAOSDataArrayTemplate, and others.
19  *
20  * vtkBuffer makes it easier to keep data pointers in vtkDataArray subclasses.
21  * This is an internal class and not intended for direct use expect when writing
22  * new types of vtkDataArray subclasses.
23 */
24 
25 #ifndef vtkBuffer_h
26 #define vtkBuffer_h
27 
28 #include "vtkObject.h"
29 #include "vtkObjectFactory.h" // New() implementation
30 
31 template <class ScalarTypeT>
32 class vtkBuffer : public vtkObject
33 {
34 public:
35   vtkTemplateTypeMacro(vtkBuffer<ScalarTypeT>, vtkObject)
36   typedef ScalarTypeT ScalarType;
37 
38   static vtkBuffer<ScalarTypeT>* New();
39 
40   /**
41    * Access the buffer as a scalar pointer.
42    */
GetBuffer()43   inline ScalarType* GetBuffer() { return this->Pointer; }
GetBuffer()44   inline const ScalarType* GetBuffer() const { return this->Pointer; }
45 
46   /**
47    * Set the memory buffer that this vtkBuffer object will manage. @a array
48    * is a pointer to the buffer data and @a size is the size of the buffer (in
49    * number of elements).
50    */
51   void SetBuffer(ScalarType* array, vtkIdType size);
52 
53   /**
54    * Set the free function to be used when releasing this object.
55    * If @a noFreeFunction is true, the buffer will not be freed when
56    * this vtkBuffer object is deleted or resize -- otherwise, @a deleteFunction
57    * will be called to free the buffer
58   **/
59   void SetFreeFunction(bool noFreeFunction, void(*deleteFunction)(void*)=free);
60 
61   /**
62    * Return the number of elements the current buffer can hold.
63    */
GetSize()64   inline vtkIdType GetSize() const { return this->Size; }
65 
66   /**
67    * Allocate a new buffer that holds @a size elements. Old data is not saved.
68    */
69   bool Allocate(vtkIdType size);
70 
71   /**
72    * Allocate a new buffer that holds @a newsize elements. Old data is
73    * preserved.
74    */
75   bool Reallocate(vtkIdType newsize);
76 
77 protected:
vtkBuffer()78   vtkBuffer()
79     : Pointer(nullptr),
80       Size(0),
81       DeleteFunction(free)
82   {
83   }
84 
~vtkBuffer()85   ~vtkBuffer() override
86   {
87     this->SetBuffer(nullptr, 0);
88   }
89 
90   ScalarType *Pointer;
91   vtkIdType Size;
92   void (*DeleteFunction)(void*);
93 
94 private:
95   vtkBuffer(const vtkBuffer&) = delete;
96   void operator=(const vtkBuffer&) = delete;
97 };
98 
99 template <class ScalarT>
New()100 inline vtkBuffer<ScalarT> *vtkBuffer<ScalarT>::New()
101 {
102   VTK_STANDARD_NEW_BODY(vtkBuffer<ScalarT>)
103 }
104 
105 //------------------------------------------------------------------------------
106 template <typename ScalarT>
SetBuffer(typename vtkBuffer<ScalarT>::ScalarType * array,vtkIdType size)107 void vtkBuffer<ScalarT>::SetBuffer(
108     typename vtkBuffer<ScalarT>::ScalarType *array, vtkIdType size) {
109   if (this->Pointer != array)
110   {
111     if(this->DeleteFunction)
112     {
113       this->DeleteFunction(this->Pointer);
114     }
115     this->Pointer = array;
116   }
117   this->Size = size;
118 }
119 //------------------------------------------------------------------------------
120 template <typename ScalarT>
SetFreeFunction(bool noFreeFunction,void (* deleteFunction)(void *))121 void vtkBuffer<ScalarT>::SetFreeFunction(bool noFreeFunction, void(*deleteFunction)(void*))
122 {
123   if(noFreeFunction)
124   {
125     this->DeleteFunction = nullptr;
126   }
127   else
128   {
129     this->DeleteFunction = deleteFunction;
130   }
131 }
132 
133 //------------------------------------------------------------------------------
134 template <typename ScalarT>
Allocate(vtkIdType size)135 bool vtkBuffer<ScalarT>::Allocate(vtkIdType size)
136 {
137   // release old memory.
138   this->SetBuffer(nullptr, 0);
139   if (size > 0)
140   {
141     ScalarType* newArray =
142         static_cast<ScalarType*>(malloc(size * sizeof(ScalarType)));
143     if (newArray)
144     {
145       this->SetBuffer(newArray, size);
146       this->DeleteFunction = free;
147       return true;
148     }
149     return false;
150   }
151   return true; // size == 0
152 }
153 
154 //------------------------------------------------------------------------------
155 template <typename ScalarT>
Reallocate(vtkIdType newsize)156 bool vtkBuffer<ScalarT>::Reallocate(vtkIdType newsize)
157 {
158   if (newsize == 0) { return this->Allocate(0); }
159 
160   if (this->Pointer && this->DeleteFunction != free)
161   {
162     ScalarType* newArray =
163         static_cast<ScalarType*>(malloc(newsize * sizeof(ScalarType)));
164     if (!newArray)
165     {
166       return false;
167     }
168     std::copy(this->Pointer, this->Pointer + std::min(this->Size, newsize),
169               newArray);
170     // now save the new array and release the old one too.
171     this->SetBuffer(newArray, newsize);
172     this->DeleteFunction = free;
173   }
174   else
175   {
176     // Try to reallocate with minimal memory usage and possibly avoid
177     // copying.
178     ScalarType* newArray = static_cast<ScalarType*>(
179           realloc(this->Pointer, newsize * sizeof(ScalarType)));
180     if (!newArray)
181     {
182       return false;
183     }
184     this->Pointer = newArray;
185     this->Size = newsize;
186   }
187   return true;
188 }
189 
190 #endif
191 // VTK-HeaderTest-Exclude: vtkBuffer.h
192