diff --git a/include/lol/base/getopt.h b/include/lol/base/getopt.h index ff7d5430..4747d550 100644 --- a/include/lol/base/getopt.h +++ b/include/lol/base/getopt.h @@ -17,25 +17,161 @@ // -------------------- // +#include +#include +#include + namespace lol { class getopt { public: - getopt(int argc, char ** _argv); - getopt(int argc, char * const * _argv); - ~getopt(); + getopt(int argc, char ** argv) + : m_argc(argc), + m_argv(argv) + { + } + + getopt(int argc, char * const * argv) + : m_argc(argc), + m_argv(argv) + { + } + + void add_opt(int short_opt, char const *long_opt, bool has_arg) + { + optdesc o { long_opt, has_arg, nullptr, short_opt }; + m_opts.push_back(o); + + /* “The standards require that the argument [to isalnum()] is either + * EOF or a value that is representable in the type unsigned char.” */ + if ((int)(unsigned char)short_opt == short_opt && isalnum(short_opt)) + { + m_optstring += (char)short_opt; + if (has_arg) + m_optstring += ':'; + } + } + + int parse() + { + int longindex = 0; // FIXME: what is this? + + /* XXX: this getopt_long implementation should not be trusted for other + * applications without any serious peer reviewing. It “just works” with + * zzuf and a few libcaca programs but may fail miserably in other + * programs. */ + char **argv = (char **)(uintptr_t)m_argv; + char *flag; + + if (this->index >= m_argc) + return -1; + + flag = argv[this->index]; + + if (flag[0] == '-' && flag[1] != '-') + { + char const *tmp; + int ret = flag[1]; + + if (ret == '\0') + return -1; + + tmp = strchr(m_optstring.c_str(), ret); + if (!tmp || ret == ':') + return '?'; - void add_opt(int short_opt, char const *long_opt, bool has_arg); - int parse(); + ++this->index; + if (tmp[1] == ':') + { + if (flag[2] != '\0') + this->arg = flag + 2; + else + { + if (this->index >= m_argc) + goto too_few; + this->arg = argv[this->index++]; + } + return ret; + } - int index; - char *arg; + if (flag[2] != '\0') + { + flag[1] = '-'; + --this->index; + ++argv[this->index]; + } + + return ret; + } + + if (flag[0] == '-' && flag[1] == '-') + { + if (flag[2] == '\0') + return -1; + + for (int i = 0; m_opts[i].name; ++i) + { + size_t l = strlen(m_opts[i].name); + + if (strncmp(flag + 2, m_opts[i].name, l)) + continue; + + switch (flag[2 + l]) + { + case '=': + if (!m_opts[i].has_arg) + goto bad_opt; + longindex = i; + ++this->index; + this->arg = flag + 2 + l + 1; + return m_opts[i].val; + case '\0': + longindex = i; + ++this->index; + if (m_opts[i].has_arg) + { + if (this->index >= m_argc) + goto too_few; + this->arg = argv[this->index++]; + } + return m_opts[i].val; + default: + break; + } + } + bad_opt: + fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); + return '?'; + + too_few: + fprintf(stderr, "%s: option `%s' requires an argument\n", + argv[0], flag); + return '?'; + } + + return -1; + } + + int index = 1; + char *arg = nullptr; private: - std::unique_ptr m_private; + struct optdesc + { + char const *name; + int has_arg; + int *flag; + int val; + }; + + int m_argc; + char * const *m_argv; + + std::string m_optstring; + std::vector m_opts; }; -} +} // namespace lol diff --git a/include/lol/base/thread.h b/include/lol/base/thread.h index f60117f8..25e48d74 100644 --- a/include/lol/base/thread.h +++ b/include/lol/base/thread.h @@ -24,6 +24,7 @@ #include #include #include +#include // std::chrono #include // assert() /* XXX: workaround for a bug in Visual Studio 2012 and 2013! @@ -233,5 +234,37 @@ private: std::condition_variable m_empty_cond, m_full_cond; }; +class timer +{ +public: + inline timer() { (void)get_seconds(true); } + + inline void reset() { (void)get_seconds(true); } + inline float get() { return get_seconds(true); } + inline float poll() { return get_seconds(false); } + + void wait(float seconds) + { + if (seconds > 0.0f) + { + float secs_elapsed = get_seconds(false); + std::this_thread::sleep_for(std::chrono::duration(seconds - secs_elapsed)); + } + } + +private: + std::chrono::steady_clock::time_point m_tp; + + float get_seconds(bool do_reset) + { + auto tp = std::chrono::steady_clock::now(), tp0 = m_tp; + + if (do_reset) + m_tp = tp; + + return std::chrono::duration_cast>(tp - tp0).count(); + } +}; + } /* namespace lol */ diff --git a/include/lol/math/polynomial.h b/include/lol/math/polynomial.h index 7a93f8c1..df64a0ad 100644 --- a/include/lol/math/polynomial.h +++ b/include/lol/math/polynomial.h @@ -22,8 +22,9 @@ #include #include -#include // std::tuple -#include // assert() +#include // std::function +#include // std::tuple +#include // assert() namespace lol { @@ -54,7 +55,7 @@ struct LOL_ATTR_NODISCARD polynomial static polynomial chebyshev(int n) { /* Use T0(x) = 1, T1(x) = x, Tn(x) = 2 x Tn-1(x) - Tn-2(x) */ - auto coeff = [&](int i, int j) -> int64_t + std::function coeff = [&](int i, int j) -> int64_t { if (i > j || i < 0 || ((j ^ i) & 1)) return (int64_t)0; @@ -306,7 +307,7 @@ struct LOL_ATTR_NODISCARD polynomial /* Add two polynomials */ polynomial &operator +=(polynomial const &p) { - int min_degree = lol::min(p.degree(), degree()); + int min_degree = std::min(p.degree(), degree()); for (int i = 0; i <= min_degree; ++i) m_coefficients[i] += p[i]; @@ -414,8 +415,8 @@ private: /* Enforce the non-zero leading coefficient rule. */ void reduce_degree() { - while (m_coefficients.count() && !m_coefficients.last()) - (void)m_coefficients.pop(); + while (m_coefficients.size() && !m_coefficients.back()) + m_coefficients.pop_back(); } /* The polynomial coefficients */ diff --git a/legacy/lol/math/rand.h b/include/lol/math/rand.h similarity index 74% rename from legacy/lol/math/rand.h rename to include/lol/math/rand.h index 6256b90a..286e030c 100644 --- a/legacy/lol/math/rand.h +++ b/include/lol/math/rand.h @@ -1,20 +1,25 @@ // -// Lol Engine +// Lol Engine // -// Copyright: (c) 2010-2013 Sam Hocevar -// This program is free software; you can redistribute it and/or -// modify it under the terms of the Do What The Fuck You Want To -// Public License, Version 2, as published by Sam Hocevar. See -// http://www.wtfpl.net/ for more details. +// Copyright © 2010—2020 Sam Hocevar +// +// Lol Engine is free software. It comes without any warranty, to +// the extent permitted by applicable law. You can redistribute it +// and/or modify it under the terms of the Do What the Fuck You Want +// to Public License, Version 2, as published by the WTFPL Task Force. +// See http://www.wtfpl.net/ for more details. // #pragma once // // The Random number generators -// ---------------------------- +// ———————————————————————————— // +#include + +#include #include #include @@ -32,27 +37,29 @@ template LOL_ATTR_NODISCARD static inline T rand(T a) return a ? rand() % a : T(0); } +#if 0 template<> LOL_ATTR_NODISCARD inline half rand(half a) { float f = (float)std::rand() / (float)RAND_MAX; return (half)(a * f); } +#endif template<> LOL_ATTR_NODISCARD inline float rand(float a) { - float f = (float)std::rand() / (float)RAND_MAX; + auto f = (float)std::rand() / (float)RAND_MAX; return a * f; } template<> LOL_ATTR_NODISCARD inline double rand(double a) { - double f = (double)std::rand() / (double)RAND_MAX; + auto f = (double)std::rand() / (double)RAND_MAX; return a * f; } -template<> LOL_ATTR_NODISCARD inline ldouble rand(ldouble a) +template<> LOL_ATTR_NODISCARD inline long double rand(long double a) { - ldouble f = (ldouble)std::rand() / (ldouble)RAND_MAX; + auto f = (long double)std::rand() / (long double)RAND_MAX; return a * f; } @@ -111,16 +118,17 @@ template LOL_ATTR_NODISCARD static inline T rand() return static_cast(ret & (~(uint64_t)0 >> 1)); } default: - ASSERT(false, "rand() doesn’t support types of size %d\n", - (int)sizeof(T)); + assert(false); return 0; } } +#if 0 template<> LOL_ATTR_NODISCARD inline half rand() { return rand(1.f); } +#endif template<> LOL_ATTR_NODISCARD inline float rand() { return rand(1.f); } template<> LOL_ATTR_NODISCARD inline double rand() { return rand(1.0); } -template<> LOL_ATTR_NODISCARD inline ldouble rand() { return rand(1.0); } +template<> LOL_ATTR_NODISCARD inline long double rand() { return rand(1.0); } } /* namespace lol */ diff --git a/legacy/sys/getopt.cpp b/legacy/sys/getopt.cpp deleted file mode 100644 index 96221ea0..00000000 --- a/legacy/sys/getopt.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// Lol Engine -// -// Copyright © 2002—2018 Sam Hocevar -// -// Lol Engine is free software. It comes without any warranty, to -// the extent permitted by applicable law. You can redistribute it -// and/or modify it under the terms of the Do What the Fuck You Want -// to Public License, Version 2, as published by the WTFPL Task Force. -// See http://www.wtfpl.net/ for more details. -// - -#include - -#if HAVE_GETOPT_H -# include -#endif -#if HAVE_UNISTD_H -# include -#endif - -namespace lol -{ - -struct getopt_private -{ - getopt_private(int argc, char * const * _argv) - : m_argc(argc), - m_argv(_argv) - {} - -#if HAVE_GETOPT_LONG - typedef option optdesc; -#else - struct optdesc - { - char const *name; - int has_arg; - int *flag; - int val; - }; -#endif - - int m_argc; - char * const *m_argv; - - std::string m_optstring; - array m_opts; -}; - -getopt::getopt(int argc, char ** _argv) - : index(1), - arg(nullptr), - m_private(new getopt_private(argc, _argv)) -{ -} - -getopt::getopt(int argc, char * const * _argv) - : index(1), - arg(nullptr), - m_private(new getopt_private(argc, _argv)) -{ -} - -getopt::~getopt() -{ -} - -void getopt::add_opt(int short_opt, char const *long_opt, bool has_arg) -{ - getopt_private::optdesc o { long_opt, has_arg, nullptr, short_opt }; - m_private->m_opts.push(o); - - /* “The standards require that the argument [to isalnum()] is either - * EOF or a value that is representable in the type unsigned char.” */ - if ((int)(unsigned char)short_opt == short_opt && isalnum(short_opt)) - { - m_private->m_optstring += (char)short_opt; - if (has_arg) - m_private->m_optstring += ':'; - } -} - -int getopt::parse() -{ - int longindex = 0; // FIXME: what is this? - -#if HAVE_GETOPT_LONG - int ret; - optind = this->index; - optarg = this->arg; - m_private->m_opts.push(getopt_private::optdesc { nullptr, 0, nullptr, 0 }); - ret = getopt_long(m_private->m_argc, m_private->m_argv, m_private->m_optstring.c_str(), - (option const *)m_private->m_opts.data(), &longindex); - this->index = optind; - this->arg = optarg; - return ret; - -#else - /* XXX: this getopt_long implementation should not be trusted for other - * applications without any serious peer reviewing. It “just works” with - * zzuf and a few libcaca programs but may fail miserably in other - * programs. */ - char **argv = (char **)(uintptr_t)m_private->m_argv; - char *flag; - - if (this->index >= m_private->m_argc) - return -1; - - flag = argv[this->index]; - - if (flag[0] == '-' && flag[1] != '-') - { - char const *tmp; - int ret = flag[1]; - - if (ret == '\0') - return -1; - - tmp = strchr(m_private->m_optstring.c_str(), ret); - if (!tmp || ret == ':') - return '?'; - - ++this->index; - if (tmp[1] == ':') - { - if (flag[2] != '\0') - this->arg = flag + 2; - else - { - if (this->index >= m_private->m_argc) - goto too_few; - this->arg = argv[this->index++]; - } - return ret; - } - - if (flag[2] != '\0') - { - flag[1] = '-'; - --this->index; - ++argv[this->index]; - } - - return ret; - } - - if (flag[0] == '-' && flag[1] == '-') - { - if (flag[2] == '\0') - return -1; - - for (int i = 0; m_private->m_opts[i].name; ++i) - { - size_t l = strlen(m_private->m_opts[i].name); - - if (strncmp(flag + 2, m_private->m_opts[i].name, l)) - continue; - - switch (flag[2 + l]) - { - case '=': - if (!m_private->m_opts[i].has_arg) - goto bad_opt; - longindex = i; - ++this->index; - this->arg = flag + 2 + l + 1; - return m_private->m_opts[i].val; - case '\0': - longindex = i; - ++this->index; - if (m_private->m_opts[i].has_arg) - { - if (this->index >= m_private->m_argc) - goto too_few; - this->arg = argv[this->index++]; - } - return m_private->m_opts[i].val; - default: - break; - } - } - bad_opt: - fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag); - return '?'; - - too_few: - fprintf(stderr, "%s: option `%s' requires an argument\n", - argv[0], flag); - return '?'; - } - - return -1; -#endif -} - -} // namespace lol -