mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 00:51:52 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			311 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			311 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 *  catch_generators.hpp
 | 
						|
 *  Catch
 | 
						|
 *
 | 
						|
 *  Created by Phil on 27/01/2011.
 | 
						|
 *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
 | 
						|
 *
 | 
						|
 *  Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
						|
 *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
 | 
						|
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
 | 
						|
 | 
						|
#include "catch_hub.h"
 | 
						|
 | 
						|
#include <iterator>
 | 
						|
#include <vector>
 | 
						|
#include <string>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
namespace Catch
 | 
						|
{
 | 
						|
 | 
						|
template<typename T>
 | 
						|
struct IGenerator
 | 
						|
{        
 | 
						|
    virtual ~IGenerator
 | 
						|
    ()
 | 
						|
    {}
 | 
						|
    
 | 
						|
    virtual T getValue
 | 
						|
        ( std::size_t index
 | 
						|
        ) const = 0;
 | 
						|
    
 | 
						|
    virtual std::size_t size
 | 
						|
        () const = 0;
 | 
						|
};
 | 
						|
 | 
						|
template<typename T>
 | 
						|
class BetweenGenerator : public IGenerator<T>
 | 
						|
{
 | 
						|
public:
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    BetweenGenerator
 | 
						|
    ( 
 | 
						|
        T from, 
 | 
						|
        T to 
 | 
						|
    )
 | 
						|
    :   m_from( from ), 
 | 
						|
        m_to( to )
 | 
						|
    {
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    virtual T getValue
 | 
						|
    (
 | 
						|
        std::size_t index
 | 
						|
    )
 | 
						|
    const
 | 
						|
    {
 | 
						|
        return m_from+static_cast<T>( index );
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    virtual std::size_t size
 | 
						|
    ()
 | 
						|
    const
 | 
						|
    {
 | 
						|
        return static_cast<std::size_t>( 1+m_to-m_from );
 | 
						|
    }
 | 
						|
    
 | 
						|
private:
 | 
						|
    
 | 
						|
    T m_from;
 | 
						|
    T m_to;
 | 
						|
};
 | 
						|
 | 
						|
template<typename T>
 | 
						|
class ValuesGenerator : public IGenerator<T>
 | 
						|
{
 | 
						|
public:
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    ValuesGenerator
 | 
						|
    ()
 | 
						|
    {
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    void add
 | 
						|
    (
 | 
						|
        T value
 | 
						|
    )
 | 
						|
    {
 | 
						|
        m_values.push_back( value );
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    virtual T getValue
 | 
						|
    (
 | 
						|
        std::size_t index
 | 
						|
    )
 | 
						|
    const
 | 
						|
    {
 | 
						|
        return m_values[index];
 | 
						|
    }
 | 
						|
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    virtual std::size_t size
 | 
						|
    ()
 | 
						|
    const
 | 
						|
    {
 | 
						|
        return m_values.size();
 | 
						|
    }
 | 
						|
    
 | 
						|
private:
 | 
						|
    
 | 
						|
    std::vector<T> m_values;
 | 
						|
};
 | 
						|
 | 
						|
template<typename T>
 | 
						|
class CompositeGenerator
 | 
						|
{
 | 
						|
public:
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    CompositeGenerator()
 | 
						|
    :   m_totalSize( 0 )
 | 
						|
    {
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
	// *** Move semantics, similar to auto_ptr ***
 | 
						|
    CompositeGenerator( CompositeGenerator& other )
 | 
						|
	:	m_fileInfo( other.m_fileInfo ),
 | 
						|
		m_totalSize( 0 )
 | 
						|
    {
 | 
						|
		move( other );
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    CompositeGenerator& setFileInfo
 | 
						|
    (
 | 
						|
        const char* fileInfo
 | 
						|
    )
 | 
						|
    {
 | 
						|
        m_fileInfo = fileInfo;
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    ~CompositeGenerator
 | 
						|
    ()
 | 
						|
    {
 | 
						|
        deleteAll( m_composed );
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    operator T
 | 
						|
    ()
 | 
						|
    const
 | 
						|
    {
 | 
						|
        size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize );
 | 
						|
        
 | 
						|
        typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
 | 
						|
        typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
 | 
						|
        for( size_t index = 0; it != itEnd; ++it )
 | 
						|
        {
 | 
						|
            const IGenerator<T>* generator = *it;
 | 
						|
            if( overallIndex >= index && overallIndex < index + generator->size() )
 | 
						|
            {
 | 
						|
                return generator->getValue( overallIndex-index );
 | 
						|
            }
 | 
						|
            index += generator->size();
 | 
						|
        }
 | 
						|
        CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
 | 
						|
		return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    void add
 | 
						|
    (
 | 
						|
        const IGenerator<T>* generator
 | 
						|
    )
 | 
						|
    {
 | 
						|
        m_totalSize += generator->size();
 | 
						|
        m_composed.push_back( generator );
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    CompositeGenerator& then
 | 
						|
    (
 | 
						|
        CompositeGenerator& other
 | 
						|
    )
 | 
						|
    {
 | 
						|
        move( other );
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    CompositeGenerator& then
 | 
						|
    (
 | 
						|
        T value
 | 
						|
    )
 | 
						|
    {
 | 
						|
        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
 | 
						|
        valuesGen->add( value );
 | 
						|
        add( valuesGen );
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
    
 | 
						|
private:
 | 
						|
    
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    void move
 | 
						|
    (
 | 
						|
        CompositeGenerator& other
 | 
						|
    )
 | 
						|
    {
 | 
						|
        std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
 | 
						|
        m_totalSize += other.m_totalSize;
 | 
						|
        other.m_composed.clear();
 | 
						|
    }
 | 
						|
    
 | 
						|
    std::vector<const IGenerator<T>*> m_composed;
 | 
						|
    std::string m_fileInfo;
 | 
						|
    size_t m_totalSize;
 | 
						|
};
 | 
						|
 | 
						|
namespace Generators
 | 
						|
{
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    template<typename T>
 | 
						|
    CompositeGenerator<T> between
 | 
						|
    (
 | 
						|
        T from, 
 | 
						|
        T to
 | 
						|
    )
 | 
						|
    {
 | 
						|
        CompositeGenerator<T> generators;
 | 
						|
        generators.add( new BetweenGenerator<T>( from, to ) );
 | 
						|
        return generators;
 | 
						|
    }
 | 
						|
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    template<typename T>
 | 
						|
    CompositeGenerator<T> values
 | 
						|
    (
 | 
						|
        T val1, 
 | 
						|
        T val2
 | 
						|
    )
 | 
						|
    {
 | 
						|
        CompositeGenerator<T> generators;
 | 
						|
        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
 | 
						|
        valuesGen->add( val1 );
 | 
						|
        valuesGen->add( val2 );
 | 
						|
        generators.add( valuesGen );
 | 
						|
        return generators;
 | 
						|
    }
 | 
						|
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    template<typename T>
 | 
						|
    CompositeGenerator<T> values
 | 
						|
    (
 | 
						|
        T val1, 
 | 
						|
        T val2, 
 | 
						|
        T val3
 | 
						|
    )
 | 
						|
    {
 | 
						|
        CompositeGenerator<T> generators;
 | 
						|
        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
 | 
						|
        valuesGen->add( val1 );
 | 
						|
        valuesGen->add( val2 );
 | 
						|
        valuesGen->add( val3 );
 | 
						|
        generators.add( valuesGen );
 | 
						|
        return generators;
 | 
						|
    }
 | 
						|
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    template<typename T>
 | 
						|
    CompositeGenerator<T> values
 | 
						|
    (
 | 
						|
        T val1, 
 | 
						|
        T val2, 
 | 
						|
        T val3, 
 | 
						|
        T val4
 | 
						|
    )
 | 
						|
    {
 | 
						|
        CompositeGenerator<T> generators;
 | 
						|
        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
 | 
						|
        valuesGen->add( val1 );
 | 
						|
        valuesGen->add( val2 );
 | 
						|
        valuesGen->add( val3 );
 | 
						|
        valuesGen->add( val4 );
 | 
						|
        generators.add( valuesGen );
 | 
						|
        return generators;
 | 
						|
    }
 | 
						|
 | 
						|
} // end namespace Generators
 | 
						|
    
 | 
						|
using namespace Generators;
 | 
						|
    
 | 
						|
} // end namespace Catch
 | 
						|
 | 
						|
#define INTERNAL_CATCH_LINESTR2( line ) #line
 | 
						|
#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
 | 
						|
 | 
						|
#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
 | 
						|
 | 
						|
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
 |