1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
21 using std::ostringstream;
23 long long strict_strtoll(const char *str, int base, std::string *err)
27 errno = 0; /* To distinguish success/failure after call (see man page) */
28 long long ret = strtoll(str, &endptr, base);
31 errStr = "Expected option value to be integer, got '";
37 if ((errno == ERANGE && (ret == LLONG_MAX || ret == LLONG_MIN))
38 || (errno != 0 && ret == 0)) {
39 errStr = "The option value '";
42 errStr.append(" seems to be invalid");
46 if (*endptr != '\0') {
47 errStr = "The option value '";
50 errStr.append(" contains invalid digits");
58 int strict_strtol(const char *str, int base, std::string *err)
61 long long ret = strict_strtoll(str, base, err);
64 if ((ret <= INT_MIN) || (ret >= INT_MAX)) {
65 errStr = "The option value '";
68 errStr.append(" seems to be invalid");
72 return static_cast<int>(ret);
75 double strict_strtod(const char *str, std::string *err)
78 errno = 0; /* To distinguish success/failure after call (see man page) */
79 double ret = strtod(str, &endptr);
80 if (errno == ERANGE) {
82 oss << "strict_strtod: floating point overflow or underflow parsing '"
89 oss << "strict_strtod: expected double, got: '" << str << "'";
93 if (*endptr != '\0') {
95 oss << "strict_strtod: garbage at end of string. got: '" << str << "'";
103 float strict_strtof(const char *str, std::string *err)
106 errno = 0; /* To distinguish success/failure after call (see man page) */
107 float ret = strtof(str, &endptr);
108 if (errno == ERANGE) {
110 oss << "strict_strtof: floating point overflow or underflow parsing '"
117 oss << "strict_strtof: expected float, got: '" << str << "'";
121 if (*endptr != '\0') {
123 oss << "strict_strtof: garbage at end of string. got: '" << str << "'";
132 T strict_si_cast(const char *str, std::string *err)
136 *err = "strict_sistrtoll: value not specified";
139 const char &u = s.back();
163 long long ll = strict_strtoll(s.c_str(), 10, err);
164 if (ll < 0 && !std::numeric_limits<T>::is_signed) {
165 *err = "strict_sistrtoll: value should not be negative";
168 if (static_cast<unsigned>(m) >= sizeof(T) * CHAR_BIT) {
169 *err = ("strict_sistrtoll: the SI prefix is too large for the designated "
173 using promoted_t = typename std::common_type<decltype(ll), T>::type;
174 if (static_cast<promoted_t>(ll) <
175 static_cast<promoted_t>(std::numeric_limits<T>::min()) >> m) {
176 *err = "strict_sistrtoll: value seems to be too small";
179 if (static_cast<promoted_t>(ll) >
180 static_cast<promoted_t>(std::numeric_limits<T>::max()) >> m) {
181 *err = "strict_sistrtoll: value seems to be too large";
187 template int strict_si_cast<int>(const char *str, std::string *err);
188 template long strict_si_cast<long>(const char *str, std::string *err);
189 template long long strict_si_cast<long long>(const char *str, std::string *err);
190 template uint64_t strict_si_cast<uint64_t>(const char *str, std::string *err);
191 template uint32_t strict_si_cast<uint32_t>(const char *str, std::string *err);
193 uint64_t strict_sistrtoll(const char *str, std::string *err)
195 return strict_si_cast<uint64_t>(str, err);