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