blob: 4b468834b1c59d8bccd61104f5f2ae2cf040b1ec [file] [log] [blame]
Phil Nash81a122e2012-05-08 08:10:49 +01001/*
2 * Created by Phil on 8/5/2012.
3 * Copyright 2012 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 */
Phil Nash328a4692014-04-23 07:03:15 +01008#ifndef TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
9#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
Phil Nash81a122e2012-05-08 08:10:49 +010010
11#include "catch_common.h"
Phil Nash5062d3e2013-04-16 22:55:31 +010012#include "catch_sfinae.hpp"
13
Phil Nash81a122e2012-05-08 08:10:49 +010014#include <sstream>
Phil Nash767f1582013-03-04 12:19:15 +010015#include <iomanip>
16#include <limits>
Phil Nashc2b0c6f2013-11-07 10:35:59 +000017#include <vector>
Phil Nash1a6f2a02014-04-23 18:19:19 +010018#include <cstddef>
Phil Nash81a122e2012-05-08 08:10:49 +010019
Phil Nash0dc9e432012-08-01 08:17:07 +010020#ifdef __OBJC__
21#include "catch_objc_arc.hpp"
22#endif
23
Phil Nash2efc1142012-05-15 07:42:26 +010024namespace Catch {
Phil Nash003960d2013-04-20 23:12:17 +010025namespace Detail {
Phil Nash5062d3e2013-04-16 22:55:31 +010026
Phil Nash9fff9e42013-04-20 23:18:44 +010027// SFINAE is currently disabled by default for all compilers.
28// If the non SFINAE version of IsStreamInsertable is ambiguous for you
Phil Nash4dd3f682013-04-22 08:19:17 +010029// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
30#ifdef CATCH_CONFIG_SFINAE
Phil Nash5062d3e2013-04-16 22:55:31 +010031
Phil Nash5062d3e2013-04-16 22:55:31 +010032 template<typename T>
33 class IsStreamInsertableHelper {
34 template<int N> struct TrueIfSizeable : TrueType {};
35
36 template<typename T2>
37 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
38 static FalseType dummy(...);
39
40 public:
41 typedef SizedIf<sizeof(dummy((T*)0))> type;
42 };
Phil Nashf3d1f082013-07-03 19:14:59 +010043
Phil Nash5062d3e2013-04-16 22:55:31 +010044 template<typename T>
45 struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
46
Phil Nash5062d3e2013-04-16 22:55:31 +010047#else
48
Phil Nash003960d2013-04-20 23:12:17 +010049 struct BorgType {
50 template<typename T> BorgType( T const& );
51 };
Phil Nashf3d1f082013-07-03 19:14:59 +010052
Phil Nash003960d2013-04-20 23:12:17 +010053 TrueType& testStreamable( std::ostream& );
54 FalseType testStreamable( FalseType );
Phil Nashf3d1f082013-07-03 19:14:59 +010055
Phil Nash003960d2013-04-20 23:12:17 +010056 FalseType operator<<( std::ostream const&, BorgType const& );
Phil Nash2efc1142012-05-15 07:42:26 +010057
Phil Nash003960d2013-04-20 23:12:17 +010058 template<typename T>
59 struct IsStreamInsertable {
60 static std::ostream &s;
Phil Nash2a9d8d92013-04-23 18:58:56 +010061 static T const&t;
Phil Nash003960d2013-04-20 23:12:17 +010062 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
63 };
Phil Nashf3d1f082013-07-03 19:14:59 +010064
Phil Nash003960d2013-04-20 23:12:17 +010065#endif
66
67 template<bool C>
68 struct StringMakerBase {
69 template<typename T>
70 static std::string convert( T const& ) { return "{?}"; }
71 };
72
73 template<>
74 struct StringMakerBase<true> {
75 template<typename T>
76 static std::string convert( T const& _value ) {
77 std::ostringstream oss;
78 oss << _value;
79 return oss.str();
80 }
Phil Nash81a122e2012-05-08 08:10:49 +010081 };
Phil Nashf3d1f082013-07-03 19:14:59 +010082
Phil Nash7cbf7402014-05-23 18:41:02 +010083 std::string rawMemoryToString( const void *object, std::size_t size );
Phil Nash48153e82014-04-22 08:19:11 +010084
Phil Nashe0910182014-01-07 17:25:27 +000085 template<typename T>
Phil Nash7cbf7402014-05-23 18:41:02 +010086 inline std::string rawMemoryToString( const T& object ) {
87 return rawMemoryToString( &object, sizeof(object) );
Phil Nashe0910182014-01-07 17:25:27 +000088 }
89
Phil Nash767f1582013-03-04 12:19:15 +010090} // end namespace Detail
91
Phil Nash767f1582013-03-04 12:19:15 +010092template<typename T>
Phil Nash1e2f1d12013-09-14 19:58:45 +010093std::string toString( T const& value );
94
95template<typename T>
Phil Nash003960d2013-04-20 23:12:17 +010096struct StringMaker :
97 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nash5062d3e2013-04-16 22:55:31 +010098
Phil Nash767f1582013-03-04 12:19:15 +010099template<typename T>
100struct StringMaker<T*> {
Phil Nash503d5d02013-07-03 08:25:11 +0100101 template<typename U>
102 static std::string convert( U* p ) {
Phil Nash81a122e2012-05-08 08:10:49 +0100103 if( !p )
104 return INTERNAL_CATCH_STRINGIFY( NULL );
Phil Nashe0910182014-01-07 17:25:27 +0000105 else
106 return Detail::rawMemoryToString( p );
107 }
108};
109
110template<typename R, typename C>
111struct StringMaker<R C::*> {
112 static std::string convert( R C::* p ) {
113 if( !p )
114 return INTERNAL_CATCH_STRINGIFY( NULL );
115 else
116 return Detail::rawMemoryToString( p );
Phil Nash767f1582013-03-04 12:19:15 +0100117 }
118};
Phil Nash81a122e2012-05-08 08:10:49 +0100119
Andy Sawyer0dbcf212013-09-17 22:22:47 +0100120namespace Detail {
121 template<typename InputIterator>
Andy Sawyerd6f23a92013-09-21 18:45:42 +0100122 std::string rangeToString( InputIterator first, InputIterator last );
Andy Sawyer0dbcf212013-09-17 22:22:47 +0100123}
124
125template<typename T, typename Allocator>
126struct StringMaker<std::vector<T, Allocator> > {
127 static std::string convert( std::vector<T,Allocator> const& v ) {
128 return Detail::rangeToString( v.begin(), v.end() );
129 }
Phil Nash767f1582013-03-04 12:19:15 +0100130};
Phil Nash81a122e2012-05-08 08:10:49 +0100131
Phil Nash767f1582013-03-04 12:19:15 +0100132namespace Detail {
133 template<typename T>
Phil Nash328a4692014-04-23 07:03:15 +0100134 std::string makeString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100135 return StringMaker<T>::convert( value );
Phil Nashf3d1f082013-07-03 19:14:59 +0100136 }
Phil Nash81a122e2012-05-08 08:10:49 +0100137} // end namespace Detail
138
139/// \brief converts any type to a string
140///
Phil Nashf3d1f082013-07-03 19:14:59 +0100141/// The default template forwards on to ostringstream - except when an
142/// ostringstream overload does not exist - in which case it attempts to detect
Phil Nash81a122e2012-05-08 08:10:49 +0100143/// that and writes {?}.
144/// Overload (not specialise) this template for custom typs that you don't want
145/// to provide an ostream overload for.
146template<typename T>
Phil Nash2a9d8d92013-04-23 18:58:56 +0100147std::string toString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100148 return StringMaker<T>::convert( value );
Phil Nash81a122e2012-05-08 08:10:49 +0100149}
Phil Nashf3d1f082013-07-03 19:14:59 +0100150
Phil Nash81a122e2012-05-08 08:10:49 +0100151// Built in overloads
152
Phil Nash328a4692014-04-23 07:03:15 +0100153std::string toString( std::string const& value );
154std::string toString( std::wstring const& value );
155std::string toString( const char* const value );
156std::string toString( char* const value );
157std::string toString( int value );
158std::string toString( unsigned long value );
159std::string toString( unsigned int value );
160std::string toString( const double value );
Phil Nashd89e74f2014-07-09 18:16:40 +0100161std::string toString( const float value );
Phil Nash328a4692014-04-23 07:03:15 +0100162std::string toString( bool value );
163std::string toString( char value );
164std::string toString( signed char value );
165std::string toString( unsigned char value );
Phil Nash86ad6342012-12-14 07:49:18 +0000166
Phil Nash5ec53b22012-05-10 07:58:48 +0100167#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash328a4692014-04-23 07:03:15 +0100168std::string toString( std::nullptr_t );
Phil Nash5ec53b22012-05-10 07:58:48 +0100169#endif
170
Phil Nash0dc9e432012-08-01 08:17:07 +0100171#ifdef __OBJC__
Phil Nash328a4692014-04-23 07:03:15 +0100172 std::string toString( NSString const * const& nsstring );
173 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
174 std::string toString( NSObject* const& nsObject );
Phil Nash0dc9e432012-08-01 08:17:07 +0100175#endif
176
Andy Sawyerd6f23a92013-09-21 18:45:42 +0100177 namespace Detail {
178 template<typename InputIterator>
179 std::string rangeToString( InputIterator first, InputIterator last ) {
180 std::ostringstream oss;
181 oss << "{ ";
182 if( first != last ) {
183 oss << toString( *first );
184 for( ++first ; first != last ; ++first ) {
185 oss << ", " << toString( *first );
186 }
187 }
188 oss << " }";
189 return oss.str();
190 }
191}
192
Phil Nash81a122e2012-05-08 08:10:49 +0100193} // end namespace Catch
194
Phil Nash328a4692014-04-23 07:03:15 +0100195#endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED