]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/strtol.cc
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 #include <boost/utility/string_view.hpp>
23 using std::ostringstream
;
25 long long strict_strtoll(const boost::string_view str
, int base
, std::string
*err
)
28 errno
= 0; /* To distinguish success/failure after call (see man page) */
29 long long ret
= strtoll(str
.data(), &endptr
, base
);
30 if (endptr
== str
.data() || endptr
!= str
.data() + str
.size()) {
31 *err
= (std::string
{"Expected option value to be integer, got '"} +
32 std::string
{str
} + "'");
36 *err
= (std::string
{"The option value '"} + std::string
{str
} +
37 "' seems to be invalid");
44 long long strict_strtoll(const char *str
, int base
, std::string
*err
)
46 return strict_strtoll(boost::string_view(str
), base
, err
);
49 int strict_strtol(const boost::string_view str
, int base
, std::string
*err
)
51 long long ret
= strict_strtoll(str
, base
, err
);
54 if ((ret
<= INT_MIN
) || (ret
>= INT_MAX
)) {
56 errStr
<< "The option value '" << str
<< "' seems to be invalid";
60 return static_cast<int>(ret
);
63 int strict_strtol(const char *str
, int base
, std::string
*err
)
65 return strict_strtol(boost::string_view(str
), base
, err
);
68 double strict_strtod(const boost::string_view str
, std::string
*err
)
71 errno
= 0; /* To distinguish success/failure after call (see man page) */
72 double ret
= strtod(str
.data(), &endptr
);
73 if (errno
== ERANGE
) {
75 oss
<< "strict_strtod: floating point overflow or underflow parsing '"
82 oss
<< "strict_strtod: expected double, got: '" << str
<< "'";
86 if (*endptr
!= '\0') {
88 oss
<< "strict_strtod: garbage at end of string. got: '" << str
<< "'";
96 double strict_strtod(const char *str
, std::string
*err
)
98 return strict_strtod(boost::string_view(str
), err
);
101 float strict_strtof(const boost::string_view str
, std::string
*err
)
104 errno
= 0; /* To distinguish success/failure after call (see man page) */
105 float ret
= strtof(str
.data(), &endptr
);
106 if (errno
== ERANGE
) {
108 oss
<< "strict_strtof: floating point overflow or underflow parsing '"
115 oss
<< "strict_strtof: expected float, got: '" << str
<< "'";
119 if (*endptr
!= '\0') {
121 oss
<< "strict_strtof: garbage at end of string. got: '" << str
<< "'";
129 float strict_strtof(const char *str
, std::string
*err
)
131 return strict_strtof(boost::string_view(str
), err
);
135 T
strict_iec_cast(const boost::string_view str
, std::string
*err
)
138 *err
= "strict_iecstrtoll: value not specified";
141 // get a view of the unit and of the value
142 boost::string_view unit
;
143 boost::string_view n
= str
;
144 size_t u
= str
.find_first_not_of("0123456789-+");
146 // deal with unit prefix is there is one
147 if (u
!= boost::string_view::npos
) {
148 n
= str
.substr(0, u
);
149 unit
= str
.substr(u
, str
.length() - u
);
150 // we accept both old si prefixes as well as the proper iec prefixes
151 // i.e. K, M, ... and Ki, Mi, ...
152 if (unit
.back() == 'i') {
153 if (unit
.front() == 'B') {
154 *err
= "strict_iecstrtoll: illegal prefix \"Bi\"";
158 if (unit
.length() > 2) {
159 *err
= "strict_iecstrtoll: illegal prefix (length > 2)";
162 switch(unit
.front()) {
184 *err
= "strict_iecstrtoll: unit prefix not recognized";
189 long long ll
= strict_strtoll(n
, 10, err
);
190 if (ll
< 0 && !std::numeric_limits
<T
>::is_signed
) {
191 *err
= "strict_iecstrtoll: value should not be negative";
194 if (static_cast<unsigned>(m
) >= sizeof(T
) * CHAR_BIT
) {
195 *err
= ("strict_iecstrtoll: the IEC prefix is too large for the designated "
199 using promoted_t
= typename
std::common_type
<decltype(ll
), T
>::type
;
200 if (static_cast<promoted_t
>(ll
) <
201 static_cast<promoted_t
>(std::numeric_limits
<T
>::min()) >> m
) {
202 *err
= "strict_iecstrtoll: value seems to be too small";
205 if (static_cast<promoted_t
>(ll
) >
206 static_cast<promoted_t
>(std::numeric_limits
<T
>::max()) >> m
) {
207 *err
= "strict_iecstrtoll: value seems to be too large";
213 template int strict_iec_cast
<int>(const boost::string_view str
, std::string
*err
);
214 template long strict_iec_cast
<long>(const boost::string_view str
, std::string
*err
);
215 template long long strict_iec_cast
<long long>(const boost::string_view str
, std::string
*err
);
216 template uint64_t strict_iec_cast
<uint64_t>(const boost::string_view str
, std::string
*err
);
217 template uint32_t strict_iec_cast
<uint32_t>(const boost::string_view str
, std::string
*err
);
219 uint64_t strict_iecstrtoll(const boost::string_view str
, std::string
*err
)
221 return strict_iec_cast
<uint64_t>(str
, err
);
224 uint64_t strict_iecstrtoll(const char *str
, std::string
*err
)
226 return strict_iec_cast
<uint64_t>(boost::string_view(str
), err
);
230 T
strict_iec_cast(const char *str
, std::string
*err
)
232 return strict_iec_cast
<T
>(boost::string_view(str
), err
);
235 template int strict_iec_cast
<int>(const char *str
, std::string
*err
);
236 template long strict_iec_cast
<long>(const char *str
, std::string
*err
);
237 template long long strict_iec_cast
<long long>(const char *str
, std::string
*err
);
238 template uint64_t strict_iec_cast
<uint64_t>(const char *str
, std::string
*err
);
239 template uint32_t strict_iec_cast
<uint32_t>(const char *str
, std::string
*err
);
242 T
strict_si_cast(const boost::string_view str
, std::string
*err
)
245 *err
= "strict_sistrtoll: value not specified";
248 boost::string_view n
= str
;
250 // deal with unit prefix is there is one
251 if (str
.find_first_not_of("0123456789+-") != boost::string_view::npos
) {
252 const char &u
= str
.back();
266 *err
= "strict_si_cast: unit prefix not recognized";
271 n
= str
.substr(0, str
.length() -1);
274 long long ll
= strict_strtoll(n
, 10, err
);
275 if (ll
< 0 && !std::numeric_limits
<T
>::is_signed
) {
276 *err
= "strict_sistrtoll: value should not be negative";
279 using promoted_t
= typename
std::common_type
<decltype(ll
), T
>::type
;
280 if (static_cast<promoted_t
>(ll
) <
281 static_cast<promoted_t
>(std::numeric_limits
<T
>::min()) / pow (10, m
)) {
282 *err
= "strict_sistrtoll: value seems to be too small";
285 if (static_cast<promoted_t
>(ll
) >
286 static_cast<promoted_t
>(std::numeric_limits
<T
>::max()) / pow (10, m
)) {
287 *err
= "strict_sistrtoll: value seems to be too large";
290 return (ll
* pow (10, m
));
293 template int strict_si_cast
<int>(const boost::string_view str
, std::string
*err
);
294 template long strict_si_cast
<long>(const boost::string_view str
, std::string
*err
);
295 template long long strict_si_cast
<long long>(const boost::string_view str
, std::string
*err
);
296 template uint64_t strict_si_cast
<uint64_t>(const boost::string_view str
, std::string
*err
);
297 template uint32_t strict_si_cast
<uint32_t>(const boost::string_view str
, std::string
*err
);
299 uint64_t strict_sistrtoll(const boost::string_view str
, std::string
*err
)
301 return strict_si_cast
<uint64_t>(str
, err
);
304 uint64_t strict_sistrtoll(const char *str
, std::string
*err
)
306 return strict_si_cast
<uint64_t>(str
, err
);
310 T
strict_si_cast(const char *str
, std::string
*err
)
312 return strict_si_cast
<T
>(boost::string_view(str
), err
);
315 template int strict_si_cast
<int>(const char *str
, std::string
*err
);
316 template long strict_si_cast
<long>(const char *str
, std::string
*err
);
317 template long long strict_si_cast
<long long>(const char *str
, std::string
*err
);
318 template uint64_t strict_si_cast
<uint64_t>(const char *str
, std::string
*err
);
319 template uint32_t strict_si_cast
<uint32_t>(const char *str
, std::string
*err
);