// license:BSD-3-Clause // copyright-holders:Couriersud #ifndef PSTONUM_H_ #define PSTONUM_H_ /// /// \file pstonum.h /// #include "pconfig.h" #include "pexception.h" #include "pgsl.h" #include "pmath.h" // for pstonum #include "pstring.h" #include #include #include #include #include namespace plib { // ---------------------------------------------------------------------------------------- // number conversions // ---------------------------------------------------------------------------------------- template T pstonum_locale(const std::locale &loc, const S &arg, bool *err) { std::stringstream ss; ss.imbue(loc); ss << putf8string(arg); auto len(ss.tellp()); T x(constants::zero()); if (ss >> x) { auto pos(ss.tellg()); if (pos == decltype(pos)(-1)) pos = len; *err = (pos != len); } else *err = true; return x; } template struct pstonum_helper; template struct pstonum_helper::value && plib::is_signed::value>> { template long long operator()(std::locale loc, const S &arg, bool *err) { //return std::stoll(arg, idx); return pstonum_locale(loc, arg, err); } }; template struct pstonum_helper::value && !plib::is_signed::value>> { template unsigned long long operator()(std::locale loc, const S &arg, bool *err) { //return std::stoll(arg, idx); return pstonum_locale(loc, arg, err); } }; template struct pstonum_helper::value>> { template long double operator()(std::locale loc, const S &arg, bool *err) { return pstonum_locale(loc, arg, err); } }; #if PUSE_FLOAT128 template<> struct pstonum_helper { // FIXME: use `strtoflt128` from `quadmath.h` template FLOAT128 operator()(std::locale loc, const S &arg, bool *err) { return narrow_cast(pstonum_locale(loc, arg, err)); } }; #endif template T pstonum(const S &arg, const std::locale &loc = std::locale::classic()) noexcept(false) { bool err(false); auto ret = pstonum_helper()(loc, arg, &err); if (err) throw pexception(pstring("Error converting string to number: ") + pstring(arg)); using ret_type = decltype(ret); if (ret >= narrow_cast(plib::numeric_limits::lowest()) && ret <= narrow_cast(plib::numeric_limits::max())) { return narrow_cast(ret); } throw pexception(pstring("Out of range: ") + pstring(arg)); } template R pstonum_ne(const T &str, bool &err, std::locale loc = std::locale::classic()) noexcept { try { err = false; return pstonum(str, loc); } catch (...) { err = true; return R(0); } } template R pstonum_ne_def(const T &str, R def, std::locale loc = std::locale::classic()) noexcept { try { return pstonum(str, loc); } catch (...) { return def; } } } // namespace plib #endif // PUTIL_H_