AkListBare.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. // AkListBare.h
  21. #ifndef _AKLISTBARE_H
  22. #define _AKLISTBARE_H
  23. // this one lets you define the structure
  24. // only requirement is that T must have member pNextItem (if using the default AkListBareNextItem policy struct).
  25. // client is responsible for allocation/deallocation of T.
  26. // WATCH OUT !
  27. // - remember that removeall/term can't delete the elements for you.
  28. // - be sure to destroy elements AFTER removing them from the list, as remove will
  29. // access members of the element.
  30. /* Usage: List of AkMyType.
  31. - With default AkMyType::pNextItem, no count (Length() is not available):
  32. typedef AkListBare<AkMyType> AkMyList1;
  33. - With custom AkMyType::pNextItemCustom, no count:
  34. struct AkListBareNextItemCustom
  35. {
  36. static AkForceInline AkMyType *& Get( AkMyType * in_pItem )
  37. {
  38. return in_pItem->pNextItemCustom;
  39. }
  40. };
  41. typedef AkListBare<AkMyType,AkListBareNextItemCustom> AkMyList2;
  42. - With default AkMyType::pNextItem, WITH count (Length() is available):
  43. typedef AkListBare<AkMyType,AkListBareNextItem,AkCountPolicyWithCount> AkMyList3;
  44. */
  45. //
  46. // List bare policy classes.
  47. //
  48. /// Next item name policy.
  49. template <class T> struct AkListBareNextItem
  50. {
  51. /// Default policy.
  52. static AkForceInline T *& Get( T * in_pItem )
  53. {
  54. return in_pItem->pNextItem;
  55. }
  56. };
  57. /// Item count policy. These policy classes must define protected methods
  58. /// ResetCount(), IncrementCount(), DecrementCount() and optionally, public unsigned int Length() const.
  59. template <class T>
  60. class AkCountPolicyNoCount
  61. {
  62. protected:
  63. AkForceInline void ResetCount( T* ) {}
  64. AkForceInline void IncrementCount( T* ) {}
  65. AkForceInline void DecrementCount( T* ) {}
  66. };
  67. template <class T>
  68. class AkCountPolicyWithCount
  69. {
  70. public:
  71. /// Get list length.
  72. AkForceInline unsigned int Length() const
  73. {
  74. return m_ulNumListItems;
  75. }
  76. protected:
  77. AkCountPolicyWithCount() :m_ulNumListItems( 0 ) {}
  78. AkForceInline void ResetCount( T* ) { m_ulNumListItems = 0; }
  79. AkForceInline void IncrementCount( T* ) { ++m_ulNumListItems; }
  80. AkForceInline void DecrementCount( T* ) { --m_ulNumListItems; }
  81. private:
  82. unsigned int m_ulNumListItems; ///< how many we have
  83. };
  84. /// Last item policy. These policy classes must define protected methods
  85. /// UpdateLast(), SetLast(), RemoveItem() and AddItem().
  86. template <class T>
  87. class AkLastPolicyWithLast
  88. {
  89. public:
  90. /// Get last element.
  91. AkForceInline T * Last() { return m_pLast; }
  92. AkForceInline const T * Last() const { return m_pLast; }
  93. protected:
  94. AkForceInline AkLastPolicyWithLast() : m_pLast( NULL ) {}
  95. // Policy interface:
  96. // UpdateLast() is called by host to inform the policy that it should set the last item to a new value.
  97. // The policy is thus free to do what it wants. On the other hand, SetLast() must make sense for the user of the list,
  98. // otherwise it must not be implemented.
  99. AkForceInline void UpdateLast( T * in_pLast ) { m_pLast = in_pLast; }
  100. AkForceInline void SetLast( T * in_pLast ) { m_pLast = in_pLast; }
  101. AkForceInline void RemoveItem( T * in_pItem, T * in_pPrevItem )
  102. {
  103. // Is it the last one ?
  104. if( in_pItem == m_pLast )
  105. {
  106. // new last one is the previous one
  107. m_pLast = in_pPrevItem;
  108. }
  109. }
  110. AkForceInline void AddItem( T * in_pItem, T * in_pNextItem )
  111. {
  112. // Update tail.
  113. // Note: will never occur since it is used with iteratorEx (have EndEx?).
  114. if ( in_pNextItem == NULL )
  115. m_pLast = in_pItem;
  116. }
  117. protected:
  118. T * m_pLast; ///< bottom of list
  119. };
  120. template <class T>
  121. class AkLastPolicyNoLast
  122. {
  123. protected:
  124. // Policy interface:
  125. // UpdateLast() is called by host to inform the policy that it should set the last item to a new value.
  126. // The policy is thus free to do what it wants. On the other hand, SetLast() must make sense for the user of the list,
  127. // otherwise it must not be implemented.
  128. AkForceInline void UpdateLast( T * ) {}
  129. // SetLast is voluntarily left undefined so that calling AkListBare::AddLast() with this policy results in a compile-time error.
  130. //AkForceInline void SetLast( T * in_pLast );
  131. AkForceInline void RemoveItem( T *, T * ) {}
  132. AkForceInline void AddItem( T *, T * ) {}
  133. };
  134. /// Implementation of List Bare.
  135. 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 >
  136. {
  137. public:
  138. /// Iterator.
  139. struct Iterator
  140. {
  141. T* pItem; ///< Next item.
  142. /// Operator ++.
  143. inline Iterator& operator++()
  144. {
  145. AKASSERT( pItem );
  146. pItem = U_NEXTITEM<T>::Get( pItem );
  147. return *this;
  148. }
  149. /// Operator *.
  150. inline T * operator*() const
  151. {
  152. AKASSERT( pItem );
  153. return pItem;
  154. }
  155. /// Operator ->
  156. inline T * operator->() const
  157. {
  158. AKASSERT(pItem);
  159. return pItem;
  160. }
  161. /// Operator !=.
  162. bool operator !=( const Iterator& in_rOp ) const
  163. {
  164. return ( pItem != in_rOp.pItem );
  165. }
  166. /// Operator ==.
  167. bool operator ==( const Iterator& in_rOp ) const
  168. {
  169. return ( pItem == in_rOp.pItem );
  170. }
  171. };
  172. /// The IteratorEx iterator is intended for usage when a possible erase may occurs
  173. /// when simply iterating trough a list, use the simple Iterator, it is faster and lighter.
  174. struct IteratorEx : public Iterator
  175. {
  176. T* pPrevItem; ///< Previous item.
  177. /// Operator ++.
  178. IteratorEx& operator++()
  179. {
  180. AKASSERT( this->pItem );
  181. pPrevItem = this->pItem;
  182. this->pItem = U_NEXTITEM<T>::Get( this->pItem );
  183. return *this;
  184. }
  185. };
  186. /// Erase item.
  187. IteratorEx Erase( const IteratorEx& in_rIter )
  188. {
  189. IteratorEx returnedIt;
  190. returnedIt.pItem = U_NEXTITEM<T>::Get( in_rIter.pItem );
  191. returnedIt.pPrevItem = in_rIter.pPrevItem;
  192. RemoveItem( in_rIter.pItem, in_rIter.pPrevItem );
  193. return returnedIt;
  194. }
  195. /// Insert item.
  196. IteratorEx Insert( const IteratorEx& in_rIter,
  197. T * in_pItem )
  198. {
  199. IteratorEx returnedIt;
  200. AddItem( in_pItem, in_rIter.pItem, in_rIter.pPrevItem );
  201. returnedIt = in_rIter;
  202. returnedIt.pPrevItem = in_pItem;
  203. return returnedIt;
  204. }
  205. /// End condition.
  206. inline Iterator End() const
  207. {
  208. Iterator returnedIt;
  209. returnedIt.pItem = NULL;
  210. return returnedIt;
  211. }
  212. /// Get IteratorEx at beginning.
  213. inline IteratorEx BeginEx()
  214. {
  215. IteratorEx returnedIt;
  216. returnedIt.pItem = m_pFirst;
  217. returnedIt.pPrevItem = NULL;
  218. return returnedIt;
  219. }
  220. /// Get Iterator at beginning.
  221. inline Iterator Begin() const
  222. {
  223. Iterator returnedIt;
  224. returnedIt.pItem = m_pFirst;
  225. return returnedIt;
  226. }
  227. /// Get Iterator from item.
  228. inline IteratorEx FindEx( T * in_pItem )
  229. {
  230. IteratorEx it = BeginEx();
  231. for ( ; it != End(); ++it )
  232. {
  233. if ( it.pItem == in_pItem )
  234. break;
  235. }
  236. return it;
  237. }
  238. /// Constructor.
  239. AkListBare()
  240. : m_pFirst( NULL )
  241. {
  242. }
  243. /// Destructor.
  244. ~AkListBare()
  245. {
  246. }
  247. /// Terminate.
  248. void Term()
  249. {
  250. RemoveAll();
  251. }
  252. /// Add element at the beginning of list.
  253. void AddFirst( T * in_pItem )
  254. {
  255. if ( m_pFirst == NULL )
  256. {
  257. m_pFirst = in_pItem;
  258. LAST_POLICY<T>::UpdateLast( in_pItem );
  259. U_NEXTITEM<T>::Get( in_pItem ) = NULL;
  260. }
  261. else
  262. {
  263. U_NEXTITEM<T>::Get( in_pItem ) = m_pFirst;
  264. m_pFirst = in_pItem;
  265. }
  266. COUNT_POLICY<T>::IncrementCount( in_pItem );
  267. }
  268. /// Add element at the end of list.
  269. void AddLast( T * in_pItem )
  270. {
  271. U_NEXTITEM<T>::Get( in_pItem ) = NULL;
  272. if ( m_pFirst == NULL )
  273. {
  274. m_pFirst = in_pItem;
  275. }
  276. else
  277. {
  278. U_NEXTITEM<T>::Get( LAST_POLICY<T>::Last() ) = in_pItem;
  279. }
  280. LAST_POLICY<T>::SetLast( in_pItem );
  281. COUNT_POLICY<T>::IncrementCount( in_pItem );
  282. }
  283. /// Remove an element.
  284. AKRESULT Remove( T * in_pItem )
  285. {
  286. IteratorEx it = FindEx( in_pItem );
  287. if ( it != End() )
  288. {
  289. Erase( it );
  290. return AK_Success;
  291. }
  292. return AK_Fail;
  293. }
  294. /// Remove the first element.
  295. AKRESULT RemoveFirst()
  296. {
  297. if( m_pFirst == NULL )
  298. return AK_Fail;
  299. if ( U_NEXTITEM<T>::Get( m_pFirst ) == NULL )
  300. {
  301. m_pFirst = NULL;
  302. LAST_POLICY<T>::UpdateLast( NULL );
  303. }
  304. else
  305. {
  306. m_pFirst = U_NEXTITEM<T>::Get( m_pFirst );
  307. }
  308. COUNT_POLICY<T>::DecrementCount( m_pFirst );
  309. return AK_Success;
  310. }
  311. /// Remove all elements.
  312. AkForceInline void RemoveAll()
  313. {
  314. // Items being externally managed, all we need to do here is clear our members.
  315. m_pFirst = NULL;
  316. LAST_POLICY<T>::UpdateLast( NULL );
  317. COUNT_POLICY<T>::ResetCount( m_pFirst );
  318. }
  319. /// Get first element.
  320. AkForceInline T * First()
  321. {
  322. return m_pFirst;
  323. }
  324. /// Empty condition.
  325. AkForceInline bool IsEmpty() const
  326. {
  327. return m_pFirst == NULL;
  328. }
  329. /// Remove an element.
  330. void RemoveItem( T * in_pItem, T * in_pPrevItem )
  331. {
  332. // Is it the first one ?
  333. if( in_pItem == m_pFirst )
  334. {
  335. // new first one is the next one
  336. m_pFirst = U_NEXTITEM<T>::Get( in_pItem );
  337. }
  338. else
  339. {
  340. // take it out of the used space
  341. U_NEXTITEM<T>::Get( in_pPrevItem ) = U_NEXTITEM<T>::Get( in_pItem );
  342. }
  343. LAST_POLICY<T>::RemoveItem( in_pItem, in_pPrevItem );
  344. COUNT_POLICY<T>::DecrementCount( m_pFirst );
  345. }
  346. /// Add an element.
  347. void AddItem( T * in_pItem, T * in_pNextItem, T * in_pPrevItem )
  348. {
  349. U_NEXTITEM<T>::Get( in_pItem ) = in_pNextItem;
  350. if ( in_pPrevItem == NULL )
  351. m_pFirst = in_pItem;
  352. else
  353. U_NEXTITEM<T>::Get( in_pPrevItem ) = in_pItem;
  354. LAST_POLICY<T>::AddItem( in_pItem, in_pNextItem );
  355. COUNT_POLICY<T>::IncrementCount( in_pItem );
  356. }
  357. void Transfer(AkListBare<T,U_NEXTITEM,COUNT_POLICY,LAST_POLICY>& in_src)
  358. {
  359. Term();
  360. m_pFirst = in_src.m_pFirst;
  361. in_src.m_pFirst = nullptr;
  362. }
  363. protected:
  364. T * m_pFirst; ///< top of list
  365. };
  366. #endif // _AKLISTBARE_H