88
78
#define qtcNew(type, n...) \
89
79
qtcNewSize(type, sizeof(type) * (QTC_DEFAULT(n, 1)))
92
81
namespace QtCurve {
84
using remove_cvr_t = typename std::remove_cv<
85
typename std::remove_reference<T>::type>::type;
88
struct _isChar : std::is_same<remove_cvr_t<T>, char> {};
91
struct _isCharPtr : std::integral_constant<
93
std::is_pointer<remove_cvr_t<T> >::value &&
94
_isChar<typename std::remove_pointer<remove_cvr_t<T> >::type>::value> {};
97
struct _isCharAry : std::integral_constant<
99
std::is_array<remove_cvr_t<T> >::value &&
100
_isChar<typename std::remove_extent<remove_cvr_t<T> >::type>::value> {};
103
struct _isCharStr : std::integral_constant<
104
bool, _isCharPtr<T>::value || _isCharAry<T>::value> {};
106
template<typename T1, typename T2, class=void>
108
inline bool operator()(T1 &&v1, T2 &&v2)
110
return std::forward<T1>(v1) == std::forward<T2>(v2);
114
template<typename T1, typename T2>
115
struct _oneOfCmp<T1, T2, typename std::enable_if<_isCharStr<T1>::value &&
116
_isCharStr<T2>::value>::type> {
117
inline bool operator()(T1 &&v1, T2 &&v2)
119
return v1 && strcmp(v1, v2) == 0;
123
template<typename...>
125
inline bool operator()(const char *str1, const char *str2)
127
return str1 && strcasecmp(str1, str2) == 0;
131
template<template<typename...> class _Cmp=_oneOfCmp,
132
typename T1, typename T2>
134
oneOf(T1 &&v1, T2 &&v2)
136
return _Cmp<T1, T2>()(std::forward<T1>(v1), std::forward<T2>(v2));
139
template<template<typename...> class _Cmp=_oneOfCmp,
140
typename T, typename First, typename... Rest>
142
oneOf(T &&value, First &&first, Rest&&... rest)
144
return (oneOf<_Cmp>(std::forward<T>(value), std::forward<First>(first)) ||
145
oneOf<_Cmp>(std::forward<T>(value), std::forward<Rest>(rest)...));
148
template<template<typename...> class _Cmp=_oneOfCmp,
151
noneOf(Args&&... args)
153
return !oneOf<_Cmp>(std::forward<Args>(args)...);
94
157
* Turn a variable into a const reference. This is useful for range-based for
95
158
* loop where a non-const variable may cause unnecessary copy.
107
* Define a buffer type (struct) for \param type.
108
* \sa QTC_DEF_LOCAL_BUFF
110
#define QTC_BUFF_TYPE(type) \
117
type *const static_p; \
118
const size_t static_l; \
122
* \brief Define a local buffer for holding an array of \param type.
123
* \param type type of the array element.
124
* \param name name of the variable
125
* \param stack_size the maximum number of elements in the array that will be
127
* \param size real size of the array.
129
* This macro define a buffer \param name for an array of \param type.
130
* The buffer's field p points to the address of the array.
131
* Use QTC_FREE_LOCAL_BUFF to free the buffer.
132
* \sa QTC_FREE_LOCAL_BUFF
133
* \sa QTC_RESIZE_LOCAL_BUFF
135
#define QTC_DEF_LOCAL_BUFF(type, name, stack_size, size) \
136
type __##qtc_local_buff##name[stack_size]; \
137
QTC_BUFF_TYPE(type) name = { \
138
{__##qtc_local_buff##name}, \
139
sizeof(__##qtc_local_buff##name) / sizeof(type), \
140
__##qtc_local_buff##name, \
141
sizeof(__##qtc_local_buff##name) / sizeof(type) \
143
QTC_RESIZE_LOCAL_BUFF(name, size)
146
* \brief Resize a local buffer defined with QTC_DEF_LOCAL_BUFF for holding
148
* \param name name of the buffer
149
* \param size new minimum size of the array.
151
* This macro resizes a buffer \param name defined with QTC_DEF_LOCAL_BUFF for
152
* holding at least \param size elements.
153
* \sa QTC_DEF_LOCAL_BUFF
154
* \sa QTC_FREE_LOCAL_BUFF
156
#define QTC_RESIZE_LOCAL_BUFF(name, size) do { \
157
size_t __new_size = (size); \
158
if (__new_size <= (name).l || __new_size <= (name).static_l) \
160
(name).l = __new_size; \
161
size_t __alloc_size = sizeof(*(name).p) * __new_size; \
162
if ((name).p == (name).static_p) { \
163
(name)._p = malloc(__alloc_size); \
165
(name)._p = realloc((name)._p, __alloc_size); \
170
* \brief Free a local buffer defined with QTC_DEF_LOCAL_BUFF if necessary.
171
* \param name name of the buffer
173
* \sa QTC_DEF_LOCAL_BUFF
174
* \sa QTC_RESIZE_LOCAL_BUFF
176
#define QTC_FREE_LOCAL_BUFF(name) do { \
177
if ((name).p != (name).static_p) { \
185
* Binary searches an sorted array of \param nmemb objects.
186
* \param key The key for the search.
187
* \param base pointer to the first element.
188
* \param nmemb number of object in the array.
189
* \param size size of each object.
190
* \param compar function to compare key with an object.
192
* \return if a matching object is found, the pointer to the object will be
193
* returned, otherwise, a pointer to where the new object should be
194
* inserted will be returned. If the key is greater than all the
195
* elements in the array, the returned pointer will point to the end
196
* of the list, i.e. out of the bound of the list.
198
void *qtcBSearch(const void *key, const void *base, size_t nmemb, size_t size,
199
int (*compar)(const void*, const void*));
200
const char *qtcGetProgName();
206
template<typename T, typename First>
207
QTC_ALWAYS_INLINE static inline bool
208
qtcOneOf(T &&value, First &&first)
210
return value == first;
212
template<typename T, typename First, typename... Rest>
213
QTC_ALWAYS_INLINE static inline bool
214
qtcOneOf(T &&value, First &&first, Rest &&...rest...)
216
return value == first || qtcOneOf(std::forward<T>(value),
217
std::forward<Rest>(rest)...);
169
void operator()(T *p)
176
using uniqueCPtr = std::unique_ptr<T, CDeleter>;
178
template<typename T, size_t N>
180
LocalBuff(const LocalBuff&) = delete;
182
LocalBuff(size_t size=N, const T *ary=nullptr)
183
: m_ptr(size > N ? qtcNew(T, size) : m_static_buf),
188
memcpy(m_ptr, ary, sizeof(T) * size);
194
return m_ptr == m_static_buf;
201
m_ptr = qtcNew(T, size);
202
memcpy(m_ptr, m_static_buf, sizeof(T) * m_size);
205
m_ptr = (T*)realloc(m_ptr, sizeof(T) * size);
215
operator[](size_t i) const
237
const char *getProgName();
240
extern "C" const char *qtcVersion();
243
using qtcPtrType = QtCurve::remove_cvr_t<typename std::remove_pointer<T>::type>;
245
#define qtcMemPtr(ptr, name) &qtcPtrType<decltype(ptr)>::name
219
247
// Use lambda for lazy evaluation of \param def
220
#define qtcDefault(val, def) \
248
#define qtcDefault(val, def) ([&] { \
222
249
auto __val = (val); \
223
250
return __val ? __val : (def); \
225
252
// Use lambda for lazy evaluation of \param args
226
253
// C++ allows returning void expression! =) See the quote of the standard
227
254
// (here)[http://gcc.gnu.org/ml/gcc/2006-10/msg00697.html]
228
255
// The current c++ implementation of this macro does not support functions
229
256
// with types that do not have accessible default constructor (including
230
257
// references) as return type.
231
#define qtcCall(func, args...) \
258
#define qtcCall(func, args...) ([&] { \
233
259
auto __func = (func); \
234
260
return __func ? __func(args) : decltype(__func(args))(); \
236
262
#define qtcAssign(addr, exp) do { \
237
263
auto __addr = (addr); \
239
265
*__addr = (exp); \
243
#define qtcOneOf(exp, args...) \
245
const typeof((exp)) __val = (exp); \
246
const typeof((exp)) __args[] = {args}; \
247
size_t __arg_n = sizeof(__args) / sizeof(__args[0]); \
248
bool __res = false; \
249
for (size_t __i = 0;__i < __arg_n;__i++) { \
250
if (__val == __args[__i]) { \
257
#define qtcDefault(val, def) \
259
typeof(val) __val = (val); \
260
__val ? __val : (def); \
262
// The current c implementation of this macro does not support functions
263
// with non-scaler as return type.
264
#define qtcCall(func, args...) \
266
typeof(func) __func = (func); \
267
__func ? __func(args) : (typeof(__func(args)))0; \
269
#define qtcAssign(addr, exp) do { \
270
typeof(addr) __addr = (addr); \
276
#define qtcNoneOf(args...) (!qtcOneOf(args))
278
// gcc and clang both seem find with returning void expression in c
279
// (even with -ansi).
280
// Not sure if this is standard but should be fine since we require gnu99
269
// Returning a void expression is valid c++, see above
270
// Or https://gcc.gnu.org/ml/gcc/2006-10/msg00697.html
282
271
#define QTC_RET_IF_FAIL(exp, val...) do { \
283
272
if (!qtcLikely(exp)) { \
284
273
return (QTC_DEFAULT(val, (void)0)); \