222 lines
7.4 KiB
C++
222 lines
7.4 KiB
C++
/*! /\ +=======================================================+
|
|
* ____/ \____ /: Open source game framework licensed to freely use, :
|
|
* \ / / : copy, and modify - created for dank.game :
|
|
* +==\ ^__^ /==+ : :
|
|
* : ~/ \~ : : Download at https://open.shampoo.ooo/shampoo/spacebox :
|
|
* : ~~~~~~~~~~~~ : +=======================================================+
|
|
* : SPACE ~~~~~ : /
|
|
* : ~~~~~~~ BOX :/
|
|
* +==============+
|
|
*
|
|
* Log messages using function calls or the stream operator.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <functional>
|
|
#include <SDL.h>
|
|
#include "json/json.hpp"
|
|
|
|
/* Include Open GL so GL errors can be logged */
|
|
#include "gl.h"
|
|
|
|
namespace sb
|
|
{
|
|
|
|
class Log
|
|
{
|
|
|
|
private:
|
|
|
|
/* Toggle this flag to allow or disallow calls to glGetError in Log::gl_errors(std::string) */
|
|
static bool allow_gl_error;
|
|
|
|
public:
|
|
|
|
/* Equivalent of SDL's SDL_LOG_PRIORITY_* values */
|
|
enum Level
|
|
{
|
|
VERBOSE = 1,
|
|
DEBUG,
|
|
INFO,
|
|
WARN,
|
|
ERR,
|
|
CRITICAL,
|
|
};
|
|
|
|
static const int DEFAULT_CATEGORY = SDL_LOG_CATEGORY_CUSTOM;
|
|
|
|
/*!
|
|
* Send a message to SDL's log function, which currently gets overridden in sb::Game. The default level is Level::INFO.
|
|
*
|
|
* Category will default to SDL's custom category. Using the default category will ensure that debug level statements are
|
|
* handled according to the options in the global configuration.
|
|
*
|
|
* @param message text to add to the log
|
|
* @param level message priority level
|
|
* @param category a category that matches SDL_LOG_CATEGORY_*
|
|
*/
|
|
static void log(const std::string& message, const Level level = INFO, const int category = DEFAULT_CATEGORY);
|
|
|
|
/*!
|
|
* Send a log statement using a stringstream.
|
|
*
|
|
* @see Log::log(const std::string&, const Level, const int)
|
|
*/
|
|
static void log(const std::ostringstream& message, const Level level = INFO, const int category = DEFAULT_CATEGORY);
|
|
|
|
/*!
|
|
* @warning `glGetError` was determined to cause significant slow down on mobile browsers. Therefore, it is disabled
|
|
* by default. This function is OK to use in testing, but should not be used in production code.
|
|
*/
|
|
static void enable_gl_errors();
|
|
|
|
/*!
|
|
* Turn off GL error reporting, even if Log::gl_errors(const std::string&) is called. This is the default because of
|
|
* lag in `glGetError` calls.
|
|
*/
|
|
static void disable_gl_errors();
|
|
|
|
/*!
|
|
* @warning `glGetError` was determined to cause significant slow down on mobile browsers. Therefore, it is disabled
|
|
* by default. Call Log::enable_gl_errors() or set "log" > "gl error" to true in the configuration file to force
|
|
* enable for testing, but it is strongly recommended to make sure GL errors are disabled in production.
|
|
*
|
|
* Log all GL errors accumulated since the last time this function was called.
|
|
*
|
|
* @param heading optional text to prepend to the error message
|
|
*/
|
|
static bool gl_errors(const std::string& heading = "");
|
|
|
|
/*!
|
|
* Log a message, adding the results of `SDL_GetError` to the end of the message. This should be used to log a message after
|
|
* an SDL API function returns an error value because SDL functions are written to set the value of SDL_GetError in that case.
|
|
* The priority level will be `Level::ERROR` unless a different level is specified.
|
|
*
|
|
* @param message text to log before the SDL error is appended
|
|
* @param level message priority level
|
|
* @return a string stream containing the full message
|
|
*/
|
|
static std::ostringstream sdl_error(const std::string& message = "", const Level level = ERR);
|
|
|
|
/*!
|
|
* Parent class for creating streaming output handlers.
|
|
*/
|
|
class Out
|
|
{
|
|
protected:
|
|
Level level = INFO;
|
|
public:
|
|
Out() = default;
|
|
Out(Level level) : level(level) {}
|
|
};
|
|
|
|
/*!
|
|
* Used to indicate the end of a series of strings being concatenated into the log.
|
|
*
|
|
* @see sb::Log::Multi
|
|
*/
|
|
inline static const std::string end = "\0";
|
|
|
|
/*!
|
|
* Log a single string and append a line-break using the stream operator.
|
|
*
|
|
* @code
|
|
* sb::Log::Line() << "Hello, World!";
|
|
* // adds "Hello, World!" to the log
|
|
* @endcode
|
|
*
|
|
* Non-string objects are compatible with the log stream if they have an overload implemented like
|
|
* `std::operator<<(std::ostream&, const CustomType&)` (which also will allow CustomType to be streamed to
|
|
* `std::cout`).
|
|
*
|
|
* @code
|
|
* sb::Log::Line() << sb::Color(0.0f, 0.6f, 0.0f);
|
|
* // adds "{r=0, g=1, b=0, a= 255, h=120, s=1, v=0.00392157}" to the log
|
|
* @endcode
|
|
*
|
|
* @see std::operator<<(std::ostream&, const sb::Color&)
|
|
*
|
|
* Defaults to INFO level. Pass a different level to the constructor to use another level.
|
|
*
|
|
* @code
|
|
* sb::Log::Line(sb::Log::DEBUG) << "the 🐞";
|
|
* // adds "the 🐞" to debug output
|
|
* @endcode
|
|
*
|
|
* @see sb::Log::Multi
|
|
*/
|
|
class Line : Out
|
|
{
|
|
|
|
public:
|
|
|
|
Line() = default;
|
|
Line(Level level) : Out(level) {}
|
|
|
|
template<typename Type>
|
|
void operator<<(const Type& out)
|
|
{
|
|
/* Pass a known type std::ostringstream to sb::Log::log */
|
|
std::ostringstream message;
|
|
message << out;
|
|
sb::Log::log(message, level);
|
|
}
|
|
|
|
};
|
|
|
|
/*!
|
|
* Log multiple strings using the stream operator. Strings concatenate until reaching the sb::Log::end property.
|
|
* A line break is automatically appended.
|
|
*
|
|
* @see sb::Log::Line
|
|
*
|
|
* @code
|
|
* sb::Log::Multi() << "It's " << luigi_game.configuration()("display", "title") << sb::Log::end;
|
|
* // adds the following to the log:
|
|
* // It's Luigi Adventure! 🏍
|
|
* @endcode
|
|
*/
|
|
class Multi : Out
|
|
{
|
|
|
|
private:
|
|
|
|
std::ostringstream message;
|
|
|
|
public:
|
|
|
|
Multi() = default;
|
|
Multi(Level level) : Out(level) {}
|
|
|
|
template<typename Type>
|
|
sb::Log::Multi& operator<<(const Type& out)
|
|
{
|
|
/* Only check for the end indicator if the stream is known to be a string type */
|
|
if constexpr (std::is_same_v<Type, std::string>)
|
|
{
|
|
if (out == end)
|
|
{
|
|
sb::Log::log(message, level);
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
/* Store the stream contents in the object */
|
|
message << out;
|
|
return *this;
|
|
}
|
|
|
|
sb::Log::Multi& operator<<(std::ostream&(*func)(std::ostream&))
|
|
{
|
|
message << func;
|
|
return *this;
|
|
}
|
|
|
|
};
|
|
};
|
|
|
|
}
|