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);
76 template <
typename T,
unsigned B> CONSTEXPR T
signextend(
const typename std::make_unsigned<T>::type x) {
95 template <
unsigned int bit,
unsigned int w
idth,
typename T>
inline constexpr
typename std::make_signed<T>::type
signed_bit_sub(T v) {
96 #if __cplusplus < 201402L
97 return ((v << (
sizeof(T) * 8 - bit - width)) >> (
sizeof(T) * 8 - width));
99 typename std::make_signed<T>::type r = v << (
sizeof(T) * 8 - bit - width);
100 typename std::make_signed<T>::type ret = (r >> (
sizeof(T) * 8 - width));
107 template <
typename T,
typename... Args> std::unique_ptr<T> make_unique(Args&&... args) {
108 #if __cplusplus < 201402L
109 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
111 return std::make_unique<T>(std::forward<Args>(args)...);
117 static std::array<const int, 32> MultiplyDeBruijnBitPosition = {
118 {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}};
119 template <
size_t N> constexpr
size_t find_first(std::bitset<N>& bits) {
120 static_assert(N <= 32,
"find_first only supports bitsets smaller than 33");
121 return MultiplyDeBruijnBitPosition[
static_cast<uint32_t
>((bits.to_ulong() & -bits.to_ulong()) * 0x077CB531U) >> 27];
123 template <
typename T> T leftmost_one(T n) {
124 for(T mask = 1; mask <
sizeof(T) * 8; mask <<= 1)
131 #if defined(__GNUG__)
132 constexpr
inline size_t bit_count(uint32_t u) {
return __builtin_popcount(u); }
133 constexpr
inline size_t bit_count(uint64_t u) {
return __builtin_popcountl(u); }
134 #elif __cplusplus < 201402L
135 constexpr
inline size_t uCount(uint32_t u) {
return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
136 constexpr
inline size_t bit_count(uint32_t u) {
return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
138 constexpr
inline size_t bit_count(uint32_t u) {
139 size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
140 return ((uCount + (uCount >> 3)) & 030707070707) % 63;
144 template <
typename T> CONSTEXPR
typename std::enable_if<std::is_integral<T>::value, T>::type rotl(T n,
unsigned int c) {
145 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
146 assert((c <= mask) &&
"left rotate by type width or more");
148 return (n << c) | (n >> ((-c) & mask));
151 template <
typename T> CONSTEXPR
typename std::enable_if<std::is_integral<T>::value, T>::type rotr(T n,
unsigned int c) {
152 const unsigned int mask = (CHAR_BIT *
sizeof(n) - 1);
153 assert((c <= mask) &&
"left rotate by type width or more");
155 return (n >> c) | (n << ((-c) & mask));
163 CONSTEXPR
inline unsigned ilog2(uint32_t val) {
165 return sizeof(uint32_t) * 8 - 1 - __builtin_clz(
static_cast<unsigned>(val));
168 return std::numeric_limits<uint32_t>::max();
180 #if defined(__GNUG__)
181 constexpr
inline bool hasOddParity(uint32_t u) {
return bit_count(u) % 2; }
183 CONSTEXPR
inline bool hasOddParity(uint32_t u) {
return bit_count(u) % 2; }
192 inline std::vector<std::string>
split(
const std::string& s,
char separator) {
193 std::vector<std::string> output;
194 std::string::size_type prev_pos = 0;
195 std::string::size_type pos = 0;
196 while((pos = s.find(separator, pos)) != std::string::npos) {
197 std::string substring(s.substr(prev_pos, pos - prev_pos));
198 output.push_back(substring);
201 output.push_back(s.substr(prev_pos, pos - prev_pos));
216 template <
typename Range,
typename Value =
typename Range::value_type>
217 std::string
join(Range
const& elements,
char const*
const delimiter) {
218 std::ostringstream os;
219 auto b = std::begin(elements);
220 auto e = std::end(elements);
222 std::copy(b, std::prev(e), std::ostream_iterator<Value>(os, delimiter));
232 template <
typename Input,
typename Output,
typename Value =
typename Output::value_type>
233 void split(
char delimiter, Output& output, Input
const& input) {
234 for(
auto cur = std::begin(input), beg = cur;; ++cur) {
235 if(cur == std::end(input) || *cur == delimiter || !*cur) {
236 output.insert(std::end(output), Value(beg, cur));
237 if(cur == std::end(input) || !*cur)
239 beg = std::next(cur);
249 inline std::string&
ltrim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
250 str.erase(0, str.find_first_not_of(chars));
259 inline std::string&
rtrim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
260 str.erase(str.find_last_not_of(chars) + 1);
269 inline std::string&
trim(std::string& str,
const std::string& chars =
"\t\n\v\f\r ") {
return ltrim(
rtrim(str, chars), chars); }
276 std::transform(str.begin(), str.end(), str.begin(), [](
unsigned char c) { return std::tolower(c); });
285 std::transform(str.begin(), str.end(), str.begin(), [](
unsigned char c) { return std::toupper(c); });
296 inline bool iequals(
const std::string& a,
const std::string& b) {
297 #if __cplusplus < 201402L
301 for(
auto i = 0U; i < sz; ++i)
302 if(tolower(
static_cast<unsigned>(a[i])) != tolower(
static_cast<unsigned>(b[i])))
306 return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](
unsigned char a,
unsigned char b) { return tolower(a) == tolower(b); });
310 inline bool ends_with(std::string
const& value, std::string
const& ending) {
313 return value.length() >= ending.length() ? !value.compare(value.length() - ending.length(), ending.length(), ending) :
false;
324 inline std::string
padded(std::string str,
size_t width,
bool show_ellipsis =
true) {
327 if(str.length() > width) {
329 auto pos = str.size() - (width - 6);
330 return str.substr(0, 3) +
"..." + str.substr(pos, str.size() - pos);
332 return str.substr(0, width);
334 return str + std::string(width - str.size(),
' ');
343 struct stat buffer {};
344 return (stat(name.c_str(), &buffer) == 0);
352 template <
class T>
inline T
dir_name(T
const& path, T
const& delims =
"/\\") {
353 auto pos = path.find_last_of(delims);
354 return pos > path.length() ?
"." : path.substr(0, pos);
362 template <
class T>
inline T
base_name(T
const& path, T
const& delims =
"/\\") {
363 auto pos = path.find_last_of(delims);
364 return pos > path.length() ? path : path.substr(pos + 1);
372 typename T::size_type
const p(filename.find_last_of(
'.'));
373 return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
388 const char* question_mark =
"[^/]";
389 const char* star =
"[^/]*";
391 const char* question_mark =
"[^.]";
392 const char* star =
"[^.]*";
394 const char* double_star =
".*";
396 auto is_regex_meta = [](
char c) ->
bool {
413 std::ostringstream oss;
415 bool in_character_class =
false, in_quote =
false;
416 for(
auto idx = 0U; idx < val.length(); ++idx) {
418 if(in_character_class) {
419 in_character_class = ((c !=
']') || (val[idx - 1] ==
'\\'));
432 }
else if(c ==
'[') {
434 in_character_class =
true;
435 if(val[idx + 1] ==
'!') {
439 }
else if(is_regex_meta(c)) {
441 }
else if(c ==
'?') {
442 oss << subst_table.question_mark;
443 }
else if(c ==
'*') {
444 if((idx + 1) < val.length() && val[idx + 1] ==
'*') {
446 oss << subst_table.double_star;
448 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
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)