00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef NVBLASTDLINK_H
00030 #define NVBLASTDLINK_H
00031
00032
00033 #include "NvBlastAssert.h"
00034 #include "NvBlastIndexFns.h"
00035
00036
00037 namespace Nv
00038 {
00039 namespace Blast
00040 {
00041
00042 template<typename IndexType>
00043 struct IndexDLink
00044 {
00045 IndexType m_adj[2];
00046 };
00047
00048
00049 template<typename IndexType>
00050 class IndexDList
00051 {
00052 public:
00053 void initLinksSolitary(IndexDLink<IndexType>* links, IndexType linkCount)
00054 {
00055 for (IndexType i = 0; i < linkCount; ++i)
00056 {
00057 links[i].m_adj[0] = invalidIndex<IndexType>();
00058 links[i].m_adj[1] = invalidIndex<IndexType>();
00059 }
00060 }
00061
00062 void initLinksChain(IndexDLink<IndexType>* links, IndexType linkCount)
00063 {
00064 if (linkCount > 0)
00065 {
00066 links[0].m_adj[0] = invalidIndex<IndexType>();
00067 for (IndexType i = 1; i < linkCount; ++i)
00068 {
00069 links[i - 1].m_adj[1] = i;
00070 links[i].m_adj[0] = i - 1;
00071 }
00072 links[linkCount - 1].m_adj[1] = invalidIndex<IndexType>();
00073 }
00074 }
00075
00076 IndexType getAdj(IndexDLink<IndexType>* links, IndexType linkIndex, int which)
00077 {
00078 return links[linkIndex].m_adj[which & 1];
00079 }
00080
00081 void remove(IndexDLink<IndexType>* links, IndexType linkIndex)
00082 {
00083 IndexDLink<IndexType>& link = links[linkIndex];
00084 const IndexType adj0 = link.m_adj[0];
00085 const IndexType adj1 = link.m_adj[1];
00086 if (!isInvalidIndex(adj1))
00087 {
00088 links[adj1].m_adj[0] = adj0;
00089 link.m_adj[1] = invalidIndex<IndexType>();
00090 }
00091 if (!isInvalidIndex(adj0))
00092 {
00093 links[adj0].m_adj[1] = adj1;
00094 link.m_adj[0] = invalidIndex<IndexType>();
00095 }
00096 }
00097
00098 bool isSolitary(IndexDLink<IndexType>* links, IndexType linkIndex)
00099 {
00100 const IndexDLink<IndexType>& link = links[linkIndex];
00101 return isInvalidIndex(link.m_adj[0]) && isInvalidIndex(link.m_adj[1]);
00102 }
00103
00104 void insertListHead(IndexType& listHead, IndexDLink<IndexType>* links, IndexType linkIndex)
00105 {
00106 NVBLAST_ASSERT(!isInvalidIndex(linkIndex));
00107 if (!isInvalidIndex(listHead))
00108 {
00109 links[listHead].m_adj[0] = linkIndex;
00110 }
00111 links[linkIndex].m_adj[1] = listHead;
00112 listHead = linkIndex;
00113 }
00114
00115 IndexType removeListHead(IndexType& listHead, IndexDLink<IndexType>* links)
00116 {
00117 const IndexType linkIndex = listHead;
00118 if (!isInvalidIndex(linkIndex))
00119 {
00120 listHead = links[linkIndex].m_adj[1];
00121 if (!isInvalidIndex(listHead))
00122 {
00123 links[listHead].m_adj[0] = invalidIndex<IndexType>();
00124 }
00125 links[linkIndex].m_adj[1] = invalidIndex<IndexType>();
00126 }
00127 return linkIndex;
00128 }
00129
00130 void removeFromList(IndexType& listHead, IndexDLink<IndexType>* links, IndexType linkIndex)
00131 {
00132 NVBLAST_ASSERT(!isInvalidIndex(linkIndex));
00133 if (listHead == linkIndex)
00134 {
00135 listHead = links[linkIndex].m_adj[1];
00136 }
00137 remove(links, linkIndex);
00138 }
00139 };
00140
00141
00142 struct DLink
00143 {
00144 DLink() : m_prev(nullptr), m_next(nullptr) {}
00145
00146 DLink* getPrev() const
00147 {
00148 return m_prev;
00149 }
00150
00151 DLink* getNext() const
00152 {
00153 return m_next;
00154 }
00155
00156 private:
00157 DLink* m_prev;
00158 DLink* m_next;
00159
00160 friend class DList;
00161 };
00162
00163
00164 class DList
00165 {
00166 public:
00167 DList() : m_head(nullptr), m_tail(nullptr) {}
00168
00169 bool isEmpty() const
00170 {
00171 NVBLAST_ASSERT((m_head == nullptr) == (m_tail == nullptr));
00172 return m_head == nullptr;
00173 }
00174
00175 bool isSolitary(const DLink& link) const
00176 {
00177 return link.m_prev == nullptr && link.m_next == nullptr && m_head != &link;
00178 }
00179
00180 DLink* getHead() const
00181 {
00182 return m_head;
00183 }
00184
00185 DLink* getTail() const
00186 {
00187 return m_tail;
00188 }
00189
00190 bool insertHead(DLink& link)
00191 {
00192 NVBLAST_ASSERT(isSolitary(link));
00193 if (!isSolitary(link))
00194 {
00195 return false;
00196 }
00197
00198 link.m_next = m_head;
00199 if (m_head != nullptr)
00200 {
00201 m_head->m_prev = &link;
00202 }
00203 m_head = &link;
00204 if (m_tail == nullptr)
00205 {
00206 m_tail = &link;
00207 }
00208
00209 return true;
00210 }
00211
00212 bool insertTail(DLink& link)
00213 {
00214 NVBLAST_ASSERT(isSolitary(link));
00215 if (!isSolitary(link))
00216 {
00217 return false;
00218 }
00219
00220 link.m_prev = m_tail;
00221 if (m_tail != nullptr)
00222 {
00223 m_tail->m_next = &link;
00224 }
00225 m_tail = &link;
00226 if (m_head == nullptr)
00227 {
00228 m_head = &link;
00229 }
00230
00231 return true;
00232 }
00233
00234 void remove(DLink& link)
00235 {
00236 if (link.m_prev != nullptr)
00237 {
00238 link.m_prev->m_next = link.m_next;
00239 }
00240 else
00241 if (m_head == &link)
00242 {
00243 m_head = link.m_next;
00244 }
00245
00246 if (link.m_next != nullptr)
00247 {
00248 link.m_next->m_prev = link.m_prev;
00249 }
00250 else
00251 if (m_tail == &link)
00252 {
00253 m_tail = link.m_prev;
00254 }
00255
00256 link.m_next = link.m_prev = nullptr;
00257 }
00258
00259 class It
00260 {
00261 public:
00262 enum Direction { Reverse, Forward };
00263
00264 It(const DList& list, Direction dir = Forward) : m_curr(dir == Forward ? list.getHead() : list.getTail()) {}
00265
00267 operator bool() const
00268 {
00269 return m_curr != nullptr;
00270 }
00271
00273 operator const DLink*() const
00274 {
00275 return m_curr;
00276 }
00277
00279 const DLink* operator ++ ()
00280 {
00281 return m_curr = m_curr->getNext();
00282 }
00283
00285 const DLink* operator -- ()
00286 {
00287 return m_curr = m_curr->getPrev();
00288 }
00289
00290 private:
00291 const DLink* m_curr;
00292 };
00293
00294 private:
00295 DLink* m_head;
00296 DLink* m_tail;
00297 };
00298
00299 }
00300 }
00301
00302
00303 #endif // #ifndef NVBLASTDLINK_H