FBX C++ API Reference
fbxarray.h
Go to the documentation of this file.
1 /****************************************************************************************
2 
3  Copyright (C) 2017 Autodesk, Inc.
4  All rights reserved.
5 
6  Use of this software is subject to the terms of the Autodesk license agreement
7  provided at the time of installation or download, or which otherwise accompanies
8  this software in either electronic or hard copy form.
9 
10 ****************************************************************************************/
11 
13 #ifndef _FBXSDK_CORE_BASE_ARRAY_H_
14 #define _FBXSDK_CORE_BASE_ARRAY_H_
15 
16 #include <fbxsdk/fbxsdk_def.h>
17 
18 #include <fbxsdk/fbxsdk_nsbegin.h>
19 
20 #if defined(FBXSDK_COMPILER_MSC)
21  #pragma warning( push )
22  #pragma warning( disable : 4201 ) // nonstandard extension used: nameless struct/union
23 #endif
24 
25 #ifdef THROW_EXCEPTIONS
26  #define FBX_THROW(x) throw std::runtime_error(x)
27  #define FBX_ARRAY_INLINE __forceinline
28 #else
29  #define FBX_THROW(x) FBX_ASSERT_NOW(x)
30  #define FBX_ARRAY_INLINE inline
31 #endif
32 
33 
37 template <class T, const int Alignment = 16> class FbxArray
38 {
39 protected:
40  struct tData {
41  union {
42  struct {
43  int mSize;
44  int mCapacity;
45  };
46  char Padding[Alignment];
47  };
48  T mArray[15];
49  } *mData;
50 public:
52  typedef int (*CompareFunc)(const void*, const void*);
53 
56 
58  FbxArray(const int pCapacity) : mData(NULL){ if( pCapacity > 0 ) Reserve(pCapacity); }
59 
61  FbxArray(const FbxArray& pArray) : mData(NULL){ *this = pArray; }
62 
65  ~FbxArray(){ Clear(); }
66 
73  inline int InsertAt(const int pIndex, const T& pElement, bool pCompact=false)
74  {
75  FBX_ASSERT_RETURN_VALUE(pIndex >= 0, -1);
76  int lIndex = FbxMin(pIndex, GetSize());
77  if( GetSize() >= GetCapacity() )
78  {
79  T lElement = pElement; //Copy element because we might move memory
80  int lNewCapacity = FbxMax(pCompact ? GetCapacity() + 1 : GetCapacity() * 2, 1); //We always double capacity when not compacting
81  Allocate(lNewCapacity);
82  FBX_ASSERT_RETURN_VALUE(mData, -1);
83  mData->mCapacity = lNewCapacity;
84  return InsertAt(pIndex, lElement); //Insert copied element because reference might be moved
85  }
86 
87  if( lIndex < GetSize() ) //Move elements to leave a space open to insert the new element
88  {
89  //If pElement is inside memmove range, copy element and insert copy instead
90  if( (&pElement >= &GetArray()[lIndex]) && (&pElement < &GetArray()[GetSize()]) )
91  {
92  T lElement = pElement;
93  return InsertAt(pIndex, lElement);
94  }
95  memmove(&GetArray()[lIndex + 1], &GetArray()[lIndex], (GetSize() - lIndex) * sizeof(T));
96  }
97 
98  memcpy(&GetArray()[lIndex], &pElement, sizeof(T));
99  mData->mSize++;
100 
101  return lIndex;
102  }
103 
108  inline int Add(const T& pElement)
109  {
110  int lIndex = GetSize();
111 
112  if (lIndex >= GetCapacity())
113  {
114  T lElement = pElement; //Copy element because we might move memory
115  int lNewCapacity = FbxMax(GetCapacity() * 2, 1); //We always double capacity
116  Allocate(lNewCapacity);
117  FBX_ASSERT_RETURN_VALUE(mData, -1);
118  mData->mCapacity = lNewCapacity;
119  return Add(lElement); //Insert copied element because reference might be moved
120  }
121 
122  memcpy(&GetArray()[lIndex], &pElement, sizeof(T));
123  mData->mSize++;
124 
125  return lIndex;
126  }
127 
131  inline int AddUnique(const T& pElement)
132  {
133  int lIndex = Find(pElement);
134  return ( lIndex == -1 ) ? Add(pElement) : lIndex;
135  }
136 
140  inline int AddCompact(const T& pElement)
141  {
142  return InsertAt(GetSize(), pElement, true);
143  }
144 
148  inline int Size() const { return GetSize(); }
149 
153  inline int Capacity() const { return GetCapacity(); }
154 
159  FBX_ARRAY_INLINE T& operator[](const int pIndex) const
160  {
161  if (pIndex < 0)
162  {
163  FBX_THROW("Index is out of range!");
164  }
165 
166  if (pIndex >= GetSize())
167  {
168  if (pIndex < GetCapacity())
169  {
170  FBX_THROW("Index is out of range, but not outside of capacity! Call SetAt() to use reserved memory.");
171  }
172 
173  FBX_THROW("Index is out of range!");
174  }
175 
176  return GetArray()[pIndex];
177  }
178 
183  inline T GetAt(const int pIndex) const
184  {
185  return operator[](pIndex);
186  }
187 
191  inline T GetFirst() const
192  {
193  return GetAt(0);
194  }
195 
199  inline T GetLast() const
200  {
201  return GetAt(GetSize() - 1);
202  }
203 
208  inline int Find(const T& pElement, const int pStartIndex = 0) const
209  {
210  const int size = GetSize();
211 
212  FBX_ASSERT_RETURN_VALUE(pStartIndex >= 0, -1);
213  FBX_ASSERT_RETURN_VALUE(size >= 0, -1);
214 
215  for (int i = pStartIndex; i < size; ++i)
216  {
217  if (GetArray()[i] == pElement) return i;
218  }
219  return -1;
220  }
221 
226  inline int FindReverse(const T& pElement, const int pStartIndex = FBXSDK_INT_MAX) const
227  {
228  const int size = GetSize();
229 
230  FBX_ASSERT_RETURN_VALUE(size > 0, -1);
231 
232  for (int i = FbxMin(pStartIndex, size - 1); i >= 0; --i)
233  {
234  if (GetArray()[i] == pElement) return i;
235  }
236  return -1;
237  }
238 
243  inline bool Reserve(const int pCapacity)
244  {
245  FBX_ASSERT_RETURN_VALUE(pCapacity >= 0, false);
246  if( pCapacity > GetCapacity() )
247  {
248  Allocate(pCapacity);
249  FBX_ASSERT_RETURN_VALUE(mData, false);
250  mData->mCapacity = pCapacity;
251 
252  //Initialize new memory to zero
253  memset(&GetArray()[GetSize()], 0, (GetCapacity() - GetSize()) * sizeof(T));
254  }
255  return true;
256  }
257 
263  inline void SetAt(const int pIndex, const T& pElement)
264  {
265  FBX_ASSERT_RETURN(pIndex >= 0 && pIndex < GetCapacity());
266  if( pIndex >= GetSize() ) mData->mSize = pIndex + 1;
267 
268  T* const array = GetArray();
269  if (array) memcpy(&array[pIndex], &pElement, sizeof(T));
270  }
271 
275  inline void SetFirst(const T& pElement)
276  {
277  SetAt(0, pElement);
278  }
279 
283  inline void SetLast(const T& pElement)
284  {
285  SetAt(GetSize() - 1, pElement);
286  }
287 
292  FBX_ARRAY_INLINE T RemoveAt(const int pIndex)
293  {
294  const int size = GetSize();
295  const int index = pIndex + 1;
296  if (index < 0 || index > size)
297  {
298  FBX_THROW("Index is out of range!");
299  }
300 
301  T lElement = GetAt(pIndex);
302  if (index < size)
303  {
304  memmove(&GetArray()[pIndex], &GetArray()[index], (size - pIndex - 1) * sizeof(T));
305  }
306  mData->mSize--;
307  return lElement;
308  }
309 
313  inline T RemoveFirst()
314  {
315  return RemoveAt(0);
316  }
317 
321  inline T RemoveLast()
322  {
323  return RemoveAt(GetSize() - 1);
324  }
325 
329  inline bool RemoveIt(const T& pElement)
330  {
331  int Index = Find(pElement);
332  if( Index >= 0 )
333  {
334  RemoveAt(Index);
335  return true;
336  }
337  return false;
338  }
339 
345  inline void RemoveRange(const int pIndex, const int pCount)
346  {
347  const int size = GetSize();
348  if (size == 0)
349  // the array is already empty (or not allocated yet)
350  // no point in continuing
351  return;
352 
353  FBX_ASSERT(GetArray() != NULL);
354  FBX_ASSERT_RETURN(pCount > 0);
355  FBX_ASSERT_RETURN(pIndex >= 0);
356 
357  size_t lastItem = pIndex + pCount;
358  FBX_ASSERT_RETURN(lastItem >= 0);
359  FBX_ASSERT_RETURN(lastItem <= (size_t)size);
360  FBX_ASSERT_RETURN(lastItem < FBXSDK_INT_MAX);
361 
362  if (lastItem < (size_t)size)
363  {
364  memmove(&GetArray()[pIndex], &GetArray()[pIndex + pCount], (size - pIndex - pCount) * (unsigned)sizeof(T));
365  }
366 
367  if (mData)
368  {
369  mData->mSize -= pCount;
370  }
371  }
372 
378  inline bool ResizeUninitialized(const int pSize, bool pPreserveCapacityIfPossible = false)
379  {
380  if( pSize == GetSize() && GetSize() == GetCapacity() ) return true;
381 
382  if( pSize == 0 )
383  {
384  Clear();
385  return true;
386  }
387 
388  FBX_ASSERT_RETURN_VALUE(pSize > 0, false);
389 
390  bool lReallocate;
391  if (pPreserveCapacityIfPossible)
392  lReallocate = pSize > GetCapacity();
393  else
394  lReallocate = pSize != GetCapacity();
395 
396  if (lReallocate)
397  {
398  Allocate(pSize);
399  FBX_ASSERT_RETURN_VALUE(mData, false);
400  mData->mCapacity = pSize;
401  }
402 
403  mData->mSize = pSize;
404  return true;
405  }
406 
412  inline bool Resize(const int pSize, bool pPreserveCapacityIfPossible = false)
413  {
414  if (pSize == GetSize() && GetSize() == GetCapacity()) return true;
415 
416  if (pSize == 0)
417  {
418  Clear();
419  return true;
420  }
421 
422  FBX_ASSERT_RETURN_VALUE(pSize > 0, false);
423 
424  bool lReallocate;
425  if (pPreserveCapacityIfPossible)
426  lReallocate = pSize > GetCapacity();
427  else
428  lReallocate = pSize != GetCapacity();
429 
430  if (lReallocate)
431  {
432  Allocate(pSize);
433  FBX_ASSERT_RETURN_VALUE(mData, false);
434 
435  if (pSize > GetCapacity()) //Initialize new memory to zero
436  {
437  memset(&GetArray()[GetSize()], 0, (pSize - GetSize()) * sizeof(T));
438  }
439 
440  mData->mCapacity = pSize;
441  }
442 
443  mData->mSize = pSize;
444  return true;
445  }
446 
450  inline bool Grow(const int pSize)
451  {
452  const int size = GetSize();
453 
454  // Check int32 paramater does not overflow
455  FbxLongLong newSize = static_cast<FbxLongLong>(size) + static_cast<FbxLongLong>(pSize);
456  if (newSize > INT_MAX)
457  {
458  return false;
459  }
460 
461  return Resize(size + pSize);
462  }
463 
467  inline bool Shrink(const int pSize)
468  {
469  const int size = GetSize();
470 
471  // Check int32 paramater does not overflow
472  FbxLongLong newSize = static_cast<FbxLongLong>(size) - static_cast<FbxLongLong>(pSize);
473  if (pSize < 0 || newSize < 0 || newSize > size)
474  {
475  return false;
476  }
477 
478  return Resize(size - pSize);
479  }
480 
483  inline bool Compact()
484  {
485  return Resize(GetSize());
486  }
487 
490  inline void Clear()
491  {
492  if( mData != NULL )
493  {
494  FbxFree(mData);
495  mData = NULL;
496  }
497  }
498 
501  inline void Sort(CompareFunc pCompareFunc)
502  {
503  qsort(GetArray(), GetSize(), sizeof(T), pCompareFunc);
504  }
505 
507  inline T* GetArray() const { return mData ? &mData->mArray[0] : NULL; }
508 
510  inline operator T* () const { return GetArray(); }
511 
514  inline void AddArray(const FbxArray<T>& pOther)
515  {
516  if( Grow(pOther.GetSize()) )
517  {
518  memcpy(&GetArray()[GetSize() - pOther.GetSize()], pOther.GetArray(), pOther.GetSize() * sizeof(T));
519  }
520  }
521 
524  inline void AddArrayNoDuplicate(const FbxArray<T>& pOther)
525  {
526  for( int i = 0, c = pOther.GetSize(); i < c; ++i )
527  {
528  AddUnique(pOther[i]);
529  }
530  }
531 
534  inline void RemoveArray(const FbxArray<T>& pOther)
535  {
536  for( int i = 0, c = pOther.GetSize(); i < c; ++i )
537  {
538  RemoveIt(pOther[i]);
539  }
540  }
541 
544  inline FbxArray<T>& operator=(const FbxArray<T>& pOther)
545  {
546  if( this != &pOther )
547  {
548  if( Resize(pOther.GetSize()) )
549  {
550  memcpy(GetArray(), pOther.GetArray(), pOther.GetSize() * sizeof(T));
551  }
552  }
553  return *this;
554  }
555 
558  inline bool operator==(const FbxArray<T>& pOther) const
559  {
560  if( this == &pOther ) return true;
561  if( GetSize() != pOther.GetSize() ) return false;
562  return memcmp(GetArray(), pOther.GetArray(), sizeof(T) * GetSize()) == 0;
563  }
564 
565 /*****************************************************************************************************************************
566 ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
567 *****************************************************************************************************************************/
568 #ifndef DOXYGEN_SHOULD_SKIP_THIS
569  inline int GetCount() const { return mData ? mData->mSize : 0; }
570 
571 private:
572  inline void Allocate(const int pCapacity)
573  {
574  tData* lOldData = mData;
575  tData* lData = (tData*)FbxRealloc(mData, (size_t)Alignment + FbxAllocSize(pCapacity, sizeof(T)));
576  if (lData)
577  {
578  mData = lData;
579  if (!lOldData)
580  {
581  mData->mSize = 0;
582  mData->mCapacity = 0;
583  }
584  }
585  else
586  {
587  mData = NULL;
588  }
589  }
590 
591  inline int GetSize() const { return mData ? mData->mSize : 0; }
592  inline int GetCapacity() const { return mData ? mData->mCapacity : 0; }
593 
594 #if defined(FBXSDK_COMPILER_MSC)
595  //Previously class FbxArray is for pointers. Somehow, it's used to store other types. Here's a compile-time checking for known incompatible classes.
596  //If it happens you find new incompatible ones, declare them with macro FBXSDK_INCOMPATIBLE_WITH_ARRAY. Also see file fbxstring.h.
597  FBX_ASSERT_STATIC(FBXSDK_IS_SIMPLE_TYPE(T) || __is_enum(T) || (__has_trivial_constructor(T)&&__has_trivial_destructor(T)) || !FBXSDK_IS_INCOMPATIBLE_WITH_ARRAY(T));
598 #endif
599 
600 #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
601 };
602 
603 #if defined(FBXSDK_COMPILER_MSC)
604  #pragma warning( pop )
605 #endif
606 
608 template <class T> inline void FbxArrayFree(FbxArray<T>& pArray)
609 {
610  for( int i = 0, c = pArray.Size(); i < c; ++i )
611  {
612  FbxFree(pArray[i]);
613  }
614  pArray.Clear();
615 }
616 
618 template <class T> inline void FbxArrayDelete(FbxArray<T>& pArray)
619 {
620  for( int i = 0, c = pArray.Size(); i < c; ++i )
621  {
622  FbxDelete(pArray[i]);
623  }
624  pArray.Clear();
625 }
626 
628 template <class T> inline void FbxArrayDestroy(FbxArray<T>& pArray)
629 {
630  for( int i = 0, c = pArray.Size(); i < c; ++i )
631  {
632  (pArray[i])->Destroy();
633  }
634  pArray.Clear();
635 }
636 
639 
640 #include <fbxsdk/fbxsdk_nsend.h>
641 
642 #undef FBX_ARRAY_INLINE
643 #undef FBX_THROW
644 
645 #endif /* _FBXSDK_CORE_BASE_ARRAY_H_ */
bool RemoveIt(const T &pElement)
Remove first matching element in the array.
Definition: fbxarray.h:329
FBX SDK environment definition.
T & operator[](const int pIndex) const
Retrieve a reference of the element at given index position in the array.
Definition: fbxarray.h:159
void FbxArrayDelete(FbxArray< T > &pArray)
Call FbxDelete on each element of the array, and then clear it.
Definition: fbxarray.h:618
FBXSDK_INCOMPATIBLE_WITH_ARRAY_TEMPLATE(FbxArray< T >)
Make sure to break build if someone try to make FbxArray>, which is not supported...
void FbxArrayDestroy(FbxArray< T > &pArray)
Call Destroy on each element of the array, and then clear it.
Definition: fbxarray.h:628
int Size() const
Retrieve the number of element contained in the array.
Definition: fbxarray.h:148
bool Grow(const int pSize)
Increase size of array by the specified size.
Definition: fbxarray.h:450
bool Compact()
Compact the array so that its capacity is the same as its size.
Definition: fbxarray.h:483
int Capacity() const
Retrieve the current allocated memory capacity of the array.
Definition: fbxarray.h:153
#define NULL
Definition: fbxarch.h:213
void Sort(CompareFunc pCompareFunc)
Sort the array using the specified compare function pointer.
Definition: fbxarray.h:501
T RemoveAt(const int pIndex)
Remove an element at the given position in the array.
Definition: fbxarray.h:292
T GetAt(const int pIndex) const
Retrieve a copy of the element at given index position in the array.
Definition: fbxarray.h:183
void FbxDelete(T *p)
Deletion policy for pointer template classes that uses the FbxDelete() function.
Definition: fbxnew.h:341
int AddCompact(const T &pElement)
Append an element at the end of the array, growing the array by one element if capacity is not suffic...
Definition: fbxarray.h:140
bool Shrink(const int pSize)
Reduce size of array by the specified size.
Definition: fbxarray.h:467
void RemoveArray(const FbxArray< T > &pOther)
Remove the elements of another array from this array is they are present.
Definition: fbxarray.h:534
T RemoveFirst()
Remove the first element in the array.
Definition: fbxarray.h:313
#define FBX_THROW(x)
Definition: fbxarray.h:29
int(* CompareFunc)(const void *, const void *)
Element compare function pointer definition.
Definition: fbxarray.h:52
int AddUnique(const T &pElement)
Append an element at the end of array, if not already present, doubling the array if capacity is not ...
Definition: fbxarray.h:131
void Clear()
Reset the number of element to zero and free the memory allocated.
Definition: fbxarray.h:490
int Add(const T &pElement)
Append an element at the end of the array, doubling the array if capacity is not sufficient.
Definition: fbxarray.h:108
FbxArray(const int pCapacity)
Reserve constructor.
Definition: fbxarray.h:58
void RemoveRange(const int pIndex, const int pCount)
Remove a range of elements at the given position in the array.
Definition: fbxarray.h:345
void SetAt(const int pIndex, const T &pElement)
Set the element at given position in the array.
Definition: fbxarray.h:263
#define INT_MAX
bool operator==(const FbxArray< T > &pOther) const
Operator to compare elements of an array.
Definition: fbxarray.h:558
~FbxArray()
Destructor.
Definition: fbxarray.h:65
#define FBX_ARRAY_INLINE
Definition: fbxarray.h:30
void AddArrayNoDuplicate(const FbxArray< T > &pOther)
Append the elements of another array at the end of this array if they are not present.
Definition: fbxarray.h:524
FbxArray< T > & operator=(const FbxArray< T > &pOther)
Operator to copy elements of an array.
Definition: fbxarray.h:544
#define FBXSDK_IS_SIMPLE_TYPE(T)
Definition: fbxnew.h:57
T mArray[15]
15 represent only the number of items to see debug
Definition: fbxarray.h:48
FbxArray()
Constructor.
Definition: fbxarray.h:55
void FbxArrayFree(FbxArray< T > &pArray)
Call FbxFree on each element of the array, and then clear it.
Definition: fbxarray.h:608
FbxChar FbxMax(const FbxChar)
Definition: fbxtypes.h:173
T * GetArray() const
Get pointer to internal array of elements.
Definition: fbxarray.h:507
bool Resize(const int pSize, bool pPreserveCapacityIfPossible=false)
Inserts or erases elements at the end such that Size() becomes pSize, increasing capacity if needed...
Definition: fbxarray.h:412
struct FbxArray::tData * mData
void SetFirst(const T &pElement)
Set the value of the first element.
Definition: fbxarray.h:275
char Padding[Alignment]
Definition: fbxarray.h:46
T RemoveLast()
Remove the last element in the array.
Definition: fbxarray.h:321
#define FBXSDK_INT_MAX
Definition: fbxtypes.h:119
void SetLast(const T &pElement)
Set the value of the last element.
Definition: fbxarray.h:283
FbxChar FbxMin(const FbxChar)
Definition: fbxtypes.h:162
bool Reserve(const int pCapacity)
Request for allocation of additional memory without inserting new elements.
Definition: fbxarray.h:243
int InsertAt(const int pIndex, const T &pElement, bool pCompact=false)
Insert an element at the given position, growing the array if capacity is not sufficient.
Definition: fbxarray.h:73
FbxArray(const FbxArray &pArray)
Copy constructor.
Definition: fbxarray.h:61
int FindReverse(const T &pElement, const int pStartIndex=0x7fffffff) const
Find first matching element, from last to first.
Definition: fbxarray.h:226
T GetLast() const
Retrieve a copy of the last element.
Definition: fbxarray.h:199
FbxInt64 FbxLongLong
Definition: fbxtypes.h:92
void AddArray(const FbxArray< T > &pOther)
Append another array at the end of this array.
Definition: fbxarray.h:514
Class for array of basic elements such as pointers and basic types.
Definition: fbxarray.h:37
T GetFirst() const
Retrieve a copy of the first element.
Definition: fbxarray.h:191
bool ResizeUninitialized(const int pSize, bool pPreserveCapacityIfPossible=false)
Inserts or erases elements at the end such that Size() becomes pSize, increasing capacity if needed...
Definition: fbxarray.h:378
int Find(const T &pElement, const int pStartIndex=0) const
Find first matching element, from first to last.
Definition: fbxarray.h:208