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

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