#include "deimos/core/format.h" #include "deimos/core/io.h" #include // NOLINT #include // NOLINT namespace deimos { class FormatContext { IWriter* m_writer; public: explicit FormatContext(IWriter* writer) : m_writer{writer} {} void PushChar(char c) { m_writer->Write(AsBytes(Span(&c, 1))); } void PushString(StringView str) { m_writer->Write(AsBytes(str)); } void PushUnsignedInteger(int64_t value) { char buffer[64]; const int size = snprintf(&buffer[0], 64, "%" PRIu64, value); PushString({ &buffer[0], size }); } void PushInteger(int64_t value) { char buffer[64]; const int size = snprintf(&buffer[0], 64, "%" PRIi64, value); PushString({ &buffer[0], size }); } void PushArg(const FormatArg& arg) { switch (arg.type) { case FormatArg::kString: PushString(arg.string); break; case FormatArg::kInteger: PushInteger(arg.integer); break; case FormatArg::kUnsignedInteger: PushUnsignedInteger(arg.integer); break; case FormatArg::kCustom: arg.custom.callback(m_writer, arg.custom.payload); break; } } }; void FormatVa(IWriter* writer, gsl::czstring fmt, Span args) { if (fmt == nullptr) { return; } const FormatArg* arg = args.begin(); const FormatArg* const end_arg = args.end(); FormatContext ctx(writer); while (*fmt != '\0') { if (*fmt == '$' && arg < end_arg) { ctx.PushArg(*arg++); // NOLINT } else { ctx.PushChar(*fmt); } fmt += 1; } } } // namespace deimos