Rewrote language backend for integrity checking and optimization
Replaced CRC32 system with real hash-map
This commit is contained in:
@ -46,9 +46,9 @@
|
||||
#define INSERT_STRING 3
|
||||
#define INSERT_NEWLINE 4
|
||||
|
||||
// dictionary format is Fast-Format-Hash-Lookup, v4
|
||||
// dictionary format is Fast-Format-Hash-Lookup, v5
|
||||
#define MAGIC_HDR 0x4646484C
|
||||
#define FFHL_VERSION 4
|
||||
#define FFHL_VERSION 5
|
||||
#define FFHL_MIN_VERSION 4
|
||||
|
||||
/*version history:
|
||||
@ -56,6 +56,7 @@
|
||||
* 2 (BAILOPAN) - One language per file with full reverse
|
||||
* 3 (PM OnoTo) - 2^32 languages per file with full reverse
|
||||
* 4 (BAILOPAN) - Optimized by separating and relocating tables (normalization)
|
||||
* 5 (BAILOPAN) - Removed hash storage
|
||||
FORMAT:
|
||||
Magic 4bytes
|
||||
Version 1byte
|
||||
@ -65,13 +66,11 @@ LANG INFO TABLE[]
|
||||
Language Name 2bytes
|
||||
Offset 4bytes
|
||||
KEY TABLE[]
|
||||
Key Hash 4bytes
|
||||
Key Lookup Offset 4bytes
|
||||
LANGUAGES TABLE[]
|
||||
Language[]
|
||||
Definitions 4bytes
|
||||
Key Hash # 4bytes (virtual # in hash table, 0 indexed)
|
||||
Def Hash 4bytes
|
||||
Key # 4bytes (0-index into key table)
|
||||
Def Offset 4bytes
|
||||
KEY LOOKUP TABLE[]
|
||||
Key length 1byte
|
||||
@ -81,70 +80,32 @@ DEF LOOKUP TABLE[]
|
||||
Def string variable
|
||||
*/
|
||||
|
||||
/******** CRC & Strip *********/
|
||||
const uint32_t CRCTable[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
|
||||
uint32_t CLangMngr::CLang::MakeHash(const char *src, bool makeLower)
|
||||
template<>
|
||||
int Compare<String>(const String &k1, const String &k2)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
|
||||
while (*src)
|
||||
crc = ((crc>>8)&0xFFFFFFFF)^CRCTable[(crc^ (makeLower ? tolower(*src++) : *src++) )&0xFF];
|
||||
|
||||
return ~crc;
|
||||
return k1.compare(k2.c_str());
|
||||
}
|
||||
|
||||
uint32_t CLangMngr::MakeHash(const char *src, bool makeLower)
|
||||
template<>
|
||||
int HashFunction<String>(const String &k)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
|
||||
while (*src)
|
||||
crc = ((crc>>8)&0xFFFFFFFF)^CRCTable[(crc^ (makeLower ? tolower(*src++) : *src++) )&0xFF];
|
||||
|
||||
return ~crc;
|
||||
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<>
|
||||
int HashFunction<int>(const int &k)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
template<>
|
||||
int Compare<int>(const int &k1, const int &k2)
|
||||
{
|
||||
return (k1-k2);
|
||||
}
|
||||
|
||||
// strip the whitespaces at the beginning and the end of a string
|
||||
@ -188,86 +149,6 @@ size_t CLangMngr::strip(char *str, char *newstr, bool makelower)
|
||||
return ptr - str + 1;
|
||||
}
|
||||
|
||||
/******** CLangMngr::CLang::LangEntry *********/
|
||||
uint32_t CLangMngr::CLang::LangEntry::GetDefHash()
|
||||
{
|
||||
return m_DefHash;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::LangEntry::SetCache(bool c)
|
||||
{
|
||||
m_isCache = c;
|
||||
}
|
||||
|
||||
bool CLangMngr::CLang::LangEntry::GetCache()
|
||||
{
|
||||
return m_isCache;
|
||||
}
|
||||
|
||||
const char *CLangMngr::CLang::LangEntry::GetDef()
|
||||
{
|
||||
return m_pDef.c_str();
|
||||
}
|
||||
|
||||
int CLangMngr::CLang::LangEntry::GetDefLength()
|
||||
{
|
||||
return m_pDef.size();
|
||||
}
|
||||
|
||||
int CLangMngr::CLang::LangEntry::GetKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry::LangEntry()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry::LangEntry(int pKey)
|
||||
{
|
||||
Clear();
|
||||
SetKey(pKey);
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry::LangEntry(int pKey, const char *pDef)
|
||||
{
|
||||
Clear();
|
||||
SetKey(pKey);
|
||||
SetDef(pDef);
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry::LangEntry(const LangEntry &other)
|
||||
{
|
||||
Clear();
|
||||
SetKey(other.key);
|
||||
SetDef(other.m_pDef.c_str());
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry::LangEntry(int pKey, uint32_t defHash, const char *pDef)
|
||||
{
|
||||
Clear();
|
||||
key = pKey;
|
||||
m_DefHash = defHash;
|
||||
m_pDef.assign(pDef);
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::LangEntry::Clear()
|
||||
{
|
||||
m_pDef.clear();
|
||||
key = -1;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::LangEntry::SetKey(int pkey)
|
||||
{
|
||||
key = pkey;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::LangEntry::SetDef(const char *pDef)
|
||||
{
|
||||
m_pDef.assign(pDef);
|
||||
m_DefHash = MakeHash(pDef);
|
||||
}
|
||||
|
||||
/******** CLangMngr::CLang *********/
|
||||
|
||||
@ -283,15 +164,14 @@ CLangMngr::CLang::CLang(const char *lang)
|
||||
m_LanguageName[2] = 0;
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry *CLangMngr::CLang::AddEntry(int pKey, uint32_t defHash, const char *def, bool cache)
|
||||
void CLangMngr::CLang::AddEntry(int key, const char *definition)
|
||||
{
|
||||
LangEntry *p = new LangEntry(pKey, defHash, def);
|
||||
defentry &d = m_LookUpTable[key];
|
||||
|
||||
if (d.definition)
|
||||
delete d.definition;
|
||||
|
||||
p->SetCache(cache);
|
||||
|
||||
m_LookUpTable.push_back(p);
|
||||
|
||||
return p;
|
||||
d.definition = new String(definition);
|
||||
}
|
||||
|
||||
CLangMngr::CLang::~CLang()
|
||||
@ -301,99 +181,66 @@ CLangMngr::CLang::~CLang()
|
||||
|
||||
void CLangMngr::CLang::Clear()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_LookUpTable.size(); i++)
|
||||
THash<int, defentry>::iterator iter;
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
if (m_LookUpTable[i])
|
||||
delete m_LookUpTable[i];
|
||||
if (iter->val.definition)
|
||||
{
|
||||
delete iter->val.definition;
|
||||
iter->val.definition = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_LookUpTable.clear();
|
||||
}
|
||||
|
||||
CLangMngr::CLang::LangEntry * CLangMngr::CLang::GetEntry(int pkey)
|
||||
void CLangMngr::CLang::MergeDefinitions(CQueue<sKeyDef> &vec)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < m_LookUpTable.size(); i++)
|
||||
{
|
||||
if (m_LookUpTable[i]->GetKey() == pkey)
|
||||
{
|
||||
return m_LookUpTable[i];
|
||||
}
|
||||
}
|
||||
|
||||
LangEntry *e = new LangEntry(pkey);
|
||||
e->SetKey(pkey);
|
||||
e->SetCache(true);
|
||||
m_LookUpTable.push_back(e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::MergeDefinitions(CQueue<sKeyDef*> &vec)
|
||||
{
|
||||
const char *def = 0;
|
||||
String *pDef;
|
||||
int key = -1;
|
||||
|
||||
while (!vec.empty())
|
||||
{
|
||||
key = vec.front()->key;
|
||||
def = vec.front()->def->c_str();
|
||||
LangEntry *entry = GetEntry(key);
|
||||
key = vec.front().key;
|
||||
pDef = vec.front().definition;
|
||||
|
||||
AddEntry(key, pDef->c_str());
|
||||
|
||||
delete vec.front().definition;
|
||||
|
||||
if (entry->GetDefHash() != MakeHash(def))
|
||||
{
|
||||
if (entry->GetCache())
|
||||
{
|
||||
entry->SetDef(def);
|
||||
entry->SetKey(key);
|
||||
entry->SetCache(false);
|
||||
} else {
|
||||
//AMXXLOG_Log("[AMXX] Language key %s[%s] defined twice", m_LMan->GetKey(key), m_LanguageName);
|
||||
}
|
||||
}
|
||||
|
||||
delete vec.front();
|
||||
vec.pop();
|
||||
}
|
||||
}
|
||||
|
||||
const char * CLangMngr::CLang::GetDef(const char *key, int &status)
|
||||
const char * CLangMngr::CLang::GetDef(int key, int &status)
|
||||
{
|
||||
int ikey = m_LMan->GetKeyEntry(key);
|
||||
|
||||
if (ikey == -1)
|
||||
defentry &def = m_LookUpTable[key];
|
||||
|
||||
if (!def.definition)
|
||||
{
|
||||
status = LANG_STATUS_KLNOTFOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < m_LookUpTable.size(); i++)
|
||||
{
|
||||
if (m_LookUpTable[i]->GetKey() == ikey)
|
||||
return m_LookUpTable[i]->GetDef();
|
||||
}
|
||||
|
||||
status = LANG_STATUS_KLNOTFOUND;
|
||||
return NULL;
|
||||
return def.definition->c_str();
|
||||
}
|
||||
|
||||
struct OffsetPair
|
||||
{
|
||||
uint32_t defOffset;
|
||||
uint32_t keyOffset;
|
||||
};
|
||||
|
||||
// Assumes fp is set to the right position
|
||||
bool CLangMngr::CLang::SaveDefinitions(FILE *fp, uint32_t &curOffset)
|
||||
{
|
||||
unsigned short defLen = 0;
|
||||
String *pdef;
|
||||
String blank;
|
||||
|
||||
for (unsigned int i = 0; i < m_LookUpTable.size(); i++)
|
||||
THash<int, defentry>::iterator iter;
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
defLen = m_LookUpTable[i]->GetDefLength();
|
||||
pdef = iter->val.definition;
|
||||
if (!pdef)
|
||||
pdef = ␣
|
||||
defLen = pdef->size();
|
||||
fwrite((void *)&defLen, sizeof(unsigned short), 1, fp);
|
||||
curOffset += sizeof(unsigned short);
|
||||
fwrite(m_LookUpTable[i]->GetDef(), sizeof(char), defLen, fp);
|
||||
fwrite(pdef->c_str(), sizeof(char), defLen, fp);
|
||||
curOffset += defLen;
|
||||
}
|
||||
|
||||
@ -404,24 +251,26 @@ bool CLangMngr::CLang::SaveDefinitions(FILE *fp, uint32_t &curOffset)
|
||||
bool CLangMngr::CLang::Save(FILE *fp, int &defOffset, uint32_t &curOffset)
|
||||
{
|
||||
uint32_t keynum = 0;
|
||||
uint32_t defhash = 0;
|
||||
uint32_t size = m_LookUpTable.size();
|
||||
String *pdef;
|
||||
String blank;
|
||||
|
||||
fwrite((void*)&size, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
|
||||
for (unsigned int i = 0; i < m_LookUpTable.size(); i++)
|
||||
THash<int, defentry>::iterator iter;
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
keynum = m_LookUpTable[i]->GetKey();
|
||||
defhash = m_LookUpTable[i]->GetDefHash();
|
||||
keynum = iter->key;
|
||||
pdef = iter->val.definition;
|
||||
if (!pdef)
|
||||
pdef = ␣
|
||||
fwrite((void *)&keynum, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
fwrite((void *)&defhash, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
fwrite((void *)&defOffset, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
defOffset += sizeof(short);
|
||||
defOffset += m_LookUpTable[i]->GetDefLength();
|
||||
defOffset += pdef->size();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -443,69 +292,36 @@ CLangMngr::CLangMngr()
|
||||
const char * CLangMngr::GetKey(int key)
|
||||
{
|
||||
if (key < 0 || key >= (int)KeyList.size())
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
return KeyList[key]->key.c_str();
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyHash(int key)
|
||||
{
|
||||
if (key < 0 || key >= (int)KeyList.size())
|
||||
return 0;
|
||||
|
||||
return KeyList[key]->hash;
|
||||
return KeyList[key]->c_str();
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(const char *key)
|
||||
{
|
||||
uint32_t hKey = MakeHash(key, true);
|
||||
uint32_t cmpKey = 0;
|
||||
unsigned int i = 0;
|
||||
keytbl_val val = KeyTable[key];
|
||||
|
||||
if (hKey == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < KeyList.size(); i++)
|
||||
{
|
||||
cmpKey = KeyList[i]->hash;
|
||||
|
||||
if (hKey == cmpKey)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return val.index;
|
||||
}
|
||||
|
||||
int CLangMngr::AddKeyEntry(String &key)
|
||||
{
|
||||
uint32_t hKey = MakeHash(key.c_str(), true);
|
||||
keytbl_val val;
|
||||
val.index = static_cast<int>(KeyList.size());
|
||||
|
||||
keyEntry *e = new keyEntry;
|
||||
e->key.assign(key);
|
||||
e->hash = hKey;
|
||||
KeyList.push_back(e);
|
||||
String *pString = new String(key);
|
||||
KeyList.push_back(pString);
|
||||
|
||||
return (KeyList.size() - 1);
|
||||
KeyTable[key] = val;
|
||||
|
||||
return val.index;
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(String &key)
|
||||
{
|
||||
uint32_t hKey = MakeHash(key.c_str(), true);
|
||||
unsigned int i = 0;
|
||||
keytbl_val val = KeyTable[key];
|
||||
|
||||
for (i = 0; i < KeyList.size(); i++)
|
||||
{
|
||||
if (hKey == KeyList[i]->hash)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return val.index;
|
||||
}
|
||||
|
||||
#define CHECK_PTR(ptr, start, bufsize) if ((ptr) - (start) >= (bufsize)) { \
|
||||
@ -993,7 +809,7 @@ char *CLangMngr::FormatString(const char *fmt, va_list &ap)
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
void CLangMngr::MergeDefinitions(const char *lang, CQueue<sKeyDef*> &tmpVec)
|
||||
void CLangMngr::MergeDefinitions(const char *lang, CQueue<sKeyDef> &tmpVec)
|
||||
{
|
||||
CLang * language = GetLang(lang);
|
||||
if (language)
|
||||
@ -1062,10 +878,10 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
// Allocate enough memory to store everything
|
||||
bool multiline = 0;
|
||||
int pos = 0, line = 0;
|
||||
CQueue<sKeyDef*> Defq;
|
||||
CQueue<sKeyDef> Defq;
|
||||
String buf;
|
||||
char language[3];
|
||||
sKeyDef *tmpEntry = NULL;
|
||||
sKeyDef tmpEntry;
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
@ -1082,9 +898,8 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
if (multiline)
|
||||
{
|
||||
AMXXLOG_Log("New section, multiline unterminated (file \"%s\" line %d)", file, line);
|
||||
if (tmpEntry)
|
||||
delete tmpEntry;
|
||||
tmpEntry = 0;
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
}
|
||||
|
||||
if (!Defq.empty())
|
||||
@ -1102,7 +917,6 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
tmpEntry = new sKeyDef;
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());
|
||||
String def;
|
||||
@ -1112,18 +926,18 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry->key = iKey;
|
||||
tmpEntry->def = new String;
|
||||
tmpEntry->def->assign(def.c_str());
|
||||
tmpEntry->def->trim();
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
tmpEntry.definition->assign(def.c_str());
|
||||
tmpEntry.definition->trim();
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry = 0;
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
} else {
|
||||
pos = buf.find(':');
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
tmpEntry = new sKeyDef;
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());;
|
||||
key.trim();
|
||||
@ -1131,8 +945,8 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry->key = iKey;
|
||||
tmpEntry->def = new String;
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
multiline = true;
|
||||
} else {
|
||||
//user typed a line with no directives
|
||||
@ -1143,10 +957,13 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
if (buf[0] == ':')
|
||||
{
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry = 0;
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
multiline = false;
|
||||
} else {
|
||||
tmpEntry->def->append(buf);
|
||||
if (!tmpEntry.definition)
|
||||
tmpEntry.definition = new String();
|
||||
tmpEntry.definition->append(buf);
|
||||
}
|
||||
} // if !multiline
|
||||
} //if - main
|
||||
@ -1194,16 +1011,30 @@ CLangMngr::CLang * CLangMngr::GetLangR(const char *name)
|
||||
const char *CLangMngr::GetDef(const char *langName, const char *key, int &status)
|
||||
{
|
||||
CLang *lang = GetLangR(langName);
|
||||
if (lang)
|
||||
keytbl_val val = KeyTable[key];
|
||||
if (lang == NULL)
|
||||
{
|
||||
//status = LANG_STATUS_OK;
|
||||
return lang->GetDef(key, status);
|
||||
} else {
|
||||
status = LANG_STATUS_LNOTFOUND;
|
||||
return NULL;
|
||||
} else if (val.index == -1) {
|
||||
status = LANG_STATUS_KLNOTFOUND;
|
||||
return NULL;
|
||||
} else {
|
||||
return lang->GetDef(val.index, status);
|
||||
}
|
||||
}
|
||||
|
||||
void CLangMngr::InvalidateCache()
|
||||
{
|
||||
for (size_t i = 0; i < FileList.size(); i++)
|
||||
{
|
||||
if (FileList[i])
|
||||
delete FileList[i];
|
||||
}
|
||||
|
||||
FileList.clear();
|
||||
}
|
||||
|
||||
bool CLangMngr::Save(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
@ -1217,7 +1048,7 @@ bool CLangMngr::Save(const char *filename)
|
||||
const char *langName = 0;
|
||||
uint32_t curOffset = 0;
|
||||
uint32_t keyNum = KeyList.size();
|
||||
uint32_t ktbSize = KeyList.size() * (sizeof(uint32_t) + sizeof(uint32_t));
|
||||
uint32_t ktbSize = KeyList.size() * sizeof(uint32_t);
|
||||
uint32_t ltbSize = m_Languages.size() * ((sizeof(char)*2) + sizeof(uint32_t));
|
||||
|
||||
fwrite((void *)&magic, sizeof(uint32_t), 1, fp);
|
||||
@ -1237,7 +1068,7 @@ bool CLangMngr::Save(const char *filename)
|
||||
fwrite(langName, sizeof(char), 2, fp);
|
||||
curOffset += sizeof(char) * 2;
|
||||
fwrite((void *)&langOffset, sizeof(uint32_t), 1, fp);
|
||||
langOffset += sizeof(uint32_t) + (m_Languages[i]->Entries() * (sizeof(uint32_t) * 3));
|
||||
langOffset += sizeof(uint32_t) + (m_Languages[i]->Entries() * (sizeof(uint32_t) * 2));
|
||||
curOffset += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
@ -1246,13 +1077,10 @@ bool CLangMngr::Save(const char *filename)
|
||||
uint32_t keyOffset = langOffset;
|
||||
for (unsigned int i = 0; i < KeyList.size(); i++)
|
||||
{
|
||||
keyHash = KeyList[i]->hash;
|
||||
fwrite((void*)&keyHash, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
fwrite((void*)&keyOffset, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
keyOffset += sizeof(char);
|
||||
keyOffset += KeyList[i]->key.size();
|
||||
keyOffset += KeyList[i]->size();
|
||||
}
|
||||
|
||||
//Note - now keyOffset points toward the start of the def table
|
||||
@ -1267,10 +1095,10 @@ bool CLangMngr::Save(const char *filename)
|
||||
unsigned char keyLen = 0;
|
||||
for (unsigned int i = 0; i < KeyList.size(); i++)
|
||||
{
|
||||
keyLen = KeyList[i]->key.size();
|
||||
keyLen = KeyList[i]->size();
|
||||
fwrite((void*)&keyLen, sizeof(unsigned char), 1, fp);
|
||||
curOffset += sizeof(unsigned char);
|
||||
fwrite(KeyList[i]->key.c_str(), sizeof(char), keyLen, fp);
|
||||
fwrite(KeyList[i]->c_str(), sizeof(char), keyLen, fp);
|
||||
curOffset += sizeof(char) * keyLen;
|
||||
}
|
||||
|
||||
@ -1314,6 +1142,19 @@ bool CLangMngr::SaveCache(const char *filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CACHEREAD(expr, type) \
|
||||
if (! (expr==sizeof(type)) ) { \
|
||||
FileList.clear(); \
|
||||
fclose(fp); \
|
||||
return false; \
|
||||
}
|
||||
#define CACHEREAD_S(expr, size) \
|
||||
if (! (expr==size) ) { \
|
||||
FileList.clear(); \
|
||||
fclose(fp); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
bool CLangMngr::LoadCache(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
@ -1326,15 +1167,15 @@ bool CLangMngr::LoadCache(const char *filename)
|
||||
char len = 0;
|
||||
char buf[255];
|
||||
char md5[34];
|
||||
fread((void*)&dictCount, sizeof(short), 1, fp);
|
||||
CACHEREAD(fread((void*)&dictCount, sizeof(short), 1, fp), short);
|
||||
md5Pair *p = 0;
|
||||
|
||||
for (int i = 1; i <= dictCount; i++)
|
||||
{
|
||||
fread((void*)&len, sizeof(char), 1, fp);
|
||||
fread(buf, sizeof(char), len, fp);
|
||||
CACHEREAD(fread((void*)&len, sizeof(char), 1, fp), char);
|
||||
CACHEREAD_S(fread(buf, sizeof(char), len, fp), len);
|
||||
buf[len] = 0;
|
||||
fread(md5, sizeof(char), 32, fp);
|
||||
CACHEREAD_S(fread(md5, sizeof(char), 32, fp), 32);
|
||||
md5[32] = 0;
|
||||
p = new md5Pair;
|
||||
p->file.assign(buf);
|
||||
@ -1348,6 +1189,19 @@ bool CLangMngr::LoadCache(const char *filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DATREAD(expr, type) \
|
||||
if (! (expr==1) ) { \
|
||||
Clear(); \
|
||||
fclose(fp); \
|
||||
return false; \
|
||||
}
|
||||
#define DATREAD_S(expr, size) \
|
||||
if (! (expr==size) ) { \
|
||||
Clear(); \
|
||||
fclose(fp); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
bool CLangMngr::Load(const char *filename)
|
||||
{
|
||||
Clear();
|
||||
@ -1362,75 +1216,93 @@ bool CLangMngr::Load(const char *filename)
|
||||
uint32_t keycount = 0;
|
||||
char version = 0;
|
||||
|
||||
fread((void*)&magic, sizeof(uint32_t), 1, fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long size = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
DATREAD(fread((void*)&magic, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
if (magic != MAGIC_HDR)
|
||||
return false;
|
||||
|
||||
fread((void*)&version, sizeof(char), 1, fp);
|
||||
DATREAD(fread((void*)&version, sizeof(char), 1, fp), char);
|
||||
if (version > FFHL_VERSION || version < FFHL_MIN_VERSION)
|
||||
return false;
|
||||
|
||||
fread((void*)&keycount, sizeof(uint32_t), 1, fp);
|
||||
fread((void*)&langCount, sizeof(uint32_t), 1, fp);
|
||||
DATREAD(fread((void*)&keycount, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
DATREAD(fread((void*)&langCount, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
|
||||
uint32_t *LangOffsets = new uint32_t[langCount];
|
||||
char langname[3];
|
||||
|
||||
for (unsigned int i = 0; i < langCount; i++)
|
||||
{
|
||||
fread(langname, sizeof(char), 2, fp);
|
||||
DATREAD_S(fread(langname, sizeof(char), 2, fp), 2);
|
||||
langname[2] = 0;
|
||||
GetLang(langname); //this will initialize for us
|
||||
fread((void *)&(LangOffsets[i]), sizeof(uint32_t), 1, fp);
|
||||
DATREAD(fread((void *)&(LangOffsets[i]), sizeof(uint32_t), 1, fp), uint32_t);
|
||||
}
|
||||
|
||||
//we should now be at the key table
|
||||
int ktbOffset = ftell(fp);
|
||||
keyEntry *e = 0;
|
||||
unsigned char keylen;
|
||||
char keybuf[255];
|
||||
uint32_t bogus;
|
||||
uint32_t keyoffset, save;
|
||||
String _tmpkey;
|
||||
|
||||
for (unsigned i = 0; i < keycount; i++)
|
||||
{
|
||||
e = new keyEntry;
|
||||
fread((void*)&(e->hash), sizeof(uint32_t), 1, fp);
|
||||
fread((void*)&keyoffset, sizeof(uint32_t), 1, fp);
|
||||
if (version == 4)
|
||||
fread((void*)&(bogus), sizeof(uint32_t), 1, fp);
|
||||
DATREAD(fread((void*)&keyoffset, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
if (keyoffset > size-sizeof(uint32_t))
|
||||
{
|
||||
Clear();
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
save = ftell(fp);
|
||||
fseek(fp, keyoffset, SEEK_SET);
|
||||
fread((void*)&keylen, sizeof(char), 1, fp);
|
||||
char *data = new char[keylen + 1];
|
||||
fread(data, sizeof(char), keylen, fp);
|
||||
data[keylen] = 0;
|
||||
e->key.assign(data);
|
||||
delete [] data;
|
||||
KeyList.push_back(e);
|
||||
DATREAD(fread((void*)&keylen, sizeof(char), 1, fp), char);
|
||||
DATREAD_S(fread(keybuf, sizeof(char), keylen, fp), keylen);
|
||||
keybuf[keylen] = 0;
|
||||
_tmpkey.assign(keybuf);
|
||||
AddKeyEntry(_tmpkey);
|
||||
fseek(fp, save, SEEK_SET); //bring back to next key
|
||||
}
|
||||
|
||||
//we should now be at the languages table
|
||||
uint32_t numentries;
|
||||
uint32_t keynum;
|
||||
uint32_t defhash;
|
||||
uint32_t defoffset;
|
||||
unsigned short deflen;
|
||||
char valbuf[4096];
|
||||
|
||||
for (unsigned int i = 0; i < langCount; i++)
|
||||
{
|
||||
fread((void*)&numentries, sizeof(uint32_t), 1, fp);
|
||||
DATREAD(fread((void*)&numentries, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
|
||||
for (unsigned int j = 0; j < numentries; j++)
|
||||
{
|
||||
fread((void *)&keynum, sizeof(uint32_t), 1, fp);
|
||||
fread((void *)&defhash, sizeof(uint32_t), 1, fp);
|
||||
fread((void *)&defoffset, sizeof(uint32_t), 1, fp);
|
||||
DATREAD(fread((void *)&keynum, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
if (version == 4)
|
||||
{
|
||||
DATREAD(fread((void *)&bogus, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
}
|
||||
DATREAD(fread((void *)&defoffset, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
if (defoffset > size-sizeof(uint32_t))
|
||||
{
|
||||
Clear();
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
save = ftell(fp);
|
||||
fseek(fp, defoffset, SEEK_SET);
|
||||
fread((void *)&deflen, sizeof(unsigned short), 1, fp);
|
||||
char *data = new char[deflen + 1];
|
||||
fread(data, sizeof(char), deflen, fp);
|
||||
data[deflen] = 0;
|
||||
m_Languages[i]->AddEntry(keynum, defhash, data, true);
|
||||
delete [] data;
|
||||
DATREAD(fread((void *)&deflen, sizeof(unsigned short), 1, fp), short);
|
||||
//:TODO: possible string overflow here.
|
||||
DATREAD_S(fread(valbuf, sizeof(char), deflen, fp), deflen);
|
||||
valbuf[deflen] = 0;
|
||||
m_Languages[i]->AddEntry(keynum, valbuf);
|
||||
fseek(fp, save, SEEK_SET); //bring back to next entry
|
||||
}
|
||||
}
|
||||
@ -1451,6 +1323,8 @@ CLangMngr::~CLangMngr()
|
||||
void CLangMngr::Clear()
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
KeyTable.clear();
|
||||
|
||||
for (i = 0; i < m_Languages.size(); i++)
|
||||
{
|
||||
|
Reference in New Issue
Block a user