Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 20, 2009, 4:55:40 PM (15 years ago)
Author:
rgrieder
Message:

Merged console branch back to trunk.

Location:
code/trunk
Files:
2 deleted
7 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/util/CMakeLists.txt

    r5929 r6105  
    2929  CRC32.cc
    3030  ExprParser.cc
    31   OutputBuffer.cc
    3231  OutputHandler.cc
    3332  SignalHandler.cc
  • code/trunk/src/libraries/util/Debug.h

    r5738 r6105  
    2121 *
    2222 *   Author:
    23  *      Benjamin Grauer
     23 *      Fabian 'x3n' Landau
     24 *      Reto Grieder
    2425 *   Co-authors:
    25  *      Fabian 'x3n' Landau
     26 *      ...
    2627 *
    2728 */
    2829
    2930/**
    30     @file
    31     @brief Handles different output-levels of errors, warnings, infos and debug information.
     31@file
     32@brief
     33    Handles different output-levels of errors, warnings, infos and debug information.
    3234
    3335    The COUT(level) macro acts like std::cout, but the output is only performed if the given
     
    3537
    3638    There are two used values in this file:
    37      - The hard debug level is used during compiletime. It describes the highest allowed output level.
     39     - The hard debug level is used during compile time. It describes the highest allowed output level.
    3840     - The soft debug level is used during runtime and is the maximum of the three configurable
    39        output-levels for console, logfile and ingame shell.
     41       output-levels for console, log file and in game shell.
    4042
    4143    The separation between the three devices is done by the OutputHandler.
     
    5052     6: Crazy debug information
    5153
    52     @example
     54@example
    5355    COUT(0) << "Very important output" << std::endl;
    5456    COUT(1) << "Error: Something went wrong!" << std::endl;
    5557    COUT(2) << "Warning: There might be a problem." << std::endl;
    56     COUT(3) << "Info: It's monday" << std::endl;
     58    COUT(3) << "Info: It's Monday" << std::endl;
    5759    COUT(4) << "Debug: x is 1.23456" << std::endl;
    58  */
     60*/
    5961
    60 #ifndef _Debug_H__
    61 #define _Debug_H__
     62#ifndef _Util_Debug_H__
     63#define _Util_Debug_H__
    6264
    6365#include "UtilPrereqs.h"
    64 
    6566#include "OutputHandler.h"
    6667
    6768namespace orxonox
    6869{
    69     /**
    70         @brief Returns the soft debug level, stored in the only existing instance of the OutputHandler class, configured in the config-file.
    71         @return The soft debug level
    72     */
    73     inline int getSoftDebugLevel()
    74     {
    75         return OutputHandler::getSoftDebugLevel();
    76     }
     70    // Just for convenience
     71    using std::endl;
    7772
    78     using std::endl;
     73    //! Adjust to discard certain output with level > hardDebugLevel at compile time
     74    const int hardDebugLevel = OutputLevel::Verbose;
    7975}
    8076
    81 // DEFINE ERROR MODES
    82 #define ORX_NONE            0
    83 #define ORX_ERROR           1
    84 #define ORX_WARNING         2
    85 #define ORX_INFO            3
    86 #define ORX_DEBUG           4
    87 #define ORX_VERBOSE         5
    88 #define ORX_ULTRA           6
     77/**
     78@brief
     79    Logs text output: use exactly like std::cout, but specify an output
     80    level as argument.
     81@example
     82    COUT(3) << "Some info" << std::endl;
     83@note
     84    The ? : operator requires both possible results to have the type of
     85    the first. This is achieved by the int conversion operator dummy
     86    in the OutputHandler.
     87*/
     88#define COUT(level)                                                    \
     89    /*if*/ (level > orxonox::hardDebugLevel) ?                         \
     90        0                                                              \
     91    /*else*/ :                                                         \
     92        /*if*/ (level > orxonox::OutputHandler::getSoftDebugLevel()) ? \
     93            0                                                          \
     94        /*else*/ :                                                     \
     95            orxonox::OutputHandler::getOutStream(level)
    8996
    90 //definitions
    91 #define ORX_PRINT_DEBUG_OUTPUT 1
    92 #define ORX_HARD_DEBUG_LEVEL ORX_VERBOSE
    93 
    94 #define COUT_EXEC(x) orxonox::OutputHandler::getOutStream().setOutputLevel(x)
    95 
    96 ////////////////////////////////////////////////////////
    97 ///  COUT: just prints output as is with std::cout   ///
    98 ////////////////////////////////////////////////////////
    99 #define COUTORX_NONE    COUT0
    100 #define COUTORX_ERROR   COUT1
    101 #define COUTORX_WARNING COUT2
    102 #define COUTORX_INFO    COUT3
    103 #define COUTORX_DEBUG   COUT4
    104 #define COUTORX_VERBOSE COUT5
    105 #define COUTORX_ULTRA   COUT6
    106 
    107 #ifndef COUT
    108  #if ORX_PRINT_DEBUG_OUTPUT
    109   #define COUT(x) \
    110    COUT ## x
    111 
    112   #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
    113    #define COUT0 \
    114    (orxonox::getSoftDebugLevel() < ORX_NONE) ? COUT_EXEC(0) : COUT_EXEC(0)
    115   #else
    116    #define COUT0 \
    117     false ? COUT_EXEC(0) : COUT_EXEC(0)
    118   #endif
    119 
    120   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    121    #define COUT1 \
    122     (orxonox::getSoftDebugLevel() < ORX_ERROR) ? COUT_EXEC(1) : COUT_EXEC(1)
    123   #else
    124    #define COUT1 \
    125     false ? COUT_EXEC(1) : COUT_EXEC(1)
    126   #endif
    127 
    128   #if ORX_HARD_DEBUG_LEVEL >= ORX_WARNING
    129    #define COUT2 \
    130     (orxonox::getSoftDebugLevel() < ORX_WARNING) ? COUT_EXEC(2) : COUT_EXEC(2)
    131   #else
    132    #define COUT2 \
    133     false ? COUT_EXEC(2) : COUT_EXEC(2)
    134   #endif
    135 
    136   #if ORX_HARD_DEBUG_LEVEL >= ORX_INFO
    137    #define COUT3 \
    138     (orxonox::getSoftDebugLevel() < ORX_INFO) ? COUT_EXEC(3) : COUT_EXEC(3)
    139   #else
    140    #define COUT3 \
    141     false ? COUT_EXEC(3) : COUT_EXEC(3)
    142   #endif
    143 
    144   #if ORX_HARD_DEBUG_LEVEL >= ORX_DEBUG
    145    #define COUT4 \
    146     (orxonox::getSoftDebugLevel() < ORX_DEBUG) ? COUT_EXEC(4) : COUT_EXEC(4)
    147   #else
    148    #define COUT4 \
    149     false ? COUT_EXEC(4) : COUT_EXEC(4)
    150   #endif
    151 
    152   #if ORX_HARD_DEBUG_LEVEL >= ORX_VERBOSE
    153    #define COUT5 \
    154     (orxonox::getSoftDebugLevel() < ORX_VERBOSE) ? COUT_EXEC(5) : COUT_EXEC(5)
    155   #else
    156    #define COUT5 \
    157     false ? COUT_EXEC(5) : COUT_EXEC(5)
    158   #endif
    159 
    160   #if ORX_HARD_DEBUG_LEVEL >= ORX_ULTRA
    161    #define COUT6 \
    162     (orxonox::getSoftDebugLevel() < ORX_ULTRA) ? COUT_EXEC(6) : COUT_EXEC(6)
    163   #else
    164    #define COUT6 \
    165     false ? COUT_EXEC(6) : COUT_EXEC(6)
    166   #endif
    167 
    168  #else /* if ORX_PRINT_DEBUG_OUTPUT */
    169   #define COUT(x) \
    170     false ? COUT_EXEC(6) : COUT_EXEC(6)
    171  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
    172 
    173 #endif /* ifndef COUT */
    174 
    175 
    176 /////////////////////////////////////////////////////////////////////
    177 ///  CCOUT: Prints output with std::cout and adds the classname   ///
    178 /////////////////////////////////////////////////////////////////////
    179 #define CCOUTORX_NONE    CCOUT0
    180 #define CCOUTORX_ERROR   CCOUT1
    181 #define CCOUTORX_WARNING CCOUT2
    182 #define CCOUTORX_INFO    CCOUT3
    183 #define CCOUTORX_DEBUG   CCOUT4
    184 #define CCOUTORX_VERBOSE CCOUT5
    185 #define CCOUTORX_ULTRA   CCOUT6
    186 
    187 #define CCOUT_EXEC(x) \
    188   orxonox::OutputHandler::getOutStream().setOutputLevel(x) \
    189   << this->getIdentifier()->getName() << ": "
    190 
    191 #ifndef CCOUT
    192  #if ORX_PRINT_DEBUG_OUTPUT
    193   #define CCOUT(x) \
    194    CCOUT ## x
    195 
    196   #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
    197    #define CCOUT0 \
    198     (orxonox::getSoftDebugLevel() < ORX_NONE) ? COUT_EXEC(0) : CCOUT_EXEC(0)
    199   #else
    200    #define CCOUT0 \
    201     false ? COUT_EXEC(0) : CCOUT_EXEC(0)
    202   #endif
    203 
    204   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    205    #define CCOUT1 \
    206     (orxonox::getSoftDebugLevel() < ORX_ERROR) ? COUT_EXEC(1) : CCOUT_EXEC(1)
    207   #else
    208    #define CCOUT1 \
    209     false ? COUT_EXEC(1) : CCOUT_EXEC(1)
    210   #endif
    211 
    212   #if ORX_HARD_DEBUG_LEVEL >= ORX_WARNING
    213    #define CCOUT2 \
    214     (orxonox::getSoftDebugLevel() < ORX_WARNING) ? COUT_EXEC(2) : CCOUT_EXEC(2)
    215   #else
    216    #define CCOUT2 \
    217     false ? COUT_EXEC(2) : CCOUT_EXEC(2)
    218   #endif
    219 
    220   #if ORX_HARD_DEBUG_LEVEL >= ORX_INFO
    221    #define CCOUT3 \
    222     (orxonox::getSoftDebugLevel() < ORX_INFO) ? COUT_EXEC(3) : CCOUT_EXEC(3)
    223   #else
    224    #define CCOUT3 \
    225     false ? COUT_EXEC(3) : CCOUT_EXEC(3)
    226   #endif
    227 
    228   #if ORX_HARD_DEBUG_LEVEL >= ORX_DEBUG
    229    #define CCOUT4 \
    230     (orxonox::getSoftDebugLevel() < ORX_DEBUG) ? COUT_EXEC(4) : CCOUT_EXEC(4)
    231   #else
    232    #define CCOUT4 \
    233     false ? COUT_EXEC(4) : CCOUT_EXEC(4)
    234   #endif
    235 
    236   #if ORX_HARD_DEBUG_LEVEL >= ORX_VERBOSE
    237    #define CCOUT5 \
    238     (orxonox::getSoftDebugLevel() < ORX_VERBOSE) ? COUT_EXEC(5) : CCOUT_EXEC(5)
    239   #else
    240    #define CCOUT5 \
    241     false ? COUT_EXEC(5) : CCOUT_EXEC(5)
    242   #endif
    243 
    244   #if ORX_HARD_DEBUG_LEVEL >= ORX_ULTRA
    245    #define CCOUT6 \
    246     (orxonox::getSoftDebugLevel() < ORX_ULTRA) ? COUT_EXEC(6) : CCOUT_EXEC(6)
    247   #else
    248    #define CCOUT6 \
    249     false ? COUT_EXEC(6) : CCOUT_EXEC(6)
    250   #endif
    251 
    252  #else /* if ORX_PRINT_DEBUG_OUTPUT */
    253   #define CCOUT(x) \
    254    false ? CCOUT_EXEC(6) : CCOUT_EXEC(6)
    255  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
    256 
    257 #endif /* ifndef CCOUT */
    258 
    259 #endif /* _Debug_H__ */
     97#endif /* _Util_Debug_H__ */
  • code/trunk/src/libraries/util/OrxAssert.h

    r5738 r6105  
    4444#ifndef NDEBUG
    4545#define OrxAssert(Assertion, ErrorMessage) \
    46     Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream().setOutputLevel(1) << ErrorMessage << std::endl); \
     46    Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream(1) << ErrorMessage << std::endl); \
    4747    assert(Assertion)
    4848#else
  • code/trunk/src/libraries/util/OutputHandler.cc

    r5738 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Implementation of the OutputHandler class.
     30@file
     31@brief
     32    Definition of classes related to output (logging).
    3233*/
    3334
    3435#include "OutputHandler.h"
    3536
     37#include <algorithm>
    3638#include <ctime>
    3739#include <cstdlib>
     40#include <fstream>
     41#include <sstream>
     42
     43#include "Debug.h"
    3844
    3945namespace orxonox
    4046{
     47    //! How the log file shall be named on the filesystem
     48    const std::string logFileBaseName_g = "orxonox.log";
     49
     50    /////////////////////////
     51    ///// LogFileWriter /////
     52    /////////////////////////
    4153    /**
    42         @brief Constructor: Opens the logfile and writes the first line.
    43         @param logfilename The name of the logfile
     54    @brief
     55        Writes the output to the log file.
     56    @note
     57        As long as the correct log path is not yet known (for pre main code), the
     58        LogFileWriter will write to a temporary file in /temp (Unix) or %TEMP% (Windows).
     59        As soon as you set the correct path setLogPath the content of the temporary file
     60        is read and put into the new file as well.
    4461    */
     62    class LogFileWriter : public OutputListener
     63    {
     64    public:
     65        /**
     66        @brief
     67            Gets temporary log path and starts the log file
     68        @param outputHandler
     69            This is only required to avoid another call to getInstance (this c'tor was
     70            called from getInstance!)
     71        */
     72        LogFileWriter()
     73            : OutputListener(OutputHandler::logFileOutputListenerName_s)
     74        {
     75            // Get path for a temporary file
     76#ifdef ORXONOX_PLATFORM_WINDOWS
     77            char* pTempDir = getenv("TEMP");
     78            this->logFilename_ = std::string(pTempDir) + "/" + logFileBaseName_g;
     79#else
     80            this->logFilename_ = std::string("/tmp/") + logFileBaseName_g;
     81#endif
     82
     83            // Get current time
     84            time_t rawtime;
     85            struct tm* timeinfo;
     86            time(&rawtime);
     87            timeinfo = localtime(&rawtime);
     88
     89            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     90            this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
     91            this->logFile_.flush();
     92
     93            this->outputStream_ = &this->logFile_;
     94        }
     95
     96        //! Closes the log file
     97        ~LogFileWriter()
     98        {
     99            this->logFile_ << "Closed log" << std::endl;
     100            this->logFile_.close();
     101        }
     102
     103        //! Changes the log path
     104        void setLogPath(const std::string& path)
     105        {
     106            this->logFile_.close();
     107            // Read old file into a buffer
     108            std::ifstream old(this->logFilename_.c_str());
     109            this->logFilename_ = path + logFileBaseName_g;
     110            // Open the new file and feed it the content of the old one
     111            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     112            this->logFile_ << old.rdbuf();
     113            this->logFile_.flush();
     114            old.close();
     115        }
     116
     117    private:
     118        std::ofstream logFile_;     //! File handle for the log file
     119        std::string   logFilename_; //! Filename of the log file
     120    };
     121
     122
     123    /////////////////////////
     124    ///// ConsoleWriter /////
     125    /////////////////////////
     126    /**
     127    @brief
     128        Writes the output to std::cout.
     129    @note
     130        This listener will usually be disable once an actual shell with console is instantiated.
     131    */
     132    class ConsoleWriter : public OutputListener
     133    {
     134    public:
     135        //! Only assigns the output stream with std::cout
     136        ConsoleWriter()
     137            : OutputListener("consoleLog")
     138        {
     139            this->outputStream_ = &std::cout;
     140        }
     141    };
     142
     143
     144    ///////////////////////////
     145    ///// MemoryLogWriter /////
     146    ///////////////////////////
     147    /**
     148    @brief
     149        OutputListener that writes all the output piece by piece to an array
     150        associated with the corresponding output level.
     151    @note
     152        Only output below or equal to the current soft debug level is written
     153        to minimise huge arrays for the normal run.
     154    */
     155    class MemoryLogWriter : public OutputListener
     156    {
     157    public:
     158        friend class OutputHandler;
     159
     160        /**
     161        @brief
     162            Sets the right soft debug level and registers itself
     163        @param outputHandler
     164            This is only required to avoid another call to getInstance (this c'tor was
     165            called from getInstance!)
     166        */
     167        MemoryLogWriter()
     168            : OutputListener("memoryLog")
     169        {
     170            this->outputStream_ = &this->buffer_;
     171        }
     172
     173        //! Pushed the just written output to the internal array
     174        void outputChanged(int level)
     175        {
     176            // Read ostringstream and store it
     177            this->output_.push_back(std::make_pair(level, this->buffer_.str()));
     178            // Clear content and flags
     179            this->buffer_.str(std::string());
     180            this->buffer_.clear();
     181        }
     182
     183    private:
     184        std::ostringstream                        buffer_; //! Stream object used to process the output
     185        std::vector<std::pair<int, std::string> > output_; //! Vector containing ALL output
     186    };
     187
     188
     189    /////////////////////////
     190    ///// OutputHandler /////
     191    /////////////////////////
     192    const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
     193          int         OutputHandler::softDebugLevel_s = hardDebugLevel;
     194
     195    //! Creates the LogFileWriter and the MemoryLogWriter
    45196    OutputHandler::OutputHandler()
    46     {
    47 #ifdef ORXONOX_PLATFORM_WINDOWS
    48         char* pTempDir = getenv("TEMP");
    49         this->logfilename_ = std::string(pTempDir) + "/orxonox.log";
     197        : outputLevel_(OutputLevel::Verbose)
     198    {
     199#ifdef ORXONOX_RELEASE
     200        const OutputLevel::Value defaultLevelConsole = OutputLevel::Error;
     201        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Info;
    50202#else
    51         this->logfilename_ = "/tmp/orxonox.log";
     203        const OutputLevel::Value defaultLevelConsole = OutputLevel::Info;
     204        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Debug;
    52205#endif
    53 #ifdef NDEBUG
    54         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 2;
    55         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 1;
    56 #else
    57         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 3;
    58         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 2;
    59 #endif
    60 
    61         this->outputBuffer_ = &this->fallbackBuffer_;
    62         this->logfile_.open(this->logfilename_.c_str(), std::fstream::out);
    63 
    64         time_t rawtime;
    65         struct tm* timeinfo;
    66         time(&rawtime);
    67         timeinfo = localtime(&rawtime);
    68 
    69         this->logfile_ << "Started log on " << asctime(timeinfo) << std::endl;
    70         this->logfile_.flush();
    71     }
    72 
    73     /**
    74         @brief Destructor: Writes the last line to the logfile and closes it.
    75     */
     206
     207        this->logFile_ = new LogFileWriter();
     208        // Use default level until we get the configValue from the Core
     209        this->logFile_->softDebugLevel_ = defaultLevelLogFile;
     210        this->registerOutputListener(this->logFile_);
     211
     212        this->consoleWriter_ = new ConsoleWriter();
     213        this->consoleWriter_->softDebugLevel_ = defaultLevelConsole;
     214        this->registerOutputListener(this->consoleWriter_);
     215
     216        this->output_  = new MemoryLogWriter();
     217        // We capture as much input as the listener with the highest level
     218        this->output_->softDebugLevel_ = getSoftDebugLevel();
     219        this->registerOutputListener(this->output_);
     220    }
     221
     222    //! Destroys the LogFileWriter and the MemoryLogWriter
    76223    OutputHandler::~OutputHandler()
    77224    {
    78         this->logfile_ << "Closed log" << std::endl;
    79         this->logfile_.close();
    80     }
    81 
    82     /**
    83         @brief Returns a reference to the only existing instance of the OutputHandler class.
    84         @return The instance
    85     */
    86     OutputHandler& OutputHandler::getOutStream()
     225        delete this->logFile_;
     226        delete this->output_;
     227    }
     228
     229    OutputHandler& OutputHandler::getInstance()
    87230    {
    88231        static OutputHandler orxout;
     
    90233    }
    91234
    92     /**
    93         @brief Sets the soft debug level for a given output device.
    94         @param device The output device
    95         @param level The debug level
    96     */
    97     void OutputHandler::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    98     {
    99         OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)] = level;
    100     }
    101 
    102     /**
    103         @brief Returns the soft debug level for a given output device.
    104         @param device The output device
    105         @return The debug level
    106     */
    107     int OutputHandler::getSoftDebugLevel(OutputHandler::OutputDevice device)
    108     {
    109         return OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)];
    110     }
    111 
    112     /**
    113         @brief Sets the OutputBuffer, representing the third output stream.
    114         @param buffer The OutputBuffer
    115     */
    116     void OutputHandler::setOutputBuffer(OutputBuffer* buffer)
    117     {
    118         if (buffer == NULL)
    119             this->outputBuffer_ = &this->fallbackBuffer_;
    120         else
    121         {
    122             buffer->getStream() >> this->outputBuffer_->getStream().rdbuf();
    123             this->outputBuffer_ = buffer;
    124         }
    125     }
    126 
    127     /**
    128         @brief Sets the path where to create orxonox.log
    129         @param Path string with trailing slash
    130     */
     235    void OutputHandler::registerOutputListener(OutputListener* listener)
     236    {
     237        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     238        {
     239            if ((*it)->name_ == listener->name_)
     240            {
     241                COUT(2) << "OutputHandler, Warning: Trying to register two listeners with the same name!" << std::endl;
     242                return;
     243            }
     244        }
     245        this->listeners_.push_back(listener);
     246        // Update global soft debug level
     247        this->setSoftDebugLevel(listener->getOutputListenerName(), listener->getSoftDebugLevel());
     248    }
     249
     250    void OutputHandler::unregisterOutputListener(OutputListener* listener)
     251    {
     252        this->listeners_.remove(listener);
     253    }
     254
    131255    void OutputHandler::setLogPath(const std::string& path)
    132256    {
    133         OutputHandler::getOutStream().logfile_.close();
    134         // store old content
    135         std::ifstream old;
    136         old.open(OutputHandler::getOutStream().logfilename_.c_str());
    137         OutputHandler::getOutStream().logfilename_ = path + "orxonox.log";
    138         OutputHandler::getOutStream().logfile_.open(OutputHandler::getOutStream().logfilename_.c_str(), std::fstream::out);
    139         OutputHandler::getOutStream().logfile_ << old.rdbuf();
    140         old.close();
    141         OutputHandler::getOutStream().logfile_.flush();
    142     }
    143 
    144     /**
    145         @brief Overloaded << operator, redirects the output to the console and the logfile.
    146         @param sb The streambuffer that should be shown in the console
    147         @return A reference to the OutputHandler itself
    148     */
    149     OutputHandler& OutputHandler::operator<<(std::streambuf* sb)
    150     {
    151         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    152             std::cout << sb;
    153 
    154         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    155         {
    156             this->logfile_ << sb;
    157             this->logfile_.flush();
    158         }
    159 
    160         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    161             (*this->outputBuffer_) << sb;
    162 
    163         return *this;
    164     }
    165 
    166     /**
    167         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    168         @param manipulator A function, manipulating the outstream.
    169         @return A reference to the OutputHandler itself
    170     */
    171     OutputHandler& OutputHandler::operator<<(std::ostream& (*manipulator)(std::ostream&))
    172     {
    173         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    174             manipulator(std::cout);
    175 
    176         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    177         {
    178             manipulator(this->logfile_);
    179             this->logfile_.flush();
    180         }
    181 
    182         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    183             (*this->outputBuffer_) << manipulator;
    184 
    185         return *this;
    186     }
    187 
    188     /**
    189         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    190         @param manipulator A function, manipulating the outstream.
    191         @return A reference to the OutputHandler itself
    192     */
    193     OutputHandler& OutputHandler::operator<<(std::ios& (*manipulator)(std::ios&))
    194     {
    195         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    196             manipulator(std::cout);
    197 
    198         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    199         {
    200             manipulator(this->logfile_);
    201             this->logfile_.flush();
    202         }
    203 
    204         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    205             (*this->outputBuffer_) << manipulator;
    206 
    207         return *this;
    208     }
    209 
    210     /**
    211         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    212         @param manipulator A function, manipulating the outstream.
    213         @return A reference to the OutputHandler itself
    214     */
    215     OutputHandler& OutputHandler::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
    216     {
    217         if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    218             manipulator(std::cout);
    219 
    220         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    221         {
    222             manipulator(this->logfile_);
    223             this->logfile_.flush();
    224         }
    225 
    226         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    227             (*this->outputBuffer_) << manipulator;
    228 
    229         return *this;
     257        this->logFile_->setLogPath(path);
     258    }
     259
     260    void OutputHandler::disableCout()
     261    {
     262        this->unregisterOutputListener(this->consoleWriter_);
     263    }
     264
     265    void OutputHandler::enableCout()
     266    {
     267        this->registerOutputListener(this->consoleWriter_);
     268    }
     269
     270    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
     271    {
     272        return this->output_->output_.begin();
     273    }
     274
     275    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
     276    {
     277        return this->output_->output_.end();
     278    }
     279
     280    int OutputHandler::getSoftDebugLevel(const std::string& name) const
     281    {
     282        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     283        {
     284            if ((*it)->name_ == name)
     285                return (*it)->softDebugLevel_;
     286        }
     287        return -1;
     288    }
     289
     290    void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
     291    {
     292        int globalSoftDebugLevel = -1;
     293        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     294        {
     295            if ((*it)->name_ == name)
     296                (*it)->softDebugLevel_ = level;
     297            if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
     298                globalSoftDebugLevel = (*it)->softDebugLevel_;
     299        }
     300        // Update global soft debug level
     301        OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
    230302    }
    231303}
  • code/trunk/src/libraries/util/OutputHandler.h

    r5738 r6105  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Definition of the OutputHandler class.
    32 
    33     The OutputHandler acts like std::cout, but output isn't only shown in the console,
    34     but also written to the logfile and the ingame shell.
     30@file
     31@brief
     32    Declaration of classes related to output (logging).
    3533*/
    3634
     
    4038#include "UtilPrereqs.h"
    4139
    42 #include <iostream>
    43 #include <fstream>
     40#include <list>
     41#include <ostream>
    4442#include <string>
    45 
    46 #include "OutputBuffer.h"
     43#include <vector>
     44#include <utility>
    4745
    4846namespace orxonox
    4947{
    50     //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
     48    /**
     49    @brief
     50        Denotes different levels of text output (log output)
     51
     52        0, None   : Very important output
     53        1, Error  : Errors
     54        2, Warning: Warnings
     55        3, Info   : Information
     56        4, Debug  : Debug information
     57        5, Verbose: More debug information
     58        6, Ultra  : Crazy debug information
     59    */
     60    namespace OutputLevel
     61    {
     62        enum Value
     63        {
     64            None    = 0,
     65            Error   = 1,
     66            Warning = 2,
     67            Info    = 3,
     68            Debug   = 4,
     69            Verbose = 5,
     70            Ultra   = 6,
     71        };
     72    }
     73
     74    // Forward declarations for classes in the source file
     75    class LogFileWriter;
     76    class ConsoleWriter;
     77    class MemoryLogWriter;
     78
     79    /**
     80    @brief
     81        The OutputHandler acts like std::cout, but output isn't only shown in the console.
     82
     83        You can register your own listener for output by inheriting from OutputListner.
     84        And if you need the output previously processed, iterate over it with
     85        OutputHandler::getOutputVector[Begin/End].
     86        The way to output text is to first set the desired output level with
     87        OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
     88    */
    5189    class _UtilExport OutputHandler
    5290    {
    5391        public:
    54             enum OutputDevice
    55             {
    56                 LD_All = 0,
    57                 LD_Console = 1,
    58                 LD_Logfile = 2,
    59                 LD_Shell = 3
    60             };
    61 
    62             static OutputHandler& getOutStream();
    63 
    64             /** @brief Puts some text on the outstream. @param text The text */
     92            //! Returns a reference to the only existing instance of the OutputHandler class.
     93            static OutputHandler& getInstance();
     94
     95            //! Sets the output level and returns a stream to be used with "<<"
     96            static inline OutputHandler& getOutStream(int level)
     97                { return OutputHandler::getInstance().setOutputLevel(level); }
     98
     99            typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
     100            //! Returns an iterator to the beginning of the all-output vector
     101            OutputVectorIterator getOutputVectorBegin() const;
     102            //! Returns an iterator to the end of the all-output vector
     103            OutputVectorIterator getOutputVectorEnd() const;
     104
     105            //! Writes to all output devices
    65106            static inline const std::string& log(const std::string& text)
    66                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
    67 
    68             /** @brief Puts an error on the outstream. @param text The text */
     107                { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
     108
     109            //! Writes an error message to the output
    69110            static inline const std::string& error(const std::string& text)
    70                 { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
    71 
    72             /** @brief Puts a warning on the outstream. @param text The text */
     111                { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
     112
     113            //! Writes a warning message to the output
    73114            static inline const std::string& warning(const std::string& text)
    74                 { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
    75 
    76             /** @brief Puts an info on the outstream. @param text The text */
     115                { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
     116
     117            //! Writes an informational message to the output
    77118            static inline const std::string& info(const std::string& text)
    78                 { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
    79 
    80             /** @brief Puts some debug output on the outstream. @param text The text */
     119                { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
     120
     121            //! Writes a debug message to the output
    81122            static inline const std::string& debug(const std::string& text)
    82                 { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
    83 
    84             /** @brief Returns a reference to the logfile. @return The logfile */
    85             inline std::ofstream& getLogfile()
    86                 { return this->logfile_; }
    87 
    88             /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
    89             inline OutputBuffer* getOutputBuffer()
    90                 { return this->outputBuffer_; }
    91 
    92             /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
     123                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
     124
     125            //! Registers an object that receives output via a provided std::ostream
     126            void registerOutputListener(OutputListener* listener);
     127            //! Unregisters an object that receives output via a provided std::ostream
     128            void unregisterOutputListener(OutputListener* listener);
     129
     130            //! Set the log path once the program has been properly initialised
     131            void setLogPath(const std::string& path);
     132            //! Disables the std::cout stream for output
     133            void disableCout();
     134            //! Enables the std::cout stream for output (startup behaviour)
     135            void enableCout();
     136
     137            //! Sets the level of the incoming output and returns the OutputHandler
    93138            inline OutputHandler& setOutputLevel(int level)
    94139                { this->outputLevel_ = level; return *this; }
    95140
    96             /** @brief Returns the level of the incoming output. @return The level */
     141            //! Returns the level of the incoming output
    97142            inline int getOutputLevel() const
    98143                { return this->outputLevel_; }
    99144
    100             static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    101             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    102 
    103             static void setLogPath(const std::string& path);
    104 
    105             void setOutputBuffer(OutputBuffer* buffer);
    106 
     145            //! Returns the maximum debug level over all registered listeners (devices)
     146            static int getSoftDebugLevel() { return softDebugLevel_s; }
     147            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
     148            int  getSoftDebugLevel(const std::string& name) const;
     149            //! Sets the soft debug level for a listener by its name   @remarks Only works for registered listeners!
     150            void setSoftDebugLevel(const std::string& name, int level);
     151
     152            /**
     153            @brief
     154                General template that copes with all output.
     155                Required because operator << might be ambiguous.
     156                @a output will be streamed into every listener with an appropriate debug level
     157            @return
     158                Returns a reference to the OutputHandler so you can use it again directly
     159            */
    107160            template <class T>
    108161            OutputHandler& output(const T& output);
    109162
    110             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     163            //! Overloaded << operator, redirects the output to the listeners
    111164            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
    112             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     165            //! Overloaded << operator, redirects the output to the listeners
    113166            inline OutputHandler& operator<<(short val)              { return this->output(val); }
    114             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     167            //! Overloaded << operator, redirects the output to the listeners
    115168            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
    116             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     169            //! Overloaded << operator, redirects the output to the listeners
    117170            inline OutputHandler& operator<<(int val)                { return this->output(val); }
    118             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     171            //! Overloaded << operator, redirects the output to the listeners
    119172            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
    120             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     173            //! Overloaded << operator, redirects the output to the listeners
    121174            inline OutputHandler& operator<<(long val)               { return this->output(val); }
    122             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     175            //! Overloaded << operator, redirects the output to the listeners
    123176            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
    124             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     177            //! Overloaded << operator, redirects the output to the listeners
    125178            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
    126             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     179            //! Overloaded << operator, redirects the output to the listeners
    127180            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
    128             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     181            //! Overloaded << operator, redirects the output to the listeners
    129182            inline OutputHandler& operator<<(float val)              { return this->output(val); }
    130             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     183            //! Overloaded << operator, redirects the output to the listeners
    131184            inline OutputHandler& operator<<(double val)             { return this->output(val); }
    132             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     185            //! Overloaded << operator, redirects the output to the listeners
    133186            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
    134             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     187            //! Overloaded << operator, redirects the output to the listeners
    135188            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
    136             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     189            //! Overloaded << operator, redirects the output to the listeners
    137190            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
    138191
    139             OutputHandler& operator<<(std::streambuf* sb);
    140 
    141             OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
    142             OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
    143             OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
     192            //! Overloaded << operator, redirects the output to the listeners
     193            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
     194
     195            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
     196            template <class T>
     197            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
     198
     199            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     200            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
     201            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     202            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
     203            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     204            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
     205
     206            //! Dummy operator required by Debug.h for the ternary operator
     207            inline operator int() const { return 0; }
     208
     209            //! Name of the OutputListener that writes to the log file
     210            static const std::string logFileOutputListenerName_s;
    144211
    145212        private:
    146             explicit OutputHandler();
    147             OutputHandler(const OutputHandler& oh);
    148             virtual ~OutputHandler();
    149 
    150             std::ofstream logfile_;              //!< The logfile where the output is logged
    151             std::string logfilename_;            //!< The name of the logfile
    152             OutputBuffer fallbackBuffer_;        //!< The OutputBuffer that gets used if there is no other OutputBuffer
    153             OutputBuffer* outputBuffer_;         //!< The OutputBuffer to put output in (usually used by the Shell)
    154             int outputLevel_;                    //!< The level of the incoming output
    155             int softDebugLevel_[4];              //!< The soft debug level for each OutputDevice - the configurable maximal output level
     213            OutputHandler();
     214            ~OutputHandler();
     215            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
     216
     217            std::list<OutputListener*> listeners_;        //!< Array with all registered output listeners
     218            int                        outputLevel_;      //!< The level of the incoming output
     219            LogFileWriter*             logFile_;          //!< Listener that writes to the log file
     220            ConsoleWriter*             consoleWriter_;    //!< Listener for std::cout (just program beginning)
     221            MemoryLogWriter*           output_;           //!< Listener that Stores ALL output below the current soft debug level
     222            static int                 softDebugLevel_s;  //!< Maximum of all soft debug levels. @note This is only static for faster access
    156223    };
    157224
    158225    /**
    159         @brief Redirects the output to the console and the logfile.
    160         @param output The value that should be shown in the console
    161         @return A reference to the OutputHandler itself
     226    @brief
     227        Interface for listening to output.
     228    @remarks
     229        Remember to register the listener (not done automatically!)
    162230    */
     231    class OutputListener
     232    {
     233        friend class OutputHandler;
     234
     235    public:
     236        OutputListener(const std::string& name)
     237            : outputStream_(NULL)
     238            , name_(name)
     239            , softDebugLevel_(OutputLevel::Info)
     240        {}
     241        virtual ~OutputListener() {}
     242
     243        //! Gets called whenever output is put into the stream
     244        virtual void outputChanged(int level) {}
     245        //! Returns the name of this output listener
     246        const std::string& getOutputListenerName() const { return this->name_; }
     247        //! Returns the soft debug level of the listener
     248        int getSoftDebugLevel() const { return this->softDebugLevel_; }
     249        //! Sets the soft debug level of the listener
     250        void setSoftDebugLevel(int level)
     251        {
     252            this->softDebugLevel_ = level;
     253            OutputHandler::getInstance().setSoftDebugLevel(this->name_, level);
     254        }
     255
     256    protected:
     257        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
     258
     259    private:
     260        const std::string name_;           //!< Name of the listener, constant and unique!
     261        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
     262    };
     263
    163264    template<class T>
    164     OutputHandler& OutputHandler::output(const T& output)
    165     {
    166         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    167             std::cout << output;
    168 
    169         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
     265    inline OutputHandler& OutputHandler::output(const T& output)
     266    {
     267        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
    170268        {
    171             this->logfile_ << output;
    172             this->logfile_.flush();
     269            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
     270            {
     271                std::ostream& stream = *((*it)->outputStream_);
     272                stream << output;
     273                stream.flush();
     274                (*it)->outputChanged(this->outputLevel_);
     275            }
    173276        }
    174 
    175         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    176             (*this->outputBuffer_) << output;
    177277
    178278        return *this;
    179279    }
    180 
    181     /**
    182         @brief Overloading of the non-member << operator to redirect the output of classes with self defined '<< to std::ostream' operators to the console and the logfile.
    183         @param out The OutputHandler itself
    184         @param output The class that should be shown in the console
    185         @return The OutputHandler itself
    186     */
    187     template<class T>
    188     OutputHandler& operator<<(OutputHandler& out, const T& output)
    189     {
    190         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
    191             std::cout << output;
    192 
    193         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
    194         {
    195             out.getLogfile() << output;
    196             out.getLogfile().flush();
    197         }
    198 
    199         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
    200             (*out.getOutputBuffer()) << output;
    201 
    202         return out;
    203     }
    204280}
    205281
  • code/trunk/src/libraries/util/UtilPrereqs.h

    r5929 r6105  
    8787    class IntVector3;
    8888    class MultiType;
    89     class OutputBuffer;
    90     class OutputBufferListener;
    9189    class OutputHandler;
     90    class OutputListener;
    9291    template <ScopeID::Value>
    9392    class Scope;
Note: See TracChangeset for help on using the changeset viewer.