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 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
50                 return "";
51 #else
52                 try {
53                     if( it == itEnd )
54                         std::rethrow_exception(std::current_exception());
55                     else
56                         return (*it)->translate( it+1, itEnd );
57                 }
58                 catch( T& ex ) {
59                     return m_translateFunction( ex );
60                 }
61 #endif
62             }
63 
64         protected:
65             std::string(*m_translateFunction)( T& );
66         };
67 
68     public:
69         template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))70         ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
71             getMutableRegistryHub().registerTranslator
72                 ( new ExceptionTranslator<T>( translateFunction ) );
73         }
74     };
75 }
76 
77 ///////////////////////////////////////////////////////////////////////////////
78 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
79     static std::string translatorName( signature ); \
80     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
81     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
82     namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
83     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
84     static std::string translatorName( signature )
85 
86 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
87 
88 #endif // TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
89