aboutsummaryrefslogtreecommitdiff
path: root/CPP/Common/Lang.cpp
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Common/Lang.cpp
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-21.07.tar.gz
7zip-21.07.tar.bz2
7zip-21.07.zip
'21.07'21.07
Diffstat (limited to 'CPP/Common/Lang.cpp')
-rw-r--r--CPP/Common/Lang.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp
new file mode 100644
index 0000000..35d3752
--- /dev/null
+++ b/CPP/Common/Lang.cpp
@@ -0,0 +1,163 @@
1// Common/Lang.cpp
2
3#include "StdAfx.h"
4
5#include "Lang.h"
6#include "StringToInt.h"
7#include "UTFConvert.h"
8
9#include "../Windows/FileIO.h"
10
11void CLang::Clear() throw()
12{
13 _ids.Clear();
14 _offsets.Clear();
15 delete []_text;
16 _text = 0;
17}
18
19static const char * const kLangSignature = ";!@Lang2@!UTF-8!";
20
21bool CLang::OpenFromString(const AString &s2)
22{
23 UString s;
24 if (!ConvertUTF8ToUnicode(s2, s))
25 return false;
26 unsigned i = 0;
27 if (s.IsEmpty())
28 return false;
29 if (s[0] == 0xFEFF)
30 i++;
31
32 for (const char *p = kLangSignature;; i++)
33 {
34 Byte c = (Byte)(*p++);
35 if (c == 0)
36 break;
37 if (s[i] != c)
38 return false;
39 }
40
41 _text = new wchar_t[s.Len() - i + 1];
42 wchar_t *text = _text;
43
44 Int32 id = -100;
45 UInt32 pos = 0;
46
47 while (i < s.Len())
48 {
49 unsigned start = pos;
50 do
51 {
52 wchar_t c = s[i++];
53 if (c == '\n')
54 break;
55 if (c == '\\')
56 {
57 if (i == s.Len())
58 return false;
59 c = s[i++];
60 switch (c)
61 {
62 case '\n': return false;
63 case 'n': c = '\n'; break;
64 case 't': c = '\t'; break;
65 case '\\': c = '\\'; break;
66 default: text[pos++] = L'\\'; break;
67 }
68 }
69 text[pos++] = c;
70 }
71 while (i < s.Len());
72
73 {
74 unsigned j = start;
75 for (; j < pos; j++)
76 if (text[j] != ' ')
77 break;
78 if (j == pos)
79 {
80 id++;
81 continue;
82 }
83 }
84 if (text[start] == ';')
85 {
86 pos = start;
87 id++;
88 continue;
89 }
90
91 text[pos++] = 0;
92 const wchar_t *end;
93 UInt32 id32 = ConvertStringToUInt32(text + start, &end);
94 if (*end == 0)
95 {
96 if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id)
97 return false;
98 id = (Int32)id32;
99 pos = start;
100 continue;
101 }
102
103 if (id < 0)
104 return false;
105 _ids.Add((UInt32)id++);
106 _offsets.Add(start);
107 }
108
109 return true;
110}
111
112bool CLang::Open(CFSTR fileName, const char *id)
113{
114 Clear();
115 NWindows::NFile::NIO::CInFile file;
116 if (!file.Open(fileName))
117 return false;
118 UInt64 length;
119 if (!file.GetLength(length))
120 return false;
121 if (length > (1 << 20))
122 return false;
123
124 AString s;
125 const unsigned len = (unsigned)length;
126 char *p = s.GetBuf(len);
127 size_t processed;
128 if (!file.ReadFull(p, len, processed))
129 return false;
130 file.Close();
131 if (len != processed)
132 return false;
133
134 char *p2 = p;
135 for (unsigned i = 0; i < len; i++)
136 {
137 char c = p[i];
138 if (c == 0)
139 break;
140 if (c != 0x0D)
141 *p2++ = c;
142 }
143 *p2 = 0;
144 s.ReleaseBuf_SetLen((unsigned)(p2 - p));
145
146 if (OpenFromString(s))
147 {
148 const wchar_t *name = Get(0);
149 if (name && StringsAreEqual_Ascii(name, id))
150 return true;
151 }
152
153 Clear();
154 return false;
155}
156
157const wchar_t *CLang::Get(UInt32 id) const throw()
158{
159 int index = _ids.FindInSorted(id);
160 if (index < 0)
161 return NULL;
162 return _text + (size_t)_offsets[(unsigned)index];
163}