1/****************************************************************************************
2
3 Copyright (C) 2015 Autodesk, Inc.
4 All rights reserved.
5
6 Use of this software is subject to the terms of the Autodesk license agreement
7 provided at the time of installation or download, or which otherwise accompanies
8 this software in either electronic or hard copy form.
9
10****************************************************************************************/
11
12//! \file fbxintrusivelist.h
13#ifndef _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_
14#define _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_
15
16#include <fbxsdk/fbxsdk_def.h>
17
18#include <fbxsdk/fbxsdk_nsbegin.h>
19
20/*****************************************************************************************************************************
21** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
22*****************************************************************************************************************************/
23#ifndef DOXYGEN_SHOULD_SKIP_THIS
24
25#define FBXSDK_INTRUSIVE_LIST_NODE(Class, NodeCount)\
26 public: inline FbxListNode<Class>& GetListNode(int index = 0){ return this->mNode[index]; }\
27 private: FbxListNode<Class> mNode[NodeCount];
28
29template <typename T> class FbxListNode
30{
31 typedef FbxListNode<T> NodeT;
32
33public:
34 explicit FbxListNode(T* pData = 0):mNext(0),mPrev(0),mData(pData){}
35 ~FbxListNode(){ Disconnect(); }
36
37 void Disconnect()
38 {
39 if ( mPrev != 0 )
40 mPrev->mNext = mNext;
41
42 if ( mNext != 0 )
43 mNext->mPrev = mPrev;
44
45 mPrev = mNext = 0;
46 }
47
48 NodeT* mNext;
49 NodeT* mPrev;
50 T* mData;
51};
52
53//-----------------------------------------------------------------
54// template arg T: Type listed
55// arg NodeIndex: If an object listed has multiple list node, which
56// index corresponds to the right node
57template <typename T, int NodeIndex=0> class FbxIntrusiveList
58{
59public:
60 typedef T allocator_type;
61 typedef T value_type;
62 typedef T& reference;
63 typedef const T& const_reference;
64 typedef T* pointer;
65 typedef const T* const_pointer;
66
67 typedef FbxListNode<T> NodeT;
68
69 // Construction / Destruction
70 FbxIntrusiveList():mHead(0)
71 {
72 mHead.mNext = mHead.mPrev = &mHead;
73 }
74 ~FbxIntrusiveList()
75 {
76 while(!Empty())
77 Begin().Get()->Disconnect(); // LINUXNote: should be Erase(Begin()); but there's an issue with gcc 4.2
78 };
79
80 // true if the list's size is 0.
81 bool Empty() const
82 {
83 return ((mHead.mNext==&mHead)&&(mHead.mPrev==&mHead));
84 }
85
86 // Back Insertion Sequence Inserts a new element at the end.
87 void PushBack(T& pElement)
88 {
89 NodeT* pNode = &pElement.GetListNode(NodeIndex);
90 pNode->mData = &pElement;
91
92 if (Empty())
93 {
94 pNode->mNext = &mHead;
95 pNode->mPrev = &mHead;
96 mHead.mNext = pNode;
97 mHead.mPrev = pNode;
98 }
99 else
100 {
101 pNode->mNext = &mHead;
102 pNode->mPrev = mHead.mPrev;
103
104 pNode->mPrev->mNext = pNode;
105 mHead.mPrev = pNode;
106 }
107 }
108
109 void PushFront(T& pElement)
110 {
111 NodeT* pNode = &pElement.GetListNode(NodeIndex);
112 pNode->mData = &pElement;
113
114 if (Empty())
115 {
116 pNode->mNext = &mHead;
117 pNode->mPrev = &mHead;
118 mHead.mNext = pNode;
119 mHead.mPrev = pNode;
120 }
121 else
122 {
123 pNode->mNext = mHead.mNext;
124 pNode->mPrev = &mHead;
125
126 pNode->mNext->mPrev = pNode;
127 mHead.mNext = pNode;
128 }
129 }
130
131 void PopFront()
132 {
133 iterator begin = Begin();
134 Erase(begin);
135 }
136
137 void PopBack()
138 {
139 Erase(--(End()));
140 }
141
142public:
143 class IntrusiveListIterator
144 {
145 public:
146 explicit IntrusiveListIterator(NodeT* ptr=0):mPtr(ptr){}
147
148 // pre-increment
149 IntrusiveListIterator& operator++()
150 {
151 mPtr = mPtr->mNext;return (*this);
152 }
153 // post-increment
154 const IntrusiveListIterator operator++(int)
155 {
156 IntrusiveListIterator temp = *this;
157 ++*this;
158 return (temp);
159 }
160 // pre-decrement
161 IntrusiveListIterator& operator--()
162 {
163 mPtr = mPtr->mPrev;return *this;
164 }
165 // post-decrement
166 const IntrusiveListIterator operator--(int)
167 {
168 IntrusiveListIterator temp = *this;
169 --*this;
170 return (temp);
171 }
172 IntrusiveListIterator& operator=(const IntrusiveListIterator &other){mPtr = other.mPtr; return *this;}
173
174 reference operator*() const { return *(mPtr->mData); }
175 pointer operator->() const { return (&**this); }
176 bool operator==(const IntrusiveListIterator& other)const{ return mPtr==other.mPtr; }
177 bool operator!=(const IntrusiveListIterator& other)const{ return !(*this == other); }
178
179 inline NodeT* Get()const { return mPtr; }
180
181 private:
182 NodeT* mPtr;
183 };
184
185 class IntrusiveListConstIterator
186 {
187 public:
188 explicit IntrusiveListConstIterator(const NodeT* ptr=0):mPtr(ptr){}
189
190 // pre-increment
191 IntrusiveListConstIterator& operator++()
192 {
193 mPtr = mPtr->mNext;return (*this);
194 }
195 // post-increment
196 const IntrusiveListConstIterator operator++(int)
197 {
198 IntrusiveListConstIterator temp = *this;
199 ++*this;
200 return (temp);
201 }
202 // pre-decrement
203 IntrusiveListConstIterator& operator--()
204 {
205 mPtr = mPtr->mPrev;return *this;
206 }
207 // post-decrement
208 const IntrusiveListConstIterator operator--(int)
209 {
210 IntrusiveListConstIterator temp = *this;
211 --*this;
212 return (temp);
213 }
214 IntrusiveListConstIterator& operator=(const IntrusiveListConstIterator &other){mPtr = other.mPtr; return *this;}
215
216 const_reference operator*() const { return *(mPtr->mData); }
217 const_pointer operator->() const { return (&**this); }
218 bool operator==(const IntrusiveListConstIterator& other)const{ return mPtr==other.mPtr; }
219 bool operator!=(const IntrusiveListConstIterator& other)const{ return !(*this == other); }
220
221 inline const NodeT* Get()const { return mPtr; }
222
223 private:
224 mutable const NodeT* mPtr;
225 };
226
227 // --- Iterator definitions ---
228 typedef IntrusiveListIterator iterator;
229 typedef IntrusiveListConstIterator const_iterator;
230
231 // iterator support
232 inline iterator Begin() { return iterator(mHead.mNext); }
233 inline const_iterator Begin() const { return const_iterator(mHead.mNext); }
234 inline iterator End() { return iterator(&mHead); }
235 inline const_iterator End() const { return const_iterator(&mHead); }
236
237 // Because there is no real use, for the reverse iterators,
238 // they have not been implemented.
239
240 reference Front(){return (*Begin());}
241 const_reference Front() const { return (*Begin()); }
242 reference Back(){ return (*(--End())); }
243 const_reference Back() const{ return (*(--End())); }
244
245 iterator& Erase(iterator& it)
246 {
247 it.Get()->Disconnect();
248 return (++it);
249 }
250private:
251 NodeT mHead;
252
253 // Not copyable
254 FbxIntrusiveList(const FbxIntrusiveList&);
255 FbxIntrusiveList& operator=(const FbxIntrusiveList& Right){return (*this);}
256};
257
258#endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
259
260#include <fbxsdk/fbxsdk_nsend.h>
261
262#endif /* _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_ */
263