diff options
Diffstat (limited to 'kernel/io/logger')
-rw-r--r-- | kernel/io/logger/base.cxx | 11 | ||||
-rw-r--r-- | kernel/io/logger/base.h | 31 | ||||
-rw-r--r-- | kernel/io/logger/base.ipp | 145 |
3 files changed, 187 insertions, 0 deletions
diff --git a/kernel/io/logger/base.cxx b/kernel/io/logger/base.cxx new file mode 100644 index 0000000..bb1e3c4 --- /dev/null +++ b/kernel/io/logger/base.cxx @@ -0,0 +1,11 @@ +#include <io/logger/base.ipp> + +#if defined (__x86_64__) +#include <amd64/io/com1.h> + +namespace hos::io +{ + template class logger<com_logger>; +} + +#endif diff --git a/kernel/io/logger/base.h b/kernel/io/logger/base.h new file mode 100644 index 0000000..7aa9e2d --- /dev/null +++ b/kernel/io/logger/base.h @@ -0,0 +1,31 @@ +#ifndef HOS_IO_BASE_H +#define HOS_IO_BASE_H + +namespace hos::io +{ + enum log_level + { + DEBUG, + INFO, + WARN, + ERROR, + FATAL + }; + + /// Ah, the glorious CRTP... + template <typename concrete_logger> + class logger + { + public: + logger (enum log_level level); + + void set_level (enum log_level level); + void write (enum log_level level, const char *message, ...); + protected: + char buffer[512]; + private: + enum log_level level; + }; +} + +#endif diff --git a/kernel/io/logger/base.ipp b/kernel/io/logger/base.ipp new file mode 100644 index 0000000..b48a132 --- /dev/null +++ b/kernel/io/logger/base.ipp @@ -0,0 +1,145 @@ +#ifndef HOS_IO_BASE_IMPL +#define HOS_IO_BASE_IMPL + +#include <io/logger/base.h> +#include <utils.h> + +#include <stdarg.h> + +namespace hos::io +{ + template <typename concrete_logger> + logger<concrete_logger>::logger (enum log_level level) + { + this->set_level(level); + } + + template <typename concrete_logger> + void logger<concrete_logger>::set_level (enum log_level level) + { + this->level = level; + } + + template <typename concrete_logger> + void logger<concrete_logger>::write (enum log_level level, const char *message, ...) + { + if (level < this->level) + { + return; + } + + char *bufferptr = this->buffer; + memset(bufferptr, 0, sizeof(this->buffer)); + + const char *logtypes[] = { + "DEBUG: ", + "INFO: ", + "WARN: ", + "ERROR: ", + "FATAL: " + }; + + int len = 0; + switch (level) + { + case log_level::DEBUG: { + len = strlen(logtypes[0]); + + memcpy(bufferptr, logtypes[0], len); + bufferptr += len; + break; + } + case log_level::INFO: { + len = strlen(logtypes[1]); + + memcpy(bufferptr, logtypes[1], len); + bufferptr += len; + break; + } + case log_level::WARN: { + len = strlen(logtypes[2]); + + memcpy(bufferptr, logtypes[2], len); + bufferptr += len; + break; + } + case log_level::ERROR: { + len = strlen(logtypes[3]); + + memcpy(bufferptr, logtypes[3], len); + bufferptr += len; + break; + } + case log_level::FATAL: { + len = strlen(logtypes[4]); + + memcpy(bufferptr, logtypes[4], len); + bufferptr += len; + break; + } + } + + len = strlen(message); + if (bufferptr + len >= this->buffer + 510) { + const char failed[] = "LOGGER: Message longer than display buffer."; + memcpy(bufferptr, failed, strlen(failed)); + static_cast<concrete_logger*>(this)->flush(); + } + + va_list args; + va_start(args, message); + + char temp_buffer[this->buffer + 510 - bufferptr]; + char *tempptr = temp_buffer; + memset(tempptr, 0, sizeof(temp_buffer)); + + char next; + while ((next = *message++) != 0) + { + if (next == '%') + { + next = *message++; + switch (next) + { + case 'c': { + char c = va_arg(args, int); + + if (!((tempptr + 1) - temp_buffer > (long int) sizeof(temp_buffer))) + { + memcpy(tempptr, &c, 1); + tempptr++; + } + + break; + } + case 's': { + char *string = va_arg(args, char *); + + len = strlen(string); + if (!((tempptr + len) - temp_buffer > (long int) sizeof(temp_buffer))) + { + memcpy(tempptr, string, len); + tempptr += len; + } + + break; + } + } + } else { + memcpy(tempptr, &next, 1); + tempptr++; + } + } + + va_end(args); + + len = strlen(temp_buffer); + memcpy(bufferptr, temp_buffer, len); + bufferptr += len; + + memcpy(bufferptr, "\n", 1); + static_cast<concrete_logger*>(this)->flush(); + } +} + +#endif |