include/boost/beast2/format.hpp

97.7% Lines (84/86) 100.0% List of functions (27/27) 95.8% Branches (46/48)
format.hpp
f(x) Functions (27)
Function Calls Lines Branches Blocks
boost::beast2::detail::format_impl::format_impl(std::ostream&, boost::core::basic_string_view<char>) :36 27x 100.0% – 100.0% boost::beast2::detail::format_impl::next() :48 57x 97.3% 95.0% 89.0% void boost::beast2::detail::format_impl::do_arg<char [2]>(char const (&) [2]) :111 17x 100.0% 100.0% 100.0% void boost::beast2::detail::format_impl::do_arg<char [6]>(char const (&) [6]) :111 2x 90.0% 60.0% 87.0% void boost::beast2::detail::format_impl::do_arg<char>(char const&) :111 1x 60.0% 40.0% 53.0% void boost::beast2::detail::format_impl::operator()<>() :126 10x 100.0% 100.0% 100.0% void boost::beast2::detail::format_impl::operator()<char [2], char [2], char [2]>(char const (&) [2], char const (&) [2], char const (&) [2]) :126 1x 80.0% 63.6% 57.0% void boost::beast2::detail::format_impl::operator()<char [2], char [2]>(char const (&) [2], char const (&) [2]) :126 1x 90.0% 90.0% 75.0% void boost::beast2::detail::format_impl::operator()<char [2]>(char const (&) [2]) :126 12x 90.0% 66.7% 79.0% void boost::beast2::detail::format_impl::operator()<char [6]>(char const (&) [6]) :126 2x 90.0% 88.9% 74.0% void boost::beast2::detail::format_impl::operator()<char>(char const&) :126 1x 80.0% 55.6% 53.0% boost::beast2::detail::appendbuf::overflow(int) :151 1x 80.0% 50.0% 83.0% boost::beast2::detail::appendbuf::xsputn(char const*, long) :162 32x 100.0% – 100.0% boost::beast2::detail::appendbuf::appendbuf(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) :169 27x 100.0% – 100.0% boost::beast2::detail::appendstream::appendstream(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) :180 27x 100.0% 100.0% 62.0% void boost::beast2::format_to<>(std::ostream&, boost::core::basic_string_view<char>) :193 10x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [2], char [2], char [2]>(std::ostream&, boost::core::basic_string_view<char>, char const (&) [2], char const (&) [2], char const (&) [2]) :193 1x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [2], char [2]>(std::ostream&, boost::core::basic_string_view<char>, char const (&) [2], char const (&) [2]) :193 1x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [2]>(std::ostream&, boost::core::basic_string_view<char>, char const (&) [2]) :193 12x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [6]>(std::ostream&, boost::core::basic_string_view<char>, char const (&) [6]) :193 2x 100.0% 100.0% 100.0% void boost::beast2::format_to<char>(std::ostream&, boost::core::basic_string_view<char>, char const&) :193 1x 100.0% 100.0% 100.0% void boost::beast2::format_to<>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>) :205 10x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [2], char [2], char [2]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>, char const (&) [2], char const (&) [2], char const (&) [2]) :205 1x 100.0% 100.0% 71.0% void boost::beast2::format_to<char [2], char [2]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>, char const (&) [2], char const (&) [2]) :205 1x 100.0% 100.0% 71.0% void boost::beast2::format_to<char [2]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>, char const (&) [2]) :205 12x 100.0% 100.0% 100.0% void boost::beast2::format_to<char [6]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>, char const (&) [6]) :205 2x 100.0% 100.0% 71.0% void boost::beast2::format_to<char>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, boost::core::basic_string_view<char>, char const&) :205 1x 100.0% 100.0% 71.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/beast2
8 //
9
10 #ifndef BOOST_BEAST2_FORMAT_HPP
11 #define BOOST_BEAST2_FORMAT_HPP
12
13 #include <boost/beast2/detail/config.hpp>
14 #include <boost/beast2/detail/except.hpp>
15 #include <boost/core/detail/string_view.hpp>
16
17 #include <memory>
18 #include <ostream>
19 #include <streambuf>
20 #include <string>
21
22 namespace boost {
23 namespace beast2 {
24
25 namespace detail {
26
27 struct format_impl
28 {
29 std::ostream& os;
30 core::string_view fs;
31 char const* p;
32 char const* p0;
33 char const* end;
34 bool has_placeholder = false;
35
36 27x format_impl(
37 std::ostream& os_,
38 core::string_view fs_)
39 27x : os(os_)
40 27x , fs(fs_)
41 27x , p(fs.data())
42 27x , p0(p)
43 27x , end(p + fs.size())
44 {
45 27x }
46
47 core::string_view
48 57x next()
49 {
50 57x has_placeholder = false;
51 57x bool unmatched_open = false;
52 57x bool unmatched_close = false;
53
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 31 times.
116x while (p != end)
54 {
55
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 67 times.
85x if(unmatched_open)
56 {
57
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13 times.
18x if(*p == '{')
58 {
59 5x p++;
60 5x core::string_view seg(p0, (p - 1) - p0);
61 5x p0 = p;
62 5x return seg;
63 }
64
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13x if(*p == '}')
65 {
66 13x p++;
67 13x core::string_view seg(p0, (p - 2) - p0);
68 13x p0 = p;
69 13x has_placeholder = true;
70 13x return seg;
71 }
72 ✗ detail::throw_invalid_argument(
73 "invalid format string, unmatched {");
74 }
75
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 59 times.
67x if(unmatched_close)
76 {
77
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8x if(*p == '}')
78 {
79 5x p++;
80 5x core::string_view seg(p0, (p - 1) - p0);
81 5x p0 = p;
82 5x return seg;
83 }
84 3x detail::throw_invalid_argument(
85 "invalid format string, unmatched }");
86 }
87
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 38 times.
59x if (*p == '{')
88 {
89 21x unmatched_open = true;
90 }
91
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 48 times.
59x if(*p == '}')
92 {
93 11x unmatched_close = true;
94 }
95 59x p++;
96 }
97
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 28 times.
31x if (unmatched_open)
98 3x detail::throw_invalid_argument(
99 "invalid format string, unmatched {");
100
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 25 times.
28x if(unmatched_close)
101 3x detail::throw_invalid_argument(
102 "invalid format string, unmatched }");
103
104 core::string_view seg(
105 25x p0, end - p0);
106 25x p0 = end;
107 25x return seg;
108 }
109
110 template<class Arg>
111 20x void do_arg(Arg const& arg)
112 {
113
1/1
✓ Branch 1 taken 14 times.
20x core::string_view seg = next();
114
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 7 times.
19x while(seg.size())
115 {
116
1/1
✓ Branch 3 taken 12 times.
12x os.write(seg.data(), static_cast<std::streamsize>(seg.size()));
117
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12x if(has_placeholder)
118 7x break;
119
1/1
✓ Branch 1 taken 5 times.
5x seg = next();
120 }
121
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14x if(has_placeholder)
122
1/1
✓ Branch 1 taken 10 times.
10x os << arg;
123 14x };
124
125 template<class... Args>
126 27x void operator()(Args const&... args)
127 {
128 using expander = int[];
129
3/3
✓ Branch 1 taken 11 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 1 time.
27x (void)expander{0, (do_arg(args), 0)...};
130
131 21x core::string_view seg;
132 do
133 {
134
1/1
✓ Branch 1 taken 29 times.
32x seg = next();
135
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 26 times.
29x if(has_placeholder)
136 3x detail::throw_invalid_argument(
137 "too few format arguments provided");
138
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 15 times.
26x if(seg.size())
139
1/1
✓ Branch 3 taken 11 times.
11x os.write(seg.data(), static_cast<std::streamsize>(seg.size()));
140 }
141
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 15 times.
26x while(seg.size());
142 15x }
143 };
144
145 class appendbuf : public std::streambuf
146 {
147 std::string* s_;
148
149 protected:
150 // Called when a single character is to be written
151 1x virtual int_type overflow(int_type ch) override
152 {
153
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1x if (ch != traits_type::eof())
154 {
155 1x s_->push_back(static_cast<char>(ch));
156 1x return ch;
157 }
158 ✗ return traits_type::eof();
159 }
160
161 // Called when multiple characters are to be written
162 32x virtual std::streamsize xsputn(const char* s, std::streamsize n) override
163 {
164 32x s_->append(s, static_cast<std::size_t>(n));
165 32x return n;
166 }
167
168 public:
169 27x explicit appendbuf(std::string& s)
170 27x : s_(&s)
171 {
172 27x }
173 };
174
175 class appendstream : public std::ostream
176 {
177 appendbuf buf_;
178
179 public:
180 27x explicit appendstream(std::string& s)
181 27x : std::ostream(&buf_)
182
2/2
✓ Branch 2 taken 27 times.
✓ Branch 5 taken 27 times.
27x , buf_(s)
183 {
184 27x }
185 };
186
187 } // detail
188
189 /** Format arguments using a format string
190 */
191 template<class... Args>
192 void
193 27x format_to(
194 std::ostream& os,
195 core::string_view fs,
196 Args const&... args)
197 {
198
1/1
✓ Branch 2 taken 15 times.
27x detail::format_impl(os, fs)(args...);
199 15x }
200
201 /** Format arguments using a format string
202 */
203 template<class... Args>
204 void
205 27x format_to(
206 std::string& dest,
207 core::string_view fs,
208 Args const&... args)
209 {
210
1/1
✓ Branch 1 taken 27 times.
27x detail::appendstream ss(dest);
211
1/1
✓ Branch 1 taken 15 times.
27x format_to(ss, fs, args...);
212 27x }
213
214 } // beast2
215 } // boost
216
217 #endif
218