summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/pstonum.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/pstonum.h')
-rw-r--r--src/lib/netlist/plib/pstonum.h145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/pstonum.h b/src/lib/netlist/plib/pstonum.h
new file mode 100644
index 00000000000..18c67ca2b86
--- /dev/null
+++ b/src/lib/netlist/plib/pstonum.h
@@ -0,0 +1,145 @@
+// 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 <algorithm>
+#include <initializer_list>
+#include <iostream>
+#include <locale>
+#include <sstream>
+
+namespace plib
+{
+ // ----------------------------------------------------------------------------------------
+ // number conversions
+ // ----------------------------------------------------------------------------------------
+
+ template <typename T, typename S>
+ 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<T>::zero());
+ if (ss >> x)
+ {
+ auto pos(ss.tellg());
+ if (pos == decltype(pos)(-1))
+ pos = len;
+ *err = (pos != len);
+ }
+ else
+ *err = true;
+ return x;
+ }
+
+ template <typename T, typename E = void>
+ struct pstonum_helper;
+
+ template<typename T>
+ struct pstonum_helper<T, std::enable_if_t<plib::is_integral<T>::value && plib::is_signed<T>::value>>
+ {
+ template <typename S>
+ long long operator()(std::locale loc, const S &arg, bool *err)
+ {
+ //return std::stoll(arg, idx);
+ return pstonum_locale<long long>(loc, arg, err);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, std::enable_if_t<plib::is_integral<T>::value && !plib::is_signed<T>::value>>
+ {
+ template <typename S>
+ unsigned long long operator()(std::locale loc, const S &arg, bool *err)
+ {
+ //return std::stoll(arg, idx);
+ return pstonum_locale<unsigned long long>(loc, arg, err);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, std::enable_if_t<std::is_floating_point<T>::value>>
+ {
+ template <typename S>
+ long double operator()(std::locale loc, const S &arg, bool *err)
+ {
+ return pstonum_locale<long double>(loc, arg, err);
+ }
+ };
+
+#if PUSE_FLOAT128
+ template<>
+ struct pstonum_helper<FLOAT128>
+ {
+ // FIXME: use `strtoflt128` from `quadmath.h`
+ template <typename S>
+ FLOAT128 operator()(std::locale loc, const S &arg, bool *err)
+ {
+ return narrow_cast<FLOAT128>(pstonum_locale<long double>(loc, arg, err));
+ }
+ };
+#endif
+
+ template<typename T, typename S>
+ T pstonum(const S &arg, const std::locale &loc = std::locale::classic()) noexcept(false)
+ {
+ bool err(false);
+ auto ret = pstonum_helper<T>()(loc, arg, &err);
+ if (err)
+ throw pexception(pstring("Error converting string to number: ") + pstring(arg));
+
+ using ret_type = decltype(ret);
+ if (ret >= narrow_cast<ret_type>(plib::numeric_limits<T>::lowest())
+ && ret <= narrow_cast<ret_type>(plib::numeric_limits<T>::max()))
+ {
+ return narrow_cast<T>(ret);
+ }
+
+ throw pexception(pstring("Out of range: ") + pstring(arg));
+ }
+
+ template<typename R, typename T>
+ R pstonum_ne(const T &str, bool &err, std::locale loc = std::locale::classic()) noexcept
+ {
+ try
+ {
+ err = false;
+ return pstonum<R>(str, loc);
+ }
+ catch (...)
+ {
+ err = true;
+ return R(0);
+ }
+ }
+
+ template<typename R, typename T>
+ R pstonum_ne_def(const T &str, R def, std::locale loc = std::locale::classic()) noexcept
+ {
+ try
+ {
+ return pstonum<R>(str, loc);
+ }
+ catch (...)
+ {
+ return def;
+ }
+ }
+
+} // namespace plib
+
+#endif // PUTIL_H_