summaryrefslogtreecommitdiff
path: root/kernel/io/logger
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/io/logger')
-rw-r--r--kernel/io/logger/base.cxx11
-rw-r--r--kernel/io/logger/base.h31
-rw-r--r--kernel/io/logger/base.ipp145
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