LCOV - code coverage report
Current view: top level - error - exception.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 16 0
Test Date: 2026-02-19 16:58:26 Functions: 0.0 % 5 0

            Line data    Source code
       1              : /** \file exception.hpp
       2              :  * \brief The mxlib exception class.
       3              :  * \ingroup error_handling_files
       4              :  *
       5              :  */
       6              : 
       7              : //***********************************************************************//
       8              : // Copyright 2025 Jared R. Males (jaredmales@gmail.com)
       9              : //
      10              : // This file is part of mxlib.
      11              : //
      12              : // mxlib is free software: you can redistribute it and/or modify
      13              : // it under the terms of the GNU General Public License as published by
      14              : // the Free Software Foundation, either version 3 of the License, or
      15              : // (at your option) any later version.
      16              : //
      17              : // mxlib is distributed in the hope that it will be useful,
      18              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      19              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20              : // GNU General Public License for more details.
      21              : //
      22              : // You should have received a copy of the GNU General Public License
      23              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      24              : //***********************************************************************//
      25              : 
      26              : #ifndef error_exception_hpp
      27              : #define error_exception_hpp
      28              : 
      29              : #include <vector>
      30              : 
      31              : #include "error.hpp"
      32              : 
      33              : namespace mx
      34              : {
      35              : 
      36              : /// Augments an exception with the source file and line
      37              : /**
      38              :  * \tparam baseexcept is the base class exception which takes a string as constructor argument
      39              :  */
      40              : template <class verboseT = verbose::d>
      41              : class exception : public std::exception
      42              : {
      43              :   protected:
      44              :     std::string m_what;                   ///< The full what message (message + file information).
      45              : 
      46              :     error_t m_code{ error_t::exception }; ///< The error_t code
      47              : 
      48              :     std::string m_message;                ///< The explanatory message
      49              : 
      50              :     std::source_location m_location;
      51              : 
      52              :   public:
      53              :     /// Constructor with location only.
      54              :     /**
      55              :      */
      56            0 :     explicit exception( const std::source_location loc = /**< [in] [opt] the location where this was thrown*/
      57              :                         std::source_location::current() )
      58            0 :         : m_location{ loc }
      59              :     {
      60            0 :         m_what = error_message<verboseT>( m_code, m_location );
      61            0 :     }
      62              : 
      63              :     /// Constructor with message.
      64              :     /**
      65              :      */
      66              :     explicit exception( const std::string &msg,          /**< [in] the error description message) */
      67              :                         const std::source_location loc = /**< [in] [opt] the location where this was thrown*/
      68              :                         std::source_location::current() )
      69              :         : m_message{ msg }, m_location{ loc }
      70              :     {
      71              :         m_what = error_message<verboseT>( m_code, m_message, m_location );
      72              :     }
      73              : 
      74              :     /// Constructor with message and cod
      75              :     /**
      76              :      */
      77            0 :     exception( error_t code,                    /**< [in] a descriptive error code */
      78              :                const std::string &msg,          /**< [in] the error description (what message) */
      79              :                const std::source_location loc = /**< [in] [opt] the location where this was thrown*/
      80              :                std::source_location::current() )
      81            0 :         : m_code{ code }, m_message{ msg }, m_location{ loc }
      82              :     {
      83            0 :         m_what = error_message<verboseT>( m_code, m_message, m_location );
      84            0 :     }
      85              : 
      86              :     /// Constructor with code
      87              :     /** The message is filled in using \ref errorMessage.
      88              :      *
      89              :      * The what() message becomes "code_message (code) [file line]".
      90              :      */
      91            0 :     exception( error_t code,                    /**< [in] a descriptive error code */
      92              :                const std::source_location loc = /**< [in] [opt] the location where this was thrown*/
      93              :                std::source_location::current() )
      94            0 :         : m_code{ code }, m_location{ loc }
      95              :     {
      96            0 :         m_what = error_message<verboseT>( m_code, m_location );
      97            0 :     }
      98              : 
      99              :     /// Get the what string
     100              :     /** \returns the value of m_what.c_str()
     101              :      *
     102              :      */
     103            0 :     virtual const char *what() const noexcept
     104              :     {
     105            0 :         return m_what.c_str();
     106              :     }
     107              : 
     108              :     /// Get the message
     109              :     /** \returns the value of m_message
     110              :      *
     111              :      */
     112              :     const std::string &message() const
     113              :     {
     114              :         return m_message;
     115              :     }
     116              : 
     117              :     /// Get the source file
     118              :     /** \returns the value of m_location.file_name()
     119              :      *
     120              :      */
     121              :     const std::string file_name() const
     122              :     {
     123              :         return m_location.file_name();
     124              :     }
     125              : 
     126              :     /// Get the source line
     127              :     /** \returns the value of m_location.line()
     128              :      *
     129              :      */
     130              :     int line() const
     131              :     {
     132              :         return m_location.line();
     133              :     }
     134              : 
     135              :     /// Get the error code
     136              :     /** \returns the value of m_code
     137              :      *
     138              :      */
     139            0 :     error_t code() const
     140              :     {
     141            0 :         return m_code;
     142              :     }
     143              : };
     144              : 
     145              : /// Extract the explanatory string of nested exceptions, placing them in a vector.
     146              : /** If the exception is nested, this recurses to extract the explanatory string of the
     147              :  * next exception it holds.
     148              :  */
     149              : inline
     150              : void unwind_exceptions( std::vector<std::string> &whats, /**< [out] the vector of what messages*/
     151              :                         const std::exception &e          /**< [in] the exception */
     152              : )
     153              : {
     154              :     whats.push_back( e.what() );
     155              : 
     156              :     try
     157              :     {
     158              :         std::rethrow_if_nested( e );
     159              :     }
     160              :     catch( const std::exception &nestedException )
     161              :     {
     162              :         unwind_exceptions( whats, nestedException );
     163              :     }
     164              :     catch( ... )
     165              :     {
     166              :     }
     167              : }
     168              : 
     169              : /// Print nested exceptions to stderr, from the earliest to latest
     170              : /** Formats in a ladder
     171              :  *
     172              : */
     173              : inline
     174              : void print_exceptions( std::vector<std::string> &whats, /**< [out] a vector of what messages*/
     175              :                        const std::string &message =     /**< [in] [optional] the top message to print */
     176              :                        "exception(s) thrown" )
     177              : {
     178              :     std::cerr << message << ":\n";
     179              :     std::cerr << "  " << whats.back() << '\n';
     180              :     for( size_t n = 1; n < whats.size(); ++n )
     181              :     {
     182              :         std::cerr << std::string( 2, ' ' ) << std::string( ( n - 1 ) * 4, ' ' ) << "|-->" << whats[whats.size() - 1 - n]
     183              :                   << '\n';
     184              :     }
     185              : }
     186              : 
     187              : } // namespace mx
     188              : 
     189              : #endif // error_exception_hpp
        

Generated by: LCOV version 2.0-1