GCC Code Coverage Report


Directory: libs/url/
File: libs/url/src/detail/format_args.cpp
Date: 2024-08-19 20:08:56
Exec Total Coverage
Lines: 304 304 100.0%
Functions: 11 11 100.0%
Branches: 233 272 85.7%

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
11 #include <boost/url/detail/config.hpp>
12 #include <boost/url/encode.hpp>
13 #include <boost/url/detail/format_args.hpp>
14 #include "boost/url/detail/replacement_field_rule.hpp"
15 #include <boost/url/grammar/delim_rule.hpp>
16 #include <boost/url/grammar/optional_rule.hpp>
17 #include <boost/url/grammar/parse.hpp>
18 #include <boost/url/grammar/tuple_rule.hpp>
19 #include <boost/url/grammar/unsigned_rule.hpp>
20
21 namespace boost {
22 namespace urls {
23 namespace detail {
24
25 std::size_t
26 68 get_uvalue( core::string_view a )
27 {
28 68 core::string_view str(a);
29 68 auto rv = grammar::parse(
30 68 str, grammar::unsigned_rule<std::size_t>{});
31
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 66 times.
68 if (rv)
32 2 return *rv;
33 66 return 0;
34 }
35
36 std::size_t
37 68 get_uvalue( char a )
38 {
39 68 core::string_view str(&a, 1);
40
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
136 return get_uvalue(str);
41 }
42
43 char const*
44 369 formatter<core::string_view>::
45 parse(format_parse_context& ctx)
46 {
47 369 char const* it = ctx.begin();
48 369 char const* end = ctx.end();
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
369 BOOST_ASSERT(it != end);
50
51 // fill / align
52
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 262 times.
369 if (end - it > 2)
53 {
54
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if (*it != '{' &&
55
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 86 times.
107 *it != '}' &&
56
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2 times.
21 (*(it + 1) == '<' ||
57
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 12 times.
19 *(it + 1) == '>' ||
58
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 *(it + 1) == '^'))
59 {
60 16 fill = *it;
61 16 align = *(it + 1);
62 16 it += 2;
63 }
64 }
65
66 // align
67
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 16 times.
369 if (align == '\0' &&
68
1/2
✓ Branch 0 taken 353 times.
✗ Branch 1 not taken.
353 (*it == '<' ||
69
1/2
✓ Branch 0 taken 353 times.
✗ Branch 1 not taken.
353 *it == '>' ||
70
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 349 times.
353 *it == '^'))
71 {
72 4 align = *it++;
73 }
74
75 // width
76 369 char const* it0 = it;
77 369 constexpr auto width_rule =
78 grammar::variant_rule(
79 grammar::unsigned_rule<std::size_t>{},
80 grammar::tuple_rule(
81 grammar::squelch(
82 grammar::delim_rule('{')),
83 grammar::optional_rule(
84 arg_id_rule),
85 grammar::squelch(
86 grammar::delim_rule('}'))));
87
1/2
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
369 auto rw = grammar::parse(it, end, width_rule);
88
2/2
✓ Branch 1 taken 349 times.
✓ Branch 2 taken 20 times.
369 if (!rw)
89 {
90 // rewind
91 349 it = it0;
92 }
93
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 else if (align != '\0')
94 {
95 // width is ignored when align is '\0'
96
2/2
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
20 if (rw->index() == 0)
97 {
98 // unsigned_rule
99
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 width = variant2::get<0>(*rw);
100 }
101 else
102 {
103 // arg_id: store the id idx or string
104
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 auto& arg_id = variant2::get<1>(*rw);
105
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 if (!arg_id)
106 {
107 // empty arg_id, use and consume
108 // the next arg idx
109 2 width_idx = ctx.next_arg_id();
110 }
111
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
8 else if (arg_id->index() == 0)
112 {
113 // string identifier
114
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 width_name = variant2::get<0>(*arg_id);
115 }
116 else
117 {
118 // integer identifier: use the
119 // idx of this format_arg
120
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 width_idx = variant2::get<1>(*arg_id);
121 }
122 }
123 }
124
125 // type is parsed but doesn't have to
126 // be stored for strings
127
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 3 times.
369 if (*it == 'c' ||
128
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 346 times.
366 *it == 's')
129 {
130 23 ++it;
131 }
132
133 // we should have arrived at the end now
134
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 368 times.
369 if (*it != '}')
135 {
136 1 urls::detail::throw_invalid_argument();
137 }
138
139 368 return it;
140 369 }
141
142 std::size_t
143 185 formatter<core::string_view>::
144 measure(
145 core::string_view str,
146 measure_context& ctx,
147 grammar::lut_chars const& cs) const
148 {
149 185 std::size_t w = width;
150
4/4
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 180 times.
367 if (width_idx != std::size_t(-1) ||
151
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 180 times.
182 !width_name.empty())
152 {
153 5 get_width_from_args(
154
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 width_idx, width_name, ctx.args(), w);
155 }
156
157 185 std::size_t n = ctx.out();
158
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 176 times.
185 if (str.size() < w)
159 9 n += measure_one(fill, cs) * (w - str.size());
160
161 185 return n + encoded_size(str, cs);
162 }
163
164 char*
165 183 formatter<core::string_view>::
166 format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
167 {
168 183 std::size_t w = width;
169
4/4
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 178 times.
363 if (width_idx != std::size_t(-1) ||
170
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 178 times.
180 !width_name.empty())
171 {
172 5 get_width_from_args(
173
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 width_idx, width_name, ctx.args(), w);
174 }
175
176 183 std::size_t lpad = 0;
177 183 std::size_t rpad = 0;
178
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 174 times.
183 if (str.size() < w)
179 {
180 9 std::size_t pad = w - str.size();
181
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
9 switch (align)
182 {
183 1 case '<':
184 1 rpad = pad;
185 1 break;
186 6 case '>':
187 6 lpad = pad;
188 6 break;
189 2 case '^':
190 2 lpad = w / 2;
191 2 rpad = pad - lpad;
192 2 break;
193 }
194 }
195
196 // unsafe `encode`, assuming `out` has
197 // enough capacity
198 183 char* out = ctx.out();
199
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 183 times.
210 for (std::size_t i = 0; i < lpad; ++i)
200 27 encode_one(out, fill, cs);
201
2/2
✓ Branch 2 taken 695 times.
✓ Branch 3 taken 183 times.
878 for (char c: str)
202 695 encode_one(out, c, cs);
203
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 183 times.
190 for (std::size_t i = 0; i < rpad; ++i)
204 7 encode_one(out, fill, cs);
205 183 return out;
206 }
207
208 void
209 28 get_width_from_args(
210 std::size_t arg_idx,
211 core::string_view arg_name,
212 format_args args,
213 std::size_t& w)
214 {
215 // check arg_id
216
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 format_arg warg;
217
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10 times.
28 if (arg_idx != std::size_t(-1))
218 {
219 // identifier
220 18 warg = args.get(arg_idx);
221 }
222 else
223 {
224 // unsigned integer
225 10 warg = args.get(arg_name);
226 }
227
228 // get unsigned int value from that format arg
229 28 w = warg.value();
230 28 }
231
232 char const*
233 97 integer_formatter_impl::
234 parse(format_parse_context& ctx)
235 {
236 97 char const* it = ctx.begin();
237 97 char const* end = ctx.end();
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 BOOST_ASSERT(it != end);
239
240 // fill / align
241
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 40 times.
97 if (end - it > 2)
242 {
243
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 if (*it != '{' &&
244
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 4 times.
57 *it != '}' &&
245
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 4 times.
53 (*(it + 1) == '<' ||
246
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 22 times.
49 *(it + 1) == '>' ||
247
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 23 times.
27 *(it + 1) == '^'))
248 {
249 30 fill = *it;
250 30 align = *(it + 1);
251 30 it += 2;
252 }
253 }
254
255 // align
256
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 30 times.
97 if (align == '\0' &&
257
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 (*it == '<' ||
258
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 8 times.
67 *it == '>' ||
259
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 55 times.
59 *it == '^'))
260 {
261 12 align = *it++;
262 }
263
264 // sign
265
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 6 times.
97 if (*it == '+' ||
266
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 *it == '-' ||
267
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 85 times.
91 *it == ' ')
268 {
269 12 sign = *it++;
270 }
271
272 // #
273
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 95 times.
97 if (*it == '#')
274 {
275 // alternate form not supported
276 2 ++it;
277 }
278
279 // 0
280
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 89 times.
97 if (*it == '0')
281 {
282 8 zeros = *it++;
283 }
284
285 // width
286 97 char const* it0 = it;
287 97 constexpr auto width_rule = grammar::variant_rule(
288 grammar::unsigned_rule<std::size_t>{},
289 grammar::tuple_rule(
290 grammar::squelch(
291 grammar::delim_rule('{')),
292 grammar::optional_rule(
293 arg_id_rule),
294 grammar::squelch(
295 grammar::delim_rule('}'))));
296
1/2
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
97 auto rw = grammar::parse(it, end, width_rule);
297
2/2
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 42 times.
97 if (!rw)
298 {
299 // rewind
300 55 it = it0;
301 }
302
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 else if (align != '\0')
303 {
304 // width is ignored when align is '\0'
305
2/2
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 18 times.
42 if (rw->index() == 0)
306 {
307 // unsigned_rule
308
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 width = variant2::get<0>(*rw);
309 }
310 else
311 {
312 // arg_id: store the id idx or string
313
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 auto& arg_id = variant2::get<1>(*rw);
314
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 14 times.
18 if (!arg_id)
315 {
316 // empty arg_id, use and consume
317 // the next arg idx
318 4 width_idx = ctx.next_arg_id();
319 }
320
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 8 times.
14 else if (arg_id->index() == 0)
321 {
322 // string identifier
323
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 width_name = variant2::get<0>(*arg_id);
324 }
325 else
326 {
327 // integer identifier: use the
328 // idx of this format_arg
329
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 width_idx = variant2::get<1>(*arg_id);
330 }
331 }
332 }
333
334 // type is parsed but doesn't have to
335 // be stored for strings
336
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 42 times.
97 if (*it == 'd')
337 {
338 // we don't include other presentation
339 // modes for integers as they are not
340 // recommended or generally used in
341 // urls
342 55 ++it;
343 }
344
345 // we should have arrived at the end now
346
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 96 times.
97 if (*it != '}')
347 {
348 1 urls::detail::throw_invalid_argument();
349 }
350
351 96 return it;
352 97 }
353
354 std::size_t
355 34 integer_formatter_impl::
356 measure(
357 long long int v,
358 measure_context& ctx,
359 grammar::lut_chars const& cs) const
360 {
361 34 std::size_t dn = 0;
362 34 std::size_t n = 0;
363
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (v < 0)
364 {
365 1 dn += measure_one('-', cs);
366 1 ++n;
367 1 v *= -1;
368 }
369
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 29 times.
33 else if (sign != '-')
370 {
371 4 dn += measure_one(sign, cs);
372 4 ++n;
373 }
374 do
375 {
376 67 int d = v % 10;
377 67 v /= 10;
378 67 dn += measure_one('0' + static_cast<char>(d), cs);
379 67 ++n;
380 }
381
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 34 times.
67 while (v > 0);
382
383 34 std::size_t w = width;
384
4/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 29 times.
65 if (width_idx != std::size_t(-1) ||
385
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 29 times.
31 !width_name.empty())
386 {
387 5 get_width_from_args(
388
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 width_idx, width_name, ctx.args(), w);
389 }
390
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 22 times.
34 if (w > n)
391 {
392
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if (!zeros)
393 9 dn += measure_one(fill, cs) * (w - n);
394 else
395 3 dn += measure_one('0', cs) * (w - n);
396 }
397 34 return ctx.out() + dn;
398 }
399
400 std::size_t
401 14 integer_formatter_impl::
402 measure(
403 unsigned long long int v,
404 measure_context& ctx,
405 grammar::lut_chars const& cs) const
406 {
407 14 std::size_t dn = 0;
408 14 std::size_t n = 0;
409
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (sign != '-')
410 {
411 2 dn += measure_one(sign, cs);
412 2 ++n;
413 }
414 do
415 {
416 53 int d = v % 10;
417 53 v /= 10;
418 53 dn += measure_one('0' + static_cast<char>(d), cs);
419 53 ++n;
420 }
421
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 14 times.
53 while (v != 0);
422
423 14 std::size_t w = width;
424
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 10 times.
25 if (width_idx != std::size_t(-1) ||
425
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
11 !width_name.empty())
426 {
427 4 get_width_from_args(
428
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 width_idx, width_name, ctx.args(), w);
429 }
430
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (w > n)
431 {
432
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (!zeros)
433 7 dn += measure_one(fill, cs) * (w - n);
434 else
435 1 dn += measure_one('0', cs) * (w - n);
436 }
437 14 return ctx.out() + dn;
438 }
439
440 char*
441 34 integer_formatter_impl::
442 format(
443 long long int v,
444 format_context& ctx,
445 grammar::lut_chars const& cs) const
446 {
447 // get n digits
448 34 long long int v0 = v;
449 34 long long int p = 1;
450 34 std::size_t n = 0;
451
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (v < 0)
452 {
453 1 v *= - 1;
454 1 ++n;
455 }
456
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 29 times.
33 else if (sign != '-')
457 {
458 4 ++n;
459 }
460 do
461 {
462
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 34 times.
67 if (v >= 10)
463 33 p *= 10;
464 67 v /= 10;
465 67 ++n;
466 }
467
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 34 times.
67 while (v > 0);
468 static constexpr auto m =
469 std::numeric_limits<long long int>::digits10;
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 BOOST_ASSERT(n <= m + 1);
471 ignore_unused(m);
472
473 // get pad
474 34 std::size_t w = width;
475
4/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 29 times.
65 if (width_idx != std::size_t(-1) ||
476
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 29 times.
31 !width_name.empty())
477 {
478 5 get_width_from_args(
479
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 width_idx, width_name, ctx.args(), w);
480 }
481 34 std::size_t lpad = 0;
482 34 std::size_t rpad = 0;
483
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 22 times.
34 if (w > n)
484 {
485 12 std::size_t pad = w - n;
486
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (zeros)
487 {
488 3 lpad = pad;
489 }
490 else
491 {
492
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
9 switch (align)
493 {
494 1 case '<':
495 1 rpad = pad;
496 1 break;
497 6 case '>':
498 6 lpad = pad;
499 6 break;
500 2 case '^':
501 2 lpad = pad / 2;
502 2 rpad = pad - lpad;
503 2 break;
504 }
505 }
506 }
507
508 // write
509 34 v = v0;
510 34 char* out = ctx.out();
511
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
34 if (!zeros)
512 {
513
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 31 times.
59 for (std::size_t i = 0; i < lpad; ++i)
514 28 encode_one(out, fill, cs);
515 }
516
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (v < 0)
517 {
518 1 encode_one(out, '-', cs);
519 1 v *= -1;
520 1 --n;
521 }
522
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 29 times.
33 else if (sign != '-')
523 {
524 4 encode_one(out, sign, cs);
525 4 --n;
526 }
527
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 31 times.
34 if (zeros)
528 {
529
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
13 for (std::size_t i = 0; i < lpad; ++i)
530 10 encode_one(out, '0', cs);
531 }
532
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 34 times.
101 while (n)
533 {
534 67 unsigned long long int d = v / p;
535 67 encode_one(out, '0' + static_cast<char>(d), cs);
536 67 --n;
537 67 v %= p;
538 67 p /= 10;
539 }
540
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
34 if (!zeros)
541 {
542
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 31 times.
39 for (std::size_t i = 0; i < rpad; ++i)
543 8 encode_one(out, fill, cs);
544 }
545 34 return out;
546 }
547
548 char*
549 14 integer_formatter_impl::
550 format(
551 unsigned long long int v,
552 format_context& ctx,
553 grammar::lut_chars const& cs) const
554 {
555 // get n digits
556 14 unsigned long long int v0 = v;
557 14 unsigned long long int p = 1;
558 14 std::size_t n = 0;
559
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (sign != '-')
560 {
561 2 ++n;
562 }
563 do
564 {
565
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 14 times.
53 if (v >= 10)
566 39 p *= 10;
567 53 v /= 10;
568 53 ++n;
569 }
570
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 14 times.
53 while (v > 0);
571 static constexpr auto m =
572 std::numeric_limits<unsigned long long int>::digits10;
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 BOOST_ASSERT(n <= m + 1);
574 ignore_unused(m);
575
576 // get pad
577 14 std::size_t w = width;
578
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 10 times.
25 if (width_idx != std::size_t(-1) ||
579
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
11 !width_name.empty())
580 {
581 4 get_width_from_args(
582
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 width_idx, width_name, ctx.args(), w);
583 }
584 14 std::size_t lpad = 0;
585 14 std::size_t rpad = 0;
586
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (w > n)
587 {
588 8 std::size_t pad = w - n;
589
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (zeros)
590 {
591 1 lpad = pad;
592 }
593 else
594 {
595
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
7 switch (align)
596 {
597 1 case '<':
598 1 rpad = pad;
599 1 break;
600 5 case '>':
601 5 lpad = pad;
602 5 break;
603 1 case '^':
604 1 lpad = pad / 2;
605 1 rpad = pad - lpad;
606 1 break;
607 }
608 }
609 }
610
611 // write
612 14 v = v0;
613 14 char* out = ctx.out();
614
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 if (!zeros)
615 {
616
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 13 times.
35 for (std::size_t i = 0; i < lpad; ++i)
617 22 encode_one(out, fill, cs);
618 }
619
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (sign != '-')
620 {
621 2 encode_one(out, sign, cs);
622 2 --n;
623 }
624
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 if (zeros)
625 {
626
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (std::size_t i = 0; i < lpad; ++i)
627 4 encode_one(out, '0', cs);
628 }
629
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 14 times.
67 while (n)
630 {
631 53 unsigned long long int d = v / p;
632 53 encode_one(out, '0' + static_cast<char>(d), cs);
633 53 --n;
634 53 v %= p;
635 53 p /= 10;
636 }
637
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 if (!zeros)
638 {
639
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 for (std::size_t i = 0; i < rpad; ++i)
640 6 encode_one(out, fill, cs);
641 }
642 14 return out;
643 }
644
645 } // detail
646 } // urls
647 } // boost
648
649