diff options
Diffstat (limited to 'src/lib/netlist/plib/putil.h')
-rw-r--r-- | src/lib/netlist/plib/putil.h | 353 |
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_ |