mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
Fixed bug at18919
This commit is contained in:
parent
164a47bde4
commit
a816767abb
@ -66,7 +66,7 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
String(String &src)
|
String(const String &src)
|
||||||
{
|
{
|
||||||
v = NULL;
|
v = NULL;
|
||||||
a_size = 0;
|
a_size = 0;
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#define _INCLUDE_JOURNAL_H
|
#define _INCLUDE_JOURNAL_H
|
||||||
|
|
||||||
#include "Binary.h"
|
#include "Binary.h"
|
||||||
#include "NHash.h"
|
#include "sh_list.h"
|
||||||
|
#include "sh_tinyhash.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
|
||||||
enum JOp
|
enum JOp
|
||||||
@ -21,7 +22,7 @@ enum Encode
|
|||||||
Encode_Medium,
|
Encode_Medium,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NHash<String,String> VaultMap;
|
typedef THash<String,String> VaultMap;
|
||||||
|
|
||||||
class Journal
|
class Journal
|
||||||
{
|
{
|
||||||
|
@ -1,320 +0,0 @@
|
|||||||
#ifndef _INCLUDE_NHASH_H
|
|
||||||
#define _INCLUDE_NHASH_H
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a primitive, typical hash class.
|
|
||||||
* Design goals were: modular, easy to use, compact
|
|
||||||
* The table size is fixed by a constant, 2K gives about ~8-16K in immediate memory usage.
|
|
||||||
* Each entry in the table uses about 20-28 bytes, depending on the data being stored.
|
|
||||||
* In theory we could optimize this further by storing a linked list of the hash items.
|
|
||||||
* (this would sacrifice ~8 bytes per node!)
|
|
||||||
* --- by David "BAILOPAN" Anderson
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TABLE_SIZE 2048
|
|
||||||
|
|
||||||
template <class K>
|
|
||||||
int HashFunction(const K & k);
|
|
||||||
|
|
||||||
template <class K>
|
|
||||||
bool Compare(const K & k1, const K & k2);
|
|
||||||
|
|
||||||
template <class K, class V>
|
|
||||||
class NHash
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
struct hashnode
|
|
||||||
{
|
|
||||||
K key;
|
|
||||||
V val;
|
|
||||||
time_t stamp;
|
|
||||||
hashnode *next;
|
|
||||||
hashnode *prev;
|
|
||||||
};
|
|
||||||
struct bucket
|
|
||||||
{
|
|
||||||
hashnode *head;
|
|
||||||
hashnode *tail;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
NHash()
|
|
||||||
{
|
|
||||||
memset(&m_Buckets, 0, sizeof(m_Buckets));
|
|
||||||
m_Size = 0;
|
|
||||||
}
|
|
||||||
~NHash()
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
hashnode *n, *t;
|
|
||||||
for (size_t i=0; i<TABLE_SIZE; i++)
|
|
||||||
{
|
|
||||||
n = m_Buckets[i].head;
|
|
||||||
while (n)
|
|
||||||
{
|
|
||||||
t = n->next;
|
|
||||||
delete n;
|
|
||||||
n = t;
|
|
||||||
}
|
|
||||||
m_Buckets[i].head = NULL;
|
|
||||||
m_Buckets[i].tail = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Insert(const K & key, const V & val)
|
|
||||||
{
|
|
||||||
Insert(key, val, time(NULL));
|
|
||||||
}
|
|
||||||
void Insert(const K & key, const V & val, time_t stamp)
|
|
||||||
{
|
|
||||||
bucket *b;
|
|
||||||
hashnode *n;
|
|
||||||
if (!_Find(key, &b, &n))
|
|
||||||
{
|
|
||||||
n = new hashnode;
|
|
||||||
n->key = key;
|
|
||||||
_Insert(b, n);
|
|
||||||
}
|
|
||||||
n->val = val;
|
|
||||||
n->stamp = stamp;
|
|
||||||
}
|
|
||||||
bool Exists(const K & k)
|
|
||||||
{
|
|
||||||
uint16_t h = HashFunction(k);
|
|
||||||
if (h >= TABLE_SIZE)
|
|
||||||
h = h % TABLE_SIZE;
|
|
||||||
bucket *b = &(m_Buckets[h]);
|
|
||||||
hashnode *n = b->head;
|
|
||||||
while (n)
|
|
||||||
{
|
|
||||||
if (Compare(n->key,k))
|
|
||||||
return true;
|
|
||||||
n = n->next;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
V & Retrieve(const K & k, time_t & stamp)
|
|
||||||
{
|
|
||||||
hashnode *n;
|
|
||||||
bucket *b;
|
|
||||||
if (!_Find(k, &b, &n))
|
|
||||||
{
|
|
||||||
n = new hashnode;
|
|
||||||
n->key = k;
|
|
||||||
n->stamp = time(NULL);
|
|
||||||
_Insert(b, n);
|
|
||||||
}
|
|
||||||
stamp = n->stamp;
|
|
||||||
return n->val;
|
|
||||||
}
|
|
||||||
V & Retrieve(const K & k)
|
|
||||||
{
|
|
||||||
time_t stamp;
|
|
||||||
return Retrieve(k, stamp);
|
|
||||||
}
|
|
||||||
size_t Size()
|
|
||||||
{
|
|
||||||
return m_Size;
|
|
||||||
}
|
|
||||||
void Remove(const K & key)
|
|
||||||
{
|
|
||||||
bucket *b;
|
|
||||||
hashnode *n;
|
|
||||||
if (_Find(key, &b, &n))
|
|
||||||
{
|
|
||||||
_Remove(b, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t Prune(time_t start=0, time_t end=0)
|
|
||||||
{
|
|
||||||
size_t num = m_Size;
|
|
||||||
hashnode *n, *t;
|
|
||||||
bucket *b;
|
|
||||||
for (size_t i=0; i<TABLE_SIZE; i++)
|
|
||||||
{
|
|
||||||
b = &(m_Buckets[i]);
|
|
||||||
n = b->head;
|
|
||||||
while (n)
|
|
||||||
{
|
|
||||||
t = n->next;
|
|
||||||
if (n->stamp != 0)
|
|
||||||
{
|
|
||||||
if (start == 0 && end == 0)
|
|
||||||
_Remove(b, n);
|
|
||||||
else if (start == 0 && n->stamp < end)
|
|
||||||
_Remove(b, n);
|
|
||||||
else if (end == 0 && n->stamp > start)
|
|
||||||
_Remove(b, n);
|
|
||||||
else if (n->stamp > start && n->stamp < end)
|
|
||||||
_Remove(b, n);
|
|
||||||
}
|
|
||||||
n = t;
|
|
||||||
}
|
|
||||||
if (!m_Size)
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
return (num - m_Size);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
bucket m_Buckets[TABLE_SIZE];
|
|
||||||
size_t m_Size;
|
|
||||||
public:
|
|
||||||
friend class iterator;
|
|
||||||
class iterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
iterator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
iterator(NHash *hash) : m_Hash(hash),
|
|
||||||
m_CurPos(0),
|
|
||||||
m_CurNode(0)
|
|
||||||
{
|
|
||||||
Next();
|
|
||||||
}
|
|
||||||
void Next()
|
|
||||||
{
|
|
||||||
if (!m_CurNode || !m_CurNode->next)
|
|
||||||
{
|
|
||||||
bucket *b;
|
|
||||||
int i;
|
|
||||||
for (i=m_CurPos+1; i<TABLE_SIZE; i++)
|
|
||||||
{
|
|
||||||
b = &(m_Hash->m_Buckets[i]);
|
|
||||||
if (b->head)
|
|
||||||
{
|
|
||||||
m_CurNode = b->head;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//m_LastPos = m_CurPos;
|
|
||||||
m_CurPos = i;
|
|
||||||
} else {
|
|
||||||
m_CurNode = m_CurNode->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool Done()
|
|
||||||
{
|
|
||||||
if (!m_CurNode)
|
|
||||||
return true;
|
|
||||||
if (!m_CurNode->next && m_CurPos >= TABLE_SIZE)
|
|
||||||
return true;
|
|
||||||
if (!m_CurNode->next)
|
|
||||||
{
|
|
||||||
bucket *b;
|
|
||||||
for (int i=m_CurPos+1; i<TABLE_SIZE; i++)
|
|
||||||
{
|
|
||||||
b = &(m_Hash->m_Buckets[i]);
|
|
||||||
if (b->head)
|
|
||||||
{
|
|
||||||
//trick next into moving to this one quickly :)
|
|
||||||
m_CurPos = i - 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
K & GetKey()
|
|
||||||
{
|
|
||||||
return m_CurNode->key;
|
|
||||||
}
|
|
||||||
V & GetVal()
|
|
||||||
{
|
|
||||||
return m_CurNode->val;
|
|
||||||
}
|
|
||||||
time_t GetStamp()
|
|
||||||
{
|
|
||||||
return m_CurNode->stamp;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
NHash *m_Hash;
|
|
||||||
int m_CurPos;
|
|
||||||
//int m_LastPos;
|
|
||||||
hashnode *m_CurNode;
|
|
||||||
//hashnode *m_LastNode;
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
iterator GetIter()
|
|
||||||
{
|
|
||||||
return iterator(this);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
bool _Find(const K & k, bucket **b, hashnode **n)
|
|
||||||
{
|
|
||||||
uint16_t h = HashFunction(k);
|
|
||||||
if (h >= TABLE_SIZE)
|
|
||||||
h = h % TABLE_SIZE;
|
|
||||||
bucket *bb = &(m_Buckets[h]);
|
|
||||||
if (b)
|
|
||||||
*b = bb;
|
|
||||||
hashnode *nn = bb->head;
|
|
||||||
while (nn)
|
|
||||||
{
|
|
||||||
if (Compare(nn->key,k))
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
*n = nn;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
nn = nn->next;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void _Insert(hashnode *n)
|
|
||||||
{
|
|
||||||
uint16_t h = HashFunction(n->key);
|
|
||||||
if (h >= TABLE_SIZE)
|
|
||||||
h = h % TABLE_SIZE;
|
|
||||||
bucket *b = &(m_Buckets[h]);
|
|
||||||
_Insert(b, n);
|
|
||||||
}
|
|
||||||
//Lowest call for insertion
|
|
||||||
void _Insert(bucket *b, hashnode *n)
|
|
||||||
{
|
|
||||||
n->next = NULL;
|
|
||||||
if (b->head == NULL)
|
|
||||||
{
|
|
||||||
b->head = n;
|
|
||||||
b->tail = n;
|
|
||||||
n->prev = NULL;
|
|
||||||
} else {
|
|
||||||
b->tail->next = n;
|
|
||||||
n->prev = b->tail;
|
|
||||||
b->tail = n;
|
|
||||||
}
|
|
||||||
m_Size++;
|
|
||||||
}
|
|
||||||
//Lowest call for deletion, returns next node if any
|
|
||||||
hashnode *_Remove(bucket *b, hashnode *n)
|
|
||||||
{
|
|
||||||
hashnode *n2 = n->next;
|
|
||||||
if (b->head == n && b->tail == n)
|
|
||||||
{
|
|
||||||
b->head = NULL;
|
|
||||||
b->tail = NULL;
|
|
||||||
} else if (b->head == n) {
|
|
||||||
n->next->prev = NULL;
|
|
||||||
b->head = n->next;
|
|
||||||
if (b->head->next == NULL)
|
|
||||||
b->tail = b->head;
|
|
||||||
} else if (b->tail == n) {
|
|
||||||
n->prev->next = NULL;
|
|
||||||
b->tail = n->prev;
|
|
||||||
if (b->tail->prev == NULL)
|
|
||||||
b->head = b->tail;
|
|
||||||
} else {
|
|
||||||
n->prev->next = n->next;
|
|
||||||
n->next->prev = n->prev;
|
|
||||||
}
|
|
||||||
delete n;
|
|
||||||
m_Size--;
|
|
||||||
return n2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //_INCLUDE_NHASH_H
|
|
@ -18,9 +18,9 @@ int HashFunction<String>(const String & k)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool Compare<String>(const String & k1, const String & k2)
|
int Compare<String>(const String & k1, const String & k2)
|
||||||
{
|
{
|
||||||
return (strcmp(k1.c_str(),k2.c_str())==0);
|
return strcmp(k1.c_str(),k2.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
NVault::NVault(const char *file)
|
NVault::NVault(const char *file)
|
||||||
@ -137,18 +137,18 @@ bool NVault::_SaveToFile()
|
|||||||
String key;
|
String key;
|
||||||
String val;
|
String val;
|
||||||
|
|
||||||
NHash<String,String>::iterator iter = m_Hash.GetIter();
|
THash<String,String>::iterator iter = m_Hash.begin();
|
||||||
while (!iter.Done())
|
while (iter != m_Hash.end())
|
||||||
{
|
{
|
||||||
key = iter.GetKey();
|
key = (*iter).key;
|
||||||
val = iter.GetVal();
|
val = (*iter).val;
|
||||||
stamp = iter.GetStamp();
|
stamp = (*iter).stamp;
|
||||||
bw.WriteInt32(stamp);
|
bw.WriteInt32(stamp);
|
||||||
bw.WriteUInt8( key.size() );
|
bw.WriteUInt8( key.size() );
|
||||||
bw.WriteUInt16( val.size() );
|
bw.WriteUInt16( val.size() );
|
||||||
bw.WriteChars( key.c_str(), key.size() );
|
bw.WriteChars( key.c_str(), key.size() );
|
||||||
bw.WriteChars( val.c_str(), val.size() );
|
bw.WriteChars( val.c_str(), val.size() );
|
||||||
iter.Next();
|
iter++;
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef _INCLUDE_NVAULT_H
|
#ifndef _INCLUDE_NVAULT_H
|
||||||
#define _INCLUDE_NVAULT_H
|
#define _INCLUDE_NVAULT_H
|
||||||
|
|
||||||
|
#include "sh_list.h"
|
||||||
|
#include "sh_tinyhash.h"
|
||||||
#include "IVault.h"
|
#include "IVault.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#include "Journal.h"
|
#include "Journal.h"
|
||||||
@ -51,7 +53,7 @@ private:
|
|||||||
bool _SaveToFile();
|
bool _SaveToFile();
|
||||||
private:
|
private:
|
||||||
String m_File;
|
String m_File;
|
||||||
NHash<String, String> m_Hash;
|
THash<String, String> m_Hash;
|
||||||
Journal *m_Journal;
|
Journal *m_Journal;
|
||||||
bool m_Open;
|
bool m_Open;
|
||||||
};
|
};
|
||||||
|
@ -29,11 +29,11 @@ static cell nvault_open(AMX *amx, cell *params)
|
|||||||
sprintf(file, "%s/%s.vault", path, name);
|
sprintf(file, "%s/%s.vault", path, name);
|
||||||
for (size_t i=0; i<g_Vaults.size(); i++)
|
for (size_t i=0; i<g_Vaults.size(); i++)
|
||||||
{
|
{
|
||||||
|
if (!g_Vaults[i])
|
||||||
|
continue;
|
||||||
if (strcmp(g_Vaults.at(i)->GetFilename(), file) == 0)
|
if (strcmp(g_Vaults.at(i)->GetFilename(), file) == 0)
|
||||||
{
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
NVault *v = new NVault(file);
|
NVault *v = new NVault(file);
|
||||||
if (!v->Open())
|
if (!v->Open())
|
||||||
{
|
{
|
||||||
|
@ -162,10 +162,13 @@
|
|||||||
RelativePath=".\Journal.h">
|
RelativePath=".\Journal.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\NHash.h">
|
RelativePath=".\NVault.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\NVault.h">
|
RelativePath=".\sh_list.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\sh_tinyhash.h">
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
@ -186,10 +189,10 @@
|
|||||||
RelativePath=".\CString.h">
|
RelativePath=".\CString.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\sdk\moduleconfig.h">
|
RelativePath=".\moduleconfig.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\moduleconfig.h">
|
RelativePath=".\sdk\moduleconfig.h">
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
|
250
dlls/nvault/sh_list.h
Executable file
250
dlls/nvault/sh_list.h
Executable file
@ -0,0 +1,250 @@
|
|||||||
|
/* ======== 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
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
//namespace SourceHook
|
||||||
|
//{
|
||||||
|
//This class is from CSDM for AMX Mod X
|
||||||
|
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:
|
||||||
|
ListNode *_Initialize()
|
||||||
|
{
|
||||||
|
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
|
||||||
|
n->next = NULL;
|
||||||
|
n->prev = NULL;
|
||||||
|
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();
|
||||||
|
if (m_Head)
|
||||||
|
{
|
||||||
|
free(m_Head);
|
||||||
|
m_Head = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void push_back(const T &obj)
|
||||||
|
{
|
||||||
|
ListNode *node = new ListNode(obj);
|
||||||
|
|
||||||
|
if (!m_Head->prev)
|
||||||
|
{
|
||||||
|
//link in the node as the first item
|
||||||
|
node->next = m_Head;
|
||||||
|
node->prev = m_Head;
|
||||||
|
m_Head->prev = node;
|
||||||
|
m_Head->next = node;
|
||||||
|
} else {
|
||||||
|
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 = NULL;
|
||||||
|
m_Head->prev = NULL;
|
||||||
|
while (node && node != m_Head)
|
||||||
|
{
|
||||||
|
temp = node->next;
|
||||||
|
delete node;
|
||||||
|
node = temp;
|
||||||
|
}
|
||||||
|
m_Size = 0;
|
||||||
|
}
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
return (m_Head->next == NULL);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
iterator & operator--()
|
||||||
|
{
|
||||||
|
if (m_This)
|
||||||
|
m_This = m_This->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
T & operator * () const
|
||||||
|
{
|
||||||
|
return m_This->obj;
|
||||||
|
}
|
||||||
|
T & operator * ()
|
||||||
|
{
|
||||||
|
return m_This->obj;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (m_Size)
|
||||||
|
return iterator(m_Head->next);
|
||||||
|
else
|
||||||
|
return iterator(m_Head);
|
||||||
|
}
|
||||||
|
iterator end() const
|
||||||
|
{
|
||||||
|
return iterator(m_Head);
|
||||||
|
}
|
||||||
|
iterator erase(iterator &where)
|
||||||
|
{
|
||||||
|
ListNode *pNode = where.m_This;
|
||||||
|
iterator iter(where);
|
||||||
|
iter++;
|
||||||
|
|
||||||
|
//If we are both the head and tail...
|
||||||
|
if (m_Head->next == pNode && m_Head->prev == pNode)
|
||||||
|
{
|
||||||
|
m_Head->next = NULL;
|
||||||
|
m_Head->prev = NULL;
|
||||||
|
} else if (m_Head->next == pNode) {
|
||||||
|
//we are only the first
|
||||||
|
pNode->next->prev = m_Head;
|
||||||
|
m_Head->next = pNode->next;
|
||||||
|
} else if (m_Head->prev == pNode) {
|
||||||
|
//we are the tail
|
||||||
|
pNode->prev->next = m_Head;
|
||||||
|
m_Head->prev = pNode->prev;
|
||||||
|
} else {
|
||||||
|
//middle unlink
|
||||||
|
pNode->prev->next = pNode->next;
|
||||||
|
pNode->next->prev = pNode->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete 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)
|
||||||
|
{
|
||||||
|
iterator iter;
|
||||||
|
for (iter=begin(); iter!=end(); iter++)
|
||||||
|
{
|
||||||
|
if ( (*iter) == equ )
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
List & operator =(List &src)
|
||||||
|
{
|
||||||
|
iterator iter;
|
||||||
|
for (iter=src.begin(); iter!=src.end(); iter++)
|
||||||
|
push_back( (*iter) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//}; //NAMESPACE
|
||||||
|
|
||||||
|
#endif //_INCLUDE_CSDM_LIST_H
|
407
dlls/nvault/sh_tinyhash.h
Executable file
407
dlls/nvault/sh_tinyhash.h
Executable file
@ -0,0 +1,407 @@
|
|||||||
|
/* ======== SourceMM ========
|
||||||
|
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||||
|
* No warranties of any kind
|
||||||
|
*
|
||||||
|
* License: zlib/libpng
|
||||||
|
*
|
||||||
|
* Author(s): David "BAILOPAN" Anderson
|
||||||
|
* ============================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SH_TINYHASH_H_
|
||||||
|
#define _INCLUDE_SH_TINYHASH_H_
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include "sh_list.h"
|
||||||
|
|
||||||
|
#define _T_INIT_HASH_SIZE 32
|
||||||
|
|
||||||
|
//namespace SourceHook
|
||||||
|
//{
|
||||||
|
template <class K>
|
||||||
|
int HashFunction(const K & k);
|
||||||
|
|
||||||
|
template <class K>
|
||||||
|
int Compare(const K & k1, const K & k2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a tiny, growable hash class.
|
||||||
|
* Meant for quick and dirty dictionaries only!
|
||||||
|
*/
|
||||||
|
template <class K, class V>
|
||||||
|
class THash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct THashNode
|
||||||
|
{
|
||||||
|
THashNode(const K & k, const V & v) :
|
||||||
|
key(k), val(v)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
K key;
|
||||||
|
V val;
|
||||||
|
time_t stamp;
|
||||||
|
};
|
||||||
|
typedef List<THashNode *> * NodePtr;
|
||||||
|
public:
|
||||||
|
THash() : m_numBuckets(0), m_Buckets(NULL), m_Items(0)
|
||||||
|
{
|
||||||
|
_Refactor();
|
||||||
|
}
|
||||||
|
~THash()
|
||||||
|
{
|
||||||
|
_Clear();
|
||||||
|
}
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
_Clear();
|
||||||
|
_Refactor();
|
||||||
|
}
|
||||||
|
void Insert(const K & key, const V & val)
|
||||||
|
{
|
||||||
|
Insert(key, val, time(NULL));
|
||||||
|
}
|
||||||
|
void Insert(const K & key, const V & val, time_t stamp)
|
||||||
|
{
|
||||||
|
THashNode *pNode = _FindOrInsert(key);
|
||||||
|
pNode->val = val;
|
||||||
|
pNode->stamp = stamp;
|
||||||
|
}
|
||||||
|
bool Exists(const K & key)
|
||||||
|
{
|
||||||
|
size_t place = HashFunction(key) % m_numBuckets;
|
||||||
|
|
||||||
|
if (!m_Buckets[place])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
for (iter = m_Buckets[place]->begin(); iter != m_Buckets[place]->end(); iter++)
|
||||||
|
{
|
||||||
|
if (Compare(key, (*iter)->key) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
V & Retrieve(const K & k, time_t & stamp)
|
||||||
|
{
|
||||||
|
THashNode *pNode = _FindOrInsert(k);
|
||||||
|
stamp = pNode->stamp;
|
||||||
|
return pNode->val;
|
||||||
|
}
|
||||||
|
V & Retrieve(const K & k)
|
||||||
|
{
|
||||||
|
time_t stamp;
|
||||||
|
return Retrieve(k, stamp);
|
||||||
|
}
|
||||||
|
void Remove(const K & key)
|
||||||
|
{
|
||||||
|
size_t place = HashFunction(key) % m_numBuckets;
|
||||||
|
|
||||||
|
if (!m_Buckets[place])
|
||||||
|
return;
|
||||||
|
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
for (iter = m_Buckets[place]->begin(); iter != m_Buckets[place]->end(); iter++)
|
||||||
|
{
|
||||||
|
if (Compare(key, (*iter)->key) == 0)
|
||||||
|
{
|
||||||
|
iter = m_Buckets[place]->erase(iter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t Prune(time_t start=0, time_t end=0)
|
||||||
|
{
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
time_t stamp;
|
||||||
|
size_t removed = 0;
|
||||||
|
for (size_t i=0; i<m_numBuckets; i++)
|
||||||
|
{
|
||||||
|
iter = m_Buckets[i]->begin();
|
||||||
|
bool remove;
|
||||||
|
while (iter != m_Buckets[i]->end())
|
||||||
|
{
|
||||||
|
stamp = (*iter)->stamp;
|
||||||
|
remove = false;
|
||||||
|
if (stamp != 0)
|
||||||
|
{
|
||||||
|
if (start == 0 && end == 0)
|
||||||
|
remove = true;
|
||||||
|
else if (start == 0 && stamp < end)
|
||||||
|
remove = true;
|
||||||
|
else if (end == 0 && stamp > start)
|
||||||
|
remove = true;
|
||||||
|
else if (stamp > start && stamp < end)
|
||||||
|
remove = true;
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
iter = m_Buckets[i]->erase(iter);
|
||||||
|
removed++;
|
||||||
|
} else {
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
size_t Size()
|
||||||
|
{
|
||||||
|
return m_Items;
|
||||||
|
}
|
||||||
|
size_t GetBuckets()
|
||||||
|
{
|
||||||
|
return m_numBuckets;
|
||||||
|
}
|
||||||
|
float PercentUsed()
|
||||||
|
{
|
||||||
|
return m_percentUsed;
|
||||||
|
}
|
||||||
|
V & operator [](const K & key)
|
||||||
|
{
|
||||||
|
THashNode *pNode = _FindOrInsert(key);
|
||||||
|
return pNode->val;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void _Clear()
|
||||||
|
{
|
||||||
|
for (size_t i=0; i<m_numBuckets; i++)
|
||||||
|
{
|
||||||
|
if (m_Buckets[i])
|
||||||
|
{
|
||||||
|
m_Buckets[i]->clear();
|
||||||
|
delete m_Buckets[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete [] m_Buckets;
|
||||||
|
m_numBuckets = 0;
|
||||||
|
m_Items = 0;
|
||||||
|
m_Buckets = NULL;
|
||||||
|
}
|
||||||
|
THashNode *_FindOrInsert(const K & key)
|
||||||
|
{
|
||||||
|
size_t place = HashFunction(key) % m_numBuckets;
|
||||||
|
THashNode *pNode = NULL;
|
||||||
|
if (!m_Buckets[place])
|
||||||
|
{
|
||||||
|
m_Buckets[place] = new List<THashNode *>;
|
||||||
|
pNode = new THashNode(key, V());
|
||||||
|
m_Buckets[place]->push_back(pNode);
|
||||||
|
m_percentUsed += (1.0f / (float)m_numBuckets);
|
||||||
|
} else {
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
|
||||||
|
{
|
||||||
|
if (Compare((*iter)->key, key) == 0)
|
||||||
|
return (*iter);
|
||||||
|
}
|
||||||
|
//node does not exist
|
||||||
|
pNode = new THashNode(key, V());
|
||||||
|
m_Buckets[place]->push_back(pNode);
|
||||||
|
}
|
||||||
|
if (PercentUsed() > 0.75f)
|
||||||
|
_Refactor();
|
||||||
|
m_Items++;
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
void _Refactor()
|
||||||
|
{
|
||||||
|
m_percentUsed = 0.0f;
|
||||||
|
if (!m_numBuckets)
|
||||||
|
{
|
||||||
|
m_numBuckets = _T_INIT_HASH_SIZE;
|
||||||
|
m_Buckets = new NodePtr[m_numBuckets];
|
||||||
|
for (size_t i=0; i<m_numBuckets; i++)
|
||||||
|
m_Buckets[i] = NULL;
|
||||||
|
} else {
|
||||||
|
size_t oldSize = m_numBuckets;
|
||||||
|
m_numBuckets *= 2;
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
size_t place;
|
||||||
|
THashNode *pHashNode;
|
||||||
|
NodePtr *temp = new NodePtr[m_numBuckets];
|
||||||
|
for (size_t i=0; i<m_numBuckets; i++)
|
||||||
|
temp[i] = NULL;
|
||||||
|
//look in old hash table
|
||||||
|
for (size_t i=0; i<oldSize; i++)
|
||||||
|
{
|
||||||
|
//does a bucket have anything?
|
||||||
|
if (m_Buckets[i])
|
||||||
|
{
|
||||||
|
//go through the list of items
|
||||||
|
for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++)
|
||||||
|
{
|
||||||
|
pHashNode = (*iter);
|
||||||
|
//rehash it with the new bucket filter
|
||||||
|
place = HashFunction(pHashNode->key) % m_numBuckets;
|
||||||
|
//add it to the new hash table
|
||||||
|
if (!temp[place])
|
||||||
|
{
|
||||||
|
temp[place] = new List<THashNode *>;
|
||||||
|
m_percentUsed += (1.0f / (float)m_numBuckets);
|
||||||
|
}
|
||||||
|
temp[place]->push_back(pHashNode);
|
||||||
|
}
|
||||||
|
//delete that bucket!
|
||||||
|
delete m_Buckets[i];
|
||||||
|
m_Buckets[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//reassign bucket table
|
||||||
|
delete [] m_Buckets;
|
||||||
|
m_Buckets = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
friend class iterator;
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class THash;
|
||||||
|
public:
|
||||||
|
iterator() : hash(NULL), end(true)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
iterator(THash *h) : hash(h), end(false)
|
||||||
|
{
|
||||||
|
if (!h->m_Buckets)
|
||||||
|
end = true;
|
||||||
|
else
|
||||||
|
_Inc();
|
||||||
|
};
|
||||||
|
//pre increment
|
||||||
|
iterator & operator++()
|
||||||
|
{
|
||||||
|
_Inc();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
//post increment
|
||||||
|
iterator operator++(int)
|
||||||
|
{
|
||||||
|
iterator old(*this);
|
||||||
|
_Inc();
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
THashNode & operator * () const
|
||||||
|
{
|
||||||
|
return *(*iter);
|
||||||
|
}
|
||||||
|
THashNode & operator * ()
|
||||||
|
{
|
||||||
|
return *(*iter);
|
||||||
|
}
|
||||||
|
THashNode * operator ->() const
|
||||||
|
{
|
||||||
|
return (*iter);
|
||||||
|
}
|
||||||
|
THashNode * operator ->()
|
||||||
|
{
|
||||||
|
return (*iter);
|
||||||
|
}
|
||||||
|
bool operator ==(const iterator &where) const
|
||||||
|
{
|
||||||
|
if (where.hash == this->hash
|
||||||
|
&& where.end == this->end
|
||||||
|
&&
|
||||||
|
(this->end ||
|
||||||
|
((where.curbucket == this->curbucket)
|
||||||
|
&& (where.iter == iter))
|
||||||
|
))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool operator !=(const iterator &where) const
|
||||||
|
{
|
||||||
|
return !( (*this) == where );
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void _Inc()
|
||||||
|
{
|
||||||
|
if (end || !hash || curbucket >= (int)hash->m_numBuckets)
|
||||||
|
return;
|
||||||
|
if (curbucket < 0)
|
||||||
|
{
|
||||||
|
for (int i=0; i<(int)hash->m_numBuckets; i++)
|
||||||
|
{
|
||||||
|
if (hash->m_Buckets[i])
|
||||||
|
{
|
||||||
|
iter = hash->m_Buckets[i]->begin();
|
||||||
|
if (iter == hash->m_Buckets[i]->end())
|
||||||
|
continue;
|
||||||
|
curbucket = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curbucket < 0)
|
||||||
|
end = true;
|
||||||
|
} else {
|
||||||
|
if (iter != hash->m_Buckets[curbucket]->end())
|
||||||
|
iter++;
|
||||||
|
if (iter == hash->m_Buckets[curbucket]->end())
|
||||||
|
{
|
||||||
|
int oldbucket = curbucket;
|
||||||
|
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
|
||||||
|
{
|
||||||
|
if (hash->m_Buckets[i])
|
||||||
|
{
|
||||||
|
iter = hash->m_Buckets[i]->begin();
|
||||||
|
if (iter == hash->m_Buckets[i]->end())
|
||||||
|
continue;
|
||||||
|
curbucket = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curbucket == oldbucket)
|
||||||
|
end = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int curbucket;
|
||||||
|
typename List<THashNode *>::iterator iter;
|
||||||
|
THash *hash;
|
||||||
|
bool end;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
iterator begin()
|
||||||
|
{
|
||||||
|
return iterator(this);
|
||||||
|
}
|
||||||
|
iterator end()
|
||||||
|
{
|
||||||
|
iterator iter;
|
||||||
|
iter.hash = this;
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
iterator find(const U & u) const
|
||||||
|
{
|
||||||
|
iterator b = begin();
|
||||||
|
iterator e = end();
|
||||||
|
for (iterator iter = b; iter != e; iter++)
|
||||||
|
{
|
||||||
|
if ( (*iter).key == u )
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
iterator find(const U & u)
|
||||||
|
{
|
||||||
|
iterator b = begin();
|
||||||
|
iterator e = end();
|
||||||
|
for (iterator iter = b; iter != e; iter++)
|
||||||
|
{
|
||||||
|
if ( (*iter).key == u )
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
NodePtr *m_Buckets;
|
||||||
|
size_t m_numBuckets;
|
||||||
|
float m_percentUsed;
|
||||||
|
size_t m_Items;
|
||||||
|
};
|
||||||
|
//};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SH_TINYHASH_H_
|
Loading…
Reference in New Issue
Block a user