//------------------------------------------------------------------------------------------------- void_t Signal::connectInfo( const std::vector<int_t> &a_signalNums, ///< const on_info_t a_onInfo ///< ) const { /** * FAQ: set handlers * * https://gist.github.com/jvranish/4441299 */ int_t iRv = 0; struct sigaction action; { // Block other terminal-generated signals while handler runs sigset_t blockMask; { iRv = ::sigemptyset(&blockMask); xTEST_DIFF(iRv, - 1); xFOR_EACH_CONST(std::vector<int_t>, it, a_signalNums) { if (*it == SIGKILL || *it == SIGSTOP) { continue; } iRv = ::sigaddset(&blockMask, *it); xTEST_DIFF(iRv, - 1); } } action.sa_sigaction = a_onInfo; action.sa_mask = blockMask; action.sa_flags = SA_RESTART | SA_SIGINFO; } xFOR_EACH_CONST(std::vector<int_t>, it, a_signalNums) { switch (*it) { case SIGKILL: Trace() << Format::str(xT("xLib: Signal {} ({}) cannot be caught or ignored"), xLEX_TO_STR(SIGKILL), SIGKILL); continue; case SIGSTOP: Trace() << Format::str(xT("xLib: Signal {} ({}) cannot be caught or ignored"), xLEX_TO_STR(SIGSTOP), SIGSTOP); continue; break; default: break; } iRv = ::sigaction(*it, &action, xPTR_NULL); xTEST_DIFF_MSG(iRv, - 1, Format::str(xT("Signal: {}"), decription(*it))); } }
//------------------------------------------------------------------------------------------------- inline void_t Console::pause( culong_t &a_timeoutMsec ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif std::tstring_t msg; if (a_timeoutMsec == xTIMEOUT_INFINITE) { msg = xT("Pause, press [ENTER] to continue..."); writeLine(msg); std::cin.clear(); std::cin.ignore(); } else { msg = String::format(xT("Pause, wait for %lu msec to continue..."), a_timeoutMsec); writeLine(msg); Thread::currentSleep(a_timeoutMsec); } }
//------------------------------------------------------------------------------------------------- inline longlong_t File::size() const { /** * TODO: File::size() - Do not use fseek() and ftell() to compute the size of a regular file * https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+file */ #if xTODO vFlush(); xTSTAT_STRUCT stat = {0}; // TODO: File::size() - fstat() int_t iRv = ::xTSTAT(_filePath.c_str(), &stat); xTEST_DIFF(iRv, - 1); return stat.st_size; #else long_t streamSize = - 1L; long_t currStreamPos = - 1L; currStreamPos = position(); setPosition(0, ppEnd); streamSize = position(); setPosition(currStreamPos, ppBegin); return static_cast<longlong_t>( streamSize ); #endif }
//------------------------------------------------------------------------------------------------- inline long_t File::position() const { long_t liRv = std::ftell(get()); xTEST_DIFF(liRv, - 1L); return liRv; }
//------------------------------------------------------------------------------------------------- inline bool_t File::isEmpty() const { longlong_t fileSize = size(); xTEST_DIFF(fileSize, - 1LL); return (fileSize == 0LL); }
//------------------------------------------------------------------------------------------------- inline tchar_t File::readChar() const { twint_t iRv = xTFGETC(get()); xTEST_DIFF(iRv, xTEOF); return static_cast<tchar_t>( iRv ); }
//------------------------------------------------------------------------------------------------- inline void_t File::writeLine( std::ctstring_t &a_str ) const { xTEST_NA(a_str); int_t iRv = xTFPUTS((a_str + Const::eol()).c_str(), get()); xTEST_DIFF(iRv, - 1); }
//------------------------------------------------------------------------------------------------- inline Console::ExModalResult Console::msgBox( std::ctstring_t &a_text, std::ctstring_t &a_title, cuint_t &a_type ) const { xUNUSED(a_type); #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif ExModalResult mrRv; enum EConsoleCmd { cmAbort = xT('a'), cmIgnore = xT('i'), cmRetry = xT('r') }; writeLine(); writeLine(xT("################################################################################")); writeLine(xT("# ") + a_title); writeLine(xT("#")); writeLine(xT("# ") + a_text); writeLine(xT("#")); writeLine(xT("################################################################################")); writeLine(); write(String::format(xT("\nAbort (%c), Ignore (%c), Retry (%c): "), cmAbort, cmIgnore, cmRetry)); EConsoleCmd cmRv = static_cast<EConsoleCmd>( std::tcin.get() ); std::tcin.ignore(); switch (cmRv) { case cmAbort: mrRv = mrAbort; writeLine(xT("Abort...")); break; case cmIgnore: mrRv = mrIgnore; writeLine(xT("Ignore...")); break; case cmRetry: mrRv = mrRetry; writeLine(xT("Retry...")); break; default: mrRv = mrRetry; writeLine(xT("Retry...")); break; } return mrRv; }
//------------------------------------------------------------------------------------------------- inline void_t File::ungetChar( ctchar_t &a_ch ) const { xTEST_NA(a_ch); twint_t iRv = xTUNGETC(a_ch, get()); xTEST_DIFF(iRv, xTEOF); xTEST_EQ(static_cast<tchar_t>( iRv ), a_ch); }
//------------------------------------------------------------------------------------------------- inline std::tstring_t Console::read() const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif return _read_impl(); }
//------------------------------------------------------------------------------------------------- inline void_t Console::clear() const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif _clear_impl(); }
//------------------------------------------------------------------------------------------------- inline void_t File::setPosition( clong_t &a_offset, const ExPointerPosition &a_pos ) const { xTEST_NA(a_offset); xTEST_NA(a_pos); int_t iRv = std::fseek(get(), a_offset, a_pos); xTEST_DIFF(iRv, - 1); }
//------------------------------------------------------------------------------------------------- inline std::tstring_t Console::setAttributesDef() const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif // n/a return _setAttributesDef_impl(); }
//------------------------------------------------------------------------------------------------- inline void_t Console::writeLine( std::ctstring_t &a_str /* = xT("") */ ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif write(a_str + Const::nl()); }
//------------------------------------------------------------------------------------------------- inline void_t File::setVBuff( char *a_buff, const ExBufferingMode &a_mode, std::csize_t &a_size ) const { xTEST_NA(a_buff); xTEST_NA(a_mode); xTEST_NA(a_size); int_t iRv = std::setvbuf(get(), a_buff, a_mode, a_size); xTEST_DIFF(iRv, - 1); }
//------------------------------------------------------------------------------------------------- inline void_t Console::writeErrLine( std::ctstring_t &a_str ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif writeLine(xT("Error: ") + a_str); pause(xTIMEOUT_INFINITE); }
//------------------------------------------------------------------------------------------------- inline void_t Console::write( std::ctstring_t &a_str ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif _write_impl(a_str); std::tcout.flush(); }
//------------------------------------------------------------------------------------------------- inline std::tstring_t Console::setAttributes( const ExForeground &a_foreground, const ExBackground &a_background, cint_t &a_attributes ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif // n/a return _setAttributes_impl(a_foreground, a_background, a_attributes); }
//------------------------------------------------------------------------------------------------- void_t Profiler::start() { xTEST_EQ(_isStarted, false); _reset(); // TODO: [skynowa] set highest thread priority { } _start = std::clock(); xTEST_DIFF(static_cast<clock_t>( - 1 ), _start); _isStarted = true; }
//------------------------------------------------------------------------------------------------- inline void_t File::read( std::tstring_t *a_buff ) const { xTEST_PTR(a_buff); clonglong_t fileSize = size(); xTEST_DIFF(static_cast<longlong_t>( ppError ), fileSize); (*a_buff).clear(); (*a_buff).resize( static_cast<size_t>( fileSize) ); xCHECK_DO(fileSize == 0LL, return); size_t uiRv = std::fread(&a_buff->at(0), 1, a_buff->size() * sizeof(std::tstring_t::value_type), get()); xTEST_EQ(uiRv, a_buff->size()); }
//------------------------------------------------------------------------------------------------- inline void_t File::locking( const ExLockingMode &a_mode, clong_t &a_bytes ) { xTEST_NA(a_mode); xTEST_NA(a_bytes); #if xENV_WIN clong_t bytes = a_bytes; #elif xENV_UNIX const off_t bytes = static_cast<off_t>( a_bytes ); #endif int_t iRv = xLOCKING(_nativeHandle(get()), a_mode, bytes); xTEST_DIFF(iRv, - 1); }
//------------------------------------------------------------------------------------------------- void_t Signal::connect( const std::vector<int_t> &a_signalNums, ///< const sighandler_t a_onSignals ///< ) const { /** * FAQ: set handlers * * https://gist.github.com/jvranish/4441299 */ int_t iRv = 0; struct sigaction action; { Utils::structZeroT(action); action.sa_handler = a_onSignals; iRv = ::sigemptyset(&action.sa_mask); xTEST_DIFF(iRv, - 1); action.sa_flags = SA_RESTART | SA_SIGINFO; } xFOR_EACH_CONST(std::vector<int_t>, it, a_signalNums) { switch (*it) { case SIGKILL: Trace() << Format::str(xT("xLib: Signal {} ({}) cannot be caught or ignored"), xLEX_TO_STR(SIGKILL), SIGKILL); continue; case SIGSTOP: Trace() << Format::str(xT("xLib: Signal {} ({}) cannot be caught or ignored"), xLEX_TO_STR(SIGSTOP), SIGSTOP); continue; break; default: break; } iRv = ::sigaction(*it, &action, xPTR_NULL); xTEST_DIFF_MSG(iRv, - 1, Format::str(xT("Signal: {}"), decription(*it))); } }
//------------------------------------------------------------------------------------------------- inline void_t Console::prompt( std::ctstring_t &a_prompt, cbool_t &a_isVisible, std::tstring_t *a_answer ) const { #if xENV_WIN xTEST_DIFF(_wnd, xWND_NATIVE_HANDLE_NULL); xTEST_EQ(_stdIn.isValid(), true); xTEST_EQ(_stdOut.isValid(), true); #endif xTEST_EQ(a_prompt.empty(), false); xTEST_PTR(a_answer); for ( ; ; ) { write(a_prompt + xT(": ")); for ( ; ; ) { ctchar_t letter = static_cast<tchar_t>( std::tcin.get() ); // asterisks xCHECK_DO(a_isVisible, write(xT("*"))); // ENTER xCHECK_DO(letter == 10, break); // BACKSPACE xCHECK_DO(letter == 0x8, a_answer->clear(); continue); a_answer->push_back(letter); } writeLine(Const::strEmpty()); xCHECK_DO(a_answer->empty(), continue); break; } }
//------------------------------------------------------------------------------------------------- size_t Profiler::stop( cptr_ctchar_t a_comment, ... ) { xTEST_EQ(_isStarted, true); // stop, get duration { _stop = std::clock(); xTEST_DIFF(static_cast<clock_t>( - 1 ), _stop); _duration = _stop - _start; xTEST_LESS_EQ(static_cast<clock_t>( 0 ), _duration); } cdouble_t durationMsec1 = (static_cast<double>( _duration ) / static_cast<double>( CLOCKS_PER_SEC )) * 1000.0; // 1 sec = 1000 msec std::size_t durationMsec2 = Utils::roundIntT<std::size_t>( durationMsec1 ); // write to log if ( !_log.filePath().empty() ) { std::tstring_t sRv; std::ctstring_t durationTime = DateTime(durationMsec2).format(xT("%H:%M:%S")); va_list args; xVA_START(args, a_comment); sRv = FormatC::strV(a_comment, args); xVA_END(args); _log.write(xT("%s: %s"), durationTime.c_str(), sRv.c_str()); } _isStarted = false; return durationMsec2; }
//------------------------------------------------------------------------------------------------- inline void_t File::flush() const { int_t iRv = std::fflush(get()); xTEST_DIFF(iRv, xTEOF); }