7zip/CPP/Common/Lang.cpp

174 lines
3.2 KiB
C++
Raw Normal View History

2021-12-27 01:00:00 +01:00
// Common/Lang.cpp
#include "StdAfx.h"
#include "Lang.h"
#include "StringToInt.h"
#include "UTFConvert.h"
#include "../Windows/FileIO.h"
void CLang::Clear() throw()
{
_ids.Clear();
_offsets.Clear();
2023-06-21 02:00:00 +02:00
Comments.Clear();
2021-12-27 01:00:00 +01:00
delete []_text;
2023-06-21 02:00:00 +02:00
_text = NULL;
2021-12-27 01:00:00 +01:00
}
2023-06-21 02:00:00 +02:00
static const char * const kLangSignature = ";!@Lang2@!UTF-8!\n";
2021-12-27 01:00:00 +01:00
bool CLang::OpenFromString(const AString &s2)
{
2023-06-21 02:00:00 +02:00
UString su;
if (!ConvertUTF8ToUnicode(s2, su))
2021-12-27 01:00:00 +01:00
return false;
2023-06-21 02:00:00 +02:00
if (su.IsEmpty())
2021-12-27 01:00:00 +01:00
return false;
2023-06-21 02:00:00 +02:00
const wchar_t *s = su;
const wchar_t *sLim = s + su.Len();
if (*s == 0xFEFF)
s++;
for (const char *p = kLangSignature;; s++)
2021-12-27 01:00:00 +01:00
{
2023-06-21 02:00:00 +02:00
const Byte c = (Byte)(*p++);
2021-12-27 01:00:00 +01:00
if (c == 0)
break;
2023-06-21 02:00:00 +02:00
if (*s != c)
2021-12-27 01:00:00 +01:00
return false;
}
2023-06-21 02:00:00 +02:00
wchar_t *text = new wchar_t[(size_t)(sLim - s) + 1];
_text = text;
2021-12-27 01:00:00 +01:00
2023-06-21 02:00:00 +02:00
UString comment;
Int32 id = -1024;
unsigned pos = 0;
2021-12-27 01:00:00 +01:00
2023-06-21 02:00:00 +02:00
while (s != sLim)
2021-12-27 01:00:00 +01:00
{
2023-06-21 02:00:00 +02:00
const unsigned start = pos;
2021-12-27 01:00:00 +01:00
do
{
2023-06-21 02:00:00 +02:00
wchar_t c = *s++;
2021-12-27 01:00:00 +01:00
if (c == '\n')
break;
if (c == '\\')
{
2023-06-21 02:00:00 +02:00
if (s == sLim)
2021-12-27 01:00:00 +01:00
return false;
2023-06-21 02:00:00 +02:00
c = *s++;
2021-12-27 01:00:00 +01:00
switch (c)
{
case '\n': return false;
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
2023-06-21 02:00:00 +02:00
case '\\': /* c = '\\'; */ break;
2021-12-27 01:00:00 +01:00
default: text[pos++] = L'\\'; break;
}
}
text[pos++] = c;
}
2023-06-21 02:00:00 +02:00
while (s != sLim);
2021-12-27 01:00:00 +01:00
{
unsigned j = start;
for (; j < pos; j++)
2023-06-21 02:00:00 +02:00
if (text[j] != ' ' && text[j] != '\t')
2021-12-27 01:00:00 +01:00
break;
if (j == pos)
{
id++;
2023-06-21 02:00:00 +02:00
pos = start;
2021-12-27 01:00:00 +01:00
continue;
}
}
2023-06-21 02:00:00 +02:00
// start != pos
text[pos++] = 0;
2021-12-27 01:00:00 +01:00
if (text[start] == ';')
{
2023-06-21 02:00:00 +02:00
comment = text + start;
comment.TrimRight();
if (comment.Len() != 1)
Comments.Add(comment);
2021-12-27 01:00:00 +01:00
id++;
2023-06-21 02:00:00 +02:00
pos = start;
2021-12-27 01:00:00 +01:00
continue;
}
2023-06-21 02:00:00 +02:00
2021-12-27 01:00:00 +01:00
const wchar_t *end;
2023-06-21 02:00:00 +02:00
const UInt32 id32 = ConvertStringToUInt32(text + start, &end);
2021-12-27 01:00:00 +01:00
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 char *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;
const unsigned len = (unsigned)length;
char *p = s.GetBuf(len);
size_t processed;
if (!file.ReadFull(p, len, processed))
return false;
file.Close();
if (len != processed)
return false;
char *p2 = p;
for (unsigned i = 0; i < len; i++)
{
2023-06-21 02:00:00 +02:00
const char c = p[i];
2021-12-27 01:00:00 +01:00
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 && StringsAreEqual_Ascii(name, id))
return true;
}
Clear();
return false;
}
const wchar_t *CLang::Get(UInt32 id) const throw()
{
2023-06-21 02:00:00 +02:00
const int index = _ids.FindInSorted(id);
2021-12-27 01:00:00 +01:00
if (index < 0)
return NULL;
return _text + (size_t)_offsets[(unsigned)index];
}