File indexing completed on 2024-05-19 09:43:05
0001 /***************************************************************************** 0002 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU Lesser General Public License as * 0006 * published by the Free Software Foundation; either version 2.1 of the * 0007 * License, or (at your option) version 3, or any later version accepted * 0008 * by the membership of KDE e.V. (or its successor approved by the * 0009 * membership of KDE e.V.), which shall act as a proxy defined in * 0010 * Section 6 of version 3 of the license. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, * 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0015 * Lesser General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU Lesser General Public * 0018 * License along with this library. If not, * 0019 * see <http://www.gnu.org/licenses/>. * 0020 *****************************************************************************/ 0021 0022 #ifndef _QTC_UTILS_UTILS_H_ 0023 #define _QTC_UTILS_UTILS_H_ 0024 0025 #include <stdint.h> 0026 #include <string.h> 0027 #include <stdlib.h> 0028 #include <stdio.h> 0029 #include <stddef.h> 0030 #include <math.h> 0031 0032 #include "macros.h" 0033 0034 #include <memory> 0035 #include <utility> 0036 #include <type_traits> 0037 #include <initializer_list> 0038 0039 /** 0040 * \file utils.h 0041 * \author Yichao Yu <yyc1992@gmail.com> 0042 * \brief Some generic functions and macros. 0043 */ 0044 0045 /** 0046 * Generic call back function. 0047 */ 0048 typedef void (*QtcCallback)(void*); 0049 0050 /** 0051 * Allocate memory and initialize it to zero. 0052 * \param size size of the memory 0053 */ 0054 QTC_ALWAYS_INLINE static inline void* 0055 qtcAlloc0(size_t size) 0056 { 0057 void *p = malloc(size); 0058 memset(p, 0, size); 0059 return p; 0060 } 0061 0062 /** 0063 * Allocate memory of size \param size for a \param type. 0064 * The memory is initialized to zero. 0065 * \param type type pointed to by the pointer 0066 * \param size size of the memory 0067 * \sa qtcAlloc0 0068 */ 0069 #define qtcNewSize(type, size) ((type*)qtcAlloc0(size)) 0070 0071 /** 0072 * Allocate memory for a \param type or an array of \param type. 0073 * The memory is initialized to zero. 0074 * \param type type pointed to by the pointer 0075 * \param n (optional) elements in the array (default: 1) 0076 * \sa qtcNewSize 0077 */ 0078 #define qtcNew(type, n...) \ 0079 qtcNewSize(type, sizeof(type) * (QTC_DEFAULT(n, 1))) 0080 0081 namespace QtCurve { 0082 0083 template<typename T> 0084 using remove_cvr_t = typename std::remove_cv< 0085 typename std::remove_reference<T>::type>::type; 0086 0087 template<typename T> 0088 struct _isChar : std::is_same<remove_cvr_t<T>, char> {}; 0089 0090 template<typename T> 0091 struct _isCharPtr : std::integral_constant< 0092 bool, 0093 std::is_pointer<remove_cvr_t<T> >::value && 0094 _isChar<typename std::remove_pointer<remove_cvr_t<T> >::type>::value> {}; 0095 0096 template<typename T> 0097 struct _isCharAry : std::integral_constant< 0098 bool, 0099 std::is_array<remove_cvr_t<T> >::value && 0100 _isChar<typename std::remove_extent<remove_cvr_t<T> >::type>::value> {}; 0101 0102 template<typename T> 0103 struct _isCharStr : std::integral_constant< 0104 bool, _isCharPtr<T>::value || _isCharAry<T>::value> {}; 0105 0106 template<typename T1, typename T2, class=void> 0107 struct _oneOfCmp { 0108 inline bool operator()(T1 &&v1, T2 &&v2) 0109 { 0110 return std::forward<T1>(v1) == std::forward<T2>(v2); 0111 } 0112 }; 0113 0114 template<typename T1, typename T2> 0115 struct _oneOfCmp<T1, T2, typename std::enable_if<_isCharStr<T1>::value && 0116 _isCharStr<T2>::value>::type> { 0117 inline bool operator()(T1 &&v1, T2 &&v2) 0118 { 0119 return v1 && strcmp(v1, v2) == 0; 0120 } 0121 }; 0122 0123 template<typename...> 0124 struct CaseCmp { 0125 inline bool operator()(const char *str1, const char *str2) 0126 { 0127 return str1 && strcasecmp(str1, str2) == 0; 0128 } 0129 }; 0130 0131 template<template<typename...> class _Cmp=_oneOfCmp, 0132 typename T1, typename T2> 0133 static inline bool 0134 oneOf(T1 &&v1, T2 &&v2) 0135 { 0136 return _Cmp<T1, T2>()(std::forward<T1>(v1), std::forward<T2>(v2)); 0137 } 0138 0139 template<template<typename...> class _Cmp=_oneOfCmp, 0140 typename T, typename First, typename... Rest> 0141 static inline bool 0142 oneOf(T &&value, First &&first, Rest&&... rest) 0143 { 0144 return (oneOf<_Cmp>(std::forward<T>(value), std::forward<First>(first)) || 0145 oneOf<_Cmp>(std::forward<T>(value), std::forward<Rest>(rest)...)); 0146 } 0147 0148 template<template<typename...> class _Cmp=_oneOfCmp, 0149 typename... Args> 0150 static inline bool 0151 noneOf(Args&&... args) 0152 { 0153 return !oneOf<_Cmp>(std::forward<Args>(args)...); 0154 } 0155 0156 /** 0157 * Turn a variable into a const reference. This is useful for range-based for 0158 * loop where a non-const variable may cause unnecessary copy. 0159 */ 0160 template <class T> 0161 static inline const T& 0162 const_(const T &t) 0163 { 0164 return t; 0165 } 0166 0167 struct CDeleter { 0168 template<typename T> 0169 void operator()(T *p) 0170 { 0171 free((void*)p); 0172 } 0173 }; 0174 0175 template<typename T> 0176 using uniqueCPtr = std::unique_ptr<T, CDeleter>; 0177 0178 template<typename T, size_t N> 0179 class LocalBuff { 0180 LocalBuff(const LocalBuff&) = delete; 0181 public: 0182 LocalBuff(size_t size=N, const T *ary=nullptr) 0183 : m_ptr(size > N ? qtcNew(T, size) : m_static_buf), 0184 m_size(size), 0185 m_static_buf{} 0186 { 0187 if (ary) { 0188 memcpy(m_ptr, ary, sizeof(T) * size); 0189 } 0190 } 0191 bool 0192 is_static() const 0193 { 0194 return m_ptr == m_static_buf; 0195 } 0196 void 0197 resize(size_t size) 0198 { 0199 if (is_static()) { 0200 if (size > N) { 0201 m_ptr = qtcNew(T, size); 0202 memcpy(m_ptr, m_static_buf, sizeof(T) * m_size); 0203 } 0204 } else { 0205 m_ptr = (T*)realloc(m_ptr, sizeof(T) * size); 0206 } 0207 m_size = size; 0208 } 0209 T* 0210 get() const 0211 { 0212 return m_ptr; 0213 } 0214 T& 0215 operator[](size_t i) const 0216 { 0217 return get()[i]; 0218 } 0219 size_t 0220 size() const 0221 { 0222 return m_size; 0223 } 0224 ~LocalBuff() 0225 { 0226 if (!is_static()) { 0227 free(m_ptr); 0228 } 0229 } 0230 protected: 0231 T *m_ptr; 0232 size_t m_size; 0233 private: 0234 T m_static_buf[N]; 0235 }; 0236 0237 const char *getProgName(); 0238 } 0239 0240 extern "C" const char *qtcVersion(); 0241 0242 template<typename T> 0243 using qtcPtrType = QtCurve::remove_cvr_t<typename std::remove_pointer<T>::type>; 0244 0245 #define qtcMemPtr(ptr, name) &qtcPtrType<decltype(ptr)>::name 0246 0247 // Use lambda for lazy evaluation of \param def 0248 #define qtcDefault(val, def) ([&] { \ 0249 auto __val = (val); \ 0250 return __val ? __val : (def); \ 0251 }()) 0252 // Use lambda for lazy evaluation of \param args 0253 // C++ allows returning void expression! =) See the quote of the standard 0254 // (here)[http://gcc.gnu.org/ml/gcc/2006-10/msg00697.html] 0255 // The current c++ implementation of this macro does not support functions 0256 // with types that do not have accessible default constructor (including 0257 // references) as return type. 0258 #define qtcCall(func, args...) ([&] { \ 0259 auto __func = (func); \ 0260 return __func ? __func(args) : decltype(__func(args))(); \ 0261 }()) 0262 #define qtcAssign(addr, exp) do { \ 0263 auto __addr = (addr); \ 0264 if (__addr) { \ 0265 *__addr = (exp); \ 0266 } \ 0267 } while(0) 0268 0269 // Returning a void expression is valid c++, see above 0270 // Or https://gcc.gnu.org/ml/gcc/2006-10/msg00697.html 0271 #define QTC_RET_IF_FAIL(exp, val...) do { \ 0272 if (!qtcLikely(exp)) { \ 0273 return (QTC_DEFAULT(val, (void)0)); \ 0274 } \ 0275 } while (0) 0276 0277 #if defined(__GNUC__) && __GNUC__ >= 7 0278 # define QTC_FALLTHROUGH() __attribute__((fallthrough)) 0279 #elif defined(__clang_major__) && defined(__clang_minor__) && \ 0280 (__clang_major__ > 4 || __clang_minor__ >= 5) 0281 // We require at least clang 3.x for c++11 0282 # define QTC_FALLTHROUGH() [[clang::fallthrough]] 0283 #else 0284 # define QTC_FALLTHROUGH() 0285 #endif 0286 0287 #endif