Port code to AMTL (#427)

* Remove CQueue

* Remove duplicated files

* Move sh_tinyhash to public/

* Remove sm_queue

Make NVault use of ke::Deque

* Remove sh_string (unused)

* Remove CList dependency from CTask

* Remove CList dependency from CEvent

* Remove CList dependency from modules' functions

* Remove CList dependency ForceObject

* Remove CList dependency Player Auth

* Remove left CList dependencies

* Fix msvc project files

* Update AMTL

* Use InlineList for CScript

* Use InlineList for CModule

* Use Vector for Player Auth
This commit is contained in:
Karol Szuster 2017-04-14 19:36:59 +02:00 committed by Vincent Herbet
parent 2d049b7ff3
commit 123246cc84
25 changed files with 388 additions and 2056 deletions

View File

@ -204,16 +204,16 @@ int EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags,
return 0;
}
auto event = new ClEvent(plugin, func, flags);
auto event = ke::AutoPtr<ClEvent>(new ClEvent(plugin, func, flags));
int handle = EventHandles.create(event);
int handle = EventHandles.create(event.get());
if (!handle)
{
return 0;
}
m_Events[msgid].put(event);
m_Events[msgid].append(ke::Move(event));
return handle;
}
@ -226,40 +226,40 @@ void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int in
m_ParseNotDone = false;
// don't parse if nothing to do
if (!m_Events[msg_type].size())
if (!m_Events[msg_type].length())
return;
m_ParseMsgType = msg_type;
m_Timer = timer;
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
for (auto &event : m_Events[msg_type])
{
if ((*iter).m_Done)
if (event->m_Done)
continue;
if (!(*iter).m_Plugin->isExecutable((*iter).m_Func))
if (!event->m_Plugin->isExecutable(event->m_Func))
{
(*iter).m_Done = true;
event->m_Done = true;
continue;
}
if (pPlayer)
{
if (!(*iter).m_FlagClient || (pPlayer->IsBot() ? !(*iter).m_FlagBot : !(*iter).m_FlagPlayer) || (pPlayer->IsAlive() ? !(*iter).m_FlagAlive : !(*iter).m_FlagDead))
if (!event->m_FlagClient || (pPlayer->IsBot() ? !event->m_FlagBot : !event->m_FlagPlayer) || (pPlayer->IsAlive() ? !event->m_FlagAlive : !event->m_FlagDead))
{
(*iter).m_Done = true;
event->m_Done = true;
continue;
}
}
else if (!(*iter).m_FlagWorld)
else if (!event->m_FlagWorld)
{
(*iter).m_Done = true;
event->m_Done = true;
continue;
}
if ((*iter).m_FlagOnce && (*iter).m_Stamp == (float)(*timer))
if (event->m_FlagOnce && event->m_Stamp == *timer)
{
(*iter).m_Done = true;
event->m_Done = true;
continue;
}
@ -292,16 +292,16 @@ void EventsMngr::parseValue(int iValue)
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
for (auto &event : *m_ParseFun)
{
if ((*iter).m_Done)
if (event->m_Done)
continue; // already skipped; don't bother with parsing
// loop through conditions
bool execute = false;
bool anyConditions = false;
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
{
if (condIter->paramId == m_ParsePos)
{
@ -320,7 +320,7 @@ void EventsMngr::parseValue(int iValue)
}
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
event->m_Done = true; // don't execute
}
}
@ -339,16 +339,16 @@ void EventsMngr::parseValue(float fValue)
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
for (auto &event : *m_ParseFun)
{
if ((*iter).m_Done)
if (event->m_Done)
continue; // already skipped; don't bother with parsing
// loop through conditions
bool execute = false;
bool anyConditions = false;
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
{
if (condIter->paramId == m_ParsePos)
{
@ -367,7 +367,7 @@ void EventsMngr::parseValue(float fValue)
}
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
event->m_Done = true; // don't execute
}
}
@ -386,16 +386,16 @@ void EventsMngr::parseValue(const char *sz)
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
for (auto &event : *m_ParseFun)
{
if ((*iter).m_Done)
if (event->m_Done)
continue; // already skipped; don't bother with parsing
// loop through conditions
bool execute = false;
bool anyConditions = false;
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next)
{
if (condIter->paramId == m_ParsePos)
{
@ -413,7 +413,7 @@ void EventsMngr::parseValue(const char *sz)
}
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
event->m_Done = true; // don't execute
}
}
@ -455,22 +455,22 @@ void EventsMngr::executeEvents()
}
// Reset this here so we don't trigger re-entrancy for unregistered messages
ClEventVec *parseFun = m_ParseFun;
m_ParseFun = NULL;
auto parseFun = m_ParseFun;
m_ParseFun = nullptr;
for (ClEventVecIter iter = parseFun->begin(); iter; ++iter)
for (auto &event : *parseFun)
{
if ((*iter).m_Done)
if (event->m_Done)
{
(*iter).m_Done = false;
event->m_Done = false;
continue;
}
(*iter).m_Stamp = (float)*m_Timer;
event->m_Stamp = *m_Timer;
if ((*iter).m_State == FSTATE_ACTIVE)
if (event->m_State == FSTATE_ACTIVE)
{
executeForwards((*iter).m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
executeForwards(event->m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
}
}

View File

@ -108,11 +108,8 @@ private:
int m_ReadVaultSize;
void NextParam(); // make sure a new parameter can be added
typedef CList<ClEvent> ClEventVec;
typedef ClEventVec::iterator ClEventVecIter;
ClEventVec m_Events[MAX_AMX_REG_MSG];
ClEventVec *m_ParseFun; // current Event vector
ke::Vector<ke::AutoPtr<ClEvent>> m_Events[MAX_AMX_REG_MSG];
ke::Vector<ke::AutoPtr<ClEvent>> *m_ParseFun; // current Event vector
bool m_ParseNotDone;
int m_ParsePos; // is args. num. - 1

View File

@ -1,307 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef CLIST_H
#define CLIST_H
// *****************************************************
// class CList
// *****************************************************
// Linked list
template <typename T, typename F = char* >
class CList
{
private:
// One list element
class CElement
{
T *m_pObject; // pointer to the object
CElement *m_pNext; // pointer to the next element
CElement *m_pPrev; // pointer to the previous element
public:
// dereference operator
T& operator* ()
{
return *m_pObject;
}
// constructor
CElement(T *pObj)
{
m_pObject = pObj;
m_pNext = NULL;
m_pPrev = NULL;
}
// destructor
~CElement()
{
delete m_pObject;
if (m_pNext)
m_pNext->m_pPrev = m_pPrev;
if (m_pPrev)
m_pPrev->m_pNext = m_pNext;
}
// returns object pointer
T *GetObj()
{
return m_pObject;
}
// returns next element pointer
CElement *GetNext()
{
return m_pNext;
}
// sets next element
void SetNext(CElement *newNext)
{
m_pNext = newNext;
}
// returns previous element pointer
CElement *GetPrev()
{
return m_pPrev;
}
// sets previous element
void SetPrev(CElement *newPrev)
{
m_pPrev = newPrev;
}
};
// CList<T, F> class
CElement *m_pHead; // head of the linked list
CElement *m_pTail; // tail of the linked list
public:
// iterator class
class iterator
{
friend class CList<T, F>;
CList<T, F> *m_pList; // The list that created this iterator
CElement *m_CurPos; // Current position in the list
public:
iterator()
{
m_pList = NULL;
m_CurPos = NULL;
}
// constructor based on list, element
iterator(CList<T, F> *pList, CElement *startPos)
{
m_pList = pList;
m_CurPos = startPos;
}
// constructor based on other iterator
iterator(const iterator &other)
{
m_pList = other.m_pList;
m_CurPos = other.m_CurPos;
}
// dereference operator
T & operator* () const
{
return *m_CurPos->GetObj();
}
T * operator-> () const
{
return m_CurPos->GetObj();
}
// validity check operator
inline operator bool () const
{
return m_pList != NULL && m_CurPos != NULL && m_CurPos->GetObj() != NULL;
}
// pre increment operator
inline iterator& operator ++ ()
{
m_CurPos = m_CurPos->GetNext();
return *this;
}
// post increment operator
inline iterator operator++(int)
{
iterator tmp(*this);
m_CurPos = m_CurPos->next;
return tmp;
}
// returns iterator that points to next element
iterator GetNext()
{
iterator tmp(*this);
return ++tmp;
}
iterator remove()
{
return m_pList->remove(*this);
}
iterator put(T *obj)
{
return m_pList->put(obj, *this);
}
};
CList<T, F>()
{
m_pHead = NULL;
m_pTail = NULL;
}
~CList<T, F>()
{
clear();
}
// removes the object referenced by where
// sets where to the next object
// returns an iterator pointing to the next object
iterator remove(iterator &where)
{
iterator tmp(where.GetNext());
if (where.m_CurPos == m_pHead)
m_pHead = where.m_CurPos->GetNext();
if (where.m_CurPos == m_pTail)
m_pTail = where.m_CurPos->GetPrev();
delete where.m_CurPos;
where = tmp;
return tmp;
}
// puts an element to the end of the list
// returns an iterator pointing to it
iterator put_back(T *pObj)
{
CElement *pTmp = new CElement(pObj);
if (!m_pHead)
{
m_pHead = pTmp;
m_pTail = pTmp;
} else {
pTmp->SetNext(NULL);
pTmp->SetPrev(m_pTail);
m_pTail->SetNext(pTmp);
m_pTail = pTmp;
}
return iterator(this, pTmp);
}
iterator put_front(T *pObj)
{
CElement *pTmp = new CElement(pObj);
if (!m_pHead)
{
m_pHead = pTmp;
m_pTail = pTmp;
} else {
pTmp->SetNext(m_pHead);
pTmp->SetPrev(NULL);
m_pHead->SetPrev(pTmp);
m_pHead = pTmp;
}
return iterator(this, pTmp);
}
// alias for put_back
iterator put(T *pObj)
{
return put_back(pObj);
}
// puts an element after where
// alters where to point to the new element
// returns an iterator pointing to the new element
iterator put(T *pObj, iterator &where)
{
CElement *pTmp = new CElement(pObj);
if (where.m_CurPos->GetNext())
where.m_CurPos->GetNext()->SetPrev(pTmp);
else // where = tail
m_pTail = pTmp;
pTmp->SetPrev(where.m_CurPos);
pTmp->SetNext(where.m_CurPos->GetNext());
where.m_CurPos->SetNext(pTmp);
return ++where;
}
iterator begin()
{
return iterator(this, m_pHead);
}
void clear()
{
iterator iter = begin();
while (iter) iter.remove();
}
iterator find(iterator startOn, const F &desc)
{
iterator iter = startOn;
while (iter)
{
if (*iter == desc)
break;
++iter;
}
return iter;
}
iterator find(const F &desc)
{
return find(begin(), desc);
}
int size()
{
iterator iter = begin();
int i = 0;
while (iter)
{
++i;
++iter;
}
return i;
}
};
#endif //CLIST_H

View File

@ -10,7 +10,6 @@
#ifndef CMISC_H
#define CMISC_H
#include "CList.h"
#include "sh_list.h"
// *****************************************************
@ -202,7 +201,7 @@ public:
// class CScript
// *****************************************************
class CScript
class CScript : public ke::InlineListNode<CScript>
{
ke::AString filename;
AMX* amx;
@ -212,7 +211,6 @@ public:
inline AMX* getAMX() { return amx; }
inline const char* getName() { return filename.chars(); }
inline bool operator==(void* a) { return (amx == (AMX*)a); }
inline void* getCode() { return code; }
};

View File

@ -52,7 +52,7 @@ struct amxx_module_info_s
#define AMXX_INTERFACE_VERSION 4
class CModule
class CModule : public ke::InlineListNode<CModule>
{
ke::AString m_Filename; // Filename
@ -87,7 +87,6 @@ public:
inline const char* getName() const { return m_InfoNew.name; }
inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new
inline int getStatusValue() { return m_Status; }
inline bool operator==(const char* fname) { return !strcmp(m_Filename.chars(), fname); }
inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); }
inline bool isAmxx() const { return m_Amxx; }
inline const char *getMissingFunc() const { return m_MissingFunc; }

View File

@ -1,107 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//by David "BAILOPAN" Anderson
#ifndef _INCLUDE_CQUEUE_H
#define _INCLUDE_CQUEUE_H
template <class T>
class CQueue
{
public:
class CQueueItem
{
public:
CQueueItem(const T &i, CQueueItem *n)
{
item = i;
next = n;
}
CQueueItem *GetNext()
{
return next;
}
T & GetItem()
{
return item;
}
void SetNext(CQueueItem *n)
{
next = n;
}
private:
T item;
CQueueItem *next;
};
public:
CQueue()
{
mSize = 0;
mFirst = NULL;
mLast = NULL;
}
bool empty()
{
return ((mSize == 0) ? true : false);
}
void push(const T &v)
{
CQueueItem *p = new CQueueItem(v, NULL);
if (empty())
{
mFirst = p;
} else {
mLast->SetNext(p);
}
mLast = p;
mSize++;
}
void pop()
{
if (mFirst == mLast)
{
delete mFirst;
mFirst = NULL;
mLast = NULL;
} else {
CQueueItem *p = mFirst->GetNext();
delete mFirst;
mFirst = p;
}
mSize--;
}
T & front()
{
return mFirst->GetItem();
}
T & back()
{
return mLast->GetItem();
}
unsigned int size()
{
return mSize;
}
private:
CQueueItem *mFirst;
CQueueItem *mLast;
unsigned int mSize;
};
#endif //_INCLUDE_CQUEUE_H

View File

@ -203,35 +203,36 @@ void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pT
void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat)
{
// first, search for free tasks
TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true));
if (iter)
for (auto &task : m_Tasks)
{
// found: reuse it
iter->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
} else {
// not found: make a new one
CTask *pTmp = new CTask;
if (!pTmp)
if (task->isFree() && !task->inExecute())
{
// found: reuse it
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
return;
pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
m_Tasks.put(pTmp);
}
}
// not found: make a new one
auto task = ke::AutoPtr<CTask>(new CTask);
if (!task)
return;
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
m_Tasks.append(ke::Move(task));
}
int CTaskMngr::removeTasks(int iId, AMX *pAmx)
{
CTaskDescriptor descriptor(iId, pAmx);
TaskListIter iter = m_Tasks.find(descriptor);
int i = 0;
while (iter)
for (auto &task : m_Tasks)
{
iter->clear();
++i;
iter = m_Tasks.find(++iter, descriptor);
if (task->match(iId, pAmx))
{
task->clear();
++i;
}
}
return i;
@ -239,16 +240,16 @@ int CTaskMngr::removeTasks(int iId, AMX *pAmx)
int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
{
CTaskDescriptor descriptor(iId, pAmx);
TaskListIter iter = m_Tasks.find(descriptor);
int i = 0;
while (iter)
for (auto &task : m_Tasks)
{
iter->changeBase(fNewBase);
iter->resetNextExecTime(*m_pTmr_CurrentTime);
++i;
iter = m_Tasks.find(++iter, descriptor);
if (task->match(iId, pAmx))
{
task->changeBase(fNewBase);
task->resetNextExecTime(*m_pTmr_CurrentTime);
++i;
}
}
return i;
@ -256,16 +257,23 @@ int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
bool CTaskMngr::taskExists(int iId, AMX *pAmx)
{
return m_Tasks.find(CTaskDescriptor(iId, pAmx));
for (auto &task : m_Tasks)
{
if (task->match(iId, pAmx))
{
return true;
}
}
return false;
}
void CTaskMngr::startFrame()
{
for (TaskListIter iter = m_Tasks.begin(); iter; ++iter)
for (auto &task : m_Tasks)
{
if (iter->isFree())
if (task->isFree())
continue;
iter->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
task->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
}
}

View File

@ -51,41 +51,18 @@ private:
inline bool inExecute() const { return m_bInExecute; }
bool shouldRepeat();
inline bool match(int id, AMX *amx)
{
return (!m_bFree) && (amx ? getAMX() == amx : true) && (m_iId == id);
}
CTask();
~CTask();
};
class CTaskDescriptor
{
public:
cell m_iId;
AMX *m_pAmx;
bool m_bFree;
CTaskDescriptor(int iId, AMX *pAmx, bool bFree = false)
{
m_iId = iId;
m_pAmx = pAmx;
m_bFree = bFree;
}
friend bool operator == (const CTask &left, const CTaskDescriptor &right)
{
if (right.m_bFree)
return (left.isFree() && !left.inExecute());
return (!left.isFree()) &&
(right.m_pAmx ? left.getAMX() == right.m_pAmx : true) &&
(left.getTaskId() == right.m_iId);
}
};
/*** CTaskMngr priv members ***/
typedef CList<CTask, CTaskDescriptor> TaskList;
typedef TaskList::iterator TaskListIter;
TaskList m_Tasks;
ke::Vector<ke::AutoPtr<CTask>> m_Tasks;
float *m_pTmr_CurrentTime;
float *m_pTmr_TimeLimit;

View File

@ -10,8 +10,6 @@
#ifndef VAULT_CUSTOM_H
#define VAULT_CUSTOM_H
#include "CList.h"
// *****************************************************
// class Vault
// *****************************************************

View File

@ -3026,16 +3026,18 @@ static cell AMX_NATIVE_CALL force_unmodified(AMX *amx, cell *params)
char* filename = get_amxstring(amx, params[4], 0, a);
ForceObject* aaa = new ForceObject(filename, (FORCE_TYPE)((int)(params[1])), vec1, vec2, amx);
auto object = ke::AutoPtr<ForceObject>(new ForceObject(filename, (FORCE_TYPE)((int)(params[1])), vec1, vec2, amx));
if (aaa)
if (object)
{
auto forceObjVec = &g_forcegeneric;
if (stristr(filename, ".wav"))
g_forcesounds.put(aaa);
forceObjVec = &g_forcesounds;
else if (stristr(filename, ".mdl"))
g_forcemodels.put(aaa);
else
g_forcegeneric.put(aaa);
forceObjVec = &g_forcemodels;
forceObjVec->append(ke::Move(object));
return 1;
}
@ -3214,9 +3216,9 @@ static cell AMX_NATIVE_CALL is_module_loaded(AMX *amx, cell *params)
char *name = get_amxstring(amx, params[1], 0, len);
int id = 0;
for (CList<CModule, const char *>::iterator iter = g_modules.begin(); iter; ++iter)
for (auto module : g_modules)
{
if (stricmp((*iter).getName(), name) == 0)
if (!stricmp(module->getName(), name))
return id;
++id;
@ -3363,50 +3365,50 @@ static cell AMX_NATIVE_CALL register_byval(AMX *amx, cell *params)
// native get_module(id, name[], nameLen, author[], authorLen, version[], versionLen, &status);
static cell AMX_NATIVE_CALL get_module(AMX *amx, cell *params)
{
CList<CModule, const char *>::iterator moduleIter;
// find the module
int i = params[1];
for (moduleIter = g_modules.begin(); moduleIter && i; ++moduleIter)
--i;
if (i != 0 || !moduleIter)
return -1; // not found
// set name, author, version
if ((*moduleIter).isAmxx())
for (auto module : g_modules)
{
const amxx_module_info_s *info = (*moduleIter).getInfoNew();
const char *name = info && info->name ? info->name : "unk";
const char *author = info && info->author ? info->author : "unk";
const char *version = info && info->version ? info->version : "unk";
if (i--)
{
continue;
}
set_amxstring_utf8(amx, params[2], name, strlen(name), params[3]);
set_amxstring_utf8(amx, params[4], author, strlen(author), params[5]);
set_amxstring_utf8(amx, params[6], version, strlen(version), params[7]);
// set name, author, version
if (module->isAmxx())
{
const amxx_module_info_s *info = module->getInfoNew();
const char *name = info && info->name ? info->name : "unk";
const char *author = info && info->author ? info->author : "unk";
const char *version = info && info->version ? info->version : "unk";
set_amxstring_utf8(amx, params[2], name, strlen(name), params[3]);
set_amxstring_utf8(amx, params[4], author, strlen(author), params[5]);
set_amxstring_utf8(amx, params[6], version, strlen(version), params[7]);
}
// compatibility problem possible
int numParams = params[0] / sizeof(cell);
if (numParams < 8)
{
LogError(amx, AMX_ERR_NATIVE, "Call to incompatible version");
return 0;
}
// set status
cell *addr;
if (amx_GetAddr(amx, params[8], &addr) != AMX_ERR_NONE)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid reference plugin");
return 0;
}
*addr = (cell)module->getStatusValue();
return params[1];
}
// compatibility problem possible
int numParams = params[0] / sizeof(cell);
if (numParams < 8)
{
LogError(amx, AMX_ERR_NATIVE, "Call to incompatible version");
return 0;
}
// set status
cell *addr;
if (amx_GetAddr(amx, params[8], &addr) != AMX_ERR_NONE)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid reference plugin");
return 0;
}
*addr = (cell)(*moduleIter).getStatusValue();
return params[1];
return -1;
}
// native log_amx(const msg[], ...);

View File

@ -30,14 +30,13 @@
#endif
#include "hashing.h"
#include "CList.h"
#include "CQueue.h"
#include "modules.h"
#include "CPlugin.h"
#include "CLibrarySys.h"
#include <auto-string.h>
#include <amtl/am-string.h>
#include <amtl/am-vector.h>
#include <amtl/am-inlinelist.h>
#include "CMisc.h"
#include "CVault.h"
#include "CModule.h"
@ -163,12 +162,12 @@ extern CFrameActionMngr g_frameActionMngr;
extern CPlayer g_players[33];
extern CPlayer* mPlayer;
extern CmdMngr g_commands;
extern CList<ForceObject> g_forcemodels;
extern CList<ForceObject> g_forcesounds;
extern CList<ForceObject> g_forcegeneric;
extern CList<CModule, const char *> g_modules;
extern CList<CScript, AMX*> g_loadedscripts;
extern CList<CPlayer*> g_auth;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcemodels;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcesounds;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcegeneric;
extern ke::Vector<ke::AutoPtr<CPlayer *>> g_auth;
extern ke::InlineList<CModule> g_modules;
extern ke::InlineList<CScript> g_loadedscripts;
extern EventsMngr g_events;
extern Grenades g_grenades;
extern LogEventsMngr g_logevents;

View File

@ -568,22 +568,26 @@ void Debugger::DisplayTrace(const char *message)
const char *Debugger::_GetFilename()
{
if (m_FileName.length() < 1)
{
const char *filename = "";
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
if (pl)
{
filename = pl->getName();
} else {
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(m_pAmx);
if (a)
filename = (*a).getName();
}
m_FileName = filename;
}
return m_FileName.chars();
if (m_FileName.length() < 1)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
if (pl)
{
m_FileName = pl->getName();
}
else
{
for (auto script : g_loadedscripts)
{
if (script->getAMX() == m_pAmx)
{
m_FileName = script->getName();
break;
}
}
}
}
return m_FileName.chars();
}
const char *Debugger::_GetVersion()
@ -605,31 +609,35 @@ const char *Debugger::_GetVersion()
void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength)
{
const char *filename = "";
char native[sNAMEMAX+1];
const char *filename = "";
char native[sNAMEMAX+1];
for (auto script : g_loadedscripts)
{
if (script->getAMX() == amx)
{
filename = script->getName();
break;
}
}
size_t len = strlen(filename);
for (size_t i=len-1; i<len; i--)
{
if ((filename[i] == '/' || filename[i] == '\\') && i != len - 1)
{
filename = &(filename[i+1]);
break;
}
}
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
if (a)
filename = (*a).getName();
size_t len = strlen(filename);
for (size_t i=len-1; i<len; i--)
{
if ((filename[i] == '/' || filename[i] == '\\') && i != len - 1)
{
filename = &(filename[i+1]);
break;
}
}
if (error == AMX_ERR_EXIT)
{
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT));
} else if (error == AMX_ERR_NATIVE) {
amx_GetNative(amx, reinterpret_cast<long>(amx->usertags[UT_NATIVE]), native);
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native);
} else {
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename);
}
if (error == AMX_ERR_EXIT)
{
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT));
} else if (error == AMX_ERR_NATIVE) {
amx_GetNative(amx, reinterpret_cast<long>(amx->usertags[UT_NATIVE]), native);
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native);
} else {
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename);
}
}
void Debugger::GenericMessage(AMX *amx, int err)

View File

@ -65,10 +65,10 @@ extern ke::Vector<CAdminData *> DynamicAdmins;
CLog g_log;
CForwardMngr g_forwards;
CList<CPlayer*> g_auth;
CList<ForceObject> g_forcemodels;
CList<ForceObject> g_forcesounds;
CList<ForceObject> g_forcegeneric;
ke::Vector<ke::AutoPtr<CPlayer *>> g_auth;
ke::Vector<ke::AutoPtr<ForceObject>> g_forcemodels;
ke::Vector<ke::AutoPtr<ForceObject>> g_forcesounds;
ke::Vector<ke::AutoPtr<ForceObject>> g_forcegeneric;
CPlayer g_players[33];
CPlayer* mPlayer;
CPluginMngr g_plugins;
@ -265,10 +265,10 @@ int C_PrecacheModel(const char *s)
if (!g_forcedmodules)
{
g_forcedmodules = true;
for (CList<ForceObject>::iterator a = g_forcemodels.begin(); a; ++a)
for (auto &model : g_forcemodels)
{
PRECACHE_MODEL((char*)(*a).getFilename());
ENGINE_FORCE_UNMODIFIED((*a).getForceType(), (*a).getMin(), (*a).getMax(), (*a).getFilename());
PRECACHE_MODEL(model->getFilename());
ENGINE_FORCE_UNMODIFIED(model->getForceType(), model->getMin(), model->getMax(), model->getFilename());
}
}
@ -280,10 +280,10 @@ int C_PrecacheSound(const char *s)
if (!g_forcedsounds)
{
g_forcedsounds = true;
for (CList<ForceObject>::iterator a = g_forcesounds.begin(); a; ++a)
for (auto &sound : g_forcesounds)
{
PRECACHE_SOUND((char*)(*a).getFilename());
ENGINE_FORCE_UNMODIFIED((*a).getForceType(), (*a).getMin(), (*a).getMax(), (*a).getFilename());
PRECACHE_SOUND(sound->getFilename());
ENGINE_FORCE_UNMODIFIED(sound->getForceType(), sound->getMin(), sound->getMax(), sound->getFilename());
}
if (!g_bmod_cstrike)
@ -533,11 +533,10 @@ int C_Spawn(edict_t *pent)
executeForwards(FF_PluginPrecache);
g_dontprecache = true;
for (CList<ForceObject>::iterator a = g_forcegeneric.begin(); a; ++a)
for (auto &generic : g_forcegeneric)
{
PRECACHE_GENERIC((char*)(*a).getFilename());
ENGINE_FORCE_UNMODIFIED((*a).getForceType(),
(*a).getMin(), (*a).getMax(), (*a).getFilename());
PRECACHE_GENERIC(generic->getFilename());
ENGINE_FORCE_UNMODIFIED(generic->getForceType(), generic->getMin(), generic->getMax(), generic->getFilename());
}
RETURN_META_VALUE(MRES_IGNORED, 0);
@ -839,9 +838,9 @@ BOOL C_ClientConnect_Post(edict_t *pEntity, const char *pszName, const char *psz
if (a)
{
CPlayer** aa = new CPlayer*(pPlayer);
if (aa)
g_auth.put(aa);
auto playerToAuth = ke::AutoPtr<CPlayer *>(new CPlayer*(pPlayer));
if (playerToAuth)
g_auth.append(ke::Move(playerToAuth));
} else {
pPlayer->Authorize();
const char* authid = GETPLAYERAUTHID(pEntity);
@ -1176,21 +1175,22 @@ void C_StartFrame_Post(void)
if (g_auth_time < gpGlobals->time)
{
g_auth_time = gpGlobals->time + 0.7f;
CList<CPlayer*>::iterator a = g_auth.begin();
while (a)
size_t i = 0;
while (i < g_auth.length())
{
const char* auth = GETPLAYERAUTHID((*a)->pEdict);
auto player = g_auth[i].get();
const char* auth = GETPLAYERAUTHID((*player)->pEdict);
if ((auth == 0) || (*auth == 0))
{
a.remove();
g_auth.remove(i);
continue;
}
if (strcmp(auth, "STEAM_ID_PENDING"))
{
(*a)->Authorize();
(*player)->Authorize();
if (g_auth_funcs.size())
{
List<AUTHORIZEFUNC>::iterator iter, end=g_auth_funcs.end();
@ -1198,15 +1198,15 @@ void C_StartFrame_Post(void)
for (iter=g_auth_funcs.begin(); iter!=end; iter++)
{
fn = (*iter);
fn((*a)->index, auth);
fn((*player)->index, auth);
}
}
executeForwards(FF_ClientAuthorized, static_cast<cell>((*a)->index), auth);
a.remove();
executeForwards(FF_ClientAuthorized, static_cast<cell>((*player)->index), auth);
g_auth.remove(i);
continue;
}
++a;
i++;
}
}

View File

@ -33,8 +33,8 @@
#include "CGameConfigs.h"
#include <amtl/os/am-path.h>
CList<CModule, const char*> g_modules;
CList<CScript, AMX*> g_loadedscripts;
ke::InlineList<CModule> g_modules;
ke::InlineList<CScript> g_loadedscripts;
CModule *g_CurrentlyCalledModule = NULL; // The module we are in at the moment; NULL otherwise
@ -333,9 +333,15 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
}
#endif
CScript* aa = new CScript(amx, *program, filename);
auto script = new CScript(amx, *program, filename);
g_loadedscripts.put(aa);
if (!script)
{
ke::SafeSprintf(error, 64, "Failed to allocate memory for script");
return (amx->error = AMX_ERR_MEMORY);
}
g_loadedscripts.append(script);
set_amxnatives(amx, error);
@ -420,23 +426,19 @@ int CheckModules(AMX *amx, char error[128])
/* for binary compat */
if (!found)
{
CList<CModule, const char *>::iterator a = g_modules.begin();
while (a)
for (auto module : g_modules)
{
CModule &cm = (*a);
if (cm.getStatusValue() != MODULE_LOADED)
if (module->getStatusValue() != MODULE_LOADED)
{
++a;
continue;
}
if (cm.getInfoNew() &&
cm.getInfoNew()->logtag &&
!strcasecmp(cm.getInfoNew()->logtag, buffer))
if (module->getInfoNew() &&
module->getInfoNew()->logtag &&
!strcasecmp(module->getInfoNew()->logtag, buffer))
{
found = true;
break;
}
++a;
}
}
@ -498,18 +500,16 @@ int CheckModules(AMX *amx, char error[128])
int set_amxnatives(AMX* amx, char error[128])
{
CModule *cm;
for (CList<CModule, const char *>::iterator a = g_modules.begin(); a ; ++a)
for (auto module : g_modules)
{
cm = &(*a);
for (size_t i=0; i<cm->m_Natives.length(); i++)
for (size_t i = 0; i < module->m_Natives.length(); i++)
{
amx_Register(amx, cm->m_Natives[i], -1);
amx_Register(amx, module->m_Natives[i], -1);
}
for (size_t i = 0; i < cm->m_NewNatives.length(); i++)
for (size_t i = 0; i < module->m_NewNatives.length(); i++)
{
amx_Register(amx, cm->m_NewNatives[i], -1);
amx_Register(amx, module->m_NewNatives[i], -1);
}
}
@ -578,10 +578,16 @@ int unload_amxscript(AMX* amx, void** program)
if (opt)
delete opt;
CList<CScript, AMX*>::iterator a = g_loadedscripts.find(amx);
for (auto script : g_loadedscripts)
{
if (script->getAMX() == amx)
{
g_loadedscripts.remove(script);
delete script;
if (a)
a.remove();
break;
}
}
char *prg = (char *)*program;
@ -628,20 +634,20 @@ int unload_amxscript(AMX* amx, void** program)
AMX* get_amxscript(int id, void** code, const char** filename)
{
CList<CScript, AMX*>::iterator a = g_loadedscripts.begin();
while (a && id--)
++a;
if (a)
for (auto script : g_loadedscripts)
{
*filename = (*a).getName();
*code = (*a).getCode();
if (id--)
{
continue;
}
return (*a).getAMX();
*filename = script->getName();
*code = script->getCode();
return script->getAMX();
}
return 0;
return nullptr;
}
const char* GetFileName(AMX *amx)
@ -652,10 +658,17 @@ const char* GetFileName(AMX *amx)
if (pl)
{
filename = pl->getName();
} else {
CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
if (a)
filename = (*a).getName();
}
else
{
for (auto script : g_loadedscripts)
{
if (script->getAMX() == amx)
{
filename = script->getName();
break;
}
}
}
return filename;
@ -663,8 +676,14 @@ const char* GetFileName(AMX *amx)
const char* get_amxscriptname(AMX* amx)
{
CList<CScript, AMX*>::iterator a = g_loadedscripts.find(amx);
return a ? (*a).getName() : "";
for (auto script : g_loadedscripts)
{
if (script->getAMX() == amx)
{
return script->getName();
}
}
return "";
}
void get_modname(char* buffer)
@ -829,18 +848,26 @@ bool LoadModule(const char *shortname, PLUG_LOADTIME now, bool simplify, bool no
fclose(fp);
}
CList<CModule, const char *>::iterator a = g_modules.find(path);
for (auto module : g_modules)
{
if (!strcmp(module->getFilename(), path))
{
return false;
}
}
if (a)
auto module = new CModule(path);
if (!module)
{
return false;
}
CModule* cc = new CModule(path);
cc->queryModule();
module->queryModule();
bool error = true;
switch (cc->getStatusValue())
switch (module->getStatusValue())
{
case MODULE_BADLOAD:
report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", path);
@ -852,7 +879,7 @@ bool LoadModule(const char *shortname, PLUG_LOADTIME now, bool simplify, bool no
report_error(1, "[AMXX] Couldn't find \"AMX_Query\" or \"AMXX_Query\" (file \"%s\")", path);
break;
case MODULE_NOATTACH:
report_error(1, "[AMXX] Couldn't find \"%s\" (file \"%s\")", cc->isAmxx() ? "AMXX_Attach" : "AMX_Attach", path);
report_error(1, "[AMXX] Couldn't find \"%s\" (file \"%s\")", module->isAmxx() ? "AMXX_Attach" : "AMX_Attach", path);
break;
case MODULE_OLD:
report_error(1, "[AMXX] Module has a different interface version (file \"%s\")", path);
@ -874,38 +901,38 @@ bool LoadModule(const char *shortname, PLUG_LOADTIME now, bool simplify, bool no
break;
}
g_modules.put(cc);
g_modules.append(module);
if (error)
{
return false;
}
if (cc->IsMetamod())
if (module->IsMetamod())
{
char *mmpathname = build_pathname_addons(
"%s/%s",
get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"),
shortname);
ConvertModuleName(mmpathname, path);
cc->attachMetamod(path, now);
module->attachMetamod(path, now);
}
bool retVal = cc->attachModule();
bool retVal = module->attachModule();
if (cc->isAmxx() && !retVal)
if (module->isAmxx() && !retVal)
{
switch (cc->getStatusValue())
switch (module->getStatusValue())
{
case MODULE_FUNCNOTPRESENT:
report_error(1, "[AMXX] Module requested a not existing function (file \"%s\")%s%s%s", cc->getFilename(), cc->getMissingFunc() ? " (func \"" : "",
cc->getMissingFunc() ? cc->getMissingFunc() : "", cc->getMissingFunc() ? "\")" : "");
report_error(1, "[AMXX] Module requested a not existing function (file \"%s\")%s%s%s", module->getFilename(), module->getMissingFunc() ? " (func \"" : "",
module->getMissingFunc() ? module->getMissingFunc() : "", module->getMissingFunc() ? "\")" : "");
break;
case MODULE_INTERROR:
report_error(1, "[AMXX] Internal error during module load (file \"%s\")", cc->getFilename());
report_error(1, "[AMXX] Internal error during module load (file \"%s\")", module->getFilename());
break;
case MODULE_BADLOAD:
report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", cc->getFilename());
report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", module->getFilename());
break;
}
@ -969,29 +996,33 @@ int loadModules(const char* filename, PLUG_LOADTIME now)
void detachModules()
{
CList<CModule, const char *>::iterator a = g_modules.begin();
while (a)
auto moduleIter = g_modules.begin(), end = g_modules.end();
while (moduleIter != end)
{
(*a).detachModule();
a.remove();
auto module = *moduleIter;
module->detachModule();
moduleIter = g_modules.erase(moduleIter);
delete module;
}
}
void detachReloadModules()
{
CList<CModule, const char *>::iterator a = g_modules.begin();
while (a)
auto moduleIter = g_modules.begin(), end = g_modules.end();
while (moduleIter != end)
{
if ((*a).isReloadable() && !(*a).IsMetamod())
auto module = *moduleIter;
if (module->isReloadable() && !module->IsMetamod())
{
(*a).detachModule();
a.remove();
module->detachModule();
moduleIter = g_modules.erase(moduleIter);
delete module;
continue;
}
++a;
moduleIter++;
}
}
@ -1015,34 +1046,29 @@ const char* strip_name(const char* a)
// Get the number of running modules
int countModules(CountModulesMode mode)
{
CList<CModule, const char *>::iterator iter;
int num;
auto num = 0;
switch (mode)
{
case CountModules_All:
return g_modules.size();
case CountModules_Running:
iter = g_modules.begin();
num = 0;
while (iter)
for (auto module : g_modules)
{
if ((*iter).getStatusValue() == MODULE_LOADED)
num++;
}
return num;
case CountModules_Running:
for (auto module : g_modules)
{
if (module->getStatusValue() == MODULE_LOADED)
++num;
++iter;
}
return num;
case CountModules_Stopped:
iter = g_modules.begin();
num = 0;
while (iter)
for (auto module : g_modules)
{
if ((*iter).getStatusValue() != MODULE_LOADED)
if (module->getStatusValue() != MODULE_LOADED)
++num;
++iter;
}
return num;
@ -1054,35 +1080,26 @@ int countModules(CountModulesMode mode)
// Call all modules' AMXX_PluginsLoaded functions
void modules_callPluginsLoaded()
{
CList<CModule, const char *>::iterator iter = g_modules.begin();
while (iter)
for (auto module : g_modules)
{
(*iter).CallPluginsLoaded();
++iter;
module->CallPluginsLoaded();
}
}
//same for unloaded
void modules_callPluginsUnloaded()
{
CList<CModule, const char *>::iterator iter = g_modules.begin();
while (iter)
for (auto module : g_modules)
{
(*iter).CallPluginsUnloaded();
++iter;
module->CallPluginsUnloaded();
}
}
void modules_callPluginsUnloading()
{
CList<CModule, const char *>::iterator iter = g_modules.begin();
while (iter)
for (auto module : g_modules)
{
(*iter).CallPluginsUnloading();
++iter;
module->CallPluginsUnloading();
}
}
@ -1114,44 +1131,42 @@ const char *MNF_GetModname(void)
AMX *MNF_GetAmxScript(int id)
{
CList<CScript, AMX*>::iterator iter = g_loadedscripts.begin();
while (iter && id--)
++iter;
if (iter == 0)
return NULL;
return (*iter).getAMX();
for (auto script : g_loadedscripts)
{
if (id--)
{
continue;
}
return script->getAMX();
}
return nullptr;
}
const char *MNF_GetAmxScriptName(int id)
{
CList<CScript, AMX*>::iterator iter = g_loadedscripts.begin();
while (iter && id--)
++iter;
if (iter == 0)
return NULL;
return (*iter).getName();
for (auto script : g_loadedscripts)
{
if (id--)
{
continue;
}
return script->getName();
}
return nullptr;
}
int MNF_FindAmxScriptByName(const char *name)
{
CList<CScript, AMX*>::iterator iter = g_loadedscripts.begin();
bool found = false;
int i = 0;
while (iter)
for (auto script : g_loadedscripts)
{
if (stricmp((*iter).getName(), name) == 0)
if (!stricmp(script->getName(), name))
{
found = true;
break;
}
++iter;
++i;
}
@ -1163,19 +1178,16 @@ int MNF_FindAmxScriptByName(const char *name)
int MNF_FindAmxScriptByAmx(const AMX *amx)
{
CList<CScript, AMX*>::iterator iter = g_loadedscripts.begin();
bool found = false;
int i = 0;
while (iter)
for (auto script : g_loadedscripts)
{
if (amx == (*iter).getAMX())
if (script->getAMX() == amx)
{
found = true;
break;
}
++iter;
++i;
}
@ -1276,17 +1288,16 @@ void MNF_OverrideNatives(AMX_NATIVE_INFO *natives, const char *name)
{
//HACKHACK - we should never have had to do this
//find a better solution for SourceMod!!!
for (CList<CModule, const char *>::iterator a = g_modules.begin(); a ; ++a)
for (auto module : g_modules)
{
CModule &cm = (*a);
if (cm.getStatusValue() != MODULE_LOADED)
if (module->getStatusValue() != MODULE_LOADED)
continue;
const amxx_module_info_s *p = cm.getInfoNew();
const amxx_module_info_s *p = module->getInfoNew();
if (!p || !p->name)
continue;
if (strcmp(p->name, name)==0)
continue;
cm.rewriteNativeLists(natives);
module->rewriteNativeLists(natives);
}
}
@ -1600,52 +1611,38 @@ cell MNF_PrepareCharArray(char *ptr, unsigned int size)
return prepareCharArray(ptr, size, false);
}
inline bool operator ==(func_s &arg1, const char *desc)
{
if (strcmp(arg1.desc, desc) == 0)
return true;
return false;
}
CList<func_s, const char *> g_functions;
ke::Vector<ke::AutoPtr<func_s>> g_functions;
// Fnptr Request function for the new interface
const char *g_LastRequestedFunc = NULL;
#define REGISTER_FUNC(name, func) \
{ \
pFunc = new func_s; \
auto pFunc = ke::AutoPtr<func_s>(new func_s); \
pFunc->pfn = (void *)func; \
pFunc->desc = name; \
g_functions.put(pFunc); \
g_functions.append(ke::Move(pFunc)); \
}
void MNF_RegisterFunction(void *pfn, const char *description)
{
func_s *pFunc;
REGISTER_FUNC(description, pfn);
}
void *MNF_RegisterFunctionEx(void *pfn, const char *description)
{
func_s *pFunc;
CList<func_s, const char *>::iterator iter;
for (iter = g_functions.begin(); iter; ++iter)
for (auto &func : g_functions)
{
pFunc = &(*iter);
if (strcmp(description, pFunc->desc) == 0)
if (!strcmp(description, func->desc))
{
void *pOld = pFunc->pfn;
pFunc->pfn = pfn;
void *pOld = func->pfn;
func->pfn = pfn;
return pOld;
}
}
MNF_RegisterFunction(pfn, description);
return NULL;
return nullptr;
}
void Module_UncacheFunctions()
@ -1774,8 +1771,6 @@ IGameConfigManager *MNF_GetConfigManager()
void Module_CacheFunctions()
{
func_s *pFunc;
REGISTER_FUNC("BuildPathname", build_pathname)
REGISTER_FUNC("BuildPathnameR", build_pathname_r)
REGISTER_FUNC("PrintSrvConsole", print_srvconsole)
@ -1883,20 +1878,15 @@ void Module_CacheFunctions()
void *Module_ReqFnptr(const char *funcName)
{
// code
// ^---- really? wow!
g_LastRequestedFunc = funcName;
CList<func_s, const char *>::iterator iter;
for (iter = g_functions.begin(); iter; ++iter)
for (auto &func : g_functions)
{
if (strcmp(funcName, iter->desc) == 0)
return iter->pfn;
if (!strcmp(funcName, func->desc))
return func->pfn;
}
return NULL;
return nullptr;
}
Debugger *DisableDebugHandler(AMX *amx)

View File

@ -316,6 +316,9 @@
<ClInclude Include="..\..\public\resdk\engine\rehlds_api.h" />
<ClInclude Include="..\..\public\resdk\engine\rehlds_interfaces.h" />
<ClInclude Include="..\..\public\resdk\mod_rehlds_api.h" />
<ClInclude Include="..\..\public\sh_list.h" />
<ClInclude Include="..\..\public\sh_stack.h" />
<ClInclude Include="..\..\public\sh_tinyhash.h" />
<ClInclude Include="..\..\third_party\hashing\hashers\crc32.h" />
<ClInclude Include="..\..\third_party\hashing\hashers\keccak.h" />
<ClInclude Include="..\..\third_party\hashing\hashers\md5.h" />
@ -350,14 +353,12 @@
<ClInclude Include="..\CGameConfigs.h" />
<ClInclude Include="..\CLang.h" />
<ClInclude Include="..\CLibrarySys.h" />
<ClInclude Include="..\CList.h" />
<ClInclude Include="..\CLogEvent.h" />
<ClInclude Include="..\CMenu.h" />
<ClInclude Include="..\CMisc.h" />
<ClInclude Include="..\CModule.h" />
<ClInclude Include="..\CoreConfig.h" />
<ClInclude Include="..\CPlugin.h" />
<ClInclude Include="..\CQueue.h" />
<ClInclude Include="..\CTask.h" />
<ClInclude Include="..\CTextParsers.h" />
<ClInclude Include="..\CvarManager.h" />
@ -375,9 +376,6 @@
<ClInclude Include="..\newmenus.h" />
<ClInclude Include="..\nongpl_matches.h" />
<ClInclude Include="..\optimizer.h" />
<ClInclude Include="..\sh_list.h" />
<ClInclude Include="..\sh_stack.h" />
<ClInclude Include="..\sh_tinyhash.h" />
<ClInclude Include="..\textparse.h" />
<ClInclude Include="..\trie_natives.h" />
<ClInclude Include="..\..\public\sdk\amxxmodule.h" />
@ -426,4 +424,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -338,9 +338,6 @@
<ClInclude Include="..\CLang.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\CList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\CLogEvent.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -356,9 +353,6 @@
<ClInclude Include="..\CPlugin.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\CQueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\CTask.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -398,15 +392,6 @@
<ClInclude Include="..\optimizer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sh_list.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sh_stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sh_tinyhash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\trie_natives.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -419,6 +404,15 @@
<ClInclude Include="..\textparse.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\public\sh_list.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\public\sh_stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\public\sh_tinyhash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\public\sdk\amxxmodule.h">
<Filter>SDK</Filter>
</ClInclude>
@ -636,4 +630,4 @@
<Filter>Assembly\Builds</Filter>
</Object>
</ItemGroup>
</Project>
</Project>

View File

@ -1,297 +0,0 @@
/* ======== SourceMM ========
* Copyright (C) 2004-2005 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): David "BAILOPAN" Anderson
* ============================
*/
#ifndef _INCLUDE_SMM_LIST_H
#define _INCLUDE_SMM_LIST_H
// MSVC8 fix for offsetof macro redefition warnings
#ifdef _MSC_VER
#if _MSC_VER >= 1400
#undef offsetof
#endif
#endif
#include <new>
#include <stdlib.h>
//namespace SourceHook
//{
//This class is from CSDM for AMX Mod X
/*
A circular, doubly-linked list with one sentinel node
Empty:
m_Head = sentinel
m_Head->next = m_Head;
m_Head->prev = m_Head;
One element:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node1
node1->next = m_Head
node1->prev = m_Head
Two elements:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node2
node1->next = node2
node1->prev = m_Head
node2->next = m_Head
node2->prev = node1
*/
template <class T>
class List
{
public:
class iterator;
friend class iterator;
class ListNode
{
public:
ListNode(const T & o) : obj(o) { };
ListNode() { };
T obj;
ListNode *next;
ListNode *prev;
};
private:
// Initializes the sentinel node.
// BAIL used malloc instead of new in order to bypass the need for a constructor.
ListNode *_Initialize()
{
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
n->next = n;
n->prev = n;
return n;
}
public:
List() : m_Head(_Initialize()), m_Size(0)
{
}
List(const List &src) : m_Head(_Initialize()), m_Size(0)
{
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
push_back( (*iter) );
}
~List()
{
clear();
// Don't forget to free the sentinel
if (m_Head)
{
free(m_Head);
m_Head = NULL;
}
}
void push_back(const T &obj)
{
ListNode *node = new ListNode(obj);
node->prev = m_Head->prev;
node->next = m_Head;
m_Head->prev->next = node;
m_Head->prev = node;
m_Size++;
}
size_t size()
{
return m_Size;
}
void clear()
{
ListNode *node = m_Head->next;
ListNode *temp;
m_Head->next = m_Head;
m_Head->prev = m_Head;
// Iterate through the nodes until we find g_Head (the sentinel) again
while (node != m_Head)
{
temp = node->next;
delete node;
node = temp;
}
m_Size = 0;
}
bool empty()
{
return (m_Size == 0);
}
T & back()
{
return m_Head->prev->obj;
}
private:
ListNode *m_Head;
size_t m_Size;
public:
class iterator
{
friend class List;
public:
iterator()
{
m_This = NULL;
}
iterator(const List &src)
{
m_This = src.m_Head;
}
iterator(ListNode *n) : m_This(n)
{
}
iterator(const iterator &where)
{
m_This = where.m_This;
}
//pre decrement
iterator & operator--()
{
if (m_This)
m_This = m_This->prev;
return *this;
}
//post decrement
iterator operator--(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->prev;
return old;
}
//pre increment
iterator & operator++()
{
if (m_This)
m_This = m_This->next;
return *this;
}
//post increment
iterator operator++(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->next;
return old;
}
const T & operator * () const
{
return m_This->obj;
}
T & operator * ()
{
return m_This->obj;
}
T * operator -> ()
{
return &(m_This->obj);
}
const T * operator -> () const
{
return &(m_This->obj);
}
bool operator != (const iterator &where) const
{
return (m_This != where.m_This);
}
bool operator ==(const iterator &where) const
{
return (m_This == where.m_This);
}
private:
ListNode *m_This;
};
public:
iterator begin() const
{
return iterator(m_Head->next);
}
iterator end() const
{
return iterator(m_Head);
}
iterator erase(iterator &where)
{
ListNode *pNode = where.m_This;
iterator iter(where);
iter++;
// Works for all cases: empty list, erasing first element, erasing tail, erasing in the middle...
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
delete pNode;
m_Size--;
return iter;
}
iterator insert(iterator where, const T &obj)
{
// Insert obj right before where
ListNode *node = new ListNode(obj);
ListNode *pWhereNode = where.m_This;
pWhereNode->prev->next = node;
node->prev = pWhereNode->prev;
pWhereNode->prev = node;
node->next = pWhereNode;
m_Size++;
return iterator(node);
}
public:
void remove(const T & obj)
{
iterator b;
for (b=begin(); b!=end(); b++)
{
if ( (*b) == obj )
{
erase( b );
break;
}
}
}
template <typename U>
iterator find(const U & equ)
{
iterator iter;
for (iter=begin(); iter!=end(); iter++)
{
if ( (*iter) == equ )
return iter;
}
return end();
}
List & operator =(const List &src)
{
clear();
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
push_back( (*iter) );
return *this;
}
};
//}; //NAMESPACE
#endif //_INCLUDE_CSDM_LIST_H

View File

@ -1,219 +0,0 @@
/* ======== SourceMM ========
* Copyright (C) 2004-2005 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): Pavol "PM OnoTo" Marko
* ============================
*/
#ifndef __SH_STACK_H__
#define __SH_STACK_H__
#define SH_STACK_DEFAULT_SIZE 4
//namespace SourceHook
//{/
// Vector
template <class T> class CStack
{
T *m_Elements;
size_t m_AllocatedSize;
size_t m_UsedSize;
public:
friend class iterator;
class iterator
{
CStack<T> *m_pParent;
size_t m_Index;
public:
iterator(CStack<T> *pParent, size_t id) : m_pParent(pParent), m_Index(id)
{
}
iterator(CStack<T> *pParent) : m_pParent(pParent), m_Index(0)
{
}
iterator() : m_pParent(NULL), m_Index(0)
{
}
T &operator *()
{
return m_pParent->m_Elements[m_Index];
}
const T &operator *() const
{
return m_pParent->m_Elements[m_Index];
}
T * operator->()
{
return m_pParent->m_Elements + m_Index;
}
const T * operator->() const
{
return m_pParent->m_Elements + m_Index;
}
iterator & operator++() // preincrement
{
++m_Index;
return (*this);
}
iterator operator++(int) // postincrement
{
iterator tmp = *this;
++m_Index;
return tmp;
}
iterator & operator--() // predecrement
{
--m_Index;
return (*this);
}
iterator operator--(int) // postdecrememnt
{
iterator tmp = *this;
--m_Index;
return tmp;
}
bool operator==(const iterator & right) const
{
return (m_pParent == right.m_pParent && m_Index == right.m_Index);
}
bool operator!=(const iterator & right) const
{
return !(*this == right);
}
};
CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]),
m_AllocatedSize(SH_STACK_DEFAULT_SIZE),
m_UsedSize(0)
{
}
CStack(size_t size) : m_Elements(new T[size]),
m_AllocatedSize(size),
m_UsedSize(0)
{
}
CStack(const CStack &other) : m_Elements(NULL),
m_AllocatedSize(0),
m_UsedSize(0)
{
reserve(other.m_AllocatedSize);
m_UsedSize = other.m_UsedSize;
for (size_t i = 0; i < m_UsedSize; ++i)
m_Elements[i] = other.m_Elements[i];
}
~CStack()
{
if (m_Elements)
delete [] m_Elements;
}
void operator=(const CStack &other)
{
if (m_AllocatedSize < other.m_AllocatedSize)
{
if (m_Elements)
delete [] m_Elements;
m_Elements = new T[other.m_AllocatedSize];
m_AllocatedSize = other.m_AllocatedSize;
}
m_UsedSize = other.m_UsedSize;
for (size_t i = 0; i < m_UsedSize; ++i)
m_Elements[i] = other.m_Elements[i];
}
bool push(const T &val)
{
if (m_UsedSize + 1 == m_AllocatedSize)
{
// zOHNOES! REALLOCATE!
m_AllocatedSize *= 2;
T *newElements = new T[m_AllocatedSize];
if (!newElements)
{
m_AllocatedSize /= 2;
return false;
}
if (m_Elements)
{
for (size_t i = 0; i < m_UsedSize; ++i)
newElements[i] = m_Elements[i];
delete [] m_Elements;
}
m_Elements = newElements;
}
m_Elements[m_UsedSize++] = val;
return true;
}
void pop()
{
--m_UsedSize;
}
T &front()
{
return m_Elements[m_UsedSize - 1];
}
const T &front() const
{
return m_Elements[m_UsedSize - 1];
}
iterator begin()
{
return iterator(this, 0);
}
iterator end()
{
return iterator(this, m_UsedSize);
}
size_t size()
{
return m_UsedSize;
}
size_t capacity()
{
return m_AllocatedSize;
}
bool empty()
{
return m_UsedSize == 0 ? true : false;
}
bool reserve(size_t size)
{
if (size > m_AllocatedSize)
{
T *newElements = new T[size];
if (!newElements)
return false;
if (m_Elements)
{
for (size_t i = 0; i < m_UsedSize; ++i)
newElements[i] = m_Elements[i];
delete [] m_Elements;
}
m_Elements = newElements;
m_AllocatedSize = size;
}
return true;
}
};
//}; //namespace SourceHook
#endif

View File

@ -188,16 +188,13 @@ void amx_command()
int running = 0;
int modules = 0;
CList<CModule, const char *>::iterator a = g_modules.begin();
while (a)
for (auto module : g_modules)
{
if ((*a).getStatusValue() == MODULE_LOADED)
if (module->getStatusValue() == MODULE_LOADED)
++running;
++modules;
print_srvconsole(" [%2d] %-23.22s %-11.10s %-20.19s %-11.10s\n", modules, (*a).getName(), (*a).getVersion(), (*a).getAuthor(), (*a).getStatus());
++a;
print_srvconsole(" [%2d] %-23.22s %-11.10s %-20.19s %-11.10s\n", modules, module->getName(), module->getVersion(), module->getAuthor(), module->getStatus());
}
print_srvconsole("%d modules, %d correct\n", modules, running);

View File

@ -14,7 +14,6 @@
#include <stdlib.h>
#include "amxxapi.h"
#include "NVault.h"
#include <sm_queue.h>
#ifdef WIN32
#define MKDIR(p) mkdir(p)
@ -31,7 +30,7 @@
#endif
ke::Vector<NVault *> g_Vaults;
Queue<int> g_OldVaults;
ke::Deque<int> g_OldVaults;
VaultMngr g_VaultMngr;
@ -63,8 +62,7 @@ static cell nvault_open(AMX *amx, cell *params)
}
if (!g_OldVaults.empty())
{
id = g_OldVaults.first();
g_OldVaults.pop();
id = g_OldVaults.popFrontCopy();
}
if (id != -1)
{
@ -210,7 +208,7 @@ static cell nvault_close(AMX *amx, cell *params)
pVault->Close();
delete pVault;
g_Vaults[id] = NULL;
g_OldVaults.push(id);
g_OldVaults.append(id);
return 1;
}
@ -268,7 +266,7 @@ void OnPluginsUnloaded()
}
g_Vaults.clear();
while (!g_OldVaults.empty())
g_OldVaults.pop();
g_OldVaults.popFront();
}
AMX_NATIVE_INFO nVault_natives[] = {

View File

@ -17,9 +17,8 @@
#include "amxxmodule.h"
#include <amtl/am-vector.h>
#include <amtl/am-string.h>
#include <sm_queue.h>
#include <amtl/am-deque.h>
extern AMX_NATIVE_INFO nVault_natives[];
#endif //_INCLUDE_AMXXAPI_H

@ -1 +1 @@
Subproject commit b0550fd444f7e0cc4f071ee587fc85ff82671502
Subproject commit c91e8560fb00984465a1a916172123b80a76dd04

View File

@ -1,367 +0,0 @@
/* ======== SourceMM ========
* Copyright (C) 2004-2005 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): David "BAILOPAN" Anderson
* ============================
*/
/* AMX Mod X
*
* by the AMX Mod X Development Team
*/
#ifndef _INCLUDE_CSTRING_H
#define _INCLUDE_CSTRING_H
#include <string.h>
#include <stdio.h>
//namespace SourceHook
//{
class String
{
public:
String()
{
v = NULL;
a_size = 0;
//assign("");
}
~String()
{
if (v)
delete [] v;
}
String(const char *src)
{
v = NULL;
a_size = 0;
assign(src);
}
String(const String &src)
{
v = NULL;
a_size = 0;
assign(src.c_str());
}
const char *c_str() { return v?v:""; }
const char *c_str() const { return v?v:""; }
void append(const char *t)
{
Grow(size() + strlen(t) + 1);
strcat(v, t);
}
void append(const char c)
{
size_t len = size();
Grow(len + 2);
v[len] = c;
v[len + 1] = '\0';
}
void append(String &d)
{
append(d.c_str());
}
void assign(const String &src)
{
assign(src.c_str());
}
void assign(const char *d)
{
if (!d)
{
clear();
} else {
Grow(strlen(d) + 1, false);
strcpy(v, d);
}
}
void clear()
{
if (v)
v[0] = '\0';
}
int compare (const char *d)
{
if (!v)
return strcmp("", d);
else
return strcmp(v, d);
}
//Added this for amxx inclusion
bool empty()
{
if (!v)
return true;
if (v[0] == '\0')
return true;
return false;
}
size_t size()
{
if (v)
return strlen(v);
else
return 0;
}
int find(const char c, int index = 0)
{
int len = static_cast<int>(size());
if (len < 1)
return npos;
if (index >= len || index < 0)
return npos;
int i = 0;
for (i=index; i<len; i++)
{
if (v[i] == c)
{
return i;
}
}
return npos;
}
bool is_space(int c)
{
if (c == '\f' || c == '\n' ||
c == '\t' || c == '\r' ||
c == '\v' || c == ' ')
{
return true;
}
return false;
}
void trim()
{
if (!v)
return;
unsigned int i = 0;
unsigned int j = 0;
size_t len = strlen(v);
if (len == 1)
{
if (is_space(v[i]))
{
clear();
return;
}
}
unsigned char c0 = v[0];
if (is_space(c0))
{
for (i=0; i<len; i++)
{
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==len-1)))
{
erase(0, i);
break;
}
}
}
len = strlen(v);
if (len < 1)
{
return;
}
if (is_space(v[len-1]))
{
for (i=len-1; i<len; i--)
{
if (!is_space(v[i])
|| (is_space(v[i]) && i==0))
{
erase(i+1, j);
break;
}
j++;
}
}
if (len == 1)
{
if (is_space(v[0]))
{
clear();
return;
}
}
}
void erase(unsigned int start, int num = npos)
{
if (!v)
return;
unsigned int i = 0;
size_t len = size();
//check for bounds
if (num == npos || start+num > len-start)
num = len - start;
//do the erasing
bool copyflag = false;
for (i=0; i<len; i++)
{
if (i>=start && i<start+num)
{
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
copyflag = true;
} else if (copyflag) {
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
}
}
len -= num;
v[len] = 0;
}
String substr(unsigned int index, int num = npos)
{
if (!v)
{
String b("");
return b;
}
String ns;
size_t len = size();
if (index >= len || !v)
return ns;
if (num == npos)
{
num = len - index;
} else if (index+num >= len) {
num = len - index;
}
unsigned int i = 0;
unsigned int nslen = num + 2;
ns.Grow(nslen);
for (i=index; i<index+num; i++)
ns.append(v[i]);
return ns;
}
void toLower()
{
if (!v)
return;
unsigned int i = 0;
size_t len = strlen(v);
for (i=0; i<len; i++)
{
if (v[i] >= 65 && v[i] <= 90)
v[i] &= ~(1<<5);
}
}
String & operator = (const String &src)
{
assign(src);
return *this;
}
String & operator = (const char *src)
{
assign(src);
return *this;
}
char operator [] (unsigned int index)
{
if (index > size() || !v)
{
return -1;
} else {
return v[index];
}
}
int at(int a)
{
if (a < 0 || a >= (int)size() || !v)
return -1;
return v[a];
}
bool at(int at, char c)
{
if (at < 0 || at >= (int)size() || !v)
return false;
v[at] = c;
return true;
}
private:
void Grow(unsigned int d, bool copy=true)
{
if (d <= a_size)
return;
char *n = new char[d + 1];
if (copy && v)
strcpy(n, v);
if (v)
delete [] v;
else
strcpy(n, "");
v = n;
a_size = d + 1;
}
char *v;
unsigned int a_size;
public:
static const int npos = -1;
};
//}; //NAMESPACE
#endif //_INCLUDE_CSTRING_H

View File

@ -1,333 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* 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/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SM_QUEUE_H
#define _INCLUDE_SM_QUEUE_H
#include <new>
#include <stdlib.h>
#include <sh_stack.h>
//using namespace SourceHook;
/*
A circular, doubly-linked List with one sentinel node
Empty:
m_Head = sentinel
m_Head->next = m_Head;
m_Head->prev = m_Head;
One element:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node1
node1->next = m_Head
node1->prev = m_Head
Two elements:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node2
node1->next = node2
node1->prev = m_Head
node2->next = m_Head
node2->prev = node1
*/
template <class T>
class Queue
{
public:
class iterator;
friend class iterator;
class QueueNode
{
public:
T obj;
QueueNode *next;
QueueNode *prev;
};
private:
// Initializes the sentinel node.
QueueNode *_Initialize()
{
QueueNode *n = (QueueNode *)malloc(sizeof(QueueNode));
n->next = n;
n->prev = n;
return n;
}
public:
Queue() : m_Head(_Initialize()), m_Size(0)
{
}
Queue(const Queue &src) : m_Head(_Initialize()), m_Size(0)
{
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
{
push_back( (*iter) );
}
}
~Queue()
{
clear();
// Don't forget to free the sentinel
if (m_Head)
{
free(m_Head);
m_Head = NULL;
}
while (!m_FreeNodes.empty())
{
free(m_FreeNodes.front());
m_FreeNodes.pop();
}
}
void push(const T &obj)
{
QueueNode *node;
if (m_FreeNodes.empty())
{
node = (QueueNode *)malloc(sizeof(QueueNode));
} else {
node = m_FreeNodes.front();
m_FreeNodes.pop();
}
/* Copy the object */
new (&node->obj) T(obj);
/* Install into the Queue */
node->prev = m_Head->prev;
node->next = m_Head;
m_Head->prev->next = node;
m_Head->prev = node;
m_Size++;
}
size_t size() const
{
return m_Size;
}
void clear()
{
QueueNode *node = m_Head->next;
QueueNode *temp;
m_Head->next = m_Head;
m_Head->prev = m_Head;
// Iterate through the nodes until we find g_Head (the sentinel) again
while (node != m_Head)
{
temp = node->next;
node->obj.~T();
m_FreeNodes.push(node);
node = temp;
}
m_Size = 0;
}
bool empty() const
{
return (m_Size == 0);
}
private:
QueueNode *m_Head;
size_t m_Size;
CStack<QueueNode *> m_FreeNodes;
public:
class iterator
{
friend class Queue;
public:
iterator()
{
m_This = NULL;
}
iterator(const Queue &src)
{
m_This = src.m_Head;
}
iterator(QueueNode *n) : m_This(n)
{
}
iterator(const iterator &where)
{
m_This = where.m_This;
}
//pre decrement
iterator & operator--()
{
if (m_This)
m_This = m_This->prev;
return *this;
}
//post decrement
iterator operator--(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->prev;
return old;
}
//pre increment
iterator & operator++()
{
if (m_This)
m_This = m_This->next;
return *this;
}
//post increment
iterator operator++(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->next;
return old;
}
const T & operator * () const
{
return m_This->obj;
}
T & operator * ()
{
return m_This->obj;
}
T * operator -> ()
{
return &(m_This->obj);
}
const T * operator -> () const
{
return &(m_This->obj);
}
bool operator != (const iterator &where) const
{
return (m_This != where.m_This);
}
bool operator ==(const iterator &where) const
{
return (m_This == where.m_This);
}
private:
QueueNode *m_This;
};
public:
iterator begin() const
{
return iterator(m_Head->next);
}
iterator end() const
{
return iterator(m_Head);
}
iterator erase(iterator &where)
{
QueueNode *pNode = where.m_This;
iterator iter(where);
iter++;
// Works for all cases: empty Queue, erasing first element, erasing tail, erasing in the middle...
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
pNode->obj.~T();
m_FreeNodes.push(pNode);
m_Size--;
return iter;
}
public:
void remove(const T & obj)
{
iterator b;
for (b=begin(); b!=end(); b++)
{
if ( (*b) == obj )
{
erase( b );
break;
}
}
}
template <typename U>
iterator find(const U & equ) const
{
iterator iter;
for (iter=begin(); iter!=end(); iter++)
{
if ( (*iter) == equ )
{
return iter;
}
}
return end();
}
Queue & operator =(const Queue &src)
{
clear();
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
{
push_back( (*iter) );
}
return *this;
}
public:
T & first() const
{
iterator i = begin();
return (*i);
}
void pop()
{
iterator iter = begin();
erase(iter);
}
};
#endif //_INCLUDE_SM_QUEUE_H