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
|
#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 <string_view>
#include <type_traits>
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 : 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 : 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 : output_buffer
{
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{};
};
} // 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();
}
//! 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
|