| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:30:36 +00:00
										 |  |  | #include <iterator>
 | 
					
						
							| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  | #include <vector>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:30:36 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2011-03-09 19:45:05 +00:00
										 |  |  |         return m_from+static_cast<T>( index ); | 
					
						
							| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     ///////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     virtual std::size_t size | 
					
						
							|  |  |  |     () | 
					
						
							|  |  |  |     const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return 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 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2011-02-23 09:06:05 +00:00
										 |  |  |     ///////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 	// *** Move semantics, similar to auto_ptr ***
 | 
					
						
							|  |  |  |     CompositeGenerator( CompositeGenerator& other ) | 
					
						
							|  |  |  | 	:	m_fileInfo( other.m_fileInfo ), | 
					
						
							|  |  |  | 		m_totalSize( 0 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | 		move( other ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  |     ///////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     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(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-02-23 09:06:05 +00:00
										 |  |  |         CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); | 
					
						
							| 
									
										
										
										
											2011-01-27 22:29:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     ///////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  |     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
 |