Initial import of new version :]

This commit is contained in:
David Anderson 2005-07-31 06:07:48 +00:00
parent dd6c169994
commit b27eaab57f
15 changed files with 1577 additions and 76 deletions

143
dlls/nvault/Binary.cpp Executable file
View File

@ -0,0 +1,143 @@
#include "Binary.h"
BinaryWriter::BinaryWriter(FILE *fp)
{
m_Fp = fp;
}
bool BinaryWriter::WriteAddr(void *buffer, size_t size)
{
if (fwrite(buffer, size, 1, m_Fp) != 1)
return false;
return true;
}
void BinaryWriter::WriteUInt32(uint32_t num)
{
if ( !WriteAddr(&num, sizeof(uint32_t)) )
throw -1;
}
void BinaryWriter::WriteInt32(int32_t num)
{
if ( !WriteAddr(&num, sizeof(int32_t)) )
throw -1;
}
void BinaryWriter::WriteUInt16(uint16_t num)
{
if ( !WriteAddr(&num, sizeof(uint16_t)) )
throw -1;
}
void BinaryWriter::WriteInt16(int16_t num)
{
if ( !WriteAddr(&num, sizeof(int16_t)) )
throw -1;
}
void BinaryWriter::WriteUInt8(uint8_t num)
{
if ( !WriteAddr(&num, sizeof(uint8_t)) )
throw -1;
}
void BinaryWriter::WriteInt8(int8_t num)
{
if ( !WriteAddr(&num, sizeof(int8_t)) )
throw -1;
}
void BinaryWriter::WriteChars(const char buffer[], size_t chars)
{
if (!chars)
return;
if (fwrite(buffer, sizeof(char), chars, m_Fp) != chars)
throw -1;
}
BinaryReader::BinaryReader(FILE *fp)
{
m_Fp = fp;
}
bool BinaryReader::ReadAddr(void *buffer, size_t size)
{
if (fread(buffer, size, 1, m_Fp) != 1)
return false;
return true;
}
uint32_t BinaryReader::ReadUInt32()
{
uint32_t num;
if ( !ReadAddr(&num, sizeof(uint32_t)) )
throw -1;
return num;
}
int32_t BinaryReader::ReadInt32()
{
int32_t num;
if ( !ReadAddr(&num, sizeof(int32_t)) )
throw -1;
return num;
}
uint16_t BinaryReader::ReadUInt16()
{
uint16_t num;
if ( !ReadAddr(&num, sizeof(uint16_t)) )
throw -1;
return num;
}
int16_t BinaryReader::ReadInt16()
{
int16_t num;
if ( !ReadAddr(&num, sizeof(int16_t)) )
throw -1;
return num;
}
uint8_t BinaryReader::ReadUInt8()
{
uint8_t num;
if ( !ReadAddr(&num, sizeof(uint8_t)) )
throw -1;
return num;
}
int8_t BinaryReader::ReadInt8()
{
int8_t num;
if ( !ReadAddr(&num, sizeof(int8_t)) )
throw -1;
return num;
}
char *BinaryReader::ReadChars(char buffer[], size_t chars)
{
if (!chars)
return buffer;
if (fread(buffer, sizeof(char), chars, m_Fp) != chars)
throw -1;
return buffer;
}

46
dlls/nvault/Binary.h Executable file
View File

@ -0,0 +1,46 @@
#ifndef _INCLUDE_BINARY_H
#define _INCLUDE_BINARY_H
#include <stdio.h>
#include "compat.h"
class BinaryReader
{
public:
BinaryReader(FILE *fp);
//~BinaryReader();
public:
uint32_t ReadUInt32();
int32_t ReadInt32();
uint16_t ReadUInt16();
int16_t ReadInt16();
uint8_t ReadUInt8();
int8_t ReadInt8();
char *ReadChars(char buffer[], size_t chars);
private:
bool ReadAddr(void *buffer, size_t size);
private:
FILE *m_Fp;
};
class BinaryWriter
{
public:
BinaryWriter() { m_Fp = NULL; }
BinaryWriter(FILE *fp);
public:
void SetFilePtr(FILE *fp) { m_Fp = fp; }
void WriteUInt32(uint32_t num);
void WriteInt32(int32_t num);
void WriteUInt16(uint16_t num);
void WriteInt16(int16_t num);
void WriteUInt8(uint8_t num);
void WriteInt8(int8_t num);
void WriteChars(const char buffer[], size_t chars);
private:
bool WriteAddr(void *buffer, size_t size);
private:
FILE *m_Fp;
};
#endif //_INCLUDE_BINARY_H

374
dlls/nvault/CString.h Executable file
View File

@ -0,0 +1,374 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef _INCLUDE_CSTRING_H
#define _INCLUDE_CSTRING_H
#include <string.h>
//by David "BAILOPAN" Anderson
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(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 false;
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)
{
size_t len = size();
if (len < 1)
return npos;
if (index >= (int)len || index < 0)
return npos;
unsigned int i = 0;
for (i=index; i<(int)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>=0; 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-num+1)
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)
return String("");
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, j=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;
v = n;
a_size = d + 1;
}
char *v;
unsigned int a_size;
public:
static const int npos = -1;
};
#endif //_INCLUDE_CSTRING_H

28
dlls/nvault/IVault.h Executable file
View File

@ -0,0 +1,28 @@
#ifndef _INCLUDE_IVAULT_H
#define _INCLUDE_IVAULT_H
#include <time.h>
class IVault
{
public:
virtual ~IVault() { }
public:
virtual bool GetValue(const char *key, time_t &stamp, char buffer[], size_t len) =0;
virtual void SetValue(const char *key, const char *val) =0;
virtual void SetValue(const char *key, const char *val, time_t stamp) =0;
virtual size_t Prune(time_t start, time_t end) =0;
virtual void Clear() =0;
virtual void Remove(const char *key) =0;
virtual size_t Items() =0;
};
class IVaultMngr
{
public:
virtual IVault *OpenVault(const char *name) =0;
};
typedef IVaultMngr *(*GETVAULTMNGR_FUNC)();
#endif //_INCLUDE_IVAULT_H

178
dlls/nvault/Journal.cpp Executable file
View File

@ -0,0 +1,178 @@
#include <stdio.h>
#include "Journal.h"
Journal::Journal(const char *file)
{
m_File.assign(file);
}
bool Journal::Erase()
{
return (unlink(m_File.c_str()) == 0);
}
int Journal::Replay(VaultMap *pMap)
{
m_fp = fopen(m_File.c_str(), "rb");
if (!m_fp)
return -1;
BinaryReader br(m_fp);
int8_t len8;
int16_t len16;
char *key = NULL;
char *val = NULL;
String sKey;
String sVal;
time_t stamp;
JOp op;
int ops = 0;
try
{
do
{
op = static_cast<JOp>(br.ReadUInt8());
if (op == Journal_Clear)
{
pMap->Clear();
} else if (op == Journal_Prune) {
time_t start;
time_t end;
start = static_cast<time_t>(br.ReadUInt32());
end = static_cast<time_t>(br.ReadUInt32());
pMap->Prune(start, end);
} else if (op == Journal_Insert) {
stamp = static_cast<time_t>(br.ReadUInt32());
len8 = br.ReadUInt8();
key = new char[len8+1];
br.ReadChars(key, len8);
len16 = br.ReadUInt16();
val = new char[len16+1];
br.ReadChars(val, len16);
key[len8] = '\0';
val[len16] = '\0';
sKey.assign(key);
sVal.assign(val);
pMap->Insert(sKey, sVal, stamp);
//clean up
delete [] key;
key = NULL;
delete [] val;
val = NULL;
} else if (op == Journal_Remove) {
len8 = br.ReadUInt8();
key = new char[len8+1];
br.ReadChars(key, len8);
key[len8] = '\0';
sKey.assign(key);
pMap->Remove(sKey);
}
ops++;
} while (op < Journal_TotalOps && op);
} catch (...) {
//journal is done
if (key)
{
delete [] key;
key = NULL;
}
if (val)
{
delete [] val;
val = NULL;
}
}
fclose(m_fp);
return ops;
}
bool Journal::Begin()
{
m_fp = fopen(m_File.c_str(), "wb");
m_Bw.SetFilePtr(m_fp);
return (m_fp != NULL);
}
bool Journal::End()
{
fclose(m_fp);
m_Bw.SetFilePtr(NULL);
return true;
}
bool Journal::Write_Clear()
{
try
{
WriteOp(Journal_Clear);
return true;
} catch (...) {
return false;
}
}
bool Journal::Write_Insert(const char *key, const char *val, time_t stamp)
{
try
{
WriteOp(Journal_Insert);
WriteInt32(static_cast<int32_t>(stamp));
WriteString(key, Encode_Small);
WriteString(val, Encode_Medium);
return true;
} catch (...) {
return false;
}
}
bool Journal::Write_Prune(time_t start, time_t end)
{
try
{
WriteOp(Journal_Prune);
WriteInt32(static_cast<int32_t>(start));
WriteInt32(static_cast<int32_t>(end));
return true;
} catch (...) {
return false;
}
}
bool Journal::Write_Remove(const char *key)
{
try
{
WriteOp(Journal_Remove);
WriteString(key, Encode_Small);
return true;
} catch (...) {
return false;
}
}
void Journal::WriteInt32(int num)
{
m_Bw.WriteInt32(num);
}
void Journal::WriteOp(JOp op)
{
m_Bw.WriteUInt8(static_cast<uint8_t>(op));
}
void Journal::WriteString(const char *str, Encode enc)
{
size_t len = strlen(str);
if (enc == Encode_Small)
{
m_Bw.WriteUInt8(static_cast<uint8_t>(len));
} else if (enc == Encode_Medium) {
m_Bw.WriteUInt16(static_cast<uint16_t>(len));
}
m_Bw.WriteChars(str, len);
}

51
dlls/nvault/Journal.h Executable file
View File

@ -0,0 +1,51 @@
#ifndef _INCLUDE_JOURNAL_H
#define _INCLUDE_JOURNAL_H
#include "Binary.h"
#include "NHash.h"
#include "CString.h"
enum JOp
{
Journal_Nop=0, //no operation
Journal_Clear, //clears, no parameters
Journal_Prune, //prunes, two params (start, end, 32bit both)
Journal_Insert, //inserts stamp (32), key (8+[]), val (16+[])
Journal_Remove, //removes key(8+[])
Journal_TotalOps,
};
enum Encode
{
Encode_Small,
Encode_Medium,
};
typedef NHash<String,String> VaultMap;
class Journal
{
public:
Journal(const char *file);
public:
bool Begin();
bool End();
int Replay(VaultMap *pMap);
bool Erase();
public:
bool Write_Clear();
bool Write_Prune(time_t start, time_t end);
bool Write_Insert(const char *key, const char *val, time_t stamp);
bool Write_Remove(const char *key);
private:
void WriteOp(JOp op);
void WriteInt32(int num);
void WriteString(const char *str, Encode enc);
private:
String m_File;
FILE *m_fp;
BinaryWriter m_Bw;
};
#endif //_INCLUDE_JOURNAL_H

317
dlls/nvault/NHash.h Executable file
View File

@ -0,0 +1,317 @@
#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 (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

262
dlls/nvault/NVault.cpp Executable file
View File

@ -0,0 +1,262 @@
#include "NVault.h"
#include "Binary.h"
template <class K>
int HashFunction<String>(const K & k)
{
unsigned long hash = 5381;
const char *str = k.c_str();
char c;
while (c = *str++) hash = ((hash << 5) + hash) + c; // hash*33 + c
return hash;
}
template <class K>
bool Compare<String>(const K & k1, const K & k2)
{
return (strcmp(k1.c_str(),k2.c_str())==0);
}
NVault::NVault(const char *file)
{
m_File.assign(file);
m_Journal = NULL;
m_Open = false;
}
NVault::~NVault()
{
Close();
}
VaultError NVault::_ReadFromFile()
{
FILE *fp = fopen(m_File.c_str(), "rb");
if (!fp)
return Vault_NoFile;
//this is a little more optimized than the other version in the journal <_<
//I could optimize this more by embedding the position in the hash table but...
// the hash function can be changed. this could be fixed by storing a string and its
// resulting hash, and the entries could be ignored therein, but not right now.
//Also the string class could have embedded binary reading (like it does for text files)
BinaryReader br(fp);
uint8_t oldkeylen=0;
uint16_t oldvallen=0;
uint8_t keylen;
uint16_t vallen;
time_t stamp;
char *key = NULL;
char *val = NULL;
String sKey;
String sVal;
try
{
int32_t magic = br.ReadUInt32();
if (magic != VAULT_MAGIC)
return Vault_BadFile;
int16_t version = br.ReadUInt16();
if (version != VAULT_VERSION)
return Vault_OldFile;
int32_t entries = br.ReadUInt32();
for (int32_t i=0; i<entries; i++)
{
stamp = static_cast<time_t>(br.ReadInt32());
keylen = br.ReadUInt8();
vallen = br.ReadUInt16();
if (keylen > oldkeylen)
{
if (key)
delete [] key;
key = new char[keylen + 1];
oldkeylen = keylen;
}
if (vallen > oldvallen)
{
if (val)
delete [] val;
val = new char[vallen + 1];
oldvallen = vallen;
}
br.ReadChars(key, keylen);
br.ReadChars(val, vallen);
key[keylen] = '\0';
val[vallen] = '\0';
sKey.assign(key);
sVal.assign(val);
m_Hash.Insert(sKey, sVal, stamp);
}
} catch (...) {
if (key)
{
delete [] key;
key = NULL;
}
if (val)
{
delete [] val;
val = NULL;
}
fclose(fp);
return Vault_Read;
}
fclose(fp);
return Vault_Ok;
}
bool NVault::_SaveToFile()
{
FILE *fp = fopen(m_File.c_str(), "wb");
if (!fp)
return false;
BinaryWriter bw(fp);
try
{
int32_t magic = VAULT_MAGIC;
int16_t version = VAULT_VERSION;
bw.WriteUInt32(magic);
bw.WriteUInt16(version);
bw.WriteUInt32( m_Hash.Size() );
time_t stamp;
String key;
String val;
NHash<String,String>::iterator iter = m_Hash.GetIter();
while (!iter.Done())
{
key = iter.GetKey();
val = iter.GetVal();
stamp = iter.GetStamp();
bw.WriteInt32(stamp);
bw.WriteUInt8( key.size() );
bw.WriteUInt16( val.size() );
bw.WriteChars( key.c_str(), key.size() );
bw.WriteChars( val.c_str(), val.size() );
iter.Next();
}
} catch (...) {
fclose(fp);
return false;
}
fclose(fp);
return true;
}
bool NVault::Open()
{
_ReadFromFile();
char *journal_name = new char[m_File.size() + 10];
strcpy(journal_name, m_File.c_str());
char *pos = strstr(journal_name, ".vault");
if (pos)
{
strcpy(pos, ".journal");
} else {
strcat(journal_name, ".journal");
}
m_Journal = new Journal(journal_name);
delete [] journal_name;
m_Journal->Replay(&m_Hash);
m_Journal->Erase();
m_Journal->Begin();
m_Open = true;
return true;
}
bool NVault::Close()
{
if (!m_Open)
return false;
_SaveToFile();
m_Journal->End();
m_Journal->Erase();
return true;
}
void NVault::SetValue(const char *key, const char *val)
{
if (m_Journal)
m_Journal->Write_Insert(key, val, time(NULL));
String sKey;
String sVal;
sKey.assign(key);
sVal.assign(val);
m_Hash.Insert(sKey, sVal);
}
void NVault::SetValue(const char *key, const char *val, time_t stamp)
{
if (m_Journal)
m_Journal->Write_Insert(key, val, stamp);
String sKey;
String sVal;
sKey.assign(key);
sVal.assign(val);
m_Hash.Insert(sKey, sVal, stamp);
}
void NVault::Remove(const char *key)
{
if (m_Journal)
m_Journal->Write_Remove(key);
String sKey(key);
m_Hash.Remove(sKey);
}
void NVault::Clear()
{
if (m_Journal)
m_Journal->Write_Clear();
m_Hash.Clear();
}
size_t NVault::Items()
{
return m_Hash.Size();
}
size_t NVault::Prune(time_t start, time_t end)
{
if (m_Journal)
m_Journal->Write_Prune(start, end);
return m_Hash.Prune(start, end);
}
bool NVault::GetValue(const char *key, time_t &stamp, char buffer[], size_t len)
{
String sKey(key);
if (!m_Hash.Exists(sKey))
{
buffer[0] = '\0';
return false;
}
time_t st;
String sVal;
sVal = m_Hash.Retrieve(sKey, st);
stamp = st;
_snprintf(buffer, len, "%s", sVal.c_str());
return true;
}

65
dlls/nvault/NVault.h Executable file
View File

@ -0,0 +1,65 @@
#ifndef _INCLUDE_NVAULT_H
#define _INCLUDE_NVAULT_H
#include "IVault.h"
#include "CString.h"
#include "Journal.h"
#define VAULT_MAGIC 0x6E564C54 //nVLT
#define VAULT_VERSION 0x0200 //second version
// File format:
// VAULT_MAGIC (int32)
// VAULT_VERSION (int16)
// ENTRIES (int32)
// [
// stamp (int32)
// keylen (int8)
// vallen (int16)
// key ([])
// val ([])
// ]
enum VaultError
{
Vault_Ok=0,
Vault_NoFile,
Vault_BadFile,
Vault_OldFile,
Vault_Read,
};
class NVault : public IVault
{
public:
NVault(const char *file);
~NVault();
public:
bool GetValue(const char *key, time_t &stamp, char buffer[], size_t len);
void SetValue(const char *key, const char *val);
void SetValue(const char *key, const char *val, time_t stamp);
size_t Prune(time_t start, time_t end);
void Clear();
void Remove(const char *key);
bool Open();
bool Close();
size_t Items();
private:
VaultError _ReadFromFile();
bool _SaveToFile();
private:
String m_File;
NHash<String, String> m_Hash;
Journal *m_Journal;
bool m_Open;
};
class VaultMngr
{
public:
//when you delete it, it will be closed+saved automatically
//when you open it, it will read the file automatically, as well as begin/restore journaling
IVault *OpenVault(const char *file);
};
#endif //_INCLUDE_NVAULT_H

View File

@ -1,7 +1,7 @@
#ifndef _INCLUDE_AMXXAPI_H
#define _INCLUDE_AMXXAPI_H
#include "sdk/CVector.h"
#include "CVector.h"
#include "hash.h"
#include "nvault.h"
#include "journal.h"

18
dlls/nvault/compat.h Executable file
View File

@ -0,0 +1,18 @@
#ifndef _INCLUDE_COMPAT_H
#define _INCLUDE_COMPAT_H
#ifdef WIN32
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
#else
#include <stdint.h>
#endif
#endif //_INCLUDE_COMPAT_H

View File

@ -21,7 +21,7 @@
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NVAULT_EXPORTS"
MinimalRebuild="TRUE"
ExceptionHandling="FALSE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
StructMemberAlignment="3"
@ -130,25 +130,13 @@
</FileConfiguration>
</File>
<File
RelativePath=".\hash.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
RelativePath=".\Binary.cpp">
</File>
<File
RelativePath=".\journal.cpp">
RelativePath=".\Journal.cpp">
</File>
<File
RelativePath=".\nvault.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Detect64BitPortabilityProblems="FALSE"/>
</FileConfiguration>
RelativePath=".\NVault.cpp">
</File>
</Filter>
<Filter
@ -159,13 +147,22 @@
RelativePath=".\amxxapi.h">
</File>
<File
RelativePath=".\hash.h">
RelativePath=".\Binary.h">
</File>
<File
RelativePath=".\journal.h">
RelativePath=".\compat.h">
</File>
<File
RelativePath=".\nvault.h">
RelativePath=".\IVault.h">
</File>
<File
RelativePath=".\Journal.h">
</File>
<File
RelativePath=".\NHash.h">
</File>
<File
RelativePath=".\NVault.h">
</File>
</Filter>
<Filter
@ -183,7 +180,7 @@
RelativePath=".\sdk\amxxmodule.h">
</File>
<File
RelativePath=".\sdk\CString.h">
RelativePath=".\CString.h">
</File>
<File
RelativePath=".\sdk\moduleconfig.h">

View File

@ -31,8 +31,10 @@
// ***** AMXX stuff *****
// module interface version is 1
#define AMXX_INTERFACE_VERSION 2
// module interface version was 1
// 2 - added logtag to struct (amxx1.1-rc1)
// 3 - added new tagAMX structure (amxx1.5)
#define AMXX_INTERFACE_VERSION 3
// amxx module info
struct amxx_module_info_s
@ -54,38 +56,55 @@ struct amxx_module_info_s
// *** Small stuff ***
// The next section is copied from the amx.h file
// Copyright (c) ITB CompuPhase, 1997-2004
// Copyright (c) ITB CompuPhase, 1997-2005
#if defined __LCC__ || defined __DMC__ || defined __linux__ || defined __GNUC__
#if defined HAVE_STDINT_H
#include <stdint.h>
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
* here, these types are probably undefined.
*/
#if defined __FreeBSD__
#include <inttypes.h>
#else
typedef short int int16_t;
typedef unsigned short int uint16_t;
#if defined SN_TARGET_PS2
typedef int int32_t;
typedef unsigned int uint32_t;
#else
#if defined __LCC__ || defined __DMC__ || defined LINUX
#if defined HAVE_INTTYPES_H
#include <inttypes.h>
#else
typedef long int int32_t;
typedef unsigned long int uint32_t;
#include <stdint.h>
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define HAVE_I64
#elif defined __GNUC__
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define HAVE_I64
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
* here, these types are probably undefined.
*/
#if defined __MACH__
#include <ppc/types.h>
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
#elif defined __FreeBSD__
#include <inttypes.h>
#else
typedef short int int16_t;
typedef unsigned short int uint16_t;
#if defined SN_TARGET_PS2
typedef int int32_t;
typedef unsigned int uint32_t;
#else
typedef long int int32_t;
typedef unsigned long int uint32_t;
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define HAVE_I64
#elif defined __GNUC__
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define HAVE_I64
#endif
#endif
#endif
#define HAVE_STDINT_H
#endif
#if defined _LP64 || defined WIN64 || defined _WIN64
#if !defined __64BIT__
#define __64BIT__
#endif
#endif
/* calling convention for native functions */
#if !defined AMX_NATIVE_CALL
@ -105,24 +124,26 @@ struct amxx_module_info_s
#define AMXEXPORT
#endif
#if !defined SMALL_CELL_SIZE
#define SMALL_CELL_SIZE 32 /* by default, use 32-bit cells */
#if !defined PAWN_CELL_SIZE
#define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
#endif
#if SMALL_CELL_SIZE==32
#if PAWN_CELL_SIZE==16
typedef uint16_t ucell;
typedef int16_t cell;
#elif PAWN_CELL_SIZE==32
typedef uint32_t ucell;
typedef int32_t cell;
typedef float REAL;
#elif SMALL_CELL_SIZE==64
#define REAL float
#elif PAWN_CELL_SIZE==64
typedef uint64_t ucell;
typedef int64_t cell;
typedef double REAL;
#define REAL double
#else
#error Unsupported cell size (SMALL_CELL_SIZE)
#error Unsupported cell size (PAWN_CELL_SIZE)
#endif
#define UNPACKEDMAX ((1 << (sizeof(cell)-1)*8) - 1)
#define UNLIMITED (~1u >> 1)
struct tagAMX;
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
@ -140,21 +161,24 @@ typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
#endif
#if defined SN_TARGET_PS2 || defined __GNUC__
/* Some compilers do not support the #pragma align, which should be fine. Some
* compilers give a warning on unknown #pragmas, which is not so fine...
*/
#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
#define AMX_NO_ALIGN
#endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#if !defined AMX_NO_ALIGN
#if defined __linux__
#if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k
#else
#pragma pack(push)
#pragma pack(1) /* structures must be packed (byte-aligned) */
@ -175,7 +199,7 @@ typedef struct {
* fields are valid at all times; many fields are cached in local variables.
*/
typedef struct tagAMX {
unsigned char _FAR *base PACKED; /* points to the AMX header ("amxhdr") plus the code, optionally also the data */
unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback PACKED;
AMX_DEBUG debug PACKED; /* debug callback */
@ -187,28 +211,25 @@ typedef struct tagAMX {
cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */
cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */
int flags PACKED; /* current status, see amx_Flags() */
/* for assertions and debug hook */
cell curline PACKED;
cell curfile PACKED;
int dbgcode PACKED;
cell dbgaddr PACKED;
cell dbgparam PACKED;
char _FAR *dbgname PACKED;
/* user data */
long usertags[AMX_USERNUM] PACKED;
//okay userdata[3] in AMX Mod X is for the CPlugin * pointer
//we're also gonna set userdata[2] to a special debug structure
void _FAR *userdata[AMX_USERNUM] PACKED;
/* native functions can raise an error */
int error PACKED;
/* passing parameters requires a "count" field */
int paramcount;
/* the sleep opcode needs to store the full AMX status */
cell pri PACKED;
cell alt PACKED;
cell reset_stk PACKED;
cell reset_hea PACKED;
cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */
/* support variables for the JIT */
int reloc_size PACKED; /* required temporary buffer for relocations */
long code_size PACKED; /* estimated memory footprint of the native code */
} AMX;
/* support variables for the JIT */
int reloc_size PACKED; /* required temporary buffer for relocations */
long code_size PACKED; /* estimated memory footprint of the native code */
} PACKED AMX;
enum {
AMX_ERR_NONE,
@ -225,6 +246,7 @@ enum {
AMX_ERR_NATIVE, /* native function failed */
AMX_ERR_DIVIDE, /* divide by zero */
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
AMX_ERR_INVSTATE, /* invalid state for this access */
AMX_ERR_MEMORY = 16, /* out of memory */
AMX_ERR_FORMAT, /* invalid file format */

View File

@ -5,12 +5,12 @@
// Module info
#define MODULE_NAME "nVault"
#define MODULE_VERSION "1.02"
#define MODULE_VERSION "1.50"
#define MODULE_AUTHOR "AMX Mod X Dev Team"
#define MODULE_URL "http://www.amxmodx.org/"
#define MODULE_LOGTAG "nVault"
// If you want the module not to be reloaded on mapchange, remove / comment out the next line
#define MODULE_RELOAD_ON_MAPCHANGE
//#define MODULE_RELOAD_ON_MAPCHANGE
#ifdef __DATE__
#define MODULE_DATE __DATE__
@ -19,7 +19,7 @@
#endif // __DATE__
// metamod plugin?
// #define USE_METAMOD
#define USE_METAMOD
// - AMXX Init functions
// Also consider using FN_META_*