summaryrefslogtreecommitdiff
path: root/deimos/core/format.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deimos/core/format.cpp')
-rw-r--r--deimos/core/format.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/deimos/core/format.cpp b/deimos/core/format.cpp
new file mode 100644
index 0000000..f4f4e83
--- /dev/null
+++ b/deimos/core/format.cpp
@@ -0,0 +1,83 @@
+#include "deimos/core/format.h"
+#include "deimos/core/io.h"
+
+#include <stdio.h> // NOLINT
+#include <inttypes.h> // 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<char>(&c, 1)));
+ }
+
+ void PushString(Span<const char> 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;
+ }
+ }
+};
+
+void FormatVa(IWriter* writer, gsl::czstring fmt, Span<const FormatArg> 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
+