use boost::lexical_cast for string2*

this avoids one copy from `s` into `str`, and possibly another copy needed to
construct `s` at the call site. lexical_cast is also more efficient in general.
This commit is contained in:
pennae 2021-12-31 03:16:59 +01:00
parent 5838354d34
commit 73fcc40fa4

View file

@ -11,6 +11,8 @@
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <boost/lexical_cast.hpp>
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <map> #include <map>
@ -417,21 +419,21 @@ bool statusOk(int status);
/* Parse a string into an integer. */ /* Parse a string into an integer. */
template<class N> template<class N>
std::optional<N> string2Int(const std::string & s) std::optional<N> string2Int(const std::string_view s)
{ {
if (s.substr(0, 1) == "-" && !std::numeric_limits<N>::is_signed) if (s.substr(0, 1) == "-" && !std::numeric_limits<N>::is_signed)
return std::nullopt; return std::nullopt;
std::istringstream str(s); try {
N n; return boost::lexical_cast<N>(s.data(), s.size());
str >> n; } catch (const boost::bad_lexical_cast &) {
if (str && str.get() == EOF) return n;
return std::nullopt; return std::nullopt;
} }
}
/* Like string2Int(), but support an optional suffix 'K', 'M', 'G' or /* Like string2Int(), but support an optional suffix 'K', 'M', 'G' or
'T' denoting a binary unit prefix. */ 'T' denoting a binary unit prefix. */
template<class N> template<class N>
N string2IntWithUnitPrefix(std::string s) N string2IntWithUnitPrefix(std::string_view s)
{ {
N multiplier = 1; N multiplier = 1;
if (!s.empty()) { if (!s.empty()) {
@ -442,7 +444,7 @@ N string2IntWithUnitPrefix(std::string s)
else if (u == 'G') multiplier = 1ULL << 30; else if (u == 'G') multiplier = 1ULL << 30;
else if (u == 'T') multiplier = 1ULL << 40; else if (u == 'T') multiplier = 1ULL << 40;
else throw UsageError("invalid unit specifier '%1%'", u); else throw UsageError("invalid unit specifier '%1%'", u);
s.resize(s.size() - 1); s.remove_suffix(1);
} }
} }
if (auto n = string2Int<N>(s)) if (auto n = string2Int<N>(s))
@ -452,14 +454,14 @@ N string2IntWithUnitPrefix(std::string s)
/* Parse a string into a float. */ /* Parse a string into a float. */
template<class N> template<class N>
std::optional<N> string2Float(const string & s) std::optional<N> string2Float(const std::string_view s)
{ {
std::istringstream str(s); try {
N n; return boost::lexical_cast<N>(s.data(), s.size());
str >> n; } catch (const boost::bad_lexical_cast &) {
if (str && str.get() == EOF) return n;
return std::nullopt; return std::nullopt;
} }
}
/* Return true iff `s' starts with `prefix'. */ /* Return true iff `s' starts with `prefix'. */