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/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_view> // std::string_view
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)
{
if (value == nullptr) {
@ -166,6 +253,8 @@ namespace Inferno {
return DebugLogStream(type, newline);
}
// -----------------------------------------
void dbgln(Log type, bool newline) {
(void)type;
dbg(newline);
@ -216,42 +305,4 @@ namespace Inferno {
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
#define LOG_H
#include <cstdio> // printf
#define BUFFER_SIZE 128
#include <cstddef> // size_t
#include <cstring> // memcpy
#include <string> // std::string
#include <string_view> // std::string_view
#include <utility> // std::forward
@ -17,7 +20,7 @@ namespace Inferno {
Comment,
};
// ----------------------------------------
// -----------------------------------------
class LogStream {
public:
@ -28,9 +31,59 @@ namespace Inferno {
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:
DebugLogStream():
m_newline(true), m_type(Log::None) {}
@ -44,26 +97,12 @@ namespace Inferno {
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:
bool m_newline;
Log m_type;
};
// ----------------------------------------
// -----------------------------------------
const LogStream& operator<<(const LogStream& stream, const 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, Log value);
// ----------------------------------------
// -----------------------------------------
DebugLogStream dbg();
DebugLogStream dbg(bool newline);
DebugLogStream dbg(Log type);
DebugLogStream dbg(Log type, bool newline);
// -----------------------------------------
void dbgln(Log type, bool newline);
void dbgln(const char* format);
void dbgln(Log type, const char* format);

Loading…
Cancel
Save