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