2023-01-13 15:13:56 +00:00
|
|
|
#pragma once
|
|
|
|
#include <iostream>
|
2023-01-14 13:47:30 +00:00
|
|
|
#include <unistd.h>
|
2023-02-04 14:33:06 +00:00
|
|
|
#include <string>
|
2023-01-14 13:47:30 +00:00
|
|
|
|
2023-01-13 15:13:56 +00:00
|
|
|
#define UNUSED [[maybe_unused]]
|
|
|
|
#define LOG(x) std::cout << x << '\n'
|
2023-01-14 13:47:30 +00:00
|
|
|
#define ASSERT(x, log) \
|
|
|
|
if (!(x)) \
|
|
|
|
{ \
|
|
|
|
LOG(log << "\n[Exiting due to assert failed]"); \
|
|
|
|
exit(-1); \
|
|
|
|
}
|
2023-01-13 15:13:56 +00:00
|
|
|
|
|
|
|
// Flag helper macros
|
|
|
|
#define BIT(x) (1 << (x))
|
|
|
|
|
|
|
|
template<typename Enum, typename std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
|
|
|
|
using EnumType = std::underlying_type_t<Enum>;
|
|
|
|
|
|
|
|
// Based on https://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c
|
|
|
|
// (Answer https://stackoverflow.com/a/23152590): Licensed under CC BY-SA 3.0
|
|
|
|
#define DEFINE_ENUM_FLAGS(T) \
|
|
|
|
inline T operator~(T a) \
|
|
|
|
{ \
|
|
|
|
return (T) ~(EnumType<T>)a; \
|
|
|
|
} \
|
|
|
|
inline T operator|(T a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T)((EnumType<T>)a | (EnumType<T>)b); \
|
|
|
|
} \
|
|
|
|
inline T operator&(T a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T)((EnumType<T>)a & (EnumType<T>)b); \
|
|
|
|
} \
|
|
|
|
inline T operator^(T a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T)((EnumType<T>)a ^ (EnumType<T>)b); \
|
|
|
|
} \
|
|
|
|
inline T& operator|=(T& a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T&)((EnumType<T>&)a |= (EnumType<T>)b); \
|
|
|
|
} \
|
|
|
|
inline T& operator&=(T& a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T&)((EnumType<T>&)a &= (EnumType<T>)b); \
|
|
|
|
} \
|
|
|
|
inline T& operator^=(T& a, T b) \
|
|
|
|
{ \
|
|
|
|
return (T&)((EnumType<T>&)a ^= (EnumType<T>)b); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FLAG_CHECK(val, check) ((int)(val & (check)) == (int)check)
|
|
|
|
|
|
|
|
namespace Utils
|
|
|
|
{
|
|
|
|
inline std::string ToStringPrecision(double x, const char* fmt)
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
snprintf(buf, sizeof(buf), fmt, x);
|
|
|
|
return buf;
|
|
|
|
}
|
2023-02-10 16:20:26 +00:00
|
|
|
|
|
|
|
// Format must be something like %0.1f %s
|
|
|
|
inline std::string StorageUnitDynamic(double bytes, const char* fmt)
|
|
|
|
{
|
|
|
|
constexpr double KiB = 1024;
|
|
|
|
constexpr double MiB = 1024 * KiB;
|
|
|
|
constexpr double GiB = 1024 * MiB;
|
|
|
|
char buf[128];
|
|
|
|
if (bytes >= GiB)
|
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), fmt, bytes * (1 / GiB), "GiB");
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
if (bytes >= MiB)
|
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), fmt, bytes * (1 / MiB), "MiB");
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
if (bytes >= KiB)
|
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), fmt, bytes * (1 / KiB), "KiB");
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), fmt, bytes, "B");
|
|
|
|
return buf;
|
|
|
|
}
|
2023-01-13 15:13:56 +00:00
|
|
|
}
|
2023-01-14 22:18:34 +00:00
|
|
|
|
|
|
|
struct Process
|
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
};
|
|
|
|
|
2023-02-04 14:33:06 +00:00
|
|
|
inline Process OpenProcess(const std::string& command)
|
2023-01-14 22:18:34 +00:00
|
|
|
{
|
|
|
|
pid_t child = fork();
|
|
|
|
ASSERT(child != -1, "fork error");
|
|
|
|
|
|
|
|
if (child == 0)
|
|
|
|
{
|
|
|
|
// Child
|
2023-02-04 14:33:06 +00:00
|
|
|
system(command.c_str());
|
2023-01-14 22:18:34 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return {child};
|
|
|
|
}
|
|
|
|
}
|
2023-01-28 14:07:07 +00:00
|
|
|
|
|
|
|
// Plugins
|
|
|
|
#include "Window.h"
|
|
|
|
#define DL_VERSION 1
|
|
|
|
|
|
|
|
#define DEFINE_PLUGIN(fun) \
|
|
|
|
extern "C" int32_t Plugin_GetVersion() \
|
|
|
|
{ \
|
|
|
|
return DL_VERSION; \
|
|
|
|
}; \
|
|
|
|
extern "C" void Plugin_InvokeCreateFun(void* window, int32_t monitor) \
|
|
|
|
{ \
|
|
|
|
fun(*(Window*)window, monitor); \
|
|
|
|
}
|