diff options
| author | Patrick Simianer <p@simianer.de> | 2013-01-21 12:29:43 +0100 | 
|---|---|---|
| committer | Patrick Simianer <p@simianer.de> | 2013-01-21 12:29:43 +0100 | 
| commit | 0d23f8aecbfaf982cd165ebfc2a1611cefcc7275 (patch) | |
| tree | 8eafa6ea43224ff70635cadd4d6f027d28f4986f /klm/util/usage.cc | |
| parent | dbc66cd3944321961c5e11d5254fd914f05a98ad (diff) | |
| parent | 7cac43b858f3b681555bf0578f54b1f822c43207 (diff) | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'klm/util/usage.cc')
| -rw-r--r-- | klm/util/usage.cc | 60 | 
1 files changed, 60 insertions, 0 deletions
| diff --git a/klm/util/usage.cc b/klm/util/usage.cc index e5cf76f0..16a004bb 100644 --- a/klm/util/usage.cc +++ b/klm/util/usage.cc @@ -1,13 +1,17 @@  #include "util/usage.hh" +#include "util/exception.hh" +  #include <fstream>  #include <ostream> +#include <sstream>  #include <string.h>  #include <ctype.h>  #if !defined(_WIN32) && !defined(_WIN64)  #include <sys/resource.h>  #include <sys/time.h> +#include <unistd.h>  #endif  namespace util { @@ -43,4 +47,60 @@ void PrintUsage(std::ostream &out) {  #endif  } +uint64_t GuessPhysicalMemory() { +#if defined(_WIN32) || defined(_WIN64) +  return 0; +#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) +  long pages = sysconf(_SC_PHYS_PAGES); +  if (pages == -1) return 0; +  long page_size = sysconf(_SC_PAGESIZE); +  if (page_size == -1) return 0; +  return static_cast<uint64_t>(pages) * static_cast<uint64_t>(page_size); +#else +  return 0; +#endif +} + +namespace { +class SizeParseError : public Exception { +  public: +    explicit SizeParseError(const std::string &str) throw() { +      *this << "Failed to parse " << str << " into a memory size "; +    } +}; + +template <class Num> uint64_t ParseNum(const std::string &arg) { +  std::stringstream stream(arg); +  Num value; +  stream >> value; +  UTIL_THROW_IF_ARG(!stream, SizeParseError, (arg), "for the leading number."); +  std::string after; +  stream >> after; +  UTIL_THROW_IF_ARG(after.size() > 1, SizeParseError, (arg), "because there are more than two characters after the number."); +  std::string throwaway; +  UTIL_THROW_IF_ARG(stream >> throwaway, SizeParseError, (arg), "because there was more cruft " << throwaway << " after the number."); + +  // Silly sort, using kilobytes as your default unit.   +  if (after.empty()) after == "K"; +  if (after == "%") { +    uint64_t mem = GuessPhysicalMemory(); +    UTIL_THROW_IF_ARG(!mem, SizeParseError, (arg), "because % was specified but the physical memory size could not be determined."); +    return static_cast<double>(value) * static_cast<double>(mem) / 100.0; +  } +   +  std::string units("bKMGTPEZY"); +  std::string::size_type index = units.find(after[0]); +  UTIL_THROW_IF_ARG(index == std::string::npos, SizeParseError, (arg), "the allowed suffixes are " << units << "%."); +  for (std::string::size_type i = 0; i < index; ++i) { +    value *= 1024; +  } +  return value; +} + +} // namespace + +uint64_t ParseSize(const std::string &arg) { +  return arg.find('.') == std::string::npos ? ParseNum<double>(arg) : ParseNum<uint64_t>(arg); +} +  } // namespace util | 
