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