diff options
Diffstat (limited to '')
-rw-r--r-- | contrib/otshell_utils/utils.cpp | 806 |
1 files changed, 0 insertions, 806 deletions
diff --git a/contrib/otshell_utils/utils.cpp b/contrib/otshell_utils/utils.cpp deleted file mode 100644 index ef9b37f03..000000000 --- a/contrib/otshell_utils/utils.cpp +++ /dev/null @@ -1,806 +0,0 @@ -/// @file -/// @author rfree (current maintainer in monero.cc project) -/// @brief various general utils taken from (and relate to) otshell project, including loggiang/debug - -/* See other files here for the LICENCE that applies here. */ -/* See header file .hpp for info */ - -#include <algorithm> -#include <functional> -#include <cctype> -#include <locale> -#include <fstream> -#include <iostream> -#include <iomanip> -#include <chrono> - -#include "utils.hpp" - -#include "ccolor.hpp" - -#include "lib_common1.hpp" - -#include "runoptions.hpp" - -#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined (WIN64) - #define OS_TYPE_WINDOWS -#elif defined(__unix__) || defined(__posix) || defined(__linux) || defined(__darwin) || defined(__APPLE__) || defined(__clang__) - #define OS_TYPE_POSIX -#else - #warning "Compiler/OS platform is not recognized. Just assuming it will work as POSIX then" - #define OS_TYPE_POSIX -#endif - -#if defined(OS_TYPE_WINDOWS) - #include <windows.h> - #include <process.h> -#elif defined(OS_TYPE_POSIX) - #include <sys/types.h> - #include <sys/stat.h> - #include <unistd.h> -#else - #error "Compiler/OS platform detection failed - not supported" -#endif - - -namespace nOT { -namespace nUtils { - -INJECT_OT_COMMON_USING_NAMESPACE_COMMON_1 // <=== namespaces - -// ==================================================================== - -// Numerical values of the debug levels - see hpp -const int _debug_level_nr_dbg3=20; -const int _debug_level_nr_dbg2=30; -const int _debug_level_nr_dbg1=40; -const int _debug_level_nr_info=50; -const int _debug_level_nr_note=60; -const int _debug_level_nr_fact=75; -const int _debug_level_nr_mark=80; -const int _debug_level_nr_warn=90; -const int _debug_level_nr_erro=100; - -// ==================================================================== - -myexception::myexception(const char * what) - : std::runtime_error(what) -{ } - -myexception::myexception(const std::string &what) - : std::runtime_error(what) -{ } - -void myexception::Report() const { - _erro("Error: " << what()); -} - -//myexception::~myexception() { } - -// ==================================================================== - -// text trimming -// http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring -std::string & ltrim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace)))); - return s; -} - -std::string & rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); - return s; -} - -std::string & trim(std::string &s) { - return ltrim(rtrim(s)); -} - -std::string get_current_time() { - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - time_t time_now = std::chrono::system_clock::to_time_t(now); - std::chrono::high_resolution_clock::duration duration = now.time_since_epoch(); - int64_t micro = std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); - - // std::localtime() - This function may not be thread-safe. - #ifdef OS_TYPE_WINDOWS - struct tm * tm_pointer = std::localtime( &time_now ); // thread-safe on mingw-w64 (thread local variable) and on MSVC btw - // http://stackoverflow.com/questions/18551409/localtime-r-support-on-mingw - // tm_pointer points to thread-local data, memory is owned/managed by the system/library - #else - // linux, freebsd, have this - struct tm tm_object; // automatic storage duration http://en.cppreference.com/w/cpp/language/storage_duration - struct tm * tm_pointer = & tm_object; // just point to our data - auto x = localtime_r( &time_now , tm_pointer ); // modifies our own (this thread) data in tm_object, this is safe http://linux.die.net/man/3/localtime_r - if (x != tm_pointer) return "(internal error in get_current_time)"; // redundant check in case of broken implementation of localtime_r - #endif - // tm_pointer now points to proper time data, and that memory is automatically managed - if (!tm_pointer) return "(internal error in get_current_time - NULL)"; // redundant check in case of broken implementation of used library methods - - std::stringstream stream; - stream << std::setfill('0') - << std::setw(2) << tm_pointer->tm_year+1900 - << '-' << std::setw(2) << tm_pointer->tm_mon+1 - << '-' << std::setw(2) << tm_pointer->tm_mday - << ' ' << std::setw(2) << tm_pointer->tm_hour - << ':' << std::setw(2) << tm_pointer->tm_min - << ':' << std::setw(2) << tm_pointer->tm_sec - << '.' << std::setw(6) << (micro%1000000); // 6 because microseconds - return stream.str(); -} - -cNullstream g_nullstream; // extern a stream that does nothing (eats/discards data) - -boost::recursive_mutex gLoggerGuard; // extern -std::atomic<int> gLoggerGuardDepth; // extern - -std::atomic<int> & gLoggerGuardDepth_Get() { - // TODO std::once would be nicer here - - static bool once=0; - - if (!once) { // initialize it once - once=1; - gLoggerGuardDepth=0; - } - - return gLoggerGuardDepth; // global, atomic counter -} - - -// ==================================================================== - -namespace nDetail { - -const char* DbgShortenCodeFileName(const char *s) { - const char *p = s; - const char *a = s; - - bool inc=1; - while (*p) { - ++p; - if (inc && ('\0' != * p)) { a=p; inc=false; } // point to the current character (if valid) becasue previous one was slash - if ((*p)=='/') { a=p; inc=true; } // point at current slash (but set inc to try to point to next character) - } - return a; -} - -} - -// a workaround for MSVC compiler; e.g. see https://bugs.webkit.org/show_bug.cgi?format=multiple&id=125795 -#ifndef _MSC_VER -template<typename T, typename ...Args> -std::unique_ptr<T> make_unique( Args&& ...args ) -{ - return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) ); -} -#else - using std::make_unique; -#endif -// ==================================================================== - -char cFilesystemUtils::GetDirSeparatorSys() { - // TODO nicer os detection? - #if defined(OS_TYPE_POSIX) - return '/'; - #elif defined(OS_TYPE_WINDOWS) - return '\\'; - #else - #error "Do not know how to compile this for your platform." - #endif -} - -char cFilesystemUtils::GetDirSeparatorInter() { - return '/'; -} - -string cFilesystemUtils::FileInternalToSystem(const std::string &name) { - string ret; - ret.resize(name.size()); - std::replace_copy(name.begin(), name.end(), ret.begin(), - GetDirSeparatorInter() , GetDirSeparatorSys()); - return ret; -} - -string cFilesystemUtils::FileSystemToInternal(const std::string &name) { - string ret; - ret.reserve(name.size()); - std::replace_copy(name.begin(), name.end(), ret.begin(), - GetDirSeparatorSys() , GetDirSeparatorInter()); - return ret; -} - -bool cFilesystemUtils::CreateDirTree(const std::string & dir, bool only_below) { - const bool dbg=false; - //struct stat st; - const char dirchS = cFilesystemUtils::GetDirSeparatorSys(); - const char dirchI = cFilesystemUtils::GetDirSeparatorInter(); - std::istringstream iss(dir); - string partI; // current par is in internal format (though it should not matter since it doesn't contain any slashes). eg "bar" - string sofarS=""; // sofarS - the so far created dir part is in SYSTEM format. eg "foo/bar" - if (dir.size()<1) return false; // illegal name - // dir[0] is valid from here - if ( only_below && ((dir[0]==dirchS) || (dir[0]==dirchI))) return false; // no jumping to top (on any os) - - while (getline(iss,partI,dirchI)) { // get new component eg "bar" into part - if (dbg) cout << '['<<partI<<']' << endl; - sofarS += partI; - if (partI.size()<1) return false; // bad format? - if ((only_below) && (partI=="..")) return false; // trying to go up - - if (dbg) cout << "test ["<<sofarS<<"]"<<endl; - // TODO nicer os detection? - #if defined(OS_TYPE_POSIX) - struct stat st; - bool exists = stat(sofarS.c_str() ,&st) == 0; // * - if (exists) { - if (! S_ISDIR(st.st_mode)) { - // std::cerr << "This exists, but as a file: [" << sofar << "]" << (size_t)st.st_ino << endl; - return false; // exists but is a file nor dir - } - } - #elif defined(OS_TYPE_WINDOWS) - DWORD dwAttrib = GetFileAttributesA(sofarS.c_str()); - bool exists = (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); - #else - #error "Do not know how to compile this for your platform." - #endif - - if (!exists) { - if (dbg) cout << "mkdir ["<<sofarS<<"]"<<endl; - #if defined(OS_TYPE_POSIX) - bool ok = 0== mkdir(sofarS.c_str(), 0700); // *** - #elif defined(OS_TYPE_WINDOWS) - bool ok = (bool) CreateDirectoryA(sofarS.c_str(), NULL); // TODO use -W() after conversion to unicode UTF16 - #else - #error "Do not know how to compile this for your platform." - #endif - if (!ok) return false; - } - sofarS += dirchS; - } - return true; -} -// ==================================================================== - -namespace nDetail { - -struct channel_use_info { ///< feedback information about using (e.g. opening) given debug channel - used internally by logging system -/// TODO not yet used in code -/// e.g. used to write into channel net/in/all that given message was a first logged message from never-before-logged thread or PID etc - bool m_was_interesting; ///< anything interesting happened when using the channel? - std::vector<std::string> m_extra_msg; ///< any additional messages about this channel use -}; - -cDebugScopeGuard::cDebugScopeGuard() : mLevel(-1) { -} - -cDebugScopeGuard::~cDebugScopeGuard() { - if (mLevel != -1) { - gCurrentLogger.write_stream(mLevel,mChan) << mMsg << " ... end" << gCurrentLogger.endline() << std::flush; - } -} - -void cDebugScopeGuard::Assign(const string &chan, const int level, const string &msg) { - mChan=chan; - mLevel=level; - mMsg=msg; -} - -} // namespace nDetail - -// ==================================================================== - -cLogger::cLogger() : -mStream(NULL), -mStreamBrokenDebug(NULL), -mIsBroken(true), // before constructor finishes -mLevel(_debug_level_nr_warn), -mThread2Number_Biggest(0), // the CURRENT biggest value (no thread yet in map) -mPid2Number_Biggest(0) -{ - mStream = & std::cout; - mStreamBrokenDebug = & std::cerr; // the backup stream - *mStreamBrokenDebug << "Creating the logger system" << endl; - mIsBroken=false; // ok, constr. succeeded, so string is not broken now - - // this is here, because it could be using logging itself to log creation of first thread/PID etc - Thread2Number( boost::this_thread::get_id() ); // convert current id to short number, useful to reserve a number so that main thread is usually called 1 - Pid2Number( getpid() ); // add this proces ID as first one -} - -cLogger::~cLogger() { - for (auto pair : mChannels) { - std::ofstream *ptr = pair.second; - delete ptr; - pair.second=NULL; - } -} - -void cLogger::SetStreamBroken() { - SetStreamBroken("(no additional details about this problem)"); -} - -void cLogger::SetStreamBroken(const std::string &msg) { - _dbg_dbg("Stream is broken (msg: " << msg << ")"); - if (!mIsBroken) { // if not already marked as broken - _dbg_dbg("(It was not broken before)"); - std::cerr << OT_CODE_STAMP << "WARNING: due to a problem in the debug/logging system itself ("<<msg<<") - we are switching back to fallback stream (e.g. cerr)" << std::endl; - if (mStreamBrokenDebug == nullptr) { - std::cerr << OT_CODE_STAMP << " ERROR: in addition, while reporting this problem, mStreamBrokenDebug stream is NULL: " << mStreamBrokenDebug << std::endl; - } else { - (*mStreamBrokenDebug) << OT_CODE_STAMP << "WARNING: due to debug stream problem ("<<msg<<") - switching back to fallback stream (e.g. cerr)" << std::endl; - } - mIsBroken = true; - } -} - -std::ostream & cLogger::write_stream(int level) { - return write_stream(level,""); -} - -std::ostream & cLogger::write_stream(int level, const std::string & channel ) { - _dbg_dbg("level="<<level<<" channel="<<channel); - if (level >= mLevel) { - if (mStream) { // TODO now disabling mStream also disables writting to any channel - _dbg_dbg("Selecting output..."); - ostream & output = SelectOutput(level,channel); - _dbg_dbg("Selecting output... done, output=" << (void*)(&output)); - #if defined(OS_TYPE_WINDOWS) - output << windows_stream(level); - #endif - output << icon(level) << ' '; - boost::thread::id this_id = boost::this_thread::get_id(); - output << "{" << Thread2Number(this_id) << "}"; - auto nicePid = Pid2Number(getpid()); - if (nicePid>0) output << " {p" << nicePid << "}"; - output << ' '; - return output; // <--- return - } else _dbg_dbg("Not writting: No mStream"); - } else _dbg_dbg("Not writting: Too low level level="<<level<<" not >= mLevel="<<mLevel); - return g_nullstream; -} - -std::string cLogger::GetLogBaseDir() const { - return "log"; -} - -void cLogger::OpenNewChannel(const std::string & channel) noexcept { - try { - _dbg_dbg("Openning channel for channel="<<channel); - OpenNewChannel_(channel); - } - catch (const std::exception &except) { - SetStreamBroken(OT_CODE_STAMP + " Got exception when opening debug channel: " + ToStr(except.what())); - } - catch (...) { - SetStreamBroken(OT_CODE_STAMP + " Got not-standard exception when opening debug channel."); - } -} - -void cLogger::OpenNewChannel_(const std::string & channel) { // channel=="net/sleep" - _dbg_dbg("Openning channel for channel="<<channel); - size_t last_split = channel.find_last_of(cFilesystemUtils::GetDirSeparatorInter()); - - string fname_system; // the full file name in system format - - if (last_split==string::npos) { // The channel name has no directory, eg channel=="test" - string dir = GetLogBaseDir(); - string basefile = channel + ".log"; - string fname = dir + cFilesystemUtils::GetDirSeparatorInter() + basefile; - fname_system = cFilesystemUtils::FileInternalToSystem(fname); // <- - } - else { // there is a directory eg channel=="net/sleep" - // net/sleep - // ^----- last_split - string dir = GetLogBaseDir() + cFilesystemUtils::GetDirSeparatorInter() + channel.substr(0, last_split); - string basefile = channel.substr(last_split+1) + ".log"; - string fname = dir + cFilesystemUtils::GetDirSeparatorInter() + basefile; - fname_system = cFilesystemUtils::FileInternalToSystem(fname); // <- - bool dirok = cFilesystemUtils::CreateDirTree(dir); - if (!dirok) { string err = "In logger failed to open directory (" + dir +") for channel (" + channel +")"; throw std::runtime_error(err); } - } - - _dbg_dbg("Openning fname_system="<<fname_system); - std::ofstream * thefile = new std::ofstream( fname_system.c_str() ); // file system - *thefile << "====== Log opened: " << fname_system << " (in " << ((void*)thefile) << ") ======" << endl; -// cerr << "====== Log opened: " << fname_system << " (in " << ((void*)thefile) << ") ======" << endl; - _dbg_dbg( "====== Log opened: " << fname_system << " (in " << ((void*)thefile) << ") ======" ); - mChannels.insert( std::pair<string,std::ofstream*>(channel , thefile ) ); // <- created the channel mapping -} - -std::ostream & cLogger::SelectOutput(int level, const std::string & channel) noexcept { - try { - if (mIsBroken) { - _dbg_dbg("The stream is broken mIsBroken="<<mIsBroken<<" so will return backup stream"); - return *mStreamBrokenDebug; - } - if (channel=="") { - _dbg_dbg("No channel given (channel="<<channel<<") so will return main stream"); - return *mStream; - } - - auto obj = mChannels.find(channel); - if (obj == mChannels.end()) { // not found - need to make new channel - _dbg_dbg("No stream openened for channel="<<channel<<" so will create it now"); - OpenNewChannel(channel); // <- create channel - obj = mChannels.find(channel); // find again - if (obj == mChannels.end()) { // still not found! something is wrong - SetStreamBroken( OT_CODE_STAMP + " WARNING: can not get stream for channel="+ToStr(channel)+" level="+ToStr(channel) ); - return *mStreamBrokenDebug; - } - } - auto the_stream_ptr = obj->second; - _dbg_dbg("Found the stream file for channel="<<channel<<" as the_stream_ptr="<<the_stream_ptr); - ASRT(the_stream_ptr); - return *the_stream_ptr; // <--- RETURN - } - catch (std::exception &except) { - SetStreamBroken( OT_CODE_STAMP + " Got exception: " + ToStr(except.what()) ); - _dbg_dbg("Exception! Returning broken stream"); - return *mStreamBrokenDebug; - } - catch (...) { - SetStreamBroken( OT_CODE_STAMP + " Got not-standard exception."); - _dbg_dbg("Exception! Returning broken stream"); - return *mStreamBrokenDebug; - } - - // dead code -} - -void cLogger::setOutStreamFile(const string &fname) { // switch to using this file - _mark("WILL SWITCH DEBUG NOW to file: " << fname); - mOutfile = make_unique<std::ofstream>(fname); - mStream = & (*mOutfile); - _mark("Started new debug, to file: " << fname); -} - -void cLogger::setOutStreamFromGlobalOptions() { - if ( gRunOptions.getDebug() ) { - if ( gRunOptions.getDebugSendToFile() ) { - mOutfile = make_unique<std::ofstream> ("debuglog.txt"); - mStream = & (*mOutfile); - } - else if ( gRunOptions.getDebugSendToCerr() ) { - mStream = & std::cerr; - } - else { - mStream = & g_nullstream; - } - } - else { - mStream = & g_nullstream; - } -} - -void cLogger::setDebugLevel(int level) { - bool note_before = (mLevel > level); // report the level change before or after the change? (on higher level) - if (note_before) _note("Setting debug level to "<<level); - mLevel = level; - if (!note_before) _note("Setting debug level to "<<level); -} - -std::string cLogger::icon(int level) const { - // TODO replan to avoid needles converting back and forth char*, string etc - - using namespace zkr; - #if defined(OS_TYPE_POSIX) - if (level >= 100) return cc::back::lightred + ToStr(cc::fore::lightyellow) + ToStr("ERROR ") + ToStr(cc::fore::lightyellow) + " " ; - if (level >= 90) return cc::back::lightyellow + ToStr(cc::fore::black) + ToStr("Warn ") + ToStr(cc::fore::red)+ " " ; - if (level >= 80) return cc::back::lightmagenta + ToStr(cc::fore::black) + ToStr("MARK "); //+ zkr::cc::console + ToStr(cc::fore::lightmagenta)+ " "; - if (level >= 75) return cc::back::lightyellow + ToStr(cc::fore::black) + ToStr("FACT ") + zkr::cc::console + ToStr(cc::fore::lightyellow)+ " "; - if (level >= 70) return cc::fore::green + ToStr("Note "); - if (level >= 50) return cc::fore::cyan + ToStr("info "); - if (level >= 40) return cc::fore::lightwhite + ToStr("dbg "); - if (level >= 30) return cc::fore::lightblue + ToStr("dbg "); - if (level >= 20) return cc::fore::blue + ToStr("dbg "); - - #elif defined(OS_TYPE_WINDOWS) - if (level >= 100) return ToStr("ERROR "); - if (level >= 90) return ToStr("Warn "); - if (level >= 80) return ToStr("MARK "); - if (level >= 75) return ToStr("FACT "); - if (level >= 70) return ToStr("Note "); - if (level >= 50) return ToStr("info "); - if (level >= 40) return ToStr("dbg "); - if (level >= 30) return ToStr("dbg "); - if (level >= 20) return ToStr("dbg "); - #endif - - return " "; -} - -std::string cLogger::endline() const { - #if defined(OS_TYPE_POSIX) - return ToStr("") + zkr::cc::console + ToStr("\n"); // TODO replan to avoid needles converting back and forth char*, string etc - #elif defined(OS_TYPE_WINDOWS) - return ToStr("\n"); - #endif -} - -int cLogger::Thread2Number(const boost::thread::id id) { - auto found = mThread2Number.find( id ); - if (found == mThread2Number.end()) { // new one - mThread2Number_Biggest++; - mThread2Number[id] = mThread2Number_Biggest; - _info_c("dbg/main", "This is a new thread (used in debug), thread id="<<id); // can cause some recursion - return mThread2Number_Biggest; - } else { - return mThread2Number[id]; - } -} - -int cLogger::Pid2Number(const t_anypid id) { - auto found = mPid2Number.find( id ); - if (found == mPid2Number.end()) { // new one - mPid2Number_Biggest++; - mPid2Number[id] = mPid2Number_Biggest; - _info_c("dbg/main", "This is a new process (used in debug), process pid="<<id); // can cause some recursion - return mPid2Number_Biggest; - } else { - return mPid2Number[id]; - } -} - -// ==================================================================== -// object gCurrentLogger is defined later - in global namespace below - - -// ==================================================================== -// vector debug - -void DisplayStringEndl(std::ostream & out, const std::string text) { - out << text; - out << std::endl; -} - -std::string SpaceFromEscape(const std::string &s) { - std::ostringstream newStr; - for(size_t i = 0; i < s.length();i++) { - if(s[i] == '\\' && s[i+1] ==32) - newStr<<""; - else - newStr<<s[i]; - } - return newStr.str(); -} - -std::string EscapeFromSpace(const std::string &s) { - std::ostringstream newStr; - for(size_t i = 0; i < s.length();i++) { - if(s[i] == 32) - newStr << "\\" << " "; - else - newStr << s[i]; - } - return newStr.str(); -} - - -std::string EscapeString(const std::string &s) { - std::ostringstream newStr; - for(size_t i = 0; i < s.length();i++) { - if(s[i] >=32 && s[i] <= 126) - newStr<<s[i]; - else - newStr<<"\\"<< (int) s[i]; - } - - return newStr.str(); -} - - -bool CheckIfBegins(const std::string & beggining, const std::string & all) { - if (all.compare(0, beggining.length(), beggining) == 0) { - return 1; - } - else { - return 0; - } -} - -bool CheckIfEnds (std::string const & ending, std::string const & all){ - if (all.length() >= ending.length()) { - return (0 == all.compare (all.length() - ending.length(), ending.length(), ending)); - } else { - return false; - } -} - - -vector<string> WordsThatMatch(const std::string & sofar, const vector<string> & possib) { - vector<string> ret; - for ( auto rec : possib) { // check of possibilities - if (CheckIfBegins(sofar,rec)) { - rec = EscapeFromSpace(rec); - ret.push_back(rec); // this record matches - } - } - return ret; -} - -char GetLastChar(const std::string & str) { // TODO unicode? - auto s = str.length(); - if (s==0) throw std::runtime_error("Getting last character of empty string (" + ToStr(s) + ")" + OT_CODE_STAMP); - return str.at( s - 1); -} - -std::string GetLastCharIf(const std::string & str) { // TODO unicode? - auto s = str.length(); - if (s==0) return ""; // empty string signalizes ther is nothing to be returned - return std::string( 1 , str.at( s - 1) ); -} - -// ==================================================================== - -// ASRT - assert. Name like ASSERT() was too long, and ASS() was just... no. -// Use it like this: ASRT( x>y ); with the semicolon at end, a clever trick forces this syntax :) - -void Assert(bool result, const std::string &stamp, const std::string &condition) { - if (!result) { - _erro("Assert failed at "+stamp+": ASSERT( " << condition << ")"); - throw std::runtime_error("Assert failed at "+stamp+": ASSERT( " + condition + ")"); - } -} - -// ==================================================================== -// advanced string - -const std::string GetMultiline(string endLine) { - std::string result(""); // Taken from OT_CLI_ReadUntilEOF - while (true) { - std::string input_line(""); - if (std::getline(std::cin, input_line, '\n')) - { - input_line += "\n"; - if (input_line[0] == '~') - break; - result += input_line; - } - if (std::cin.eof() ) - { - std::cin.clear(); - break; - } - if (std::cin.fail() ) - { - std::cin.clear(); - break; - } - if (std::cin.bad()) - { - std::cin.clear(); - break; - } - } - return result; -} - -vector<string> SplitString(const string & str){ - std::istringstream iss(str); - vector<string> vec { std::istream_iterator<string>{iss}, std::istream_iterator<string>{} }; - return vec; -} - -bool checkPrefix(const string & str, char prefix) { - if (str.at(0) == prefix) - return true; - return false; -} - -// ==================================================================== -// operation on files - - -#ifdef __unix - -void cEnvUtils::GetTmpTextFile() { - // TODO make this name configurable (depending on project) - char filename[] = "/tmp/otshellutils_text.XXXXXX"; - fd = mkstemp(filename); - if (fd == -1) { - _erro("Can't create the file: " << filename); - return; - } - mFilename = filename; -} - -void cEnvUtils::CloseFile() { - close(fd); - unlink( mFilename.c_str() ); -} - -void cEnvUtils::OpenEditor() { - char* editor = std::getenv("OT_EDITOR"); //TODO Read editor from configuration file - if (editor == NULL) - editor = std::getenv("VISUAL"); - if (editor == NULL) - editor = std::getenv("EDITOR"); - - string command; - if (editor != NULL) - command = ToStr(editor) + " " + mFilename; - else - command = "/usr/bin/editor " + mFilename; - _dbg3("Opening editor with command: " << command); - if ( system( command.c_str() ) == -1 ) - _erro("Cannot execute system command: " << command); -} - -const string cEnvUtils::ReadFromTmpFile() { - std::ifstream ifs(mFilename); - string msg((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); - return msg; -} - -const string cEnvUtils::Compose() { - GetTmpTextFile(); - OpenEditor(); - string input = ReadFromTmpFile(); - CloseFile(); - return input; -} - -#endif - -const string cEnvUtils::ReadFromFile(const string path) { - std::ifstream ifs(path); - string msg((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); - return msg; -} - -void hintingToTxt(std::fstream & file, string command, vector<string> &commands) { - if(file.good()) { - file<<command<<"~"<<endl; - for (auto a: commands) { - file <<a<< " "; - file.flush(); - } - file<<endl; - } -} - -string stringToColor(const string &hash) { - // Generete vector with all possible light colors - vector <string> lightColors; - using namespace zkr; - lightColors.push_back(cc::fore::lightblue); - lightColors.push_back(cc::fore::lightred); - lightColors.push_back(cc::fore::lightmagenta); - lightColors.push_back(cc::fore::lightgreen); - lightColors.push_back(cc::fore::lightcyan); - lightColors.push_back(cc::fore::lightyellow); - lightColors.push_back(cc::fore::lightwhite); - - int sum=0; - - for (auto ch : hash) sum+=ch; - auto color = sum%(lightColors.size()-1); - - return lightColors.at( color ); -} - - -// ==================================================================== -// algorthms - - -} // namespace nUtil - - -} // namespace OT - -// global namespace - -const extern int _dbg_ignore = 0; // see description in .hpp - -std::string GetObjectName() { - //static std::string * name=nullptr; - //if (!name) name = new std::string("(global)"); - return ""; -} - -// ==================================================================== - -nOT::nUtils::cLogger gCurrentLogger; - |