summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/putil.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/putil.h')
-rw-r--r--src/lib/netlist/plib/putil.h353
1 files changed, 158 insertions, 195 deletions
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index e6e6153d840..ae383aaf807 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -1,33 +1,121 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * putil.h
- *
- */
#ifndef PUTIL_H_
#define PUTIL_H_
+///
+/// \file putil.h
+///
+
+#include "palloc.h"
#include "pexception.h"
#include "pstring.h"
+
#include <algorithm>
#include <initializer_list>
-#include <locale>
#include <sstream>
#include <vector>
-#include <iostream>
-#define PSTRINGIFY_HELP(y) # y
+#define PSTRINGIFY_HELP(y) #y
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x)
+// Discussion and background of this MSVC bug:
+// https://github.com/mamedev/mame/issues/6106
+///
+/// \brief Macro to work around a bug in MSVC treatment of __VA_ARGS__
+///
+#define PMSVC_VARARG_BUG(MACRO, ARGS) MACRO ARGS
+
+// clang-format off
+
+/// \brief Determine number of arguments in __VA_ARGS__
+///
+/// This macro works up to 16 arguments in __VA_ARGS__
+///
+/// \returns Number of arguments
+///
+#define PNARGS(...) PNARGS_1(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define PNARGS_2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
+#define PNARGS_1(...) PMSVC_VARARG_BUG(PNARGS_2, (__VA_ARGS__))
+
+/// \brief Concatenate two arguments after expansion
+///
+/// \returns Concatenated expanded arguments
+///
+#define PCONCAT(a, b) PCONCAT_(a, b)
+
+#define PCONCAT_(a, b) a ## b
+
+#define PSTRINGIFY_1(x) #x
+#define PSTRINGIFY_2(x, x2) #x, #x2
+#define PSTRINGIFY_3(x, x2, x3) #x, #x2, #x3
+#define PSTRINGIFY_4(x, x2, x3, x4) #x, #x2, #x3, #x4
+#define PSTRINGIFY_5(x, x2, x3, x4, x5) #x, #x2, #x3, #x4, #x5
+#define PSTRINGIFY_6(x, x2, x3, x4, x5, x6) #x, #x2, #x3, #x4, #x5, #x6
+#define PSTRINGIFY_7(x, x2, x3, x4, x5, x6, x7) #x, #x2, #x3, #x4, #x5, #x6, #x7
+#define PSTRINGIFY_8(x, x2, x3, x4, x5, x6, x7, x8) #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8
+#define PSTRINGIFY_9(x, x2, x3, x4, x5, x6, x7, x8, x9) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9
+#define PSTRINGIFY_10(x, x2, x3, x4, x5, x6, x7, x8, x9, xa) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa
+#define PSTRINGIFY_11(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb
+#define PSTRINGIFY_12(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc
+#define PSTRINGIFY_13(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd
+#define PSTRINGIFY_14(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe
+#define PSTRINGIFY_15(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe, #xf
+#define PSTRINGIFY_16(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, x10) \
+ #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe, #xf, #x10
+
+// clang-format on
+
+/// \brief Individually stringify up to 16 arguments
+///
+/// PSTRINGIFY_VA(a, b, c) will be expanded to "a", "b", "c"
+///
+/// \returns List of stringified individual arguments
+///
+#define PSTRINGIFY_VA(...) \
+ PMSVC_VARARG_BUG(PCONCAT, (PSTRINGIFY_, PNARGS(__VA_ARGS__)))(__VA_ARGS__)
+
+/// \brief Dispatch VARARG macro to specialized macros
+///
+/// ```
+/// #define LOCAL_LIB_ENTRY(...) PCALLVARARG(LOCAL_LIB_ENTRY_, __VA_ARGS__)
+/// ```
+///
+/// Will pass varargs depending on number of arguments to
+///
+/// ```
+/// LOCAL_LIB_ENTRY_1(a1)
+/// LOCAL_LIB_ENTRY_2(a1 , a2)
+/// ```
+///
+/// \returns result of specialized macro
+///
+#define PCALLVARARG(MAC, ...) \
+ PMSVC_VARARG_BUG(PCONCAT, (MAC, PNARGS(__VA_ARGS__)))(__VA_ARGS__)
+
+// FIXME:: __FUNCTION__ may be not be supported by all compilers.
+
+#define PSOURCELOC() plib::source_location(__FILE__, __LINE__)
namespace plib
{
namespace util
{
- const pstring buildpath(std::initializer_list<pstring> list );
- const pstring environment(const pstring &var, const pstring &default_val);
+ pstring basename(const pstring &filename, const pstring &suffix = "");
+ pstring path(const pstring &filename);
+ bool exists(const pstring &filename);
+ pstring build_path(std::initializer_list<pstring> list);
+ pstring environment(const pstring &var, const pstring &default_val);
} // namespace util
namespace container
@@ -40,18 +128,19 @@ namespace plib
static constexpr const std::size_t npos = static_cast<std::size_t>(-1);
template <class C>
- std::size_t indexof(C &con, const typename C::value_type &elem)
+ std::size_t index_of(C &con, const typename C::value_type &elem)
{
auto it = std::find(con.begin(), con.end(), elem);
if (it != con.end())
- return static_cast<std::size_t>(it - con.begin());
+ return narrow_cast<std::size_t>(it - con.begin());
return npos;
}
template <class C>
- void insert_at(C &con, const std::size_t index, const typename C::value_type &elem)
+ void insert_at(C &con, const std::size_t index,
+ const typename C::value_type &elem)
{
- con.insert(con.begin() + static_cast<std::ptrdiff_t>(index), elem);
+ con.insert(con.begin() + narrow_cast<std::ptrdiff_t>(index), elem);
}
template <class C>
@@ -61,198 +150,72 @@ namespace plib
}
} // namespace container
- /* May be further specialized .... This is the generic version */
- template <typename T>
- struct constants
- {
- static constexpr T zero() noexcept { return static_cast<T>(0); }
- static constexpr T one() noexcept { return static_cast<T>(1); }
- static constexpr T two() noexcept { return static_cast<T>(2); }
- static constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209); }
- static constexpr T pi() noexcept { return static_cast<T>(3.14159265358979323846264338327950); }
-
- /*!
- * \brief Electric constant of vacuum
- */
- static constexpr T eps_0() noexcept { return static_cast<T>(8.854187817e-12); }
- /*!
- * \brief Relative permittivity of Silicon dioxide
- */
- static constexpr T eps_SiO2() noexcept { return static_cast<T>(3.9); }
- /*!
- * \brief Relative permittivity of Silicon
- */
- static constexpr T eps_Si() noexcept { return static_cast<T>(11.7); }
- /*!
- * \brief Boltzmann constant
- */
- static constexpr T k_b() noexcept { return static_cast<T>(1.38064852e-23); }
- /*!
- * \brief room temperature (gives VT = 0.02585 at T=300)
- */
- static constexpr T T0() noexcept { return static_cast<T>(300); }
- /*!
- * \brief Elementary charge
- */
- static constexpr T Q_e() noexcept { return static_cast<T>(1.6021765314e-19); }
- /*!
- * \brief Intrinsic carrier concentration in 1/m^3 of Silicon
- */
- static constexpr T NiSi() noexcept { return static_cast<T>(1.45e16); }
-
- template <typename V>
- static constexpr const T cast(V &&v) noexcept { return static_cast<T>(v); }
- };
-
- static_assert(noexcept(constants<double>::one()) == true, "Not evaluated as constexpr");
-
-
- template <class C>
- struct indexed_compare
+ /// \brief Consistent hash implementation
+ ///
+ /// Hash implementations in c++ standard libraries may differ and deliver
+ /// different results. This hash can be used as a replacement hash in e.g.
+ /// std::map to deliver consistent results.
+ ///
+ /// \tparam V result type
+ /// \tparam T buffer element type
+ /// \param buf pointer to buffer for which hash should be calculated
+ /// \param size number of buffer elements
+ /// \return the hash of the buffer
+ ///
+ template <typename V, typename T>
+ constexpr V hash(const T *buf, std::size_t size) noexcept
{
- explicit indexed_compare(const C& target): m_target(target) {}
-
- bool operator()(int a, int b) const { return m_target[a] < m_target[b]; }
-
- const C& m_target;
- };
-
- // ----------------------------------------------------------------------------------------
- // string list
- // ----------------------------------------------------------------------------------------
-
- std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty = false);
- std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl);
- std::vector<std::string> psplit_r(const std::string &stri,
- const std::string &token,
- const std::size_t maxsplit);
-
- // ----------------------------------------------------------------------------------------
- // 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;
+ V result = 5381; // NOLINT
+ for (const T *p = buf; p != buf + size; p++)
+ result = ((result << 5) + result) ^ (result >> (32 - 5))
+ ^ narrow_cast<std::size_t>(*p); // NOLINT
+ return result;
}
- 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>
+ /// \brief Execute code at end of block
+ ///
+ /// The class can be used to execute code at the end of a block. It follows
+ /// the same design as std::lock_guard.
+ ///
+ /// Since the functor is executed in the destructor of the class the
+ /// execution is protected by a try catch block. If an exception is raised,
+ /// \ref plib::terminate is called.
+ ///
+ /// \tparam F type of functor - will be derived by template deduction guide
+ ///
+ template <typename F>
+ struct functor_guard
{
- template <typename S>
- long long operator()(std::locale loc, const S &arg, std::size_t *idx)
+ /// \brief constructor
+ ///
+ /// \param f functor to execute
+ functor_guard(F &&f)
+ : m_f(std::move(f))
{
- //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)
+ /// \brief destructor
+ ///
+ ~functor_guard()
{
- //return std::stoll(arg, idx);
- return pstonum_locale<unsigned long long>(loc, arg, idx);
+ try
+ {
+ m_f();
+ }
+ catch (...)
+ {
+ plib::terminate("exception raised in lambda_guard");
+ }
}
- };
- 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);
- }
+ private:
+ F m_f;
};
- template<typename T, typename S>
- T pstonum(const S &arg, 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) || std::abs(ret) >= std::numeric_limits<T>::min() ))
- {
- if (cstr[idx] != 0)
- throw pexception(pstring("Continuation after numeric value ends: ") + cstr);
- }
- else
- {
- throw pexception(pstring("Out of range: ") + cstr);
- }
- return static_cast<T>(ret);
- }
-
- template<typename R, bool CLOCALE, 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);
- }
- }
-
- //============================================================
- // penum - strongly typed enumeration
- //============================================================
-
- struct penum_base
- {
- protected:
- static int from_string_int(const char *str, const char *x);
- static std::string nthstr(int n, const char *str);
- };
+ /// \brief template deduction guide
+ ///
+ template <class F>
+ functor_guard(F f) -> functor_guard<F>;
} // namespace plib
-#define P_ENUM(ename, ...) \
- struct ename : public plib::penum_base { \
- enum E { __VA_ARGS__ }; \
- ename (E v) : m_v(v) { } \
- bool set_from_string (const std::string &s) { \
- static char const *const strings = # __VA_ARGS__; \
- int f = from_string_int(strings, s.c_str()); \
- if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
- } \
- operator E() const {return m_v;} \
- bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
- bool operator==(const E &rhs) const {return m_v == rhs;} \
- std::string name() const { \
- static char const *const strings = # __VA_ARGS__; \
- return nthstr(static_cast<int>(m_v), strings); \
- } \
- private: E m_v; };
-
-
-#endif /* PUTIL_H_ */
+#endif // PUTIL_H_