fixed bcompat trans + optimized it a bit

added bcompat trans support to format() and copy()
This commit is contained in:
David Anderson 2006-09-10 22:08:52 +00:00
parent 3d74b7cf09
commit 2df8b4269e
4 changed files with 116 additions and 74 deletions

View File

@ -2,52 +2,28 @@
#include "amxmod_compat.h"
#include "format.h"
struct translate_result
bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang)
{
int suki;
int dest;
int lang;
};
key = (trans & BCOMPAT_TRANSLATE_KEYMASK);
dest = (trans >> BCOMPAT_TRANSLATE_DESTRSH) & BCOMPAT_TRANSLATE_DESTMASK;
lang = (trans >> BCOMPAT_TRANSLATE_LANGRSH) & BCOMPAT_TRANSLATE_LANGMASK;
CVector<translate_result *> g_tr_results;
CStack<size_t> g_old_ids;
bool GetTranslation(int id, int &key, int &dest, int &lang)
if (dest == 0x3F)
{
if (id < 0 || (unsigned int)id > g_tr_results.size())
{
return false;
dest = -1;
}
translate_result *pRes = g_tr_results[id];
key = pRes->suki;
dest = pRes->dest;
lang = pRes->lang;
g_old_ids.push((size_t)id);
if (lang == 0x1F)
{
lang = -1;
}
return true;
}
void ClearTransCache()
{
for (size_t i=0; i<g_tr_results.size(); i++)
{
delete g_tr_results[i];
}
g_tr_results.clear();
while (!g_old_ids.empty())
{
g_old_ids.pop();
}
}
bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def)
{
unsigned int trans = static_cast<unsigned int>(*source);
trans &= ~BCOMPAT_TRANSLATE_BITS;
amxtrans_t trans = static_cast<amxtrans_t>(*source);
int key, _dest, lang;
if (!GetTranslation(trans, key, _dest, lang))
{
@ -95,36 +71,41 @@ static cell AMX_NATIVE_CALL amx_translate(AMX *amx, cell *params)
int len;
char *key = get_amxstring(amx, params[1], 0, len);
translate_result *pRes;
size_t id;
if (g_old_ids.empty())
amxtrans_t trans;
int suki = g_langMngr.GetKeyEntry(key);
//Some AMX Mod plugins do not register everything they need. Prevent a crash.
if (suki == -1)
{
pRes = new translate_result;
id = g_tr_results.size();
g_tr_results.push_back(pRes);
} else {
if (g_tr_results.size() >= BCOMPAT_TRANSLATE_MAX)
suki = g_langMngr.AddKeyEntry(key);
}
if (suki > BCOMPAT_TRANSLATE_KEYMASK)
{
LogError(amx, AMX_ERR_NATIVE, "Exceeded bcompat translation limit of %d!", BCOMPAT_TRANSLATE_MAX);
LogError(amx, AMX_ERR_NATIVE, "Not enough translation space, aborting!");
return 0;
}
id = g_old_ids.front();
g_old_ids.pop();
pRes = g_tr_results[id];
}
pRes->suki = g_langMngr.GetKeyEntry(key);
//Some AMX Mod plugins do not register everything they need. Prevent a crash.
if (pRes->suki == -1)
trans = suki & BCOMPAT_TRANSLATE_KEYMASK;
int dest = static_cast<int>(params[2]);
int lang = static_cast<int>(params[3]);
if (dest == -1)
{
pRes->suki = g_langMngr.AddKeyEntry(key);
trans |= (0x3F << BCOMPAT_TRANSLATE_DESTRSH);
} else {
trans |= (dest & BCOMPAT_TRANSLATE_DESTMASK) << BCOMPAT_TRANSLATE_DESTRSH;
}
pRes->dest = params[2];
pRes->lang = params[3];
if (lang == -1)
{
trans |= (0x1F << BCOMPAT_TRANSLATE_LANGRSH);
} else {
trans |= (lang & BCOMPAT_TRANSLATE_LANGMASK) << BCOMPAT_TRANSLATE_LANGRSH;
}
return (cell)((unsigned int)BCOMPAT_TRANSLATE_BITS | (unsigned int)id);
trans |= BCOMPAT_TRANSLATE_BITS;
return static_cast<cell>(trans);
}
AMX_NATIVE_INFO g_BcompatNatives[] =

View File

@ -1,11 +1,27 @@
#ifndef _INCLUDE_AMXMOD_CORE_COMPAT_H
#define _INCLUDE_AMXMOD_CORE_COMPAT_H
#define BCOMPAT_TRANSLATE_BITS 0xFFFFF400
#define BCOMPAT_TRANSLATE_MAX 0x400
/**
* New format for translation:
* Note that we only support:
* 4k keys
* 32 languages
* 0000 0000 0000 0000 0000 0000 0000 0000
* | key id |
* | | <- dest id
* | | <- lang id
*/
bool GetTranslation(int id, int &key, int &dest, int &lang);
void ClearTransCache();
#define BCOMPAT_TRANSLATE_BITS 0xFF000000
#define BCOMPAT_TRANSLATE_KEYMASK 0xFFF
#define BCOMPAT_TRANSLATE_DESTMASK 0x3F
#define BCOMPAT_TRANSLATE_DESTRSH 12
#define BCOMPAT_TRANSLATE_LANGMASK 0x1F
#define BCOMPAT_TRANSLATE_LANGRSH 18
typedef unsigned int amxtrans_t;
bool GetTranslation(amxtrans_t trans, int &key, int &dest, int &lang);
extern AMX_NATIVE_INFO g_BcompatNatives[];

View File

@ -628,7 +628,6 @@ void C_ServerDeactivate_Post()
g_xvars.clear();
g_plugins.clear();
ClearPluginLibraries();
ClearTransCache();
modules_callPluginsUnloaded();
ClearMessages();

View File

@ -443,16 +443,43 @@ static cell AMX_NATIVE_CALL add(AMX *amx, cell *params) /* 4 param */
static cell AMX_NATIVE_CALL copy(AMX *amx, cell *params) /* 4 param */
{
cell *src = get_amxaddr(amx, params[3]);
cell *dest = get_amxaddr(amx, params[1]);
cell *start = dest;
int c = params[2];
if (amx->flags & AMX_FLAG_OLDFILE)
{
if (*src & BCOMPAT_TRANSLATE_BITS)
{
const char *key, *def;
if (!translate_bcompat(amx, src, &key, &def))
{
goto normal_string;
}
cell *dest = get_amxaddr(amx, params[1]);
cell *start = dest;
while (c-- && *def)
{
*dest++ = static_cast<cell>(*def++);
}
*dest = '\0';
return dest-start;
} else {
goto normal_string;
}
} else {
normal_string:
cell *dest = get_amxaddr(amx, params[1]);
cell *start = dest;
while (c-- && *src)
{
*dest++ = *src++;
*dest = 0;
}
*dest = '\0';
return (dest - start);
}
}
static cell AMX_NATIVE_CALL copyc(AMX *amx, cell *params) /* 4 param */
{
@ -568,7 +595,26 @@ static cell AMX_NATIVE_CALL format(AMX *amx, cell *params) /* 3 param */
if (copy)
buf = g_cpbuf;
int param = 4;
size_t total = atcprintf(buf, maxlen, fmt, amx, params, &param);
size_t total = 0;
if (amx->flags & AMX_FLAG_OLDFILE)
{
if (*fmt & BCOMPAT_TRANSLATE_BITS)
{
const char *key, *def;
if (!translate_bcompat(amx, fmt, &key, &def))
{
goto normal_string;
}
total = atcprintf(buf, maxlen, def, amx, params, &param);
} else {
goto normal_string;
}
} else {
normal_string:
total = atcprintf(buf, maxlen, fmt, amx, params, &param);
}
if (copy)
{
/* copy back */