Darryl Pogue
13 years ago
25 changed files with 47 additions and 598 deletions
@ -1,477 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtSkipList.h |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTSKIPLIST_H |
|
||||||
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtSkipList.h included more than once" |
|
||||||
#endif |
|
||||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTSKIPLIST_H |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Macros |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
#define SKIPLIST(type, keyType, keyField, cmp) TSkipList< type, keyType, offsetof(type, keyField), cmp > |
|
||||||
#define SKIPLIST_NUMERIC(type, keyType, keyField) SKIPLIST(type, keyType, keyField, TSkipListNumericCmp<keyType>) |
|
||||||
#define SKIPLIST_STRING(type, keyType, keyField) SKIPLIST(type, keyType, keyField, TSkipListStringCmp<keyType>) |
|
||||||
#define SKIPLIST_STRINGI(type, keyType, keyField) SKIPLIST(type, keyType, keyField, TSkipListStringCmpI<keyType>) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Typedefs |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
typedef void * SkipListTag; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Comparers |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
|
|
||||||
template<class K> |
|
||||||
class TSkipListNumericCmp { |
|
||||||
public: |
|
||||||
static bool Eq (const K & a, const K & b) { return a == b; } |
|
||||||
static bool Lt (const K & a, const K & b) { return a < b; } |
|
||||||
}; |
|
||||||
|
|
||||||
template<class K> |
|
||||||
class TSkipListStringCmp { |
|
||||||
public: |
|
||||||
static bool Eq (const K & a, const K & b) { return StrCmp(a, b, (unsigned)-1) == 0; } |
|
||||||
static bool Lt (const K & a, const K & b) { return StrCmp(a, b, (unsigned)-1) < 0; } |
|
||||||
}; |
|
||||||
|
|
||||||
template<class K> |
|
||||||
class TSkipListStringCmpI { |
|
||||||
public: |
|
||||||
static bool Eq (const K & a, const K & b) { return StrCmpI(a, b, (unsigned)-1) == 0; } |
|
||||||
static bool Lt (const K & a, const K & b) { return StrCmpI(a, b, (unsigned)-1) < 0; } |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* TSkipList |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
class TSkipList { |
|
||||||
private: |
|
||||||
enum { kMaxLevels = 32 }; |
|
||||||
|
|
||||||
template<class T2, class K2> |
|
||||||
struct TNode { |
|
||||||
const K2 * key; |
|
||||||
T2 * object; |
|
||||||
unsigned level; |
|
||||||
TNode<T2, K2> * prev; |
|
||||||
TNode<T2, K2> * next[1]; // variable size array
|
|
||||||
}; |
|
||||||
typedef TNode<T,K> Node; |
|
||||||
|
|
||||||
unsigned m_level; |
|
||||||
Node * m_head; |
|
||||||
Node * m_stop; |
|
||||||
unsigned m_randomBits; |
|
||||||
unsigned m_randomsLeft; |
|
||||||
|
|
||||||
Node * AllocNode (unsigned levels); |
|
||||||
void FreeNode (Node * node); |
|
||||||
unsigned RandomLevel (); |
|
||||||
|
|
||||||
public: |
|
||||||
inline TSkipList (); |
|
||||||
inline ~TSkipList (); |
|
||||||
inline void Clear (); |
|
||||||
inline void Delete (T * object); |
|
||||||
inline T * Find (const K & key, SkipListTag * tag = nil) const; |
|
||||||
inline T * FindNext (SkipListTag * tag) const; |
|
||||||
inline T * Head (SkipListTag * tag) const; |
|
||||||
inline T * Next (SkipListTag * tag) const; |
|
||||||
inline T * Prev (SkipListTag * tag) const; |
|
||||||
inline T * Tail (SkipListTag * tag) const; |
|
||||||
inline void Link (T * object); |
|
||||||
inline void Unlink (T * object); |
|
||||||
inline void Unlink (SkipListTag * tag); |
|
||||||
inline void UnlinkAll (); |
|
||||||
|
|
||||||
#ifdef HS_DEBUGGING |
|
||||||
inline void Print () const; |
|
||||||
#endif |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* TSkipList private member functions |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
typename TSkipList<T,K,keyOffset,Cmp>::Node* TSkipList<T,K,keyOffset,Cmp>::AllocNode (unsigned level) { |
|
||||||
|
|
||||||
unsigned size = offsetof(Node, next) + (level + 1) * sizeof(Node); |
|
||||||
Node * node = (Node *)malloc(size); |
|
||||||
node->level = level; |
|
||||||
return node; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::FreeNode (TNode<T,K> * node) { |
|
||||||
|
|
||||||
free(node); |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
unsigned TSkipList<T,K,keyOffset,Cmp>::RandomLevel () { |
|
||||||
|
|
||||||
unsigned level = 0; |
|
||||||
unsigned bits = 0; |
|
||||||
|
|
||||||
while (!bits) { |
|
||||||
bits = m_randomBits % 4; |
|
||||||
if (!bits) |
|
||||||
++level; |
|
||||||
m_randomBits >>= 2; |
|
||||||
m_randomsLeft -= 2; |
|
||||||
if (!m_randomsLeft) { |
|
||||||
m_randomBits = RandUnsigned(); |
|
||||||
m_randomsLeft = 30; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return level; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* TSkipList public member functions |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
TSkipList<T,K,keyOffset,Cmp>::TSkipList () { |
|
||||||
|
|
||||||
m_level = 0;
|
|
||||||
m_head = AllocNode(kMaxLevels); |
|
||||||
m_stop = AllocNode(0); |
|
||||||
m_randomBits = RandUnsigned(); |
|
||||||
m_randomsLeft = 30; |
|
||||||
|
|
||||||
// Initialize header and stop skip node pointers
|
|
||||||
m_stop->prev = m_head; |
|
||||||
m_stop->object = nil; |
|
||||||
m_stop->next[0] = nil; |
|
||||||
m_head->object = nil; |
|
||||||
for (unsigned index = 0; index < kMaxLevels; ++index) |
|
||||||
m_head->next[index] = m_stop; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
TSkipList<T,K,keyOffset,Cmp>::~TSkipList () { |
|
||||||
|
|
||||||
UnlinkAll(); |
|
||||||
ASSERT(m_stop->prev == m_head); |
|
||||||
FreeNode(m_head); |
|
||||||
FreeNode(m_stop); |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::Clear () { |
|
||||||
|
|
||||||
Node * ptr = m_head->next[0]; |
|
||||||
while (ptr != m_stop) { |
|
||||||
Node * next = ptr->next[0]; |
|
||||||
delete ptr->object; |
|
||||||
FreeNode(ptr); |
|
||||||
ptr = next; |
|
||||||
} |
|
||||||
|
|
||||||
m_stop->prev = m_head; |
|
||||||
for (unsigned index = 0; index < kMaxLevels; ++index) |
|
||||||
m_head->next[index] = m_stop; |
|
||||||
m_level = 0; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::Delete (T * object) { |
|
||||||
|
|
||||||
Unlink(object); |
|
||||||
delete object; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::Find (const K & key, SkipListTag * tag) const { |
|
||||||
|
|
||||||
Node * node = m_head; |
|
||||||
|
|
||||||
m_stop->key = &key; |
|
||||||
for (int level = (int)m_level; level >= 0; --level) |
|
||||||
while (Cmp::Lt(*node->next[level]->key, key)) |
|
||||||
node = node->next[level]; |
|
||||||
|
|
||||||
node = node->next[0]; |
|
||||||
if (node != m_stop && Cmp::Eq(*node->key, *m_stop->key)) { |
|
||||||
if (tag) |
|
||||||
*tag = node; |
|
||||||
return node->object; |
|
||||||
} |
|
||||||
else { |
|
||||||
if (tag) |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::FindNext (SkipListTag * tag) const { |
|
||||||
|
|
||||||
Node * node = (Node *)*tag; |
|
||||||
|
|
||||||
m_stop->key = node->key; |
|
||||||
for (int level = (int)node->level; level >= 0; --level) |
|
||||||
while (Cmp::Lt(*node->next[level]->key, *m_stop->key)) |
|
||||||
node = node->next[level]; |
|
||||||
|
|
||||||
node = node->next[0]; |
|
||||||
if (node != m_stop && Cmp::Eq(*node->key, *m_stop->key)) { |
|
||||||
*tag = node; |
|
||||||
return node->object; |
|
||||||
} |
|
||||||
else { |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::Head (SkipListTag * tag) const { |
|
||||||
|
|
||||||
ASSERT(tag); |
|
||||||
Node * first = m_head->next[0]; |
|
||||||
if (first == m_stop) { |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
|
|
||||||
*tag = first; |
|
||||||
return first->object; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::Next (SkipListTag * tag) const { |
|
||||||
|
|
||||||
ASSERT(tag); |
|
||||||
Node * node = (Node *)*tag; |
|
||||||
ASSERT(node); |
|
||||||
if (node->next[0] == m_stop) { |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
|
|
||||||
*tag = node->next[0]; |
|
||||||
return node->next[0]->object; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::Prev (SkipListTag * tag) const { |
|
||||||
|
|
||||||
ASSERT(tag); |
|
||||||
Node * node = (Node *)*tag; |
|
||||||
ASSERT(node); |
|
||||||
if (node->prev == m_head) { |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
|
|
||||||
*tag = node->prev; |
|
||||||
return node->prev->object; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
T * TSkipList<T,K,keyOffset,Cmp>::Tail (SkipListTag * tag) const { |
|
||||||
|
|
||||||
ASSERT(tag); |
|
||||||
Node * last = m_stop->prev; |
|
||||||
if (last == m_head) { |
|
||||||
*tag = nil; |
|
||||||
return nil; |
|
||||||
} |
|
||||||
|
|
||||||
*tag = last; |
|
||||||
return last->object; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::Link (T * object) { |
|
||||||
|
|
||||||
const K * key = (const K *)((const uint8_t *)object + keyOffset); |
|
||||||
|
|
||||||
// Find the node's insertion point
|
|
||||||
m_stop->key = key; |
|
||||||
Node * update[kMaxLevels]; |
|
||||||
Node * node = m_head; |
|
||||||
for (int level = (int)m_level; level >= 0; --level) { |
|
||||||
while (Cmp::Lt(*node->next[level]->key, *key)) |
|
||||||
node = node->next[level]; |
|
||||||
update[level] = node; |
|
||||||
} |
|
||||||
node = node->next[0]; |
|
||||||
|
|
||||||
{ |
|
||||||
// Select a level for the skip node
|
|
||||||
unsigned newLevel = RandomLevel(); |
|
||||||
if (newLevel > m_level) { |
|
||||||
if (m_level < kMaxLevels - 1) { |
|
||||||
newLevel = ++m_level; |
|
||||||
update[newLevel] = m_head; |
|
||||||
} |
|
||||||
else |
|
||||||
newLevel = m_level; |
|
||||||
} |
|
||||||
|
|
||||||
// Create the node and insert it into the skip list
|
|
||||||
Node * node = AllocNode(newLevel); |
|
||||||
node->key = key; |
|
||||||
node->object = object; |
|
||||||
for (unsigned level = newLevel; level >= 1; --level) { |
|
||||||
node->next[level] = update[level]->next[level]; |
|
||||||
update[level]->next[level] = node; |
|
||||||
} |
|
||||||
node->prev = update[0]; |
|
||||||
node->next[0] = update[0]->next[0]; |
|
||||||
update[0]->next[0]->prev = node; |
|
||||||
update[0]->next[0] = node; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::Unlink (T * object) { |
|
||||||
|
|
||||||
const K * key = (const K *)((const uint8_t *)object + keyOffset); |
|
||||||
|
|
||||||
Node * node = m_head; |
|
||||||
Node * update[kMaxLevels]; |
|
||||||
int level = m_level; |
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
// Find the node being unlinked
|
|
||||||
m_stop->key = key; |
|
||||||
for (; level >= 0; --level) { |
|
||||||
while (Cmp::Lt(*node->next[level]->key, *key)) |
|
||||||
node = node->next[level]; |
|
||||||
update[level] = node; |
|
||||||
} |
|
||||||
node = node->next[0]; |
|
||||||
|
|
||||||
// Node wasn't found so do nothing
|
|
||||||
if (*node->key != *key || node == m_stop) |
|
||||||
return; |
|
||||||
|
|
||||||
if (node->object == object) |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// Update all links
|
|
||||||
for (level = m_level; level >= 1; --level) { |
|
||||||
if (update[level]->next[level] != node) |
|
||||||
continue; |
|
||||||
update[level]->next[level] = node->next[level]; |
|
||||||
} |
|
||||||
ASSERT(update[0]->next[0] == node); |
|
||||||
node->next[0]->prev = update[0]; |
|
||||||
update[0]->next[0] = node->next[0]; |
|
||||||
|
|
||||||
// Update header
|
|
||||||
while (m_level && m_head->next[m_level] == m_stop) |
|
||||||
--m_level; |
|
||||||
|
|
||||||
FreeNode(node); |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
template<class T, class K, unsigned keyOffset, class Cmp> |
|
||||||
void TSkipList<T,K,keyOffset,Cmp>::UnlinkAll () { |
|
||||||
|
|
||||||
Node * ptr = m_head->next[0]; |
|
||||||
while (ptr != m_stop) { |
|
||||||
Node * next = ptr->next[0]; |
|
||||||
FreeNode(ptr); |
|
||||||
ptr = next; |
|
||||||
} |
|
||||||
|
|
||||||
m_stop->prev = m_head; |
|
||||||
for (unsigned index = 0; index < kMaxLevels; ++index) |
|
||||||
m_head->next[index] = m_stop; |
|
||||||
m_level = 0; |
|
||||||
} |
|
@ -1,57 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtTypes.h |
|
||||||
*
|
|
||||||
* |
|
||||||
* By Eric Anderson (10/10/2005) |
|
||||||
* Copyright 2005 Cyan Worlds, Inc. |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTTYPES_H |
|
||||||
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtTypes.h included more than once" |
|
||||||
#endif |
|
||||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTTYPES_H |
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue