Add BufferedLogStream
This commit is contained in:
@@ -1,12 +1,99 @@
|
|||||||
#include "inferno/assert.h"
|
#include "inferno/assert.h"
|
||||||
#include "inferno/io/log.h"
|
#include "inferno/io/log.h"
|
||||||
|
|
||||||
#include <cstring> // strlen
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdio> // fwrite, snprintf
|
||||||
|
#include <cstdlib> // malloc, free
|
||||||
|
#include <cstring> // memcpy, strlen
|
||||||
#include <string> // std::string
|
#include <string> // std::string
|
||||||
#include <string_view> // std::string_view
|
#include <string_view> // std::string_view
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
|
BufferedLogStream::~BufferedLogStream()
|
||||||
|
{
|
||||||
|
// Free buffer memory
|
||||||
|
if (m_capacity > sizeof(m_buffer.stack)) {
|
||||||
|
free(m_buffer.heap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferedLogStream::grow(size_t bytes) const
|
||||||
|
{
|
||||||
|
// Bitwise & ~ example, we use 127 as binary starts at 0
|
||||||
|
// 0b001111111 127 ~
|
||||||
|
// 0b100000100 260 &
|
||||||
|
// -----------
|
||||||
|
// 0b110000000 384
|
||||||
|
// 0b100000100 260 &
|
||||||
|
// -----------
|
||||||
|
// 0b100000000 256
|
||||||
|
|
||||||
|
// Buffer is is chunks of 128 bytes
|
||||||
|
size_t newCapacity = (m_count + bytes + BUFFER_SIZE - 1) & ~(BUFFER_SIZE - 1);
|
||||||
|
|
||||||
|
unsigned char* newBuffer = static_cast<unsigned char*>(malloc(newCapacity));
|
||||||
|
|
||||||
|
// Copy the non-heap data into the new buffer
|
||||||
|
if (m_capacity <= sizeof(m_buffer.stack)) {
|
||||||
|
memcpy(newBuffer, m_buffer.stack, m_count);
|
||||||
|
}
|
||||||
|
// Copy old heap-buffer data into the new buffer, free old heap-buffer
|
||||||
|
else if (m_buffer.heap) {
|
||||||
|
memcpy(newBuffer, m_buffer.heap, m_count);
|
||||||
|
free(m_buffer.heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer.heap = newBuffer;
|
||||||
|
m_capacity = newCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
DebugLogStream::~DebugLogStream()
|
||||||
|
{
|
||||||
|
if (empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_type != Log::None) {
|
||||||
|
const char* clear = "\033[0m";
|
||||||
|
write(clear, strlen(clear));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_newline) {
|
||||||
|
char newline = '\n';
|
||||||
|
write(&newline, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(buffer(), 1, count(), stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugLogStream::color() const
|
||||||
|
{
|
||||||
|
const char* color = "";
|
||||||
|
|
||||||
|
if (m_type == Log::Info) {
|
||||||
|
color = "\x1B[34m";
|
||||||
|
}
|
||||||
|
else if (m_type == Log::Warn) {
|
||||||
|
color = "\x1B[33m";
|
||||||
|
}
|
||||||
|
else if (m_type == Log::Danger) {
|
||||||
|
color = "\x1B[31m";
|
||||||
|
}
|
||||||
|
else if (m_type == Log::Success) {
|
||||||
|
color = "\x1B[32m";
|
||||||
|
}
|
||||||
|
else if (m_type == Log::Comment) {
|
||||||
|
color = "\x1B[37m";
|
||||||
|
}
|
||||||
|
|
||||||
|
write(color, strlen(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const char* value)
|
const LogStream& operator<<(const LogStream& stream, const char* value)
|
||||||
{
|
{
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
@@ -166,6 +253,8 @@ namespace Inferno {
|
|||||||
return DebugLogStream(type, newline);
|
return DebugLogStream(type, newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
void dbgln(Log type, bool newline) {
|
void dbgln(Log type, bool newline) {
|
||||||
(void)type;
|
(void)type;
|
||||||
dbg(newline);
|
dbg(newline);
|
||||||
@@ -216,42 +305,4 @@ namespace Inferno {
|
|||||||
dbg(type, newline) << format;
|
dbg(type, newline) << format;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
DebugLogStream::~DebugLogStream()
|
|
||||||
{
|
|
||||||
if (m_type != Log::None) {
|
|
||||||
write("\033[0m", 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_newline) {
|
|
||||||
char newline = '\n';
|
|
||||||
write(&newline, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugLogStream::color() const
|
|
||||||
{
|
|
||||||
const char* color = "";
|
|
||||||
if (m_type == Log::Info) {
|
|
||||||
color = "\x1B[34m";
|
|
||||||
}
|
|
||||||
else if (m_type == Log::Warn) {
|
|
||||||
color = "\x1B[33m";
|
|
||||||
}
|
|
||||||
else if (m_type == Log::Danger) {
|
|
||||||
color = "\x1B[31m";
|
|
||||||
}
|
|
||||||
else if (m_type == Log::Success) {
|
|
||||||
color = "\x1B[32m";
|
|
||||||
}
|
|
||||||
else if (m_type == Log::Comment) {
|
|
||||||
color = "\x1B[37m";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color[0] != '\0') {
|
|
||||||
write(color, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
|
|
||||||
#include <cstdio> // printf
|
#define BUFFER_SIZE 128
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <cstring> // memcpy
|
||||||
#include <string> // std::string
|
#include <string> // std::string
|
||||||
#include <string_view> // std::string_view
|
#include <string_view> // std::string_view
|
||||||
#include <utility> // std::forward
|
#include <utility> // std::forward
|
||||||
@@ -17,7 +20,7 @@ namespace Inferno {
|
|||||||
Comment,
|
Comment,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
class LogStream {
|
class LogStream {
|
||||||
public:
|
public:
|
||||||
@@ -28,9 +31,59 @@ namespace Inferno {
|
|||||||
virtual void write(const unsigned char* characters, int length) const = 0;
|
virtual void write(const unsigned char* characters, int length) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
class DebugLogStream final : public LogStream {
|
class BufferedLogStream : public LogStream {
|
||||||
|
public:
|
||||||
|
BufferedLogStream() {}
|
||||||
|
virtual ~BufferedLogStream();
|
||||||
|
|
||||||
|
inline virtual void write(const char* characters, int length) const override
|
||||||
|
{
|
||||||
|
write(reinterpret_cast<const unsigned char*>(characters), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline virtual void write(const unsigned char* characters, int length) const override
|
||||||
|
{
|
||||||
|
size_t newSize = m_count + length;
|
||||||
|
|
||||||
|
if (newSize > m_capacity) {
|
||||||
|
grow(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append to buffer
|
||||||
|
memcpy(buffer() + m_count, characters, length);
|
||||||
|
|
||||||
|
m_count = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
inline unsigned char* buffer() const
|
||||||
|
{
|
||||||
|
if (m_capacity <= sizeof(m_buffer.stack)) {
|
||||||
|
return m_buffer.stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_buffer.heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool empty() const { return m_count == 0; }
|
||||||
|
inline size_t count() const { return m_count; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void grow(size_t bytes) const;
|
||||||
|
|
||||||
|
mutable size_t m_count { 0 };
|
||||||
|
mutable size_t m_capacity { BUFFER_SIZE };
|
||||||
|
union {
|
||||||
|
mutable unsigned char* heap { nullptr };
|
||||||
|
mutable unsigned char stack[BUFFER_SIZE];
|
||||||
|
} m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class DebugLogStream final : public BufferedLogStream {
|
||||||
public:
|
public:
|
||||||
DebugLogStream():
|
DebugLogStream():
|
||||||
m_newline(true), m_type(Log::None) {}
|
m_newline(true), m_type(Log::None) {}
|
||||||
@@ -44,26 +97,12 @@ namespace Inferno {
|
|||||||
|
|
||||||
void color() const;
|
void color() const;
|
||||||
|
|
||||||
inline virtual void write(const char* characters, int length) const override
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
printf("%c", characters[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline virtual void write(const unsigned char* characters, int length) const override
|
|
||||||
{
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
printf("%c", characters[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_newline;
|
bool m_newline;
|
||||||
Log m_type;
|
Log m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const char* value);
|
const LogStream& operator<<(const LogStream& stream, const char* value);
|
||||||
const LogStream& operator<<(const LogStream& stream, const unsigned char* value);
|
const LogStream& operator<<(const LogStream& stream, const unsigned char* value);
|
||||||
@@ -83,13 +122,15 @@ namespace Inferno {
|
|||||||
const LogStream& operator<<(const LogStream& stream, bool value);
|
const LogStream& operator<<(const LogStream& stream, bool value);
|
||||||
const LogStream& operator<<(const LogStream& stream, Log value);
|
const LogStream& operator<<(const LogStream& stream, Log value);
|
||||||
|
|
||||||
// ----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
DebugLogStream dbg();
|
DebugLogStream dbg();
|
||||||
DebugLogStream dbg(bool newline);
|
DebugLogStream dbg(bool newline);
|
||||||
DebugLogStream dbg(Log type);
|
DebugLogStream dbg(Log type);
|
||||||
DebugLogStream dbg(Log type, bool newline);
|
DebugLogStream dbg(Log type, bool newline);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
void dbgln(Log type, bool newline);
|
void dbgln(Log type, bool newline);
|
||||||
void dbgln(const char* format);
|
void dbgln(const char* format);
|
||||||
void dbgln(Log type, const char* format);
|
void dbgln(Log type, const char* format);
|
||||||
|
|||||||
Reference in New Issue
Block a user