17 #ifndef _UTIL_ITIES_H_
18 #define _UTIL_ITIES_H_
30 #include <type_traits>
33 #if __cplusplus < 201402L
36 #define CONSTEXPR constexpr
53 template <
unsigned int bit,
unsigned int w
idth,
typename T>
54 CONSTEXPR
typename std::enable_if<std::is_unsigned<T>::value, T>::type
bit_sub(T v) {
55 static_assert((bit + width) <= 8 *
sizeof(T));
56 T res = (v >> bit) & ((T(1) << width) - 1);
60 template <
unsigned int bit,
unsigned int w
idth,
typename T>
61 CONSTEXPR
typename std::enable_if<std::is_signed<T>::value, T>::type
bit_sub(T v) {
62 static_assert((bit + width) <= 8 *
sizeof(T));
63 static_assert(width > 0);
64 auto field = v >> bit;
65 auto amount = (field & ~(~T(1) << (width - 1) << 1)) - (field & (T(1) << (width - 1)) << 1);
69 template <
unsigned offset,
typename R,
typename T> R _bit_comb(T v) {
return v << offset; }
70 template <
unsigned offset,
typename R,
typename T,
typename... Args> R _bit_comb(T first, Args... args) {
71 return (first << offset) + _bit_comb<offset + 8, R>(args...);
82 template <
typename R,
typename T,
typename... Args> R
bit_comb(T first, Args... args) {
return first + _bit_comb<8, R>(args...); }
92 template <
typename T,
unsigned B> CONSTEXPR T
signextend(
const typename std::make_unsigned<T>::type x) {
111 template <
unsigned int bit,
unsigned int w
idth,
typename T>
inline constexpr
typename std::make_signed<T>::type
signed_bit_sub(T v) {
112 #if __cplusplus < 201402L
113 return ((v << (
sizeof(T) * 8 - bit - width)) >> (
sizeof(T) * 8 - width));
115 typename std::make_signed<T>::type r = v << (
sizeof(T) * 8 - bit - width);
116 typename std::make_signed<T>::type ret = (r >> (
sizeof(T) * 8 - width));
122 inline constexpr uint64_t
operator"" _kB(
unsigned long long val) {
return val * 1 << 10; }
124 inline constexpr uint64_t
operator"" _MB(
unsigned long long val) {
return val * 1 << 20; }
126 inline constexpr uint64_t
operator"" _GB(
unsigned long long val) {
return val * 1 << 30; }
128 inline constexpr uint64_t
operator"" _KiB(
unsigned long long val) {
return val * 1 << 10; }
130 inline constexpr uint64_t
operator"" _MiB(
unsigned long long val) {
return val * 1 << 20; }
132 inline constexpr uint64_t
operator"" _GiB(
unsigned long long val) {
return val * 1 << 30; }
134 inline constexpr uint64_t
operator"" _TiB(
unsigned long long val) {
return val * 1 << 40; }
138 template <
typename T,
typename... Args> std::unique_ptr<T> make_unique(Args&&... args) {
139 #if __cplusplus < 201402L
140 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
142 return std::make_unique<T>(std::forward<Args>(args)...);
148 static std::array<const int, 32> MultiplyDeBruijnBitPosition = {
149 {0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}};
150 template <
size_t N> constexpr
size_t find_first(std::bitset<N>& bits) {
151 static_assert(N <= 32,
"find_first only supports bitsets smaller than 33");
152 return MultiplyDeBruijnBitPosition[
static_cast<uint32_t
>((bits.to_ulong() & -bits.to_ulong()) * 0x077CB531U) >> 27];
154 template <
typename T> T leftmost_one(T n) {
155 for(T mask = 1; mask <
sizeof(T) * 8; mask <<= 1)
162 #if defined(__GNUG__)
163 constexpr
inline size_t bit_count(uint32_t u) {
return __builtin_popcount(u); }
164 constexpr
inline size_t bit_count(uint64_t u) {
return __builtin_popcountl(u); }
165 #elif __cplusplus < 201402L
166 constexpr
inline size_t uCount(uint32_t u) {
return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
167 constexpr
inline size_t bit_count(uint32_t u) {
return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
169 constexpr
inline size_t bit_count(uint32_t u) {
170 size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
171 return ((uCount + (uCount >> 3)) & 030707070707) % 63;
175 template <
typename T> CONSTEXPR
typename std::enable_if<std::is_integral<T>::value, T>::type rotl(T n,
unsigned int c) {
176 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
177 assert((c <= mask) &&
"left rotate by type width or more");
179 return (n << c) | (n >> ((-c) & mask));
182 template <
typename T> CONSTEXPR
typename std::enable_if<std::is_integral<T>::value, T>::type rotr(T n,
unsigned int c) {
183 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
184 assert((c <= mask) &&
"left rotate by type width or more");
186 return (n >> c) | (n << ((-c) & mask));
194 CONSTEXPR
inline unsigned ilog2(uint32_t val) {
196 return sizeof(uint32_t) * 8 - 1 - __builtin_clz(
static_cast<unsigned>(val));
199 return std::numeric_limits<uint32_t>::max();
211 #if defined(__GNUG__)
212 constexpr
inline bool hasOddParity(uint32_t u) {
return bit_count(u) % 2; }
214 CONSTEXPR
inline bool hasOddParity(uint32_t u) {
return bit_count(u) % 2; }
223 inline std::vector<std::string>
split(
const std::string& s,
char separator) {
224 std::vector<std::string> output;
225 std::string::size_type prev_pos = 0;
226 std::string::size_type pos = 0;
227 while((pos = s.find(separator, pos)) != std::string::npos) {
228 std::string substring(s.substr(prev_pos, pos - prev_pos));
229 output.push_back(substring);
232 output.push_back(s.substr(prev_pos, pos - prev_pos));
247 template <
typename Range,
typename Value =
typename Range::value_type>
248 std::string
join(Range
const& elements,
char const*
const delimiter) {
249 std::ostringstream os;
250 auto b = std::begin(elements);
251 auto e = std::end(elements);
253 std::copy(b, std::prev(e), std::ostream_iterator<Value>(os, delimiter));
263 template <
typename Input,
typename Output,
typename Value =
typename Output::value_type>
264 void split(
char delimiter, Output& output, Input
const& input) {
265 for(
auto cur = std::begin(input), beg = cur;; ++cur) {
266 if(cur == std::end(input) || *cur == delimiter || !*cur) {
267 output.insert(std::end(output), Value(beg, cur));
268 if(cur == std::end(input) || !*cur)
270 beg = std::next(cur);
280 inline std::string&
ltrim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
281 str.erase(0, str.find_first_not_of(chars));
290 inline std::string&
rtrim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
291 str.erase(str.find_last_not_of(chars) + 1);
300 inline std::string&
trim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
return ltrim(
rtrim(str, chars), chars); }
307 std::transform(str.begin(), str.end(), str.begin(), [](
unsigned char c) { return std::tolower(c); });
316 std::transform(str.begin(), str.end(), str.begin(), [](
unsigned char c) { return std::toupper(c); });
327 inline bool iequals(
const std::string& a,
const std::string& b) {
328 #if __cplusplus < 201402L
332 for(
auto i = 0U; i < sz; ++i)
333 if(tolower(
static_cast<unsigned>(a[i])) != tolower(
static_cast<unsigned>(b[i])))
337 return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](
unsigned char a,
unsigned char b) { return tolower(a) == tolower(b); });
341 inline bool ends_with(std::string
const& value, std::string
const& ending) {
344 return value.length() >= ending.length() ? !value.compare(value.length() - ending.length(), ending.length(), ending) :
false;
355 inline std::string
padded(std::string str,
size_t width,
bool show_ellipsis =
true) {
358 if(str.length() > width) {
360 auto pos = str.size() - (width - 6);
361 return str.substr(0, 3) +
"..." + str.substr(pos, str.size() - pos);
363 return str.substr(0, width);
365 return str + std::string(width - str.size(),
' ');
374 struct stat buffer {};
375 return (stat(name.c_str(), &buffer) == 0);
383 template <
class T>
inline T
dir_name(T
const& path, T
const& delims =
"/\\") {
384 auto pos = path.find_last_of(delims);
385 return pos > path.length() ?
"." : path.substr(0, pos);
393 template <
class T>
inline T
base_name(T
const& path, T
const& delims =
"/\\") {
394 auto pos = path.find_last_of(delims);
395 return pos > path.length() ? path : path.substr(pos + 1);
403 typename T::size_type
const p(filename.find_last_of(
'.'));
404 return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
419 const char* question_mark =
"[^/]";
420 const char* star =
"[^/]*";
422 const char* question_mark =
"[^.]";
423 const char* star =
"[^.]*";
425 const char* double_star =
".*";
427 auto is_regex_meta = [](
char c) ->
bool {
444 std::ostringstream oss;
446 bool in_character_class =
false, in_quote =
false;
447 for(
auto idx = 0U; idx < val.length(); ++idx) {
449 if(in_character_class) {
450 in_character_class = ((c !=
']') || (val[idx - 1] ==
'\\'));
463 }
else if(c ==
'[') {
465 in_character_class =
true;
466 if(val[idx + 1] ==
'!') {
470 }
else if(is_regex_meta(c)) {
472 }
else if(c ==
'?') {
473 oss << subst_table.question_mark;
474 }
else if(c ==
'*') {
475 if((idx + 1) < val.length() && val[idx + 1] ==
'*') {
477 oss << subst_table.double_star;
479 oss << subst_table.star;
CONSTEXPR T signextend(const typename std::make_unsigned< T >::type x)
sign-extend a given value
constexpr std::make_signed< T >::type signed_bit_sub(T v)
a function that converts from B bits to T in one operation
CONSTEXPR std::enable_if< std::is_unsigned< T >::value, T >::type bit_sub(T v)
extract bit ranges from plain data types
R bit_comb(T first, Args... args)
std::string glob_to_regex(std::string val)
std::string str_tolower(std::string str)
std::string padded(std::string str, size_t width, bool show_ellipsis=true)
pad a string to a given length by either cutting of the overflow or inserting an ellipsis
T remove_ext(T const &filename)
CONSTEXPR unsigned ilog2(uint32_t val)
std::vector< std::string > split(const std::string &s, char separator)
bool iequals(const std::string &a, const std::string &b)
compare two string ignoring case
bool file_exists(const std::string &name)
std::string join(Range const &elements, char const *const delimiter)
T dir_name(T const &path, T const &delims="/\\")
std::string & trim(std::string &str, const std::string &chars="\t\n\v\f\r ")
std::string & ltrim(std::string &str, const std::string &chars="\t\n\v\f\r ")
std::string & rtrim(std::string &str, const std::string &chars="\t\n\v\f\r ")
T base_name(T const &path, T const &delims="/\\")
std::string str_toupper(std::string str)