1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H 11 #define _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H 12 13 #include <__algorithm/find_if.h> 14 #include <__algorithm/min.h> 15 #include <__assert> 16 #include <__config> 17 #include <__format/format_arg.h> 18 #include <__format/format_error.h> 19 #include <__format/format_string.h> 20 #include <__variant/monostate.h> 21 #include <bit> 22 #include <concepts> 23 #include <cstdint> 24 #include <type_traits> 25 26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27 # pragma GCC system_header 28 #endif 29 30 _LIBCPP_PUSH_MACROS 31 #include <__undef_macros> 32 33 _LIBCPP_BEGIN_NAMESPACE_STD 34 35 #if _LIBCPP_STD_VER > 17 36 37 namespace __format_spec { 38 39 /** 40 * Contains the flags for the std-format-spec. 41 * 42 * Some format-options can only be used for specific C++ types and may depend on 43 * the selected format-type. 44 * * The C++type filtering can be done using the proper policies for 45 * @ref __parser_std. 46 * * The format-type filtering needs to be done post parsing in the parser 47 * derived from @ref __parser_std. 48 */ 49 _LIBCPP_PACKED_BYTE_FOR_AIX 50 class _LIBCPP_TYPE_VIS _Flags { 51 public: 52 enum class _LIBCPP_ENUM_VIS _Alignment : uint8_t { 53 /** 54 * No alignment is set in the format string. 55 * 56 * Zero-padding is ignored when an alignment is selected. 57 * The default alignment depends on the selected format-type. 58 */ 59 __default, 60 __left, 61 __center, 62 __right 63 }; 64 enum class _LIBCPP_ENUM_VIS _Sign : uint8_t { 65 /** 66 * No sign is set in the format string. 67 * 68 * The sign isn't allowed for certain format-types. By using this value 69 * it's possible to detect whether or not the user explicitly set the sign 70 * flag. For formatting purposes it behaves the same as @ref __minus. 71 */ 72 __default, 73 __minus, 74 __plus, 75 __space 76 }; 77 78 _Alignment __alignment : 2 {_Alignment::__default}; 79 _Sign __sign : 2 {_Sign::__default}; 80 uint8_t __alternate_form : 1 {false}; 81 uint8_t __zero_padding : 1 {false}; 82 uint8_t __locale_specific_form : 1 {false}; 83 84 enum class _LIBCPP_ENUM_VIS _Type : uint8_t { 85 __default, 86 __string, 87 __binary_lower_case, 88 __binary_upper_case, 89 __octal, 90 __decimal, 91 __hexadecimal_lower_case, 92 __hexadecimal_upper_case, 93 __pointer, 94 __char, 95 __float_hexadecimal_lower_case, 96 __float_hexadecimal_upper_case, 97 __scientific_lower_case, 98 __scientific_upper_case, 99 __fixed_lower_case, 100 __fixed_upper_case, 101 __general_lower_case, 102 __general_upper_case 103 }; 104 105 _Type __type{_Type::__default}; 106 }; 107 _LIBCPP_PACKED_BYTE_FOR_AIX_END 108 109 namespace __detail { 110 template <class _CharT> 111 _LIBCPP_HIDE_FROM_ABI constexpr bool 112 __parse_alignment(_CharT __c, _Flags& __flags) noexcept { 113 switch (__c) { 114 case _CharT('<'): 115 __flags.__alignment = _Flags::_Alignment::__left; 116 return true; 117 118 case _CharT('^'): 119 __flags.__alignment = _Flags::_Alignment::__center; 120 return true; 121 122 case _CharT('>'): 123 __flags.__alignment = _Flags::_Alignment::__right; 124 return true; 125 } 126 return false; 127 } 128 } // namespace __detail 129 130 template <class _CharT> 131 class _LIBCPP_TEMPLATE_VIS __parser_fill_align { 132 public: 133 // TODO FMT The standard doesn't specify this character is a Unicode 134 // character. Validate what fmt and MSVC have implemented. 135 _CharT __fill{_CharT(' ')}; 136 137 protected: 138 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 139 __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) { 140 _LIBCPP_ASSERT(__begin != __end, 141 "When called with an empty input the function will cause " 142 "undefined behavior by evaluating data not in the input"); 143 if (__begin + 1 != __end) { 144 if (__detail::__parse_alignment(*(__begin + 1), __flags)) { 145 if (*__begin == _CharT('{') || *__begin == _CharT('}')) 146 __throw_format_error( 147 "The format-spec fill field contains an invalid character"); 148 __fill = *__begin; 149 return __begin + 2; 150 } 151 } 152 153 if (__detail::__parse_alignment(*__begin, __flags)) 154 return __begin + 1; 155 156 return __begin; 157 } 158 }; 159 160 template <class _CharT> 161 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 162 __parse_sign(const _CharT* __begin, _Flags& __flags) noexcept { 163 switch (*__begin) { 164 case _CharT('-'): 165 __flags.__sign = _Flags::_Sign::__minus; 166 break; 167 case _CharT('+'): 168 __flags.__sign = _Flags::_Sign::__plus; 169 break; 170 case _CharT(' '): 171 __flags.__sign = _Flags::_Sign::__space; 172 break; 173 default: 174 return __begin; 175 } 176 return __begin + 1; 177 } 178 179 template <class _CharT> 180 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 181 __parse_alternate_form(const _CharT* __begin, _Flags& __flags) noexcept { 182 if (*__begin == _CharT('#')) { 183 __flags.__alternate_form = true; 184 ++__begin; 185 } 186 187 return __begin; 188 } 189 190 template <class _CharT> 191 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 192 __parse_zero_padding(const _CharT* __begin, _Flags& __flags) noexcept { 193 if (*__begin == _CharT('0')) { 194 __flags.__zero_padding = true; 195 ++__begin; 196 } 197 198 return __begin; 199 } 200 201 template <class _CharT> 202 _LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> 203 __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 204 // This function is a wrapper to call the real parser. But it does the 205 // validation for the pre-conditions and post-conditions. 206 if (__begin == __end) 207 __throw_format_error("End of input while parsing format-spec arg-id"); 208 209 __format::__parse_number_result __r = 210 __format::__parse_arg_id(__begin, __end, __parse_ctx); 211 212 if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) 213 __throw_format_error("Invalid arg-id"); 214 215 ++__r.__ptr; 216 return __r; 217 } 218 219 template <class _Context> 220 _LIBCPP_HIDE_FROM_ABI constexpr uint32_t 221 __substitute_arg_id(basic_format_arg<_Context> _Arg) { 222 return visit_format_arg( 223 [](auto __arg) -> uint32_t { 224 using _Type = decltype(__arg); 225 if constexpr (integral<_Type>) { 226 if constexpr (signed_integral<_Type>) { 227 if (__arg < 0) 228 __throw_format_error("A format-spec arg-id replacement shouldn't " 229 "have a negative value"); 230 } 231 232 using _CT = common_type_t<_Type, decltype(__format::__number_max)>; 233 if (static_cast<_CT>(__arg) > 234 static_cast<_CT>(__format::__number_max)) 235 __throw_format_error("A format-spec arg-id replacement exceeds " 236 "the maximum supported value"); 237 238 return __arg; 239 } else if constexpr (same_as<_Type, monostate>) 240 __throw_format_error("Argument index out of bounds"); 241 else 242 __throw_format_error("A format-spec arg-id replacement argument " 243 "isn't an integral type"); 244 }, 245 _Arg); 246 } 247 248 class _LIBCPP_TYPE_VIS __parser_width { 249 public: 250 /** Contains a width or an arg-id. */ 251 uint32_t __width : 31 {0}; 252 /** Determines whether the value stored is a width or an arg-id. */ 253 uint32_t __width_as_arg : 1 {0}; 254 255 /** 256 * Does the supplied width field contain an arg-id? 257 * 258 * If @c true the formatter needs to call @ref __substitute_width_arg_id. 259 */ 260 constexpr bool __width_needs_substitution() const noexcept { return __width_as_arg; } 261 262 protected: 263 /** 264 * Does the supplied std-format-spec contain a width field? 265 * 266 * When the field isn't present there's no padding required. This can be used 267 * to optimize the formatting. 268 */ 269 constexpr bool __has_width_field() const noexcept { return __width_as_arg || __width; } 270 271 template <class _CharT> 272 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 273 __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 274 if (*__begin == _CharT('0')) 275 __throw_format_error( 276 "A format-spec width field shouldn't have a leading zero"); 277 278 if (*__begin == _CharT('{')) { 279 __format::__parse_number_result __r = 280 __parse_arg_id(++__begin, __end, __parse_ctx); 281 __width = __r.__value; 282 __width_as_arg = 1; 283 return __r.__ptr; 284 } 285 286 if (*__begin < _CharT('0') || *__begin > _CharT('9')) 287 return __begin; 288 289 __format::__parse_number_result __r = 290 __format::__parse_number(__begin, __end); 291 __width = __r.__value; 292 _LIBCPP_ASSERT(__width != 0, 293 "A zero value isn't allowed and should be impossible, " 294 "due to validations in this function"); 295 return __r.__ptr; 296 } 297 298 _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_width_arg_id(auto __arg) { 299 _LIBCPP_ASSERT(__width_as_arg == 1, 300 "Substitute width called when no substitution is required"); 301 302 // The clearing of the flag isn't required but looks better when debugging 303 // the code. 304 __width_as_arg = 0; 305 __width = __substitute_arg_id(__arg); 306 if (__width == 0) 307 __throw_format_error( 308 "A format-spec width field replacement should have a positive value"); 309 } 310 }; 311 312 class _LIBCPP_TYPE_VIS __parser_precision { 313 public: 314 /** Contains a precision or an arg-id. */ 315 uint32_t __precision : 31 {__format::__number_max}; 316 /** 317 * Determines whether the value stored is a precision or an arg-id. 318 * 319 * @note Since @ref __precision == @ref __format::__number_max is a valid 320 * value, the default value contains an arg-id of INT32_MAX. (This number of 321 * arguments isn't supported by compilers.) This is used to detect whether 322 * the std-format-spec contains a precision field. 323 */ 324 uint32_t __precision_as_arg : 1 {1}; 325 326 /** 327 * Does the supplied precision field contain an arg-id? 328 * 329 * If @c true the formatter needs to call @ref __substitute_precision_arg_id. 330 */ 331 constexpr bool __precision_needs_substitution() const noexcept { 332 return __precision_as_arg && __precision != __format::__number_max; 333 } 334 335 protected: 336 /** 337 * Does the supplied std-format-spec contain a precision field? 338 * 339 * When the field isn't present there's no truncating required. This can be 340 * used to optimize the formatting. 341 */ 342 constexpr bool __has_precision_field() const noexcept { 343 344 return __precision_as_arg == 0 || // Contains a value? 345 __precision != __format::__number_max; // The arg-id is valid? 346 } 347 348 template <class _CharT> 349 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 350 __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 351 if (*__begin != _CharT('.')) 352 return __begin; 353 354 ++__begin; 355 if (__begin == __end) 356 __throw_format_error("End of input while parsing format-spec precision"); 357 358 if (*__begin == _CharT('{')) { 359 __format::__parse_number_result __arg_id = 360 __parse_arg_id(++__begin, __end, __parse_ctx); 361 _LIBCPP_ASSERT(__arg_id.__value != __format::__number_max, 362 "Unsupported number of arguments, since this number of " 363 "arguments is used a special value"); 364 __precision = __arg_id.__value; 365 return __arg_id.__ptr; 366 } 367 368 if (*__begin < _CharT('0') || *__begin > _CharT('9')) 369 __throw_format_error( 370 "The format-spec precision field doesn't contain a value or arg-id"); 371 372 __format::__parse_number_result __r = 373 __format::__parse_number(__begin, __end); 374 __precision = __r.__value; 375 __precision_as_arg = 0; 376 return __r.__ptr; 377 } 378 379 _LIBCPP_HIDE_FROM_ABI constexpr void __substitute_precision_arg_id( 380 auto __arg) { 381 _LIBCPP_ASSERT( 382 __precision_as_arg == 1 && __precision != __format::__number_max, 383 "Substitute precision called when no substitution is required"); 384 385 // The clearing of the flag isn't required but looks better when debugging 386 // the code. 387 __precision_as_arg = 0; 388 __precision = __substitute_arg_id(__arg); 389 } 390 }; 391 392 template <class _CharT> 393 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 394 __parse_locale_specific_form(const _CharT* __begin, _Flags& __flags) noexcept { 395 if (*__begin == _CharT('L')) { 396 __flags.__locale_specific_form = true; 397 ++__begin; 398 } 399 400 return __begin; 401 } 402 403 template <class _CharT> 404 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 405 __parse_type(const _CharT* __begin, _Flags& __flags) { 406 407 // Determines the type. It does not validate whether the selected type is 408 // valid. Most formatters have optional fields that are only allowed for 409 // certain types. These parsers need to do validation after the type has 410 // been parsed. So its easier to implement the validation for all types in 411 // the specific parse function. 412 switch (*__begin) { 413 case 'A': 414 __flags.__type = _Flags::_Type::__float_hexadecimal_upper_case; 415 break; 416 case 'B': 417 __flags.__type = _Flags::_Type::__binary_upper_case; 418 break; 419 case 'E': 420 __flags.__type = _Flags::_Type::__scientific_upper_case; 421 break; 422 case 'F': 423 __flags.__type = _Flags::_Type::__fixed_upper_case; 424 break; 425 case 'G': 426 __flags.__type = _Flags::_Type::__general_upper_case; 427 break; 428 case 'X': 429 __flags.__type = _Flags::_Type::__hexadecimal_upper_case; 430 break; 431 case 'a': 432 __flags.__type = _Flags::_Type::__float_hexadecimal_lower_case; 433 break; 434 case 'b': 435 __flags.__type = _Flags::_Type::__binary_lower_case; 436 break; 437 case 'c': 438 __flags.__type = _Flags::_Type::__char; 439 break; 440 case 'd': 441 __flags.__type = _Flags::_Type::__decimal; 442 break; 443 case 'e': 444 __flags.__type = _Flags::_Type::__scientific_lower_case; 445 break; 446 case 'f': 447 __flags.__type = _Flags::_Type::__fixed_lower_case; 448 break; 449 case 'g': 450 __flags.__type = _Flags::_Type::__general_lower_case; 451 break; 452 case 'o': 453 __flags.__type = _Flags::_Type::__octal; 454 break; 455 case 'p': 456 __flags.__type = _Flags::_Type::__pointer; 457 break; 458 case 's': 459 __flags.__type = _Flags::_Type::__string; 460 break; 461 case 'x': 462 __flags.__type = _Flags::_Type::__hexadecimal_lower_case; 463 break; 464 default: 465 return __begin; 466 } 467 return ++__begin; 468 } 469 470 /** 471 * Process the parsed alignment and zero-padding state of arithmetic types. 472 * 473 * [format.string.std]/13 474 * If the 0 character and an align option both appear, the 0 character is 475 * ignored. 476 * 477 * For the formatter a @ref __default alignment means zero-padding. 478 */ 479 _LIBCPP_HIDE_FROM_ABI constexpr void __process_arithmetic_alignment(_Flags& __flags) { 480 __flags.__zero_padding &= __flags.__alignment == _Flags::_Alignment::__default; 481 if (!__flags.__zero_padding && __flags.__alignment == _Flags::_Alignment::__default) 482 __flags.__alignment = _Flags::_Alignment::__right; 483 } 484 485 /** 486 * The parser for the std-format-spec. 487 * 488 * [format.string.std]/1 specifies the std-format-spec: 489 * fill-and-align sign # 0 width precision L type 490 * 491 * All these fields are optional. Whether these fields can be used depend on: 492 * - The type supplied to the format string. 493 * E.g. A string never uses the sign field so the field may not be set. 494 * This constrain is validated by the parsers in this file. 495 * - The supplied value for the optional type field. 496 * E.g. A int formatted as decimal uses the sign field. 497 * When formatted as a char the sign field may no longer be set. 498 * This constrain isn't validated by the parsers in this file. 499 * 500 * The base classes are ordered to minimize the amount of padding. 501 * 502 * This implements the parser for the string types. 503 */ 504 template <class _CharT> 505 class _LIBCPP_TEMPLATE_VIS __parser_string 506 : public __parser_width, // provides __width(|as_arg) 507 public __parser_precision, // provides __precision(|as_arg) 508 public __parser_fill_align<_CharT>, // provides __fill and uses __flags 509 public _Flags // provides __flags 510 { 511 public: 512 using char_type = _CharT; 513 514 _LIBCPP_HIDE_FROM_ABI constexpr __parser_string() { 515 this->__alignment = _Flags::_Alignment::__left; 516 } 517 518 /** 519 * The low-level std-format-spec parse function. 520 * 521 * @pre __begin points at the beginning of the std-format-spec. This means 522 * directly after the ':'. 523 * @pre The std-format-spec parses the entire input, or the first unmatched 524 * character is a '}'. 525 * 526 * @returns The iterator pointing at the last parsed character. 527 */ 528 _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) 529 -> decltype(__parse_ctx.begin()) { 530 auto __it = __parse(__parse_ctx); 531 __process_display_type(); 532 return __it; 533 } 534 535 private: 536 /** 537 * Parses the std-format-spec. 538 * 539 * @throws __throw_format_error When @a __parse_ctx contains an ill-formed 540 * std-format-spec. 541 * 542 * @returns An iterator to the end of input or point at the closing '}'. 543 */ 544 _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) 545 -> decltype(__parse_ctx.begin()) { 546 547 auto __begin = __parse_ctx.begin(); 548 auto __end = __parse_ctx.end(); 549 if (__begin == __end) 550 return __begin; 551 552 __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, 553 static_cast<_Flags&>(*this)); 554 if (__begin == __end) 555 return __begin; 556 557 __begin = __parser_width::__parse(__begin, __end, __parse_ctx); 558 if (__begin == __end) 559 return __begin; 560 561 __begin = __parser_precision::__parse(__begin, __end, __parse_ctx); 562 if (__begin == __end) 563 return __begin; 564 565 __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); 566 567 if (__begin != __end && *__begin != _CharT('}')) 568 __throw_format_error( 569 "The format-spec should consume the input or end with a '}'"); 570 571 return __begin; 572 } 573 574 /** Processes the parsed std-format-spec based on the parsed display type. */ 575 _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { 576 switch (this->__type) { 577 case _Flags::_Type::__default: 578 case _Flags::_Type::__string: 579 break; 580 581 default: 582 __throw_format_error("The format-spec type has a type not supported for " 583 "a string argument"); 584 } 585 } 586 }; 587 588 /** 589 * The parser for the std-format-spec. 590 * 591 * This implements the parser for the integral types. This includes the 592 * character type and boolean type. 593 * 594 * See @ref __parser_string. 595 */ 596 template <class _CharT> 597 class _LIBCPP_TEMPLATE_VIS __parser_integral 598 : public __parser_width, // provides __width(|as_arg) 599 public __parser_fill_align<_CharT>, // provides __fill and uses __flags 600 public _Flags // provides __flags 601 { 602 public: 603 using char_type = _CharT; 604 605 protected: 606 /** 607 * The low-level std-format-spec parse function. 608 * 609 * @pre __begin points at the beginning of the std-format-spec. This means 610 * directly after the ':'. 611 * @pre The std-format-spec parses the entire input, or the first unmatched 612 * character is a '}'. 613 * 614 * @returns The iterator pointing at the last parsed character. 615 */ 616 _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) 617 -> decltype(__parse_ctx.begin()) { 618 auto __begin = __parse_ctx.begin(); 619 auto __end = __parse_ctx.end(); 620 if (__begin == __end) 621 return __begin; 622 623 __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, 624 static_cast<_Flags&>(*this)); 625 if (__begin == __end) 626 return __begin; 627 628 __begin = __parse_sign(__begin, static_cast<_Flags&>(*this)); 629 if (__begin == __end) 630 return __begin; 631 632 __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this)); 633 if (__begin == __end) 634 return __begin; 635 636 __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this)); 637 if (__begin == __end) 638 return __begin; 639 640 __begin = __parser_width::__parse(__begin, __end, __parse_ctx); 641 if (__begin == __end) 642 return __begin; 643 644 __begin = 645 __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this)); 646 if (__begin == __end) 647 return __begin; 648 649 __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); 650 651 if (__begin != __end && *__begin != _CharT('}')) 652 __throw_format_error( 653 "The format-spec should consume the input or end with a '}'"); 654 655 return __begin; 656 } 657 658 /** Handles the post-parsing updates for the integer types. */ 659 _LIBCPP_HIDE_FROM_ABI constexpr void __handle_integer() noexcept { 660 __process_arithmetic_alignment(static_cast<_Flags&>(*this)); 661 } 662 663 /** 664 * Handles the post-parsing updates for the character types. 665 * 666 * Sets the alignment and validates the format flags set for a character type. 667 * 668 * At the moment the validation for a character and a Boolean behave the 669 * same, but this may change in the future. 670 * Specifically at the moment the locale-specific form is allowed for the 671 * char output type, but it has no effect on the output. 672 */ 673 _LIBCPP_HIDE_FROM_ABI constexpr void __handle_char() { __handle_bool(); } 674 675 /** 676 * Handles the post-parsing updates for the Boolean types. 677 * 678 * Sets the alignment and validates the format flags set for a Boolean type. 679 */ 680 _LIBCPP_HIDE_FROM_ABI constexpr void __handle_bool() { 681 if (this->__sign != _Flags::_Sign::__default) 682 __throw_format_error("A sign field isn't allowed in this format-spec"); 683 684 if (this->__alternate_form) 685 __throw_format_error( 686 "An alternate form field isn't allowed in this format-spec"); 687 688 if (this->__zero_padding) 689 __throw_format_error( 690 "A zero-padding field isn't allowed in this format-spec"); 691 692 if (this->__alignment == _Flags::_Alignment::__default) 693 this->__alignment = _Flags::_Alignment::__left; 694 } 695 }; 696 697 /** 698 * The parser for the std-format-spec. 699 * 700 * This implements the parser for the floating-point types. 701 * 702 * See @ref __parser_string. 703 */ 704 template <class _CharT> 705 class _LIBCPP_TEMPLATE_VIS __parser_floating_point 706 : public __parser_width, // provides __width(|as_arg) 707 public __parser_precision, // provides __precision(|as_arg) 708 public __parser_fill_align<_CharT>, // provides __fill and uses __flags 709 public _Flags // provides __flags 710 { 711 public: 712 using char_type = _CharT; 713 714 /** 715 * The low-level std-format-spec parse function. 716 * 717 * @pre __begin points at the beginning of the std-format-spec. This means 718 * directly after the ':'. 719 * @pre The std-format-spec parses the entire input, or the first unmatched 720 * character is a '}'. 721 * 722 * @returns The iterator pointing at the last parsed character. 723 */ 724 _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) 725 -> decltype(__parse_ctx.begin()) { 726 auto __it = __parse(__parse_ctx); 727 __process_arithmetic_alignment(static_cast<_Flags&>(*this)); 728 __process_display_type(); 729 return __it; 730 } 731 protected: 732 /** 733 * The low-level std-format-spec parse function. 734 * 735 * @pre __begin points at the beginning of the std-format-spec. This means 736 * directly after the ':'. 737 * @pre The std-format-spec parses the entire input, or the first unmatched 738 * character is a '}'. 739 * 740 * @returns The iterator pointing at the last parsed character. 741 */ 742 _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) 743 -> decltype(__parse_ctx.begin()) { 744 auto __begin = __parse_ctx.begin(); 745 auto __end = __parse_ctx.end(); 746 if (__begin == __end) 747 return __begin; 748 749 __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, 750 static_cast<_Flags&>(*this)); 751 if (__begin == __end) 752 return __begin; 753 754 __begin = __parse_sign(__begin, static_cast<_Flags&>(*this)); 755 if (__begin == __end) 756 return __begin; 757 758 __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this)); 759 if (__begin == __end) 760 return __begin; 761 762 __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this)); 763 if (__begin == __end) 764 return __begin; 765 766 __begin = __parser_width::__parse(__begin, __end, __parse_ctx); 767 if (__begin == __end) 768 return __begin; 769 770 __begin = __parser_precision::__parse(__begin, __end, __parse_ctx); 771 if (__begin == __end) 772 return __begin; 773 774 __begin = 775 __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this)); 776 if (__begin == __end) 777 return __begin; 778 779 __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); 780 781 if (__begin != __end && *__begin != _CharT('}')) 782 __throw_format_error( 783 "The format-spec should consume the input or end with a '}'"); 784 785 return __begin; 786 } 787 788 /** Processes the parsed std-format-spec based on the parsed display type. */ 789 _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { 790 switch (this->__type) { 791 case _Flags::_Type::__default: 792 // When no precision specified then it keeps default since that 793 // formatting differs from the other types. 794 if (this->__has_precision_field()) 795 this->__type = _Flags::_Type::__general_lower_case; 796 break; 797 case _Flags::_Type::__float_hexadecimal_lower_case: 798 case _Flags::_Type::__float_hexadecimal_upper_case: 799 // Precision specific behavior will be handled later. 800 break; 801 case _Flags::_Type::__scientific_lower_case: 802 case _Flags::_Type::__scientific_upper_case: 803 case _Flags::_Type::__fixed_lower_case: 804 case _Flags::_Type::__fixed_upper_case: 805 case _Flags::_Type::__general_lower_case: 806 case _Flags::_Type::__general_upper_case: 807 if (!this->__has_precision_field()) { 808 // Set the default precision for the call to to_chars. 809 this->__precision = 6; 810 this->__precision_as_arg = false; 811 } 812 break; 813 814 default: 815 __throw_format_error("The format-spec type has a type not supported for " 816 "a floating-point argument"); 817 } 818 } 819 }; 820 821 /** 822 * The parser for the std-format-spec. 823 * 824 * This implements the parser for the pointer types. 825 * 826 * See @ref __parser_string. 827 */ 828 template <class _CharT> 829 class _LIBCPP_TEMPLATE_VIS __parser_pointer : public __parser_width, // provides __width(|as_arg) 830 public __parser_fill_align<_CharT>, // provides __fill and uses __flags 831 public _Flags // provides __flags 832 { 833 public: 834 using char_type = _CharT; 835 836 _LIBCPP_HIDE_FROM_ABI constexpr __parser_pointer() { 837 // Implements LWG3612 Inconsistent pointer alignment in std::format. 838 // The issue's current status is "Tentatively Ready" and libc++ status is 839 // still experimental. 840 // 841 // TODO FMT Validate this with the final resolution of LWG3612. 842 this->__alignment = _Flags::_Alignment::__right; 843 } 844 845 /** 846 * The low-level std-format-spec parse function. 847 * 848 * @pre __begin points at the beginning of the std-format-spec. This means 849 * directly after the ':'. 850 * @pre The std-format-spec parses the entire input, or the first unmatched 851 * character is a '}'. 852 * 853 * @returns The iterator pointing at the last parsed character. 854 */ 855 _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 856 auto __it = __parse(__parse_ctx); 857 __process_display_type(); 858 return __it; 859 } 860 861 protected: 862 /** 863 * The low-level std-format-spec parse function. 864 * 865 * @pre __begin points at the beginning of the std-format-spec. This means 866 * directly after the ':'. 867 * @pre The std-format-spec parses the entire input, or the first unmatched 868 * character is a '}'. 869 * 870 * @returns The iterator pointing at the last parsed character. 871 */ 872 _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) -> decltype(__parse_ctx.begin()) { 873 auto __begin = __parse_ctx.begin(); 874 auto __end = __parse_ctx.end(); 875 if (__begin == __end) 876 return __begin; 877 878 __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, static_cast<_Flags&>(*this)); 879 if (__begin == __end) 880 return __begin; 881 882 // An integer presentation type isn't defined in the Standard. 883 // Since a pointer is formatted as an integer it can be argued it's an 884 // integer presentation type. However there are two LWG-issues asserting it 885 // isn't an integer presentation type: 886 // - LWG3612 Inconsistent pointer alignment in std::format 887 // - LWG3644 std::format does not define "integer presentation type" 888 // 889 // There's a paper to make additional clarifications on the status of 890 // formatting pointers and proposes additional fields to be valid. That 891 // paper hasn't been reviewed by the Committee yet. 892 // - P2510 Formatting pointers 893 // 894 // The current implementation assumes formatting pointers isn't covered by 895 // "integer presentation type". 896 // TODO FMT Apply the LWG-issues/papers after approval/rejection by the Committee. 897 898 __begin = __parser_width::__parse(__begin, __end, __parse_ctx); 899 if (__begin == __end) 900 return __begin; 901 902 __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); 903 904 if (__begin != __end && *__begin != _CharT('}')) 905 __throw_format_error("The format-spec should consume the input or end with a '}'"); 906 907 return __begin; 908 } 909 910 /** Processes the parsed std-format-spec based on the parsed display type. */ 911 _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { 912 switch (this->__type) { 913 case _Flags::_Type::__default: 914 this->__type = _Flags::_Type::__pointer; 915 break; 916 case _Flags::_Type::__pointer: 917 break; 918 default: 919 __throw_format_error("The format-spec type has a type not supported for a pointer argument"); 920 } 921 } 922 }; 923 924 /** Helper struct returned from @ref __get_string_alignment. */ 925 template <class _CharT> 926 struct _LIBCPP_TEMPLATE_VIS __string_alignment { 927 /** Points beyond the last character to write to the output. */ 928 const _CharT* __last; 929 /** 930 * The estimated number of columns in the output or 0. 931 * 932 * Only when the output needs to be aligned it's required to know the exact 933 * number of columns in the output. So if the formatted output has only a 934 * minimum width the exact size isn't important. It's only important to know 935 * the minimum has been reached. The minimum width is the width specified in 936 * the format-spec. 937 * 938 * For example in this code @code std::format("{:10}", MyString); @endcode 939 * the width estimation can stop once the algorithm has determined the output 940 * width is 10 columns. 941 * 942 * So if: 943 * * @ref __align == @c true the @ref __size is the estimated number of 944 * columns required. 945 * * @ref __align == @c false the @ref __size is the estimated number of 946 * columns required or 0 when the estimation algorithm stopped prematurely. 947 */ 948 ptrdiff_t __size; 949 /** 950 * Does the output need to be aligned. 951 * 952 * When alignment is needed the output algorithm needs to add the proper 953 * padding. Else the output algorithm just needs to copy the input up to 954 * @ref __last. 955 */ 956 bool __align; 957 }; 958 959 #ifndef _LIBCPP_HAS_NO_UNICODE 960 namespace __detail { 961 962 /** 963 * Unicode column width estimates. 964 * 965 * Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. 966 * Depending on format the relation between the number of code units stored and 967 * the number of output columns differs. The first relation is the number of 968 * code units forming a code point. (The text assumes the code units are 969 * unsigned.) 970 * - UTF-8 The number of code units is between one and four. The first 127 971 * Unicode code points match the ASCII character set. When the highest bit is 972 * set it means the code point has more than one code unit. 973 * - UTF-16: The number of code units is between 1 and 2. When the first 974 * code unit is in the range [0xd800,0xdfff) it means the code point uses two 975 * code units. 976 * - UTF-32: The number of code units is always one. 977 * 978 * The code point to the number of columns isn't well defined. The code uses the 979 * estimations defined in [format.string.std]/11. This list might change in the 980 * future. 981 * 982 * The algorithm of @ref __get_string_alignment uses two different scanners: 983 * - The simple scanner @ref __estimate_column_width_fast. This scanner assumes 984 * 1 code unit is 1 column. This scanner stops when it can't be sure the 985 * assumption is valid: 986 * - UTF-8 when the code point is encoded in more than 1 code unit. 987 * - UTF-16 and UTF-32 when the first multi-column code point is encountered. 988 * (The code unit's value is lower than 0xd800 so the 2 code unit encoding 989 * is irrelevant for this scanner.) 990 * Due to these assumptions the scanner is faster than the full scanner. It 991 * can process all text only containing ASCII. For UTF-16/32 it can process 992 * most (all?) European languages. (Note the set it can process might be 993 * reduced in the future, due to updates in the scanning rules.) 994 * - The full scanner @ref __estimate_column_width. This scanner, if needed, 995 * converts multiple code units into one code point then converts the code 996 * point to a column width. 997 * 998 * See also: 999 * - [format.string.general]/11 1000 * - https://en.wikipedia.org/wiki/UTF-8#Encoding 1001 * - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF 1002 */ 1003 1004 /** 1005 * The first 2 column code point. 1006 * 1007 * This is the point where the fast UTF-16/32 scanner needs to stop processing. 1008 */ 1009 inline constexpr uint32_t __two_column_code_point = 0x1100; 1010 1011 /** Helper concept for an UTF-8 character type. */ 1012 template <class _CharT> 1013 concept __utf8_character = same_as<_CharT, char> || same_as<_CharT, char8_t>; 1014 1015 /** Helper concept for an UTF-16 character type. */ 1016 template <class _CharT> 1017 concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) || same_as<_CharT, char16_t>; 1018 1019 /** Helper concept for an UTF-32 character type. */ 1020 template <class _CharT> 1021 concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) || same_as<_CharT, char32_t>; 1022 1023 /** Helper concept for an UTF-16 or UTF-32 character type. */ 1024 template <class _CharT> 1025 concept __utf16_or_32_character = __utf16_character<_CharT> || __utf32_character<_CharT>; 1026 1027 /** 1028 * Converts a code point to the column width. 1029 * 1030 * The estimations are conforming to [format.string.general]/11 1031 * 1032 * This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 1033 * character. 1034 */ 1035 _LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_3(uint32_t __c) noexcept { 1036 _LIBCPP_ASSERT(__c < 0x10000, 1037 "Use __column_width_4 or __column_width for larger values"); 1038 1039 // clang-format off 1040 return 1 + (__c >= 0x1100 && (__c <= 0x115f || 1041 (__c >= 0x2329 && (__c <= 0x232a || 1042 (__c >= 0x2e80 && (__c <= 0x303e || 1043 (__c >= 0x3040 && (__c <= 0xa4cf || 1044 (__c >= 0xac00 && (__c <= 0xd7a3 || 1045 (__c >= 0xf900 && (__c <= 0xfaff || 1046 (__c >= 0xfe10 && (__c <= 0xfe19 || 1047 (__c >= 0xfe30 && (__c <= 0xfe6f || 1048 (__c >= 0xff00 && (__c <= 0xff60 || 1049 (__c >= 0xffe0 && (__c <= 0xffe6 1050 )))))))))))))))))))); 1051 // clang-format on 1052 } 1053 1054 /** 1055 * @overload 1056 * 1057 * This version expects a value greater than or equal to 0x1'0000, which is a 1058 * 4-byte UTF-8 character. 1059 */ 1060 _LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_4(uint32_t __c) noexcept { 1061 _LIBCPP_ASSERT(__c >= 0x10000, 1062 "Use __column_width_3 or __column_width for smaller values"); 1063 1064 // clang-format off 1065 return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || 1066 (__c >= 0x1'f900 && (__c <= 0x1'f9ff || 1067 (__c >= 0x2'0000 && (__c <= 0x2'fffd || 1068 (__c >= 0x3'0000 && (__c <= 0x3'fffd 1069 )))))))); 1070 // clang-format on 1071 } 1072 1073 /** 1074 * @overload 1075 * 1076 * The general case, accepting all values. 1077 */ 1078 _LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width(uint32_t __c) noexcept { 1079 if (__c < 0x10000) 1080 return __column_width_3(__c); 1081 1082 return __column_width_4(__c); 1083 } 1084 1085 /** 1086 * Estimate the column width for the UTF-8 sequence using the fast algorithm. 1087 */ 1088 template <__utf8_character _CharT> 1089 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 1090 __estimate_column_width_fast(const _CharT* __first, 1091 const _CharT* __last) noexcept { 1092 return _VSTD::find_if(__first, __last, 1093 [](unsigned char __c) { return __c & 0x80; }); 1094 } 1095 1096 /** 1097 * @overload 1098 * 1099 * The implementation for UTF-16/32. 1100 */ 1101 template <__utf16_or_32_character _CharT> 1102 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* 1103 __estimate_column_width_fast(const _CharT* __first, 1104 const _CharT* __last) noexcept { 1105 return _VSTD::find_if(__first, __last, 1106 [](uint32_t __c) { return __c >= 0x1100; }); 1107 } 1108 1109 template <class _CharT> 1110 struct _LIBCPP_TEMPLATE_VIS __column_width_result { 1111 /** The number of output columns. */ 1112 size_t __width; 1113 /** 1114 * The last parsed element. 1115 * 1116 * This limits the original output to fit in the wanted number of columns. 1117 */ 1118 const _CharT* __ptr; 1119 }; 1120 1121 /** 1122 * Small helper to determine the width of malformed Unicode. 1123 * 1124 * @note This function's only needed for UTF-8. During scanning UTF-8 there 1125 * are multiple place where it can be detected that the Unicode is malformed. 1126 * UTF-16 only requires 1 test and UTF-32 requires no testing. 1127 */ 1128 template <__utf8_character _CharT> 1129 _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> 1130 __estimate_column_width_malformed(const _CharT* __first, const _CharT* __last, 1131 size_t __maximum, size_t __result) noexcept { 1132 size_t __size = __last - __first; 1133 size_t __n = _VSTD::min(__size, __maximum); 1134 return {__result + __n, __first + __n}; 1135 } 1136 1137 /** 1138 * Determines the number of output columns needed to render the input. 1139 * 1140 * @note When the scanner encounters malformed Unicode it acts as-if every code 1141 * unit at the end of the input is one output column. It's expected the output 1142 * terminal will replace these malformed code units with a one column 1143 * replacement characters. 1144 * 1145 * @param __first Points to the first element of the input range. 1146 * @param __last Points beyond the last element of the input range. 1147 * @param __maximum The maximum number of output columns. The returned number 1148 * of estimated output columns will not exceed this value. 1149 */ 1150 template <__utf8_character _CharT> 1151 _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> 1152 __estimate_column_width(const _CharT* __first, const _CharT* __last, 1153 size_t __maximum) noexcept { 1154 size_t __result = 0; 1155 1156 while (__first != __last) { 1157 // Based on the number of leading 1 bits the number of code units in the 1158 // code point can be determined. See 1159 // https://en.wikipedia.org/wiki/UTF-8#Encoding 1160 switch (_VSTD::countl_one(static_cast<unsigned char>(*__first))) { 1161 case 0: // 1-code unit encoding: all 1 column 1162 ++__result; 1163 ++__first; 1164 break; 1165 1166 case 2: // 2-code unit encoding: all 1 column 1167 // Malformed Unicode. 1168 if (__last - __first < 2) [[unlikely]] 1169 return __estimate_column_width_malformed(__first, __last, __maximum, 1170 __result); 1171 __first += 2; 1172 ++__result; 1173 break; 1174 1175 case 3: // 3-code unit encoding: either 1 or 2 columns 1176 // Malformed Unicode. 1177 if (__last - __first < 3) [[unlikely]] 1178 return __estimate_column_width_malformed(__first, __last, __maximum, 1179 __result); 1180 { 1181 uint32_t __c = static_cast<unsigned char>(*__first++) & 0x0f; 1182 __c <<= 6; 1183 __c |= static_cast<unsigned char>(*__first++) & 0x3f; 1184 __c <<= 6; 1185 __c |= static_cast<unsigned char>(*__first++) & 0x3f; 1186 __result += __column_width_3(__c); 1187 if (__result > __maximum) 1188 return {__result - 2, __first - 3}; 1189 } 1190 break; 1191 case 4: // 4-code unit encoding: either 1 or 2 columns 1192 // Malformed Unicode. 1193 if (__last - __first < 4) [[unlikely]] 1194 return __estimate_column_width_malformed(__first, __last, __maximum, 1195 __result); 1196 { 1197 uint32_t __c = static_cast<unsigned char>(*__first++) & 0x07; 1198 __c <<= 6; 1199 __c |= static_cast<unsigned char>(*__first++) & 0x3f; 1200 __c <<= 6; 1201 __c |= static_cast<unsigned char>(*__first++) & 0x3f; 1202 __c <<= 6; 1203 __c |= static_cast<unsigned char>(*__first++) & 0x3f; 1204 __result += __column_width_4(__c); 1205 if (__result > __maximum) 1206 return {__result - 2, __first - 4}; 1207 } 1208 break; 1209 default: 1210 // Malformed Unicode. 1211 return __estimate_column_width_malformed(__first, __last, __maximum, 1212 __result); 1213 } 1214 1215 if (__result >= __maximum) 1216 return {__result, __first}; 1217 } 1218 return {__result, __first}; 1219 } 1220 1221 template <__utf16_character _CharT> 1222 _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> 1223 __estimate_column_width(const _CharT* __first, const _CharT* __last, 1224 size_t __maximum) noexcept { 1225 size_t __result = 0; 1226 1227 while (__first != __last) { 1228 uint32_t __c = *__first; 1229 // Is the code unit part of a surrogate pair? See 1230 // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF 1231 if (__c >= 0xd800 && __c <= 0xDfff) { 1232 // Malformed Unicode. 1233 if (__last - __first < 2) [[unlikely]] 1234 return {__result + 1, __first + 1}; 1235 1236 __c -= 0xd800; 1237 __c <<= 10; 1238 __c += (*(__first + 1) - 0xdc00); 1239 __c += 0x10000; 1240 1241 __result += __column_width_4(__c); 1242 if (__result > __maximum) 1243 return {__result - 2, __first}; 1244 __first += 2; 1245 } else { 1246 __result += __column_width_3(__c); 1247 if (__result > __maximum) 1248 return {__result - 2, __first}; 1249 ++__first; 1250 } 1251 1252 if (__result >= __maximum) 1253 return {__result, __first}; 1254 } 1255 1256 return {__result, __first}; 1257 } 1258 1259 template <__utf32_character _CharT> 1260 _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> 1261 __estimate_column_width(const _CharT* __first, const _CharT* __last, 1262 size_t __maximum) noexcept { 1263 size_t __result = 0; 1264 1265 while (__first != __last) { 1266 uint32_t __c = *__first; 1267 __result += __column_width(__c); 1268 1269 if (__result > __maximum) 1270 return {__result - 2, __first}; 1271 1272 ++__first; 1273 if (__result >= __maximum) 1274 return {__result, __first}; 1275 } 1276 1277 return {__result, __first}; 1278 } 1279 1280 } // namespace __detail 1281 1282 template <class _CharT> 1283 _LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> 1284 __get_string_alignment(const _CharT* __first, const _CharT* __last, 1285 ptrdiff_t __width, ptrdiff_t __precision) noexcept { 1286 _LIBCPP_ASSERT(__width != 0 || __precision != -1, 1287 "The function has no effect and shouldn't be used"); 1288 1289 // TODO FMT There might be more optimizations possible: 1290 // If __precision == __format::__number_max and the encoding is: 1291 // * UTF-8 : 4 * (__last - __first) >= __width 1292 // * UTF-16 : 2 * (__last - __first) >= __width 1293 // * UTF-32 : (__last - __first) >= __width 1294 // In these cases it's certain the output is at least the requested width. 1295 // It's unknown how often this happens in practice. For now the improvement 1296 // isn't implemented. 1297 1298 /* 1299 * First assume there are no special Unicode code units in the input. 1300 * - Apply the precision (this may reduce the size of the input). When 1301 * __precison == -1 this step is omitted. 1302 * - Scan for special code units in the input. 1303 * If our assumption was correct the __pos will be at the end of the input. 1304 */ 1305 const ptrdiff_t __length = __last - __first; 1306 const _CharT* __limit = 1307 __first + 1308 (__precision == -1 ? __length : _VSTD::min(__length, __precision)); 1309 ptrdiff_t __size = __limit - __first; 1310 const _CharT* __pos = 1311 __detail::__estimate_column_width_fast(__first, __limit); 1312 1313 if (__pos == __limit) 1314 return {__limit, __size, __size < __width}; 1315 1316 /* 1317 * Our assumption was wrong, there are special Unicode code units. 1318 * The range [__first, __pos) contains a set of code units with the 1319 * following property: 1320 * Every _CharT in the range will be rendered in 1 column. 1321 * 1322 * If there's no maximum width and the parsed size already exceeds the 1323 * minimum required width. The real size isn't important. So bail out. 1324 */ 1325 if (__precision == -1 && (__pos - __first) >= __width) 1326 return {__last, 0, false}; 1327 1328 /* If there's a __precision, truncate the output to that width. */ 1329 ptrdiff_t __prefix = __pos - __first; 1330 if (__precision != -1) { 1331 _LIBCPP_ASSERT(__precision > __prefix, "Logic error."); 1332 auto __lengh_info = __detail::__estimate_column_width( 1333 __pos, __last, __precision - __prefix); 1334 __size = __lengh_info.__width + __prefix; 1335 return {__lengh_info.__ptr, __size, __size < __width}; 1336 } 1337 1338 /* Else use __width to determine the number of required padding characters. */ 1339 _LIBCPP_ASSERT(__width > __prefix, "Logic error."); 1340 /* 1341 * The column width is always one or two columns. For the precision the wanted 1342 * column width is the maximum, for the width it's the minimum. Using the 1343 * width estimation with its truncating behavior will result in the wrong 1344 * result in the following case: 1345 * - The last code unit processed requires two columns and exceeds the 1346 * maximum column width. 1347 * By increasing the __maximum by one avoids this issue. (It means it may 1348 * pass one code point more than required to determine the proper result; 1349 * that however isn't a problem for the algorithm.) 1350 */ 1351 size_t __maximum = 1 + __width - __prefix; 1352 auto __lengh_info = 1353 __detail::__estimate_column_width(__pos, __last, __maximum); 1354 if (__lengh_info.__ptr != __last) { 1355 // Consumed the width number of code units. The exact size of the string 1356 // is unknown. We only know we don't need to align the output. 1357 _LIBCPP_ASSERT(static_cast<ptrdiff_t>(__lengh_info.__width + __prefix) >= 1358 __width, 1359 "Logic error"); 1360 return {__last, 0, false}; 1361 } 1362 1363 __size = __lengh_info.__width + __prefix; 1364 return {__last, __size, __size < __width}; 1365 } 1366 #else // _LIBCPP_HAS_NO_UNICODE 1367 template <class _CharT> 1368 _LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> 1369 __get_string_alignment(const _CharT* __first, const _CharT* __last, 1370 ptrdiff_t __width, ptrdiff_t __precision) noexcept { 1371 const ptrdiff_t __length = __last - __first; 1372 const _CharT* __limit = 1373 __first + 1374 (__precision == -1 ? __length : _VSTD::min(__length, __precision)); 1375 ptrdiff_t __size = __limit - __first; 1376 return {__limit, __size, __size < __width}; 1377 } 1378 #endif // _LIBCPP_HAS_NO_UNICODE 1379 1380 } // namespace __format_spec 1381 1382 #endif //_LIBCPP_STD_VER > 17 1383 1384 _LIBCPP_END_NAMESPACE_STD 1385 1386 _LIBCPP_POP_MACROS 1387 1388 #endif // _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H 1389