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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
#ifndef KSTD_BITS_FORMAT_VFORMAT_HPP
#define KSTD_BITS_FORMAT_VFORMAT_HPP
// IWYU pragma: private, include <kstd/format.hpp>
#include <kstd/bits/basic_string.hpp>
#include <kstd/bits/format/args.hpp>
#include <kstd/bits/format/output_buffer.hpp>
#include <kstd/bits/format/string.hpp>
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <span>
#include <string_view>
#include <type_traits>
#include <utility>
namespace kstd
{
namespace bits::format
{
//! Format a string with the given arguments into the given buffer.
//!
//! External implementations of `vprint` may call this function.
//!
//! @param buffer The buffer to format into.
//! @param format The format string to use.
//! @param args The arguments for the format string.
auto vformat_to(output_buffer & buffer, std::string_view format, format_args args) -> void;
struct string_writer final : output_buffer
{
auto push(std::string_view text) -> void final;
auto push(char character) -> void final;
auto release() -> basic_string<char> &&;
private:
basic_string<char> m_result{};
};
//! A buffer that merely records the size of the output written to it.
struct size_recorder final : output_buffer
{
auto push(std::string_view text) -> void final;
auto push(char character) -> void final;
[[nodiscard]] auto size() const noexcept -> std::size_t;
private:
std::size_t m_size{};
};
template<std::output_iterator<char> Output>
struct iterator_writer final : output_buffer
{
constexpr explicit iterator_writer(Output iterator)
: m_output{iterator}
{}
[[nodiscard]] auto iterator() const -> Output
{
return m_output;
}
auto push(std::string_view text) -> void override
{
m_output = std::ranges::copy(text, m_output).out;
}
auto push(char character) -> void override
{
*m_output++ = character;
}
private:
Output m_output{};
};
struct span_writer final : output_buffer
{
constexpr explicit span_writer(std::span<char> span)
: m_span{span}
{}
auto push(std::string_view text) -> void override;
auto push(char character) -> void override;
[[nodiscard]] constexpr auto position() const noexcept -> std::size_t
{
return m_position;
}
private:
std::size_t m_position{};
std::span<char> m_span{};
};
} // namespace bits::format
//! Format a given string with the provided arguments.
//!
//! @param format The format string.
//! @param args The arguments for the format string.
//! @return A new string containing the result of the format operation.
template<typename... ArgumentTypes>
auto format(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
-> basic_string<char>
{
auto buffer = bits::format::string_writer{};
bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
return buffer.release();
}
//! Format a given string with the provided arguments.
//!
//! @param iterator The iterator to write to.
//! @param format The format string.
//! @param args The arguments for the format string.
//! @return An iterator past the last element written.
template<std::output_iterator<char> Output, typename... ArgumentTypes>
auto format_to(Output iterator, format_string<std::type_identity_t<ArgumentTypes>...> format,
ArgumentTypes &&... args) -> Output
{
auto buffer = bits::format::iterator_writer{iterator};
bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
return buffer.iterator();
}
//! Format a given string with the provided arguments.
//!
//! @param span The span to write to.
//! @param format The format string.
//! @param args The arguments for the format string.
//! @return A pair of the span written to and the next position to write to.
template<typename... ArgumentTypes>
auto format_to(std::span<char> span, format_string<std::type_identity_t<ArgumentTypes>...> format,
ArgumentTypes &&... args) -> std::pair<std::span<char>, std::size_t>
{
auto buffer = bits::format::span_writer{span};
bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
return {span, buffer.position()};
}
//! Determine the number of characters required to format the format string with the given arguments.
//!
//! @param format The format string.
//! @param args The arguments for the format string.
//! @tparam ArgumentTypes The type of the format string arguments.
//! @return The number of characters required to format @p format with @p args
template<typename... ArgumentTypes>
auto formatted_size(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
-> std::size_t
{
auto buffer = bits::format::size_recorder{};
bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
return buffer.size();
}
} // namespace kstd
#endif
|