1// (C) Copyright Gennadiy Rozental 2001.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6// See http://www.boost.org/libs/test for the library home page.
7//
8// File : $RCSfile$
9//
10// Version : $Revision: 74248 $
11//
12// Description : defines level of indiration facilitating workarounds for non printable types
13// ***************************************************************************
14
15#ifndef BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER
16#define BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER
17
18// Boost.Test
19#include <boost/test/detail/config.hpp>
20#include <boost/test/detail/global_typedef.hpp>
21#include <boost/test/detail/workaround.hpp>
22
23// Boost
24#include <boost/mpl/or.hpp>
25#include <boost/type_traits/is_array.hpp>
26#include <boost/type_traits/is_function.hpp>
27#include <boost/type_traits/is_abstract.hpp>
28#include <limits>
29
30#include <boost/test/detail/suppress_warnings.hpp>
31
32//____________________________________________________________________________//
33
34namespace boost {
35namespace test_tools {
36namespace tt_detail {
37
38// ************************************************************************** //
39// ************** print_log_value ************** //
40// ************************************************************************** //
41
42template<typename T>
43struct print_log_value {
44 void operator()( std::ostream& ostr, T const& t )
45 {
46 typedef typename mpl::or_<is_array<T>,is_function<T>,is_abstract<T> >::type cant_use_nl;
47
48 std::streamsize old_precision = set_precision( ostr, cant_use_nl() );
49
50 ostr << t;
51
52 if( old_precision != (std::streamsize)-1 )
53 ostr.precision( old_precision );
54 }
55
56 std::streamsize set_precision( std::ostream& ostr, mpl::false_ )
57 {
58 if( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2 )
59 return ostr.precision( 2 + std::numeric_limits<T>::digits * 301/1000 );
60 else if ( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 10 ) {
61#ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
62 // (was BOOST_NO_NUMERIC_LIMITS_LOWEST but now deprecated).
63 // No support for std::numeric_limits<double>::max_digits10,
64 // so guess that a couple of guard digits more than digits10 will display any difference.
65 return ostr.precision( 2 + std::numeric_limits<T>::digits10 );
66#else
67 // std::numeric_limits<double>::max_digits10; IS supported.
68 // Any noisy or guard digits needed to display any difference are included in max_digits10.
69 return ostr.precision( std::numeric_limits<T>::max_digits10 );
70#endif
71 }
72 // else if T is not specialized for std::numeric_limits<>,
73 // then will just get the default precision of 6 digits.
74 return (std::streamsize)-1;
75 }
76
77 std::streamsize set_precision( std::ostream&, mpl::true_ ) { return (std::streamsize)-1; }
78};
79
80//____________________________________________________________________________//
81
82#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
83template<typename T, std::size_t N >
84struct print_log_value< T[N] > {
85 void operator()( std::ostream& ostr, T const* t )
86 {
87 ostr << t;
88 }
89};
90#endif
91
92//____________________________________________________________________________//
93
94template<>
95struct BOOST_TEST_DECL print_log_value<bool> {
96 void operator()( std::ostream& ostr, bool t )
97 {
98 ostr << std::boolalpha << t;
99 }
100};
101
102//____________________________________________________________________________//
103
104template<>
105struct BOOST_TEST_DECL print_log_value<char> {
106 void operator()( std::ostream& ostr, char t );
107};
108
109//____________________________________________________________________________//
110
111template<>
112struct BOOST_TEST_DECL print_log_value<unsigned char> {
113 void operator()( std::ostream& ostr, unsigned char t );
114};
115
116//____________________________________________________________________________//
117
118template<>
119struct BOOST_TEST_DECL print_log_value<char const*> {
120 void operator()( std::ostream& ostr, char const* t );
121};
122
123//____________________________________________________________________________//
124
125template<>
126struct BOOST_TEST_DECL print_log_value<wchar_t const*> {
127 void operator()( std::ostream& ostr, wchar_t const* t );
128};
129
130//____________________________________________________________________________//
131
132// ************************************************************************** //
133// ************** print_helper ************** //
134// ************************************************************************** //
135// Adds level of indirection to the output operation, allowing us to customize
136// it for types that do not support operator << directly or for any other reason
137
138template<typename T>
139struct print_helper_t {
140 explicit print_helper_t( T const& t ) : m_t( t ) {}
141
142 T const& m_t;
143};
144
145//____________________________________________________________________________//
146
147#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
148// Borland suffers premature pointer decay passing arrays by reference
149template<typename T, std::size_t N >
150struct print_helper_t< T[N] > {
151 explicit print_helper_t( T const * t ) : m_t( t ) {}
152
153 T const * m_t;
154};
155#endif
156
157//____________________________________________________________________________//
158
159template<typename T>
160inline print_helper_t<T>
161print_helper( T const& t )
162{
163 return print_helper_t<T>( t );
164}
165
166//____________________________________________________________________________//
167
168template<typename T>
169inline std::ostream&
170operator<<( std::ostream& ostr, print_helper_t<T> const& ph )
171{
172 print_log_value<T>()( ostr, ph.m_t );
173
174 return ostr;
175}
176
177//____________________________________________________________________________//
178
179} // namespace tt_detail
180
181// ************************************************************************** //
182// ************** BOOST_TEST_DONT_PRINT_LOG_VALUE ************** //
183// ************************************************************************** //
184
185#define BOOST_TEST_DONT_PRINT_LOG_VALUE( the_type ) \
186namespace boost{ namespace test_tools{ namespace tt_detail{ \
187template<> \
188struct print_log_value<the_type > { \
189 void operator()( std::ostream&, the_type const& ) {} \
190}; \
191}}} \
192/**/
193
194} // namespace test_tools
195} // namespace boost
196
197#include <boost/test/detail/enable_warnings.hpp>
198
199#endif // BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER
200