diff options
Diffstat (limited to 'lib/common/Utils.cpp')
-rw-r--r-- | lib/common/Utils.cpp | 179 |
1 files changed, 162 insertions, 17 deletions
diff --git a/lib/common/Utils.cpp b/lib/common/Utils.cpp index 83a12ccf..f45ed26b 100644 --- a/lib/common/Utils.cpp +++ b/lib/common/Utils.cpp @@ -13,11 +13,17 @@ #include <sys/stat.h> #include <errno.h> +#include <cstdlib> + #ifdef SHOW_BACKTRACE_ON_EXCEPTION #include <execinfo.h> #include <stdlib.h> #endif +#ifdef HAVE_CXXABI_H + #include <cxxabi.h> +#endif + #include "Utils.h" #include "CommonException.h" #include "Logging.h" @@ -52,11 +58,11 @@ void SplitString(const std::string &String, char SplitOn, std::vector<std::strin { rOutput.push_back(String.substr(b)); } -/*#ifndef NDEBUG - TRACE2("Splitting string '%s' on %c\n", String.c_str(), SplitOn); +/*#ifndef BOX_RELEASE_BUILD + BOX_TRACE("Splitting string '" << String << " on " << (char)SplitOn); for(unsigned int l = 0; l < rOutput.size(); ++l) { - TRACE2("%d = '%s'\n", l, rOutput[l].c_str()); + BOX_TRACE(l << " = '" << rOutput[l] << "'"); } #endif*/ } @@ -64,23 +70,83 @@ void SplitString(const std::string &String, char SplitOn, std::vector<std::strin #ifdef SHOW_BACKTRACE_ON_EXCEPTION void DumpStackBacktrace() { - void *array[10]; - size_t size; - char **strings; - size_t i; - - size = backtrace (array, 10); - strings = backtrace_symbols (array, size); + void *array[10]; + size_t size = backtrace (array, 10); + char **strings = backtrace_symbols (array, size); BOX_TRACE("Obtained " << size << " stack frames."); - for(i = 0; i < size; i++) + for(size_t i = 0; i < size; i++) { - BOX_TRACE(strings[i]); + // Demangling code copied from + // cctbx_sources/boost_adaptbx/meta_ext.cpp, BSD license + + std::string mangled_frame = strings[i]; + std::string output_frame = strings[i]; // default + + #ifdef HAVE_CXXABI_H + int start = mangled_frame.find('('); + int end = mangled_frame.find('+', start); + std::string mangled_func = mangled_frame.substr(start + 1, + end - start - 1); + + int status; + +#include "MemLeakFindOff.h" + char* result = abi::__cxa_demangle(mangled_func.c_str(), + NULL, NULL, &status); +#include "MemLeakFindOn.h" + + if (result == NULL) + { + if (status == 0) + { + BOX_WARNING("Demangle failed but no error: " << + mangled_func); + } + else if (status == -1) + { + BOX_WARNING("Demangle failed with " + "memory allocation error: " << + mangled_func); + } + else if (status == -2) + { + // Probably non-C++ name, don't demangle + /* + BOX_WARNING("Demangle failed with " + "with invalid name: " << + mangled_func); + */ + } + else if (status == -3) + { + BOX_WARNING("Demangle failed with " + "with invalid argument: " << + mangled_func); + } + else + { + BOX_WARNING("Demangle failed with " + "with unknown error " << status << + ": " << mangled_func); + } + } + else + { + output_frame = mangled_frame.substr(0, start + 1) + + result + mangled_frame.substr(end); +#include "MemLeakFindOff.h" + std::free(result); +#include "MemLeakFindOn.h" + } + #endif // HAVE_CXXABI_H + + BOX_TRACE("Stack frame " << i << ": " << output_frame); } #include "MemLeakFindOff.h" - free (strings); + std::free (strings); #include "MemLeakFindOn.h" } #endif @@ -97,8 +163,8 @@ void DumpStackBacktrace() // -------------------------------------------------------------------------- bool FileExists(const char *Filename, int64_t *pFileSize, bool TreatLinksAsNotExisting) { - struct stat st; - if(::lstat(Filename, &st) != 0) + EMU_STRUCT_STAT st; + if(EMU_LSTAT(Filename, &st) != 0) { if(errno == ENOENT) { @@ -142,8 +208,8 @@ bool FileExists(const char *Filename, int64_t *pFileSize, bool TreatLinksAsNotEx // -------------------------------------------------------------------------- int ObjectExists(const std::string& rFilename) { - struct stat st; - if(::stat(rFilename.c_str(), &st) != 0) + EMU_STRUCT_STAT st; + if(EMU_STAT(rFilename.c_str(), &st) != 0) { if(errno == ENOENT) { @@ -159,6 +225,85 @@ int ObjectExists(const std::string& rFilename) return ((st.st_mode & S_IFDIR) == 0)?ObjectExists_File:ObjectExists_Dir; } +std::string HumanReadableSize(int64_t Bytes) +{ + double readableValue = Bytes; + std::string units = " B"; + + if (readableValue > 1024) + { + readableValue /= 1024; + units = "kB"; + } + + if (readableValue > 1024) + { + readableValue /= 1024; + units = "MB"; + } + + if (readableValue > 1024) + { + readableValue /= 1024; + units = "GB"; + } + + std::ostringstream result; + result << std::fixed << std::setprecision(2) << readableValue << + " " << units; + return result.str(); +} + +std::string FormatUsageBar(int64_t Blocks, int64_t Bytes, int64_t Max, + bool MachineReadable) +{ + std::ostringstream result; + + + if (MachineReadable) + { + result << (Bytes >> 10) << " kB, " << + std::setprecision(0) << ((Bytes*100)/Max) << "%"; + } + else + { + // Bar graph + char bar[17]; + unsigned int b = (int)((Bytes * (sizeof(bar)-1)) / Max); + if(b > sizeof(bar)-1) {b = sizeof(bar)-1;} + for(unsigned int l = 0; l < b; l++) + { + bar[l] = '*'; + } + for(unsigned int l = b; l < sizeof(bar) - 1; l++) + { + bar[l] = ' '; + } + bar[sizeof(bar)-1] = '\0'; + + result << std::fixed << + std::setw(10) << Blocks << " blocks, " << + std::setw(10) << HumanReadableSize(Bytes) << ", " << + std::setw(3) << std::setprecision(0) << + ((Bytes*100)/Max) << "% |" << bar << "|"; + } + + return result.str(); +} +std::string FormatUsageLineStart(const std::string& rName, + bool MachineReadable) +{ + std::ostringstream result; + if (MachineReadable) + { + result << rName << ": "; + } + else + { + result << std::setw(20) << std::right << rName << ": "; + } + return result.str(); +} |