summaryrefslogtreecommitdiff
path: root/deimos/core/format.cpp
blob: b9a0ca39b92b81d1e5c72036b18820580feaf4d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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