LCOV - code coverage report
Current view: top level - src/utils/common - MsgHandler.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 20 20 100.0 %
Date: 2024-05-02 15:31:40 Functions: 49 58 84.5 %

          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       11119 :         cleanupOnEnd();
      67       11119 :         myFactory = func;
      68        3850 :     }
      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        1428 :         return myWriteDebugMessages;
      94             :     }
      95             : 
      96             :     /// @brief check whether to enable/disable gl-debug messages
      97             :     static inline bool writeDebugGLMessages() {
      98       61011 :         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      374197 :     void informf(const std::string& format, T value, Targs... Fargs) {
     123      374197 :         if (!aggregationThresholdReached(format)) {
     124     1017230 :             inform(StringUtils::format(format, value, Fargs...), true);
     125             :         }
     126      374197 :     }
     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     1338876 :     inline std::string build(const std::string& msg, bool addType) {
     177             :         std::string prefix;
     178     1338876 :         if (myWriteTimestamps) {
     179          10 :             prefix += buildTimestampPrefix();
     180             :         }
     181     1338876 :         if (myWriteProcessId) {
     182          10 :             prefix += buildProcessIdPrefix();
     183             :         }
     184     1338876 :         if (addType) {
     185     1333121 :             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     2677752 :         return prefix + msg;
     205             :     }
     206             : 
     207      374196 :     virtual bool aggregationThresholdReached(const std::string& format) {
     208      374196 :         return myAggregationThreshold >= 0 && myAggregationCount[format]++ >= myAggregationThreshold;
     209             :     }
     210             : 
     211             :     void setAggregationThreshold(const int thresh) {
     212       86300 :         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 1.14