1 /*
2  *  Created by Phil on 20/04/2011.
3  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
9 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
10 
11 #include "catch_interfaces_registry_hub.h"
12 
13 #if defined(CATCH_CONFIG_DISABLE)
14     #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
15         static std::string translatorName( signature )
16 #endif
17 
18 #include <exception>
19 #include <string>
20 #include <vector>
21 
22 namespace Catch {
23     using exceptionTranslateFunction = std::string(*)();
24 
25     struct IExceptionTranslator;
26     using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
27 
28     struct IExceptionTranslator {
29         virtual ~IExceptionTranslator();
30         virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
31     };
32 
33     struct IExceptionTranslatorRegistry {
34         virtual ~IExceptionTranslatorRegistry();
35 
36         virtual std::string translateActiveException() const = 0;
37     };
38 
39     class ExceptionTranslatorRegistrar {
40         template<typename T>
41         class ExceptionTranslator : public IExceptionTranslator {
42         public:
43 
ExceptionTranslator(std::string (* translateFunction)(T &))44             ExceptionTranslator( std::string(*translateFunction)( T& ) )
45             : m_translateFunction( translateFunction )
46             {}
47 
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd)48             std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
49                 try {
50                     if( it == itEnd )
51                         std::rethrow_exception(std::current_exception());
52                     else
53                         return (*it)->translate( it+1, itEnd );
54                 }
55                 catch( T& ex ) {
56                     return m_translateFunction( ex );
57                 }
58             }
59 
60         protected:
61             std::string(*m_translateFunction)( T& );
62         };
63 
64     public:
65         template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))66         ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
67             getMutableRegistryHub().registerTranslator
68                 ( new ExceptionTranslator<T>( translateFunction ) );
69         }
70     };
71 }
72 
73 ///////////////////////////////////////////////////////////////////////////////
74 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
75     static std::string translatorName( signature ); \
76     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
77     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
78     namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
79     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
80     static std::string translatorName( signature )
81 
82 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
83 
84 #endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
85