Version

menu_open
Wwise SDK 2024.1.0
AkArray.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 #ifndef _AKARRAY_H
28 #define _AKARRAY_H
29 
34 
35 #include <utility>
36 
37 template <AkMemID T_MEMID>
39 {
40  static AkForceInline void * Alloc( size_t in_uSize )
41  {
42  return AkAlloc(T_MEMID, in_uSize);
43  }
44 
45  static AkForceInline void * ReAlloc( void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize )
46  {
47  return AkRealloc(T_MEMID, in_pCurrent, in_uNewSize);
48  }
49 
50  static AkForceInline void Free( void * in_pAddress )
51  {
52  AkFree(T_MEMID, in_pAddress);
53  }
54 
55  static AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorNoAlign<T_MEMID> in_srcAlloc, void * in_pSrc )
56  {
57  io_pDest = in_pSrc;
58  }
59 };
60 
61 template <AkMemID T_MEMID>
63 {
64  AkForceInline void * Alloc( size_t in_uSize )
65  {
66  return AkMalign(T_MEMID, in_uSize, AK_SIMD_ALIGNMENT);
67  }
68 
69  AkForceInline void * ReAlloc(void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
70  {
71  return AkReallocAligned(T_MEMID, in_pCurrent, in_uNewSize, AK_SIMD_ALIGNMENT);
72  }
73 
74  AkForceInline void Free( void * in_pAddress )
75  {
76  AkFree(T_MEMID, in_pAddress);
77  }
78 
79  AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorAlignedSimd<T_MEMID> in_srcAlloc, void * in_pSrc )
80  {
81  io_pDest = in_pSrc;
82  }
83 };
84 
85 // AkHybridAllocator
86 // Attempts to allocate from a small buffer of size uBufferSizeBytes, which is contained within the array type. Useful if the array is expected to contain a small number of elements.
87 // If the array grows to a larger size than uBufferSizeBytes, the the memory is allocated with the specified AkMemID.
88 // NOTE: The use of this allocator is not allowed when AkArray::TMovePolicy::IsTrivial() == false,
89 // since TMovePolicy::Move will not be invoked in TransferMem.
90 template< AkUInt32 uBufferSizeBytes, AkUInt8 uAlignmentSize = 1, AkMemID T_MEMID = AkMemID_Object>
92 {
93  static const AkUInt32 _uBufferSizeBytes = uBufferSizeBytes;
94 
95  AkForceInline void * Alloc(size_t in_uSize)
96  {
97  if (in_uSize <= uBufferSizeBytes)
98  return (void *)&m_buffer;
99  return AkMalign(T_MEMID, in_uSize, uAlignmentSize);
100  }
101 
102  AkForceInline void * ReAlloc(void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
103  {
104  if (in_uNewSize <= uBufferSizeBytes)
105  return (void *)&m_buffer;
106 
107  if (&m_buffer != in_pCurrent)
108  return AkReallocAligned(T_MEMID, in_pCurrent, in_uNewSize, uAlignmentSize);
109 
110  void* pAddress = AkMalign(T_MEMID, in_uNewSize, uAlignmentSize);
111  if (!pAddress)
112  return NULL;
113 
114  AKPLATFORM::AkMemCpy(pAddress, m_buffer, (AkUInt32)in_uOldSize);
115  return pAddress;
116  }
117 
118  AkForceInline void Free(void * in_pAddress)
119  {
120  if (&m_buffer != in_pAddress)
121  AkFree(T_MEMID, in_pAddress);
122  }
123 
125  {
126  if (&in_srcAlloc.m_buffer == in_pSrc)
127  {
128  AKPLATFORM::AkMemCpy(m_buffer, in_srcAlloc.m_buffer, uBufferSizeBytes);
129  io_pDest = m_buffer;
130  }
131  else
132  {
133  io_pDest = in_pSrc;
134  }
135  }
136 
137  AK_ALIGN(char m_buffer[uBufferSizeBytes], uAlignmentSize);
138 };
139 
140 // Helper for AkHybridAllocator for uCount items of type T.
141 // NOTE: The use of this allocator is not allowed when AkArray::TMovePolicy::IsTrivial() == false,
142 // since TMovePolicy::Move will not be invoked in TransferMem.
143 template <class T, AkUInt32 uCount = 1, AkMemID MemID = AkMemID_Object>
144 using AkSmallArrayAllocator = AkHybridAllocator<sizeof(T)* uCount, alignof(T), MemID>;
145 
146 template <class T>
148 {
149  // By default the assignment operator is invoked to move elements of an array from slot to slot. If desired,
150  // a custom 'Move' operation can be passed into TMovePolicy to transfer ownership of resources from in_Src to in_Dest.
151  static AkForceInline void Move( T& in_Dest, T& in_Src )
152  {
153  in_Dest = in_Src;
154  }
155 
156  // todo: use std::is_trivially_copyable<T>::value everywhere instead
157  // To do so, we must revise usage of the different policies first.
158  // Until then, it is not recommended to use this policy if T is not trivially copyable.
159  static AkForceInline bool IsTrivial()
160  {
161  return true;
162  }
163 };
164 
165 // AkStdMovePolicy, for non-trivially copyable types.
167 {
168  template <class T>
169  static AkForceInline void Move(T&& io_Dest, T&& io_Src)
170  {
171  io_Dest = std::move(io_Src);
172  }
173 
174  static AkForceInline bool IsTrivial()
175  {
176  return false;
177  }
178 };
179 
180 // AkStdMovePolicy, for trivially copyable types.
182 {
183  template <class T>
184  static AkForceInline void Move(T&& io_Dest, T&& io_Src)
185  {
186  io_Dest = std::move(io_Src);
187  }
188 
189  static AkForceInline bool IsTrivial()
190  {
191  return true;
192  }
193 };
194 
195 // Can be used as TMovePolicy to create arrays of arrays.
196 template <class T>
198 {
199  static AkForceInline void Move( T& in_Dest, T& in_Src )
200  {
201  in_Dest.Transfer(in_Src); //transfer ownership of resources.
202  }
203 
204  static AkForceInline bool IsTrivial()
205  {
206  return false;
207  }
208 };
209 
210 // Common allocators:
215 
217 {
218  static AkUInt32 GrowBy( AkUInt32 /*in_CurrentArraySize*/ ) { return 1; }
219 };
220 
222 {
223  static AkUInt32 GrowBy( AkUInt32 /*in_CurrentArraySize*/ ) { return 0; }
224 };
225 
226 // The hybrid GrowBy policy will try to grow to exactly uCount before growing farther to prevent unneccesary allocations.
227 // The goal is to avoid expanding past uBufferSizeBytes until you have to, then behave like AkGrowByPolicy_Proportional
228 // uCount should be uBufferSizeBytes / sizeof(T)
229 template <AkUInt32 uCount>
231 {
232  static AkUInt32 GrowBy(AkUInt32 in_CurrentArraySize)
233  {
234  if (in_CurrentArraySize < uCount)
235  return uCount - in_CurrentArraySize;
236  else
237  {
238  return in_CurrentArraySize + (in_CurrentArraySize >> 1);
239  }
240  }
241 };
242 
244 {
245  static AkUInt32 GrowBy( AkUInt32 in_CurrentArraySize )
246  {
247  if ( in_CurrentArraySize == 0 )
248  return 1;
249  else
250  return in_CurrentArraySize + ( in_CurrentArraySize >> 1 );
251  }
252 };
253 
254 //#define AkGrowByPolicy_DEFAULT AkGrowByPolicy_Legacy
255 #define AkGrowByPolicy_DEFAULT AkGrowByPolicy_Proportional
256 
257 /// Specific implementation of array
258 template <class T, class ARG_T, class TAlloc = ArrayPoolDefault, class TGrowBy = AkGrowByPolicy_DEFAULT, class TMovePolicy = AkAssignmentMovePolicy<T> > class AkArray : public TAlloc
259 {
260 public:
261  /// Constructor
263  : m_pItems( 0 )
264  , m_uLength( 0 )
265  , m_ulReserved( 0 )
266  {
267  }
268 
269  /// Destructor
271  {
272  AKASSERT( m_pItems == 0 );
273  AKASSERT( m_uLength == 0 );
274  AKASSERT( m_ulReserved == 0 );
275  }
276 
277 // Workaround for SWIG to parse nested structure:
278 // Bypass this inner struct and use a proxy in a separate header.
279 #ifndef SWIG
280  /// Iterator
281  struct Iterator
282  {
283  T* pItem; ///< Pointer to the item in the array.
284 
285  /// + operator
287  {
288  AKASSERT( pItem );
289  Iterator returnedIt;
290  returnedIt.pItem = pItem + inc;
291  return returnedIt;
292  }
293 
294  /// - operator
295  AkUInt32 operator-(Iterator const& rhs) const
296  {
297  AKASSERT((pItem && rhs.pItem)||(!pItem && !rhs.pItem));
298  return (AkUInt32)(pItem - rhs.pItem);
299  }
300 
301  /// ++ operator
303  {
304  AKASSERT( pItem );
305  ++pItem;
306  return *this;
307  }
308 
309  /// -- operator
311  {
312  AKASSERT( pItem );
313  --pItem;
314  return *this;
315  }
316 
317  /// * operator
319  {
320  AKASSERT( pItem );
321  return *pItem;
322  }
323 
324  T* operator->() const
325  {
326  AKASSERT( pItem );
327  return pItem;
328  }
329 
330  /// == operator
331  bool operator ==( const Iterator& in_rOp ) const
332  {
333  return ( pItem == in_rOp.pItem );
334  }
335 
336  /// != operator
337  bool operator !=( const Iterator& in_rOp ) const
338  {
339  return ( pItem != in_rOp.pItem );
340  }
341  };
342 #endif // #ifndef SWIG
343 
344  /// Returns the iterator to the first item of the array, will be End() if the array is empty.
345  Iterator Begin() const
346  {
347  Iterator returnedIt;
348  returnedIt.pItem = m_pItems;
349  return returnedIt;
350  }
351 
352  /// Returns the iterator to the end of the array
353  Iterator End() const
354  {
355  Iterator returnedIt;
356  returnedIt.pItem = m_pItems + m_uLength;
357  return returnedIt;
358  }
359 
360  /// Returns the iterator th the specified item, will be End() if the item is not found
361  Iterator FindEx( ARG_T in_Item ) const
362  {
363  Iterator it = Begin();
364 
365  for ( Iterator itEnd = End(); it != itEnd; ++it )
366  {
367  if ( *it == in_Item )
368  break;
369  }
370 
371  return it;
372  }
373 
374  /// Returns the iterator of the specified item, will be End() if the item is not found
375  /// The array must be in ascending sorted order.
376  Iterator BinarySearch( ARG_T in_Item ) const
377  {
378  AkUInt32 uNumToSearch = Length();
379  T* pBase = m_pItems;
380  T* pPivot;
381 
382  while ( uNumToSearch > 0 )
383  {
384  pPivot = pBase + ( uNumToSearch >> 1 );
385  if ( in_Item == *pPivot )
386  {
387  Iterator result;
388  result.pItem = pPivot;
389  return result;
390  }
391 
392  if ( in_Item > *pPivot )
393  {
394  pBase = pPivot + 1;
395  uNumToSearch--;
396  }
397  uNumToSearch >>= 1;
398  }
399 
400  return End();
401  }
402 
403  /// Erase the specified iterator from the array
404  Iterator Erase( Iterator& in_rIter )
405  {
406  AKASSERT( m_pItems != 0 );
407 
408  if (TMovePolicy::IsTrivial())
409  {
410  T* pItem = in_rIter.pItem;
411  T* pLastItem = m_pItems + (m_uLength - 1);
412 
413  // Destroy item
414  pItem->~T();
415 
416  // Move all others by one <-
417  if (pItem < pLastItem)
418  {
420  pItem,
421  pItem + 1,
422  (AkUInt32)(pLastItem - pItem) * sizeof(T)
423  );
424  }
425  }
426  else
427  {
428  // Move items by 1 <-
429  T* pItemLast = m_pItems + m_uLength - 1;
430 
431  for (T* pItem = in_rIter.pItem; pItem < pItemLast; pItem++)
432  TMovePolicy::Move(pItem[0], pItem[1]);
433 
434  // Destroy the last item
435  pItemLast->~T();
436  }
437 
438  m_uLength--;
439 
440  return in_rIter;
441  }
442 
443  /// Erase the item at the specified index
444  void Erase( unsigned int in_uIndex )
445  {
446  AKASSERT( m_pItems != 0 );
447 
448  if (TMovePolicy::IsTrivial())
449  {
450  T* pItem = m_pItems + in_uIndex;
451 
452  // Destroy item
453  pItem->~T();
454 
455  // Move all others by one <-
456  if (in_uIndex + 1 < m_uLength)
457  {
459  pItem,
460  pItem + 1,
461  (m_uLength - in_uIndex - 1) * sizeof(T)
462  );
463  }
464  }
465  else
466  {
467  // Move items by 1 <-
468  T* pItemLast = m_pItems + m_uLength - 1;
469 
470  for (T* pItem = m_pItems + in_uIndex; pItem < pItemLast; pItem++)
471  TMovePolicy::Move(pItem[0], pItem[1]);
472 
473  // Destroy the last item
474  pItemLast->~T();
475  }
476 
477  m_uLength--;
478  }
479 
480  /// Erase the specified iterator in the array. but it does not guarantee the ordering in the array.
481  /// This version should be used only when the order in the array is not an issue.
482  Iterator EraseSwap( Iterator& in_rIter )
483  {
484  AKASSERT( m_pItems != 0 && Length() > 0 );
485 
486  if (in_rIter.pItem < (m_pItems + m_uLength - 1))
487  {
488  // Swap last item with this one.
489  TMovePolicy::Move( *in_rIter.pItem, Last( ) );
490  }
491 
492  // Destroy.
493  AKASSERT( Length( ) > 0 );
494  Last( ).~T();
495 
496  m_uLength--;
497 
498  return in_rIter;
499  }
500 
501  /// Erase the item at the specified index, but it does not guarantee the ordering in the array.
502  /// This version should be used only when the order in the array is not an issue.
503  void EraseSwap(unsigned int in_uIndex)
504  {
505  Iterator Iterator;
506  Iterator.pItem = m_pItems + in_uIndex;
507  EraseSwap(Iterator);
508  }
509 
510  bool IsGrowingAllowed() const
511  {
512  return TGrowBy::GrowBy( 1 ) != 0;
513  }
514 
515  /// Ensure preallocation of a number of items.
516  ///
517  /// Reserve() won't change the Length() of the array and does nothing if
518  /// in_ulReserve is smaller or equal to current Reserved() size.
519  ///
520  /// If an allocation occurs, i.e. `in_ulReserve > Reserved()`, all iterators and
521  /// all references to the array elements are invalidated.
522  ///
523  /// \note When template parameter `TGrowBy = AkGrowByPolicy_NoGrow`, Reserve() shall
524  /// only be called if the current reserved size is zero.
525  /// It should normally only be called once on init.
526  ///
527  /// \note When template parameter `TGrowBy = AkGrowByPolicy_Proportional`, inappropriate
528  /// calls to Reserve(), e.g. calling it before every AddLast(), may increase the
529  /// number of reallocations and result in decreased performance.
530  inline AKRESULT Reserve(AkUInt32 in_ulReserve)
531  {
532  if (in_ulReserve <= m_ulReserved)
533  return AK_Success;
534 
535  if (m_ulReserved && !IsGrowingAllowed())
536  {
537  AKASSERT(!"AkArray calling Reserve() with AkGrowByPolicy_NoGrow is only allowed when reserved size is zero");
538  return AK_InvalidParameter;
539  }
540 
541  return GrowArray(in_ulReserve - m_ulReserved) ? AK_Success : AK_InsufficientMemory;
542  }
543 
544  /// Ensure preallocation of a number of extra items on top of current array size.
545  /// Same as calling `myArray.Reserve(myArray.Length() + extraItemCount)`.
546  /// \see Reserve()
547  inline AKRESULT ReserveExtra(AkUInt32 in_ulReserve)
548  {
549  return Reserve(Length() + in_ulReserve);
550  }
551 
552  AkUInt32 Reserved() const { return m_ulReserved; }
553 
554  /// Term the array. Must be called before destroying the object.
555  void Term()
556  {
557  if ( m_pItems )
558  {
559  RemoveAll();
561  m_pItems = 0;
562  m_ulReserved = 0;
563  }
564  }
565 
566  /// Returns the numbers of items in the array.
568  {
569  return m_uLength;
570  }
571 
572  /// Returns a pointer to the first item in the array.
573  AkForceInline T * Data() const
574  {
575  return m_pItems;
576  }
577 
578  /// Returns true if the number items in the array is 0, false otherwise.
579  AkForceInline bool IsEmpty() const
580  {
581  return m_uLength == 0;
582  }
583 
584  /// Returns a pointer to the specified item in the list if it exists, 0 if not found.
585  AkForceInline T* Exists(ARG_T in_Item) const
586  {
587  Iterator it = FindEx( in_Item );
588  return ( it != End() ) ? it.pItem : 0;
589  }
590 
591  /// Add an item in the array, without filling it.
592  /// Returns a pointer to the location to be filled.
594  {
595  size_t cItems = Length();
596 
597 #if defined(_MSC_VER)
598 #pragma warning( push )
599 #pragma warning( disable : 4127 )
600 #endif
601  if ( ( cItems >= m_ulReserved ) && IsGrowingAllowed() )
602  {
603  if ( !GrowArray() )
604  return 0;
605  }
606 #if defined(_MSC_VER)
607 #pragma warning( pop )
608 #endif
609 
610  // have we got space for a new one ?
611  if( cItems < m_ulReserved )
612  {
613  T * pEnd = m_pItems + m_uLength++;
614  AkPlacementNew( pEnd ) T;
615  return pEnd;
616  }
617 
618  return 0;
619  }
620 
621  /// Add an item in the array, and fills it with the provided item.
622  AkForceInline T * AddLast(ARG_T in_rItem)
623  {
624  T * pItem = AddLast();
625  if ( pItem )
626  *pItem = in_rItem;
627  return pItem;
628  }
629 
630  /// Returns a reference to the last item in the array.
631  T& Last()
632  {
633  AKASSERT( m_uLength );
634 
635  return *( m_pItems + m_uLength - 1 );
636  }
637 
638  /// Removes the last item from the array.
639  void RemoveLast()
640  {
641  AKASSERT( m_uLength );
642  ( m_pItems + m_uLength - 1 )->~T();
643  m_uLength--;
644  }
645 
646  /// Removes the specified item if found in the array.
647  AKRESULT Remove(ARG_T in_rItem)
648  {
649  Iterator it = FindEx( in_rItem );
650  if ( it != End() )
651  {
652  Erase( it );
653  return AK_Success;
654  }
655 
656  return AK_Fail;
657  }
658 
659  /// Fast remove of the specified item in the array.
660  /// This method do not guarantee keeping ordering of the array.
661  AKRESULT RemoveSwap(ARG_T in_rItem)
662  {
663  Iterator it = FindEx( in_rItem );
664  if ( it != End() )
665  {
666  EraseSwap( it );
667  return AK_Success;
668  }
669 
670  return AK_Fail;
671  }
672 
673  /// Removes all items in the array
674  void RemoveAll()
675  {
676  for ( Iterator it = Begin(), itEnd = End(); it != itEnd; ++it )
677  (*it).~T();
678  m_uLength = 0;
679  }
680 
681  /// Operator [], return a reference to the specified index.
682  AkForceInline T& operator[](unsigned int uiIndex) const
683  {
684  AKASSERT( m_pItems );
685  AKASSERT( uiIndex < Length() );
686  return m_pItems[uiIndex];
687  }
688 
689  /// Insert an item at the specified position without filling it.
690  /// Success: returns an iterator pointing to the new item.
691  /// Failure: returns end iterator.
692  Iterator Insert(Iterator& in_rIter)
693  {
694  AKASSERT(!in_rIter.pItem || m_pItems);
695 
696  AkUInt32 index = (in_rIter.pItem && m_pItems) ? (AkUInt32)(in_rIter.pItem - m_pItems) : 0;
697  if (index <= Length())
698  {
699  if (T* ptr = Insert(index))
700  {
701  Iterator it;
702  it.pItem = ptr;
703  return it;
704  }
705  }
706 
707  return End();
708  }
709 
710  /// Insert an item at the specified position without filling it.
711  /// Returns the pointer to the item to be filled.
712  T * Insert(unsigned int in_uIndex)
713  {
714  AKASSERT( in_uIndex <= Length() );
715 
716  size_t cItems = Length();
717 
718 #if defined(_MSC_VER)
719 #pragma warning( push )
720 #pragma warning( disable : 4127 )
721 #endif
722  if ( ( cItems >= m_ulReserved ) && IsGrowingAllowed() )
723  {
724  if ( !GrowArray() )
725  return 0;
726  }
727 #if defined(_MSC_VER)
728 #pragma warning( pop )
729 #endif
730 
731  // have we got space for a new one ?
732  if (cItems < m_ulReserved)
733  {
734  if (TMovePolicy::IsTrivial())
735  {
736  T* pItem = m_pItems + in_uIndex;
737 
738  // Move items by one ->
739  if (in_uIndex < m_uLength)
740  {
742  pItem + 1,
743  pItem,
744  (m_uLength - in_uIndex) * sizeof(T)
745  );
746  }
747 
748  // Initialize the new item
749  AkPlacementNew(pItem) T;
750 
751  m_uLength++;
752  }
753  else
754  {
755  T* pItemLast = m_pItems + m_uLength++;
756  AkPlacementNew(pItemLast) T;
757 
758  // Move items by 1 ->
759  for (T* pItem = pItemLast; pItem > (m_pItems + in_uIndex); --pItem)
760  TMovePolicy::Move(pItem[0], pItem[-1]);
761 
762  // Reinitialize item at index
763  (m_pItems + in_uIndex)->~T();
764  AkPlacementNew(m_pItems + in_uIndex) T;
765  }
766 
767  return m_pItems + in_uIndex;
768  }
769 
770  return 0;
771  }
772 
773  bool GrowArray()
774  {
775  // If no size specified, growing by the declared growth policy of the array.
776  return GrowArray( TGrowBy::GrowBy( m_ulReserved ) );
777  }
778 
779  /// Resize the array.
780  bool GrowArray( AkUInt32 in_uGrowBy )
781  {
782  AKASSERT( in_uGrowBy );
783 
784  AkUInt32 ulNewReserve = m_ulReserved + in_uGrowBy;
785  T * pNewItems = NULL;
786  size_t cItems = Length();
787 
788  // Reallocate only if IsTrivial() and m_pItems is already allocated.
789  if (m_pItems && TMovePolicy::IsTrivial())
790  {
791  pNewItems = (T *)TAlloc::ReAlloc(m_pItems, sizeof(T) * cItems, sizeof(T) * ulNewReserve);
792  if (!pNewItems)
793  return false;
794  }
795  else
796  {
797  pNewItems = (T *)TAlloc::Alloc(sizeof(T) * ulNewReserve);
798  if (!pNewItems)
799  return false;
800 
801  // Copy all elements in new array, destroy old ones
802  if (m_pItems && m_pItems != pNewItems /*AkHybridAllocator may serve up same memory*/)
803  {
804  for (size_t i = 0; i < cItems; ++i)
805  {
806  AkPlacementNew(pNewItems + i) T;
807 
808  TMovePolicy::Move(pNewItems[i], m_pItems[i]);
809 
810  m_pItems[i].~T();
811  }
812 
814  }
815  }
816 
817  m_pItems = pNewItems;
818  m_ulReserved = ulNewReserve;
819  return true;
820  }
821 
822  /// Resize the array to the specified size.
823  bool Resize(AkUInt32 in_uiSize)
824  {
825  AkUInt32 cItems = Length();
826  if (in_uiSize < cItems)
827  {
828  for (AkUInt32 i = in_uiSize; i < cItems; i++)
829  {
830  m_pItems[i].~T();
831  }
832 
833  m_uLength = in_uiSize;
834  return true;
835  }
836 
837  if ( in_uiSize > m_ulReserved )
838  {
839  if ( !GrowArray(in_uiSize - m_ulReserved) )
840  return false;
841  }
842 
843  //Create the missing items.
844  for(size_t i = cItems; i < in_uiSize; i++)
845  {
846  AkPlacementNew( m_pItems + i ) T;
847  }
848 
849  m_uLength = in_uiSize;
850  return true;
851  }
852 
854  {
855  Term();
856 
857  TAlloc::TransferMem( (void*&)m_pItems, in_rSource, (void*)in_rSource.m_pItems );
858  m_uLength = in_rSource.m_uLength;
859  m_ulReserved = in_rSource.m_ulReserved;
860 
861  in_rSource.m_pItems = NULL;
862  in_rSource.m_uLength = 0;
863  in_rSource.m_ulReserved = 0;
864  }
865 
867  {
868  RemoveAll();
869 
870  if (Resize(in_rSource.Length()))
871  {
872  for (AkUInt32 i = 0; i < in_rSource.Length(); ++i)
873  m_pItems[i] = in_rSource.m_pItems[i];
874  return AK_Success;
875  }
876  return AK_Fail;
877  }
878 
879 protected:
880 
881  T * m_pItems; ///< pointer to the beginning of the array.
882  AkUInt32 m_uLength; ///< number of items in the array.
883  AkUInt32 m_ulReserved; ///< how many we can have at most (currently allocated).
884 };
885 
886 
887 #endif
void EraseSwap(unsigned int in_uIndex)
Definition: AkArray.h:503
static AkForceInline void TransferMem(void *&io_pDest, AkArrayAllocatorNoAlign< T_MEMID > in_srcAlloc, void *in_pSrc)
Definition: AkArray.h:55
AkForceInline void TransferMem(void *&io_pDest, AkHybridAllocator< uBufferSizeBytes, uAlignmentSize, T_MEMID > &in_srcAlloc, void *in_pSrc)
Definition: AkArray.h:124
AkUInt32 operator-(Iterator const &rhs) const
Definition: AkArray.h:295
AkForceInline void * Alloc(size_t in_uSize)
Definition: AkArray.h:64
AkForceInline void Free(void *in_pAddress)
Definition: AkArray.h:74
Iterator & operator++()
++ operator
Definition: AkArray.h:302
static const AkUInt32 _uBufferSizeBytes
Definition: AkArray.h:93
AkForceInline void AkMemMove(void *pDest, const void *pSrc, AkUInt32 uSize)
~AkArray()
Destructor.
Definition: AkArray.h:270
@ AK_Fail
The operation failed.
Definition: AkTypes.h:137
bool IsGrowingAllowed() const
Definition: AkArray.h:510
AkForceInline void * ReAlloc(void *in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
Definition: AkArray.h:102
AKRESULT Copy(const AkArray< T, ARG_T, TAlloc, TGrowBy, TMovePolicy > &in_rSource)
Definition: AkArray.h:866
Iterator FindEx(ARG_T in_Item) const
Returns the iterator th the specified item, will be End() if the item is not found.
Definition: AkArray.h:361
#define AkPlacementNew(_memory)
void RemoveAll()
Removes all items in the array.
Definition: AkArray.h:674
#define AkFree(_pool, _pvmem)
Definition: AkObject.h:58
AKSOUNDENGINE_API void Free(AkMemPoolId in_poolId, void *in_pMemAddress)
AK_ALIGN(char m_buffer[uBufferSizeBytes], uAlignmentSize)
T & Last()
Returns a reference to the last item in the array.
Definition: AkArray.h:631
AKRESULT
Standard function call result.
Definition: AkTypes.h:134
AkForceInline void * ReAlloc(void *in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
Definition: AkArray.h:69
AKRESULT RemoveSwap(ARG_T in_rItem)
Definition: AkArray.h:661
AkArrayAllocatorAlignedSimd< AkMemID_Processing > ArrayPoolLEngineDefaultAlignedSimd
Definition: AkArray.h:214
AkForceInline void Free(void *in_pAddress)
Definition: AkArray.h:118
static AkUInt32 GrowBy(AkUInt32 in_CurrentArraySize)
Definition: AkArray.h:232
AkForceInline T * Exists(ARG_T in_Item) const
Returns a pointer to the specified item in the list if it exists, 0 if not found.
Definition: AkArray.h:585
Specific implementation of array.
Definition: AkArray.h:259
#define AkAlloc(_pool, _size)
Definition: AkObject.h:51
#define NULL
Definition: AkTypes.h:46
static AkForceInline bool IsTrivial()
Definition: AkArray.h:174
T * pItem
Pointer to the item in the array.
Definition: AkArray.h:283
@ AK_Success
The operation was successful.
Definition: AkTypes.h:136
bool GrowArray(AkUInt32 in_uGrowBy)
Resize the array.
Definition: AkArray.h:780
T * operator->() const
Definition: AkArray.h:324
AkArrayAllocatorNoAlign< AkMemID_Profiler > ArrayPoolProfiler
Definition: AkArray.h:213
AkArrayAllocatorNoAlign< AkMemID_Processing > ArrayPoolLEngineDefault
Definition: AkArray.h:212
AkForceInline void TransferMem(void *&io_pDest, AkArrayAllocatorAlignedSimd< T_MEMID > in_srcAlloc, void *in_pSrc)
Definition: AkArray.h:79
bool operator==(const Iterator &in_rOp) const
== operator
Definition: AkArray.h:331
void RemoveLast()
Removes the last item from the array.
Definition: AkArray.h:639
@ AK_InvalidParameter
Something is not within bounds, check the documentation of the function returning this code.
Definition: AkTypes.h:152
static AkForceInline void * Alloc(size_t in_uSize)
Definition: AkArray.h:40
AkUInt32 m_uLength
number of items in the array.
Definition: AkArray.h:882
bool Resize(AkUInt32 in_uiSize)
Resize the array to the specified size.
Definition: AkArray.h:823
AkArray()
Constructor.
Definition: AkArray.h:262
AkForceInline T * AddLast(ARG_T in_rItem)
Add an item in the array, and fills it with the provided item.
Definition: AkArray.h:622
Iterator.
Definition: AkArray.h:282
#define AKASSERT(Condition)
Definition: AkAssert.h:67
static AkUInt32 GrowBy(AkUInt32)
Definition: AkArray.h:223
static AkForceInline void * ReAlloc(void *in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
Definition: AkArray.h:45
AKRESULT ReserveExtra(AkUInt32 in_ulReserve)
Definition: AkArray.h:547
AkForceInline void AkMemCpy(void *pDest, const void *pSrc, AkUInt32 uSize)
Platform Independent Helper for memcpy/memmove/memset.
Iterator End() const
Returns the iterator to the end of the array.
Definition: AkArray.h:353
AkUInt32 Reserved() const
Definition: AkArray.h:552
Iterator Insert(Iterator &in_rIter)
Definition: AkArray.h:692
AkForceInline void * Alloc(size_t in_uSize)
Definition: AkArray.h:95
#define AK_SIMD_ALIGNMENT
Platform-specific alignment requirement for SIMD data.
Definition: AkTypes.h:52
void Transfer(AkArray< T, ARG_T, TAlloc, TGrowBy, TMovePolicy > &in_rSource)
Definition: AkArray.h:853
Iterator Erase(Iterator &in_rIter)
Erase the specified iterator from the array.
Definition: AkArray.h:404
static AkForceInline void Move(T &in_Dest, T &in_Src)
Definition: AkArray.h:199
#define AkMalign(_pool, _size, _align)
Definition: AkObject.h:52
AkUInt32 m_ulReserved
how many we can have at most (currently allocated).
Definition: AkArray.h:883
Iterator Begin() const
Returns the iterator to the first item of the array, will be End() if the array is empty.
Definition: AkArray.h:345
AkForceInline AkUInt32 Length() const
Returns the numbers of items in the array.
Definition: AkArray.h:567
static AkForceInline bool IsTrivial()
Definition: AkArray.h:204
#define AkRealloc(_pool, _pvmem, _size)
Definition: AkObject.h:54
AkArrayAllocatorNoAlign< AkMemID_Object > ArrayPoolDefault
Definition: AkArray.h:211
AKRESULT Remove(ARG_T in_rItem)
Removes the specified item if found in the array.
Definition: AkArray.h:647
void Erase(unsigned int in_uIndex)
Erase the item at the specified index.
Definition: AkArray.h:444
bool operator!=(const Iterator &in_rOp) const
!= operator
Definition: AkArray.h:337
bool GrowArray()
Definition: AkArray.h:773
AkForceInline T * AddLast()
Definition: AkArray.h:593
static AkForceInline void Free(void *in_pAddress)
Definition: AkArray.h:50
uint32_t AkUInt32
Unsigned 32-bit integer.
void Term()
Term the array. Must be called before destroying the object.
Definition: AkArray.h:555
static AkForceInline bool IsTrivial()
Definition: AkArray.h:159
@ AK_InsufficientMemory
Memory error.
Definition: AkTypes.h:164
static AkUInt32 GrowBy(AkUInt32 in_CurrentArraySize)
Definition: AkArray.h:245
static AkUInt32 GrowBy(AkUInt32)
Definition: AkArray.h:218
AkForceInline bool IsEmpty() const
Returns true if the number items in the array is 0, false otherwise.
Definition: AkArray.h:579
static AkForceInline void Move(T &in_Dest, T &in_Src)
Definition: AkArray.h:151
#define AkForceInline
Definition: AkTypes.h:63
AkForceInline T * Data() const
Returns a pointer to the first item in the array.
Definition: AkArray.h:573
T * Insert(unsigned int in_uIndex)
Definition: AkArray.h:712
Iterator & operator--()
– operator
Definition: AkArray.h:310
Iterator EraseSwap(Iterator &in_rIter)
Definition: AkArray.h:482
AkForceInline T & operator[](unsigned int uiIndex) const
Operator [], return a reference to the specified index.
Definition: AkArray.h:682
#define AkReallocAligned(_pool, _pvmem, _size, _align)
Definition: AkObject.h:55
AKRESULT Reserve(AkUInt32 in_ulReserve)
Definition: AkArray.h:530
Iterator operator+(AkUInt32 inc) const
Definition: AkArray.h:286
static AkForceInline void Move(T &&io_Dest, T &&io_Src)
Definition: AkArray.h:169
Iterator BinarySearch(ARG_T in_Item) const
Definition: AkArray.h:376
T * m_pItems
pointer to the beginning of the array.
Definition: AkArray.h:881
static AkForceInline void Move(T &&io_Dest, T &&io_Src)
Definition: AkArray.h:184
static AkForceInline bool IsTrivial()
Definition: AkArray.h:189

Cette page a-t-elle été utile ?

Besoin d'aide ?

Des questions ? Des problèmes ? Besoin de plus d'informations ? Contactez-nous, nous pouvons vous aider !

Visitez notre page d'Aide

Décrivez-nous de votre projet. Nous sommes là pour vous aider.

Enregistrez votre projet et nous vous aiderons à démarrer sans aucune obligation !

Partir du bon pied avec Wwise