1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SoPlex is distributed under the terms of the ZIB Academic Licence.       */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SoPlex; see the file COPYING. If not email to soplex@zib.de.  */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file  spxout.h
17   	 * @brief Wrapper for different output streams and verbosity levels.
18   	 */
19   	#ifndef _SPXOUT_H_
20   	#define _SPXOUT_H_
21   	
22   	#include <iostream>
23   	#include <iomanip>
24   	#include <assert.h>
25   	
26   	#include "soplex/spxdefines.h"
27   	
28   	// ----------------------------------------------------------------------
29   	//    class SPxOut
30   	// ----------------------------------------------------------------------
31   	
32   	namespace soplex
33   	{
34   	
35   	/**@class SPxOut
36   	   @ingroup Elementary
37   	
38   	   @brief Wrapper for several output streams.
39   	   A verbosity level is used to decide which stream to use and whether to
40   	   really print a given message. Regardless of whether the verbosity level
41   	   is set via a manipulator or via the member function, it is persistent
42   	   until a new value is set.
43   	
44   	   Most ostream member functions are not provided here; use the corresponding
45   	   stream manipulators (e.g., @c setprecision()) instead. These are passed on
46   	   to the <em>current</em> ostream, which is chosen according to the verbosity
47   	   level. In particular, this means that the first element in an output stream
48   	   should always be the verbosity. For instance, use
49   	   @code
50   	      spxout << verb( SPxOut::WARNING ) << std::setw( 15 ) << 42 << std::endl;
51   	   @endcode
52   	   or
53   	   @code
54   	      spxout.setVerbosity( SPxOut::WARNING );
55   	      spxout << std::setw( 15 ) << 42 << std::endl;
56   	   @endcode
57   	   instead of
58   	   @code
59   	      spxout << std::setw( 15 ) << verb( SPxOut::WARNING ) << 42 << std::endl;
60   	   @endcode
61   	   in order to make sure that @c std::setw( 15 ) is applied to the warning stream.
62   	*/
63   	class SPxOut
64   	{
65   	public:
66   	
67   	
68   	   //-----------------------------------
69   	   /**@name Output control types */
70   	   ///@{
71   	   /// Verbosity level
72   	   typedef enum
73   	   {
74   	      // Note: the implementation uses the fact that ERROR == 0
75   	      // and that the verbosity levels are subsequent numbers.
76   	      // If you change this, change the implementation as well.
77   	      ERROR    = 0,
78   	      WARNING  = 1,
79   	      DEBUG    = 2,
80   	      INFO1    = 3,
81   	      INFO2    = 4,
82   	      INFO3    = 5
83   	   } Verbosity;
84   	
85   	   /// helper struct for the output operator
86   	   struct struct_Verbosity
87   	   {
88   	      /// verbosity level
89   	      Verbosity v_;
90   	   };
91   	   ///@}
92   	
93   	   //-----------------------------------
94   	   /**@name Construction / destruction */
95   	   ///@{
96   	   /// constructor
97   	   SPxOut();
98   	   /// destructor
99   	   virtual ~SPxOut();
100  	   /// copy constructor
101  	   SPxOut(const SPxOut&);
102  	   /// assignment operator
103  	   SPxOut& operator=(const SPxOut&);
104  	   ///@}
105  	
106  	   //-----------------------------------
107  	   /**@name Verbosity */
108  	   ///@{
109  	   ///
110  	   virtual void
111  	   setVerbosity(const Verbosity& v)
112  	   {
113  	      m_verbosity = v;
114  	   }
115  	   ///
116  	   inline Verbosity
117  	   getVerbosity()
118  	   const
119  	   {
120  	      return m_verbosity;
121  	   }
122  	
123  	   ///@}
124  	
125  	   //----------------------------------------
126  	   /**@name Wrappers for the current stream */
127  	   ///@{
128  	   ///
129  	   inline bool good() const
130  	   {
131  	      return getCurrentStream().good();
132  	   }
133  	   ///
134  	   inline bool operator !() const
135  	   {
136  	      return ! getCurrentStream();
137  	   }
138  	   ///
139  	   inline std::streamsize precision() const
140  	   {
141  	      return getCurrentStream().precision();
142  	   }
143  	   ///@}
144  	
145  	   //-----------------------------------
146  	   /**@name Getting / setting streams */
147  	   ///@{
148  	   /// Sets the stream for the specified verbosity level.
149  	   virtual void
150  	   setStream(const Verbosity& verbosity,
151  	             std::ostream&   stream)
152  	   {
153  	      m_streams[ verbosity ] = &stream;
154  	   }
155  	   /// Returns the stream for the specified verbosity level.
156  	   inline std::ostream&
157  	   getStream(const Verbosity& verbosity)
158  	   const
159  	   {
160  	      return *(m_streams[ verbosity ]);
161  	   }
162  	   /// Returns the stream for the current verbosity.
163  	   inline std::ostream&
164  	   getCurrentStream()
165  	   const
166  	   {
167  	      return getStream(getVerbosity());
168  	   }
169  	
170  	   /// Sets the precision of the stream to 16 and the floatfield to scientifix.
171  	   static inline void setScientific(std::ostream& stream, int precision = 8)
172  	   {
173  	      stream << std::setprecision(precision) << std::scientific;
174  	   }
175  	
176  	   /// Sets the precision of the stream to 8 and the floatfield to fixed.
177  	   static inline void setFixed(std::ostream& stream, int precision = 8)
178  	   {
179  	      stream << std::setprecision(precision) << std::fixed;
180  	   }
181  	   ///@}
182  	
183  	private:
184  	
185  	   //-----------------------------------
186  	   /**@name Private data */
187  	   ///@{
188  	   /// verbosity level
189  	   Verbosity               m_verbosity;
190  	   /// array of pointers to internal streams, indexed by verbosity level
191  	   std::ostream**          m_streams;
192  	   ///@}
193  	};
194  	
195  	// ---------------------------------------------------------
196  	//    Manipulators
197  	// ---------------------------------------------------------
198  	
199  	
200  	//-------------------------------------------
201  	/**@name Verbosity manipulator
202  	    Manipulators are implemented in a similar way as done for @c setw(),
203  	    @c setprecision(), etc. in the standard library file iomanip. For
204  	    instance, the non-member function \ref verb() "verb(v)" returns a
205  	    struct struct_Severity which contains only the verbosity level.
206  	    Calling
207  	    @code
208  	         SPxOut spxout;
209  	         spxout << verb( SPxOut::ERROR ) << "This is an error!" << std::endl;
210  	    @endcode
211  	    passes such a struct to the output operator defined below, which
212  	    extracts the verbosity level from the struct and passes it to the
213  	    member function SPxOut::setVerbosity().
214  	*/
215  	//@{
216  	/// manipulator to be used in an output statement
217  	inline SPxOut::struct_Verbosity
218  	verb(const SPxOut::Verbosity&  v)
219  	{
220  	   SPxOut::struct_Verbosity verbosity;
221  	   verbosity.v_ = v;
222  	   return verbosity;
223  	}
224  	
225  	/// output operator with verbosity level struct
226  	inline SPxOut&
227  	operator<< (SPxOut& stream,
228  	            const SPxOut::struct_Verbosity&  verbosity)
229  	{
230  	   stream.setVerbosity(verbosity.v_);
231  	   return stream;
232  	}
233  	///@}
234  	
235  	//--------------------------------------------------------
236  	/**@name Output of standard manipulators and other types
237  	 *
238  	 * We have to define an output operator for many kinds of numeric
239  	 * types here because they can all be more or less casted into each
240  	 * other. When using only a template type, it is not clear what the
241  	 * compiler makes out of it (according to lint).
242  	 */
243  	//@{
244  	///
245  	/// Passes instances of type \p Type to the current stream.
246  	inline SPxOut& operator<< (SPxOut& _spxout, long t)
247  	{
248  	   _spxout.getCurrentStream() << t;
249  	   return _spxout;
250  	}
251  	
252  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned long t)
253  	{
254  	   _spxout.getCurrentStream() << t;
255  	   return _spxout;
256  	}
257  	
258  	inline SPxOut& operator<< (SPxOut& _spxout, bool t)
259  	{
260  	   _spxout.getCurrentStream() << t;
261  	   return _spxout;
262  	}
263  	
264  	inline SPxOut& operator<< (SPxOut& _spxout, short t)
265  	{
266  	   _spxout.getCurrentStream() << t;
267  	   return _spxout;
268  	}
269  	
270  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned short t)
271  	{
272  	   _spxout.getCurrentStream() << t;
273  	   return _spxout;
274  	}
275  	
276  	inline SPxOut& operator<< (SPxOut& _spxout, int t)
277  	{
278  	   _spxout.getCurrentStream() << t;
279  	   return _spxout;
280  	}
281  	
282  	inline SPxOut& operator<< (SPxOut& _spxout, unsigned int t)
283  	{
284  	   _spxout.getCurrentStream() << t;
285  	   return _spxout;
286  	}
287  	
288  	inline SPxOut& operator<< (SPxOut& _spxout, double t)
289  	{
290  	   _spxout.getCurrentStream() << t;
291  	   return _spxout;
292  	}
293  	
294  	inline SPxOut& operator<< (SPxOut& _spxout, float t)
295  	{
296  	   _spxout.getCurrentStream() << t;
297  	   return _spxout;
298  	}
299  	
300  	inline SPxOut& operator<< (SPxOut& _spxout, long double t)
301  	{
302  	   _spxout.getCurrentStream() << t;
303  	   return _spxout;
304  	}
305  	
306  	inline SPxOut& operator<< (SPxOut& _spxout, const void* t)
307  	{
308  	   _spxout.getCurrentStream() << t;
309  	   return _spxout;
310  	}
311  	
312  	/// Passes standard manipulators without arguments, like @c std::endl
313  	/// or @c std::ios::right to the current stream.
314  	inline SPxOut&
315  	operator<< (SPxOut&       _spxout,
316  	            std::ostream & (*manip)(std::ostream&))
317  	{
318  	   _spxout.getCurrentStream() << manip;
319  	   return _spxout;
320  	}
321  	
322  	//lint -e{818} (pointer could be made const; this is ok.)
323  	/// Passes everything else to the current stream. In particular,
324  	/// this includes structs corresponding to manipulators with arguments,
325  	/// such as the struct @c _Setw for the @c setw() manipulator.
326  	template <typename T>
327  	inline SPxOut& operator<< (SPxOut& _spxout, T  t)
328  	{
329  	   _spxout.getCurrentStream() << t;
330  	   return _spxout;
331  	}
332  	//@}
333  	
334  	}  // namespace soplex
335  	
336  	#endif // _SPXOUT_H_
337