YSTest: Host.cpp 源文件

YSTest PreAlpha_b700_20160611 The YSLib Test Project

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

- 文件列表
- 文件成员

Host.cpp
浏览该文件的文档.
1 /*
2 © 2014-2015 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
32 #include YFM_YCLib_NativeAPI
33 #include YFM_YCLib_FileIO // for platform::FileOperationFailure,
34 // platform::ThrowFileOperationFailure;
35 #include YFM_YSLib_Core_YException // for YSLib::FilterExceptions;
36 #if YCL_Win32
37 # include YFM_Win32_YCLib_Consoles
38 # include <io.h> // for ::_isatty;
39 # include YFM_YSLib_Core_YConsole
40 #elif YF_Hosted
41 # include YFM_YSLib_Core_YConsole
42 #endif
43
44 using namespace YSLib;
46 using platform::FileOperationFailure;
48 using platform::ThrowFileOperationFailure;
50 using YSLib::string;
52 using platform::string_view;
53
54 #if YF_Hosted
55
56 namespace platform_ex
57 {
58
59 Exception::Exception(std::error_code ec, const char* str, RecordLevel lv)
60 : system_error(ec, Nonnull(str)),
61 level(lv)
62 {}
63 Exception::Exception(std::error_code ec, string_view sv, RecordLevel lv)
64 : system_error(ec, (Nonnull(sv.data()), std::string(sv))),
65 level(lv)
66 {}
67 Exception::Exception(int ev, const std::error_category& ecat, const char* str,
68 RecordLevel lv)
69 : system_error(ev, ecat, Nonnull(str)),
70 level(lv)
71 {}
72 Exception::Exception(int ev, const std::error_category& ecat, string_view sv,
73 RecordLevel lv)
74 : system_error(ev, ecat, (Nonnull(sv.data()), std::string(sv))),
75 level(lv)
76 {}
77 ImplDeDtor(Exception)
78
79
80 #if YCL_Win32
81 void
82 HandleDelete::operator()(pointer h) const ynothrow
83 {
84 YCL_CallWin32F_Trace(CloseHandle, h);
85 }
86 #endif
87
88
89 string
90 FetchCommandOutput(const char* cmd, size_t buf_size)
91 {
92 if(YB_UNLIKELY(buf_size == 0))
93 throw std::invalid_argument("Zero buffer size found.");
94 // TODO: Improve Win32 implementation?
95 if(const auto fp = ystdex::unique_raw(platform::upopen(cmd, "r"),
96 platform::upclose))
97 {
98 ystdex::setnbuf(fp.get());
99
100 // TODO: Improve performance?
101 const auto p_buf(make_unique_default_init<char[]>(buf_size));
102 string res;
103
104 for(size_t n; (n = std::fread(&p_buf[0], 1, buf_size, fp.get())) != 0; )
105 res.append(&p_buf[0], n);
106 return res;
107 }
108 ThrowFileOperationFailure("Failed opening pipe.");
109 }
110
111
112 YSLib::locked_ptr<CommandCache>
113 LockCommandCache()
114 {
115 struct cmd_cache_tag
116 {};
117 static YSLib::mutex mtx;
118
119 return {&ystdex::parameterize_static_object<CommandCache, cmd_cache_tag>(),
120 mtx};
121 }
122
123 const string&
124 FetchCachedCommandResult(const string& cmd, size_t buf_size)
125 {
126 auto p_locked(LockCommandCache());
127 auto& cache(Deref(p_locked));
128
129 try
130 {
131 // TODO: Blocked. Use %string_view as argument using C++14 heterogeneous
132 // %find template.
133 const auto i_entry(cache.find(cmd));
134
135 return (i_entry != cache.cend() ? i_entry : (cache.emplace(cmd,
136 YB_UNLIKELY(cmd.empty()) ? string()
137 : FetchCommandOutput(cmd.c_str(), buf_size))).first)->second;
138 }
139 CatchExpr(FileOperationFailure& e,
140 YTraceDe(Err, "Command execution failed: %s", e.what()))
141 return cache[string()];
142 }
143
144
145 pair<UniqueHandle, UniqueHandle>
146 MakePipe()
147 {
148 # if YCL_Win32
149 ::HANDLE h_raw_read, h_raw_write;
150
151 YCL_CallWin32F(CreatePipe, &h_raw_read, &h_raw_write, {}, 0);
152
153 UniqueHandle h_read(h_raw_read), h_write(h_raw_write);
154
155 YCL_CallWin32F(SetHandleInformation, h_write.get(), HANDLE_FLAG_INHERIT,
156 HANDLE_FLAG_INHERIT);
157 return {std::move(h_read), std::move(h_write)};
158 # elif YCL_API_Has_unistd_h
159 int fds[2];
160
161 // TODO: Check whether '::socketpair' is available.
162 if(::pipe(fds) != 0)
163 ThrowFileOperationFailure("Failed getting file size.");
164
165 auto pr(make_pair(UniqueHandle(fds[0]), UniqueHandle(fds[1])));
166 auto check([](UniqueHandle& h, const char* msg){
167 // NOTE: %O_NONBLOCK is initially cleared on ::pipe results.
168 // See http://pubs.opengroup.org/onlinepubs/9699919799/.
169 if(!(h && h->SetNonblocking()))
170 ThrowFileOperationFailure(msg);
171 });
172
173 check(pr.first, "Failed making pipe for reading."),
174 check(pr.second, "Failed making pipe for writing.");
175 return pr;
176 # else
177 # error "Unsupported platform found."
178 # endif
179 }
180
181
182 # if YCL_Win32
183 string
184 DecodeArg(const char* str)
185 {
186 return MBCSToMBCS(str, CP_ACP, CP_UTF8);
187 }
188
189 string
190 EncodeArg(const char* str)
191 {
192 return MBCSToMBCS(str);
193 }
194 # endif
195
196
197 #if !YCL_Android
198 # if YCL_Win32
199 class TerminalData : private WConsole
200 {
201 public:
203 TerminalData(int fd)
204 : WConsole(::HANDLE(::_get_osfhandle(fd)))
205 {}
206
207 PDefH(bool, RestoreAttributes, )
208 ImplRet(WConsole::RestoreAttributes(), true)
209
210 PDefH(bool, UpdateForeColor, std::uint8_t c)
211 ImplRet(WConsole::UpdateForeColor(c), true)
212 };
213 # else
214 namespace
216 {
217
218 yconstexpr const int cmap[] = {0, 4, 2, 6, 1, 5, 3, 7};
219
220 } //unnamed namespace
221
223 class TerminalData : private noncopyable, private nonmovable
224 {
225 private:
227 std::FILE* stream;
228
229 public:
230 TerminalData(std::FILE* fp)
231 : stream(fp)
232 {}
233 private:
235 bool
236 ExecuteCommand(const string&) const;
237
238 public:
239 PDefH(bool, RestoreAttributes, ) ynothrow
240 ImplRet(ExecuteCommand("tput sgr0"))
241
242 PDefH(bool, UpdateForeColor, std::uint8_t c) ynothrow
243 ImplRet(ExecuteCommand("tput setaf " + to_string(cmap[c & 7]))
244 && (c < ystdex::underlying(YSLib::Consoles::DarkGray)
245 || ExecuteCommand("tput bold")))
246 };
247
248 bool
249 TerminalData::ExecuteCommand(const string& cmd) const
250 {
251 const auto& str(FetchCachedCommandString(cmd));
252
253 if(str.empty())
254 return {};
255 std::fprintf(Nonnull(stream), "%s", str.c_str());
256 return true;
257 }
258 # endif
259
260
261 Terminal::Guard::~Guard()
262 {
263 if(terminal)
264 FilterExceptions([this]{
265 if(!YB_LIKELY(terminal.p_term->RestoreAttributes()))
266 throw LoggedEvent("Restoring terminal attributes failed.");
267 });
268 }
269
270
271 Terminal::Terminal(std::FILE* fp)
272 : p_term([fp]()->TerminalData*{
273 # if YCL_Win32
274 const int fd(::_fileno(Nonnull(fp)));
275
276 // NOTE: This is not necessary for Windows since it only determine
277 // whether the file descriptor is associated with a character device.
278 // However as a optimization, it is somewhat more efficient for some
279 // cases. See $2015-01 @ %Documentation::Workflow::Annual2015.
280 if(::_isatty(fd))
281 TryRet(new TerminalData(fd))
282 # else
283 // XXX: Performance?
284 ystdex::setnbuf(fp);
285
286 const int fd(fileno(Nonnull(fp)));
287
288 if(::isatty(fd))
289 TryRet(new TerminalData(fp))
290 # endif
291 CatchExpr(Exception& e,
292 YTraceDe(Informative, "Creating console failed: %s.", e.what()))
293 return {};
294 }())
295 {}
296
297 ImplDeDtor(Terminal)
298
299 bool
300 Terminal::RestoreAttributes()
301 {
302 return p_term ? p_term->RestoreAttributes() : false;
303 }
304
305 bool
306 Terminal::UpdateForeColor(std::uint8_t c)
307 {
308 return p_term ? p_term->UpdateForeColor(c) : false;
309 }
310
311 bool
312 UpdateForeColorByLevel(Terminal& term, RecordLevel lv)
313 {
314 if(term)
315 {
316 using namespace Consoles;
317 static yconstexpr const RecordLevel
318 lvs[]{Err, Warning, Notice, Informative, Debug};
319 static yconstexpr const Color
320 colors[]{Red, Yellow, Cyan, Magenta, DarkGreen};
321 const auto i(std::lower_bound(ystdex::begin(lvs), ystdex::end(lvs), lv));
322
323 if(i == ystdex::end(lvs))
324 term.RestoreAttributes();
325 else
326 term.UpdateForeColor(colors[i - lvs]);
327 return true;
328 }
329 return {};
330 }
331 #endif
332
333 } // namespace platform_ex;
334
335 #endif
336
NPL::term
const TermNode &term ValueNode &node const ValueNode &node const TermNode & term
Definition: SContext.h:72
YSLib::lv
RecordLevel lv
Definition: YException.cpp:58
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
YSLib::locked_ptr
unique_ptr< _type, unlock_delete< _tMutex, _tLock >> locked_ptr
独占所有权的锁定指针：使用线程模型对应的互斥量和锁以及 unique_ptr 。
Definition: YShellDefinition.h:108
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:653
platform::containers::string
basic_string< char > string
Definition: Container.h:101
platform::Nonnull
_type && Nonnull(_type &&p) ynothrow
断言并返回非空指针。
Definition: Debug.h:411
platform::Descriptions::Warning
Definition: YCommon.h:157
platform::Descriptions::Informative
Definition: YCommon.h:159
YSLib::Consoles::Magenta
Definition: YConsole.h:66
ystdex::underlying
underlying_type_t< _type > underlying(_type val)
取枚举值的底层整数。
Definition: utility.hpp:120
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
YSLib::Consoles::Yellow
Definition: YConsole.h:67
platform::Color
颜色。
Definition: Video.h:451
YSLib::UI::ImplRet
const IWidget &wgt ImplRet(wgt.GetView().IsVisible()) bool YF_API Contains(const IWidget &
判断点是否在部件的可视区域内。
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:202
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:49
ystdex::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:280
CHRLib::c
c
Definition: CharacterProcessing.h:81
YCL_CallWin32F
#define YCL_CallWin32F(_fn,...)
Definition: MinGW32.h:179
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:305
YSLib::Consoles::Cyan
Definition: YConsole.h:64
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
platform::upclose
int upclose(std::FILE *fp) ynothrowv
Definition: FileIO.cpp:892
YSLib::Consoles::DarkGreen
Definition: YConsole.h:55
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:438
std
Definition: memory.hpp:1100
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:440
YSLib::Consoles::DarkGray
Definition: YConsole.h:61
platform_ex::Windows::MBCSToMBCS
YF_API string MBCSToMBCS(string_view, unsigned=CP_UTF8, unsigned=CP_ACP)
platform_ex
平台扩展命名空间。
Definition: Android.h:45
ystdex::make_unique_default_init
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique_default_init()
Definition: memory.hpp:756
ystdex
特性测试宏。
Definition: ydef.h:796
YSLib::Text::str
const char const char * str
Definition: TextFile.h:77
platform::FileOperationFailure
表示文件操作失败的异常。
Definition: FileIO.h:1142
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
ystdex::nonmovable
Definition: base.h:81
YModules.h
fp
tidy_ptr< std::istream > fp
Definition: TextManager.cpp:86
YSLib::i
return i
Definition: YCoreUtilities.h:176
YSLib::UI::e
void e
Definition: YWidget.h:352
platform::Descriptions::Debug
Definition: YCommon.h:160
YB_LIKELY
#define YB_LIKELY(_expr)
Definition: ydef.h:437
ystdex::noncopyable
不可复制对象：禁止派生类调用默认原型的复制构造函数和复制赋值操作符。
Definition: base.h:41
ystdex::single_thread::mutex
Definition: pseudo_mutex.h:63
YSLib::level
YF_API size_t level
Definition: YException.h:141
ystdex::setnbuf
int setnbuf(std::FILE *stream)
关闭流缓冲。
Definition: ystdex/cstdio.h:61
platform::Descriptions::RecordLevel
RecordLevel
记录等级。
Definition: YCommon.h:151
ystdex::cpp2011::begin
_type * begin(_type(&&array)[_vN])
Definition: range.hpp:46
platform::Descriptions::Err
Definition: YCommon.h:156
platform::upopen
std::FILE * upopen(const char *filename, const char *mode) ynothrowv
Definition: FileIO.cpp:906
YSLib::UI::PDefH
PDefH(void, DisplayFor, IWidget &wgt, Timers::TimeSpan delay) ImplExpr(Show(wgt)
在一定时间内显示部件。
platform::Descriptions::Notice
Definition: YCommon.h:158
ystdex::unique_raw
std::unique_ptr< _type > unique_raw(_pSrc *p)
Definition: memory.hpp:617
ystdex::cpp2011::end
_type * end(_type(&&array)[_vN])
Definition: range.hpp:54
YCL_CallWin32F_Trace
#define YCL_CallWin32F_Trace(_fn,...)
Definition: MinGW32.h:202
platform::n
size_t n
Definition: YCLib/FileSystem.cpp:321
YSLib::Consoles::Red
Definition: YConsole.h:65