azur: restructure to adhere to a more consistent C++ style

This commit is contained in:
Lephenixnoir 2022-07-18 23:01:42 +01:00
parent 2e63daa59a
commit c74e8fcf13
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
10 changed files with 279 additions and 212 deletions

View File

@ -21,7 +21,7 @@ The following are Azur libraries:
* **libazrp** is C library that implements Azur's Rendering Pipeline. On fx-CG, Azur uses a very unique rendering method that sacrifices some generality for a significant boost in performance, and this system has uses beyond games. (TODO: Currently still in the `azur/` folder)
* **azur** is of course the engine itself.
The following external projects are Azur by some of Azur's features, and maintained as submodules in `3rdparty/`:
The following external projects are used by some of Azur's features, and maintained as submodules in `3rdparty/`:
* [**gl3w**](https://github.com/skaslev/gl3w) is a minimalist OpenGL loader, which is used in Azur's OpenGL backend to load the core profile.
* [**GLM**](https://glm.g-truc.net/0.9.9/index.html) is math library for graphics, which is interoperable with OpenGL shaders. In the future I hope to use libnum everywhere, but GLM is still useful in OpenGL-related code.
@ -29,7 +29,7 @@ The following external projects are Azur by some of Azur's features, and maintai
## Building
You *must* install into a different folder for each platform, as the headers would otherwise clash (particulary the auto-generated `<azur/config.h>`. The library names are different (eg. `libazur_emscripten.a`), but this is just to avoid confusing errors; the folders must still be different.
You *must* install into a different folder for each platform, as the headers would otherwise clash (particulary the auto-generated `<azur/config.h>`). The library names are different (eg. `libazur_emscripten.a`), but this is just to avoid confusing errors; the folders must still be different.
**Building for fx-CG**
@ -90,4 +90,4 @@ endif()
Back in 2021 I made a single repository for this engine, along with other programs that I intended to write with it. At the time I didn't intend to distribute the engine in any serious fashion, but that changed after people expressed interest in playing with [After Burner](https://www.planet-casio.com/Fr/programmes/programme4238-1-after-burner-lephenixnoir-jeux-add-ins.html).
I split the original repository in May 2022 with `git filter-branch`, extracting Azur-related contents to this repository. I edited the history so that old commits can still be built, but mostly for the sake of preserving history; don't expect to be able to use these early commits out-of-the-box.
I split the original repository in May 2022 with `git filter-branch`, extracting Azur-related contents to this repository. I patched old commits so they can still be built, but mostly for the sake of preserving history; don't expect to be able to use these early commits out-of-the-box.

View File

@ -8,14 +8,14 @@
configure_file(include/azur/config.h.in include/azur/config.h)
set(SOURCES
src/log.c)
src/log.cpp)
set(ASSETS)
# SDL/OpenGL rendering
if(AZUR_TOOLKIT_SDL AND AZUR_GRAPHICS_OPENGL)
list(APPEND SOURCES
src/sdl_opengl/init.c
src/sdl_opengl/util.c
src/gl/init.cpp
src/gl/util.cpp
"${CMAKE_CURRENT_BINARY_DIR}/src/glsl.c")
list(APPEND ASSETS

View File

@ -43,7 +43,7 @@ int azur_init(char const *title, int window_width, int window_height);
The update framerate is determined second. If AZUR_MAIN_LOOP_TIED is set,
updates are set to run before renders (except before the very first render),
and update_ups is ignored is ignored. Otherwise, the target UPS is used.
and update_ups is ignored. Otherwise, the target UPS is used.
The main loop stops whenever update() returns non-zero. */
int azur_main_loop(

75
azur/include/azur/gl/gl.h Normal file
View File

@ -0,0 +1,75 @@
//---------------------------------------------------------------------------//
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
// azur.gl.gl: OpenGL 3.3 / OpenGL ES 2.0 compatibility and utilities
//
// This header is specific to OpenGL targets. It provides helpers for some
// degree of compatibility between OpenGL ES 2.0 (with some extensions) and
// OpenGL 3.3. We always use OpenGL 3.3 as the reference and try to expose
// everything as if we are running OpenGL 3.3 on every platform.
//
// This header also provides utility functions to load and compile shaders.
// Azur provides a header for all shader files, which includes the `#version`
// string, modern keywords on OpenGL ES 2.0 (in/out/layout), and two macros
// _GL() and _GLES() that expand to their argument on the corresponding
// platform and nothing otherwise, for when differences in GLSL aren't easily
// fixable by preprocessor. See glsl/prelude*.glsl for details.
//---
#pragma once
#include <azur/defs.h>
#ifdef AZUR_GRAPHICS_OPENGL_3_3
# include <GL/gl3w.h>
# include <SDL2/SDL_opengl.h>
#endif /* OpenGL 3.3 */
#ifdef AZUR_GRAPHICS_OPENGL_ES_2_0
# define GL_GLEXT_PROTOTYPES
# include <SDL2/SDL_opengles2.h>
/* We expose vertex array objects through OES_vertex_array_object. */
# define glGenVertexArrays glGenVertexArraysOES
# define glBindVertexArray glBindVertexArrayOES
# define glDeleteVertexArrays glDeleteVertexArraysOES
# define glIsVertexArray glIsVertexArrayOES
#endif /* OpenGL ES 2.0 */
namespace azur::gl {
/* Returns a string description of an OpenGL error code. The return value if
the GLenum is not recognized is the address of a static buffer, which can
be modified by further calls to the function. */
char const *errorString(GLenum errorCode);
/* Loads the file at `path` and compiles it as a shader of the specified type.
Returns the new shader's ID, or 0 in case of error. Errors are logged. */
GLuint compileShaderFile(GLenum type, char const *path);
/* Compiles the provided code string as a shader of the specified type. If size
is -1, `code` is assumed to be NUL-terminated and strlen(code) is used.
Returns the shader ID, 0 in case of error. Errors are logged. */
GLuint compileShaderSource(GLenum type, char const *code, ssize_t size);
/* Link a program. This function takes a 0-terminated list of shaders IDs and
links them into a new program. Returns the new program's ID, or 0 in case
of error. Errors are logged. */
GLuint linkProgram(GLuint shader_1, ... /* 0-terminated */);
/* Loads a program from shader source files. The arguments come in pairs of
type and file path until a 0-type terminates the list. Each file is loaded
and compiled with compileShaderFile(), then the whole program is linked
with linkProgram(). Returns the program ID, or 0 in case of error. */
GLuint loadProgramFiles(
GLenum type_1, char const *path_1,
... /* Pairs repeat until 0-terminated */);
/* Analoguous to loadProgramFiles(), but takes string inputs and compiles them
with loadShaderSource() with size=-1. */
GLuint loadProgramSources(
GLenum type_1, char const *code_1,
... /* Pairs repeat until 0-terminated */);
} /* namespace azur::gl */

View File

@ -1,54 +1,70 @@
//---
//---------------------------------------------------------------------------//
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
// azur.log: Logging utilities
//
// This header provides the basic logging utilities. Logs are emitted with the
// azlog() macro, then filtered by level and printed to file.
//
// The main function is the azlog() macro, which takes a level parameter and a
// printf()-style format:
//
// azlog(ERROR, "rc = %d\n", rc);
// azlog(INFO, "Game saved!\n");
//---
#pragma once
#include <azur/defs.h>
AZUR_BEGIN_DECLS
#include <stdio.h>
/* Message levels, numbered by "severity". */
enum {
AZLOG_DEBUG = 0,
AZLOG_INFO = 1,
AZLOG_WARN = 2,
AZLOG_ERROR = 3,
AZLOG_FATAL = 4,
};
namespace azur::log {
/* azlog_level(): Get the current logging level
Any message with a level at least the current logging level is printed. The
default logging level is AZLOG_ERROR in release builds, AZLOG_DEBUG in
development builds. */
int azlog_level(void);
/* DEBUG: Disabled by default unless debug build; includes source file/line
INFO: General information that is meaningful to the user (not developer)
WARN: Unexpected behavior but program can still keep going
ERROR: Erroneous behavior, abandoning some tasks
FATAL: Complete panic; provokes exit(1); highest priority */
enum class LogLevel { DEBUG, INFO, WARN, ERROR, FATAL };
/* azlog_set_level(): Set the current logging level */
void azlog_set_level(int level);
/* Coloring options.
PLAIN: No escape sequences; suitable for files and plain terminals.
ANSI: ANSI escape sequences; suitable for terminals. */
enum class LogStyle { PLAIN, ANSI };
/* azlog(): Write an error message
This macro produces a line of log at the specified level. The AZLOG_ prefix
is added automatically by the macro, as well as standard function/line
information in development builds. */
#define azlog(level, fmt, ...) \
azlog_write(AZLOG_ ## level, __FILE__, __LINE__, __func__, false, fmt, \
## __VA_ARGS__)
/* azlogc(): Continue an error message
Same as azlog(), but inhibits prefixes, for multi-part messages. */
#define azlogc(level, fmt, ...) \
azlog_write(AZLOG_ ## level, __FILE__, __LINE__, __func__, true, fmt, \
## __VA_ARGS__)
/* Disable output in gint. */
#ifdef AZUR_TERMINAL_NONE
# undef azlog
# undef azlogc
# define azlog(level, fmt, ...)
# define azlogc(level, fmt, ...)
#endif
/* azlog_write(): Support function for azlog() */
void azlog_write(int level, char const *file, int line, char const *func,
/* Produce a log message. See also azlog() and azlogc() for shorter versions.
level: Message level
file: File name (normally __FILE__)
line: Line number (normally __LINE__)
func: Function name (normally __func__)
cont: Whether this is the continuation of a previous message
fmt...: print()-style format */
void write(LogLevel level, char const *file, int line, char const *func,
bool cont, char const *fmt, ...);
AZUR_END_DECLS
/* Get the minimum-level filter. Messages below the minimum level are filtered
out. The default is INFO in release builds, DEBUG in debug builds. */
LogLevel minimumLevelFilter();
/* Set the minimum-level filter. */
void setMinimumLevelFilter(LogLevel level);
/* Get the output stream for log messages. Default is stderr. */
FILE *outputStream();
/* Set the output stream for log messages. Since the library might output
messages until very late in execution, a valid output stream should always
be specified. When using a file, stderr should be set as the output stream
before closing the file at the end of execution. */
void setOutputStream(FILE *fp, LogStyle style);
} /* namespace azur::log */
/* Quick macros that insert parameters automatically. */
#define azlog(LEVEL, FMT, ...) \
azur::log::write(azur::log::LogLevel::LEVEL, __FILE__, __LINE__, \
__func__, false, FMT, ## __VA_ARGS__)
#define azlogc(LEVEL, FMT, ...) \
azur::log::write(azur::log::LogLevel::LEVEL, __FILE__, __LINE__, \
__func__, true, FMT, ## __VA_ARGS__)

View File

@ -1,65 +0,0 @@
//---
// azur.sdl_opengl.gl: General OpenGL utilities
//---
#pragma once
#include <azur/defs.h>
AZUR_BEGIN_DECLS
#ifdef AZUR_GRAPHICS_OPENGL_3_3
# include <GL/gl3w.h>
# include <SDL2/SDL_opengl.h>
#endif /* OpenGL 3.3 */
#ifdef AZUR_GRAPHICS_OPENGL_ES_2_0
# define GL_GLEXT_PROTOTYPES
# include <SDL2/SDL_opengles2.h>
# define glGenVertexArrays glGenVertexArraysOES
# define glBindVertexArray glBindVertexArrayOES
# define glDeleteVertexArrays glDeleteVertexArraysOES
#endif /* OpenGL ES 2.0 */
/* azgl_error(): String description of a GLenum error code.
The returned pointer might be a static buffer modified by further calls. */
char const *azgl_error(GLenum error_code);
/* azgl_compile_shader_file(): Load and compile a shader from file.
This function loads the file at [path], and compiles it into a shader of the
specified type. If the file cannot be loaded, the shader cannot be created,
or there are compilation errors, this function returns 0. Otherwise, it
returns the shader ID. */
GLuint azgl_compile_shader_file(GLenum type, char const *path);
/* azgl_compile_shader_source(): Load and compile a shader from its code.
Like azgl_load_shader(), but without the filesystem step. If the size is set
to -1, [code] is assumed to be NUL-terminated. */
GLuint azgl_compile_shader_source(GLenum type, char const *code, ssize_t size);
/* azgl_link_program(): Link a program.
This function attaches the 0-terminated list of shaders to a program, links
it, and returns the program ID (0 if link fails). */
GLuint azgl_link_program(GLuint shader_1, ... /* 0-terminated */);
/* azgl_load_program_file(): Load a program from shader source files.
This function runs both azgl_compile_shader_file() and azgl_link_program()
for all specified files. Each argument should be a pair with a shader type
and a file name, with a final 0.
Returns the program ID, or 0 if any loading/compilation/link step fails. */
GLuint azgl_load_program_file(
GLenum type_1, char const *path_1,
... /* Pairs repeat until 0-terminated */);
/* azgl_load_program_source(): Load a program from shader source strings.
Like azgl_load_program_file(), but takes code directly as input. */
GLuint azgl_load_program_source(
GLenum type_1, char const *code_1,
... /* Pairs repeat until 0-terminated */);
AZUR_END_DECLS

View File

@ -1,6 +1,6 @@
#include <azur/azur.h>
#include <azur/log.h>
#include <azur/sdl_opengl/gl.h>
#include <azur/gl/gl.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
@ -214,10 +214,9 @@ static Uint32 handler(Uint32 interval, void *param)
{
*(int *)param = 1;
SDL_Event e = {
.user.type = SDL_USEREVENT,
.user.code = ml_event,
};
SDL_Event e;
e.user.type = SDL_USEREVENT;
e.user.code = ml_event;
SDL_PushEvent(&e);
return interval;
}

View File

@ -1,13 +1,21 @@
#include <azur/sdl_opengl/gl.h>
//---------------------------------------------------------------------------//
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
#include <azur/gl/gl.h>
#include <azur/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
/* Read the full contents of a file into the heap. Returns an malloc'd pointer
on success, NULL if an error occurs. */
// TODO: Move the load_file() function to a more convenient fs util header
static char *load_file(char const *path, size_t *out_size)
{
char *contents = NULL;
@ -20,7 +28,7 @@ static char *load_file(char const *path, size_t *out_size)
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
contents = malloc(size + 1);
contents = new char[size + 1];
if(!contents) goto load_file_end;
if(out_size) *out_size = size;
@ -32,7 +40,14 @@ load_file_end:
return contents;
}
char const *azgl_error(GLenum ec)
extern char const *azur_glsl__vs_prelude_gles2;
extern char const *azur_glsl__vs_prelude_gl3;
extern char const *azur_glsl__fs_prelude_gles2;
extern char const *azur_glsl__fs_prelude_gl3;
namespace azur::gl {
char const *errorString(GLenum ec)
{
static char str[32];
@ -54,7 +69,7 @@ char const *azgl_error(GLenum ec)
}
/* Common code for the shader compiling functions. */
static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
static GLuint compileShader(GLenum type, char const *code, ssize_t size,
char const *origin)
{
/* Shader prelude; this gives shader version, some macro definitions and
@ -65,19 +80,15 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
if(!vs_prelude) {
#if defined AZUR_GRAPHICS_OPENGL_ES_2_0
extern char const *azur_glsl__vs_prelude_gles2;
vs_prelude = azur_glsl__vs_prelude_gles2;
#elif defined AZUR_GRAPHICS_OPENGL_3_3
extern char const *azur_glsl__vs_prelude_gl3;
vs_prelude = azur_glsl__vs_prelude_gl3;
#endif
}
if(!fs_prelude) {
#if defined AZUR_GRAPHICS_OPENGL_ES_2_0
extern char const *azur_glsl__fs_prelude_gles2;
fs_prelude = azur_glsl__fs_prelude_gles2;
#elif defined AZUR_GRAPHICS_OPENGL_3_3
extern char const *azur_glsl__fs_prelude_gl3;
fs_prelude = azur_glsl__fs_prelude_gl3;
#endif
}
@ -99,11 +110,10 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
GLint rc = GL_FALSE;
GLsizei log_length = 0;
if(size < 0)
size = (int)strlen(code);
char const *string_array[] = { prelude, code };
GLint size_array[] = { strlen(prelude), size };
GLint size_array[] = {
(int)strlen(prelude),
(int)(size < 0 ? strlen(code) : size) };
azlog(INFO, "Compiling shader: %s\n", origin);
glShaderSource(id, 2, string_array, size_array);
@ -111,24 +121,24 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
glGetShaderiv(id, GL_COMPILE_STATUS, &rc);
if(rc == GL_FALSE)
azlog(ERROR, "compilation failed!\n");
azlog(ERROR, "Compilation failed!\n");
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length);
if(log_length > 0) {
GLchar *log = malloc((log_length + 1) * sizeof *log);
GLchar *log = new GLchar[log_length + 1];
glGetShaderInfoLog(id, log_length, &log_length, log);
if(log_length > 0) {
azlogc(ERROR, "%s", log);
if(log[log_length - 1] != '\n')
azlogc(ERROR, "\n");
}
free(log);
delete[] log;
}
return id;
}
GLuint azgl_compile_shader_file(GLenum type, char const *path)
GLuint compileShaderFile(GLenum type, char const *path)
{
size_t size;
char *source = load_file(path, &size);
@ -137,17 +147,17 @@ GLuint azgl_compile_shader_file(GLenum type, char const *path)
return 0;
}
GLuint id = azgl_compile_shader(type, source, size, path);
free(source);
GLuint id = compileShader(type, source, size, path);
delete[] source;
return id;
}
GLuint azgl_compile_shader_source(GLenum type, char const *code, ssize_t size)
GLuint compileShaderSource(GLenum type, char const *code, ssize_t size)
{
return azgl_compile_shader(type, code, size, "<inline>");
return compileShader(type, code, size, "<inline>");
}
static GLuint azgl_link(GLuint *shaders, int count)
static GLuint link(GLuint *shaders, int count)
{
GLuint prog = glCreateProgram();
if(prog == 0) {
@ -171,14 +181,14 @@ static GLuint azgl_link(GLuint *shaders, int count)
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_length);
if(log_length > 0) {
GLchar *log = malloc((log_length + 1) * sizeof *log);
GLchar *log = new GLchar[log_length + 1];
glGetProgramInfoLog(prog, log_length, &log_length, log);
if(log_length > 0) {
azlogc(ERROR, "%s", log);
if(log[log_length - 1] != '\n')
azlogc(ERROR, "\n");
}
free(log);
delete[] log;
}
/* Detach all shaders */
@ -188,7 +198,7 @@ static GLuint azgl_link(GLuint *shaders, int count)
return prog;
}
GLuint azgl_link_program(GLuint shader_1, ... /* 0-terminated */)
GLuint linkProgram(GLuint shader_1, ... /* 0-terminated */)
{
va_list args;
va_start(args, shader_1);
@ -203,10 +213,10 @@ GLuint azgl_link_program(GLuint shader_1, ... /* 0-terminated */)
while(count < 32 && shader_1 != 0);
va_end(args);
return azgl_link(shaders, count);
return link(shaders, count);
}
static GLuint azgl_load_program(bool is_file, GLenum type, char const *input,
static GLuint loadProgram_v(bool is_file, GLenum type, char const *input,
va_list *args)
{
GLuint shaders[32];
@ -214,14 +224,14 @@ static GLuint azgl_load_program(bool is_file, GLenum type, char const *input,
do {
shaders[count++] = is_file
? azgl_compile_shader_file(type, input)
: azgl_compile_shader_source(type, input, -1);
? compileShaderFile(type, input)
: compileShaderSource(type, input, -1);
type = va_arg(*args, GLenum);
input = va_arg(*args, char const *);
}
while(count < 32 && type != 0);
GLuint prog = azgl_link(shaders, count);
GLuint prog = link(shaders, count);
for(int i = 0; i < count; i++)
glDeleteShader(shaders[i]);
@ -229,20 +239,22 @@ static GLuint azgl_load_program(bool is_file, GLenum type, char const *input,
return prog;
}
GLuint azgl_load_program_file(GLenum type, char const *path, ...)
GLuint loadProgramFiles(GLenum type, char const *path, ...)
{
va_list args;
va_start(args, path);
GLuint prog = azgl_load_program(true, type, path, &args);
GLuint prog = loadProgram_v(true, type, path, &args);
va_end(args);
return prog;
}
GLuint azgl_load_program_source(GLenum type, char const *code, ...)
GLuint loadProgramSources(GLenum type, char const *code, ...)
{
va_list args;
va_start(args, code);
GLuint prog = azgl_load_program(false, type, code, &args);
GLuint prog = loadProgram_v(false, type, code, &args);
va_end(args);
return prog;
}
} /* namespace azur::gl */

View File

@ -1,59 +0,0 @@
#include <azur/log.h>
#include <stdio.h>
#ifdef AZUR_DEBUG
static int _level = AZLOG_DEBUG;
#else
static int _level = AZLOG_INFO;
#endif
#ifdef AZUR_TERMINAL_ANSI
# define RED "\e[31m"
# define CYAN "\e[36m"
# define YELLOW "\e[33m"
# define STOP "\e[0m"
#else /* AZUR_TERMINAL_PLAIN, by default */
# define RED
# define CYAN
# define YELLOW
# define STOP
#endif
int azlog_level(void)
{
return _level;
}
void azlog_set_level(int level)
{
_level = level;
}
void azlog_write(int level, char const *file, int line, char const *func,
bool cont, char const *fmt, ...)
{
if(level < _level) return;
if(!cont) {
#ifdef AZUR_DEBUG
fprintf(stderr, CYAN "%s:%d: " STOP YELLOW "%s: " STOP,
file, line, func);
#else
(void)file;
(void)line;
fprintf(stderr, "%s: ", func);
#endif
if(level == AZLOG_ERROR)
fprintf(stderr, RED "error: " STOP);
if(level == AZLOG_FATAL)
fprintf(stderr, RED "fatal error: " STOP);
}
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}

89
azur/src/log.cpp Normal file
View File

@ -0,0 +1,89 @@
//---------------------------------------------------------------------------//
// ," /\ ", Azur: A game engine for CASIO fx-CG and PC //
// | _/__\_ | Designed by Lephe' and the Planète Casio community. //
// "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------//
#include <azur/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
namespace azur::log {
#ifdef AZUR_DEBUG
static LogLevel levelFilter = LogLevel::DEBUG;
#else
static LogLevel levelFilter = LogLevel::INFO;
#endif
#ifdef AZUR_TERMINAL_ANSI
static LogStyle style = LogStyle::ANSI;
#else
static LogStyle style = LogStyle::PLAIN;
#endif
static FILE *fp = stderr;
#define ANSI_RED "\e[31m"
#define ANSI_CYAN "\e[36m"
#define ANSI_YELLOW "\e[33m"
#define ANSI_CLEAR "\e[0m"
void write(LogLevel level, char const *file, int line, char const *func,
bool cont, char const *fmt, ...)
{
if(level < levelFilter)
return;
char const *RED = ANSI_RED;
char const *CYAN = ANSI_CYAN;
char const *YELLOW = ANSI_YELLOW;
char const *CLEAR = ANSI_CLEAR;
if(style == LogStyle::PLAIN)
RED = CYAN = YELLOW = CLEAR = "";
if(!cont) {
if(level == LogLevel::DEBUG)
fprintf(fp, "%s%s:%d:", CYAN, file, line);
fprintf(fp, "%s%s:%s ", YELLOW, func, CLEAR);
if(level == LogLevel::ERROR)
fprintf(fp, "%serror:%s ", RED, CLEAR);
if(level == LogLevel::FATAL)
fprintf(fp, "%sfatal error:%s ", RED, CLEAR);
}
va_list args;
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
if(level == LogLevel::FATAL)
exit(1);
}
LogLevel minimumLevelFilter()
{
return levelFilter;
}
void setMinimumLevelFilter(LogLevel lv)
{
levelFilter = lv;
}
FILE *outputStream()
{
return fp;
}
void setOutputStream(FILE *new_fp, LogStyle new_style)
{
fp = new_fp;
style = new_style;
}
} /* namespace azur::log */