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