From f011d871ef3af26c8f4e19de2c8d781c601ceffb Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Fri, 11 Oct 2024 00:32:49 +0200 Subject: Add console printing --- asl/BUILD.bazel | 3 +++ asl/format.cpp | 12 ++++++++++++ asl/format.hpp | 40 +++++++++++++++------------------------- asl/format_tests.cpp | 4 ++++ asl/io.hpp | 20 ++++++++++++++++++++ asl/print.hpp | 31 +++++++++++++++++++++++++++++++ asl/print_win32.cpp | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 asl/io.hpp create mode 100644 asl/print.hpp create mode 100644 asl/print_win32.cpp diff --git a/asl/BUILD.bazel b/asl/BUILD.bazel index 5137c8f..f904624 100644 --- a/asl/BUILD.bazel +++ b/asl/BUILD.bazel @@ -5,15 +5,18 @@ cc_library( "assert.hpp", "format.hpp", "integers.hpp", + "io.hpp", "layout.hpp", "maybe_uninit.hpp", "memory.hpp", "meta.hpp", "option.hpp", + "print.hpp", "utility.hpp", ], srcs = [ "format.cpp", + "print_win32.cpp", ], visibility = ["//visibility:public"], ) diff --git a/asl/format.cpp b/asl/format.cpp index eb653e9..ff565bd 100644 --- a/asl/format.cpp +++ b/asl/format.cpp @@ -80,6 +80,18 @@ void asl::AslFormat(formatter& f, double) f.write("", 8); // @Todo Float formatting } +void asl::AslFormat(formatter& f, bool v) +{ + if (v) + { + f.write("true", 4); + } + else + { + f.write("false", 5); + } +} + void asl::AslFormat(formatter& f, uint8_t v) { AslFormat(f, static_cast(v)); diff --git a/asl/format.hpp b/asl/format.hpp index f17329f..b4cb439 100644 --- a/asl/format.hpp +++ b/asl/format.hpp @@ -2,23 +2,11 @@ #include "asl/integers.hpp" #include "asl/meta.hpp" -#include "asl/utility.hpp" +#include "asl/io.hpp" namespace asl { -// @Todo Move this to io -class writer -{ -public: - writer() = default; - ASL_DELETE_COPY_MOVE(writer); - virtual ~writer() = default; - - // @Todo Use string view, or span of bytes? - virtual void write(const char* str, int64_t len) = 0; -}; - class formatter; template @@ -70,21 +58,21 @@ public: }; // @Todo Use string_view -template +template void format(writer* w, const char* fmt, const Args&... args) { - format_internals::type_erased_arg type_erased_args[] = { - format_internals::type_erased_arg(args)... - }; - - // @Todo Use array extent - format_internals::format(w, fmt, type_erased_args, types_count); -} + if constexpr (types_count > 0) + { + format_internals::type_erased_arg type_erased_args[] = { + format_internals::type_erased_arg(args)... + }; -// @Todo Use string_view -inline void format(writer* w, const char* fmt) -{ - format_internals::format(w, fmt, nullptr, 0); + format_internals::format(w, fmt, type_erased_args, types_count); + } + else + { + format_internals::format(w, fmt, nullptr, 0); + } } template @@ -96,6 +84,8 @@ void AslFormat(formatter& f, const char (&str)[N]) void AslFormat(formatter& f, float); void AslFormat(formatter& f, double); +void AslFormat(formatter& f, bool); + void AslFormat(formatter& f, uint8_t); void AslFormat(formatter& f, uint16_t); void AslFormat(formatter& f, uint32_t); diff --git a/asl/format_tests.cpp b/asl/format_tests.cpp index 55ed97b..818773b 100644 --- a/asl/format_tests.cpp +++ b/asl/format_tests.cpp @@ -98,5 +98,9 @@ int main() asl::format(&sink, "{} {} {} {}", -1, -23, -456, -7890); assert(strcmp(sink.cstr(), "-1 -23 -456 -7890") == 0); + sink.reset(); + asl::format(&sink, "{} {}", true, false); + assert(strcmp(sink.cstr(), "true false") == 0); + return 0; } diff --git a/asl/io.hpp b/asl/io.hpp new file mode 100644 index 0000000..79c70c2 --- /dev/null +++ b/asl/io.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "asl/integers.hpp" +#include "asl/utility.hpp" + +namespace asl +{ + +class writer +{ +public: + writer() = default; + ASL_DELETE_COPY_MOVE(writer); + virtual ~writer() = default; + + // @Todo Use string view, or span of bytes? + virtual void write(const char* str, int64_t len) = 0; +}; + +} // namespace asl diff --git a/asl/print.hpp b/asl/print.hpp new file mode 100644 index 0000000..d82d52b --- /dev/null +++ b/asl/print.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "asl/format.hpp" + +namespace asl +{ + +namespace print_internals +{ + +// @Todo Make print writers thread safe +writer* get_stdout_writer(); +writer* get_stderr_writer(); + +} // namespace print_internals + +// @Todo Use string_view +template +void print(const char* fmt, const Args&... args) +{ + format(print_internals::get_stdout_writer(), fmt, args...); +} + +// @Todo Use string_view +template +void eprint(const char* fmt, const Args&... args) +{ + format(print_internals::get_stderr_writer(), fmt, args...); +} + +} // namespace asl diff --git a/asl/print_win32.cpp b/asl/print_win32.cpp new file mode 100644 index 0000000..45939b2 --- /dev/null +++ b/asl/print_win32.cpp @@ -0,0 +1,33 @@ +#include "asl/print.hpp" + +#define WIN32_LEAN_AND_MEAN +#include + +// @Todo Optimize this, maybe make buffered +class Win32ConsoleWriter : public asl::writer +{ + HANDLE m_handle; + +public: + explicit Win32ConsoleWriter(HANDLE handle) + : m_handle{handle} + {} + + void write(const char* str, int64_t len) override + { + ::WriteConsoleA(m_handle, str, static_cast(len), nullptr, nullptr); + } +}; + +asl::writer* asl::print_internals::get_stdout_writer() +{ + static Win32ConsoleWriter writer{::GetStdHandle(STD_OUTPUT_HANDLE)}; + return &writer; +} + +asl::writer* asl::print_internals::get_stderr_writer() +{ + static Win32ConsoleWriter writer{::GetStdHandle(STD_ERROR_HANDLE)}; + return &writer; +} + -- cgit