diff options
| author | Jan Niklas Hasse | 2026-03-28 16:02:01 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2026-04-01 16:12:08 +0200 |
| commit | 572f96b8febec9dd14ac5284e6a959a7246325c8 (patch) | |
| tree | 542479ee537175e5a4c5787c953fb68109fd14e9 /src/catch2 | |
| parent | 8492fd444e42f331f48611d2b5ef11c8ce338423 (diff) | |
| download | catch3-572f96b8febec9dd14ac5284e6a959a7246325c8.tar.gz | |
Fix counting of UTF-8 codepoints in TextFlow
For line-wrapping bytes were counted instead of codepoints. This
resulted in line-breaks being inserted at the wrong position and also
breaking UTF-8 characters.
Fixes #1022.
Diffstat (limited to 'src/catch2')
| -rw-r--r-- | src/catch2/internal/catch_textflow.cpp | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/catch2/internal/catch_textflow.cpp b/src/catch2/internal/catch_textflow.cpp index 1c21d20e..3979048f 100644 --- a/src/catch2/internal/catch_textflow.cpp +++ b/src/catch2/internal/catch_textflow.cpp @@ -26,6 +26,10 @@ namespace { return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr; } + bool isUtf8ContinuationByte( char c ) { + return ( static_cast<unsigned char>( c ) & 0xC0 ) == 0x80; + } + } // namespace namespace Catch { @@ -52,6 +56,11 @@ namespace Catch { if ( it != m_string.end() ) { ++m_size; ++it; + // Skip UTF-8 continuation bytes + while ( it != m_string.end() && + isUtf8ContinuationByte( *it ) ) { + ++it; + } } } } @@ -114,6 +123,11 @@ namespace Catch { void AnsiSkippingString::const_iterator::advance() { assert( m_it != m_string->end() ); m_it++; + // Skip UTF-8 continuation bytes + while ( m_it != m_string->end() && + isUtf8ContinuationByte( *m_it ) ) { + m_it++; + } tryParseAnsiEscapes(); } @@ -133,6 +147,11 @@ namespace Catch { assert( *m_it == '\033' ); m_it--; } + // Skip back over UTF-8 continuation bytes to the leading byte + while ( isUtf8ContinuationByte( *m_it ) ) { + assert( m_it != m_string->begin() ); + m_it--; + } } static bool isBoundary( AnsiSkippingString const& line, |