65#include <sys/sysctl.h>
68using std::invalid_argument;
69using std::out_of_range;
85 if (ret == NAN || ret >= nexttoward((
double) LLONG_MAX, LLONG_MAX)) {
104 char *endptr_tmp =
nullptr;
106 double ret = strtod(str, &endptr_tmp);
111 if (endptr_tmp == str) {
115 char unit_prefix = case_sensitive ? *endptr_tmp : toupper(*endptr_tmp);
117 switch(unit_prefix) {
138 ret *= 1000'000'000LL;
144 if (endptr !=
nullptr) {
145 *endptr = endptr_tmp;
155 const char *si_prefixes[] = {
"",
"k",
"M",
"G",
"T" };
158 while (
val > 10000) {
159 reminder =
val % 1000;
162 if (prefix_idx ==
sizeof si_prefixes /
sizeof si_prefixes[0] - 1) {
166 thread_local char buf[128];
167 snprintf(buf,
sizeof buf,
"%lld.%d %s",
val, reminder / 100, si_prefixes[prefix_idx]);
174 HMODULE hntdll = GetModuleHandle(
"ntdll.dll");
179 return GetProcAddress(hntdll,
"wine_get_version");
186 return round(fps * denominator / 100.0) * 100.0;
192 int fps_rounded_x1000 =
round(fps) * 1000;
193 if (fabs(fps * 1001 - fps_rounded_x1000) <
194 fabs(fps * 1000 - fps_rounded_x1000)
195 && fps * 1000 < fps_rounded_x1000) {
206 STRERROR_BUF_LEN = 1024,
208 static thread_local char strerror_buf[STRERROR_BUF_LEN];
209 strerror_s(strerror_buf,
sizeof strerror_buf, errnum);
222 GetSystemInfo(&sysinfo);
223 return MIN(sysinfo.dwNumberOfProcessors, INT_MAX);
225 long numCPU = sysconf(_SC_NPROCESSORS_ONLN);
227 perror(
"sysconf(_SC_NPROCESSORS_ONLN)");
230 return MIN(numCPU, INT_MAX);
244 struct key_val nullopts[] = { {
nullptr,
nullptr } };
248 std::ostringstream oss;
251 auto desc_key = [](
const char *
key) {
253 if (
const char *k = strchr(
key,
'='); k !=
nullptr && strpbrk(
key,
"[:") ==
nullptr) {
259 auto add_opt = [&](
const struct key_val *it) {
266 max_key_len =
MAX(max_key_len, (
int) strlen(desc_key(it->key)));
267 oss <<
":" << it->key;
269 for (
const auto *it =
options; it->key !=
nullptr; ++it) {
272 if (print_full_help && options_full) {
273 for (
const auto *it = options_full; it->
key !=
nullptr; ++it) {
278 oss <<
"] | " << module_name << (options_full ?
":[full]help" :
":help") <<
TERM_RESET;
286 for (
const auto *it =
options; it->key !=
nullptr; ++it) {
287 color_printf(
"\t" TBOLD(
"%*s")
" - %s\n", max_key_len, desc_key(it->key), it->val);
289 if (print_full_help && options_full) {
290 for (
const auto *it = options_full; it->
key !=
nullptr; ++it) {
291 color_printf(
"\t" TBOLD(
"%*s")
" - %s\n", max_key_len, desc_key(it->key), it->val);
299 long long val = stoll(value_str, &pos);
301 throw out_of_range(
"negative number");
303 if (
val > UINT32_MAX) {
304 throw out_of_range(
"higher value than range of uint32");
307 throw invalid_argument(
"no conversion was performed");
318 size_t len =
sizeof machine;
319 if (sysctlbyname(
"hw.machine", &machine, &
len, NULL, 0) != 0) {
320 perror(
"sysctlbyname hw.machine");
323 int proc_translated = -1;
324 len =
sizeof proc_translated;
325 if (
int ret = sysctlbyname(
"sysctl.proc_translated", &proc_translated, &
len, NULL, 0); ret != 0 && errno != ENOENT) {
326 perror(
"sysctlbyname sysctl.proc_translated");
328 return strstr(machine,
"arm") != NULL || proc_translated == 1;
341 if (what ==
nullptr) {
344 return strncmp(what,
"stoi", 4) == 0 || strncmp(what,
"stod", 4) == 0;
int color_printf(const char *format,...)
static __device__ vec3 round(const vec3 &v)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_ERROR
general errors
bool invalid_arg_is_numeric(const char *what)
void ug_perror(const char *s)
void print_module_usage(const char *module_name, const struct key_val *options, const struct key_val *options_full, bool print_full_help)
double unit_evaluate_dbl(const char *str, bool case_sensitive, const char **endptr)
int get_framerate_d(double fps)
int get_cpu_core_count(void)
long long unit_evaluate(const char *str, const char **endptr)
int get_framerate_n(double fps)
const char * ug_strerror(int errnum)
const char * format_in_si_units(unsigned long long int val)
uint32_t parse_uint32(const char *value_str) noexcept(false)
#define strerror_s(buf, bufsz, errnum)