ceph/src/common/strtol.cc
Joao Eduardo Luis 67dc5751ba common/strtol.cc: strict_strtosi() converts str with SI units to uint64_t
Accepts values with a suffix (B, K, M, G, T, P, E) and returns the
appropriate byte value.

E.g., 10B = 10, while 10K = 10240.

Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
2014-05-30 22:09:23 +01:00

170 lines
4.0 KiB
C++

// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#include <errno.h>
#include <limits.h>
#include <sstream>
#include <stdlib.h>
#include <string>
extern "C" {
#include <stdint.h>
}
using std::ostringstream;
long long strict_strtoll(const char *str, int base, std::string *err)
{
char *endptr;
errno = 0; /* To distinguish success/failure after call (see man page) */
long long ret = strtoll(str, &endptr, base);
if ((errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN))
|| (errno != 0 && ret == 0)) {
ostringstream oss;
oss << "strict_strtoll: integer underflow or overflow parsing '" << str << "'";
*err = oss.str();
return 0;
}
if (endptr == str) {
ostringstream oss;
oss << "strict_strtoll: expected integer, got: '" << str << "'";
*err = oss.str();
return 0;
}
if (*endptr != '\0') {
ostringstream oss;
oss << "strict_strtoll: garbage at end of string. got: '" << str << "'";
*err = oss.str();
return 0;
}
*err = "";
return ret;
}
int strict_strtol(const char *str, int base, std::string *err)
{
long long ret = strict_strtoll(str, base, err);
if (!err->empty())
return 0;
if (ret <= INT_MIN) {
ostringstream oss;
oss << "strict_strtol: integer underflow parsing '" << str << "'";
*err = oss.str();
return 0;
}
if (ret >= INT_MAX) {
ostringstream oss;
oss << "strict_strtol: integer overflow parsing '" << str << "'";
*err = oss.str();
return 0;
}
return static_cast<int>(ret);
}
double strict_strtod(const char *str, std::string *err)
{
char *endptr;
errno = 0; /* To distinguish success/failure after call (see man page) */
double ret = strtod(str, &endptr);
if (errno == ERANGE) {
ostringstream oss;
oss << "strict_strtod: floating point overflow or underflow parsing '"
<< str << "'";
*err = oss.str();
return 0.0;
}
if (endptr == str) {
ostringstream oss;
oss << "strict_strtod: expected double, got: '" << str << "'";
*err = oss.str();
return 0;
}
if (*endptr != '\0') {
ostringstream oss;
oss << "strict_strtod: garbage at end of string. got: '" << str << "'";
*err = oss.str();
return 0;
}
*err = "";
return ret;
}
float strict_strtof(const char *str, std::string *err)
{
char *endptr;
errno = 0; /* To distinguish success/failure after call (see man page) */
float ret = strtof(str, &endptr);
if (errno == ERANGE) {
ostringstream oss;
oss << "strict_strtof: floating point overflow or underflow parsing '"
<< str << "'";
*err = oss.str();
return 0.0;
}
if (endptr == str) {
ostringstream oss;
oss << "strict_strtof: expected float, got: '" << str << "'";
*err = oss.str();
return 0;
}
if (*endptr != '\0') {
ostringstream oss;
oss << "strict_strtof: garbage at end of string. got: '" << str << "'";
*err = oss.str();
return 0;
}
*err = "";
return ret;
}
uint64_t strict_sistrtoll(const char *str, std::string *err)
{
std::string s(str);
if (s.size() == 0) {
ostringstream oss;
oss << "strict_sistrtoll: value not specified";
*err = oss.str();
return 0;
}
const char &u = s.at(s.size()-1); //str[std::strlen(str)-1];
int m = 0;
if (u == 'B')
m = 0;
else if (u == 'K')
m = 10;
else if (u == 'M')
m = 20;
else if (u == 'G')
m = 30;
else if (u == 'T')
m = 40;
else if (u == 'P')
m = 50;
else if (u == 'E')
m = 60;
else
m = -1;
const char *v = NULL;
if (m >= 0)
s = std::string(str, s.size()-1);
v = s.c_str();
uint64_t r = strict_strtoll(v, 10, err);
if (err->empty() && m > 0) {
r = (r << m);
}
return r;
}