| 537 | |
| 538 | template <typename... Args> |
| 539 | static std::string format( std::string_view format, Args&&... args ) { |
| 540 | #ifdef __clang__ |
| 541 | #pragma clang diagnostic push |
| 542 | #pragma clang diagnostic ignored "-Wformat-security" |
| 543 | #elif defined( __GNUC__ ) |
| 544 | #pragma GCC diagnostic push |
| 545 | #pragma GCC diagnostic ignored "-Wformat-security" |
| 546 | #endif |
| 547 | |
| 548 | int reqSize = |
| 549 | std::snprintf( nullptr, 0, format.data(), |
| 550 | FormatArg<std::decay_t<Args>>::get( std::forward<Args>( args ) )... ); |
| 551 | |
| 552 | if ( reqSize < 0 ) |
| 553 | return ""; |
| 554 | |
| 555 | std::size_t bufSize = static_cast<std::size_t>( reqSize ) + 1; |
| 556 | std::string result( bufSize, '\0' ); |
| 557 | |
| 558 | int writtenChars = |
| 559 | std::snprintf( &result[0], bufSize, format.data(), |
| 560 | FormatArg<std::decay_t<Args>>::get( std::forward<Args>( args ) )... ); |
| 561 | |
| 562 | if ( writtenChars < 0 ) |
| 563 | return ""; |
| 564 | |
| 565 | if ( static_cast<std::size_t>( writtenChars ) < bufSize ) { |
| 566 | result.resize( static_cast<std::size_t>( writtenChars ) ); |
| 567 | } else { |
| 568 | result.resize( bufSize - 1 ); |
| 569 | } |
| 570 | |
| 571 | #ifdef __clang__ |
| 572 | #pragma clang diagnostic pop |
| 573 | #elif defined( __GNUC__ ) |
| 574 | #pragma GCC diagnostic pop |
| 575 | #endif |
| 576 | return result; |
| 577 | } |
| 578 | |
| 579 | /** Format a char buffer */ |
| 580 | static void formatBuffer( char* Buffer, int BufferSize, const char* format, ... ); |