diff --git a/amxmodx/CLang.cpp b/amxmodx/CLang.cpp index aefec03a..f6f067f6 100755 --- a/amxmodx/CLang.cpp +++ b/amxmodx/CLang.cpp @@ -57,29 +57,36 @@ void qdbg(const char *s, ...) // dictionary format is Fast-Format-Hash-Lookup, v4 #define MAGIC_HDR 0x4646484C #define FFHL_VERSION 4 +#define FFHL_MIN_VERSION 4 -/* +/*version history: + * 1 (BAILOPAN) - Simplest form possible, no reverse + * 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) FORMAT: -Magic 4bytes -Version 1byte +Magic 4bytes +Version 1byte +Number of Keys 4bytes Number of Languages 4bytes LANG INFO TABLE[] Language Name 2bytes - Offset 4bytes + Offset 4bytes KEY TABLE[] - Key Hash 4bytes + Key Hash 4bytes Key Lookup Offset 4bytes LANGUAGES TABLE[] Language[] - Key Hash # 4bytes (virtual # in hash table, 0 indexed) - Def Hash 4bytes - Def Offset 4bytes + Definitions 4bytes + Key Hash # 4bytes (virtual # in hash table, 0 indexed) + Def Hash 4bytes + Def Offset 4bytes KEY LOOKUP TABLE[] - Key length 1byte - Key string variable + Key length 1byte + Key string variable DEF LOOKUP TABLE[] - Def length 2bytes - Def string variable + Def length 2bytes + Def string variable */ /******** CRC & Strip *********/ @@ -199,6 +206,11 @@ 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; @@ -229,6 +241,15 @@ CLangMngr::CLang::LangEntry::LangEntry(const LangEntry &other) SetDef(other.m_pDef.c_str()); } +CLangMngr::CLang::LangEntry::LangEntry(int pKey, uint32_t defHash, const char *pDef) +{ + Clear(); + key = pKey; + this-> + m_DefHash = defHash; + m_pDef.assign(pDef); +} + void CLangMngr::CLang::LangEntry::Clear() { m_pDef.clear(); @@ -260,6 +281,15 @@ CLangMngr::CLang::CLang(const char *lang) m_LanguageName[2]=0; } +CLangMngr::CLang::LangEntry *CLangMngr::CLang::AddEntry(int pKey, uint32_t defHash, const char *def) +{ + LangEntry *p = new LangEntry(pKey, defHash, def); + + m_LookUpTable.push_back(p); + + return p; +} + CLangMngr::CLang::~CLang() { Clear(); @@ -332,10 +362,49 @@ struct OffsetPair uint32_t defOffset; uint32_t keyOffset; }; + // Assumes fp is set to the right position -bool CLangMngr::CLang::Save(FILE *fp) +bool CLangMngr::CLang::SaveDefinitions(FILE *fp, uint32_t &curOffset) { - return false; + unsigned short defLen = 0; + for (unsigned int i = 0; iGetDefLength(); + fwrite((void *)&defLen, sizeof(unsigned short), 1, fp); + curOffset += sizeof(unsigned short); + fwrite(m_LookUpTable[i]->GetDef(), sizeof(char), defLen, fp); + curOffset += defLen; + } + + return true; +} + +// Assumes fp is set to the right position +bool CLangMngr::CLang::Save(FILE *fp, int &defOffset, uint32_t &curOffset) +{ + uint32_t keynum = 0; + uint32_t defhash = 0; + uint32_t defoff = defOffset; + uint32_t size = m_LookUpTable.size(); + + fwrite((void*)&size, sizeof(uint32_t), 1, fp); + curOffset += sizeof(uint32_t); + + for (unsigned int i = 0; iGetKey(); + defhash = m_LookUpTable[i]->GetDefHash(); + 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 *)&defoff, sizeof(uint32_t), 1, fp); + curOffset += sizeof(uint32_t); + defOffset += sizeof(short); + defOffset += m_LookUpTable[i]->GetDefLength(); + } + + return true; } // assumes fp is set to the right position @@ -888,7 +957,7 @@ const char *CLangMngr::GetDef(const char *langName, const char *key) bool CLangMngr::Save(const char *filename) { - /*FILE *fp = fopen(filename, "wb"); + FILE *fp = fopen(filename, "wb"); if (!fp) return false; @@ -897,19 +966,76 @@ bool CLangMngr::Save(const char *filename) unsigned char version = FFHL_VERSION; uint32_t langNum = m_Languages.size(); 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 ltbSize = m_Languages.size() * ((sizeof(char)*2) + sizeof(uint32_t)); fwrite((void *)&magic, sizeof(uint32_t), 1, fp); fwrite((void *)&version, sizeof(unsigned char), 1, fp); + fwrite((void *)&keyNum, sizeof(uint32_t), 1, fp); fwrite((void *)&langNum, sizeof(uint32_t), 1, fp); - LangVecIter iter; - for (iter = m_Languages.begin(); iter!=m_Languages.end(); iter++) - { - langName = (*iter)->GetName(); - fwrite(langName, sizeof(char), 2, fp); + curOffset += sizeof(uint32_t); + curOffset += sizeof(unsigned char); + curOffset += sizeof(uint32_t); + curOffset += sizeof(uint32_t); - }*/ - return false; + uint32_t langOffset = curOffset + ktbSize + ltbSize; + for (unsigned int i = 0; iGetName(); + 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)); + curOffset += sizeof(uint32_t); + } + + //Note - langOffset now points to the start of key lookup table + uint32_t keyHash = 0; + uint32_t keyOffset = langOffset; + for (unsigned int i = 0; ihash; + 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(); + } + + //Note - now keyOffset points toward the start of the def table + int defOffset = keyOffset; + for (unsigned int i = 0; iSave(fp, defOffset, curOffset); + } + + //Now, defOffset points toward the END of the file + //curoffset should point toward the key table, so... + unsigned char keyLen = 0; + for (unsigned int i = 0; ikey.size(); + fwrite((void*)&keyLen, sizeof(unsigned char), 1, fp); + curOffset += sizeof(unsigned char); + fwrite(KeyList[i]->key.c_str(), sizeof(char), keyLen, fp); + curOffset += sizeof(char) * keyLen; + } + + //Finally, write the def table + // It's assumed no orders changed... + for (unsigned int i = 0; iSaveDefinitions(fp, curOffset); + } + + fclose(fp); + + //done! + return true; } bool CLangMngr::SaveCache(const char *filename) @@ -978,6 +1104,87 @@ bool CLangMngr::Load(const char *filename) { Clear(); + FILE *fp = fopen(filename, "rb"); + + if (!fp) + return false; + + uint32_t magic = 0; + uint32_t langCount = 0; + uint32_t keycount = 0; + char version = 0; + + fread((void*)&magic, sizeof(uint32_t), 1, fp); + if (magic != MAGIC_HDR) + return false; + + fread((void*)&version, sizeof(char), 1, fp); + if (version > FFHL_VERSION || version < FFHL_MIN_VERSION) + return false; + + fread((void*)&langCount, sizeof(uint32_t), 1, fp); + + uint32_t *LangOffsets = new uint32_t[langCount]; + char langname[3]; + for (unsigned int i=0; ihash), sizeof(uint32_t), 1, fp); + fread((void*)&keyoffset, sizeof(uint32_t), 1, fp); + 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); + 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; + for (unsigned int i=0; iAddEntry(keynum, defhash, data); + delete [] data; + fseek(fp, save, SEEK_SET); //bring back to next entry + } + } + + fclose(fp); + + //we're done! return true; } diff --git a/amxmodx/CLang.h b/amxmodx/CLang.h index 177c83f7..2da4df5c 100755 --- a/amxmodx/CLang.h +++ b/amxmodx/CLang.h @@ -73,9 +73,11 @@ class CLangMngr return strcmp(left.m_LanguageName, right)==0 ? true : false; } const char *GetName() { return m_LanguageName; } - bool Save(FILE *fp); + bool Save(FILE *fp, int &defOffset, uint32_t &curOffset); + bool SaveDefinitions(FILE *fp, uint32_t &curOffset); bool Load(FILE *fp); void SetMngr(CLangMngr *l) { lman = l; } + int Entries() { return m_LookUpTable.size(); } private: static uint32_t MakeHash(const char *src, bool makeLower = false); @@ -92,11 +94,13 @@ class CLangMngr int GetKey(); const char *GetDef(); + int GetDefLength(); LangEntry(); LangEntry(int key); LangEntry(int key, const char *pDef); LangEntry(const LangEntry &other); + LangEntry(int pKey, uint32_t defHash, const char *pDef); void Clear(); }; @@ -109,6 +113,8 @@ class CLangMngr LookUpVec m_LookUpTable; CLangMngr *lman; + public: + LangEntry *AddEntry(int pKey, uint32_t defHash, const char *def); }; void MergeDefinitions(const char *lang, CQueue &tmpVec);