Browse Source

Add BufferedLogStream

master
Riyyi 4 years ago
parent
commit
774ae23a20
  1. 129
      inferno/src/inferno/io/log.cpp
  2. 81
      inferno/src/inferno/io/log.h

129
inferno/src/inferno/io/log.cpp

@ -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);
}
}
} }

81
inferno/src/inferno/io/log.h

@ -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 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 LogStream { 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);

Loading…
Cancel
Save