GCC Code Coverage Report


Directory: libs/url/
File: boost/url/detail/format_args.hpp
Date: 2024-03-15 21:27:27
Exec Total Coverage
Lines: 85 85 100.0%
Functions: 102 102 100.0%
Branches: 7 8 87.5%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.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/boostorg/url
8 //
9
10 #ifndef BOOST_URL_DETAIL_FORMAT_ARGS_HPP
11 #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
12
13 #include <boost/url/detail/encode.hpp>
14 #include <boost/url/grammar/lut_chars.hpp>
15
16 #include <boost/core/ignore_unused.hpp>
17 #include <array>
18
19 // This file implements functions and classes to
20 // type-erase format arguments.
21
22 namespace boost {
23 namespace urls {
24 namespace detail {
25
26 // state of the format string. It basically keeps
27 // track of where we are in the format string.
28 class format_parse_context
29 {
30 char const* begin_;
31 char const* end_;
32 std::size_t arg_id_ = 0;
33
34 public:
35 constexpr
36 632 format_parse_context(
37 char const* first,
38 char const* last,
39 std::size_t arg_id = 0)
40 632 : begin_( first )
41 , end_( last )
42 632 , arg_id_( arg_id )
43 632 {}
44
45 constexpr
46 495 format_parse_context(
47 core::string_view fmt,
48 std::size_t arg_id = 0)
49 495 : format_parse_context(
50 fmt.data(),
51 495 fmt.data() + fmt.size(),
52 495 arg_id )
53 495 {}
54
55 constexpr
56 char const*
57 1445 begin() const noexcept
58 {
59 1445 return begin_;
60 }
61
62 constexpr
63 char const*
64 971 end() const noexcept
65 {
66 971 return end_;
67 }
68
69 BOOST_CXX14_CONSTEXPR
70 void
71 950 advance_to( char const* it )
72 {
73 950 begin_ = it;
74 950 }
75
76 std::size_t
77 871 next_arg_id()
78 {
79 871 return arg_id_++;
80 }
81 };
82
83 // State of the destination string
84 class format_context;
85 class measure_context;
86 struct ignore_format {};
87
88 template <class T>
89 struct named_arg
90 {
91 core::string_view name;
92 T const& value;
93
94 37 named_arg(core::string_view n, T const& v)
95 : name(n)
96 37 , value(v)
97 37 {}
98 };
99
100 // A type erased format argument
101 class format_arg
102 {
103 void const* arg_;
104 void (*measure_)(
105 format_parse_context&,
106 measure_context&,
107 grammar::lut_chars const&,
108 void const* );
109 void (*fmt_)(
110 format_parse_context&,
111 format_context&,
112 grammar::lut_chars const&,
113 void const* );
114 core::string_view name_;
115 std::size_t value_ = 0;
116 bool ignore_ = false;
117
118 template <class A>
119 static
120 void
121 measure_impl(
122 format_parse_context& pctx,
123 measure_context& mctx,
124 grammar::lut_chars const& cs,
125 void const* a );
126
127 template <class A>
128 static
129 void
130 format_impl(
131 format_parse_context& pctx,
132 format_context& fctx,
133 grammar::lut_chars const& cs,
134 void const* a );
135
136 public:
137 template<class A>
138 format_arg( A&& a );
139
140 template<class A>
141 format_arg( named_arg<A>&& a );
142
143 template<class A>
144 format_arg( core::string_view name, A&& a );
145
146 34 format_arg()
147
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 : format_arg(ignore_format{})
148 34 {}
149
150 explicit
151 operator bool() const noexcept
152 {
153 return !ignore_;
154 }
155
156 void
157 240 measure(
158 format_parse_context& pctx,
159 measure_context& mctx,
160 grammar::lut_chars const& cs)
161 {
162 240 measure_( pctx, mctx, cs, arg_ );
163 238 }
164
165 void
166 236 format(
167 format_parse_context& pctx,
168 format_context& fctx,
169 grammar::lut_chars const& cs )
170 {
171 236 fmt_( pctx, fctx, cs, arg_ );
172 236 }
173
174 core::string_view
175 130 name() const
176 {
177 130 return name_;
178 }
179
180 std::size_t
181 28 value() const
182 {
183 28 return value_;
184 }
185 };
186
187 // create temp stack storage for type erased args
188 template< class... Args >
189 std::array<format_arg, sizeof...(Args)>
190 288 make_format_args( Args&&... args )
191 {
192 288 return {{ std::forward<Args>(args)... }};
193 }
194
195 // reference to an array of format_args
196 class format_args
197 {
198 format_arg const* p_{nullptr};
199 std::size_t n_{0};
200
201 public:
202 3 format_args(
203 detail::format_arg const* first,
204 detail::format_arg const* last ) noexcept
205 3 : p_(first)
206 3 , n_(static_cast<std::size_t>(last - first))
207 3 {}
208
209 template < std::size_t N >
210 288 format_args( std::array<format_arg, N> const& store ) noexcept
211 : p_(store.data())
212 288 , n_(store.size())
213 288 {}
214
215 format_arg
216 442 get( std::size_t i ) const noexcept
217 {
218
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 4 times.
442 if (i < n_)
219 438 return p_[i];
220 4 return {};
221 }
222
223 format_arg
224 62 get( core::string_view name ) const noexcept
225 {
226
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 2 times.
132 for (std::size_t i = 0; i < n_; ++i)
227 {
228
2/2
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 70 times.
130 if (p_[i].name() == name)
229 60 return p_[i];
230 }
231 2 return {};
232 }
233 };
234
235 // define the format_context after format_args
236 class format_context
237 {
238 format_args args_;
239 char* out_;
240
241 public:
242 137 format_context(
243 char* out,
244 format_args args )
245 137 : args_( args )
246 137 , out_( out )
247 137 {}
248
249 format_args
250 14 args() const noexcept
251 {
252 14 return args_;
253 }
254
255 format_arg
256 210 arg( std::size_t id ) const noexcept
257 {
258 210 return args_.get( id );
259 }
260
261 format_arg
262 26 arg( core::string_view name ) const noexcept
263 {
264 26 return args_.get( name );
265 }
266
267 char*
268 939 out()
269 {
270 939 return out_;
271 }
272
273 void
274 939 advance_to( char* it )
275 {
276 939 out_ = it;
277 939 }
278 };
279
280 // define the measure_context after format_args
281 class measure_context
282 {
283 format_args args_;
284 std::size_t out_;
285
286 public:
287 140 measure_context(
288 format_args args )
289 140 : measure_context(0, args)
290 140 {}
291
292 140 measure_context(
293 std::size_t out,
294 format_args args )
295 140 : args_( args )
296 140 , out_( out )
297 140 {}
298
299 format_args
300 14 args() const noexcept
301 {
302 14 return args_;
303 }
304
305 format_arg
306 214 arg( std::size_t id ) const noexcept
307 {
308 214 return args_.get( id );
309 }
310
311 format_arg
312 26 arg( core::string_view name ) const noexcept
313 {
314 26 return args_.get( name );
315 }
316
317 std::size_t
318 953 out()
319 {
320 953 return out_;
321 }
322
323 void
324 953 advance_to( std::size_t n )
325 {
326 953 out_ = n;
327 953 }
328 };
329
330 // fwd declare the formatter
331 template <class T, class = void>
332 struct formatter;
333
334 } // detail
335 } // url
336 } // boost
337
338 #include <boost/url/detail/impl/format_args.hpp>
339
340 #endif
341