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