Parcourir la source

Make a lot of headers work independently.

wip/core-clipp
Sam Hocevar il y a 4 ans
Parent
révision
0ba2833bd4
5 fichiers modifiés avec 207 ajouts et 227 suppressions
  1. +145
    -9
      include/lol/base/getopt.h
  2. +33
    -0
      include/lol/base/thread.h
  3. +7
    -6
      include/lol/math/polynomial.h
  4. +22
    -14
      include/lol/math/rand.h
  5. +0
    -198
      legacy/sys/getopt.cpp

+ 145
- 9
include/lol/base/getopt.h Voir le fichier

@@ -17,25 +17,161 @@
// --------------------
//

#include <vector>
#include <string>
#include <cstring>

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<struct getopt_private> 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<optdesc> m_opts;
};

}
} // namespace lol


+ 33
- 0
include/lol/base/thread.h Voir le fichier

@@ -24,6 +24,7 @@
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono> // std::chrono
#include <cassert> // 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<float>(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<std::chrono::duration<float>>(tp - tp0).count();
}
};

} /* namespace lol */


+ 7
- 6
include/lol/math/polynomial.h Voir le fichier

@@ -22,8 +22,9 @@
#include <lol/base/features.h>
#include <lol/base/core.h>

#include <tuple> // std::tuple
#include <cassert> // assert()
#include <functional> // std::function
#include <tuple> // std::tuple
#include <cassert> // assert()

namespace lol
{
@@ -54,7 +55,7 @@ struct LOL_ATTR_NODISCARD polynomial
static polynomial<T> 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<int64_t (int, int)> 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<T> &operator +=(polynomial<T> 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 */


legacy/lol/math/rand.h → include/lol/math/rand.h Voir le fichier

@@ -1,20 +1,25 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// 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 <sam@hocevar.net>
//
// 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 <lol/base/features.h>

#include <cassert>
#include <cstdlib>
#include <stdint.h>

@@ -32,27 +37,29 @@ template<typename T> LOL_ATTR_NODISCARD static inline T rand(T a)
return a ? rand<T>() % a : T(0);
}

#if 0
template<> LOL_ATTR_NODISCARD inline half rand<half>(half a)
{
float f = (float)std::rand() / (float)RAND_MAX;
return (half)(a * f);
}
#endif

template<> LOL_ATTR_NODISCARD inline float rand<float>(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>(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>(ldouble a)
template<> LOL_ATTR_NODISCARD inline long double rand<long double>(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<typename T> LOL_ATTR_NODISCARD static inline T rand()
return static_cast<T>(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<half>() { return rand<half>(1.f); }
#endif
template<> LOL_ATTR_NODISCARD inline float rand<float>() { return rand<float>(1.f); }
template<> LOL_ATTR_NODISCARD inline double rand<double>() { return rand<double>(1.0); }
template<> LOL_ATTR_NODISCARD inline ldouble rand<ldouble>() { return rand<ldouble>(1.0); }
template<> LOL_ATTR_NODISCARD inline long double rand<long double>() { return rand<long double>(1.0); }

} /* namespace lol */


+ 0
- 198
legacy/sys/getopt.cpp Voir le fichier

@@ -1,198 +0,0 @@
//
// Lol Engine
//
// Copyright © 2002—2018 Sam Hocevar <sam@hocevar.net>
//
// 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 <lol/engine-internal.h>

#if HAVE_GETOPT_H
# include <getopt.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#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<optdesc> 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


Chargement…
Annuler
Enregistrer