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