diff --git a/dlls/nvault/hash.cpp b/dlls/nvault/hash.cpp index d58176ae..10b3c1d0 100755 --- a/dlls/nvault/hash.cpp +++ b/dlls/nvault/hash.cpp @@ -23,7 +23,7 @@ HashTable::htNode *HashTable::Retrieve(const char *key) return _FindNode(key); } -//Adds an entry into the hash table +//Adds an entry into the hash table with current time void HashTable::Store(const char *key, const char *value, bool temporary) { time_t stamp = 0; @@ -34,6 +34,22 @@ void HashTable::Store(const char *key, const char *value, bool temporary) _Insert(key, value, stamp); } +//Adds an entry into the hash table with preset time +void HashTable::Store(const char *key, const char *value, time_t stamp) +{ + _Insert(key, value, stamp); +} + +//Erases a key +void HashTable::EraseKey(const char *key) +{ + HashTable::htNodeSet *set = _FindNodeSet(key); + HashTable::htNode *node = _FindNode(key, false); + + if (set && node) + _Unlink(set, node); +} + //Deletes all keys between the two times. // 0 specifies "match all" //All specifies whether permanent keys (time_t = 0) are erased @@ -106,7 +122,20 @@ void HashTable::Clear() bool HashTable::KeyExists(const char *key) { - return _FindNode(key, false); + return (_FindNode(key, false) != NULL); +} + +size_t HashTable::UsedHashes() +{ + size_t num = 0; + + for (uint32_t i=0; i +#include "journal.h" +#include "sdk/CVector.h" + +struct j_info +{ + int id; + Vault *vault; +}; + +Journal::Journal(const char *file) +{ + m_File.assign(file); + m_Fp = NULL; + m_LastId = 0; +} + +#define rd(v,s) if (fread(&v, sizeof(s), 1, m_Fp) != 1) { \ + fclose(m_Fp); \ + m_Fp = NULL; \ + goto _error; } +#define rds(v,l) if (fread(v, sizeof(char), l, m_Fp) != l) { \ + fclose(m_Fp); \ + m_Fp = NULL; \ + goto _error; } else { \ + v[l] = '\0'; } + +bool Journal::Replay(size_t &files, size_t &ops) +{ + m_Fp = fopen(m_File.c_str(), "rb"); + + files = 0; + ops = 0; + + if (!m_Fp) + return false; + + //this must come before the first jump... + CVector table; + uint32_t magic; + + rd(magic, uint32_t); + if (magic != JOURNAL_MAGIC) + return false; + + j_info *j; + uint8_t op, klen; + uint16_t vlen; + uint32_t id; + size_t i; + char *key=NULL, *val=NULL; + while (!feof(m_Fp)) + { + if (fread(&op, sizeof(uint8_t), 1, m_Fp) != 1) + { + if (feof(m_Fp)) + break; + else + goto _error; + } + switch (op) + { + case Journal_Nop: + { + break; + } + case Journal_Name: + { + rd(id, uint32_t); + rd(klen, uint8_t); + key = new char[klen+1]; + rds(key, klen); + j = new j_info; + j->id = id; + j->vault = new Vault(key); + j->vault->ReadFromFile(); + table.push_back(j); + files++; + delete [] key; + key = NULL; + break; + } + case Journal_Store: + { + //Stores key/val (id,time,klen,vlen,[],[]) + uint32_t stamp; + rd(id, uint32_t); + rd(stamp, uint32_t); + rd(klen, uint8_t); + rd(vlen, uint16_t); + key = new char[klen+1]; + val = new char[vlen+1]; + rds(key, klen); + rds(val, vlen); + for (i=0; iid == id) + { + table.at(i)->vault->Store(key, val, (time_t)stamp); + break; + } + } + delete [] key; + delete [] val; + key = NULL; + val = NULL; + break; + } + case Journal_Erase: + { + //Erases key (id,klen,[]) + rd(id, uint32_t); + rd(klen, uint8_t); + key = new char[klen+1]; + rds(key, klen); + for (i=0; iid == id) + { + table.at(i)->vault->EraseKey(key); + break; + } + } + delete [] key; + key = NULL; + break; + } + case Journal_Clear: + { + //Clears (id) + rd(id, uint32_t); + for (i=0; iid == id) + { + table.at(i)->vault->Clear(); + break; + } + } + break; + } + case Journal_Prune: + { + //Prunes (id,t1,t2,all) + rd(id, uint32_t); + uint32_t begin, end; + uint8_t all; + rd(begin, uint32_t); + rd(end, uint32_t); + rd(all, uint8_t); + for (i=0; iid == id) + { + table.at(i)->vault->Prune((time_t)begin, (time_t)end, all?true:false); + break; + } + } + break; + } + default: + { + goto _error; + } + } //end while + ops++; + } + + for (uint32_t i=0; ivault->WriteToFile(); + delete j->vault; + delete j; + } + + fclose(m_Fp); + + return true; +_error: + for (uint32_t i=0; ivault->WriteToFile(); + delete j->vault; + delete j; + } + if (key) + { + delete [] key; + key = NULL; + } + if (val) + { + delete [] val; + val = NULL; + } + return false; +} + +void Journal::ClearJournal() +{ + m_Fp = fopen(m_File.c_str(), "wb"); + + if (m_Fp) + { + fclose(m_Fp); + m_Fp = NULL; + } +} + +bool Journal::StartJournal() +{ + m_Fp = fopen(m_File.c_str(), "wb"); + + if (!m_Fp) + return false; + + uint32_t magic = JOURNAL_MAGIC; + + fwrite(&magic, sizeof(uint32_t), 1, m_Fp); + + return true; +} + +void Journal::EndJournal() +{ + if (m_Fp) + { + fclose(m_Fp); + m_Fp = NULL; + } +} + +//Stores key/val (id,time,klen,vlen,[],[] +void Journal::Store(const char *name, const char *key, const char *val, time_t stamp) +{ + uint32_t time32 = (uint32_t)stamp; + uint16_t vlen = (uint16_t)strlen(val); + uint8_t klen = (uint8_t)strlen(key); + + BeginOp(name, Journal_Store); + WriteInt(time32); + WriteByte(klen); + WriteShort(vlen); + WriteString(key); + WriteString(val); + EndOp(); +} + +//Erases key (id,klen,[]) +void Journal::Erase(const char *name, const char *key) +{ + uint8_t klen = (uint8_t)strlen(key); + + BeginOp(name, Journal_Erase); + WriteByte(klen); + WriteString(key); + EndOp(); +} + +//Clears (id) +void Journal::Clear(const char *name) +{ + BeginOp(name, Journal_Clear); + EndOp(); +} + +//Prunes (id,t1,t2,all) +void Journal::Prune(const char *name, time_t begin, time_t end, bool all) +{ + uint32_t begin32 = (uint32_t)begin; + uint32_t end32 = (uint32_t)end; + uint8_t all8 = (uint8_t)all; + + BeginOp(name, Journal_Prune); + WriteInt(begin32); + WriteInt(end32); + WriteByte(all8); + EndOp(); +} + +void Journal::BeginOp(const char *name, JournalOp jop) +{ + uint32_t id; + + if (!m_Names.KeyExists(name)) + { + char name_buf[12]; + id = ++m_LastId; + sprintf(name_buf, "%d", id); + m_Names.Store(name, name_buf, false); + WriteByte(Journal_Name); + WriteInt(id); + WriteByte(strlen(name)); + WriteString(name); + } else { + id = atoi(m_Names.Retrieve(name)->val.c_str()); + } + + WriteByte(jop); + WriteInt(id); +} + +void Journal::WriteByte(uint8_t num) +{ + fwrite(&num, sizeof(uint8_t), 1, m_Fp); +} + +void Journal::WriteShort(uint16_t num) +{ + fwrite(&num, sizeof(uint16_t), 1, m_Fp); +} + +void Journal::WriteInt(uint32_t num) +{ + fwrite(&num, sizeof(uint32_t), 1, m_Fp); +} + +void Journal::WriteString(const char *str) +{ + fwrite(str, sizeof(char), strlen(str), m_Fp); +} + +size_t Journal::EndOp() +{ + return 1; +} diff --git a/dlls/nvault/journal.h b/dlls/nvault/journal.h new file mode 100755 index 00000000..ffa70037 --- /dev/null +++ b/dlls/nvault/journal.h @@ -0,0 +1,46 @@ +#ifndef _INCLUDE_JOURNAL_H +#define _INCLUDE_JOURNAL_H + +#include "nvault.h" + +#define JOURNAL_MAGIC 0x6E564A4C + +class Journal +{ +public: + enum JournalOp + { + Journal_Nop, //Nothing + Journal_Name, //Maps name to Id (id,len,[]) + Journal_Store, //Stores key/val (id,time,klen,vlen,[],[]) + Journal_Erase, //Erases key (id,klen,[]) + Journal_Clear, //Clears (id) + Journal_Prune //Prunes (id,t1,t2,all) + }; +public: + Journal(const char *file); +public: + bool Replay(size_t &files, size_t &ops); + void ClearJournal(); + bool StartJournal(); + void EndJournal(); +public: + void Store(const char *name, const char *key, const char *val, time_t stamp); + void Erase(const char *name, const char *key); + void Clear(const char *name); + void Prune(const char *name, time_t begin, time_t end, bool all); +private: + void BeginOp(const char *name, JournalOp jop); + void WriteByte(uint8_t num); + void WriteShort(uint16_t num); + void WriteInt(uint32_t num); + void WriteString(const char *str); + size_t EndOp(); +private: + String m_File; + FILE *m_Fp; + HashTable m_Names; + uint32_t m_LastId; +}; + +#endif //_INCLUDE_JOURNAL_H diff --git a/dlls/nvault/nvault.cpp b/dlls/nvault/nvault.cpp index 97966a05..3886bcb3 100755 --- a/dlls/nvault/nvault.cpp +++ b/dlls/nvault/nvault.cpp @@ -1,2 +1,206 @@ #include "nvault.h" +Vault::Vault(const char *name) +{ + m_File.assign(name); + m_Vault = NULL; +} + +Vault::~Vault() +{ + if (m_Vault) + { + delete m_Vault; + m_Vault = NULL; + } +} + +void Vault::Clear() +{ + if (m_Vault) + m_Vault->Clear(); +} + +void Vault::EraseKey(const char *key) +{ + if (m_Vault) + m_Vault->EraseKey(key); +} + +HashTable::htNode *Vault::Find(const char *key) +{ + if (m_Vault) + return m_Vault->Retrieve(key); + + return NULL; +} + +bool Vault::KeyExists(const char *key) +{ + if (m_Vault) + return m_Vault->KeyExists(key); + + return NULL; +} + +size_t Vault::Prune(time_t begin, time_t end, bool all) +{ + if (m_Vault) + return m_Vault->Prune(begin, end, all); + + return 0; +} + +void Vault::Store(const char *key, const char *value, bool temporary) +{ + if (m_Vault) + m_Vault->Store(key, value, temporary); +} + +void Vault::Store(const char *key, const char *value, time_t stamp) +{ + if (m_Vault) + m_Vault->Store(key, value, stamp); +} + +#define wr(v,s) fwrite(&v, sizeof(s), 1, fp) + +bool Vault::WriteToFile() +{ + FILE *fp = fopen(m_File.c_str(), "wb"); + + if (!fp) + return false; + + uint32_t hashes = m_Vault->UsedHashes(); + + _WriteHeaders(fp, hashes); + + HashTable::htNode *node; + uint32_t keys, stamp; + uint16_t vChars; + uint8_t kChars; + for (uint32_t i=0; im_Table[i]) + { + keys = 0; + node = m_Vault->m_Table[i]->head;; + while (node != NULL) + { + keys++; + node = node->next; + } + wr(i, uint32_t); + wr(keys, uint32_t); + node = m_Vault->m_Table[i]->head; + while (node != NULL) + { + stamp = (uint32_t)(node->stamp); + wr(stamp, uint32_t); + kChars = (uint8_t)(node->key.size()); + vChars = (uint16_t)(node->val.size()); + wr(kChars, uint8_t); + wr(vChars, uint16_t); + fwrite(node->key.c_str(), sizeof(char), kChars, fp); + fwrite(node->val.c_str(), sizeof(char), vChars, fp); + node = node->next; + } + } + } + + fclose(fp); + + return true; +} + +#define rd(v,s) if (fread(&v, sizeof(s), 1, fp) != 1) { \ + fclose(fp); \ + return Vault_ReadFail; } + +Vault::VaultError Vault::ReadFromFile() +{ + FILE *fp = fopen(m_File.c_str(), "rb"); + + if (!fp) + { + fp = fopen(m_File.c_str(), "wb"); + if (!fp) + return Vault_ReadFail; + _WriteHeaders(fp, 0); + fclose(fp); + m_Vault = new HashTable(); + return Vault_Ok; + } + + uint32_t magic, keysize, hashes; + uint8_t timesize; + + rd(magic, uint32_t); + if (magic != VAULT_MAGIC) + { + fclose(fp); + return Vault_BadMagic; + } + rd(timesize, uint8_t); + rd(keysize, uint32_t); + rd(hashes, uint32_t); + + m_Vault = new HashTable(); + + uint32_t hash, keys, stamp; + uint16_t vChars; + uint8_t kChars; + char *key, *value; + for (uint32_t i=0; iStore(key, value, (time_t)stamp); + delete [] key; + delete [] value; + } + } + + fclose(fp); + + return Vault_Ok; +} + +/////////////////// +// Private stuff // +/////////////////// + +void Vault::_WriteHeaders(FILE *fp, uint32_t keys) +{ + uint32_t magic = VAULT_MAGIC; + uint32_t keysize = (1<<11); + uint8_t timesize = sizeof(time_t); + + fwrite(&magic, sizeof(uint32_t), 1, fp); + fwrite(×ize, sizeof(uint8_t), 1, fp); + fwrite(&keysize, sizeof(uint32_t), 1, fp); + fwrite(&keys, sizeof(uint32_t), 1, fp); +} + diff --git a/dlls/nvault/nvault.h b/dlls/nvault/nvault.h index 67199adf..b76e0fae 100755 --- a/dlls/nvault/nvault.h +++ b/dlls/nvault/nvault.h @@ -4,47 +4,50 @@ #include "sdk/CString.h" #include "hash.h" -class Journal +/** + * Vault file format: + * Headers + * uint32_t - nVLT + * uint8_t - sizeof(time_t) + * uint32_t - key size (will be used in future maybe) + * uint32_t - number of hashes stored + * Data + * uint32_t - key hash + * uint32_t - # of keys in this hash + * Data + * uint32_t - Time + * uint8_t - Characters in key + * uint16_t - Characters in value + * char[] - Key + * char[] - Value + */ + +#define VAULT_MAGIC 0x6E564C54 + +class Vault { public: - enum JournalOp + Vault(const char *name); + ~Vault(); + enum VaultError { - Journal_Store, - Journal_Erase, - Journal_Clear, - Journal_Prune + Vault_Ok=0, + Vault_ReadFail, + Vault_BadMagic, }; -public: - Journal(const char *file); -public: - bool Replay(size_t &files, size_t &ops); - void Clear(); -public: - void Begin(const char *name, JournalOp jop); - void WriteByte(uint8_t num); - void WriteInt(uint32_t num); - void WriteTime(time_t n); - void WriteString(const char *str); - size_t End(); -private: - String m_File; - FILE *m_Fp; - size_t m_WriteSize; -}; - -class nVault -{ -public: - nVault(const char *name); public: bool WriteToFile(); - bool ReadFromFile(); + VaultError ReadFromFile(); public: void Store(const char *key, const char *value, bool temporary=true); + void Store(const char *key, const char *value, time_t stamp); size_t Prune(time_t begin, time_t end, bool all=false); HashTable::htNode *Find(const char *key); bool KeyExists(const char *key); void Clear(); + void EraseKey(const char *key); +private: + void _WriteHeaders(FILE *fp, uint32_t hashes); private: String m_File; HashTable *m_Vault; diff --git a/dlls/nvault/nvault.vcproj b/dlls/nvault/nvault.vcproj index 0cc035d4..50b8d18e 100755 --- a/dlls/nvault/nvault.vcproj +++ b/dlls/nvault/nvault.vcproj @@ -23,7 +23,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="1" - UsePrecompiledHeader="3" + UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="TRUE" DebugInformationFormat="4"/> @@ -117,9 +117,24 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + + + + + + + + + + diff --git a/dlls/nvault/sdk/CVector.h b/dlls/nvault/sdk/CVector.h new file mode 100755 index 00000000..05538f53 --- /dev/null +++ b/dlls/nvault/sdk/CVector.h @@ -0,0 +1,444 @@ +/* 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 __CVECTOR_H__ +#define __CVECTOR_H__ + +#include + +// Vector +template class CVector +{ + bool Grow() + { + // automatic grow + size_t newSize = m_Size * 2; + if (newSize == 0) + newSize = 8; // a good init value + T *newData = new T[newSize]; + if (!newData) + return false; + if (m_Data) + { + memcpy(newData, m_Data, m_Size * sizeof(T)); + delete [] m_Data; + } + m_Data = newData; + m_Size = newSize; + return true; + } + + bool GrowIfNeeded() + { + if (m_CurrentUsedSize >= m_Size) + return Grow(); + else + return true; + } + + bool ChangeSize(size_t size) + { + // change size + if (size == m_Size) + return true; + T *newData = new T[size]; + if (!newData) + return false; + if (m_Data) + { + memcpy(newData, m_Data, (m_Size < size) ? (m_Size * sizeof(T)) : (size * sizeof(T))); + delete [] m_Data; + } + if (m_Size < size) + m_CurrentSize = size; + m_Data = newData; + m_Size = size; + return true; + } + + void FreeMemIfPossible() + { + + } +protected: + T *m_Data; + size_t m_Size; + size_t m_CurrentUsedSize; + size_t m_CurrentSize; +public: + class iterator + { + protected: + T *m_Ptr; + public: + // constructors / destructors + iterator() + { + m_Ptr = NULL; + } + + iterator(T * ptr) + { + m_Ptr = ptr; + } + + // member functions + T * base() + { + return m_Ptr; + } + + const T * base() const + { + return m_Ptr; + } + + // operators + T & operator*() + { + return *m_Ptr; + } + + T * operator->() + { + return m_Ptr; + } + + iterator & operator++() // preincrement + { + ++m_Ptr; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Ptr; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Ptr; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Ptr; + return tmp; + } + + bool operator==(T * right) const + { + return (m_Ptr == right); + } + + bool operator==(const iterator & right) const + { + return (m_Ptr == right.m_Ptr); + } + + bool operator!=(T * right) const + { + return (m_Ptr != right); + } + + bool operator!=(const iterator & right) const + { + return (m_Ptr != right.m_Ptr); + } + + iterator & operator+=(size_t offset) + { + m_Ptr += offset; + return (*this); + } + + iterator & operator-=(size_t offset) + { + m_Ptr += offset; + return (*this); + } + + iterator operator+(size_t offset) const + { + iterator tmp(*this); + tmp.m_Ptr += offset; + return tmp; + } + + iterator operator-(size_t offset) const + { + iterator tmp(*this); + tmp.m_Ptr += offset; + return tmp; + } + + T & operator[](size_t offset) + { + return (*(*this + offset)); + } + + const T & operator[](size_t offset) const + { + return (*(*this + offset)); + } + + bool operator<(const iterator & right) const + { + return m_Ptr < right.m_Ptr; + } + + bool operator>(const iterator & right) const + { + return m_Ptr > right.m_Ptr; + } + + bool operator<=(const iterator & right) const + { + return m_Ptr <= right.m_Ptr; + } + + bool operator>=(const iterator & right) const + { + return m_Ptr >= right.m_Ptr; + } + + size_t operator-(const iterator & right) const + { + return m_Ptr - right.m_Ptr; + } + }; + + // constructors / destructors + CVector() + { + m_Size = 0; + m_CurrentUsedSize = 0; + m_Data = NULL; + } + + CVector(const CVector & other) + { + // copy data + m_Data = new T [other.m_Size]; + m_Size = other.m_Size; + m_CurrentUsedSize = other.m_CurrentUsedSize; + memcpy(m_Data, other.m_Data, m_CurrentUsedSize * sizeof(T)); + } + + ~CVector() + { + clear(); + } + + // interface + size_t size() const + { + return m_CurrentUsedSize; + } + + size_t capacity() const + { + return m_Size; + } + + iterator begin() + { + return iterator(m_Data); + } + + iterator end() + { + return iterator(m_Data + m_CurrentUsedSize); + } + + iterator iterAt(size_t pos) + { + if (pos > m_CurrentUsedSize) + assert(0); + return iterator(m_Data + pos); + } + + bool reserve(size_t newSize) + { + return ChangeSize(newSize); + } + + bool push_back(const T & elem) + { + ++m_CurrentUsedSize; + if (!GrowIfNeeded()) + { + --m_CurrentUsedSize; + return false; + } + + m_Data[m_CurrentUsedSize - 1] = elem; + return true; + } + + void pop_back() + { + --m_CurrentUsedSize; + if (m_CurrentUsedSize < 0) + m_CurrentUsedSize = 0; + // :TODO: free memory sometimes + } + + bool resize(size_t newSize) + { + if (!ChangeSize(newSize)) + return false; + FreeMemIfPossible(); + return true; + } + + bool empty() const + { + return (m_CurrentUsedSize == 0); + } + + T & at(size_t pos) + { + if (pos > m_CurrentUsedSize) + { + assert(0); + } + return m_Data[pos]; + } + + const T & at(size_t pos) const + { + if (pos > m_CurrentUsedSize) + { + assert(0); + } + return m_Data[pos]; + } + + T & operator[](size_t pos) + { + return at(pos); + } + + const T & operator[](size_t pos) const + { + return at(pos); + } + + T & front() + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[0]; + } + + const T & front() const + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[0]; + } + + T & back() + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[m_CurrentUsedSize - 1]; + } + + const T & back() const + { + if (m_CurrentUsedSize < 1) + { + assert(0); + } + return m_Data[m_CurrentUsedSize - 1]; + } + + bool insert(iterator where, const T & value) + { + // we have to insert before + // if it is begin, don't decrement + if (where != m_Data) + --where; + // validate iter + if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) + return false; + + ++m_CurrentUsedSize; + if (!GrowIfNeeded()) + { + --m_CurrentUsedSize; + return false; + } + + memmove(where.base() + 1, where.base(), m_CurrentUsedSize - (where - m_Data)); + memcpy(where.base(), &value, sizeof(T)); + return true; + } + + void erase(iterator where) + { + // validate iter + if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) + return false; + + if (m_CurrentUsedSize > 1) + { + // move + memmove(where.base(), where.base() + 1, m_CurrentUsedSize - 1); + } + + --m_CurrentUsedSize; + // :TODO: free memory sometimes + } + + void clear() + { + m_Size = 0; + m_CurrentUsedSize = 0; + delete [] m_Data; + m_Data = NULL; + } +}; + +#endif // __CVECTOR_H__ +