#pragma once #include #include template class Iterator { public: T next() { return buffer[reverse ? pos-- : pos++]; } operator bool() const { return reverse ? (pos >= 0) : (pos < length); } explicit Iterator(T* b, size_t l) : buffer(b), length(l) { if (reverse) pos = length - 1; }; private: ssize_t pos = 0; T* const buffer; const size_t length; }; class Console { public: virtual void write(char c) = 0; virtual void write(ViewIterator& msg) = 0; virtual void update_cursor() = 0; static void set(Console* ptr); static Iterator begin(); }; template void print_c(Console* c, const T& a) { if constexpr (is_same()) { c->write(a); } else if constexpr (requires { StringView(a); }) { StringView v(a); auto iter = v.begin(); c->write(iter); } else if constexpr (requires { IntegerView(a); }) { IntegerView v(a); auto iter = v.begin(); c->write(iter); } else c->write(a); } template void print_c(Console* console, const T& a, const Args&... x) { print_c(console, a); print_c(console, x...); } template void printk(const T& a, const Args&... x) { auto iter = Console::begin(); while (iter) { auto* c = iter.next(); print_c(c, a, x...); c->update_cursor(); } } extern "C" __attribute__((__noreturn__)) void abort(); #define runtime_assert(x, msg) \ if (!x) { \ printk(__FILE__, ':', __LINE__, ' ', msg); \ abort(); \ }