YSTest: NLS.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

NLS.cpp
浏览该文件的文档.
1 /*
2 © 2014-2016 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) std::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 : mapped(WCSToMBCS(FetchSystemPath() + FetchCPFileNameFromRegistry(cp)))
171 {
172 const auto base(reinterpret_cast<unsigned short*>(mapped.GetPtr()));
173 auto& header(*reinterpret_cast<NLS_FILE_HEADER*>(base));
174
175 yunseq(
176 table.CodePage = header.CodePage,
177 table.MaximumCharacterSize = header.MaximumCharacterSize,
178 table.DefaultChar = header.DefaultChar,
179 table.UniDefaultChar = header.UniDefaultChar,
180 table.TransDefaultChar = header.TransDefaultChar,
181 table.TransUniDefaultChar = header.TransUniDefaultChar,
182 ystdex::trivially_copy_n(header.LeadByte, 1, table.LeadByte),
183 // NOTE: Offset to wide char table is after the header, then the multibyte
184 // table (256 wide characters) .
185 table.WideCharTable = base + header.HeaderSize + 1
186 + base[header.HeaderSize],
187 table.MultiByteTable = base + header.HeaderSize + 1
188 );
189 // NOTE: Glyph table (256 wide characters) is probably present.
190 table.DBCSRanges = table.MultiByteTable + 256 + 1;
191 if(table.MultiByteTable[256])
192 table.DBCSRanges += 256;
193 table.DBCSOffsets = (table.DBCSCodePage = *table.DBCSRanges)
194 ? table.DBCSRanges + 1 : nullptr;
195 }
196
197
198 mutex NLSCacheMutex;
200 map<int, NLSTableEntry> NLSCache;
201
202 } // unnamed namespace;
203
204 string
205 MBCSToMBCS(const char* str, unsigned cp_src, unsigned cp_dst)
206 {
207 return MBCSToMBCSImpl(-1, str, cp_src, cp_dst);
208 }
209 string
210 MBCSToMBCS(string_view sv, unsigned cp_src, unsigned cp_dst)
211 {
212 return sv.length() != 0 ? MBCSToMBCSImpl(CheckNonnegative<int>(sv.length()),
213 sv.data(), cp_src, cp_dst) : string();
214 }
215
216 wstring
217 MBCSToWCS(const char* str, unsigned cp)
218 {
219 return MBCSToWCSImpl(-1, str, cp);
220 }
221 wstring
222 MBCSToWCS(string_view sv, unsigned cp)
223 {
224 return sv.length() != 0 ? MBCSToWCSImpl(
225 CheckNonnegative<int>(sv.length()), sv.data(), cp) : wstring();
226 }
227
228 string
229 WCSToMBCS(const wchar_t* str, unsigned cp)
230 {
231 return WCSToMBCSImpl(-1, str, cp);
232 }
233 string
234 WCSToMBCS(wstring_view sv, unsigned cp)
235 {
236 return sv.length() != 0 ? WCSToMBCSImpl(
237 CheckNonnegative<int>(sv.length()), sv.data(), cp) : string();
238 }
239
240
241 const unsigned short*
242 FetchDBCSOffset(int cp) ynothrow
243 {
244 return TryInvoke([=]{
245 lock_guard<mutex> lck(NLSCacheMutex);
246 // TODO: Enable concurrent initialization using 'call_once', etc?
247 auto& tbl(ystdex::try_emplace(NLSCache, cp, cp).first
248 ->second.GetTable());
249
250 return tbl.DBCSCodePage ? tbl.DBCSOffsets : nullptr;
251 });
252 }
253
254 } // inline namespace Windows;
255
256 #endif
257
258 } // namespace platform_ex;
259
platform::containers::wstring
basic_string< wchar_t > wstring
Definition: Container.h:108
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
ystdex::trivially_copy_n
_type * trivially_copy_n(const _type *first, size_t n, _type *result)
复制不覆盖的序列。
Definition: algorithm.hpp:394
YSLib::TryInvoke
ystdex::nonvoid_result_t< ystdex::result_of_t< _fCallable &&(_tParams &&...)> > TryInvoke(_fCallable &&f, _tParams &&...args) ynothrow
调用函数并尝试返回。
Definition: YException.h:186
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:679
platform::containers::string
basic_string< char > string
Definition: Container.h:101
platform_ex::Windows::WCSToMBCS
YF_API string WCSToMBCS(wstring_view, unsigned=CP_ACP)
platform::KeyCodes::DS::L
Definition: Keys.h:227
ystdex::try_emplace
std::pair< typename _tAssocCon::iterator, bool > try_emplace(_tAssocCon &con, _tKey &&k, _tParams &&...args)
Definition: container.hpp:1230
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1022
mapped
MappedFile mapped
Definition: Initialization.cpp:224
ystdex::wstring_view
basic_string_view< wchar_t > wstring_view
Definition: string_view.hpp:418
platform_ex::Windows::MBCSToMBCS
YF_API string MBCSToMBCS(string_view, unsigned=CP_UTF8, unsigned=CP_ACP)
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
Drawing
YModules.h
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
base.h
基类实用设施。
YSLib::YB_NONNULL
YF_API YB_NONNULL(1, 2) ValueNode LoadNPLA1File(const char *disp
载入 NPLA1 配置文件。
std
Definition: memory.hpp:1183
DefGetter
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:241
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:834
platform::Nonnull
_type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:422
platform_ex
平台扩展命名空间。
Definition: Android.h:45
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
YSLib::Text::str
const char const char * str
Definition: TextFile.h:81
platform_ex::Windows::FetchSystemPath
YF_API wstring FetchSystemPath(size_t=MAX_PATH)
取系统目录路径。
platform::MappedFile
只读内存映射文件。
Definition: MemoryMapping.h:111
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
platform_ex::Windows::MBCSToWCS
YF_API wstring MBCSToWCS(string_view, unsigned=CP_ACP)