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.h148
1 files changed, 148 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..c73a348db9b
--- /dev/null
+++ b/src/lib/netlist/plib/pstonum.h
@@ -0,0 +1,148 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pstonuml.h
+ *
+ */
+
+#ifndef PSTONUM_H_
+#define PSTONUM_H_
+
+#include "pconfig.h"
+#include "pexception.h"
+#include "pstring.h"
+#include "pmath.h" // for pstonum
+
+#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, std::size_t *idx)
+ {
+ std::stringstream ss;
+ ss.imbue(loc);
+ ss << arg;
+ auto len(ss.tellp());
+ T x(constants<T>::zero());
+ if (ss >> x)
+ {
+ auto pos(ss.tellg());
+ if (pos == static_cast<decltype(pos)>(-1))
+ pos = len;
+ *idx = static_cast<std::size_t>(pos);
+ }
+ else
+ *idx = constants<std::size_t>::zero();
+ //printf("%s, %f, %lu %ld\n", arg, (double)x, *idx, (long int) ss.tellg());
+ return x;
+ }
+
+ template <typename T, typename E = void>
+ struct pstonum_helper;
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value>::type>
+ {
+ template <typename S>
+ long long operator()(std::locale loc, const S &arg, std::size_t *idx)
+ {
+ //return std::stoll(arg, idx);
+ return pstonum_locale<long long>(loc, arg, idx);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value && !std::is_signed<T>::value>::type>
+ {
+ template <typename S>
+ unsigned long long operator()(std::locale loc, const S &arg, std::size_t *idx)
+ {
+ //return std::stoll(arg, idx);
+ return pstonum_locale<unsigned long long>(loc, arg, idx);
+ }
+ };
+
+ template<typename T>
+ struct pstonum_helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
+ {
+ template <typename S>
+ long double operator()(std::locale loc, const S &arg, std::size_t *idx)
+ {
+ return pstonum_locale<long double>(loc, arg, idx);
+ }
+ };
+
+#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, std::size_t *idx)
+ {
+ return static_cast<__float128>(pstonum_locale<long double>(loc, arg, idx));
+ }
+ };
+#endif
+
+ template<typename T, typename S>
+ T pstonum(const S &arg, const std::locale &loc = std::locale::classic())
+ {
+ decltype(arg.c_str()) cstr = arg.c_str();
+ std::size_t idx(0);
+ auto ret = pstonum_helper<T>()(loc, cstr, &idx);
+ using ret_type = decltype(ret);
+ if (ret >= static_cast<ret_type>(std::numeric_limits<T>::lowest())
+ && ret <= static_cast<ret_type>(std::numeric_limits<T>::max()))
+ //&& (ret == T(0) || plib::abs(ret) >= std::numeric_limits<T>::min() ))
+ {
+ if (cstr[idx] != 0)
+ throw pexception(pstring("Continuation after numeric value ends: ") + pstring(cstr));
+ }
+ else
+ {
+ throw pexception(pstring("Out of range: ") + pstring(cstr));
+ }
+ return static_cast<T>(ret);
+ }
+
+ 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_ */