164 lines
2.9 KiB
C++
164 lines
2.9 KiB
C++
// Common/Lang.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "Lang.h"
|
|
#include "StringToInt.h"
|
|
#include "UTFConvert.h"
|
|
|
|
#include "../Windows/FileIO.h"
|
|
|
|
void CLang::Clear() throw()
|
|
{
|
|
delete []_text;
|
|
_text = 0;
|
|
_ids.Clear();
|
|
_offsets.Clear();
|
|
}
|
|
|
|
static const wchar_t *kLangSignature = L";!@Lang2@!UTF-8!";
|
|
|
|
bool CLang::OpenFromString(const AString &s2)
|
|
{
|
|
UString s;
|
|
if (!ConvertUTF8ToUnicode(s2, s))
|
|
return false;
|
|
unsigned i = 0;
|
|
if (s.IsEmpty())
|
|
return false;
|
|
if (s[0] == 0xFEFF)
|
|
i++;
|
|
|
|
for (const wchar_t *p = kLangSignature;; i++)
|
|
{
|
|
wchar_t c = *p++;
|
|
if (c == 0)
|
|
break;
|
|
if (s[i] != c)
|
|
return false;
|
|
}
|
|
|
|
_text = new wchar_t[s.Len() - i + 1];
|
|
wchar_t *text = _text;
|
|
|
|
Int32 id = -100;
|
|
UInt32 pos = 0;
|
|
|
|
while (i < s.Len())
|
|
{
|
|
unsigned start = pos;
|
|
do
|
|
{
|
|
wchar_t c = s[i++];
|
|
if (c == '\n')
|
|
break;
|
|
if (c == '\\')
|
|
{
|
|
if (i == s.Len())
|
|
return false;
|
|
c = s[i++];
|
|
switch (c)
|
|
{
|
|
case '\n': return false;
|
|
case 'n': c = '\n'; break;
|
|
case 't': c = '\t'; break;
|
|
case '\\': c = '\\'; break;
|
|
default: text[pos++] = L'\\'; break;
|
|
}
|
|
}
|
|
text[pos++] = c;
|
|
}
|
|
while (i < s.Len());
|
|
|
|
{
|
|
unsigned j = start;
|
|
for (; j < pos; j++)
|
|
if (text[j] != ' ')
|
|
break;
|
|
if (j == pos)
|
|
{
|
|
id++;
|
|
continue;
|
|
}
|
|
}
|
|
if (text[start] == ';')
|
|
{
|
|
pos = start;
|
|
id++;
|
|
continue;
|
|
}
|
|
|
|
text[pos++] = 0;
|
|
const wchar_t *end;
|
|
UInt32 id32 = ConvertStringToUInt32(text + start, &end);
|
|
if (*end == 0)
|
|
{
|
|
if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id)
|
|
return false;
|
|
id = (Int32)id32;
|
|
pos = start;
|
|
continue;
|
|
}
|
|
|
|
if (id < 0)
|
|
return false;
|
|
_ids.Add((UInt32)id++);
|
|
_offsets.Add(start);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CLang::Open(CFSTR fileName, const wchar_t *id)
|
|
{
|
|
Clear();
|
|
NWindows::NFile::NIO::CInFile file;
|
|
if (!file.Open(fileName))
|
|
return false;
|
|
UInt64 length;
|
|
if (!file.GetLength(length))
|
|
return false;
|
|
if (length > (1 << 20))
|
|
return false;
|
|
|
|
AString s;
|
|
unsigned len = (unsigned)length;
|
|
char *p = s.GetBuf(len);
|
|
UInt32 processed;
|
|
if (!file.Read(p, len, processed))
|
|
return false;
|
|
file.Close();
|
|
if (len != processed)
|
|
return false;
|
|
|
|
char *p2 = p;
|
|
for (unsigned i = 0; i < len; i++)
|
|
{
|
|
char c = p[i];
|
|
if (c == 0)
|
|
break;
|
|
if (c != 0x0D)
|
|
*p2++ = c;
|
|
}
|
|
*p2 = 0;
|
|
s.ReleaseBuf_SetLen((unsigned)(p2 - p));
|
|
|
|
if (OpenFromString(s))
|
|
{
|
|
const wchar_t *name = Get(0);
|
|
if (name && wcscmp(name, id) == 0)
|
|
return true;
|
|
}
|
|
|
|
Clear();
|
|
return false;
|
|
}
|
|
|
|
const wchar_t *CLang::Get(UInt32 id) const throw()
|
|
{
|
|
int index = _ids.FindInSorted(id);
|
|
if (index < 0)
|
|
return NULL;
|
|
return _text + (size_t)_offsets[index];
|
|
}
|