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 | |
29 | template <typename T> class FbxListNode |
30 | { |
31 | typedef FbxListNode<T> NodeT; |
32 | |
33 | public: |
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 |
57 | template <typename T, int NodeIndex=0> class FbxIntrusiveList |
58 | { |
59 | public: |
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 | |
142 | public: |
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 | } |
250 | private: |
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 | |