2019-07-01 22:58:19 -07:00
|
|
|
#pragma once
|
|
|
|
|
2019-12-13 00:37:06 -05:00
|
|
|
#include <pthread.h>
|
2019-07-01 22:58:19 -07:00
|
|
|
#include <string>
|
|
|
|
#include <functional>
|
|
|
|
#include <string_view>
|
2022-01-21 04:43:27 -08:00
|
|
|
#include <bitset>
|
2019-07-01 22:58:19 -07:00
|
|
|
|
2022-09-15 01:17:05 -07:00
|
|
|
#include <base-rs.hpp>
|
|
|
|
|
2021-03-06 13:55:30 -08:00
|
|
|
#define DISALLOW_COPY_AND_MOVE(clazz) \
|
|
|
|
clazz(const clazz &) = delete; \
|
|
|
|
clazz(clazz &&) = delete;
|
|
|
|
|
2019-09-25 23:55:39 -04:00
|
|
|
class mutex_guard {
|
2021-03-06 13:55:30 -08:00
|
|
|
DISALLOW_COPY_AND_MOVE(mutex_guard)
|
2019-07-01 22:58:19 -07:00
|
|
|
public:
|
2020-12-30 22:11:24 -08:00
|
|
|
explicit mutex_guard(pthread_mutex_t &m): mutex(&m) {
|
|
|
|
pthread_mutex_lock(mutex);
|
|
|
|
}
|
2021-01-12 00:07:48 -08:00
|
|
|
void unlock() {
|
|
|
|
pthread_mutex_unlock(mutex);
|
|
|
|
mutex = nullptr;
|
2020-12-30 22:11:24 -08:00
|
|
|
}
|
|
|
|
~mutex_guard() {
|
2021-01-12 00:07:48 -08:00
|
|
|
if (mutex) pthread_mutex_unlock(mutex);
|
2020-12-30 22:11:24 -08:00
|
|
|
}
|
2019-07-01 22:58:19 -07:00
|
|
|
private:
|
2020-12-30 22:11:24 -08:00
|
|
|
pthread_mutex_t *mutex;
|
2019-07-01 22:58:19 -07:00
|
|
|
};
|
|
|
|
|
2020-04-30 01:27:36 -07:00
|
|
|
template <class Func>
|
2019-09-25 23:55:39 -04:00
|
|
|
class run_finally {
|
2021-03-06 13:55:30 -08:00
|
|
|
DISALLOW_COPY_AND_MOVE(run_finally)
|
2019-07-01 22:58:19 -07:00
|
|
|
public:
|
2021-08-19 01:54:12 -07:00
|
|
|
explicit run_finally(Func &&fn) : fn(std::move(fn)) {}
|
2020-12-30 22:11:24 -08:00
|
|
|
~run_finally() { fn(); }
|
2019-07-01 22:58:19 -07:00
|
|
|
private:
|
2021-08-19 01:54:12 -07:00
|
|
|
Func fn;
|
2019-07-01 22:58:19 -07:00
|
|
|
};
|
|
|
|
|
2019-11-19 00:16:20 -05:00
|
|
|
template <typename T>
|
|
|
|
class reversed_container {
|
|
|
|
public:
|
2020-12-30 22:11:24 -08:00
|
|
|
reversed_container(T &base) : base(base) {}
|
|
|
|
decltype(std::declval<T>().rbegin()) begin() { return base.rbegin(); }
|
|
|
|
decltype(std::declval<T>().crbegin()) begin() const { return base.crbegin(); }
|
|
|
|
decltype(std::declval<T>().crbegin()) cbegin() const { return base.crbegin(); }
|
|
|
|
decltype(std::declval<T>().rend()) end() { return base.rend(); }
|
|
|
|
decltype(std::declval<T>().crend()) end() const { return base.crend(); }
|
|
|
|
decltype(std::declval<T>().crend()) cend() const { return base.crend(); }
|
2019-11-19 00:16:20 -05:00
|
|
|
private:
|
2020-12-30 22:11:24 -08:00
|
|
|
T &base;
|
2019-11-19 00:16:20 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
reversed_container<T> reversed(T &base) {
|
2020-12-30 22:11:24 -08:00
|
|
|
return reversed_container<T>(base);
|
2019-11-19 00:16:20 -05:00
|
|
|
}
|
|
|
|
|
2021-08-18 02:01:54 -07:00
|
|
|
template<class T>
|
|
|
|
static inline void default_new(T *&p) { p = new T(); }
|
|
|
|
|
2022-02-08 16:49:22 +08:00
|
|
|
template<class T>
|
|
|
|
static inline void default_new(std::unique_ptr<T> &p) { p.reset(new T()); }
|
|
|
|
|
2021-08-01 14:35:16 -07:00
|
|
|
template<typename T, typename Impl>
|
|
|
|
class stateless_allocator {
|
|
|
|
public:
|
|
|
|
using value_type = T;
|
|
|
|
T *allocate(size_t num) { return static_cast<T*>(Impl::allocate(sizeof(T) * num)); }
|
|
|
|
void deallocate(T *ptr, size_t num) { Impl::deallocate(ptr, sizeof(T) * num); }
|
|
|
|
stateless_allocator() = default;
|
|
|
|
stateless_allocator(const stateless_allocator&) = default;
|
|
|
|
stateless_allocator(stateless_allocator&&) = default;
|
|
|
|
template <typename U>
|
|
|
|
stateless_allocator(const stateless_allocator<U, Impl>&) {}
|
|
|
|
bool operator==(const stateless_allocator&) { return true; }
|
|
|
|
bool operator!=(const stateless_allocator&) { return false; }
|
|
|
|
};
|
|
|
|
|
2022-02-07 00:17:07 -08:00
|
|
|
class dynamic_bitset_impl {
|
2022-01-21 04:43:27 -08:00
|
|
|
public:
|
2022-01-23 04:39:00 -08:00
|
|
|
using slot_type = unsigned long;
|
|
|
|
constexpr static int slot_size = sizeof(slot_type) * 8;
|
|
|
|
using slot_bits = std::bitset<slot_size>;
|
|
|
|
|
2022-02-07 00:17:07 -08:00
|
|
|
size_t slots() const { return slot_list.size(); }
|
|
|
|
slot_type get_slot(size_t slot) const {
|
|
|
|
return slot_list.size() > slot ? slot_list[slot].to_ulong() : 0ul;
|
|
|
|
}
|
2022-02-11 01:00:58 -08:00
|
|
|
void emplace_back(slot_type l) {
|
|
|
|
slot_list.emplace_back(l);
|
|
|
|
}
|
2022-02-07 00:17:07 -08:00
|
|
|
protected:
|
|
|
|
slot_bits::reference get(size_t pos) {
|
2022-01-21 04:43:27 -08:00
|
|
|
size_t slot = pos / slot_size;
|
|
|
|
size_t index = pos % slot_size;
|
2022-01-23 04:39:00 -08:00
|
|
|
if (slot_list.size() <= slot) {
|
|
|
|
slot_list.resize(slot + 1);
|
2022-01-21 04:43:27 -08:00
|
|
|
}
|
2022-01-23 04:39:00 -08:00
|
|
|
return slot_list[slot][index];
|
2022-01-21 04:43:27 -08:00
|
|
|
}
|
2022-02-07 00:17:07 -08:00
|
|
|
bool get(size_t pos) const {
|
2022-01-24 22:30:13 -08:00
|
|
|
size_t slot = pos / slot_size;
|
|
|
|
size_t index = pos % slot_size;
|
|
|
|
return slot_list.size() > slot && slot_list[slot][index];
|
|
|
|
}
|
2022-01-23 04:39:00 -08:00
|
|
|
private:
|
|
|
|
std::vector<slot_bits> slot_list;
|
2022-01-21 04:43:27 -08:00
|
|
|
};
|
|
|
|
|
2022-02-07 00:17:07 -08:00
|
|
|
struct dynamic_bitset : public dynamic_bitset_impl {
|
|
|
|
slot_bits::reference operator[] (size_t pos) { return get(pos); }
|
|
|
|
bool operator[] (size_t pos) const { return get(pos); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct StringCmp {
|
|
|
|
using is_transparent = void;
|
|
|
|
bool operator()(std::string_view a, std::string_view b) const { return a < b; }
|
|
|
|
};
|
|
|
|
|
2022-09-15 01:17:05 -07:00
|
|
|
template<typename T>
|
|
|
|
rust::Slice<uint8_t> byte_slice(T *buf, size_t sz) {
|
|
|
|
return rust::Slice(reinterpret_cast<uint8_t *>(buf), sz);
|
|
|
|
}
|
|
|
|
|
2021-10-23 14:38:30 -07:00
|
|
|
int parse_int(std::string_view s);
|
2019-07-01 22:58:19 -07:00
|
|
|
|
2020-04-30 01:27:36 -07:00
|
|
|
using thread_entry = void *(*)(void *);
|
2021-01-06 22:21:17 -08:00
|
|
|
int new_daemon_thread(thread_entry entry, void *arg = nullptr);
|
2019-07-01 22:58:19 -07:00
|
|
|
|
2020-12-30 15:55:53 -08:00
|
|
|
static inline bool str_contains(std::string_view s, std::string_view ss) {
|
2020-12-30 22:11:24 -08:00
|
|
|
return s.find(ss) != std::string::npos;
|
2020-12-30 15:55:53 -08:00
|
|
|
}
|
|
|
|
static inline bool str_starts(std::string_view s, std::string_view ss) {
|
2021-03-18 13:36:42 +08:00
|
|
|
return s.size() >= ss.size() && s.compare(0, ss.size(), ss) == 0;
|
2020-12-30 15:55:53 -08:00
|
|
|
}
|
|
|
|
static inline bool str_ends(std::string_view s, std::string_view ss) {
|
2020-12-30 22:11:24 -08:00
|
|
|
return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0;
|
2020-12-30 15:55:53 -08:00
|
|
|
}
|
2021-05-26 01:21:54 +08:00
|
|
|
static inline std::string ltrim(std::string &&s) {
|
|
|
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
|
|
|
return !std::isspace(ch);
|
|
|
|
}));
|
|
|
|
return std::move(s);
|
|
|
|
}
|
|
|
|
static inline std::string rtrim(std::string &&s) {
|
|
|
|
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
|
|
|
return !std::isspace(ch) && ch != '\0';
|
|
|
|
}).base(), s.end());
|
|
|
|
return std::move(s);
|
|
|
|
}
|
2020-12-30 15:55:53 -08:00
|
|
|
|
2020-11-07 14:36:13 -08:00
|
|
|
int fork_dont_care();
|
2020-12-17 16:54:53 -08:00
|
|
|
int fork_no_orphan();
|
2020-11-07 14:36:13 -08:00
|
|
|
void init_argv0(int argc, char **argv);
|
|
|
|
void set_nice_name(const char *name);
|
|
|
|
uint32_t binary_gcd(uint32_t u, uint32_t v);
|
|
|
|
int switch_mnt_ns(int pid);
|
|
|
|
int gen_rand_str(char *buf, int len, bool varlen = true);
|
|
|
|
std::string &replace_all(std::string &str, std::string_view from, std::string_view to);
|
2022-03-01 20:09:59 -08:00
|
|
|
std::vector<std::string> split(const std::string &s, const std::string &delims);
|
|
|
|
std::vector<std::string_view> split_ro(std::string_view, std::string_view delims);
|
2020-11-07 14:36:13 -08:00
|
|
|
|
2022-09-09 04:29:50 -07:00
|
|
|
// Similar to vsnprintf, but the return value is the written number of bytes
|
|
|
|
int vssprintf(char *dest, size_t size, const char *fmt, va_list ap);
|
|
|
|
// Similar to snprintf, but the return value is the written number of bytes
|
|
|
|
int ssprintf(char *dest, size_t size, const char *fmt, ...);
|
2022-09-15 01:17:05 -07:00
|
|
|
// This is not actually the strscpy from the Linux kernel.
|
|
|
|
// Silently truncates, and returns the number of bytes written.
|
|
|
|
extern "C" size_t strscpy(char *dest, const char *src, size_t size);
|
2022-09-09 04:29:50 -07:00
|
|
|
|
|
|
|
// Ban usage of unsafe cstring functions
|
|
|
|
#define vsnprintf __use_vssprintf_instead__
|
|
|
|
#define snprintf __use_ssprintf_instead__
|
2022-09-15 01:17:05 -07:00
|
|
|
#define strlcpy __use_strscpy_instead__
|
2022-09-09 04:29:50 -07:00
|
|
|
|
2019-07-01 22:58:19 -07:00
|
|
|
struct exec_t {
|
2020-12-30 22:11:24 -08:00
|
|
|
bool err = false;
|
|
|
|
int fd = -2;
|
|
|
|
void (*pre_exec)() = nullptr;
|
|
|
|
int (*fork)() = xfork;
|
|
|
|
const char **argv = nullptr;
|
2019-07-01 22:58:19 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
int exec_command(exec_t &exec);
|
|
|
|
template <class ...Args>
|
|
|
|
int exec_command(exec_t &exec, Args &&...args) {
|
2020-12-30 22:11:24 -08:00
|
|
|
const char *argv[] = {args..., nullptr};
|
|
|
|
exec.argv = argv;
|
|
|
|
return exec_command(exec);
|
2019-07-01 22:58:19 -07:00
|
|
|
}
|
|
|
|
int exec_command_sync(exec_t &exec);
|
|
|
|
template <class ...Args>
|
|
|
|
int exec_command_sync(exec_t &exec, Args &&...args) {
|
2020-12-30 22:11:24 -08:00
|
|
|
const char *argv[] = {args..., nullptr};
|
|
|
|
exec.argv = argv;
|
|
|
|
return exec_command_sync(exec);
|
2019-07-01 22:58:19 -07:00
|
|
|
}
|
|
|
|
template <class ...Args>
|
|
|
|
int exec_command_sync(Args &&...args) {
|
2021-08-26 03:09:56 -07:00
|
|
|
exec_t exec;
|
2020-12-30 22:11:24 -08:00
|
|
|
return exec_command_sync(exec, args...);
|
2019-07-01 22:58:19 -07:00
|
|
|
}
|
2020-11-07 14:36:13 -08:00
|
|
|
template <class ...Args>
|
|
|
|
void exec_command_async(Args &&...args) {
|
2020-12-30 22:11:24 -08:00
|
|
|
const char *argv[] = {args..., nullptr};
|
|
|
|
exec_t exec {
|
2022-01-30 07:11:51 -08:00
|
|
|
.fork = fork_dont_care,
|
2020-12-30 22:11:24 -08:00
|
|
|
.argv = argv,
|
|
|
|
};
|
|
|
|
exec_command(exec);
|
2020-11-07 14:36:13 -08:00
|
|
|
}
|