// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #ifndef DebuggableClass #define DebuggableClass #include #include // Objects of this class have debugging facilities which may be turned // on or off per-class or more specifically if objects have individual // names, as returned by getName(). extern ostream &endlog(ostream& outs); class Debuggable { friend inline ostream &debug(); friend inline ostream &err(); friend ostream &endlog(ostream& outs); friend bool debugging() { return !Debuggable::noDebug; } public: Debuggable(); virtual ~Debuggable() {} virtual const char *getName() const { return ""; } bool isGood() const { return good; } bool isBad() const { return !good; } static void setDebugConfigPath( const char * ); friend ostream& operator<<( ostream &s, const Debuggable &d ) { return d.print( s ); } protected: void setGood( bool p = true ) { good = good && p; } void setBad() { good = false; } virtual void reset() { good = true; } virtual ostream &print( ostream & ) const; ostream &debug(); ostream &debug() const; bool debugging(); private: void initDebug(); static void reconfigure(); private: bool good; int init; ostream *_debug; enum { bufferSize = 1024 }; static int initLevel; static bool noDebug; static char **tok; static int nrTok; static int activeTok; static char configPath[256]; static ostrstream errStr; static ostrstream debugOn; static ostrstream debugOff; static char errBuf[]; static char debugOnBuf[]; static char debugOffBuf[]; }; // If you have debugging information which would be printed so often // as to affect performance, a reasonable structure is: // // if_debug { // debug() << ... complex business ... << endlog; // } #ifdef NO_DEBUG # define if_debug if(0) #else # define if_debug if(debugging()) #endif inline ostream & Debuggable::debug() { #ifdef NO_DEBUG return Debuggable::debugOff; #else if (init != initLevel) initDebug(); return *_debug << getName() << ": "; #endif } inline ostream & Debuggable::debug() const { #ifdef NO_DEBUG return Debuggable::debugOff; #else if (*_debug == debugOn) { return debugOn << getName() << ": "; } else { return debugOff; } #endif } inline ostream & debug() { #ifdef NO_DEBUG return Debuggable::debugOff; #else ostrstream *xx; if (Debuggable::noDebug) { xx = &Debuggable::debugOff; } else { xx = &Debuggable::debugOn; } return *(ostream *)xx; #endif } inline ostream & err() { return Debuggable::errStr; } inline bool Debuggable::debugging() { if (init != initLevel) initDebug(); return _debug == &debugOn; } #endif