mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-03 21:49:32 +01:00 
			
		
		
		
	v3.6.0
This commit is contained in:
		@@ -6,8 +6,8 @@
 | 
			
		||||
 | 
			
		||||
// SPDX-License-Identifier: BSL-1.0
 | 
			
		||||
 | 
			
		||||
//  Catch v3.5.4
 | 
			
		||||
//  Generated: 2024-04-10 12:03:46.281848
 | 
			
		||||
//  Catch v3.6.0
 | 
			
		||||
//  Generated: 2024-05-05 20:53:27.562886
 | 
			
		||||
//  ----------------------------------------------------------
 | 
			
		||||
//  This file is an amalgamation of multiple different files.
 | 
			
		||||
//  You probably shouldn't edit it directly.
 | 
			
		||||
@@ -2156,13 +2156,13 @@ std::string StringMaker<unsigned char>::convert(unsigned char value) {
 | 
			
		||||
    return ::Catch::Detail::stringify(static_cast<char>(value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int StringMaker<float>::precision = 5;
 | 
			
		||||
int StringMaker<float>::precision = std::numeric_limits<float>::max_digits10;
 | 
			
		||||
 | 
			
		||||
std::string StringMaker<float>::convert(float value) {
 | 
			
		||||
    return Detail::fpToString(value, precision) + 'f';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int StringMaker<double>::precision = 10;
 | 
			
		||||
int StringMaker<double>::precision = std::numeric_limits<double>::max_digits10;
 | 
			
		||||
 | 
			
		||||
std::string StringMaker<double>::convert(double value) {
 | 
			
		||||
    return Detail::fpToString(value, precision);
 | 
			
		||||
@@ -2273,7 +2273,7 @@ namespace Catch {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Version const& libraryVersion() {
 | 
			
		||||
        static Version version( 3, 5, 4, "", 0 );
 | 
			
		||||
        static Version version( 3, 6, 0, "", 0 );
 | 
			
		||||
        return version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -5853,6 +5853,13 @@ namespace Catch {
 | 
			
		||||
        assertionEnded(CATCH_MOVE(result) );
 | 
			
		||||
        resetAssertionInfo();
 | 
			
		||||
 | 
			
		||||
        // Best effort cleanup for sections that have not been destructed yet
 | 
			
		||||
        // Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
 | 
			
		||||
        while (!m_activeSections.empty()) {
 | 
			
		||||
            auto nl = m_activeSections.back()->nameAndLocation();
 | 
			
		||||
            SectionEndInfo endInfo{ SectionInfo(CATCH_MOVE(nl.location), CATCH_MOVE(nl.name)), {}, 0.0 };
 | 
			
		||||
            sectionEndedEarly(CATCH_MOVE(endInfo));
 | 
			
		||||
        }
 | 
			
		||||
        handleUnfinishedSections();
 | 
			
		||||
 | 
			
		||||
        // Recreate section for test case (as we will lose the one that was in scope)
 | 
			
		||||
@@ -7207,117 +7214,228 @@ namespace {
 | 
			
		||||
        return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool isBoundary( std::string const& line, size_t at ) {
 | 
			
		||||
        assert( at > 0 );
 | 
			
		||||
        assert( at <= line.size() );
 | 
			
		||||
 | 
			
		||||
        return at == line.size() ||
 | 
			
		||||
               ( isWhitespace( line[at] ) && !isWhitespace( line[at - 1] ) ) ||
 | 
			
		||||
               isBreakableBefore( line[at] ) ||
 | 
			
		||||
               isBreakableAfter( line[at - 1] );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    namespace TextFlow {
 | 
			
		||||
        void AnsiSkippingString::preprocessString() {
 | 
			
		||||
            for ( auto it = m_string.begin(); it != m_string.end(); ) {
 | 
			
		||||
                // try to read through an ansi sequence
 | 
			
		||||
                while ( it != m_string.end() && *it == '\033' &&
 | 
			
		||||
                        it + 1 != m_string.end() && *( it + 1 ) == '[' ) {
 | 
			
		||||
                    auto cursor = it + 2;
 | 
			
		||||
                    while ( cursor != m_string.end() &&
 | 
			
		||||
                            ( isdigit( *cursor ) || *cursor == ';' ) ) {
 | 
			
		||||
                        ++cursor;
 | 
			
		||||
                    }
 | 
			
		||||
                    if ( cursor == m_string.end() || *cursor != 'm' ) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    // 'm' -> 0xff
 | 
			
		||||
                    *cursor = AnsiSkippingString::sentinel;
 | 
			
		||||
                    // if we've read an ansi sequence, set the iterator and
 | 
			
		||||
                    // return to the top of the loop
 | 
			
		||||
                    it = cursor + 1;
 | 
			
		||||
                }
 | 
			
		||||
                if ( it != m_string.end() ) {
 | 
			
		||||
                    ++m_size;
 | 
			
		||||
                    ++it;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AnsiSkippingString::AnsiSkippingString( std::string const& text ):
 | 
			
		||||
            m_string( text ) {
 | 
			
		||||
            preprocessString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AnsiSkippingString::AnsiSkippingString( std::string&& text ):
 | 
			
		||||
            m_string( CATCH_MOVE( text ) ) {
 | 
			
		||||
            preprocessString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AnsiSkippingString::const_iterator AnsiSkippingString::begin() const {
 | 
			
		||||
            return const_iterator( m_string );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AnsiSkippingString::const_iterator AnsiSkippingString::end() const {
 | 
			
		||||
            return const_iterator( m_string, const_iterator::EndTag{} );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string AnsiSkippingString::substring( const_iterator begin,
 | 
			
		||||
                                                   const_iterator end ) const {
 | 
			
		||||
            // There's one caveat here to an otherwise simple substring: when
 | 
			
		||||
            // making a begin iterator we might have skipped ansi sequences at
 | 
			
		||||
            // the start. If `begin` here is a begin iterator, skipped over
 | 
			
		||||
            // initial ansi sequences, we'll use the true beginning of the
 | 
			
		||||
            // string. Lastly: We need to transform any chars we replaced with
 | 
			
		||||
            // 0xff back to 'm'
 | 
			
		||||
            auto str = std::string( begin == this->begin() ? m_string.begin()
 | 
			
		||||
                                                           : begin.m_it,
 | 
			
		||||
                                    end.m_it );
 | 
			
		||||
            std::transform( str.begin(), str.end(), str.begin(), []( char c ) {
 | 
			
		||||
                return c == AnsiSkippingString::sentinel ? 'm' : c;
 | 
			
		||||
            } );
 | 
			
		||||
            return str;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void AnsiSkippingString::const_iterator::tryParseAnsiEscapes() {
 | 
			
		||||
            // check if we've landed on an ansi sequence, and if so read through
 | 
			
		||||
            // it
 | 
			
		||||
            while ( m_it != m_string->end() && *m_it == '\033' &&
 | 
			
		||||
                    m_it + 1 != m_string->end() &&  *( m_it + 1 ) == '[' ) {
 | 
			
		||||
                auto cursor = m_it + 2;
 | 
			
		||||
                while ( cursor != m_string->end() &&
 | 
			
		||||
                        ( isdigit( *cursor ) || *cursor == ';' ) ) {
 | 
			
		||||
                    ++cursor;
 | 
			
		||||
                }
 | 
			
		||||
                if ( cursor == m_string->end() ||
 | 
			
		||||
                     *cursor != AnsiSkippingString::sentinel ) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                // if we've read an ansi sequence, set the iterator and
 | 
			
		||||
                // return to the top of the loop
 | 
			
		||||
                m_it = cursor + 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void AnsiSkippingString::const_iterator::advance() {
 | 
			
		||||
            assert( m_it != m_string->end() );
 | 
			
		||||
            m_it++;
 | 
			
		||||
            tryParseAnsiEscapes();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void AnsiSkippingString::const_iterator::unadvance() {
 | 
			
		||||
            assert( m_it != m_string->begin() );
 | 
			
		||||
            m_it--;
 | 
			
		||||
            // if *m_it is 0xff, scan back to the \033 and then m_it-- once more
 | 
			
		||||
            // (and repeat check)
 | 
			
		||||
            while ( *m_it == AnsiSkippingString::sentinel ) {
 | 
			
		||||
                while ( *m_it != '\033' ) {
 | 
			
		||||
                    assert( m_it != m_string->begin() );
 | 
			
		||||
                    m_it--;
 | 
			
		||||
                }
 | 
			
		||||
                // if this happens, we must have been a begin iterator that had
 | 
			
		||||
                // skipped over ansi sequences at the start of a string
 | 
			
		||||
                assert( m_it != m_string->begin() );
 | 
			
		||||
                assert( *m_it == '\033' );
 | 
			
		||||
                m_it--;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static bool isBoundary( AnsiSkippingString const& line,
 | 
			
		||||
                                AnsiSkippingString::const_iterator it ) {
 | 
			
		||||
            return it == line.end() ||
 | 
			
		||||
                   ( isWhitespace( *it ) &&
 | 
			
		||||
                     !isWhitespace( *it.oneBefore() ) ) ||
 | 
			
		||||
                   isBreakableBefore( *it ) ||
 | 
			
		||||
                   isBreakableAfter( *it.oneBefore() );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void Column::const_iterator::calcLength() {
 | 
			
		||||
            m_addHyphen = false;
 | 
			
		||||
            m_parsedTo = m_lineStart;
 | 
			
		||||
            AnsiSkippingString const& current_line = m_column.m_string;
 | 
			
		||||
 | 
			
		||||
            std::string const& current_line = m_column.m_string;
 | 
			
		||||
            if ( current_line[m_lineStart] == '\n' ) {
 | 
			
		||||
                ++m_parsedTo;
 | 
			
		||||
            if ( m_parsedTo == current_line.end() ) {
 | 
			
		||||
                m_lineEnd = m_parsedTo;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            assert( m_lineStart != current_line.end() );
 | 
			
		||||
            if ( *m_lineStart == '\n' ) { ++m_parsedTo; }
 | 
			
		||||
 | 
			
		||||
            const auto maxLineLength = m_column.m_width - indentSize();
 | 
			
		||||
            const auto maxParseTo = std::min(current_line.size(), m_lineStart + maxLineLength);
 | 
			
		||||
            while ( m_parsedTo < maxParseTo &&
 | 
			
		||||
                    current_line[m_parsedTo] != '\n' ) {
 | 
			
		||||
            std::size_t lineLength = 0;
 | 
			
		||||
            while ( m_parsedTo != current_line.end() &&
 | 
			
		||||
                    lineLength < maxLineLength && *m_parsedTo != '\n' ) {
 | 
			
		||||
                ++m_parsedTo;
 | 
			
		||||
                ++lineLength;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // If we encountered a newline before the column is filled,
 | 
			
		||||
            // then we linebreak at the newline and consider this line
 | 
			
		||||
            // finished.
 | 
			
		||||
            if ( m_parsedTo < m_lineStart + maxLineLength ) {
 | 
			
		||||
                m_lineLength = m_parsedTo - m_lineStart;
 | 
			
		||||
            if ( lineLength < maxLineLength ) {
 | 
			
		||||
                m_lineEnd = m_parsedTo;
 | 
			
		||||
            } else {
 | 
			
		||||
                // Look for a natural linebreak boundary in the column
 | 
			
		||||
                // (We look from the end, so that the first found boundary is
 | 
			
		||||
                // the right one)
 | 
			
		||||
                size_t newLineLength = maxLineLength;
 | 
			
		||||
                while ( newLineLength > 0 && !isBoundary( current_line, m_lineStart + newLineLength ) ) {
 | 
			
		||||
                    --newLineLength;
 | 
			
		||||
                m_lineEnd = m_parsedTo;
 | 
			
		||||
                while ( lineLength > 0 &&
 | 
			
		||||
                        !isBoundary( current_line, m_lineEnd ) ) {
 | 
			
		||||
                    --lineLength;
 | 
			
		||||
                    --m_lineEnd;
 | 
			
		||||
                }
 | 
			
		||||
                while ( newLineLength > 0 &&
 | 
			
		||||
                        isWhitespace( current_line[m_lineStart + newLineLength - 1] ) ) {
 | 
			
		||||
                    --newLineLength;
 | 
			
		||||
                while ( lineLength > 0 &&
 | 
			
		||||
                        isWhitespace( *m_lineEnd.oneBefore() ) ) {
 | 
			
		||||
                    --lineLength;
 | 
			
		||||
                    --m_lineEnd;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // If we found one, then that is where we linebreak
 | 
			
		||||
                if ( newLineLength > 0 ) {
 | 
			
		||||
                    m_lineLength = newLineLength;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Otherwise we have to split text with a hyphen
 | 
			
		||||
                // If we found one, then that is where we linebreak, otherwise
 | 
			
		||||
                // we have to split text with a hyphen
 | 
			
		||||
                if ( lineLength == 0 ) {
 | 
			
		||||
                    m_addHyphen = true;
 | 
			
		||||
                    m_lineLength = maxLineLength - 1;
 | 
			
		||||
                    m_lineEnd = m_parsedTo.oneBefore();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        size_t Column::const_iterator::indentSize() const {
 | 
			
		||||
            auto initial =
 | 
			
		||||
                m_lineStart == 0 ? m_column.m_initialIndent : std::string::npos;
 | 
			
		||||
            auto initial = m_lineStart == m_column.m_string.begin()
 | 
			
		||||
                               ? m_column.m_initialIndent
 | 
			
		||||
                               : std::string::npos;
 | 
			
		||||
            return initial == std::string::npos ? m_column.m_indent : initial;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string
 | 
			
		||||
        Column::const_iterator::addIndentAndSuffix( size_t position,
 | 
			
		||||
                                              size_t length ) const {
 | 
			
		||||
        std::string Column::const_iterator::addIndentAndSuffix(
 | 
			
		||||
            AnsiSkippingString::const_iterator start,
 | 
			
		||||
            AnsiSkippingString::const_iterator end ) const {
 | 
			
		||||
            std::string ret;
 | 
			
		||||
            const auto desired_indent = indentSize();
 | 
			
		||||
            ret.reserve( desired_indent + length + m_addHyphen );
 | 
			
		||||
            // ret.reserve( desired_indent + (end - start) + m_addHyphen );
 | 
			
		||||
            ret.append( desired_indent, ' ' );
 | 
			
		||||
            ret.append( m_column.m_string, position, length );
 | 
			
		||||
            if ( m_addHyphen ) {
 | 
			
		||||
                ret.push_back( '-' );
 | 
			
		||||
            }
 | 
			
		||||
            // ret.append( start, end );
 | 
			
		||||
            ret += m_column.m_string.substring( start, end );
 | 
			
		||||
            if ( m_addHyphen ) { ret.push_back( '-' ); }
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Column::const_iterator::const_iterator( Column const& column ): m_column( column ) {
 | 
			
		||||
        Column::const_iterator::const_iterator( Column const& column ):
 | 
			
		||||
            m_column( column ),
 | 
			
		||||
            m_lineStart( column.m_string.begin() ),
 | 
			
		||||
            m_lineEnd( column.m_string.begin() ),
 | 
			
		||||
            m_parsedTo( column.m_string.begin() ) {
 | 
			
		||||
            assert( m_column.m_width > m_column.m_indent );
 | 
			
		||||
            assert( m_column.m_initialIndent == std::string::npos ||
 | 
			
		||||
                    m_column.m_width > m_column.m_initialIndent );
 | 
			
		||||
            calcLength();
 | 
			
		||||
            if ( m_lineLength == 0 ) {
 | 
			
		||||
                m_lineStart = m_column.m_string.size();
 | 
			
		||||
            if ( m_lineStart == m_lineEnd ) {
 | 
			
		||||
                m_lineStart = m_column.m_string.end();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string Column::const_iterator::operator*() const {
 | 
			
		||||
            assert( m_lineStart <= m_parsedTo );
 | 
			
		||||
            return addIndentAndSuffix( m_lineStart, m_lineLength );
 | 
			
		||||
            return addIndentAndSuffix( m_lineStart, m_lineEnd );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Column::const_iterator& Column::const_iterator::operator++() {
 | 
			
		||||
            m_lineStart += m_lineLength;
 | 
			
		||||
            std::string const& current_line = m_column.m_string;
 | 
			
		||||
            if ( m_lineStart < current_line.size() && current_line[m_lineStart] == '\n' ) {
 | 
			
		||||
                m_lineStart += 1;
 | 
			
		||||
            m_lineStart = m_lineEnd;
 | 
			
		||||
            AnsiSkippingString const& current_line = m_column.m_string;
 | 
			
		||||
            if ( m_lineStart != current_line.end() && *m_lineStart == '\n' ) {
 | 
			
		||||
                m_lineStart++;
 | 
			
		||||
            } else {
 | 
			
		||||
                while ( m_lineStart < current_line.size() &&
 | 
			
		||||
                        isWhitespace( current_line[m_lineStart] ) ) {
 | 
			
		||||
                while ( m_lineStart != current_line.end() &&
 | 
			
		||||
                        isWhitespace( *m_lineStart ) ) {
 | 
			
		||||
                    ++m_lineStart;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ( m_lineStart != current_line.size() ) {
 | 
			
		||||
                calcLength();
 | 
			
		||||
            }
 | 
			
		||||
            if ( m_lineStart != current_line.end() ) { calcLength(); }
 | 
			
		||||
            return *this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -7414,25 +7532,25 @@ namespace Catch {
 | 
			
		||||
            return os;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Columns operator+(Column const& lhs, Column const& rhs) {
 | 
			
		||||
        Columns operator+( Column const& lhs, Column const& rhs ) {
 | 
			
		||||
            Columns cols;
 | 
			
		||||
            cols += lhs;
 | 
			
		||||
            cols += rhs;
 | 
			
		||||
            return cols;
 | 
			
		||||
        }
 | 
			
		||||
        Columns operator+(Column&& lhs, Column&& rhs) {
 | 
			
		||||
        Columns operator+( Column&& lhs, Column&& rhs ) {
 | 
			
		||||
            Columns cols;
 | 
			
		||||
            cols += CATCH_MOVE( lhs );
 | 
			
		||||
            cols += CATCH_MOVE( rhs );
 | 
			
		||||
            return cols;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Columns& operator+=(Columns& lhs, Column const& rhs) {
 | 
			
		||||
        Columns& operator+=( Columns& lhs, Column const& rhs ) {
 | 
			
		||||
            lhs.m_columns.push_back( rhs );
 | 
			
		||||
            return lhs;
 | 
			
		||||
        }
 | 
			
		||||
        Columns& operator+=(Columns& lhs, Column&& rhs) {
 | 
			
		||||
            lhs.m_columns.push_back( CATCH_MOVE(rhs) );
 | 
			
		||||
        Columns& operator+=( Columns& lhs, Column&& rhs ) {
 | 
			
		||||
            lhs.m_columns.push_back( CATCH_MOVE( rhs ) );
 | 
			
		||||
            return lhs;
 | 
			
		||||
        }
 | 
			
		||||
        Columns operator+( Columns const& lhs, Column const& rhs ) {
 | 
			
		||||
@@ -8077,7 +8195,7 @@ namespace Detail {
 | 
			
		||||
 | 
			
		||||
    std::string WithinRelMatcher::describe() const {
 | 
			
		||||
        Catch::ReusableStringStream sstr;
 | 
			
		||||
        sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
 | 
			
		||||
        sstr << "and " << ::Catch::Detail::stringify(m_target) << " are within " << m_epsilon * 100. << "% of each other";
 | 
			
		||||
        return sstr.str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user