More AMTL conversion - 🔥 CString and CVector
This commit is contained in:
@@ -11,8 +11,7 @@
|
||||
#include "amxmodx.h"
|
||||
#include "CLang.h"
|
||||
#include "format.h"
|
||||
|
||||
CVector<FILE *> FileList;
|
||||
#include "ITextParsers.h"
|
||||
|
||||
#define LITIDX_NONE 0
|
||||
#define LITIDX_BRACKET 1
|
||||
@@ -24,24 +23,29 @@ CVector<FILE *> FileList;
|
||||
#define INSERT_NEWLINE 4
|
||||
|
||||
template<>
|
||||
int Compare<String>(const String &k1, const String &k2)
|
||||
int Compare<ke::AString>(const ke::AString &k1, const ke::AString &k2)
|
||||
{
|
||||
return k1.compare(k2.c_str());
|
||||
return k1.compare(k2.chars());
|
||||
}
|
||||
|
||||
template<>
|
||||
int CompareAlt<char const *, String>(char const * const &k1, String const &k2)
|
||||
int CompareAlt<char const *, ke::AString>(char const * const &k1, ke::AString const &k2)
|
||||
{
|
||||
return strcmp(k1, k2.c_str());
|
||||
return strcmp(k1, k2.chars());
|
||||
}
|
||||
template<>
|
||||
int CompareAlt<ke::AString, ke::AString>(ke::AString const &k1, ke::AString const &k2)
|
||||
{
|
||||
return strcmp(k1.chars(), k2.chars());
|
||||
}
|
||||
|
||||
template<>
|
||||
int HashFunction<String>(const String &k)
|
||||
int HashFunction<ke::AString>(const ke::AString &k)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k.c_str();
|
||||
register const char *str = k.chars();
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
@@ -54,13 +58,27 @@ int HashAlt<const char *>(char const * const &k)
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k;
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<>
|
||||
int HashAlt<ke::AString>(ke::AString const &k)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
register const char *str = k.chars();
|
||||
register char c;
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; // hash*33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
int HashFunction<int>(const int &k)
|
||||
{
|
||||
@@ -70,7 +88,7 @@ int HashFunction<int>(const int &k)
|
||||
template<>
|
||||
int Compare<int>(const int &k1, const int &k2)
|
||||
{
|
||||
return (k1-k2);
|
||||
return (k1 - k2);
|
||||
}
|
||||
|
||||
// strip the whitespaces at the beginning and the end of a string
|
||||
@@ -142,7 +160,7 @@ void CLangMngr::CLang::AddEntry(int key, const char *definition)
|
||||
m_entries++;
|
||||
}
|
||||
|
||||
d.definition = new String(definition);
|
||||
d.definition = new ke::AString(definition);
|
||||
}
|
||||
|
||||
CLangMngr::CLang::~CLang()
|
||||
@@ -165,21 +183,21 @@ void CLangMngr::CLang::Clear()
|
||||
m_entries = 0;
|
||||
}
|
||||
|
||||
void CLangMngr::CLang::MergeDefinitions(CQueue<sKeyDef> &vec)
|
||||
void CLangMngr::CLang::MergeDefinitions(ke::Vector<sKeyDef> &vec)
|
||||
{
|
||||
String *pDef;
|
||||
ke::AutoString *pDef;
|
||||
int key = -1;
|
||||
|
||||
while (!vec.empty())
|
||||
{
|
||||
key = vec.front().key;
|
||||
pDef = vec.front().definition;
|
||||
auto keydef = vec.popCopy();
|
||||
|
||||
AddEntry(key, pDef->c_str());
|
||||
key = keydef.key;
|
||||
pDef = keydef.definition;
|
||||
|
||||
delete vec.front().definition;
|
||||
|
||||
vec.pop();
|
||||
AddEntry(key, pDef->ptr());
|
||||
|
||||
delete pDef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +212,7 @@ const char * CLangMngr::CLang::GetDef(int key, int &status)
|
||||
}
|
||||
|
||||
status = 0;
|
||||
return def.definition->c_str();
|
||||
return def.definition->chars();
|
||||
}
|
||||
|
||||
int CLangMngr::CLang::Entries()
|
||||
@@ -204,15 +222,6 @@ int CLangMngr::CLang::Entries()
|
||||
|
||||
/******** CLangMngr *********/
|
||||
|
||||
inline String &make_string(const char *str)
|
||||
{
|
||||
static String g_temp;
|
||||
|
||||
g_temp.assign(str);
|
||||
|
||||
return g_temp;
|
||||
}
|
||||
|
||||
CLangMngr::CLangMngr()
|
||||
{
|
||||
Clear();
|
||||
@@ -220,15 +229,15 @@ CLangMngr::CLangMngr()
|
||||
|
||||
const char * CLangMngr::GetKey(int key)
|
||||
{
|
||||
if (key < 0 || key >= (int)KeyList.size())
|
||||
if (key < 0 || key >= (int)KeyList.length())
|
||||
return NULL;
|
||||
|
||||
return KeyList[key]->c_str();
|
||||
return KeyList[key]->chars();
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(const char *key)
|
||||
{
|
||||
keytbl_val &val = KeyTable[key];
|
||||
keytbl_val &val = KeyTable[ke::AString(key)];
|
||||
|
||||
return val.index;
|
||||
}
|
||||
@@ -236,22 +245,21 @@ int CLangMngr::GetKeyEntry(const char *key)
|
||||
int CLangMngr::AddKeyEntry(const char *key)
|
||||
{
|
||||
keytbl_val val;
|
||||
val.index = static_cast<int>(KeyList.size());
|
||||
val.index = static_cast<int>(KeyList.length());
|
||||
|
||||
String *pString = new String(key);
|
||||
KeyList.push_back(pString);
|
||||
KeyList.append(new ke::AString(key));
|
||||
|
||||
KeyTable[key] = val;
|
||||
KeyTable[ke::AString(key)] = val;
|
||||
|
||||
return val.index;
|
||||
}
|
||||
|
||||
int CLangMngr::AddKeyEntry(String &key)
|
||||
int CLangMngr::AddKeyEntry(ke::AString &key)
|
||||
{
|
||||
return AddKeyEntry(key.c_str());
|
||||
return AddKeyEntry(key.chars());
|
||||
}
|
||||
|
||||
int CLangMngr::GetKeyEntry(String &key)
|
||||
int CLangMngr::GetKeyEntry(ke::AString &key)
|
||||
{
|
||||
keytbl_val &val = KeyTable[key];
|
||||
|
||||
@@ -269,16 +277,16 @@ char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len)
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
void CLangMngr::MergeDefinitions(const char *lang, CQueue<sKeyDef> &tmpVec)
|
||||
void CLangMngr::MergeDefinitions(const char *lang, ke::Vector<sKeyDef> &tmpVec)
|
||||
{
|
||||
CLang * language = GetLang(lang);
|
||||
if (language)
|
||||
language->MergeDefinitions(tmpVec);
|
||||
}
|
||||
|
||||
void reparse_color(String* def)
|
||||
void reparse_newlines_and_color(char* def)
|
||||
{
|
||||
size_t len = def->size();
|
||||
size_t len = strlen(def);
|
||||
int offs = 0;
|
||||
int c;
|
||||
|
||||
@@ -287,21 +295,25 @@ void reparse_color(String* def)
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
c = def->at(i);
|
||||
if (c == '^' && (i != len-1))
|
||||
c = def[i];
|
||||
|
||||
if (c == '^' && (i != len - 1))
|
||||
{
|
||||
c = def->at(++i);
|
||||
if (c >= '1' && c <= '4')
|
||||
c = def[++i];
|
||||
|
||||
if (c == 'n' || c == 't' || (c >= '1' && c <= '4'))
|
||||
{
|
||||
switch(c)
|
||||
switch (c)
|
||||
{
|
||||
case '1' : c = '\x01'; break;
|
||||
case '2' : c = '\x02'; break;
|
||||
case '3' : c = '\x03'; break;
|
||||
case '4' : c = '\x04'; break;
|
||||
case '1': c = '\x01'; break;
|
||||
case '2': c = '\x02'; break;
|
||||
case '3': c = '\x03'; break;
|
||||
case '4': c = '\x04'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
}
|
||||
|
||||
if (!g_bmod_cstrike) // remove completely these two characters if not under CS
|
||||
if (!g_bmod_cstrike && (c >= '1' && c <= '4')) // remove completely these two characters if not under CS
|
||||
{
|
||||
offs += 2;
|
||||
continue;
|
||||
@@ -310,10 +322,146 @@ void reparse_color(String* def)
|
||||
offs++;
|
||||
}
|
||||
}
|
||||
def->at(i-offs, c);
|
||||
|
||||
def[i - offs] = c;
|
||||
}
|
||||
|
||||
def->at(len-offs, '\0');
|
||||
def[len-offs] = '\0';
|
||||
}
|
||||
|
||||
struct LangFileData
|
||||
{
|
||||
void reset()
|
||||
{
|
||||
multiLine = false;
|
||||
|
||||
*language = '\0';
|
||||
*valueBuffer = '\0';
|
||||
|
||||
clearEntry();
|
||||
}
|
||||
|
||||
void clearEntry()
|
||||
{
|
||||
entry.key = -1;
|
||||
entry.definition = nullptr;
|
||||
}
|
||||
|
||||
bool multiLine;
|
||||
char language[3];
|
||||
char valueBuffer[512];
|
||||
ke::AString currentFile;
|
||||
ke::AString lastKey;
|
||||
ke::Vector<sKeyDef> defsQueue;
|
||||
sKeyDef entry;
|
||||
|
||||
} Data;
|
||||
|
||||
void CLangMngr::ReadINI_ParseStart()
|
||||
{
|
||||
Data.reset();
|
||||
}
|
||||
|
||||
bool CLangMngr::ReadINI_NewSection(const char *section, bool invalid_tokens, bool close_bracket, bool extra_tokens, unsigned int *curtok)
|
||||
{
|
||||
if (Data.multiLine)
|
||||
{
|
||||
AMXXLOG_Log("New section, unterminated block (file \"%s\" key \"%s\" lang \"%s\")", Data.currentFile.chars(), Data.lastKey.chars(), Data.language);
|
||||
|
||||
Data.clearEntry();
|
||||
}
|
||||
|
||||
if (!Data.defsQueue.empty())
|
||||
{
|
||||
MergeDefinitions(Data.language, Data.defsQueue);
|
||||
}
|
||||
|
||||
Data.reset();
|
||||
|
||||
Data.language[0] = section[0];
|
||||
Data.language[1] = section[1];
|
||||
Data.language[2] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLangMngr::ReadINI_KeyValue(const char *key, const char *value, bool invalid_tokens, bool equal_token, bool quotes, unsigned int *curtok)
|
||||
{
|
||||
bool colons_token = (key[strlen(key) - 1] == ':');
|
||||
|
||||
if (!Data.multiLine)
|
||||
{
|
||||
Data.lastKey = key;
|
||||
|
||||
if (colons_token || equal_token)
|
||||
{
|
||||
int iKey = GetKeyEntry(key);
|
||||
|
||||
if (iKey == -1)
|
||||
{
|
||||
iKey = AddKeyEntry(key);
|
||||
}
|
||||
|
||||
if (equal_token)
|
||||
{
|
||||
strncopy(Data.valueBuffer, value, sizeof(Data.valueBuffer));
|
||||
|
||||
reparse_newlines_and_color(Data.valueBuffer);
|
||||
|
||||
Data.entry.key = iKey;
|
||||
Data.entry.definition = new ke::AutoString;
|
||||
*Data.entry.definition = Data.valueBuffer;
|
||||
|
||||
Data.defsQueue.append(Data.entry);
|
||||
Data.clearEntry();
|
||||
}
|
||||
else if (!value && colons_token)
|
||||
{
|
||||
Data.entry.key = iKey;
|
||||
Data.entry.definition = new ke::AutoString;
|
||||
|
||||
Data.multiLine = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AMXXLOG_Log("Invalid multi-lingual line (file \"%s\" key \"%s\" lang \"%s\")", Data.currentFile.chars(), Data.lastKey.chars(), Data.language);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!value && colons_token)
|
||||
{
|
||||
strncopy(Data.valueBuffer, Data.entry.definition->ptr(), sizeof(Data.valueBuffer));
|
||||
reparse_newlines_and_color(Data.valueBuffer);
|
||||
|
||||
*Data.entry.definition = Data.valueBuffer;
|
||||
|
||||
Data.defsQueue.append(Data.entry);
|
||||
Data.clearEntry();
|
||||
|
||||
Data.multiLine = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Data.entry.definition)
|
||||
{
|
||||
Data.entry.definition = new ke::AutoString();
|
||||
}
|
||||
|
||||
*Data.entry.definition = *Data.entry.definition + key;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLangMngr::ReadINI_ParseEnd(bool halted)
|
||||
{
|
||||
if (!Data.defsQueue.empty())
|
||||
{
|
||||
MergeDefinitions(Data.language, Data.defsQueue);
|
||||
}
|
||||
}
|
||||
|
||||
//this is the file parser for dictionary text files
|
||||
@@ -332,167 +480,60 @@ int CLangMngr::MergeDefinitionFile(const char *file)
|
||||
/** Checks if there is an existing entry with same time stamp. */
|
||||
time_t timeStamp;
|
||||
if (FileList.retrieve(file, &timeStamp) && fileStat.st_mtime == timeStamp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** If yes, it either means that the entry doesn't exist or the existing entry needs to be updated. */
|
||||
FileList.replace(file, fileStat.st_mtime);
|
||||
|
||||
FILE* fp = fopen(file, "rt");
|
||||
if (!fp)
|
||||
Data.currentFile = file;
|
||||
|
||||
unsigned int line, col;
|
||||
bool result = textparsers->ParseFile_INI(file, static_cast<ITextListener_INI*>(this), &line, &col);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
AMXXLOG_Log("[AMXX] Failed to re-open dictionary file: %s", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate enough memory to store everything
|
||||
bool multiline = 0;
|
||||
int pos = 0, line = 0;
|
||||
CQueue<sKeyDef> Defq;
|
||||
String buf;
|
||||
char language[3];
|
||||
sKeyDef tmpEntry = {NULL, 0};
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
line++;
|
||||
buf._fread(fp);
|
||||
buf.trim();
|
||||
if (buf[0] == 0)
|
||||
continue;
|
||||
if ((buf[0] == ';') || (buf[0] == '/' && buf[1] == '/'))
|
||||
continue;
|
||||
|
||||
/* Check for BOM markings, which is only relevant on the first line.
|
||||
* Not worth it, but it could be moved out of the loop.
|
||||
*/
|
||||
if (line == 1 && (buf[0] == (char)0xEF && buf[1] == (char)0xBB && buf[2] == (char)0xBF))
|
||||
{
|
||||
buf.erase(0, 3);
|
||||
}
|
||||
|
||||
if (buf[0] == '[' && buf.size() >= 3)
|
||||
{
|
||||
if (multiline)
|
||||
{
|
||||
AMXXLOG_Log("New section, multiline unterminated (file \"%s\" line %d)", file, line);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
}
|
||||
|
||||
if (!Defq.empty())
|
||||
{
|
||||
MergeDefinitions(language, Defq);
|
||||
}
|
||||
|
||||
language[0] = buf[1];
|
||||
language[1] = buf[2];
|
||||
language[2] = 0;
|
||||
} else {
|
||||
if (!multiline)
|
||||
{
|
||||
pos = buf.find('=');
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());
|
||||
String def;
|
||||
def.assign(buf.substr(pos + 1).c_str());
|
||||
key.trim();
|
||||
key.toLower();
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
tmpEntry.definition->assign(def.c_str());
|
||||
tmpEntry.definition->trim();
|
||||
reparse_color(tmpEntry.definition);
|
||||
tmpEntry.definition->reparse_newlines();
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
} else {
|
||||
pos = buf.find(':');
|
||||
|
||||
if (pos > String::npos)
|
||||
{
|
||||
String key;
|
||||
key.assign(buf.substr(0, pos).c_str());;
|
||||
key.trim();
|
||||
key.toLower();
|
||||
int iKey = GetKeyEntry(key);
|
||||
if (iKey == -1)
|
||||
iKey = AddKeyEntry(key);
|
||||
tmpEntry.key = iKey;
|
||||
tmpEntry.definition = new String;
|
||||
multiline = true;
|
||||
} else {
|
||||
//user typed a line with no directives
|
||||
AMXXLOG_Log("Invalid multi-lingual line (file \"%s\" line %d)", file, line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (buf[0] == ':')
|
||||
{
|
||||
reparse_color(tmpEntry.definition);
|
||||
tmpEntry.definition->reparse_newlines();
|
||||
Defq.push(tmpEntry);
|
||||
tmpEntry.key = -1;
|
||||
tmpEntry.definition = NULL;
|
||||
multiline = false;
|
||||
} else {
|
||||
if (!tmpEntry.definition)
|
||||
tmpEntry.definition = new String();
|
||||
tmpEntry.definition->append(buf);
|
||||
}
|
||||
} // if !multiline
|
||||
} //if - main
|
||||
}
|
||||
|
||||
// merge last section
|
||||
if (!Defq.empty())
|
||||
{
|
||||
MergeDefinitions(language, Defq);
|
||||
}
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find a CLang by name, if not found, add it
|
||||
CLangMngr::CLang * CLangMngr::GetLang(const char *name)
|
||||
{
|
||||
LangVecIter iter;
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), name) == 0)
|
||||
return (*iter);
|
||||
if (strcmp(m_Languages[iter]->GetName(), name) == 0)
|
||||
return m_Languages[iter];
|
||||
}
|
||||
|
||||
CLang *p = new CLang(name);
|
||||
p->SetMngr(this);
|
||||
|
||||
m_Languages.push_back(p);
|
||||
m_Languages.append(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Find a CLang by name, if not found, return NULL
|
||||
CLangMngr::CLang * CLangMngr::GetLangR(const char *name)
|
||||
{
|
||||
LangVecIter iter;
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), name) == 0)
|
||||
return (*iter);
|
||||
if (strcmp(m_Languages[iter]->GetName(), name) == 0)
|
||||
return m_Languages[iter];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *CLangMngr::GetDef(const char *langName, const char *key, int &status)
|
||||
{
|
||||
CLang *lang = GetLangR(langName);
|
||||
keytbl_val &val = KeyTable.AltFindOrInsert(key); //KeyTable[make_string(key)];
|
||||
|
||||
keytbl_val &val = KeyTable.AltFindOrInsert(ke::AString(key)); //KeyTable[make_string(key)];
|
||||
if (lang == NULL)
|
||||
{
|
||||
status = ERR_BADLANG;
|
||||
@@ -522,13 +563,13 @@ void CLangMngr::Clear()
|
||||
|
||||
KeyTable.clear();
|
||||
|
||||
for (i = 0; i < m_Languages.size(); i++)
|
||||
for (i = 0; i < m_Languages.length(); i++)
|
||||
{
|
||||
if (m_Languages[i])
|
||||
delete m_Languages[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < KeyList.size(); i++)
|
||||
for (i = 0; i < KeyList.length(); i++)
|
||||
{
|
||||
if (KeyList[i])
|
||||
delete KeyList[i];
|
||||
@@ -541,23 +582,19 @@ void CLangMngr::Clear()
|
||||
|
||||
int CLangMngr::GetLangsNum()
|
||||
{
|
||||
return m_Languages.size();
|
||||
return m_Languages.length();
|
||||
}
|
||||
|
||||
const char *CLangMngr::GetLangName(int langId)
|
||||
{
|
||||
int i = 0;
|
||||
LangVecIter iter;
|
||||
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (i == langId)
|
||||
if (iter == langId)
|
||||
{
|
||||
return (*iter)->GetName();
|
||||
return m_Languages[iter]->GetName();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -572,14 +609,13 @@ bool CLangMngr::LangExists(const char *langName)
|
||||
break;
|
||||
}
|
||||
|
||||
LangVecIter iter;
|
||||
|
||||
for (iter = m_Languages.begin(); iter != m_Languages.end(); ++iter)
|
||||
for (size_t iter = 0; iter < m_Languages.length(); ++iter)
|
||||
{
|
||||
if (strcmp((*iter)->GetName(), buf) == 0)
|
||||
if (strcmp(m_Languages[iter]->GetName(), buf) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user