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