10#include <initializer_list>
15#include <mutable/mutable-config.hpp>
30inline bool strneq(
const char *first,
const char *second, std::size_t n)
35inline std::string
replace_all(std::string str,
const std::string &from,
const std::string &to)
37 std::string::size_type pos = 0;
38 while ((pos = str.find(from, pos)) != std::string::npos) {
39 str.replace(pos, from.length(), to);
46inline uint64_t
FNV1a(
const char *c_str)
49 uint64_t hash = 0xcbf29ce484222325UL;
51 while ((c = *c_str++)) {
53 hash = hash * 0x100000001b3UL;
58inline uint64_t
FNV1a(
const char *c_str, std::size_t len)
61 uint64_t hash = 0xcbf29ce484222325;
62 for (
auto end = c_str + len; c_str != end
and *c_str; ++c_str) {
64 hash = hash * 0x100000001b3UL;
77 uint64_t
operator()(
const char *c_str, std::size_t len)
const {
return FNV1a(c_str, len); }
79 uint64_t
operator()(
const std::string_view &sv)
const {
return FNV1a(sv.data(), sv.size()); }
82 requires requires (
T &&t) { std::string_view(std::forward<T>(t)); }
84 const auto sv = std::string_view(std::forward<T>(t));
85 return FNV1a(sv.data(), sv.length());
96 bool operator()(
const char *first,
const char *second)
const {
return streq(first, second); }
97 bool operator()(
const std::string_view &first,
const std::string_view &second)
const {
return first == second; }
99 template<
typename T,
typename U>
100 requires requires (
T &&t) { std::string_view(std::forward<T>(t)); }
and
101 requires (
U &&u) { std::string_view(std::forward<U>(u)); }
103 return std::string_view(std::forward<T>(first)) == std::string_view(std::forward<U>(second));
110 bool operator()(
const char *first,
const char *second)
const {
111 return first == second or (first !=
nullptr and second !=
nullptr and streq(first, second));
116template<
typename T1,
typename T2,
typename H1 = std::hash<T1>,
typename H2 = std::hash<T2>>
122 return std::rotl(h1(p.first), 32) ^ h2(p.second);
127requires unsigned_integral<T>
131 return n ? (n & (n -
T(1))) ==
T(0) :
false;
135typename std::enable_if_t<std::is_integral_v<T>
and std::is_unsigned_v<T>
and sizeof(T) <=
sizeof(
unsigned long long), T>
139 if (n <= 1)
return 1;
143 if constexpr (
sizeof(T) <=
sizeof(
unsigned)) {
144 lz = __builtin_clz(n - 1U);
145 }
else if constexpr (
sizeof(
T) <=
sizeof(
unsigned long)) {
146 lz = __builtin_clzl(n - 1UL);
147 }
else if constexpr (
sizeof(
T) <=
sizeof(
unsigned long long)) {
148 lz = __builtin_clzll(n - 1ULL);
150 static_assert(
sizeof(
T) >
sizeof(
unsigned long long),
"unsupported width of integral type");
152 M_insist(lz > 0,
"ceiled value would exceed data type");
154 T ceiled =
T(1) << (8 *
sizeof(
T) - lz);
155 M_insist(n <= ceiled,
"the ceiled value must be greater or equal to the original value");
156 M_insist((n << 1) == 0 or ceiled < (n << 1),
"the ceiled value must be smaller than twice the original value");
161typename std::enable_if<std::is_floating_point<T>::value,
T>::type
165 return ceil_to_pow_2((
unsigned long) std::ceil(f));
170typename std::enable_if_t<std::is_integral_v<T>
and std::is_unsigned_v<T>,
T>
172ceil_to_multiple_of_pow_2(T n, T power_of_two)
175 T ceiled = (
n + (power_of_two -
T(1))) & ~(power_of_two -
T(1));
181typename std::enable_if_t<std::is_integral_v<T>
and std::is_unsigned_v<T>,
T>
183round_up_to_multiple(T val, T factor)
185 if (val == 0)
return val;
189 T differ = (d * factor) != val;
190 return (d + differ) * factor;
194typename std::enable_if_t<std::is_integral_v<T>
and std::is_unsigned_v<T>
and sizeof(
T) <=
sizeof(
unsigned long long),
T>
198 if constexpr (
sizeof(
T) <=
sizeof(
unsigned)) {
199 return sizeof(
T) * 8 - __builtin_clz(n) - 1;
200 }
else if constexpr (
sizeof(
T) <=
sizeof(
unsigned long)) {
201 return sizeof(
T) * 8 - __builtin_clzl(n) - 1;
202 }
else if constexpr (
sizeof(
T) <=
sizeof(
unsigned long long)) {
203 return sizeof(
T) * 8 - __builtin_clzll(n) - 1;
205 static_assert(
sizeof(
T) >
sizeof(
unsigned long long),
"unsupported width of integral type");
210typename std::enable_if_t<std::is_integral_v<T>
and std::is_unsigned_v<T>
and sizeof(
T) <=
sizeof(
unsigned long long),
T>
214 return n <= 1 ? 0 : log2_floor(n -
T(1)) +
T(1);
218template<
typename To,
typename From>
219requires (not is_unique_ptr<From>)
and (not is_reference_wrapper<From>)
and (not is_unsharable_shared_ptr<From>)
220To * M_EXPORT cast(From *v) {
return dynamic_cast<To*
>(v); }
222template<
typename To,
typename From>
223To * M_EXPORT cast(std::reference_wrapper<From> v) {
return dynamic_cast<To*
>(&v.get()); }
225template<
typename To,
typename From>
226std::unique_ptr<To> M_EXPORT cast(std::unique_ptr<From> &v) {
227 if (
auto ptr =
dynamic_cast<To*
>(v.get())) {
229 return std::unique_ptr<To>(ptr);
231 return std::unique_ptr<To>(
nullptr);
235template<
typename To,
typename From>
236unsharable_shared_ptr<To> M_EXPORT cast(unsharable_shared_ptr<From> v) {
237 return std::dynamic_pointer_cast<To>(std::move(v));
241template<
typename To,
typename From>
242requires (not is_unique_ptr<From>)
and (not is_reference_wrapper<From>)
and (not is_unsharable_shared_ptr<From>)
243bool M_EXPORT is(From *v) {
return cast<To>(v) !=
nullptr; }
245template<
typename To,
typename From>
246requires (not is_unique_ptr<From>)
and (not is_reference_wrapper<From>)
and (not is_unsharable_shared_ptr<From>)
247bool M_EXPORT is(From &v) {
return is<To>(&v); }
249template<
typename To,
typename From>
250bool M_EXPORT is(std::reference_wrapper<From> v) {
return is<To>(v.get()); }
252template<
typename To,
typename From>
253bool M_EXPORT is(
const std::unique_ptr<From> &v) {
return is<To>(v.get()); }
255template<
typename To,
typename From>
256bool M_EXPORT is(
const unsharable_shared_ptr<From> &v) {
return cast<To>(v).get() !=
nullptr; }
260template<
typename To,
typename From>
261requires (not is_unique_ptr<From>)
and (not is_reference_wrapper<From>)
and (not is_unsharable_shared_ptr<From>)
262To * M_EXPORT as(From *v) {
M_insist(is<To>(v));
return static_cast<To*
>(v); }
264template<
typename To,
typename From>
265requires (not is_unique_ptr<From>)
and (not is_reference_wrapper<From>)
and (not is_unsharable_shared_ptr<From>)
266To & M_EXPORT as(From &v) {
return *as<To>(&v); }
268template<
typename To,
typename From>
269To & M_EXPORT as(std::reference_wrapper<From> v) {
return as<To>(v.get()); }
271template<
typename To,
typename From>
272std::unique_ptr<To> M_EXPORT as(std::unique_ptr<From> v) {
return std::unique_ptr<To>(as<To>(v.release())); }
274template<
typename To,
typename From>
275unsharable_shared_ptr<To> M_EXPORT as(unsharable_shared_ptr<From> v) {
277 return std::static_pointer_cast<To>(std::move(v));
280template<
typename T,
typename... Us>
286template<
typename T,
typename... Us>
295 default:
return std::string(1, c);
296 case '\\':
return "\\\\";
297 case '\"':
return "\\\"";
298 case '\n':
return "\\n";
302std::string M_EXPORT
escape(
const std::string &str,
char esc =
'\\',
char quote =
'"');
304std::string M_EXPORT
unescape(
const std::string &str,
char esc =
'\\',
char quote =
'"');
306inline std::string
quote(
const std::string &str) {
return std::string(
"\"") + str +
'"'; }
310 using std::next, std::prev;
311 if (str.length() < 2)
313 if (str[0] !=
quote)
return str;
314 if (*str.rbegin() !=
quote)
316 return std::string(next(str.begin()), prev(str.end()));
319inline std::string
interpret(
const std::string &str,
char esc =
'\\',
char quote =
'"')
328inline std::regex
pattern_to_regex(
const char *pattern,
const bool optimize =
false,
const char escape_char =
'\\')
330 if (
'_' == escape_char or
'%' == escape_char)
333 std::stringstream ss;
334 for (
const char *c = pattern; *c; ++c) {
335 if (*c == escape_char) {
337 if (
'_' == *c or
'%' == *c) {
341 }
else if (escape_char == *c) {
375 return optimize ? std::regex(ss.str(), std::regex::optimize) : std::regex(ss.str());
379bool M_EXPORT
like(
const std::string &str,
const std::string &pattern,
const char escape_char =
'\\');
382template<
typename H,
typename N>
383bool M_EXPORT
contains(
const H &haystack,
const N &needle)
385 using std::find, std::begin, std::end;
386 return find(begin(haystack), end(haystack), needle) != end(haystack);
390template<
typename T,
typename U>
391bool M_EXPORT
equal(
const T &first,
const U &second)
393 for (
auto t : first) {
397 for (
auto t : second) {
405template<
typename Container,
typename Set>
409 if (set.count(t) == 0)
416template<
typename Container,
typename Set>
417bool M_EXPORT
intersect(
const Container &first,
const Set &second)
419 for (
auto t : first) {
427template<
integral T,
unsigned_
integral U>
428T M_EXPORT
powi(
const T base,
const U exp)
434 return base *
powi(base, exp -
U(1));
436 T tmp =
powi(base, exp /
U(2));
442void M_EXPORT
setbit(T *bytes,
bool value, uint32_t n)
444 *bytes ^= (-
T(value) ^ *bytes) & (
T(1) << n);
447template<
typename T,
typename... Args>
448std::ostream & M_EXPORT
operator<<(std::ostream &out,
const std::variant<T, Args...> value)
450 std::visit([&](
auto &&arg) { out << arg; }, value);
455template<
class...
Ts>
struct M_EXPORT
overloaded :
Ts... {
using Ts::operator()...; };
469 v *= 0x7fb5d329728ea185ULL;
471 v *= 0x81dadef4bc2dd44dULL;
486 const auto oldfill = out.fill(
'0');
487 const auto oldflags = out.flags();
488 out << std::internal;
489 if (pt.
tm_.tm_year < -1900)
490 out <<
'-' << setw(4) << -(pt.
tm_.tm_year + 1900);
492 out << setw(4) << pt.
tm_.tm_year + 1900;
494 << setw(2) << pt.
tm_.tm_mon + 1 <<
'-'
495 << setw(2) << pt.
tm_.tm_mday <<
' '
496 << setw(2) << pt.
tm_.tm_hour <<
':'
497 << setw(2) << pt.
tm_.tm_min <<
':'
498 << setw(2) << pt.
tm_.tm_sec;
514 in >> gt.
tm_.tm_year;
515 if (in
and in.peek() ==
'-') in.get();
else return in;
517 if (in
and in.peek() ==
'-') in.get();
else return in;
518 in >> gt.
tm_.tm_mday;
519 if (in
and in.peek() ==
' ') in.get();
else return in;
520 in >> gt.
tm_.tm_hour;
521 if (in
and in.peek() ==
':') in.get();
else return in;
523 if (in
and in.peek() ==
':') in.get();
else return in;
526 gt.
tm_.tm_year -= 1900;
532template<
typename Clock,
typename Duration>
536 std::chrono::time_point<Clock, Duration>
tp_;
540 put_timepoint(std::chrono::time_point<Clock, Duration> tp,
bool utc =
false) : tp_(tp), utc_(utc) { }
544 using namespace std::chrono;
548 if constexpr (std::is_same_v<Clock, system_clock>) {
549 time = system_clock::to_time_t(ptp.
tp_);
553 auto tpc_now = Clock::now();
554 auto sys_now = system_clock::now();
555 auto tp_sys = time_point_cast<system_clock::duration>(ptp.
tp_ - tpc_now + sys_now);
556 time = system_clock::to_time_t(tp_sys);
563 chk = gmtime_r(&time, &tm);
565 chk = localtime_r(&time, &tm);
574template <
typename T,
typename... Args>
struct Concat;
576template <
typename... Args0,
typename... Args1>
577struct M_EXPORT
Concat<
std::variant<Args0...>, Args1...> {
578 using type = std::variant<Args0..., Args1...>;
583template<
typename S,
typename T,
typename =
void>
585template<
typename S,
typename T>
586struct is_streamable<S,
T,
std::void_t<decltype( std::declval<S&>() << std::declval<T>() )>> : std::true_type {};
588inline bool is_oct (int c) { return '0' <= c && c <= '7'; }
589inline bool is_dec (int c) { return '0' <= c && c <= '9'; }
590inline bool is_hex (int c) { return is_dec(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); }
591inline bool is_lower(int c) { return ('a' <= c && c <= 'z'); }
592inline bool is_upper(int c) { return ('A' <= c && c <= 'Z'); }
593inline bool is_alpha(int c) { return is_lower(c) || is_upper(c); }
594inline bool is_alnum(int c) { return is_dec(c) || is_alpha(c); }
597inline std::filesystem::path get_home_path()
599 std::filesystem::path path;
601 auto home = getenv("HOME");
605 auto home = getenv("HOME");
609 auto homedrive = getenv("HOMEDRIVE");
610 auto homepath = getenv("HOMEPATH");
611 if (homedrive and homepath) {
622inline bool isspace(const char *s, std::size_t len)
624 return std::all_of(s, s + len, static_cast<int(*)(int)>(std::isspace));
627inline bool isspace(const char *s) { return isspace(s, strlen(s)); }
629void M_EXPORT exec(const char *executable, std::initializer_list<const char*> args);
632template<typename T, typename U>
633auto M_EXPORT add_wo_overflow(T left, U right)
635 static_assert(std::is_integral_v<T>, "LHS must be an integral type");
636 static_assert(std::is_integral_v<U>, "RHS must be an integral type");
638 static_assert(not std::is_signed_v<T>, "LHS must be unsigned");
639 static_assert(not std::is_signed_v<U>, "RHS must be unsigned");
641 using CT = std::common_type_t<T, U>;
643 if (__builtin_add_overflow(CT(left), CT(right), &res))
644 return std::numeric_limits<CT>::max();
648template<typename N0, typename N1>
649auto M_EXPORT sum_wo_overflow(N0 n0, N1 n1)
651 return add_wo_overflow(n0, n1);
656template<typename N0, typename N1, typename... Numbers>
657auto M_EXPORT sum_wo_overflow(N0 n0, N1 n1, Numbers... numbers)
659 return sum_wo_overflow(add_wo_overflow(n0, n1), numbers...);
663template<typename T, typename U>
664auto M_EXPORT mul_wo_overflow(T left, U right)
666 static_assert(std::is_integral_v<T>, "LHS must be an integral type");
667 static_assert(std::is_integral_v<U>, "RHS must be an integral type");
669 static_assert(not std::is_signed_v<T>, "LHS must be unsigned");
670 static_assert(not std::is_signed_v<U>, "RHS must be unsigned");
672 using CT = std::common_type_t<T, U>;
674 if (__builtin_mul_overflow(CT(left), CT(right), &res))
675 return std::numeric_limits<CT>::max();
679template<typename N0, typename N1>
680auto M_EXPORT prod_wo_overflow(N0 n0, N1 n1)
682 return mul_wo_overflow(n0, n1);
687template<typename N0, typename N1, typename... Numbers>
688auto M_EXPORT prod_wo_overflow(N0 n0, N1 n1, Numbers... numbers)
690 return prod_wo_overflow(prod_wo_overflow(n0, n1), numbers...);
694inline const char * strdupn(const char *str) { return str ? strdup(str) : nullptr; }
697std::size_t M_EXPORT get_pagesize();
700inline std::size_t Is_Page_Aligned(std::size_t n) { return (n & (get_pagesize() - 1UL)) == 0; }
703inline std::size_t Ceil_To_Next_Page(std::size_t n) { return ((n - 1UL) | (get_pagesize() - 1UL)) + 1UL; }
708inline uint64_t sequence_number(double x)
711 std::memcpy(&u64, &x, sizeof u64);
712 if (u64 & 0x8000000000000000UL) {
713 u64 ^= 0x8000000000000000UL;
714 return 0x8000000000000000UL - u64;
716 return u64 + 0x8000000000000000UL;
722inline uint32_t sequence_number(float x)
725 std::memcpy(&u32, &x, sizeof u32);
726 if (u32 & 0x80000000U) {
728 return 0x80000000U - u32;
730 return u32 + 0x80000000U;
735constexpr bool M_EXPORT is_range_wide_enough(T a, T b, std::size_t n)
738 if (a > b) swap(a, b);
740 if (n == 0) return true;
744 if constexpr (integral<T>) {
745 if constexpr (signed_integral<T>) {
746 using U = std::make_unsigned_t<T>;
748 if ((a < 0) == (b < 0)) {
749 return U(b - a) >= n - 1;
753 U a_abs = U(~a) + 1U;
754 return a_abs >= n or (U(b) >= n - a_abs - 1);
757 return (b - a) >= n - 1;
759 } else if constexpr (std::floating_point<T>) {
760 return sequence_number(b) - sequence_number(a) >= n - 1;
762 static_assert(std::is_same_v<T, T>, "unsupported type");
769std::enable_if_t<std::is_integral_v<T>, unsigned long long>
771n_choose_k_approx(T n, T k)
773 return std::exp(std::lgamma(n + T(1)) - std::lgamma(k + T(1)) - std::lgamma(n - k + T(1)));
777inline float fast_reciprocal_sqrtf(const float n)
779 const int32_t i = 0x5F375A86 - (*reinterpret_cast<const int32_t*>(&n) >> 1);
780 const float f = *reinterpret_cast<const float*>(&i);
781 return (int32_t(3) - n * f * f) * f * 0.5f;
783inline float fast_reciprocal_sqrt(const float n) { return fast_reciprocal_sqrtf(n); }
787inline double fast_reciprocal_sqrtd(const double n)
789 const int64_t l = 0x5fe6eb50c7b537a9 - (*reinterpret_cast<const int64_t*>(&n) >> 1);
790 const double d = *reinterpret_cast<const double*>(&l);
791 return (int64_t(3) - n * d * d) * d * 0.5f;
793inline double fast_reciprocal_sqrt(const double n) { return fast_reciprocal_sqrtd(n); }
795inline float fast_sqrtf(float n)
797 return n * fast_reciprocal_sqrtf(n);
799inline float fast_sqrt(float n) { return fast_sqrtf(n); }
801inline double fast_sqrtd(double n)
803 return n * fast_reciprocal_sqrtd(n);
805inline double fast_sqrt(double n) { return fast_sqrtd(n); }
809inline uint64_t _pdep_u64(uint64_t source, uint64_t mask) {
814 for (int i = 0; i < 64; i++) {
826inline uint64_t pext_u64(uint64_t source, uint64_t mask) {
831 for (int i = 0; i < 64; i++) {
832 if (source & srcBit) {
845template<class Factory>
848 using result_type = std::invoke_result_t<const Factory&>;
854 lazy_construct(Factory&& factory) : factory_(std::move(factory)) { }
856 operator result_type() const { return factory_(); }
and(sizeof(T)==4) U64x1 reinterpret_to_U64(m
std::conditional_t< std::is_signed_v< T >, int16_t, uint16_t > To
std::string replace_all(std::string str, const std::string &from, const std::string &to)
std::string escape(char c)
M_EXPORT constexpr bool is_pow_2(T n)
uint64_t FNV1a(const char *c_str)
std::string unquote(const std::string &str, char quote='"')
bool M_EXPORT intersect(const Container &first, const Set &second)
Checks whether first and second intersect.
T M_EXPORT powi(const T base, const U exp)
Power function for integral types.
bool M_EXPORT subset(const Container &subset, const Set &set)
Checks whether subset is a subset of set.
bool M_EXPORT equal(const T &first, const U &second)
Checks whether first and second are equal considering permutations.
uint64_t murmur3_64(uint64_t v)
This function implements the 64-bit finalizer of Murmur3_x64 by Austin Appleby, available at https://...
bool streq(const char *first, const char *second)
bool strneq(const char *first, const char *second, std::size_t n)
bool M_EXPORT contains(const H &haystack, const N &needle)
Checks whether haystack contains needle.
std::string quote(const std::string &str)
std::string M_EXPORT unescape(const std::string &str, char esc='\\', char quote='"')
std::string M_EXPORT html_escape(std::string str)
Escapes special characters in a string to be printable in HTML documents.
std::regex pattern_to_regex(const char *pattern, const bool optimize=false, const char escape_char='\\')
Transforms a SQL-style LIKE pattern into a std::regex.
bool M_EXPORT like(const std::string &str, const std::string &pattern, const char escape_char='\\')
Compares a SQL-style LIKE pattern with the given std::string.
M_LCOV_EXCL_START std::ostream & operator<<(std::ostream &out, const PlanTableBase< Actual > &PT)
and arithmetic< U > and same_signedness< T, U > U
std::string interpret(const std::string &str, char esc='\\', char quote='"')
T & get_as(std::variant< Us... > &v)
void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
std::variant< Args0..., Args1... > type
Computes the XOR-hash for a pair.
uint64_t operator()(const std::pair< T1, T2 > &p) const
Compares two cstrings for equality.
bool operator()(const char *first, const char *second) const
Compares two cstrings for equality.
bool operator()(const std::string_view &first, const std::string_view &second) const
void is_transparent
Mark this callable as transparent, allowing for comparing various types that are interoperable.
bool operator()(const char *first, const char *second) const
bool operator()(T &&first, U &&second) const
Computes the FNV-1a 64-bit hash of a cstring.
uint64_t operator()(const char *c_str) const
uint64_t operator()(T &&t)
void is_transparent
Mark this callable as transparent, allowing for computing the hash of various types that are interop...
uint64_t operator()(const char *c_str, std::size_t len) const
uint64_t operator()(const std::string &s) const
uint64_t operator()(const std::string_view &sv) const
friend std::istream & operator>>(std::istream &in, get_tm gt)
Signals that an argument to a function of method was invalid.
std::chrono::time_point< Clock, Duration > tp_
friend std::ostream & operator<<(std::ostream &out, const put_timepoint &ptp)
Print the given std::chrono::time_point in the given format.
put_timepoint(std::chrono::time_point< Clock, Duration > tp, bool utc=false)
friend std::ostream & operator<<(std::ostream &out, const put_tm &pt)
Signals a runtime error that mu*t*able is not responsible for and that mu*t*able was not able to reco...