CTR Pia  4.11.3
Game Communication Engine
common_OffsetList.h
1 /*---------------------------------------------------------------------------*
2  Project: Pia
3  File: common_OffsetList.h
4 
5  Copyright Nintendo. All rights reserved.
6 
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law. They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 
14 
15 #pragma once
16 
17 #include <pia/common/common_definitions.h>
18 #include <pia/common/common_ListBase.h>
19 
20 
21 namespace nn
22 {
23 namespace pia
24 {
25 namespace common
26 {
27 
28 
29 /*!
30 @cond PRIVATE
31 @brief Represents a doubly linked list that maintains a <tt>ListNode</tt> instance for each element member.
32 
33 @details Before using the list, you must specify the location of the <tt>ListNode</tt> instance in the element, as shown below.
34 
35 class Node
36  {
37 public:
38 static s32 GetListNodeOffset() {return offsetof(Node, m_ListNode);}
39 Private:
40 ListNode m_ListNode;
41  };
42 
43 OffsetList<Node> list;
44 list.InitOffset(Node::GetListNodeOffset());
45 
46 @param T Specifies the type of object being managed.
47 
48 
49 */
50 template <typename T>
51 class OffsetList : public nn::pia::common::ListBase
52 {
53 public:
54  typedef T Node;
55 
56 
57 /*!
58 @brief Instantiates the object with default parameters (default constructor).
59 */
60  OffsetList(void)
61  : ListBase(), m_Offset(-1)
62  {
63  }
64 
65 
66 /*!
67 @brief Sets the offset from the start address of <tt>T</tt> to the <tt>ListNode</tt> member.
68 
69 @details You must call this function before use.
70 
71 @param offset Specifies the offset.
72 */
73  void InitOffset(s32 offset)
74  {
75  m_Offset = offset;
76  }
77 
78 
79 /*!
80 @brief Removes all elements from the list.
81 */
82  void Clear()
83  {
84  ClearNode();
85  }
86 
87 
88 /*!
89 @brief Adds an element to the end of the list.
90 
91 @param pObj Specifies the element to add.
92 */
93  void PushBack(T* pObj)
94  {
95  PushBackNode(ObjToListNode(pObj));
96  }
97 
98 
99 /*!
100 @brief Adds an element to the start of the list.
101 
102 @param pObj Specifies the element to add.
103 */
104  void PushFront(T* pObj)
105  {
106  PushFrontNode(ObjToListNode(pObj));
107  }
108 
109 
110 /*!
111 @brief Removes and returns the last element in the list.
112 
113 @return Returns the popped element.
114 Returns <tt>NULL</tt> if the list is empty.
115 */
116  T* PopBack()
117  {
118  return ListNodeToObjWithNullCheck(PopBackNode());
119  }
120 
121 
122 /*!
123 @brief Removes and returns the first element on the list.
124 
125 @return Returns the popped element.
126 Returns <tt>NULL</tt> if the list is empty.
127 */
128  T* PopFront()
129  {
130  return ListNodeToObjWithNullCheck(PopFrontNode());
131  }
132 
133 
134 /*!
135 @brief Adds an element in front of the specified element.
136 
137 @param pBasis Specifies the base element.
138 Operations are undefined if the specified element is not in the list.
139 @param pObj Specifies the element to add.
140 */
141  void InsertBefore(const T* pBasis, T* pObj)
142  {
143  InsertBeforeNode(ObjToListNode(pBasis), ObjToListNode(pObj));
144  }
145 
146 
147 /*!
148 @brief Adds an element after the specified element.
149 
150 @param pBasis Specifies the base element.
151 Operations are undefined if the specified element is not in the list.
152 @param pObj Specifies the element to add.
153 */
154  void InsertAfter(const T* pBasis, T* pObj)
155  {
156  InsertAfterNode(ObjToListNode(pBasis), ObjToListNode(pObj));
157  }
158 
159 
160 /*!
161 @brief Removes the specified element.
162 
163 @details Operations are undefined if the specified element is not in the list.
164 
165 @param pObj Specifies the element to remove.
166 */
167  void Erase(T* pObj)
168  {
169  EraseNode(ObjToListNode(pObj));
170  }
171 
172 
173 /*!
174 @brief Gets the element at the start of the list.
175 
176 @return Returns the element at the start of the list.
177 Returns <tt>NULL</tt> if the list is empty.
178 */
179  T* Front() const
180  {
181  return ListNodeToObjWithNullCheck(FrontNode());
182  }
183 
184 
185 /*!
186 @brief Gets the last element in the list.
187 
188 @return Returns the last element in the list.
189 Returns <tt>NULL</tt> if the list is empty.
190 */
191  T* Back() const
192  {
193  return ListNodeToObjWithNullCheck(BackNode());
194  }
195 
196 
197 /*!
198 @brief Gets the element before the specified element.
199 
200 @param pObj Specifies the base element.
201 Operations are undefined if the specified element is not in the list.
202 
203 @return Returns the element before the specified element.
204 Returns <tt>NULL</tt> if the first element in the list is specified as the base.
205 */
206  T* Prev(const T* pObj) const
207  {
208  ListNode* pPrev = ObjToListNode(pObj)->Prev();
209  if (pPrev == Terminator())
210  {
211  return NULL;
212  }
213  else
214  {
215  return ListNodeToObj(pPrev);
216  }
217  }
218 
219 
220 /*!
221 @brief Gets the element after the specified element.
222 
223 @param pObj Specifies the base element.
224 Operations are undefined if the specified element is not in the list.
225 
226 @return Returns the element after the specified element.
227 Returns <tt>NULL</tt> if the last element in the list is specified as the base.
228 */
229  T* Next(const T* pObj) const
230  {
231  ListNode* pNext = ObjToListNode(pObj)->Next();
232  if (pNext == Terminator())
233  {
234  return NULL;
235  }
236  else
237  {
238  return ListNodeToObj(pNext);
239  }
240  }
241 
242 
243 /*!
244 @brief Checks whether the specified element is in the list.
245 
246 @param pObj Specifies the element to check.
247 
248 @return Returns <tt>true</tt> if the element is in the list.
249 */
250  bool IsInclude(const T* pObj) const
251  {
252  return IsIncludeNode(ObjToListNode(pObj));
253  }
254 
255 
256 /*!
257 @brief Rotates the list so the specified element is at the start of the list.
258 
259 @param pObj Specifies the element to put at the start.
260 Operations are undefined if the specified element is not in the list.
261 */
262  void Rotate(const T* pObj)
263  {
264  RotateNode(ObjToListNode(pObj));
265  }
266 
267 
268 /*!
269 @brief Represents an iterator for <tt>OffsetList</tt>.
270 */
271  class Iterator
272  {
273  friend class OffsetList<T>;
274 
275  private:
276  Iterator(const OffsetList<T>* pList, T* pObj)
277  : m_pList(pList), m_pObj(pObj)
278  {
279  }
280 
281  public:
282  Iterator& operator++()
283  {
284  m_pObj = m_pList->ListNodeToObj(m_pList->ObjToListNode(m_pObj)->Next());
285  return *this;
286  }
287 
288  bool operator==(const Iterator& x) const
289  {
290  return m_pObj == x.m_pObj;
291  }
292  bool operator!=(const Iterator& x) const
293  {
294  return m_pObj != x.m_pObj;
295  }
296 
297  T& operator*()
298  {
299  return *m_pObj;
300  }
301  T* operator->()
302  {
303  return m_pObj;
304  }
305 
306  const OffsetList<T>* GetList() const
307  {
308  return m_pList;
309  }
310 
311  private:
312  const OffsetList<T>* m_pList;
313  T* m_pObj;
314  };
315 
316 
317 /*!
318 @brief Represents a <tt>const</tt> iterator for <tt>OffsetList</tt>.
319 */
320  class ConstIterator
321  {
322  friend class OffsetList<T>;
323 
324  private:
325  ConstIterator(const OffsetList<T>* pList, const T* pObj)
326  : m_pList(pList), m_pObj(pObj)
327  {
328  }
329 
330  public:
331  ConstIterator& operator++()
332  {
333  m_pObj = m_pList->ListNodeToObj(m_pList->ObjToListNode(m_pObj)->Next());
334  return *this;
335  }
336 
337  bool operator==(const ConstIterator& x) const
338  {
339  return m_pObj == x.m_pObj;
340  }
341  bool operator!=(const ConstIterator& x) const
342  {
343  return m_pObj != x.m_pObj;
344  }
345 
346  const T& operator*()
347  {
348  return *m_pObj;
349  }
350  const T* operator->()
351  {
352  return m_pObj;
353  }
354 
355  const OffsetList<T>* GetList() const
356  {
357  return m_pList;
358  }
359 
360  private:
361  const OffsetList<T>* m_pList;
362  const T* m_pObj;
363  };
364 
365 
366 /*!
367 @brief Represents a <tt>robust</tt> iterator for <tt>OffsetList</tt>.
368 
369 @details The iterator remains valid even if the element it points to is removed.
370 The iterator is no longer valid if an element is added or an element it does not point to is removed.
371 */
372  class RobustIterator
373  {
374  friend class OffsetList<T>;
375 
376  private:
377  RobustIterator(const OffsetList<T>* pList, T* pObj)
378  : m_pList(pList), m_pObj(pObj)
379  {
380  m_pNextNode = m_pList->ObjToListNode(pObj)->Next();
381  }
382 
383  public:
384  RobustIterator& operator++()
385  {
386  m_pObj = m_pList->ListNodeToObj(m_pNextNode);
387  m_pNextNode = m_pList->ObjToListNode(m_pObj)->Next();
388  return *this;
389  }
390 
391  bool operator==(const RobustIterator& x) const
392  {
393  return m_pObj == x.m_pObj;
394  }
395  bool operator!=(const RobustIterator& x) const
396  {
397  return m_pObj != x.m_pObj;
398  }
399 
400  T& operator*()
401  {
402  return *m_pObj;
403  }
404  T* operator->()
405  {
406  return m_pObj;
407  }
408 
409  const OffsetList<T>* GetList() const
410  {
411  return m_pList;
412  }
413 
414  private:
415  const OffsetList<T>* m_pList;
416  T* m_pObj;
417  ListNode* m_pNextNode;
418  };
419 
420 
421 /*!
422 @brief Gets an Iterator pointing to the element at the start of the list.
423 
424 @return Returns an iterator pointing to the element at the start of the list.
425 */
426  Iterator Begin() const
427  {
428  return Iterator(this, ListNodeToObj(Terminator()->Next()));
429  }
430 
431 
432 /*!
433 @brief Gets an <tt>Iterator</tt> object pointing to the element after the last element in the list.
434 
435 @return Returns an <tt>Iterator</tt> object pointing to the element after the last element in the list.
436 */
437  Iterator End() const
438  {
439  return Iterator(this, ListNodeToObj(Terminator()));
440  }
441 
442 
443 /*!
444 @brief Gets a <tt>const</tt> iterator pointing to the element at the start of the list.
445 
446 @return Returns a <tt>ConstIterator</tt> object pointing to the element at the start of the list.
447 */
448  ConstIterator ConstBegin() const
449  {
450  return ConstIterator(this, ListNodeToObj(Terminator()->Next()));
451  }
452 
453 
454 /*!
455 @brief Gets a <tt>const</tt> iterator pointing to the element after the last element in the list.
456 
457 @return Returns a <tt>ConstIterator</tt> object pointing to the element after the last element in the list.
458 */
459  ConstIterator ConstEnd() const
460  {
461  return ConstIterator(this, ListNodeToObj(Terminator()));
462  }
463 
464 
465 /*!
466 @brief Gets a <tt>RobustIterator</tt> object pointing to the element at the start of the list.
467 
468 @return Returns a <tt>RobustIterator</tt> object pointing to the element at the start of the list.
469 */
470  RobustIterator RobustBegin() const
471  {
472  return RobustIterator(this, ListNodeToObj(Terminator()->Next()));
473  }
474 
475 
476 /*!
477 @brief Gets a <tt>RobustIterator</tt> object pointing to the element after the last element in the list.
478 
479 @return Returns a <tt>RobustIterator</tt> object pointing to the element after the last element in the list.
480 */
481  RobustIterator RobustEnd() const
482  {
483  return RobustIterator(this, ListNodeToObj(Terminator()));
484  }
485 
486 
487 private:
488  s32 m_Offset;
489 
490  ListNode* ObjToListNode(const T* pObj) const
491  {
492  return reinterpret_cast<ListNode*>((reinterpret_cast<u32>(pObj)) + m_Offset);
493  }
494 
495  T* ListNodeToObj(const ListNode* pNode) const
496  {
497  return reinterpret_cast<T*>((reinterpret_cast<u32>(pNode)) - m_Offset);
498  }
499 
500  T* ListNodeToObjWithNullCheck(const ListNode* pNode) const
501  {
502  if (pNode)
503  return reinterpret_cast<T*>((reinterpret_cast<u32>(pNode)) - m_Offset);
504  else
505  return NULL;
506  }
507 };
508 //! @endcond
509 }
510 }
511 } // end of namespace nn::pia::common
Definition: assert.h:115