1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkAOSDataArrayTemplate.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   vtkAOSDataArrayTemplate
17  * @brief   Array-Of-Structs implementation of
18  * vtkGenericDataArray.
19  *
20  *
21  * vtkGenericDataArray specialization that stores data array in the traditional
22  * VTK memory layout where a 3 component is stored in contiguous memory as
23  * \c A1A2A3B1B2B3C1C2C3 ... where A,B,C,... are tuples.
24  *
25  * This replaces vtkDataArrayTemplate.
26  *
27  * @sa
28  * vtkGenericDataArray vtkSOADataArrayTemplate
29 */
30 
31 #ifndef vtkAOSDataArrayTemplate_h
32 #define vtkAOSDataArrayTemplate_h
33 
34 #include "vtkCommonCoreModule.h" // For export macro
35 #include "vtkGenericDataArray.h"
36 #include "vtkBuffer.h" // For storage buffer.
37 
38 // The export macro below makes no sense, but is necessary for older compilers
39 // when we export instantiations of this class from vtkCommonCore.
40 template <class ValueTypeT>
41 class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate :
42     public vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>, ValueTypeT>
43 {
44   typedef vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>, ValueTypeT>
45           GenericDataArrayType;
46 public:
47   typedef vtkAOSDataArrayTemplate<ValueTypeT> SelfType;
48   vtkTemplateTypeMacro(SelfType, GenericDataArrayType)
49   typedef typename Superclass::ValueType ValueType;
50 
51   enum DeleteMethod
52   {
53     VTK_DATA_ARRAY_FREE=vtkAbstractArray::VTK_DATA_ARRAY_FREE,
54     VTK_DATA_ARRAY_DELETE=vtkAbstractArray::VTK_DATA_ARRAY_DELETE,
55     VTK_DATA_ARRAY_ALIGNED_FREE=vtkAbstractArray::VTK_DATA_ARRAY_ALIGNED_FREE,
56     VTK_DATA_ARRAY_USER_DEFINED=vtkAbstractArray::VTK_DATA_ARRAY_USER_DEFINED
57   };
58 
59   static vtkAOSDataArrayTemplate* New();
60 
61   /**
62    * Get the value at @a valueIdx. @a valueIdx assumes AOS ordering.
63    */
GetValue(vtkIdType valueIdx)64   ValueType GetValue(vtkIdType valueIdx) const
65     VTK_EXPECTS(0 <= valueIdx && valueIdx < GetNumberOfValues())
66   {
67     return this->Buffer->GetBuffer()[valueIdx];
68   }
69 
70   /**
71    * Set the value at @a valueIdx to @a value. @a valueIdx assumes AOS ordering.
72    */
SetValue(vtkIdType valueIdx,ValueType value)73   void SetValue(vtkIdType valueIdx, ValueType value)
74     VTK_EXPECTS(0 <= valueIdx && valueIdx < GetNumberOfValues())
75   {
76     this->Buffer->GetBuffer()[valueIdx] = value;
77   }
78 
79   //@{
80   /**
81    * Copy the tuple at @a tupleIdx into @a tuple.
82    */
GetTypedTuple(vtkIdType tupleIdx,ValueType * tuple)83   void GetTypedTuple(vtkIdType tupleIdx, ValueType* tuple) const
84     VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples())
85   {
86     const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents;
87     std::copy(this->Buffer->GetBuffer() + valueIdx,
88               this->Buffer->GetBuffer() + valueIdx + this->NumberOfComponents,
89               tuple);
90   }
91   //@}
92 
93   //@{
94   /**
95    * Set this array's tuple at @a tupleIdx to the values in @a tuple.
96    */
SetTypedTuple(vtkIdType tupleIdx,const ValueType * tuple)97   void SetTypedTuple(vtkIdType tupleIdx, const ValueType* tuple)
98     VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples())
99   {
100     const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents;
101     std::copy(tuple, tuple + this->NumberOfComponents,
102               this->Buffer->GetBuffer() + valueIdx);
103   }
104   //@}
105 
106   /**
107    * Get component @a comp of the tuple at @a tupleIdx.
108    */
GetTypedComponent(vtkIdType tupleIdx,int comp)109   ValueType GetTypedComponent(vtkIdType tupleIdx, int comp) const
110     VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples())
111     VTK_EXPECTS(0 <= comp && comp < GetNumberOfComponents())
112   {
113     return this->Buffer->GetBuffer()[this->NumberOfComponents*tupleIdx + comp];
114   }
115 
116   //@{
117   /**
118    * Set component @a comp of the tuple at @a tupleIdx to @a value.
119    */
SetTypedComponent(vtkIdType tupleIdx,int comp,ValueType value)120   void SetTypedComponent(vtkIdType tupleIdx, int comp, ValueType value)
121     VTK_EXPECTS(0 <= tupleIdx && tupleIdx < GetNumberOfTuples())
122     VTK_EXPECTS(0 <= comp && comp < GetNumberOfComponents())
123   {
124     const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents + comp;
125     this->SetValue(valueIdx, value);
126   }
127   //@}
128 
129   //@{
130   /**
131    * Set component @a comp of all tuples to @a value.
132    */
133   void FillTypedComponent(int compIdx, ValueType value) override;
134   //@}
135 
136   //@{
137   /**
138    * Set all the values in array to @a value.
139    */
140   void FillValue(ValueType value) override;
141   void Fill(double value) override;
142   //@}
143 
144   //@{
145   /**
146    * Get the address of a particular data index. Make sure data is allocated
147    * for the number of items requested. Set MaxId according to the number of
148    * data values requested.
149    */
150   ValueType* WritePointer(vtkIdType valueIdx, vtkIdType numValues);
151   void* WriteVoidPointer(vtkIdType valueIdx, vtkIdType numValues) override;
152   //@}
153 
154   //@{
155   /**
156    * Get the address of a particular data index. Performs no checks
157    * to verify that the memory has been allocated etc.
158    * Use of this method is discouraged, as newer arrays require a deep-copy of
159    * the array data in order to return a suitable pointer. See vtkArrayDispatch
160    * for a safer alternative for fast data access.
161    */
162   ValueType* GetPointer(vtkIdType valueIdx);
163   void* GetVoidPointer(vtkIdType valueIdx) override;
164   //@}
165 
166   //@{
167   /**
168    * This method lets the user specify data to be held by the array.  The
169    * array argument is a pointer to the data.  size is the size of the
170    * array supplied by the user (as number of values, not in bytes).
171    * Set save to 1 to prevent the class from
172    * deleting the array when it cleans up or reallocates memory.  The class
173    * uses the actual array provided; it does not copy the data from the
174    * suppled array. If specified, the delete method determines how the data
175    * array will be deallocated. If the delete method is
176    * VTK_DATA_ARRAY_FREE, free() will be used. If the delete method is
177    * VTK_DATA_ARRAY_DELETE, delete[] will be used. If the delete method is
178    * VTK_DATA_ARRAY_ALIGNED_FREE _aligned_free() will be used on Windows, while
179    * free() will be used everywhere else. The default is FREE.
180    */
181   void SetArray(VTK_ZEROCOPY ValueType* array, vtkIdType size, int save,
182                 int deleteMethod);
183   void SetArray(VTK_ZEROCOPY ValueType* array, vtkIdType size, int save);
184   void SetVoidArray(void* array, vtkIdType size, int save) override;
185   void SetVoidArray(void* array, vtkIdType size, int save,
186                     int deleteMethod) override;
187   //@}
188 
189   /**
190     * This method allows the user to specify a custom free function to be
191     * called when the array is deallocated. Calling this method will implicitly
192     * mean that the given free function will be called when the class
193     * cleans up or reallocates memory.
194   **/
195   void SetArrayFreeFunction(void (*callback)(void *)) override;
196 
197   // Overridden for optimized implementations:
198   void SetTuple(vtkIdType tupleIdx, const float *tuple) override;
199   void SetTuple(vtkIdType tupleIdx, const double *tuple) override;
200   // MSVC doesn't like 'using' here (error C2487). Just forward instead:
201   // using Superclass::SetTuple;
SetTuple(vtkIdType dstTupleIdx,vtkIdType srcTupleIdx,vtkAbstractArray * source)202   void SetTuple(vtkIdType dstTupleIdx, vtkIdType srcTupleIdx,
203                 vtkAbstractArray *source) override
204   { this->Superclass::SetTuple(dstTupleIdx, srcTupleIdx, source); }
205   void InsertTuple(vtkIdType tupleIdx, const float *source) override;
206   void InsertTuple(vtkIdType tupleIdx, const double *source) override;
207   // MSVC doesn't like 'using' here (error C2487). Just forward instead:
208   // using Superclass::InsertTuple;
InsertTuple(vtkIdType dstTupleIdx,vtkIdType srcTupleIdx,vtkAbstractArray * source)209   void InsertTuple(vtkIdType dstTupleIdx, vtkIdType srcTupleIdx,
210                    vtkAbstractArray *source) override
211   { this->Superclass::InsertTuple(dstTupleIdx, srcTupleIdx, source); }
212   void InsertComponent(vtkIdType tupleIdx, int compIdx,
213                        double value) override;
214   vtkIdType InsertNextTuple(const float *tuple) override;
215   vtkIdType InsertNextTuple(const double *tuple) override;
216   // MSVC doesn't like 'using' here (error C2487). Just forward instead:
217   // using Superclass::InsertNextTuple;
InsertNextTuple(vtkIdType srcTupleIdx,vtkAbstractArray * source)218   vtkIdType InsertNextTuple(vtkIdType srcTupleIdx,
219                             vtkAbstractArray *source) override
220   { return this->Superclass::InsertNextTuple(srcTupleIdx, source); }
221   void GetTuple(vtkIdType tupleIdx, double * tuple) override;
222   double *GetTuple(vtkIdType tupleIdx) override;
223 
224   /**
225    * Tell the array explicitly that a single data element has
226    * changed. Like DataChanged(), then is only necessary when you
227    * modify the array contents without using the array's API.
228    * @note This is a legacy method from vtkDataArrayTemplate, and is only
229    * implemented for array-of-struct arrays. It currently just calls
230    * DataChanged() and does nothing clever.
231    * TODO this is only defined for AOS (vtkDataArrayTemplate leftover).
232    * Deprecate to favor DataChanged?
233    */
DataElementChanged(vtkIdType)234   void DataElementChanged(vtkIdType) { this->DataChanged(); }
235 
236   /**
237    * Legacy support for array-of-structs value iteration.
238    * TODO Deprecate?
239    */
240   typedef ValueType* Iterator;
Begin()241   Iterator Begin() { return Iterator(this->GetVoidPointer(0)); }
End()242   Iterator End() { return Iterator(this->GetVoidPointer(this->MaxId + 1)); }
243 
244   //@{
245   /**
246    * Perform a fast, safe cast from a vtkAbstractArray to a
247    * vtkAOSDataArrayTemplate.
248    * This method checks if source->GetArrayType() returns DataArray
249    * or a more derived type, and performs a static_cast to return
250    * source as a vtkDataArray pointer. Otherwise, nullptr is returned.
251    */
252   static vtkAOSDataArrayTemplate<ValueType>*
FastDownCast(vtkAbstractArray * source)253   FastDownCast(vtkAbstractArray *source)
254   {
255     if (source)
256     {
257       switch (source->GetArrayType())
258       {
259         case vtkAbstractArray::AoSDataArrayTemplate:
260           if (vtkDataTypesCompare(source->GetDataType(),
261                                   vtkTypeTraits<ValueType>::VTK_TYPE_ID))
262           {
263             return static_cast<vtkAOSDataArrayTemplate<ValueType>*>(source);
264           }
265           break;
266       }
267     }
268     return nullptr;
269   }
270   //@}
271 
GetArrayType()272   int GetArrayType() override { return vtkAbstractArray::AoSDataArrayTemplate; }
273   VTK_NEWINSTANCE vtkArrayIterator *NewIterator() override;
HasStandardMemoryLayout()274   bool HasStandardMemoryLayout() override { return true; }
275   void ShallowCopy(vtkDataArray *other) override;
276 
277   // Reimplemented for efficiency:
278   void InsertTuples(vtkIdType dstStart, vtkIdType n, vtkIdType srcStart,
279                     vtkAbstractArray* source) override;
280   // MSVC doesn't like 'using' here (error C2487). Just forward instead:
281   // using Superclass::InsertTuples;
InsertTuples(vtkIdList * dstIds,vtkIdList * srcIds,vtkAbstractArray * source)282   void InsertTuples(vtkIdList *dstIds, vtkIdList *srcIds,
283                     vtkAbstractArray *source) override
284   { this->Superclass::InsertTuples(dstIds, srcIds, source); }
285 
286 protected:
287   vtkAOSDataArrayTemplate();
288   ~vtkAOSDataArrayTemplate() override;
289 
290   /**
291    * Allocate space for numTuples. Old data is not preserved. If numTuples == 0,
292    * all data is freed.
293    */
294   bool AllocateTuples(vtkIdType numTuples);
295 
296   /**
297    * Allocate space for numTuples. Old data is preserved. If numTuples == 0,
298    * all data is freed.
299    */
300   bool ReallocateTuples(vtkIdType numTuples);
301 
302   vtkBuffer<ValueType> *Buffer;
303 
304 private:
305   vtkAOSDataArrayTemplate(const vtkAOSDataArrayTemplate&) = delete;
306   void operator=(const vtkAOSDataArrayTemplate&) = delete;
307 
308   friend class vtkGenericDataArray<vtkAOSDataArrayTemplate<ValueTypeT>,
309                                    ValueTypeT>;
310 
311 };
312 
313 // Declare vtkArrayDownCast implementations for AoS containers:
314 vtkArrayDownCast_TemplateFastCastMacro(vtkAOSDataArrayTemplate)
315 
316 // This macro is used by the subclasses to create dummy
317 // declarations for these functions such that the wrapper
318 // can see them. The wrappers ignore vtkAOSDataArrayTemplate.
319 #define vtkCreateWrappedArrayInterface(T) \
320   int GetDataType() override;\
321   void GetTypedTuple(vtkIdType i, T* tuple) \
322     VTK_EXPECTS(0 <= i && i < GetNumberOfTuples()); \
323   void SetTypedTuple(vtkIdType i, const T* tuple) \
324     VTK_EXPECTS(0 <= i && i < GetNumberOfTuples()); \
325   void InsertTypedTuple(vtkIdType i, const T* tuple) \
326     VTK_EXPECTS(0 <= i); \
327   vtkIdType InsertNextTypedTuple(const T* tuple); \
328   T GetValue(vtkIdType id) \
329     VTK_EXPECTS(0 <= id && id < GetNumberOfValues()); \
330   void SetValue(vtkIdType id, T value) \
331     VTK_EXPECTS(0 <= id && id < GetNumberOfValues()); \
332   void SetNumberOfValues(vtkIdType number) override;\
333   void InsertValue(vtkIdType id, T f) \
334     VTK_EXPECTS(0 <= id); \
335   vtkIdType InsertNextValue(T f); \
336   T *GetValueRange(int comp) VTK_SIZEHINT(2); \
337   T *GetValueRange() VTK_SIZEHINT(2); \
338   T* WritePointer(vtkIdType id, vtkIdType number); \
339   T* GetPointer(vtkIdType id); \
340   void SetArray(VTK_ZEROCOPY T* array, vtkIdType size, int save); \
341   void SetArray(VTK_ZEROCOPY T* array, vtkIdType size, int save, int deleteMethod)
342 
343 #endif // header guard
344 
345 // This portion must be OUTSIDE the include blockers. This is used to tell
346 // libraries other than vtkCommonCore that instantiations of
347 // vtkAOSDataArrayTemplate can be found externally. This prevents each library
348 // from instantiating these on their own.
349 #ifdef VTK_AOS_DATA_ARRAY_TEMPLATE_INSTANTIATING
350 #define VTK_AOS_DATA_ARRAY_TEMPLATE_INSTANTIATE(T) \
351   template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate< T >
352 #elif defined(VTK_USE_EXTERN_TEMPLATE)
353 #ifndef VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN
354 #define VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN
355 #ifdef _MSC_VER
356 #pragma warning (push)
357 // The following is needed when the vtkAOSDataArrayTemplate is declared
358 // dllexport and is used from another class in vtkCommonCore
359 #pragma warning (disable: 4910) // extern and dllexport incompatible
360 #endif
361 vtkExternTemplateMacro(
362   extern template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate)
363 #ifdef _MSC_VER
364 #pragma warning (pop)
365 #endif
366 #endif // VTK_AOS_DATA_ARRAY_TEMPLATE_EXTERN
367 
368 // The following clause is only for MSVC
369 #elif defined(_MSC_VER) && !defined(VTK_BUILD_SHARED_LIBS)
370 #pragma warning (push)
371 
372 // C4091: 'extern ' : ignored on left of 'int' when no variable is declared
373 #pragma warning (disable: 4091)
374 
375 // Compiler-specific extension warning.
376 #pragma warning (disable: 4231)
377 
378 // We need to disable warning 4910 and do an extern dllexport
379 // anyway.  When deriving vtkCharArray and other types from an
380 // instantiation of this template the compiler does an explicit
381 // instantiation of the base class.  From outside the vtkCommon
382 // library we block this using an extern dllimport instantiation.
383 // For classes inside vtkCommon we should be able to just do an
384 // extern instantiation, but VS complains about missing
385 // definitions.  We cannot do an extern dllimport inside vtkCommon
386 // since the symbols are local to the dll.  An extern dllexport
387 // seems to be the only way to convince VS to do the right
388 // thing, so we just disable the warning.
389 #pragma warning (disable: 4910) // extern and dllexport incompatible
390 
391 // Use an "extern explicit instantiation" to give the class a DLL
392 // interface.  This is a compiler-specific extension.
393 vtkInstantiateTemplateMacro(
394   extern template class VTKCOMMONCORE_EXPORT vtkAOSDataArrayTemplate)
395 
396 #pragma warning (pop)
397 
398 #endif
399 
400 // VTK-HeaderTest-Exclude: vtkAOSDataArrayTemplate.h
401