LCOV - code coverage report
Current view: top level - elsa/core - Error.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 35 97 36.1 %
Date: 2024-05-16 04:22:26 Functions: 8 18 44.4 %

          Line data    Source code
       1             : #include "Error.h"
       2             : 
       3             : #include <sstream>
       4             : 
       5             : #include "Backtrace.h"
       6             : 
       7             : namespace elsa
       8             : {
       9             :     constexpr const char* runtime_error_message = "polymorphic elsa error, catch by reference!";
      10             : 
      11             :     Error::Error(std::string msg, bool generate_backtrace, bool store_cause)
      12             :         : std::runtime_error{runtime_error_message}, backtrace{nullptr}, msg{std::move(msg)}
      13         381 :     {
      14             : 
      15         381 :         if (generate_backtrace) {
      16         381 :             this->backtrace = std::make_shared<Backtrace>();
      17         381 :             this->backtrace->analyze();
      18         381 :         }
      19             : 
      20         381 :         if (store_cause) {
      21         381 :             this->storeCause();
      22         381 :         }
      23         381 :     }
      24             : 
      25             :     std::string Error::str() const
      26         379 :     {
      27         379 :         return this->msg;
      28         379 :     }
      29             : 
      30             :     const char* Error::what() const noexcept
      31         379 :     {
      32         379 :         this->what_cache = this->str();
      33         379 :         return this->what_cache.c_str();
      34         379 :     }
      35             : 
      36             :     void Error::storeCause()
      37         381 :     {
      38         381 :         if (not std::current_exception()) {
      39         379 :             return;
      40         379 :         }
      41             : 
      42           2 :         try {
      43           2 :             throw;
      44           2 :         } catch (Error& cause) {
      45           2 :             cause.trimBacktrace();
      46           2 :             this->cause = std::current_exception();
      47           2 :         } catch (...) {
      48           0 :             this->cause = std::current_exception();
      49           0 :         }
      50           2 :     }
      51             : 
      52             :     void Error::trimBacktrace()
      53           2 :     {
      54           2 :         if (this->backtrace) {
      55           2 :             this->backtrace->trimToCurrentStackFrame();
      56           2 :         }
      57           2 :     }
      58             : 
      59             :     void Error::rethrowCause() const
      60           0 :     {
      61           0 :         if (this->cause) {
      62           0 :             std::rethrow_exception(this->cause);
      63           0 :         }
      64           0 :     }
      65             : 
      66             :     std::string Error::typeName() const
      67           0 :     {
      68           0 :         return detail::symbolDemangle(typeid(*this).name());
      69           0 :     }
      70             : 
      71             :     Backtrace* Error::getBacktrace() const
      72           0 :     {
      73           0 :         return this->backtrace.get();
      74           0 :     }
      75             : 
      76             :     const std::string& Error::getMsg() const
      77           0 :     {
      78           0 :         return this->msg;
      79           0 :     }
      80             : 
      81             :     std::ostream& operator<<(std::ostream& os, const Error& e)
      82           0 :     {
      83             :         // output the exception cause
      84           0 :         bool had_a_cause = true;
      85           0 :         try {
      86           0 :             e.rethrowCause();
      87           0 :             had_a_cause = false;
      88           0 :         } catch (Error& cause) {
      89           0 :             os << cause << std::endl;
      90           0 :         } catch (std::exception& cause) {
      91           0 :             os << detail::symbolDemangle(typeid(cause).name()) << ": " << cause.what() << std::endl;
      92           0 :         }
      93             : 
      94           0 :         if (had_a_cause) {
      95           0 :             os << std::endl
      96           0 :                << "The above exception was the direct cause "
      97           0 :                   "of the following exception:"
      98           0 :                << std::endl
      99           0 :                << std::endl;
     100           0 :         }
     101             : 
     102             :         // output the exception backtrace
     103           0 :         auto* bt = e.getBacktrace();
     104           0 :         if (bt != nullptr) {
     105           0 :             os << *bt;
     106           0 :         } else {
     107           0 :             os << "origin:" << std::endl;
     108           0 :         }
     109             : 
     110           0 :         os << e.typeName() << ":" << std::endl;
     111           0 :         os << e.str();
     112             : 
     113           0 :         return os;
     114           0 :     }
     115             : 
     116             :     /**
     117             :      * Prints a backtrace_symbol object.
     118             :      */
     119             :     std::ostream& operator<<(std::ostream& os, const backtrace_symbol& bt_sym)
     120           0 :     {
     121             :         // imitate the looks of a Python traceback.
     122           0 :         os << " -> ";
     123             : 
     124           0 :         if (bt_sym.functionname.empty()) {
     125           0 :             os << '?';
     126           0 :         } else {
     127           0 :             os << bt_sym.functionname;
     128           0 :         }
     129             : 
     130           0 :         if (bt_sym.pc != nullptr) {
     131           0 :             os << " " << detail::addrToString(bt_sym.pc);
     132           0 :         }
     133             : 
     134           0 :         return os;
     135           0 :     }
     136             : 
     137             :     /**
     138             :      * Prints an entire Backtrace object.
     139             :      */
     140             :     std::ostream& operator<<(std::ostream& os, const Backtrace& bt)
     141           0 :     {
     142             :         // imitate the looks of a Python traceback.
     143           0 :         os << "Traceback (most recent call last):" << std::endl;
     144             : 
     145           0 :         bt.getSymbols([&os](const backtrace_symbol* symbol) { os << *symbol << std::endl; }, true);
     146             : 
     147           0 :         return os;
     148           0 :     }
     149             : 
     150           0 :     InternalError::InternalError(const std::string& msg) : Error{msg} {}
     151             : 
     152         138 :     LogicError::LogicError(const std::string& msg) : Error{msg} {}
     153             : 
     154         190 :     InvalidArgumentError::InvalidArgumentError(const std::string& msg) : Error{msg} {}
     155             : 
     156           3 :     BadCastError::BadCastError(const std::string& msg) : Error{msg} {}
     157             : 
     158           0 :     NotImplementedError::NotImplementedError(const std::string& msg) : Error{msg} {}
     159             : 
     160             : } // namespace elsa

Generated by: LCOV version 1.14