YSTest: Host.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

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

- 文件列表
- 文件成员

Host.cpp
浏览该文件的文档.
1 /*
2 © 2014-2017 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
30 #include "YCLib/YModules.h"
31 #include YFM_YCLib_Host // for make_observer, platform::CallNothrow;
32 #include YFM_YCLib_NativeAPI // for YCL_TraceCallF_CAPI, ::sem_open,
33 // ::sem_close, ::sem_unlink, ::pipe, ToHandle, YCL_CallGlobal, isatty;
34 #include YFM_YCLib_FileIO // for MakePathStringW, YCL_Raise_SysE,
35 // MakePathString, YCL_CallF_CAPI;
36 #include YFM_YSLib_Core_YException // for YSLib::FilterExceptions;
37 #include <stdlib.h> // for ::putenv, ::setenv;
38 #if YCL_Win32
39 # include <limits> // for std::numeric_limits;
40 # include YFM_Win32_YCLib_NLS // for CloseHandle, MBCSToMBCS;
41 # include YFM_Win32_YCLib_Consoles // for WConsole;
42 #endif
43 #if YF_Hosted
44 # include YFM_YSLib_Core_YConsole
45 # if !(YCL_Win32 || YCL_API_Has_semaphore_h)
46 # error "Unsupported platform found."
47 # endif
48 #endif
49
50 using namespace YSLib;
52 using YSLib::string;
54 using platform::string_view;
55
56 #if YF_Hosted
57
58 namespace platform_ex
59 {
60
61 Exception::Exception(std::error_code ec, const char* str, RecordLevel lv)
62 : system_error(ec, Nonnull(str)),
63 level(lv)
64 {}
65 Exception::Exception(std::error_code ec, string_view sv, RecordLevel lv)
66 : system_error(ec, (Nonnull(sv.data()), std::string(sv))),
67 level(lv)
68 {}
69 Exception::Exception(int ev, const std::error_category& ecat, const char* str,
70 RecordLevel lv)
71 : system_error(ev, ecat, Nonnull(str)),
72 level(lv)
73 {}
74 Exception::Exception(int ev, const std::error_category& ecat, string_view sv,
75 RecordLevel lv)
76 : system_error(ev, ecat, (Nonnull(sv.data()), std::string(sv))),
77 level(lv)
78 {}
79 ImplDeDtor(Exception)
80
81
82 #if YCL_Win32
83 void
84 HandleDelete::operator()(pointer h) const ynothrowv
85 {
86 YCL_TraceCallF_Win32(CloseHandle, h);
87 }
88 #endif
89
90
91 int
92 upclose(std::FILE* fp) ynothrowv
93 {
94 YAssertNonnull(fp);
95 #if YCL_DS
96 errno = ENOSYS;
97 return -1;
98 #else
99 return YCL_CallGlobal(pclose, fp);
100 #endif
101 }
102
103 std::FILE*
104 upopen(const char* filename, const char* mode) ynothrowv
105 {
106 YAssertNonnull(filename);
107 YAssert(Deref(mode) != char(), "Invalid argument found.");
108 #if YCL_Win32
109 return platform::CallNothrow({}, [=]{
110 return ::_wpopen(MakePathStringW(filename).c_str(),
111 MakePathStringW(mode).c_str());
112 });
113 #else
114 return ::popen(filename, mode);
115 #endif
116 }
117 std::FILE*
118 upopen(const char16_t* filename, const char16_t* mode) ynothrowv
119 {
120 using namespace platform;
121
122 YAssertNonnull(filename);
123 YAssert(Deref(mode) != char(), "Invalid argument found.");
124 #if YCL_Win32
125 return ::_wpopen(wcast(filename), wcast(mode));
126 #else
127 return CallNothrow({}, [=]{
128 return ::popen(MakePathString(filename).c_str(),
129 MakePathString(mode).c_str());
130 });
131 #endif
132 }
133
134
135 void
136 SetEnvironmentVariable(const char* envname, const char* envval)
137 {
138 #if YCL_Win32
139 // TODO: Use %::_wputenv_s when available.
140 // NOTE: Only narrow enviornment is used.
141 // XXX: Though not documented, %::putenv actually copies the argument.
142 // Confirmed in ucrt source. See also https://patchwork.ozlabs.org/patch/127453/.
143 YCL_CallF_CAPI(, ::_putenv,
144 (string(Nonnull(envname)) + '=' + Nonnull(envval)).c_str());
145 #else
146 YCL_CallF_CAPI(, ::setenv, Nonnull(envname), Nonnull(envval), 1);
147 #endif
148 }
149
150 #if !YCL_Win32
151 void
152 Semaphore::Deleter::operator()(pointer p) const ynothrowv
153 {
154 YCL_TraceCallF_CAPI(::sem_close, static_cast<::sem_t*>(p));
155 if(Referent)
156 YCL_TraceCallF_CAPI(::sem_unlink, Referent->name.c_str());
157 }
158 #endif
159
160
161 Semaphore::Semaphore(const char* n, CountType init)
162 #if YCL_Win32
163 : Semaphore(platform::ucast(MakePathStringW(n).c_str()), init)
164 #else
165 : h_sem([=]{
166 using platform::OpenMode;
167 const auto create([=](OpenMode omode) ynothrow{
168 // TODO: Allow setting of permission mode.
169 return ystdex::retry_on_cond([](::sem_t* res) ynothrow{
170 return res == SEM_FAILED && errno == EINTR;
171 }, [=]() ynothrow{
172 // NOTE: Some implementations may force shared lock when
173 // %O_CREAT is specified, e.g. https://www.gnu.org/software/libc/manual/html_node/Open_002dtime-Flags.html.
174 // FIXME: Blocked. Possible race condition otherwise.
175 return ::sem_open(Nonnull(n),
176 int(omode), platform::DefaultPMode(), init);
177 });
178 });
179
180 auto p(create(OpenMode::CreateExclusive));
181
182 if(p != SEM_FAILED)
183 name = n;
184 else
185 {
186 // FIXME: Blocked. TOCTTOU access. The semaphore might be recreated
187 // before the call.
188 if(errno == EEXIST)
189 p = create(OpenMode::Create);
190 // FIXME: Blocked. TOCTTOU access. The semaphore might be recreated
191 // and the creation state is not recorded properly, missing
192 // %::sem_unlink would cause leak.
193 if(YB_UNLIKELY(p == SEM_FAILED))
194 YCL_Raise_SysE(, "::sem_open", yfsig);
195 }
196 return p;
197 }())
198 #endif
199 {
200 #if !YCL_Win32
201 h_sem.get_deleter().Referent = make_observer(this);
202 #endif
203 }
204 Semaphore::Semaphore(const char16_t* n, CountType init)
205 #if YCL_Win32
206 // TODO: Allow setting of security attributes.
207 : h_sem(YCL_CallF_Win32(CreateSemaphore, {}, init,
208 std::numeric_limits<CountType>::max(), platform::wcast(n)))
209 #else
210 : Semaphore(platform::MakePathString(n).c_str(), init)
211 #endif
212 {}
213
214 void
215 Semaphore::lock()
216 {
217 #if YCL_Win32
218 WaitUnique(native_handle());
219 #else
220 platform::RetryOnInterrupted(std::bind(YCL_WrapCall_CAPI(, ::sem_wait,
221 static_cast<::sem_t*>(native_handle())), yfsig));
222 #endif
223 }
224
225 bool
226 Semaphore::try_lock() ynothrow
227 {
228 #if YCL_Win32
229 return TryWaitUnique(native_handle());
230 #else
231 return platform::RetryOnInterrupted([this]{
232 return ::sem_trywait(static_cast<::sem_t*>(native_handle()));
233 }) == 0;
234 #endif
235 }
236
237 void
238 Semaphore::unlock() ynothrow
239 {
240 #if YCL_Win32
241 const auto
242 res(YCL_TraceCallF_Win32(ReleaseSemaphore, native_handle(), 1, {}));
243
244 YAssert(res, "Invalid semaphore found.");
245 #else
246 const auto res(YCL_TraceCallF_CAPI(::sem_post,
247 static_cast<::sem_t*>(native_handle())));
248
249 YAssert(res == 0, "Invalid semaphore found.");
250 #endif
251 yunused(res);
252 }
253
254
255 pair<string, int>
256 FetchCommandOutput(const char* cmd, size_t buf_size)
257 {
258 if(YB_UNLIKELY(buf_size == 0))
259 throw std::invalid_argument("Zero buffer size found.");
260
261 string str;
262 int exit_code(0);
263
264 // TODO: Improve Win32 implementation?
265 if(const auto fp = ystdex::unique_raw(upopen(cmd, "r"), [&](std::FILE* p){
266 exit_code = upclose(p);
267 }))
268 {
269 ystdex::setnbuf(fp.get());
270
271 // TODO: Improve performance?
272 const auto p_buf(make_unique_default_init<char[]>(buf_size));
273
274 for(size_t n; (n = std::fread(&p_buf[0], 1, buf_size, fp.get())) != 0; )
275 str.append(&p_buf[0], n);
276 }
277 else
278 YCL_Raise_SysE(, "::popen", yfsig);
279 return {std::move(str), exit_code};
280 }
281
282
283 YSLib::locked_ptr<CommandCache>
284 LockCommandCache()
285 {
286 static CommandCache cache;
287 static YSLib::mutex mtx;
288
289 return {&cache, mtx};
290 }
291
292 const string&
293 FetchCachedCommandResult(const string& cmd, size_t buf_size)
294 {
295 auto p_locked(LockCommandCache());
296 auto& cache(Deref(p_locked));
297
298 try
299 {
300 // TODO: Blocked. Use %string_view as argument using C++14 heterogeneous
301 // %find template.
302 const auto i_entry(cache.find(cmd));
303
304 return (i_entry != cache.cend() ? i_entry : (cache.emplace(cmd,
305 YB_UNLIKELY(cmd.empty()) ? string()
306 : FetchCommandOutput(cmd.c_str(), buf_size).first)).first)->second;
307 }
308 CatchExpr(std::system_error& e,
309 YTraceDe(Err, "Failed execution of command."), ExtractAndTrace(e, Err))
310 return cache[string()];
311 }
312
313
314 pair<UniqueHandle, UniqueHandle>
315 MakePipe()
316 {
317 # if YCL_Win32
318 ::HANDLE h_raw_read, h_raw_write;
319
320 YCL_CallF_Win32(CreatePipe, &h_raw_read, &h_raw_write, {}, 0);
321
322 UniqueHandle h_read(h_raw_read), h_write(h_raw_write);
323
324 YCL_CallF_Win32(SetHandleInformation, h_write.get(), HANDLE_FLAG_INHERIT,
325 HANDLE_FLAG_INHERIT);
326 return {std::move(h_read), std::move(h_write)};
327 # elif YCL_API_Has_unistd_h
328 int fds[2];
329
330 // TODO: Check whether '::socketpair' is available.
331 YCL_CallF_CAPI(, ::pipe, fds);
332
333 auto pr(make_pair(UniqueHandle(fds[0]), UniqueHandle(fds[1])));
334 auto check([](UniqueHandle& h, const char* msg) YB_NONNULL(3){
335 // NOTE: %O_NONBLOCK is initially cleared on ::pipe results.
336 // See http://pubs.opengroup.org/onlinepubs/9699919799/.
337 if(h)
338 h->SetNonblocking();
339 else
340 ystdex::throw_error(std::errc::bad_file_descriptor, msg);
341 });
342
343 check(pr.first, "Failed making pipe for reading."),
344 check(pr.second, "Failed making pipe for writing.");
345 return pr;
346 # else
347 # error "Unsupported platform found."
348 # endif
349 }
350
351
352 # if YCL_Win32
353 string
354 DecodeArg(const char* str)
355 {
356 return MBCSToMBCS(str, CP_ACP, CP_UTF8);
357 }
358
359 string
360 EncodeArg(const char* str)
361 {
362 return MBCSToMBCS(str);
363 }
364 # endif
365
366
367 #if !YCL_Android
368 namespace
370 {
371
372 template<typename _func, typename _tPointer, typename... _tParams>
373 bool
374 CallTe(_func pmf, _tPointer& p, _tParams&... args)
375 {
376 return ystdex::call_value_or(ystdex::bind1(pmf, std::ref(args)...), p);
377 }
378
379 } // unnamed namespace;
380
381 # if YCL_Win32
382 class TerminalData : private WConsole
383 {
384 public:
386 TerminalData(int fd)
387 : WConsole(ToHandle(fd))
388 {}
389
391 PDefH(bool, Clear, )
392 ImplRet(WConsole::Clear(), true)
393
394 PDefH(bool, RestoreAttributes, )
395 ImplRet(WConsole::RestoreAttributes(), true)
396
397 PDefH(bool, UpdateForeColor, std::uint8_t c)
398 ImplRet(WConsole::UpdateForeColor(c), true)
399 };
400 # else
401 namespace
403 {
404
405 yconstexpr const int cmap[] = {0, 4, 2, 6, 1, 5, 3, 7};
406
407 } //unnamed namespace
408
410 class TerminalData : private noncopyable, private nonmovable
411 {
412 private:
414 std::FILE* stream;
415
416 public:
417 TerminalData(std::FILE* fp)
418 : stream(fp)
419 {}
420 private:
422 bool
423 ExecuteCommand(const string&) const;
424
425 public:
427 PDefH(bool, Clear, ) ynothrow
428 ImplRet(ExecuteCommand("tput clear"))
429
430 PDefH(bool, RestoreAttributes, ) ynothrow
431 ImplRet(ExecuteCommand("tput sgr0"))
432
433 PDefH(bool, UpdateForeColor, std::uint8_t c) ynothrow
434 ImplRet(ExecuteCommand("tput setaf " + to_string(cmap[c & 7]))
435 && (c < ystdex::underlying(YSLib::Consoles::DarkGray)
436 || ExecuteCommand("tput bold")))
437 };
438
439 bool
440 TerminalData::ExecuteCommand(const string& cmd) const
441 {
442 const auto& str(FetchCachedCommandString(cmd));
443
444 if(str.empty())
445 return {};
446 std::fprintf(Nonnull(stream), "%s", str.c_str());
447 return true;
448 }
449 # endif
450
451
452 Terminal::Guard::~Guard()
453 {
454 if(p_terminal && *p_terminal)
455 FilterExceptions([this]{
456 if(YB_UNLIKELY(!p_terminal->p_data->RestoreAttributes()))
457 throw LoggedEvent("Restoring terminal attributes failed.");
458 });
459 }
460
461
462 Terminal::Terminal(std::FILE* fp)
463 : p_data([fp]()->TerminalData*{
464 # if !YCL_Win32
465 // XXX: Performance?
466 ystdex::setnbuf(fp);
467 # endif
468 const int fd(YCL_CallGlobal(fileno, Nonnull(fp)));
469
470 // NOTE: This is not necessary for Windows since it only determine
471 // whether the file descriptor is associated with a character device.
472 // However as a optimization, it is somewhat more efficient for some
473 // cases. See $2015-01 @ %Documentation::Workflow::Annual2015.
474 if(YCL_CallGlobal(isatty, fd))
475 # if YCL_Win32
476 TryRet(new TerminalData(fd))
477 # else
478 TryRet(new TerminalData(fp))
479 # endif
480 CatchExpr(Exception& e,
481 YTraceDe(Informative, "Creating console failed: %s.", e.what()))
482 return {};
483 }())
484 {}
485
486 ImplDeDtor(Terminal)
487
488 bool
489 Terminal::Clear()
490 {
491 return CallTe(&TerminalData::Clear, p_data);
492 }
493
494 Terminal::Guard
495 Terminal::LockForeColor(std::uint8_t c)
496 {
497 return Guard(*this, &Terminal::UpdateForeColor, c);
498 }
499
500 bool
501 Terminal::RestoreAttributes()
502 {
503 return CallTe(&TerminalData::RestoreAttributes, p_data);
504 }
505
506 bool
507 Terminal::UpdateForeColor(std::uint8_t c)
508 {
509 return CallTe(&TerminalData::UpdateForeColor, p_data, c);
510 }
511
512 bool
513 UpdateForeColorByLevel(Terminal& term, RecordLevel lv)
514 {
515 if(term)
516 {
517 using namespace Consoles;
518 static yconstexpr const RecordLevel
519 lvs[]{Err, Warning, Notice, Informative, Debug};
520 static yconstexpr const Color
521 colors[]{Red, Yellow, Cyan, Magenta, DarkGreen};
522 const auto
523 i(std::lower_bound(ystdex::begin(lvs), ystdex::end(lvs), lv));
524
525 if(i == ystdex::end(lvs))
526 term.RestoreAttributes();
527 else
528 term.UpdateForeColor(colors[i - lvs]);
529 return true;
530 }
531 return {};
532 }
533 #endif
534
535 } // namespace platform_ex;
536
537 #endif
538
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
platform_ex::Windows::WaitUnique
YF_API void WaitUnique(UniqueHandle::pointer, unsigned long=INFINITE)
以指定的时间间隔上限等待句柄指定的同步对象。
YSLib::Consoles::DarkGray
Definition: YConsole.h:61
ystdex::bind1
auto bind1(_func &&f, _tParams &&...args) -> decltype(std::bind(std::forward< decltype(f)>(f), std::placeholders::_1, std::forward< decltype(args)>(args)...))
复合调用 std::bind 和 std::placeholders::_1 。
Definition: functional.hpp:623
platform::Descriptions::Debug
Definition: YCommon.h:170
YSLib::UI::PDefH
PDefH(void, DisplayFor, IWidget &wgt, Timers::TimeSpan delay) ImplExpr(Show(wgt)
在一定时间内显示部件。
YSLib::UI::ynothrow
AView &y ynothrow
Definition: YWidgetView.cpp:47
platform::msg
const string & msg
Definition: Debug.h:464
YSLib::UI::args
yconstfn const string _tParams && args
Definition: Loader.h:131
YSLib::Consoles::Cyan
Definition: YConsole.h:64
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:326
platform
默认平台命名空间。
Definition: Container.h:47
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
platform_ex::Windows::TryWaitUnique
YF_API bool TryWaitUnique(UniqueHandle::pointer, unsigned long=0) ynothrow
yfsig
#define yfsig
展开为表示函数签名的预定义变量的宏。
Definition: ydef.h:728
ystdex::call_value_or
auto call_value_or(_func f, _type &&p) -> decay_t< decltype(f(*std::forward< decltype(p)>(p)))>
调用非空值或取默认值。
Definition: deref_op.hpp:140
platform::MakePathString
MakePathString
Definition: FileIO.h:62
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:464
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:131
YSLib::UI::ImplRet
const IWidget &wgt ImplRet(wgt.GetView().IsVisible()) bool YF_API Contains(const IWidget &
判断点是否在部件的可视区域内。
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:50
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:679
platform::containers::string
basic_string< char > string
Definition: Container.h:101
YCL_CallF_Win32
#define YCL_CallF_Win32(_fn,...)
Definition: MinGW32.h:190
ystdex::unique_raw
std::unique_ptr< _type > unique_raw(_pSrc *p)
Definition: memory.hpp:740
ystdex::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:280
YCL_Raise_SysE
#define YCL_Raise_SysE(_t, _msg, _sig)
按错误值和指定参数抛出第一参数指定类型的对象。
Definition: FileIO.h:1178
ystdex::max
const _type & max(const _type &a, const _type &b, _fComp comp=less< _type >())
取较大的元素。
Definition: algorithm.hpp:549
ystdex::cpp2011::end
_type * end(_type(&&array)[_vN])
Definition: range.hpp:54
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
NPL::Guard
ystdex::any Guard
作用域守护类型。
Definition: NPLA.h:958
platform::Descriptions::RecordLevel
RecordLevel
记录等级。
Definition: YCommon.h:161
YSLib::Consoles::Red
Definition: YConsole.h:65
YSLib::level
YF_API size_t level
Definition: YException.h:142
platform_ex::Windows::MBCSToMBCS
YF_API string MBCSToMBCS(string_view, unsigned=CP_UTF8, unsigned=CP_ACP)
YSLib::locked_ptr
unique_ptr< _type, unlock_delete< _tMutex, _tLock >> locked_ptr
独占所有权的锁定指针：使用线程模型对应的互斥量和锁以及 unique_ptr 。
Definition: YShellDefinition.h:108
ystdex::throw_error
void throw_error(std::error_code ec, _tParams &&...args)
抛出错误： std::system_error 或允许相同构造函数参数的异常。
Definition: ystdex/exception.h:206
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:203
ystdex
特性测试宏。
Definition: ydef.h:822
ystdex::setnbuf
int setnbuf(std::FILE *stream)
关闭流缓冲。
Definition: ystdex/cstdio.h:61
YCL_CallGlobal
#define YCL_CallGlobal(_n,...)
调用按实现修饰的具有全局保留名称的函数。
Definition: NativeAPI.h:67
YSLib::i
return i
Definition: YCoreUtilities.h:176
YSLib::Consoles::Magenta
Definition: YConsole.h:66
YModules.h
platform::Color
颜色。
Definition: Video.h:416
platform::Descriptions::Notice
Definition: YCommon.h:168
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:968
YSLib::UI::e
void e
Definition: YWidget.h:352
platform::RetryOnInterrupted
_type RetryOnInterrupted(_func f)
循环可能被中断的操作。
Definition: YCommon.h:261
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
ystdex::underlying
underlying_type_t< _type > underlying(_type val)
取枚举值的底层整数。
Definition: utility.hpp:240
ystdex::nonmovable
Definition: base.h:81
YCL_WrapCall_CAPI
#define YCL_WrapCall_CAPI(_t, _fn,...)
调用系统 C API 或其它可用 errno 取得调用状态的例程。
Definition: FileIO.h:1225
YSLib::YB_NONNULL
YF_API YB_NONNULL(1, 2) ValueNode LoadNPLA1File(const char *disp
载入 NPLA1 配置文件。
std
Definition: memory.hpp:1183
YSLib::Consoles::Yellow
Definition: YConsole.h:67
platform::Nonnull
_type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:422
YSLib::Consoles::DarkGreen
Definition: YConsole.h:55
platform::Descriptions::Warning
Definition: YCommon.h:167
platform::Descriptions::Err
Definition: YCommon.h:166
ystdex::single_thread::try_lock
int try_lock(_tLock1 &&, _tLock2 &&, _tLocks &&...)
Definition: pseudo_mutex.h:983
platform_ex
平台扩展命名空间。
Definition: Android.h:45
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
platform::Descriptions::Informative
Definition: YCommon.h:169
ystdex::noncopyable
不可复制对象：禁止派生类调用默认原型的复制构造函数和复制赋值操作符。
Definition: base.h:41
YSLib::Text::str
const char const char * str
Definition: TextFile.h:81
CHRLib::c
c
Definition: CharacterProcessing.h:81
YCL_TraceCallF_Win32
#define YCL_TraceCallF_Win32(_fn,...)
Definition: MinGW32.h:211
ystdex::retry_on_cond
result_of_t< _fCallable &&(_tParams &&...)> retry_on_cond(_fCond cond, _fCallable &&f, _tParams &&...args)
循环重复调用：代替直接使用 do-while 语句以避免过多引入作用域外的变量。
Definition: functional.hpp:1152
ystdex::single_thread::lock
void lock(_tLock1 &&, _tLock2 &&, _tLocks &&...)
Definition: pseudo_mutex.h:990
CHRLib::char16_t
char16_t((*c_ptr<< CHAR_BIT)|c_ptr[1])) inline PDefH(char16_t
取 c_ptr 指向的小端序双字节字符。
ystdex::cpp2011::begin
_type * begin(_type(&&array)[_vN])
Definition: range.hpp:46
ystdex::single_thread::mutex
Definition: pseudo_mutex.h:746
ystdex::make_unique_default_init
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique_default_init()
Definition: memory.hpp:879
YCL_CallF_CAPI
#define YCL_CallF_CAPI(_t, _fn,...)
Definition: FileIO.h:1237
ystdex::ref
lref< _type > ref(_type &t)
构造引用包装。
Definition: ref.hpp:132
platform::DefaultPMode
YF_API YB_STATELESS mode_t DefaultPMode() ynothrow
取默认权限。
Definition: FileIO.cpp:772
YSLib::ExtractAndTrace
YF_API void ExtractAndTrace(const std::exception &, RecordLevel=Err) ynothrow
使用 TraceException 展开和跟踪异常类型和信息。
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
YCL_TraceCallF_CAPI
#define YCL_TraceCallF_CAPI(_fn,...)
Definition: FileIO.h:1258
CHRLib::p
const auto p(d)
fp
tidy_ptr< std::streambuf > fp
Definition: TextManager.cpp:93
YSLib::lv
RecordLevel lv
Definition: YException.cpp:58
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125