int Util::parseSize()

in src/oomd/util/Util.cpp [63:130]


int Util::parseSize(const std::string& input, int64_t* output) {
  bool is_neg = false;
  uint64_t size = 0;
  size_t pos = 0;
  auto istr = input;

  // lower case and get rid of spaces
  transform(istr.begin(), istr.end(), istr.begin(), tolower);
  auto new_end = std::remove_if(istr.begin(), istr.end(), isspace);
  istr.erase(new_end - istr.begin());

  // pop off leading sign
  if (istr[0] == '+') {
    pos++;
  } else if (istr[0] == '-') {
    is_neg = true;
    pos++;
  }

  while (pos < istr.length()) {
    size_t unit_pos;
    size_t end_pos;

    unit_pos = istr.find_first_of("kmgt", pos);
    if (unit_pos == pos) {
      return -1;
    }
    if (unit_pos == std::string::npos) {
      unit_pos = istr.length();
    }

    auto num = istr.substr(pos, unit_pos - pos);
    auto unit = istr.c_str()[unit_pos];

    double v;
    try {
      v = std::stold(num, &end_pos);
    } catch (...) {
      return -1;
    }
    if (end_pos != num.length() || v < 0) {
      return -1;
    }

    switch (unit) {
      case '\0':
        break;
      case 'k':
        v *= 1ULL << 10;
        break;
      case 'm':
        v *= 1ULL << 20;
        break;
      case 'g':
        v *= 1ULL << 30;
        break;
      case 't':
        v *= 1ULL << 40;
        break;
      default:
        return -1;
    }
    size += v;
    pos = unit_pos + 1;
  }
  *output = is_neg ? -size : size;
  return 0;
}