summaryrefslogtreecommitdiff
path: root/kernel/io/logger/base.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/io/logger/base.ipp')
-rw-r--r--kernel/io/logger/base.ipp145
1 files changed, 145 insertions, 0 deletions
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