diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Common/Lang.cpp | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-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.cpp | 163 |
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 | |||
11 | void CLang::Clear() throw() | ||
12 | { | ||
13 | _ids.Clear(); | ||
14 | _offsets.Clear(); | ||
15 | delete []_text; | ||
16 | _text = 0; | ||
17 | } | ||
18 | |||
19 | static const char * const kLangSignature = ";!@Lang2@!UTF-8!"; | ||
20 | |||
21 | bool 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 | |||
112 | bool 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 | |||
157 | const 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 | } | ||