YSTest: NLS.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

NLS.cpp
浏览该文件的文档.
1 /*
2 © 2014-2016, 2018 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
29 #include "YCLib/YModules.h"
30 #include YFM_YCLib_Platform
31 #if YCL_Win32
32 # include YFM_Win32_YCLib_NLS // for map, ystdex::trivially_copy_n,
33 // ystdex::try_emplace;
34 # include YFM_Win32_YCLib_Registry // for FetchRegistryString;
35 # include YFM_YSLib_Core_YCoreUtilities // for YSLib::CheckPositive;
36 # include <ystdex/base.h> // for ystdex::noncopyable, ystdex::nonmovable;
37 # include YFM_YCLib_MemoryMapping // for platform::MappedFile;
38
39 using namespace YSLib;
40 using namespace Drawing;
41 #endif
42
43 namespace platform_ex
44 {
45
46 #if YCL_Win32
47
48 inline namespace Windows
49 {
50
52 YB_NONNULL(1) wstring
53 FetchNLSItemFromRegistry(const wchar_t* name)
54 {
55 return FetchRegistryString(HKEY_LOCAL_MACHINE,
56 L"System\\CurrentControlSet\\Control\\Nls\\CodePage", name);
57 }
58
59
61 namespace
62 {
63
65
66 YB_NONNULL(2) string
67 MBCSToMBCSImpl(int l, const char* str, unsigned cp_src, unsigned cp_dst)
68 {
69 if(cp_src != cp_dst)
70 {
71 const int
72 w_len(::MultiByteToWideChar(cp_src, 0, Nonnull(str), l, {}, 0));
73
74 if(w_len != 0)
75 {
76 wstring wstr(CheckPositive<size_t>(w_len), wchar_t());
77 const auto w_str(&wstr[0]);
78
79 ::MultiByteToWideChar(cp_src, 0, str, l, w_str, w_len);
80 if(l == -1 && !wstr.empty())
81 wstr.pop_back();
82 return WCSToMBCS({w_str, wstr.length()}, cp_dst);
83 }
84 return {};
85 }
86 return str;
87 }
88
89 YB_NONNULL(2) wstring
90 MBCSToWCSImpl(int l, const char* str, unsigned cp)
91 {
92 const int
93 w_len(::MultiByteToWideChar(cp, 0, Nonnull(str), l, {}, 0));
94
95 if(w_len != 0)
96 {
97 wstring res(CheckPositive<size_t>(w_len), wchar_t());
98
99 ::MultiByteToWideChar(cp, 0, str, l, &res[0], w_len);
100 if(l == -1 && !res.empty())
101 res.pop_back();
102 return res;
103 }
104 return {};
105 }
106
107 YB_NONNULL(2) string
108 WCSToMBCSImpl(int l, const wchar_t* str, unsigned cp)
109 {
110 const int r_l(::WideCharToMultiByte(cp, 0, Nonnull(str), l, {}, 0, {}, {}));
111
112 if(r_l != 0)
113 {
114 string res(CheckPositive<size_t>(r_l), char());
115
116 ::WideCharToMultiByte(cp, 0, str, l, &res[0], r_l, {}, {});
117 if(l == -1 && !res.empty())
118 res.pop_back();
119 return res;
120 }
121 return {};
122 }
124
125
126 yconstexpr const size_t MAXIMUM_LEADBYTES(12);
127
128 struct NLS_FILE_HEADER
129 {
130 unsigned short HeaderSize;
131 unsigned short CodePage;
132 unsigned short MaximumCharacterSize;
133 unsigned short DefaultChar;
134 unsigned short UniDefaultChar;
135 unsigned short TransDefaultChar;
136 unsigned short TransUniDefaultChar;
137 byte LeadByte[MAXIMUM_LEADBYTES];
138 };
139
140 struct CPTABLEINFO
141 {
142 unsigned short CodePage;
143 unsigned short MaximumCharacterSize;
144 unsigned short DefaultChar;
145 unsigned short UniDefaultChar;
146 unsigned short TransDefaultChar;
147 unsigned short TransUniDefaultChar;
148 unsigned short DBCSCodePage;
149 byte LeadByte[MAXIMUM_LEADBYTES];
150 unsigned short* MultiByteTable;
151 void* WideCharTable;
152 unsigned short* DBCSRanges;
153 unsigned short* DBCSOffsets;
154 };
155
156
157 class NLSTableEntry final : private noncopyable, private nonmovable
158 {
159 private:
161 platform::MappedFile mapped;
162 CPTABLEINFO table;
163
164 public:
165 NLSTableEntry(int);
166 DefGetter(const ynothrow, const CPTABLEINFO&, Table, table)
167 };
168
169 NLSTableEntry::NLSTableEntry(int cp)
170 // FIXME: Some NLS files are missing from SysWOW64 directory in some
171 // versions of 64-bit Windows 10.
172 : mapped(WCSToMBCS(FetchSystemPath() + FetchCPFileNameFromRegistry(cp)))
173 {
174 const auto base(reinterpret_cast<unsigned short*>(mapped.GetPtr()));
175 auto& header(*reinterpret_cast<NLS_FILE_HEADER*>(base));
176
177 yunseq(
178 table.CodePage = header.CodePage,
179 table.MaximumCharacterSize = header.MaximumCharacterSize,
180 table.DefaultChar = header.DefaultChar,
181 table.UniDefaultChar = header.UniDefaultChar,
182 table.TransDefaultChar = header.TransDefaultChar,
183 table.TransUniDefaultChar = header.TransUniDefaultChar,
184 ystdex::trivially_copy_n(header.LeadByte, 1, table.LeadByte),
185 // NOTE: Offset to wide char table is after the header, then the multibyte
186 // table (256 wide characters) .
187 table.WideCharTable = base + header.HeaderSize + 1
188 + base[header.HeaderSize],
189 table.MultiByteTable = base + header.HeaderSize + 1
190 );
191 // NOTE: Glyph table (256 wide characters) is probably present.
192 table.DBCSRanges = table.MultiByteTable + 256 + 1;
193 if(table.MultiByteTable[256])
194 table.DBCSRanges += 256;
195 table.DBCSOffsets = (table.DBCSCodePage = *table.DBCSRanges)
196 ? table.DBCSRanges + 1 : nullptr;
197 }
198
199
200 mutex NLSCacheMutex;
202 map<int, NLSTableEntry> NLSCache;
203
204 } // unnamed namespace;
205
206 string
207 MBCSToMBCS(const char* str, unsigned cp_src, unsigned cp_dst)
208 {
209 return MBCSToMBCSImpl(-1, str, cp_src, cp_dst);
210 }
211 string
212 MBCSToMBCS(string_view sv, unsigned cp_src, unsigned cp_dst)
213 {
214 return sv.length() != 0 ? MBCSToMBCSImpl(CheckNonnegative<int>(sv.length()),
215 sv.data(), cp_src, cp_dst) : string();
216 }
217
218 wstring
219 MBCSToWCS(const char* str, unsigned cp)
220 {
221 return MBCSToWCSImpl(-1, str, cp);
222 }
223 wstring
224 MBCSToWCS(string_view sv, unsigned cp)
225 {
226 return sv.length() != 0 ? MBCSToWCSImpl(
227 CheckNonnegative<int>(sv.length()), sv.data(), cp) : wstring();
228 }
229
230 string
231 WCSToMBCS(const wchar_t* str, unsigned cp)
232 {
233 return WCSToMBCSImpl(-1, str, cp);
234 }
235 string
236 WCSToMBCS(wstring_view sv, unsigned cp)
237 {
238 return sv.length() != 0 ? WCSToMBCSImpl(
239 CheckNonnegative<int>(sv.length()), sv.data(), cp) : string();
240 }
241
242
243 const unsigned short*
244 FetchDBCSOffset(int cp) ynothrow
245 {
246 return TryInvoke([=]{
247 lock_guard<mutex> lck(NLSCacheMutex);
248 // TODO: Enable concurrent initialization using 'call_once', etc?
249 auto& tbl(ystdex::try_emplace(NLSCache, cp, cp).first
250 ->second.GetTable());
251
252 return tbl.DBCSCodePage ? tbl.DBCSOffsets : nullptr;
253 });
254 }
255
256 } // inline namespace Windows;
257
258 #endif
259
260 } // namespace platform_ex;
261
platform::Nonnull
YB_PURE _type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:518
YSLib::TryInvoke
ystdex::nonvoid_result_t< ystdex::invoke_result_t< _fCallable, _tParams... > > TryInvoke(_fCallable &&f, _tParams &&... args) ynothrow
调用函数并尝试返回。
Definition: YException.h:206
platform_ex::Windows::FetchSystemPath
YF_API wstring FetchSystemPath(size_t=MAX_PATH)
取系统目录路径。
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:1072
base.h
基类实用设施。
platform_ex
平台扩展命名空间。
Definition: Android.h:46
ystdex::noncopyable
bases::noncopyable noncopyable
Definition: base.h:215
ystdex::cpp2017::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:437
ystdex::cpp2017::wstring_view
basic_string_view< wchar_t > wstring_view
Definition: string_view.hpp:440
platform::MappedFile
只读内存映射文件。
Definition: MemoryMapping.h:115
platform_ex::Windows::FetchRegistryString
YF_API const wchar_t FetchRegistryString
Definition: Registry.h:127
platform_ex::Windows::MBCSToMBCS
YF_API string MBCSToMBCS(string_view, unsigned=CP_UTF8, unsigned=CP_ACP)
ystdex::try_emplace
std::pair< typename _tAssocCon::iterator, bool > try_emplace(_tAssocCon &con, _tKey &&k, _tParams &&... args)
Definition: container.hpp:1039
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1535
platform::KeyCodes::DS::L
@ L
Definition: Keys.h:228
ystdex::trivially_copy_n
_type * trivially_copy_n(const _type *first, size_t n, _type *result)
复制不覆盖的序列。
Definition: algorithm.hpp:469
ystdex::cpp2017::wstring
basic_string< wchar_t > wstring
Definition: string.hpp:775
platform_ex::Windows::WCSToMBCS
YF_API string WCSToMBCS(wstring_view, unsigned=CP_ACP)
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:46
platform_ex::Windows::MBCSToWCS
YF_API wstring MBCSToWCS(string_view, unsigned=CP_ACP)
YSLib::str
const char * str
Definition: YException.cpp:60
NPL::A1::name
const char * name
Definition: NPLA1.h:1876
YSLib::Drawing::ynothrow
YB_ATTR_nodiscard yconstfn YB_PURE x x x Bottom YB_ATTR_nodiscard yconstfn YB_PURE x Right y x Top y x Bottom y Bottom YB_ATTR_nodiscard yconstfn YB_PURE x Right y x Top y x Bottom y Bottom YB_ATTR_nodiscard yconstfn YB_PURE const Padding & ynothrow
Definition: YGDI.h:132
YSLib::YB_NONNULL
YB_ATTR_nodiscard YF_API YB_NONNULL(1, 2) ValueNode LoadNPLA1File(const char *disp
载入 NPLA1 配置文件。
YModules.h
YCLib 库模块配置文件。
DefGetter
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:241
ystdex::nonmovable
bases::nonmovable nonmovable
Definition: base.h:217
mapped
MappedFile mapped
Definition: Initialization.cpp:316
YSLib::Text::str
YB_ATTR_nodiscard YB_PURE const char const char * str
Definition: TextFile.h:83
const
const Decapsulate const Decapsulate &y ynothrow ContextNode &ctx const
Definition: NPLA1Forms.cpp:1629
ystdex::cpp2017::string
basic_string< char > string
Definition: string.hpp:772
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:1199
platform::l
return l
Definition: YCLib/FileSystem.h:402