CTR-Pia  5.4.3
Game Communication Engine
 全て クラス ネームスペース 関数 変数 型定義 列挙型 列挙型の値 ページ
common_OffsetList.h
1 /*--------------------------------------------------------------------------------*
2  Copyright (C)Nintendo All rights reserved.
3 
4  These coded instructions, statements, and computer programs contain proprietary
5  information of Nintendo and/or its licensed developers and are protected by
6  national and international copyright laws. They may not be disclosed to third
7  parties or copied or duplicated in any form, in whole or in part, without the
8  prior written consent of Nintendo.
9 
10  The content herein is highly confidential and should be handled accordingly.
11  *--------------------------------------------------------------------------------*/
12 
13 
14 #pragma once
15 
16 #include <nn/pia/common/common_Definitions.h>
17 #include <nn/pia/common/common_PtrUtil.h>
18 #include <nn/pia/common/common_ListBase.h>
19 
20 namespace nn
21 {
22 namespace pia
23 {
24 namespace common
25 {
26 
27 
28 /*!
29  @cond PRIVATE
30  @brief 要素のメンバにListNodeを持たせるタイプの双方向リストのクラスです。
31 
32  @details リストを利用する前に、ListNodeが要素の中のどこにあるのかを以下のように
33  設定する必要があります。
34 
35  class Node
36  {
37  public:
38  static int32_t 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 管理するオブジェクトの型。
47 
48  */
49 template <typename T>
50 class OffsetList : public nn::pia::common::ListBase
51 {
52 public:
53  typedef T Node;
54 
55 
56  /*!
57  @brief デフォルトコンストラクタです。
58  */
59  OffsetList(void)
60  : ListBase(), m_Offset(-1)
61  {
62  }
63 
64 
65  /*!
66  @brief Tの先頭アドレスからListNodeへのオフセット値を設定します。
67 
68  @details 使用する前に必ず呼び出す必要があります。
69  <br>
70  @param offset 設定するオフセット。
71  */
72  void InitOffset(int32_t offset)
73  {
74  m_Offset = offset;
75  }
76 
77 
78  /*!
79  @brief リストからすべての要素を削除します。
80  */
81  void Clear()
82  {
83  ClearNode();
84  }
85 
86 
87  /*!
88  @brief リストの末尾に要素を追加します。
89 
90  @param pObj 追加する要素。
91  */
92  void PushBack(T* pObj)
93  {
94  PushBackNode(ObjToListNode(pObj));
95  }
96 
97 
98  /*!
99  @brief リストの先頭に要素を追加します。
100 
101  @param pObj 追加する要素。
102  */
103  void PushFront(T* pObj)
104  {
105  PushFrontNode(ObjToListNode(pObj));
106  }
107 
108 
109  /*!
110  @brief リストの末尾から要素を取り出して返します。
111 
112  @return 取り出した要素。
113  リストが空の時はNULLを返します。
114  */
115  T* PopBack()
116  {
117  return ListNodeToObjWithNullCheck(PopBackNode());
118  }
119 
120 
121  /*!
122  @brief リストの先頭から要素を取り出して返します。
123 
124  @return 取り出した要素。
125  リストが空の時はNULLを返します。
126  */
127  T* PopFront()
128  {
129  return ListNodeToObjWithNullCheck(PopFrontNode());
130  }
131 
132 
133  /*!
134  @brief 指定した要素の前に要素を追加します。
135 
136  @param pBasis 基準となる要素。
137  リストに含まれていない要素を指定した場合の挙動は不定です。
138  @param pObj 追加する要素。
139  */
140  void InsertBefore(const T* pBasis, T* pObj)
141  {
142  InsertBeforeNode(ObjToListNode(pBasis), ObjToListNode(pObj));
143  }
144 
145 
146  /*!
147  @brief 指定した要素の後ろに要素を追加します。
148 
149  @param pBasis 基準となる要素。
150  リストに含まれていない要素を指定した場合の挙動は不定です。
151  @param pObj 追加する要素。
152  */
153  void InsertAfter(const T* pBasis, T* pObj)
154  {
155  InsertAfterNode(ObjToListNode(pBasis), ObjToListNode(pObj));
156  }
157 
158 
159  /*!
160  @brief 指定した要素を削除します。
161 
162  @details リストに含まれていない要素を指定した場合の挙動は不定です。
163  <br>
164  @param pObj 削除する要素。
165  */
166  void Erase(T* pObj)
167  {
168  EraseNode(ObjToListNode(pObj));
169  }
170 
171 
172  /*!
173  @brief 先頭の要素を取得します。
174 
175  @return 先頭の要素。
176  リストが空の場合はNULLを返します。
177  */
178  T* Front() const
179  {
180  return ListNodeToObjWithNullCheck(FrontNode());
181  }
182 
183 
184  /*!
185  @brief 末尾の要素を取得します。
186 
187  @return 末尾の要素。
188  リストが空の場合はNULLを返します。
189  */
190  T* Back() const
191  {
192  return ListNodeToObjWithNullCheck(BackNode());
193  }
194 
195 
196  /*!
197  @brief 指定した要素の前の要素を取得します。
198 
199  @param pObj 基準となる要素。
200  リストに含まれていない要素を指定した場合の挙動は不定です。
201 
202  @return 指定した要素の前の要素。
203  先頭の要素が指定された場合はNULLを返します。
204  */
205  T* Prev(const T* pObj) const
206  {
207  ListNode* pPrev = ObjToListNode(pObj)->Prev();
208  if (pPrev == Terminator())
209  {
210  return NULL;
211  }
212  else
213  {
214  return ListNodeToObj(pPrev);
215  }
216  }
217 
218 
219  /*!
220  @brief 指定した要素の後ろの要素を取得します。
221 
222  @param pObj 基準となる要素。
223  リストに含まれていない要素を指定した場合の挙動は不定です。
224 
225  @return 指定した要素の後ろの要素。
226  末尾の要素が指定された場合はNULLを返します。
227  */
228  T* Next(const T* pObj) const
229  {
230  ListNode* pNext = ObjToListNode(pObj)->Next();
231  if (pNext == Terminator())
232  {
233  return NULL;
234  }
235  else
236  {
237  return ListNodeToObj(pNext);
238  }
239  }
240 
241 
242  /*!
243  @brief 要素がリストに含まれているか調べます。
244 
245  @param pObj 調べたい要素。
246 
247  @return 含まれていれば true を返します。
248  */
249  bool IsInclude(const T* pObj) const
250  {
251  return IsIncludeNode(ObjToListNode(pObj));
252  }
253 
254 
255  /*!
256  @brief 指定した要素が先頭の要素となるようにリストを回転します。
257 
258  @param pObj 先頭にする要素
259  リストに含まれていない要素を指定した場合の挙動は不定です。
260  */
261  void Rotate(const T* pObj)
262  {
263  RotateNode(ObjToListNode(pObj));
264  }
265 
266 
267  /*!
268  @brief OffsetListのイテレータです。
269  */
270  class Iterator
271  {
272  friend class OffsetList<T>;
273 
274  private:
275  Iterator(const OffsetList<T>* pList, T* pObj)
276  : m_pList(pList), m_pObj(pObj)
277  {
278  }
279 
280  public:
281  Iterator& operator++()
282  {
283  m_pObj = m_pList->ListNodeToObj(m_pList->ObjToListNode(m_pObj)->Next());
284  return *this;
285  }
286 
287  bool operator==(const Iterator& x) const
288  {
289  return m_pObj == x.m_pObj;
290  }
291  bool operator!=(const Iterator& x) const
292  {
293  return m_pObj != x.m_pObj;
294  }
295 
296  T& operator*()
297  {
298  return *m_pObj;
299  }
300  T* operator->()
301  {
302  return m_pObj;
303  }
304 
305  const OffsetList<T>* GetList() const
306  {
307  return m_pList;
308  }
309 
310  private:
311  const OffsetList<T>* m_pList;
312  T* m_pObj;
313  };
314 
315 
316  /*!
317  @brief OffsetListのconst iteratorです。
318  */
319  class ConstIterator
320  {
321  friend class OffsetList<T>;
322 
323  private:
324  ConstIterator(const OffsetList<T>* pList, const T* pObj)
325  : m_pList(pList), m_pObj(pObj)
326  {
327  }
328 
329  public:
330  ConstIterator& operator++()
331  {
332  m_pObj = m_pList->ListNodeToObj(m_pList->ObjToListNode(m_pObj)->Next());
333  return *this;
334  }
335 
336  bool operator==(const ConstIterator& x) const
337  {
338  return m_pObj == x.m_pObj;
339  }
340  bool operator!=(const ConstIterator& x) const
341  {
342  return m_pObj != x.m_pObj;
343  }
344 
345  const T& operator*()
346  {
347  return *m_pObj;
348  }
349  const T* operator->()
350  {
351  return m_pObj;
352  }
353 
354  const OffsetList<T>* GetList() const
355  {
356  return m_pList;
357  }
358 
359  private:
360  const OffsetList<T>* m_pList;
361  const T* m_pObj;
362  };
363 
364 
365  /*!
366  @brief OffsetListのrobust iteratorです。
367 
368  @details イテレータが指し示す要素を削除してもイテレータを継続できます。
369  要素の追加やイテレータが指し示していない要素の削除をした場合はイテレータを継続できません。
370  */
371  class RobustIterator
372  {
373  friend class OffsetList<T>;
374 
375  private:
376  RobustIterator(const OffsetList<T>* pList, T* pObj)
377  : m_pList(pList), m_pObj(pObj)
378  {
379  m_pNextNode = m_pList->ObjToListNode(pObj)->Next();
380  }
381 
382  public:
383  RobustIterator& operator++()
384  {
385  m_pObj = m_pList->ListNodeToObj(m_pNextNode);
386  m_pNextNode = m_pList->ObjToListNode(m_pObj)->Next();
387  return *this;
388  }
389 
390  bool operator==(const RobustIterator& x) const
391  {
392  return m_pObj == x.m_pObj;
393  }
394  bool operator!=(const RobustIterator& x) const
395  {
396  return m_pObj != x.m_pObj;
397  }
398 
399  T& operator*()
400  {
401  return *m_pObj;
402  }
403  T* operator->()
404  {
405  return m_pObj;
406  }
407 
408  const OffsetList<T>* GetList() const
409  {
410  return m_pList;
411  }
412 
413  private:
414  const OffsetList<T>* m_pList;
415  T* m_pObj;
416  ListNode* m_pNextNode;
417  };
418 
419 
420  /*!
421  @brief 先頭の要素を指すIteratorを取得します。
422 
423  @return 先頭の要素を指すIterator。
424  */
425  Iterator Begin() const
426  {
427  return Iterator(this, ListNodeToObj(Terminator()->Next()));
428  }
429 
430 
431  /*!
432  @brief 末尾の要素の次を指すIteratorを取得します。
433 
434  @return 末尾の要素の次を指すIterator。
435  */
436  Iterator End() const
437  {
438  return Iterator(this, ListNodeToObj(Terminator()));
439  }
440 
441 
442  /*!
443  @brief 先頭の要素を指すConstIteratorを取得します。
444 
445  @return 先頭の要素を指すConstIterator。
446  */
447  ConstIterator ConstBegin() const
448  {
449  return ConstIterator(this, ListNodeToObj(Terminator()->Next()));
450  }
451 
452 
453  /*!
454  @brief 末尾の要素の次を指すConstIteratorを取得します。
455 
456  @return 末尾の要素の次を指すConstIterator。
457  */
458  ConstIterator ConstEnd() const
459  {
460  return ConstIterator(this, ListNodeToObj(Terminator()));
461  }
462 
463 
464  /*!
465  @brief 先頭の要素を指すRobustIteratorを取得します。
466 
467  @return 先頭の要素を指すRobustIterator。
468  */
469  RobustIterator RobustBegin() const
470  {
471  return RobustIterator(this, ListNodeToObj(Terminator()->Next()));
472  }
473 
474 
475  /*!
476  @brief 末尾の要素の次を指すRobustIteratorを取得します。
477 
478  @return 末尾の要素の次を指すRobustIterator。
479  */
480  RobustIterator RobustEnd() const
481  {
482  return RobustIterator(this, ListNodeToObj(Terminator()));
483  }
484 
485 
486 private:
487  int32_t m_Offset;
488 
489  ListNode* ObjToListNode(const T* pObj) const
490  {
491  return reinterpret_cast<ListNode*>(PtrUtil::addOffset(pObj, m_Offset));
492  }
493 
494  T* ListNodeToObj(const ListNode* pNode) const
495  {
496  return reinterpret_cast<T*>(PtrUtil::addOffset(pNode, -m_Offset));
497  }
498 
499  T* ListNodeToObjWithNullCheck(const ListNode* pNode) const
500  {
501  if (pNode)
502  return reinterpret_cast<T*>(PtrUtil::addOffset(pNode, -m_Offset));
503  else
504  return NULL;
505  }
506 
507  OffsetList(const OffsetList&);
508  OffsetList& operator=(const OffsetList&);
509 };
510 //! @endcond
511 }
512 }
513 } // end of namespace nn::pia::common