UniSet  2.6.0
DebugStream.h
00001 // -*- C++ -*-
00002 
00003 // Created by Lars Gullik BjЬnnes
00004 // Copyright 1999 Lars Gullik BjЬnnes (larsbj@lyx.org)
00005 // Released into the public domain.
00006 
00007 // Implemented and tested on g++ 2.7.2.3
00008 
00009 // Primarily developed for use in the LyX Project http://www.lyx.org/
00010 // but should be adaptable to any project.
00011 
00012 // (c) 2002 adapted for UniSet by Lav, GNU LGPL license
00013 // Modify for UniSet by pv@eterspft.ru, GNU LGPL license
00014 
00015 #ifndef DEBUGSTREAM_H
00016 #define DEBUGSTREAM_H
00017 
00018 //#ifdef __GNUG__
00019 //#pragma interface
00020 //#endif
00021 
00022 #include <iostream>
00023 #include <string>
00024 #include <sigc++/sigc++.h>
00025 #include "Debug.h"
00026 
00027 #ifdef TEST_DEBUGSTREAM
00028 #include <string>
00029 struct Debug
00030 {
00031     enum type
00032     {
00033         NONE = 0,
00034         INFO       = (1 << 0),   // 1
00035         WARN       = (1 << 1),   // 2
00036         CRIT       = (1 << 2)   // 4
00037     };
00038     static const type ANY = type(INFO | WARN | CRIT);
00039     static Debug::type value(std::string const& val)
00040     {
00041         if (val == "NONE") return Debug::NONE;
00042 
00043         if (val == "INFO") return Debug::INFO;
00044 
00045         if (val == "WARN") return Debug::WARN;
00046 
00047         if (val == "CRIT") return Debug::CRIT;
00048 
00049         return Debug::NONE;
00050     }
00051 };
00052 #endif
00053 
00091 class DebugStream : public std::ostream
00092 {
00093     public:
00095         explicit DebugStream(Debug::type t = Debug::NONE);
00096 
00098         explicit
00099         DebugStream(char const* f, Debug::type t = Debug::NONE, bool truncate = false );
00100 
00102         virtual ~DebugStream();
00103 
00104         typedef sigc::signal<void, const std::string&> StreamEvent_Signal;
00105         StreamEvent_Signal signal_stream_event();
00106 
00108         void level(Debug::type t) noexcept
00109         {
00110             dt = Debug::type(t & Debug::ANY);
00111         }
00112 
00114         Debug::type level() const noexcept
00115         {
00116             return dt;
00117         }
00118 
00120         void addLevel(Debug::type t) noexcept
00121         {
00122             dt = Debug::type(dt | t);
00123         }
00124 
00126         void delLevel(Debug::type t) noexcept
00127         {
00128             dt = Debug::type(dt & ~t);
00129         }
00130 
00132         virtual void logFile( const std::string& f, bool truncate = false );
00133 
00134         inline std::string getLogFile() const noexcept
00135         {
00136             return fname;
00137         }
00138 
00139         // имя лог файла можно установить отдельно, но не вклчать запись..
00140         inline void setLogFile( const std::string& n ) noexcept
00141         {
00142             fname = n;
00143         }
00144 
00145         // включена ли запись лог-файла
00146         inline bool isOnLogFile() const noexcept
00147         {
00148             return isWriteLogFile;
00149         }
00150 
00151         // включить запись лог файла
00152         inline void onLogFile( bool truncate = false )
00153         {
00154             logFile(fname, truncate);
00155         }
00156 
00157         // отключить запись логфайла
00158         inline void offLogFile() noexcept
00159         {
00160             logFile("");
00161         }
00162 
00164         inline bool debugging(Debug::type t = Debug::ANY) const noexcept
00165         {
00166             return (dt & t);
00167         }
00168 
00173         std::ostream& debug(Debug::type t = Debug::ANY) noexcept;
00174         //        if (dt & t) return *this;
00175         //        return nullstream;
00176         //    }
00177 
00178 
00183         std::ostream& operator[](Debug::type t) noexcept
00184         {
00185             return debug(t);
00186         }
00187 
00191         inline std::ostream& to_end(Debug::type t) noexcept
00192         {
00193             return this->operator()(t);
00194         }
00195 
00199         std::ostream& operator()(Debug::type t) noexcept;
00200 
00201         inline void showDateTime(bool s) noexcept
00202         {
00203             show_datetime = s;
00204         }
00205 
00206         inline void showMilliseconds( bool s ) noexcept
00207         {
00208             show_msec = s;
00209         }
00210 
00211         inline void showMicroseconds( bool s ) noexcept
00212         {
00213             show_usec = s;
00214         }
00215 
00216         inline void showLogType(bool s) noexcept
00217         {
00218             show_logtype = s;
00219         }
00220 
00221         inline std::ostream& log(Debug::type l) noexcept
00222         {
00223             return this->operator[](l);
00224         }
00225 
00226         // короткие функции (для удобства)
00227         // log.level1()  - вывод с датой и временем  "date time [LEVEL] ...",
00228         //    если вывод даты и времени не выключен при помощи showDateTime(false)
00229         // if( log.is_level1() ) - проверка включён ли лог.."
00230 
00231 #define DMANIP(FNAME,LEVEL) \
00232     inline std::ostream& FNAME( bool showdatetime=true ) noexcept \
00233     {\
00234         if( showdatetime )\
00235             return operator[](Debug::LEVEL); \
00236         return  operator()(Debug::LEVEL); \
00237     } \
00238     \
00239     inline bool is_##FNAME() const  noexcept\
00240     { return debugging(Debug::LEVEL); }
00241 
00242         DMANIP(level1, LEVEL1)
00243         DMANIP(level2, LEVEL2)
00244         DMANIP(level3, LEVEL3)
00245         DMANIP(level4, LEVEL4)
00246         DMANIP(level5, LEVEL5)
00247         DMANIP(level6, LEVEL6)
00248         DMANIP(level7, LEVEL7)
00249         DMANIP(level8, LEVEL8)
00250         DMANIP(level9, LEVEL9)
00251         DMANIP(info, INFO)
00252         DMANIP(warn, WARN)
00253         DMANIP(crit, CRIT)
00254         DMANIP(repository, REPOSITORY)
00255         DMANIP(system, SYSTEM)
00256         DMANIP(exception, EXCEPTION)
00257         DMANIP(any, ANY)
00258 #undef DMANIP
00259 
00260         std::ostream& printDate(Debug::type t, char brk = '/') noexcept;
00261         std::ostream& printTime(Debug::type t, char brk = ':') noexcept;
00262         std::ostream& printDateTime(Debug::type t) noexcept;
00263 
00264         std::ostream& pos(int x, int y) noexcept;
00265 
00266         const DebugStream& operator=(const DebugStream& r);
00267 
00268         inline void setLogName( const std::string& n ) noexcept
00269         {
00270             logname = n;
00271         }
00272 
00273         inline std::string  getLogName() const noexcept
00274         {
00275             return logname;
00276         }
00277 
00278         // ------------------------------------------------------------------------------------------------
00279         // RAII
00280         // https://stackoverflow.com/questions/2273330/restore-the-state-of-stdcout-after-manipulating-it
00281         class IosFlagSaver
00282         {
00283             public:
00284                 explicit IosFlagSaver(std::ostream& _ios):
00285                     ios(_ios),
00286                     f(_ios.flags())
00287                 {
00288                 }
00289                 ~IosFlagSaver()
00290                 {
00291                     ios.flags(f);
00292                 }
00293 
00294                 IosFlagSaver(const IosFlagSaver& rhs) = delete;
00295                 IosFlagSaver& operator= (const IosFlagSaver& rhs) = delete;
00296 
00297             private:
00298                 std::ostream& ios;
00299                 std::ios::fmtflags f;
00300         };
00301         // ------------------------------------------------------------------------------------------------
00302 
00303     protected:
00304         void sbuf_overflow( const std::string& s ) noexcept;
00305 
00306         // private:
00308         Debug::type dt = { Debug::NONE };
00310         std::ostream nullstream;
00312         struct debugstream_internal;
00314         debugstream_internal* internal = { 0 };
00315         bool show_datetime = { true };
00316         bool show_logtype = { true };
00317         bool show_msec = { false };
00318         bool show_usec = { false };
00319         std::string fname = { "" };
00320 
00321         StreamEvent_Signal s_stream;
00322         std::string logname = { "" };
00323 
00324         bool isWriteLogFile = { false };
00325 };
00326 // ------------------------------------------------------------------------------------------------
00327 #endif