Log.h#
This file contains Logging functionality.
Includes#
PVRCore/Errors.h
assert.h
cstdarg
cstdio
cstdlib
cstring
string
(CompileTimeHash.h)
Included By#
Namespaces#
Classes#
Enums#
Functions#
Defines#
Variables#
Source Code#
#ifndef _PVR_LOG_H
#define _PVR_LOG_H
#pragma once
#include <string>
#include <assert.h>
#include <cstdlib>
#include <cstdarg>
#include <cstring>
#include <cstdio>
#include "PVRCore/Errors.h"
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#define vsnprintf _vsnprintf
#endif
#if defined(__linux__)
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#endif
#if defined(__ANDROID__)
#include <android/log.h>
static const android_LogPriority messageTypes[] = {
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
};
#elif defined(__QNXNTO__)
#include <sys/slog.h>
static const int messageTypes[] = { _SLOG_DEBUG1, _SLOG_DEBUG1, _SLOG_INFO, _SLOG_WARNING, _SLOG_ERROR, _SLOG_CRITICAL };
#else
static const char* messageTypes[] = { "VERBOSE: ", "DEBUG: ", "INFORMATION: ", "WARNING: ", "ERROR: ", "CRITICAL: ", "PERFORMANCE: " };
#endif
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || defined(__ANDROID__)
#define PVR_PLATFORM_IS_MOBILE 1
#else
#define PVR_PLATFORM_IS_DESKTOP 1
#endif
enum class LogLevel
{
Verbose = 0,
Debug = 1,
Information = 2,
Warning = 3,
Error = 4,
Critical = 5,
Performance = 6,
None = 100,
};
class ILogger
{
public:
ILogger() : _verbosityThreshold(LogLevel::Information) {}
void setVerbosity(const LogLevel minimumLevelToOutput) { _verbosityThreshold = minimumLevelToOutput; }
LogLevel getVerbosity() const { return _verbosityThreshold; }
void operator()(LogLevel severity, const char* const formatString, ...) const
{
if (severity < _verbosityThreshold) { return; }
va_list argumentList;
va_start(argumentList, formatString);
vaOutput(severity, formatString, argumentList);
va_end(argumentList);
}
void operator()(const char* const formatString, ...) const
{
if (LogLevel::Error < _verbosityThreshold) { return; }
va_list argumentList;
va_start(argumentList, formatString);
vaOutput(LogLevel::Error, formatString, argumentList);
va_end(argumentList);
}
void output(LogLevel severity, const char* formatString, ...) const
{
if (severity < _verbosityThreshold) { return; }
va_list argumentList;
va_start(argumentList, formatString);
vaOutput(severity, formatString, argumentList);
va_end(argumentList);
}
void output(const char* formatString, ...) const
{
if (LogLevel::Error < _verbosityThreshold) { return; }
va_list argumentList;
va_start(argumentList, formatString);
vaOutput(LogLevel::Error, formatString, argumentList);
va_end(argumentList);
}
virtual void vaOutput(LogLevel severity, const char* formatString, va_list argumentList) const = 0;
private:
LogLevel _verbosityThreshold;
};
class Logger : public ILogger
{
FILE* file;
public:
Logger()
{
#if defined(PVR_PLATFORM_IS_DESKTOP) && !defined(TARGET_OS_MAC)
file = fopen("log.txt", "w");
#endif
}
virtual ~Logger() { close(); }
void close()
{
if (file)
{
fclose(file);
file = 0;
}
}
virtual void vaOutput(LogLevel severity, const char* formatString, va_list argumentList) const
{
#ifndef DEBUG
if (severity > LogLevel::Debug)
#endif
{
#if defined(__ANDROID__)
// Note: There may be issues displaying 64bits values with this function
// Note: This function will truncate long messages
__android_log_vprint(messageTypes[static_cast<uint32_t>(severity)], "com.powervr.Example", formatString, argumentList);
#elif defined(__QNXNTO__)
vslogf(1, messageTypes[static_cast<uint32_t>(severity)], formatString, argumentList);
#else // Not android Not QNX
static char buffer[4096];
va_list tempList;
memset(buffer, 0, sizeof(buffer));
#if (defined _MSC_VER) // Pre VS2013
tempList = argumentList;
#else
va_copy(tempList, argumentList);
#endif
vsnprintf(buffer, 4095, formatString, argumentList);
buffer[4095] = 0;
#if defined(_WIN32)
if (isDebuggerPresent())
{
OutputDebugString(messageTypes[static_cast<int>(severity)]);
OutputDebugString(buffer);
OutputDebugString("\n");
}
#endif
vprintf(formatString, tempList);
printf("\n");
#if defined(PVR_PLATFORM_IS_DESKTOP) && !defined(TARGET_OS_MAC)
{
if (file)
{
fwrite(messageTypes[static_cast<int>(severity)], 1, strlen(messageTypes[static_cast<int>(severity)]), file);
fwrite(buffer, 1, strlen(buffer), file);
fwrite("\n", 1, 1, file);
fflush(file);
}
}
#endif
#endif
}
}
};
namespace impl {
static Logger originalDefaultLogger;
}
inline Logger& originalDefaultLogger() { return impl::originalDefaultLogger; }
inline Logger& DefaultLogger()
{
static Logger* logger = &originalDefaultLogger();
return *logger;
}
inline void LogClose() { DefaultLogger().close(); }
inline void Log(LogLevel severity, const char* formatString, ...)
{
va_list argumentList;
va_start(argumentList, formatString);
DefaultLogger().vaOutput(severity, formatString, argumentList);
va_end(argumentList);
}
inline void Log(const char* formatString, ...)
{
va_list argumentList;
va_start(argumentList, formatString);
DefaultLogger().vaOutput(LogLevel::Error, formatString, argumentList);
va_end(argumentList);
}
// clang-format off
#define SLASH(s) /##s
#define COMMENT SLASH(/)
// clang-format on
#ifdef DEBUG
#define DebugLog(message) Log(LogLevel::Debug, message)
#else
#define DebugLog(message) void(0)
#endif
#ifdef DEBUG
#define debug_warning(condition, message) assert_warning(condition, message)
#else
#define debug_warning(condition, message) ((void)0)
#endif
inline void assert_warning(bool condition, const char* msg)
{
if (!condition) { Log(LogLevel::Warning, msg); }
}
inline void assertion(bool condition, const char* msg)
{
if (!condition)
{
Log(LogLevel::Critical, "ASSERTION FAILED: %s", msg);
debuggerBreak();
assert(0);
}
}
inline void assertion(bool condition) { assertion(condition, ""); }
#ifdef DEBUG
#define debug_assertion(condition, message) assertion(condition, message)
#else
#define debug_assertion(condition, message) ((void)0)
#endif
inline void assertion(bool condition, const std::string& message)
{
if (!condition)
{
Log(LogLevel::Critical, ("ASSERTION FAILED: " + message).c_str());
debuggerBreak();
assert(0);
}
}
#endif