-
Notifications
You must be signed in to change notification settings - Fork 0
/
debug.h
202 lines (171 loc) · 7.74 KB
/
debug.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Utilidades de depuración
#pragma once
#include <iostream>
#include <sstream>
#include "tipos.h"
#ifndef GL_STACK_OVERFLOW
#define GL_STACK_OVERFLOW 0x0503
#endif
#ifndef GL_STACK_UNDERFLOW
#define GL_STACK_UNDERFLOW 0x0504
#endif
namespace tofu {
// Formatear strings
namespace detail
{
template <typename T>
inline str to_string(const T& a) {
std::ostringstream ss;
ss << a;
return ss.str();
}
template <size_t N>
inline void format_args(std::array<str, N>& fmt) {}
template <size_t N, typename T, typename ... A>
inline void format_args(std::array<str, N>& fmt, T&& arg, A&& ... other) {
fmt[N - 1 - sizeof...(A)] = to_string(arg);
format_args(fmt, std::forward<A>(other)...);
}
struct source_location {
static constexpr auto current(
#if (__has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE))
const char *file = __builtin_FILE(),
int line = __builtin_LINE()
#else
const char *file = "no file",
int line = 0
#endif
) noexcept {
return source_location{file, line};
}
constexpr auto file_name() const noexcept { return file_; }
constexpr auto line() const noexcept { return line_; }
const char* file_;
int line_;
};
}
template <typename ... A>
str format(const str& fmt, A&& ... args) {
// Formatear los argumentos
std::array<str, sizeof...(A)> args_formateados;
detail::format_args(args_formateados, std::forward<A>(args)...);
// Variables necesarias
std::ostringstream ss;
bool en_formato = false;
std::array<bool, sizeof...(A)> args_usados;
std::fill(args_usados.begin(), args_usados.end(), false);
// Recorremos el string de formato
for (size_t i = 0; i < fmt.size(); i++) {
// Abrimos un formato
if (fmt[i] == '{') {
en_formato = true;
continue;
}
if (en_formato) {
bool contiene_numero = false;
for (size_t j = i; j < fmt.size(); j++) {
// Si se indica un número, intentamos añadir ese argumento
if (fmt[j] >= '0' && fmt[j] <= '9') {
size_t arg = fmt[j] - '0';
if (arg >= args_formateados.size())
throw std::runtime_error("El string de formato no está bien construído, hay un argumento que no existe");
if (args_usados[arg])
throw std::runtime_error("El string de formato no está bien construído, hay un argumento que se usa más de una vez");
args_usados[arg] = true;
ss << args_formateados[arg];
contiene_numero = true;
}
// Cerramos un formato y lo completamos si no se ha especificado un número
if (fmt[j] == '}') {
if (not contiene_numero) {
bool hay_argumento = false;
for (size_t k = 0; k < args_formateados.size(); k++) {
if (not args_usados[k]) {
args_usados[k] = true;
ss << args_formateados[k];
hay_argumento = true;
break;
}
}
if (not hay_argumento)
throw std::runtime_error("El string de formato no está bien construído, hay corchetes de más");
}
i = j;
en_formato = false;
break;
}
}
} else {
// Si no estamos añadiendo una variable, ponemos la cadena original
ss << fmt[i];
}
}
// Comprobamos que no haya habido errores
if (en_formato)
throw std::runtime_error("El string de formato no está bien construído, hay un corchete sin cerrar");
for (size_t i = 0; i < args_formateados.size(); i++)
if (not args_usados[i])
throw std::runtime_error("El string de formato no está bien construído, hay un argumento sin usar");
return ss.str();
}
// ---
namespace color
{
inline std::ostream& bold_on(std::ostream& os) { return os << "\e[1m"; }
inline std::ostream& bold_off(std::ostream& os) { return os << "\e[0m"; }
inline std::ostream& red(std::ostream& os) { return os << "\e[31m"; }
inline std::ostream& green(std::ostream& os) { return os << "\e[32m"; }
inline std::ostream& yellow(std::ostream& os) { return os << "\e[33m"; }
inline std::ostream& blue(std::ostream& os) { return os << "\e[34m"; }
inline std::ostream& magenta(std::ostream& os) { return os << "\e[35m"; }
inline std::ostream& reset(std::ostream& os) { return os << "\033[0m"; }
}
// ---
namespace log
{
template <typename ... T>
inline void info(const str& fmt, T&& ... args) { std::clog << color::bold_on << color::blue << "[INF]: " << color::reset << color::bold_off << format(fmt, std::forward<T>(args)...) << std::endl; }
template <typename ... T>
inline void warn(const str& fmt, T&& ... args) { std::clog << color::bold_on << color::yellow << "[WAR]: " << color::reset << color::bold_off << format(fmt, std::forward<T>(args)...) << std::endl; }
template <typename ... T>
inline void error(const str& fmt, T&& ... args) { std::cerr << color::bold_on << color::red << "[ERR]: " << color::reset << color::bold_off << format(fmt, std::forward<T>(args)...) << std::endl; }
}
namespace debug
{
inline double time() { return glfwGetTime(); }
#ifdef DEBUG
inline void gl(const detail::source_location &location = detail::source_location::current()) {
GLenum err;
str err_type = "UNKNOWN";
while ((err = glGetError()) != GL_NO_ERROR) {
switch (err) {
case GL_INVALID_ENUM: err_type = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: err_type = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: err_type = "INVALID_OPERATION"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: err_type = "INVALID_FRAMEBUFFER_OPERATION"; break;
case GL_OUT_OF_MEMORY: err_type = "OUT_OF_MEMORY"; break;
case GL_STACK_UNDERFLOW: err_type = "STACK_UNDERFLOW"; break;
case GL_STACK_OVERFLOW: err_type = "STACK_OVERFLOW"; break;
}
std::cerr << color::bold_on << color::magenta << "[GL!]: " << color::reset << color::bold_off << err_type << " in " << location.file_name() << ":" << location.line() << std::endl;
}
}
inline double curr_time = 0, prev_time = 0;
inline double frame_time = 0, render_usuario_time = 0, render_gui_time = 0, present_time = 0;
inline ui32 num_draw = 0, num_instancias = 0;
inline ui32 num_vertices = 0, num_triangulos = 0;
inline bool usar_instancias = true;
#else
inline void gl() {}
#endif
}
}
#ifdef DEBUG
#define TIME(x, res) { \
double t = debug::time(); \
x; \
res = debug::time() - t; \
}
#else
#define TIME(x, res) x
#endif