You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
6.4 KiB
321 lines
6.4 KiB
#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 |
|
|
|
#include "ruc/meta/assert.h" |
|
|
|
#include "inferno/io/log.h" |
|
|
|
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 increased in 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 (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)); |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
StringLogStream::~StringLogStream() |
|
{ |
|
char terminator = '\0'; |
|
write(&terminator, 1); |
|
*m_fill = std::string(reinterpret_cast<char*>(buffer())); |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
const LogStream& operator<<(const LogStream& stream, const char* value) |
|
{ |
|
if (value == nullptr) { |
|
stream.write("(null)", 6); |
|
return stream; |
|
} |
|
|
|
stream.write(value, strlen(value)); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, const unsigned char* value) |
|
{ |
|
if (value == nullptr) { |
|
stream.write("(null)", 6); |
|
return stream; |
|
} |
|
|
|
stream.write(value, strlen((const char*)value)); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, const std::string& value) |
|
{ |
|
stream.write(value.c_str(), value.length()); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, const std::string_view& value) |
|
{ |
|
stream.write(value.data(), value.length()); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, char value) |
|
{ |
|
stream.write(&value, 1); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, unsigned char value) |
|
{ |
|
stream.write(&value, 1); |
|
return stream; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, int value) |
|
{ |
|
// return stream << std::to_string(value); |
|
|
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%d", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, long int value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%ld", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, long long int value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%lld", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, unsigned int value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%u", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, long unsigned int value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%lu", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, long long unsigned int value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%llu", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, double value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%.4f", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, float value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%.4f", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, const void* value) |
|
{ |
|
char buffer[32]; |
|
snprintf(buffer, sizeof(buffer), "%p", value); |
|
return stream << buffer; |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, bool value) |
|
{ |
|
return stream << (value ? "true" : "false"); |
|
} |
|
|
|
const LogStream& operator<<(const LogStream& stream, Log value) |
|
{ |
|
switch (value) { |
|
case Log::None: |
|
return stream << "Log"; |
|
case Log::Info: |
|
return stream << "Info"; |
|
case Log::Warn: |
|
return stream << "Warn"; |
|
case Log::Danger: |
|
return stream << "Danger"; |
|
case Log::Success: |
|
return stream << "Success"; |
|
case Log::Comment: |
|
return stream << "Comment"; |
|
default: |
|
VERIFY_NOT_REACHED(); |
|
return stream; |
|
} |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
DebugLogStream dbg() |
|
{ |
|
return {}; |
|
} |
|
|
|
DebugLogStream dbg(bool newline) |
|
{ |
|
return DebugLogStream(newline); |
|
} |
|
|
|
DebugLogStream info() |
|
{ |
|
return DebugLogStream(Log::Info); |
|
} |
|
|
|
DebugLogStream warn() |
|
{ |
|
return DebugLogStream(Log::Warn); |
|
} |
|
|
|
DebugLogStream danger() |
|
{ |
|
return DebugLogStream(Log::Danger); |
|
} |
|
|
|
DebugLogStream success() |
|
{ |
|
return DebugLogStream(Log::Success); |
|
} |
|
|
|
DebugLogStream comment() |
|
{ |
|
return DebugLogStream(Log::Comment); |
|
} |
|
|
|
DebugLogStream info(bool newline) |
|
{ |
|
return DebugLogStream(Log::Info, newline); |
|
} |
|
|
|
DebugLogStream warn(bool newline) |
|
{ |
|
return DebugLogStream(Log::Warn, newline); |
|
} |
|
|
|
DebugLogStream danger(bool newline) |
|
{ |
|
return DebugLogStream(Log::Danger, newline); |
|
} |
|
|
|
DebugLogStream success(bool newline) |
|
{ |
|
return DebugLogStream(Log::Success, newline); |
|
} |
|
|
|
DebugLogStream comment(bool newline) |
|
{ |
|
return DebugLogStream(Log::Comment, newline); |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
void dbgln(Log type, bool newline) |
|
{ |
|
(void)type, DebugLogStream(newline); |
|
} |
|
|
|
void dbgln(Log type, bool newline, const char* format) |
|
{ |
|
DebugLogStream(type, newline) << format; |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
StringLogStream str(std::string* fill) |
|
{ |
|
return StringLogStream(fill); |
|
} |
|
|
|
} // namespace Inferno
|
|
|