// license:GPL-2.0+ // 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, std::size_t *idx) { std::stringstream ss; ss.imbue(loc); ss << arg; auto len(ss.tellp()); T x(constants::zero()); if (ss >> x) { auto pos(ss.tellg()); if (pos == decltype(pos)(-1)) pos = len; *idx = narrow_cast(pos); } else *idx = constants::zero(); 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, std::size_t *idx) { //return std::stoll(arg, idx); return pstonum_locale(loc, arg, idx); } }; template struct pstonum_helper::value && !plib::is_signed::value>> { template unsigned long long operator()(std::locale loc, const S &arg, std::size_t *idx) { //return std::stoll(arg, idx); return pstonum_locale(loc, arg, idx); } }; template struct pstonum_helper::value>> { template long double operator()(std::locale loc, const S &arg, std::size_t *idx) { return pstonum_locale(loc, arg, idx); } }; #if PUSE_FLOAT128 template<> struct pstonum_helper { // FIXME: use strtoflt128 from quadmath.h template FLOAT128 operator()(std::locale loc, const S &arg, std::size_t *idx) { return narrow_cast(pstonum_locale(loc, arg, idx)); } }; #endif template T pstonum(const S &arg, const std::locale &loc = std::locale::classic()) noexcept(false) { putf8string u8arg(arg); decltype(u8arg.c_str()) cstr(u8arg.c_str()); std::size_t idx(0); auto ret = pstonum_helper()(loc, cstr, &idx); using ret_type = decltype(ret); if (ret >= narrow_cast(plib::numeric_limits::lowest()) && ret <= narrow_cast(plib::numeric_limits::max())) { if (cstr[idx] != 0) throw pexception(pstring("Continuation after numeric value ends: ") + pstring(cstr)); } else { throw pexception(pstring("Out of range: ") + pstring(cstr)); } return narrow_cast(ret); } 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_