123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- /*******************************************************************************
- The content of this file includes portions of the AUDIOKINETIC Wwise Technology
- released in source code form as part of the SDK installer package.
- Commercial License Usage
- Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
- may use this file in accordance with the end user license agreement provided
- with the software or, alternatively, in accordance with the terms contained in a
- written agreement between you and Audiokinetic Inc.
- Apache License Usage
- Alternatively, this file may be used under the Apache License, Version 2.0 (the
- "Apache License"); you may not use this file except in compliance with the
- Apache License. You may obtain a copy of the Apache License at
- http://www.apache.org/licenses/LICENSE-2.0.
- Unless required by applicable law or agreed to in writing, software distributed
- under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
- OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
- the specific language governing permissions and limitations under the License.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- // AkListBare.h
- #ifndef _AKLISTBARE_H
- #define _AKLISTBARE_H
- // this one lets you define the structure
- // only requirement is that T must have member pNextItem (if using the default AkListBareNextItem policy struct).
- // client is responsible for allocation/deallocation of T.
- // WATCH OUT !
- // - remember that removeall/term can't delete the elements for you.
- // - be sure to destroy elements AFTER removing them from the list, as remove will
- // access members of the element.
- /* Usage: List of AkMyType.
- - With default AkMyType::pNextItem, no count (Length() is not available):
- typedef AkListBare<AkMyType> AkMyList1;
- - With custom AkMyType::pNextItemCustom, no count:
- struct AkListBareNextItemCustom
- {
- static AkForceInline AkMyType *& Get( AkMyType * in_pItem )
- {
- return in_pItem->pNextItemCustom;
- }
- };
- typedef AkListBare<AkMyType,AkListBareNextItemCustom> AkMyList2;
- - With default AkMyType::pNextItem, WITH count (Length() is available):
- typedef AkListBare<AkMyType,AkListBareNextItem,AkCountPolicyWithCount> AkMyList3;
- */
- //
- // List bare policy classes.
- //
- /// Next item name policy.
- template <class T> struct AkListBareNextItem
- {
- /// Default policy.
- static AkForceInline T *& Get( T * in_pItem )
- {
- return in_pItem->pNextItem;
- }
- };
- /// Item count policy. These policy classes must define protected methods
- /// ResetCount(), IncrementCount(), DecrementCount() and optionally, public unsigned int Length() const.
- template <class T>
- class AkCountPolicyNoCount
- {
- protected:
- AkForceInline void ResetCount( T* ) {}
- AkForceInline void IncrementCount( T* ) {}
- AkForceInline void DecrementCount( T* ) {}
- };
- template <class T>
- class AkCountPolicyWithCount
- {
- public:
- /// Get list length.
- AkForceInline unsigned int Length() const
- {
- return m_ulNumListItems;
- }
- protected:
- AkCountPolicyWithCount() :m_ulNumListItems( 0 ) {}
- AkForceInline void ResetCount( T* ) { m_ulNumListItems = 0; }
- AkForceInline void IncrementCount( T* ) { ++m_ulNumListItems; }
- AkForceInline void DecrementCount( T* ) { --m_ulNumListItems; }
- private:
- unsigned int m_ulNumListItems; ///< how many we have
- };
- /// Last item policy. These policy classes must define protected methods
- /// UpdateLast(), SetLast(), RemoveItem() and AddItem().
- template <class T>
- class AkLastPolicyWithLast
- {
- public:
- /// Get last element.
- AkForceInline T * Last() { return m_pLast; }
- AkForceInline const T * Last() const { return m_pLast; }
- protected:
- AkForceInline AkLastPolicyWithLast() : m_pLast( NULL ) {}
- // Policy interface:
- // UpdateLast() is called by host to inform the policy that it should set the last item to a new value.
- // The policy is thus free to do what it wants. On the other hand, SetLast() must make sense for the user of the list,
- // otherwise it must not be implemented.
- AkForceInline void UpdateLast( T * in_pLast ) { m_pLast = in_pLast; }
- AkForceInline void SetLast( T * in_pLast ) { m_pLast = in_pLast; }
- AkForceInline void RemoveItem( T * in_pItem, T * in_pPrevItem )
- {
- // Is it the last one ?
- if( in_pItem == m_pLast )
- {
- // new last one is the previous one
- m_pLast = in_pPrevItem;
- }
- }
- AkForceInline void AddItem( T * in_pItem, T * in_pNextItem )
- {
- // Update tail.
- // Note: will never occur since it is used with iteratorEx (have EndEx?).
- if ( in_pNextItem == NULL )
- m_pLast = in_pItem;
- }
- protected:
- T * m_pLast; ///< bottom of list
- };
- template <class T>
- class AkLastPolicyNoLast
- {
- protected:
- // Policy interface:
- // UpdateLast() is called by host to inform the policy that it should set the last item to a new value.
- // The policy is thus free to do what it wants. On the other hand, SetLast() must make sense for the user of the list,
- // otherwise it must not be implemented.
- AkForceInline void UpdateLast( T * ) {}
- // SetLast is voluntarily left undefined so that calling AkListBare::AddLast() with this policy results in a compile-time error.
- //AkForceInline void SetLast( T * in_pLast );
- AkForceInline void RemoveItem( T *, T * ) {}
- AkForceInline void AddItem( T *, T * ) {}
- };
- /// Implementation of List Bare.
- template <class T, template <class> class U_NEXTITEM = AkListBareNextItem, template <class> class COUNT_POLICY = AkCountPolicyNoCount, template <class> class LAST_POLICY = AkLastPolicyWithLast > class AkListBare : public COUNT_POLICY< T >, public LAST_POLICY< T >
- {
- public:
- /// Iterator.
- struct Iterator
- {
- T* pItem; ///< Next item.
- /// Operator ++.
- inline Iterator& operator++()
- {
- AKASSERT( pItem );
- pItem = U_NEXTITEM<T>::Get( pItem );
- return *this;
- }
- /// Operator *.
- inline T * operator*() const
- {
- AKASSERT( pItem );
- return pItem;
- }
- /// Operator ->
- inline T * operator->() const
- {
- AKASSERT(pItem);
- return pItem;
- }
- /// Operator !=.
- bool operator !=( const Iterator& in_rOp ) const
- {
- return ( pItem != in_rOp.pItem );
- }
-
- /// Operator ==.
- bool operator ==( const Iterator& in_rOp ) const
- {
- return ( pItem == in_rOp.pItem );
- }
- };
- /// The IteratorEx iterator is intended for usage when a possible erase may occurs
- /// when simply iterating trough a list, use the simple Iterator, it is faster and lighter.
- struct IteratorEx : public Iterator
- {
- T* pPrevItem; ///< Previous item.
- /// Operator ++.
- IteratorEx& operator++()
- {
- AKASSERT( this->pItem );
-
- pPrevItem = this->pItem;
- this->pItem = U_NEXTITEM<T>::Get( this->pItem );
-
- return *this;
- }
- };
- /// Erase item.
- IteratorEx Erase( const IteratorEx& in_rIter )
- {
- IteratorEx returnedIt;
- returnedIt.pItem = U_NEXTITEM<T>::Get( in_rIter.pItem );
- returnedIt.pPrevItem = in_rIter.pPrevItem;
- RemoveItem( in_rIter.pItem, in_rIter.pPrevItem );
- return returnedIt;
- }
- /// Insert item.
- IteratorEx Insert( const IteratorEx& in_rIter,
- T * in_pItem )
- {
- IteratorEx returnedIt;
- AddItem( in_pItem, in_rIter.pItem, in_rIter.pPrevItem );
- returnedIt = in_rIter;
- returnedIt.pPrevItem = in_pItem;
- return returnedIt;
- }
- /// End condition.
- inline Iterator End() const
- {
- Iterator returnedIt;
- returnedIt.pItem = NULL;
- return returnedIt;
- }
- /// Get IteratorEx at beginning.
- inline IteratorEx BeginEx()
- {
- IteratorEx returnedIt;
-
- returnedIt.pItem = m_pFirst;
- returnedIt.pPrevItem = NULL;
-
- return returnedIt;
- }
- /// Get Iterator at beginning.
- inline Iterator Begin() const
- {
- Iterator returnedIt;
-
- returnedIt.pItem = m_pFirst;
-
- return returnedIt;
- }
- /// Get Iterator from item.
- inline IteratorEx FindEx( T * in_pItem )
- {
- IteratorEx it = BeginEx();
- for ( ; it != End(); ++it )
- {
- if ( it.pItem == in_pItem )
- break;
- }
- return it;
- }
- /// Constructor.
- AkListBare()
- : m_pFirst( NULL )
- {
- }
-
- /// Destructor.
- ~AkListBare()
- {
- }
- /// Terminate.
- void Term()
- {
- RemoveAll();
- }
- /// Add element at the beginning of list.
- void AddFirst( T * in_pItem )
- {
- if ( m_pFirst == NULL )
- {
- m_pFirst = in_pItem;
- LAST_POLICY<T>::UpdateLast( in_pItem );
- U_NEXTITEM<T>::Get( in_pItem ) = NULL;
- }
- else
- {
- U_NEXTITEM<T>::Get( in_pItem ) = m_pFirst;
- m_pFirst = in_pItem;
- }
- COUNT_POLICY<T>::IncrementCount( in_pItem );
- }
- /// Add element at the end of list.
- void AddLast( T * in_pItem )
- {
- U_NEXTITEM<T>::Get( in_pItem ) = NULL;
- if ( m_pFirst == NULL )
- {
- m_pFirst = in_pItem;
- }
- else
- {
- U_NEXTITEM<T>::Get( LAST_POLICY<T>::Last() ) = in_pItem;
- }
- LAST_POLICY<T>::SetLast( in_pItem );
- COUNT_POLICY<T>::IncrementCount( in_pItem );
- }
- /// Remove an element.
- AKRESULT Remove( T * in_pItem )
- {
- IteratorEx it = FindEx( in_pItem );
- if ( it != End() )
- {
- Erase( it );
- return AK_Success;
- }
- return AK_Fail;
- }
- /// Remove the first element.
- AKRESULT RemoveFirst()
- {
- if( m_pFirst == NULL )
- return AK_Fail;
- if ( U_NEXTITEM<T>::Get( m_pFirst ) == NULL )
- {
- m_pFirst = NULL;
- LAST_POLICY<T>::UpdateLast( NULL );
- }
- else
- {
- m_pFirst = U_NEXTITEM<T>::Get( m_pFirst );
- }
- COUNT_POLICY<T>::DecrementCount( m_pFirst );
- return AK_Success;
- }
- /// Remove all elements.
- AkForceInline void RemoveAll()
- {
- // Items being externally managed, all we need to do here is clear our members.
- m_pFirst = NULL;
- LAST_POLICY<T>::UpdateLast( NULL );
- COUNT_POLICY<T>::ResetCount( m_pFirst );
- }
- /// Get first element.
- AkForceInline T * First()
- {
- return m_pFirst;
- }
- /// Empty condition.
- AkForceInline bool IsEmpty() const
- {
- return m_pFirst == NULL;
- }
- /// Remove an element.
- void RemoveItem( T * in_pItem, T * in_pPrevItem )
- {
- // Is it the first one ?
- if( in_pItem == m_pFirst )
- {
- // new first one is the next one
- m_pFirst = U_NEXTITEM<T>::Get( in_pItem );
- }
- else
- {
- // take it out of the used space
- U_NEXTITEM<T>::Get( in_pPrevItem ) = U_NEXTITEM<T>::Get( in_pItem );
- }
- LAST_POLICY<T>::RemoveItem( in_pItem, in_pPrevItem );
- COUNT_POLICY<T>::DecrementCount( m_pFirst );
- }
- /// Add an element.
- void AddItem( T * in_pItem, T * in_pNextItem, T * in_pPrevItem )
- {
- U_NEXTITEM<T>::Get( in_pItem ) = in_pNextItem;
- if ( in_pPrevItem == NULL )
- m_pFirst = in_pItem;
- else
- U_NEXTITEM<T>::Get( in_pPrevItem ) = in_pItem;
- LAST_POLICY<T>::AddItem( in_pItem, in_pNextItem );
-
- COUNT_POLICY<T>::IncrementCount( in_pItem );
- }
- void Transfer(AkListBare<T,U_NEXTITEM,COUNT_POLICY,LAST_POLICY>& in_src)
- {
- Term();
- m_pFirst = in_src.m_pFirst;
- in_src.m_pFirst = nullptr;
- }
- protected:
- T * m_pFirst; ///< top of list
- };
- #endif // _AKLISTBARE_H
|