1 // license:GPL-2.0+ 2 // copyright-holders:Couriersud 3 4 #ifndef PUTIL_H_ 5 #define PUTIL_H_ 6 7 /// 8 /// \file putil.h 9 /// 10 11 #include "palloc.h" 12 #include "pexception.h" 13 #include "pstring.h" 14 15 #include <algorithm> 16 #include <initializer_list> 17 #include <sstream> 18 #include <vector> 19 20 #define PSTRINGIFY_HELP(y) # y 21 #define PSTRINGIFY(x) PSTRINGIFY_HELP(x) 22 23 // Discussion and background of this MSVC bug: https://github.com/mamedev/mame/issues/6106 24 /// 25 /// \brief Macro to work around a bug in MSVC treatment of __VA_ARGS__ 26 /// 27 #define PMSVC_VARARG_BUG(MACRO, ARGS) MACRO ARGS 28 29 /// \brief Determine number of arguments in __VA_ARGS__ 30 /// 31 /// This macro works up to 16 arguments in __VA_ARGS__ 32 /// 33 /// \returns Number of arguments 34 /// 35 #define PNARGS(...) PNARGS_1(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 36 37 #define PNARGS_2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N 38 #define PNARGS_1(...) PMSVC_VARARG_BUG(PNARGS_2, (__VA_ARGS__)) 39 40 /// \brief Concatenate two arguments after expansion 41 /// 42 /// \returns Concatenated expanded arguments 43 /// 44 #define PCONCAT(a, b) PCONCAT_(a, b) 45 46 #define PCONCAT_(a, b) a ## b 47 48 #define PSTRINGIFY_1(x) #x 49 #define PSTRINGIFY_2(x, x2) #x, #x2 50 #define PSTRINGIFY_3(x, x2, x3) #x, #x2, #x3 51 #define PSTRINGIFY_4(x, x2, x3, x4) #x, #x2, #x3, #x4 52 #define PSTRINGIFY_5(x, x2, x3, x4, x5) #x, #x2, #x3, #x4, #x5 53 #define PSTRINGIFY_6(x, x2, x3, x4, x5, x6) #x, #x2, #x3, #x4, #x5, #x6 54 #define PSTRINGIFY_7(x, x2, x3, x4, x5, x6, x7) #x, #x2, #x3, #x4, #x5, #x6, #x7 55 #define PSTRINGIFY_8(x, x2, x3, x4, x5, x6, x7, x8) #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8 56 #define PSTRINGIFY_9(x, x2, x3, x4, x5, x6, x7, x8, x9) \ 57 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9 58 #define PSTRINGIFY_10(x, x2, x3, x4, x5, x6, x7, x8, x9, xa) \ 59 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa 60 #define PSTRINGIFY_11(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb) \ 61 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb 62 #define PSTRINGIFY_12(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc) \ 63 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc 64 #define PSTRINGIFY_13(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd) \ 65 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd 66 #define PSTRINGIFY_14(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe) \ 67 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe 68 #define PSTRINGIFY_15(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf) \ 69 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe, #xf 70 #define PSTRINGIFY_16(x, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, x10) \ 71 #x, #x2, #x3, #x4, #x5, #x6, #x7, #x8, #x9, #xa, #xb, #xc, #xd, #xe, #xf, #x10 72 73 /// \brief Individually stringify up to 16 arguments 74 /// 75 /// PSTRINGIFY_VA(a, b, c) will be expanded to "a", "b", "c" 76 /// 77 /// \returns List of stringified individual arguments 78 /// 79 #define PSTRINGIFY_VA(...) PMSVC_VARARG_BUG(PCONCAT, (PSTRINGIFY_, PNARGS(__VA_ARGS__)))(__VA_ARGS__) 80 81 /// \brief Dispatch VARARG macro to specialized macros 82 /// 83 /// ``` 84 /// #define LOCAL_LIB_ENTRY(...) PCALLVARARG(LOCAL_LIB_ENTRY_, __VA_ARGS__) 85 /// ``` 86 /// 87 /// Will pass varargs depending on number of arguments to 88 /// 89 /// ``` 90 /// LOCAL_LIB_ENTRY_1(a1) 91 /// LOCAL_LIB_ENTRY_2(a1 , a2) 92 /// ``` 93 /// 94 /// \returns result of specialized macro 95 /// 96 #define PCALLVARARG(MAC, ...) PMSVC_VARARG_BUG(PCONCAT, (MAC, PNARGS(__VA_ARGS__)))(__VA_ARGS__) 97 98 // FIXME:: __FUNCTION__ may be not be supported by all compilers. 99 100 #define PSOURCELOC() plib::source_location(__FILE__, __LINE__) 101 102 namespace plib 103 { 104 105 namespace util 106 { 107 pstring basename(const pstring &filename, const pstring &suffix = ""); 108 pstring path(const pstring &filename); 109 bool exists(const pstring &filename); 110 pstring buildpath(std::initializer_list<pstring> list ); 111 pstring environment(const pstring &var, const pstring &default_val); 112 } // namespace util 113 114 namespace container 115 { 116 template <class C, class T> contains(C & con,const T & elem)117 bool contains(C &con, const T &elem) 118 { 119 return std::find(con.begin(), con.end(), elem) != con.end(); 120 } 121 122 static constexpr const std::size_t npos = static_cast<std::size_t>(-1); 123 template <class C> indexof(C & con,const typename C::value_type & elem)124 std::size_t indexof(C &con, const typename C::value_type &elem) 125 { 126 auto it = std::find(con.begin(), con.end(), elem); 127 if (it != con.end()) 128 return narrow_cast<std::size_t>(it - con.begin()); 129 return npos; 130 } 131 132 template <class C> insert_at(C & con,const std::size_t index,const typename C::value_type & elem)133 void insert_at(C &con, const std::size_t index, const typename C::value_type &elem) 134 { 135 con.insert(con.begin() + narrow_cast<std::ptrdiff_t>(index), elem); 136 } 137 138 template <class C> remove(C & con,const typename C::value_type & elem)139 void remove(C &con, const typename C::value_type &elem) 140 { 141 con.erase(std::remove(con.begin(), con.end(), elem), con.end()); 142 } 143 } // namespace container 144 145 // ---------------------------------------------------------------------------------------- 146 // simple hash 147 // ---------------------------------------------------------------------------------------- 148 149 template <typename T> hash(const T * buf,std::size_t size)150 std::size_t hash(const T *buf, std::size_t size) 151 { 152 std::size_t result = 5381; // NOLINT 153 for (const T* p = buf; p != buf + size; p++) 154 result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ narrow_cast<std::size_t>(*p); // NOLINT 155 return result; 156 } 157 158 } // namespace plib 159 160 #endif // PUTIL_H_ 161