committed new language code
This commit is contained in:
parent
555ac1c7f3
commit
ccaa4434ad
@ -47,41 +47,6 @@
|
||||
#define INSERT_STRING 3
|
||||
#define INSERT_NEWLINE 4
|
||||
|
||||
// dictionary format is Fast-Format-Hash-Lookup, v6
|
||||
#define MAGIC_HDR 0x4646484C
|
||||
#define FFHL_VERSION 6
|
||||
#define FFHL_MIN_VERSION 6
|
||||
|
||||
/*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)
|
||||
* 5 (BAILOPAN) - Removed hash storage
|
||||
* 6 (BAILOPAN) - Arbitrary bump to force reparse.
|
||||
FORMAT:
|
||||
Magic 4bytes
|
||||
Version 1byte
|
||||
Number of Keys 4bytes
|
||||
Number of Languages 4bytes
|
||||
LANG INFO TABLE[]
|
||||
Language Name 2bytes
|
||||
Offset 4bytes
|
||||
KEY TABLE[]
|
||||
Key Lookup Offset 4bytes
|
||||
LANGUAGES TABLE[]
|
||||
Language[]
|
||||
Definitions 4bytes
|
||||
Key # 4bytes (0-index into key table)
|
||||
Def Offset 4bytes
|
||||
KEY LOOKUP TABLE[]
|
||||
Key length 1byte
|
||||
Key string variable
|
||||
DEF LOOKUP TABLE[]
|
||||
Def length 2bytes
|
||||
Def string variable
|
||||
*/
|
||||
|
||||
template<>
|
||||
int Compare<String>(const String &k1, const String &k2)
|
||||
{
|
||||
@ -249,76 +214,11 @@ const char * CLangMngr::CLang::GetDef(int key, int &status)
|
||||
return def.definition->c_str();
|
||||
}
|
||||
|
||||
// Assumes fp is set to the right position
|
||||
bool CLangMngr::CLang::SaveDefinitions(FILE *fp, uint32_t &curOffset)
|
||||
{
|
||||
unsigned short defLen = 0;
|
||||
String *pdef;
|
||||
|
||||
THash<int, defentry>::iterator iter;
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
pdef = iter->val.definition;
|
||||
if (!pdef)
|
||||
continue;
|
||||
defLen = pdef->size();
|
||||
fwrite((void *)&defLen, sizeof(unsigned short), 1, fp);
|
||||
curOffset += sizeof(unsigned short);
|
||||
fwrite(pdef->c_str(), sizeof(char), defLen, fp);
|
||||
curOffset += defLen;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CLangMngr::CLang::Entries()
|
||||
{
|
||||
return m_entries;
|
||||
}
|
||||
|
||||
// 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 size = 0;
|
||||
String *pdef;
|
||||
|
||||
//:TODO: remove this loop and assertion, use m_entries for size
|
||||
THash<int, defentry>::iterator iter;
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
if (iter->val.definition)
|
||||
size++;
|
||||
}
|
||||
|
||||
assert(size == m_entries);
|
||||
|
||||
fwrite((void*)&size, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
|
||||
for (iter=m_LookUpTable.begin(); iter!=m_LookUpTable.end(); iter++)
|
||||
{
|
||||
keynum = iter->key;
|
||||
pdef = iter->val.definition;
|
||||
if (!pdef)
|
||||
continue;
|
||||
fwrite((void *)&keynum, 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 += pdef->size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// assumes fp is set to the right position
|
||||
bool CLangMngr::CLang::Load(FILE *fp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/******** CLangMngr *********/
|
||||
|
||||
inline String &make_string(const char *str)
|
||||
@ -381,35 +281,6 @@ char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len)
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
const char *CLangMngr::Format(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
const char *retVal = FormatString(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#undef CHECK_PTR
|
||||
#undef CHECK_OUTPR
|
||||
#undef ZEROTERM
|
||||
#undef NEXT_PARAM
|
||||
|
||||
#define CHECK_PTR(ptr, start, bufsize) if ((ptr) - (start) >= (bufsize)) { \
|
||||
AMXXLOG_Log("[AMXX] Buffer overflow in formatting"); \
|
||||
outbuf[0] = 0; \
|
||||
return outbuf; }
|
||||
#define CHECK_OUTPTR(offset) CHECK_PTR(outptr+offset, outbuf, sizeof(outbuf))
|
||||
#define ZEROTERM(buf) buf[(sizeof(buf)/sizeof(buf[0]))-1]=0;
|
||||
#define NEXT_PARAM()
|
||||
|
||||
//this is not implemented....
|
||||
char *CLangMngr::FormatString(const char *fmt, va_list &ap)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void CLangMngr::MergeDefinitions(const char *lang, CQueue<sKeyDef> &tmpVec)
|
||||
{
|
||||
CLang * language = GetLang(lang);
|
||||
@ -638,294 +509,6 @@ void CLangMngr::InvalidateCache()
|
||||
FileList.clear();
|
||||
}
|
||||
|
||||
bool CLangMngr::Save(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
uint32_t magic = MAGIC_HDR;
|
||||
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);
|
||||
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);
|
||||
|
||||
curOffset += sizeof(uint32_t);
|
||||
curOffset += sizeof(unsigned char);
|
||||
curOffset += sizeof(uint32_t);
|
||||
curOffset += sizeof(uint32_t);
|
||||
|
||||
uint32_t langOffset = curOffset + ktbSize + ltbSize;
|
||||
for (unsigned int i = 0; i < m_Languages.size(); i++)
|
||||
{
|
||||
langName = m_Languages[i]->GetName();
|
||||
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) * 2));
|
||||
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; i < KeyList.size(); i++)
|
||||
{
|
||||
fwrite((void*)&keyOffset, sizeof(uint32_t), 1, fp);
|
||||
curOffset += sizeof(uint32_t);
|
||||
keyOffset += sizeof(char);
|
||||
keyOffset += KeyList[i]->size();
|
||||
}
|
||||
|
||||
//Note - now keyOffset points toward the start of the def table
|
||||
int defOffset = keyOffset;
|
||||
for (unsigned int i = 0; i < m_Languages.size(); i++)
|
||||
{
|
||||
m_Languages[i]->Save(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; i < KeyList.size(); i++)
|
||||
{
|
||||
keyLen = KeyList[i]->size();
|
||||
fwrite((void*)&keyLen, sizeof(unsigned char), 1, fp);
|
||||
curOffset += sizeof(unsigned char);
|
||||
fwrite(KeyList[i]->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; i < m_Languages.size(); i++)
|
||||
{
|
||||
m_Languages[i]->SaveDefinitions(fp, curOffset);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
//done!
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLangMngr::SaveCache(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
if (!fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CVector<md5Pair *>::iterator i;
|
||||
short dictCount = FileList.size();
|
||||
char len = 0;
|
||||
|
||||
fwrite((void *)&dictCount, sizeof(short), 1, fp);
|
||||
|
||||
for (i = FileList.begin(); i != FileList.end(); i++)
|
||||
{
|
||||
len = (*i)->file.size();
|
||||
fwrite((void *)&len, sizeof(char), 1, fp);
|
||||
fwrite((*i)->file.c_str(), sizeof(char), len, fp);
|
||||
fwrite((*i)->val.c_str(), sizeof(char), 32, fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CACHEREAD(expr, type) \
|
||||
if (! (expr==1) ) { \
|
||||
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");
|
||||
if (!fp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SetUnhandledExceptionFilter(NULL);
|
||||
|
||||
short dictCount = 0;
|
||||
char len = 0;
|
||||
char buf[255];
|
||||
char md5[34];
|
||||
CACHEREAD(fread((void*)&dictCount, sizeof(short), 1, fp), short);
|
||||
md5Pair *p = 0;
|
||||
|
||||
for (int i = 1; i <= dictCount; i++)
|
||||
{
|
||||
CACHEREAD(fread((void*)&len, sizeof(char), 1, fp), char);
|
||||
CACHEREAD_S(fread(buf, sizeof(char), len, fp), len);
|
||||
buf[len] = 0;
|
||||
CACHEREAD_S(fread(md5, sizeof(char), 32, fp), 32);
|
||||
md5[32] = 0;
|
||||
p = new md5Pair;
|
||||
p->file.assign(buf);
|
||||
p->val.assign(md5);
|
||||
FileList.push_back(p);
|
||||
p = 0;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
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();
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
uint32_t magic = 0;
|
||||
uint32_t langCount = 0;
|
||||
uint32_t keycount = 0;
|
||||
char version = 0;
|
||||
|
||||
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;
|
||||
|
||||
DATREAD(fread((void*)&version, sizeof(char), 1, fp), char);
|
||||
if (version > FFHL_VERSION || version < FFHL_MIN_VERSION)
|
||||
return false;
|
||||
|
||||
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++)
|
||||
{
|
||||
DATREAD_S(fread(langname, sizeof(char), 2, fp), 2);
|
||||
langname[2] = 0;
|
||||
GetLang(langname); //this will initialize for us
|
||||
DATREAD(fread((void *)&(LangOffsets[i]), sizeof(uint32_t), 1, fp), uint32_t);
|
||||
}
|
||||
|
||||
//we should now be at the key table
|
||||
int ktbOffset = ftell(fp);
|
||||
unsigned char keylen;
|
||||
char keybuf[255];
|
||||
uint32_t bogus;
|
||||
uint32_t keyoffset, save;
|
||||
String _tmpkey;
|
||||
|
||||
for (unsigned i = 0; i < keycount; i++)
|
||||
{
|
||||
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);
|
||||
DATREAD(fread((void*)&keylen, sizeof(char), 1, fp), char);
|
||||
//technically this isn't possible since
|
||||
// a char will never be more than 255
|
||||
// but it's good practice.
|
||||
if (keylen > sizeof(keybuf))
|
||||
return false;
|
||||
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 defoffset;
|
||||
unsigned short deflen;
|
||||
char valbuf[4096];
|
||||
|
||||
for (unsigned int i = 0; i < langCount; i++)
|
||||
{
|
||||
DATREAD(fread((void*)&numentries, sizeof(uint32_t), 1, fp), uint32_t);
|
||||
|
||||
for (unsigned int j = 0; j < numentries; j++)
|
||||
{
|
||||
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);
|
||||
DATREAD(fread((void *)&deflen, sizeof(unsigned short), 1, fp), short);
|
||||
if (deflen > sizeof(valbuf))
|
||||
return false;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
delete [] LangOffsets;
|
||||
|
||||
//we're done!
|
||||
return true;
|
||||
}
|
||||
|
||||
CLangMngr::~CLangMngr()
|
||||
{
|
||||
Clear();
|
||||
|
@ -111,11 +111,6 @@ class CLangMngr
|
||||
|
||||
// Get language name
|
||||
const char *GetName() { return m_LanguageName; }
|
||||
// Save to file
|
||||
bool Save(FILE *fp, int &defOffset, uint32_t &curOffset);
|
||||
bool SaveDefinitions(FILE *fp, uint32_t &curOffset);
|
||||
// Load
|
||||
bool Load(FILE *fp);
|
||||
void SetMngr(CLangMngr *l) { m_LMan = l; }
|
||||
// Get number of entries
|
||||
int Entries();
|
||||
@ -159,18 +154,8 @@ public:
|
||||
int MergeDefinitionFile(const char *file);
|
||||
// Get a definition from a lang name and a key
|
||||
const char *GetDef(const char *langName, const char *key, int &status);
|
||||
// Format a string
|
||||
const char *Format(const char *src, ...);
|
||||
// Format a string for an AMX plugin
|
||||
char *FormatAmxString(AMX *amx, cell *params, int parm, int &len);
|
||||
char *FormatString(const char *fmt, va_list &ap);
|
||||
// Save
|
||||
bool Save(const char *filename);
|
||||
// Load
|
||||
bool Load(const char *filename);
|
||||
// Cache
|
||||
bool LoadCache(const char *filename);
|
||||
bool SaveCache(const char *filename);
|
||||
void InvalidateCache();
|
||||
// Get index
|
||||
int GetKeyEntry(String &key);
|
||||
|
@ -244,15 +244,6 @@ int C_Spawn(edict_t *pent)
|
||||
// ###### Initialize task manager
|
||||
g_tasksMngr.registerTimers(&gpGlobals->time, &mp_timelimit->value, &g_game_timeleft);
|
||||
|
||||
// ###### Load lang
|
||||
char file[256];
|
||||
if (!g_langMngr.Load(build_pathname_r(file, sizeof(file) - 1, "%s/languages.dat", get_localinfo("amxmodx_datadir", "addons/amxmodx/data"))))
|
||||
{
|
||||
g_langMngr.InvalidateCache();
|
||||
} else {
|
||||
g_langMngr.LoadCache(build_pathname_r(file, sizeof(file) - 1, "%s/dictionary.cache", get_localinfo("amxx_datadir", "addons/amxmodx/data")));
|
||||
}
|
||||
|
||||
// ###### Initialize commands prefixes
|
||||
g_commands.registerPrefix("amx");
|
||||
g_commands.registerPrefix("amxx");
|
||||
@ -279,6 +270,7 @@ int C_Spawn(edict_t *pent)
|
||||
CVAR_SET_STRING(init_amxmodx_modules.name, buffer);
|
||||
|
||||
// ###### Load Vault
|
||||
char file[255];
|
||||
g_vault.setSource(build_pathname_r(file, sizeof(file) - 1, "%s", get_localinfo("amxx_vault", "addons/amxmodx/configs/vault.ini")));
|
||||
g_vault.loadVault();
|
||||
|
||||
@ -449,11 +441,6 @@ void C_ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
executeForwards(FF_PluginInit);
|
||||
executeForwards(FF_PluginCfg);
|
||||
|
||||
// ###### Save lang
|
||||
char file[256];
|
||||
g_langMngr.Save(build_pathname_r(file, sizeof(file) - 1, "%s/languages.dat", get_localinfo("amxx_datadir", "addons/amxmodx/data")));
|
||||
g_langMngr.SaveCache(build_pathname_r(file, sizeof(file) - 1, "%s/dictionary.cache", get_localinfo("amxx_datadir", "addons/amxmodx/data")));
|
||||
|
||||
// Correct time in Counter-Strike and other mods (except DOD)
|
||||
if (!g_bmod_dod)
|
||||
g_game_timeleft = 0;
|
||||
@ -524,12 +511,6 @@ void C_ServerDeactivate_Post()
|
||||
g_plugins.clear();
|
||||
ClearPluginLibraries();
|
||||
|
||||
char file[256];
|
||||
|
||||
g_langMngr.Save(build_pathname_r(file, sizeof(file) - 1, "%s/languages.dat", get_localinfo("amxx_datadir", "addons/amxmodx/data")));
|
||||
g_langMngr.SaveCache(build_pathname_r(file, sizeof(file) - 1, "%s/dictionary.cache", get_localinfo("amxx_datadir", "addons/amxmodx/data")));
|
||||
g_langMngr.Clear();
|
||||
|
||||
for (unsigned int i=0; i<g_hudsync.size(); i++)
|
||||
delete [] g_hudsync[i];
|
||||
g_hudsync.clear();
|
||||
@ -1316,6 +1297,7 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
||||
g_xvars.clear();
|
||||
g_plugins.clear();
|
||||
g_cvars.clear();
|
||||
g_langMngr.Clear();
|
||||
|
||||
detachModules();
|
||||
|
||||
|
@ -1503,12 +1503,7 @@ edict_t* MNF_GetPlayerEdict(int id)
|
||||
|
||||
const char *MNF_Format(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
const char *retVal = g_langMngr.FormatString(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return retVal;
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *MNF_GetPlayerTeam(int id)
|
||||
|
Loading…
Reference in New Issue
Block a user