LCOV - code coverage report
Current view: top level - src/utils/common - MsgHandler.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 20 20
Test Date: 2024-11-22 15:46:21 Functions: 81.8 % 66 54

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2003-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MsgHandler.h
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Mirko Barthauer
      19              : /// @date    Tue, 17 Jun 2003
      20              : ///
      21              : // Retrieves messages about the process and gives them further to output
      22              : /****************************************************************************/
      23              : #pragma once
      24              : #include <config.h>
      25              : #include <string>
      26              : #include <vector>
      27              : #include <map>
      28              : #include <utils/common/StringUtils.h>
      29              : #include <utils/common/Translation.h>
      30              : #include <utils/iodevices/OutputDevice.h>
      31              : 
      32              : 
      33              : // ===========================================================================
      34              : // class definitions
      35              : // ===========================================================================
      36              : /**
      37              :  * MsgHandler
      38              :  */
      39              : class MsgHandler {
      40              : public:
      41              :     /**
      42              :      * @enum MsgType
      43              :      * An enumeration to differ between different types of messages
      44              :      * (errors, warning and information)
      45              :      */
      46              :     enum class MsgType {
      47              :         /// The message is only something to show
      48              :         MT_MESSAGE,
      49              :         /// The message is a warning
      50              :         MT_WARNING,
      51              :         /// The message is an error
      52              :         MT_ERROR,
      53              :         /// The message is debug output
      54              :         MT_DEBUG,
      55              :         /// The message is GL debug output
      56              :         MT_GLDEBUG
      57              :     };
      58              : 
      59              : private:
      60              :     typedef MsgHandler* (*Factory)(MsgType);
      61              : 
      62              : public:
      63              :     /// @brief Sets the factory function to use for new MsgHandlers
      64              :     static void setFactory(Factory func) {
      65              :         // clean old instances
      66        11623 :         cleanupOnEnd();
      67        11623 :         myFactory = func;
      68         4060 :     }
      69              : 
      70              :     /// @brief Returns the instance to add normal messages to
      71              :     static MsgHandler* getMessageInstance();
      72              : 
      73              :     /// @brief Returns the instance to add warnings to
      74              :     static MsgHandler* getWarningInstance();
      75              : 
      76              :     /// @brief Returns the instance to add errors to
      77              :     static MsgHandler* getErrorInstance();
      78              : 
      79              :     /// @brief Returns the instance to add debug to
      80              :     static MsgHandler* getDebugInstance();
      81              : 
      82              :     /// @brief Returns the instance to add GLdebug to
      83              :     static MsgHandler* getGLDebugInstance();
      84              : 
      85              :     /// @brief enable/disable debug messages
      86              :     static void enableDebugMessages(bool enable);
      87              : 
      88              :     /// @brief enable/disable gl-debug messages
      89              :     static void enableDebugGLMessages(bool enable);
      90              : 
      91              :     /// @brief check whether to enable/disable debug messages
      92              :     static inline bool writeDebugMessages() {
      93         1467 :         return myWriteDebugMessages;
      94              :     }
      95              : 
      96              :     /// @brief check whether to enable/disable gl-debug messages
      97              :     static inline bool writeDebugGLMessages() {
      98        61456 :         return myWriteDebugGLMessages;
      99              :     }
     100              : 
     101              :     /// @brief reformats a long string to contain newline after a certain line length in px (depending on the current font)
     102              :     static std::string insertLineBreaks(std::string msg, int lineWidth);
     103              : 
     104              :     /// @brief ensure that that given output device is no longer used as retriever by any instance
     105              :     static void removeRetrieverFromAllInstances(OutputDevice* out);
     106              : 
     107              :     ///@brief set up gettext stuff
     108              :     static void setupI18n(const std::string& locale = "");
     109              : 
     110              :     ///@brief init output options
     111              :     static void initOutputOptions();
     112              : 
     113              :     /// @brief Removes pending handler
     114              :     static void cleanupOnEnd();
     115              : 
     116              :     /// @brief adds a new error to the list
     117              :     virtual void inform(std::string msg, bool addType = true);
     118              : 
     119              :     /// @brief adds a new formatted message
     120              :     // variadic function
     121              :     template<typename T, typename... Targs>
     122       429989 :     void informf(const std::string& format, T value, Targs... Fargs) {
     123       429989 :         if (!aggregationThresholdReached(format)) {
     124      1150823 :             inform(StringUtils::format(format, value, Fargs...), true);
     125              :         }
     126       429989 :     }
     127              : 
     128              :     /** @brief Begins a process information
     129              :      *
     130              :      * When a longer action is started, this method should be used to inform the user about it.
     131              :      * There will be no newline printed, but the message handler will be informed that
     132              :      *  a process message has been begun. If an error occurs, a newline will be printed.
     133              :      * After the action has been performed, use endProcessMsg to inform the user about it.
     134              :      */
     135              :     virtual void beginProcessMsg(std::string msg, bool addType = true);
     136              : 
     137              :     /// @brief Ends a process information with predefined messages
     138              :     virtual void endProcessMsg2(bool success, long duration = -1);
     139              : 
     140              :     /// @brief Ends a process information
     141              :     virtual void endProcessMsg(std::string msg);
     142              : 
     143              :     /// @brief Clears information whether an error occurred previously and print aggregated message summary
     144              :     virtual void clear(bool resetInformed = true);
     145              : 
     146              :     /// @brief Adds a further retriever to the instance responsible for a certain msg type
     147              :     virtual void addRetriever(OutputDevice* retriever);
     148              : 
     149              :     /// @brief Removes the retriever from the handler
     150              :     virtual void removeRetriever(OutputDevice* retriever);
     151              : 
     152              :     /// @brief Returns whether the given output device retrieves messages from the handler
     153              :     bool isRetriever(OutputDevice* retriever) const;
     154              : 
     155              :     /// @brief Returns the information whether any messages were added
     156              :     bool wasInformed() const;
     157              : 
     158              :     /** @brief Generic output operator
     159              :      * @return The MsgHandler for further processing
     160              :      */
     161              :     template <class T>
     162              :     MsgHandler& operator<<(const T& t) {
     163              :         // inform all other receivers
     164              :         for (OutputDevice* o : myRetrievers) {
     165              :             (*o) << t;
     166              :         }
     167              :         return *this;
     168              :     }
     169              : 
     170              : protected:
     171              : 
     172              :     std::string buildTimestampPrefix(void) const;
     173              :     std::string buildProcessIdPrefix(void) const;
     174              : 
     175              :     /// @brief Builds the string which includes the mml-message type
     176      1242340 :     inline std::string build(const std::string& msg, bool addType) {
     177              :         std::string prefix;
     178      1242340 :         if (myWriteTimestamps) {
     179           10 :             prefix += buildTimestampPrefix();
     180              :         }
     181      1242340 :         if (myWriteProcessId) {
     182           10 :             prefix += buildProcessIdPrefix();
     183              :         }
     184      1242340 :         if (addType) {
     185      1232932 :             switch (myType) {
     186              :                 case MsgType::MT_MESSAGE:
     187              :                     break;
     188              :                 case MsgType::MT_WARNING:
     189              :                     prefix += myWarningPrefix;
     190              :                     break;
     191              :                 case MsgType::MT_ERROR:
     192              :                     prefix += myErrorPrefix;
     193              :                     break;
     194              :                 case MsgType::MT_DEBUG:
     195              :                     prefix += "Debug: ";
     196              :                     break;
     197              :                 case MsgType::MT_GLDEBUG:
     198              :                     prefix += "GLDebug: ";
     199              :                     break;
     200              :                 default:
     201              :                     break;
     202              :             }
     203              :         }
     204      1242340 :         return prefix + msg;
     205              :     }
     206              : 
     207       429989 :     virtual bool aggregationThresholdReached(const std::string& format) {
     208       429989 :         return myAggregationThreshold >= 0 && myAggregationCount[format]++ >= myAggregationThreshold;
     209              :     }
     210              : 
     211              :     void setAggregationThreshold(const int thresh) {
     212       110518 :         myAggregationThreshold = thresh;
     213              :     }
     214              : 
     215              :     /// @brief standard constructor
     216              :     MsgHandler(MsgType type);
     217              : 
     218              :     /// @brief destructor
     219              :     virtual ~MsgHandler();
     220              : 
     221              : private:
     222              :     /// @brief The function to call for new MsgHandlers, nullptr means use default constructor
     223              :     static Factory myFactory;
     224              : 
     225              :     /// @brief The instance to handle debug
     226              :     static MsgHandler* myDebugInstance;
     227              : 
     228              :     /// @brief The instance to handle glDebug
     229              :     static MsgHandler* myGLDebugInstance;
     230              : 
     231              :     /// @brief The instance to handle errors
     232              :     static MsgHandler* myErrorInstance;
     233              : 
     234              :     /// @brief The instance to handle warnings
     235              :     static MsgHandler* myWarningInstance;
     236              : 
     237              :     /// @brief The instance to handle normal messages
     238              :     static MsgHandler* myMessageInstance;
     239              : 
     240              :     /// @brief Information whether a process information is printed to cout
     241              :     static bool myAmProcessingProcess;
     242              : 
     243              : private:
     244              :     /// @brief The type of the instance
     245              :     MsgType myType;
     246              : 
     247              :     /// @brief information whether an output occurred at all
     248              :     bool myWasInformed;
     249              : 
     250              :     /// @brief do not output more messages of the same type if the count exceeds this threshold
     251              :     int myAggregationThreshold;
     252              : 
     253              :     /// @brief count for messages of the same type
     254              :     std::map<const std::string, int> myAggregationCount;
     255              : 
     256              :     /// @brief The list of retrievers that shall be informed about new messages or errors
     257              :     std::vector<OutputDevice*> myRetrievers;
     258              : 
     259              :     /// @brief storage for initial messages
     260              :     std::vector<std::string> myInitialMessages;
     261              : 
     262              :     /** @brief Flag to enable or disable debug output
     263              :      *
     264              :      * This value is used to show more internal information through warning messages about certain operations
     265              :      */
     266              :     static bool myWriteDebugMessages;
     267              : 
     268              :     /// @brief Flag to enable or disable GL specific debug output
     269              :     static bool myWriteDebugGLMessages;
     270              : 
     271              :     /// @brief Whether to prefix every message with a time stamp
     272              :     static bool myWriteTimestamps;
     273              : 
     274              :     /// @brief Whether to prefix every message with the process id
     275              :     static bool myWriteProcessId;
     276              : 
     277              :     /// @brief The possibly translated error prefix (mainly for speedup)
     278              :     static std::string myErrorPrefix;
     279              : 
     280              :     /// @brief The possibly translated warning prefix (mainly for speedup)
     281              :     static std::string myWarningPrefix;
     282              : 
     283              : private:
     284              :     /// @brief invalid copy constructor
     285              :     MsgHandler(const MsgHandler& s) = delete;
     286              : 
     287              :     /// @brief invalid assignment operator
     288              :     MsgHandler& operator=(const MsgHandler& s) = delete;
     289              : };
     290              : 
     291              : 
     292              : // ===========================================================================
     293              : // global definitions
     294              : // ===========================================================================
     295              : #define WRITE_WARNING(msg) MsgHandler::getWarningInstance()->inform(msg);
     296              : #define WRITE_WARNINGF(...) MsgHandler::getWarningInstance()->informf(__VA_ARGS__);
     297              : #define WRITE_MESSAGE(msg) MsgHandler::getMessageInstance()->inform(msg);
     298              : #define WRITE_MESSAGEF(...) MsgHandler::getMessageInstance()->informf(__VA_ARGS__);
     299              : #define PROGRESS_BEGIN_MESSAGE(msg) MsgHandler::getMessageInstance()->beginProcessMsg((msg) + std::string(" ..."));
     300              : #define PROGRESS_DONE_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg2(true);
     301              : #define PROGRESS_BEGIN_TIME_MESSAGE(msg) SysUtils::getCurrentMillis(); MsgHandler::getMessageInstance()->beginProcessMsg((msg) + std::string(" ..."));
     302              : #define PROGRESS_TIME_MESSAGE(before) MsgHandler::getMessageInstance()->endProcessMsg2(true, SysUtils::getCurrentMillis() - before);
     303              : #define PROGRESS_FAILED_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg2(false);
     304              : #define WRITE_ERROR(msg) MsgHandler::getErrorInstance()->inform(msg);
     305              : #define WRITE_ERRORF(...) MsgHandler::getErrorInstance()->informf(__VA_ARGS__);
     306              : #define WRITE_DEBUG(msg) if(MsgHandler::writeDebugMessages()){MsgHandler::getDebugInstance()->inform(msg);};
     307              : #define WRITE_GLDEBUG(msg) if(MsgHandler::writeDebugGLMessages()){MsgHandler::getGLDebugInstance()->inform(msg);};
     308              : #ifdef HAVE_INTL
     309              : // basic translation
     310              : #define TL(string) gettext(string)
     311              : // complex translation ("This % an %", "is", "example")
     312              : #define TLF(string, ...) StringUtils::format(gettext(string), __VA_ARGS__)
     313              : #else
     314              : // basic translation
     315              : #define TL(string) (string)
     316              : // complex translation ("This % an %", "is", "example")
     317              : #define TLF(string, ...) StringUtils::format(string, __VA_ARGS__)
     318              : #endif
        

Generated by: LCOV version 2.0-1