packages feed

inline-c-cpp-0.4.0.3: cxx-src/HaskellException.cxx

#include "HaskellException.hxx"

// see
// <https://stackoverflow.com/questions/28166565/detect-gcc-as-opposed-to-msvc-clang-with-macro>
// regarding how to detect g++ or clang.
// 
// the defined(__clang__) should actually be redundant, since apparently it also
// defines GNUC, but but let's be safe.

#include <cstring>
#include <cstdlib>

#if defined(__GNUC__) || defined(__clang__)
#include <cxxabi.h>
#include <string>
#endif


HaskellException::HaskellException(std::string renderedExceptionIn, void *haskellExceptionStablePtrIn)
  : haskellExceptionStablePtr(new HaskellStablePtr(haskellExceptionStablePtrIn))
  , displayExceptionValue(renderedExceptionIn)
{
}

HaskellException::HaskellException(const HaskellException &other)
  : haskellExceptionStablePtr(other.haskellExceptionStablePtr)
  , displayExceptionValue(other.displayExceptionValue)
{
}

const char* HaskellException::what() const noexcept {
  return displayExceptionValue.c_str();
}


// see
// <https://stackoverflow.com/questions/561997/determining-exception-type-after-the-exception-is-caught/47164539#47164539>
// regarding how to show the type of an exception.

#if defined(__GNUC__) || defined(__clang__)
const char* currentExceptionTypeName()
{
  int demangle_status;
  return abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &demangle_status);
}
#endif

void setMessageOfStdException(std::exception &e,char** __inline_c_cpp_error_message__){
#if defined(__GNUC__) || defined(__clang__)
  const char* demangle_result = currentExceptionTypeName();
  std::string message = "Exception: " + std::string(e.what()) + "; type: " + std::string(demangle_result);
#else
  std::string message = "Exception: " + std::string(e.what()) + "; type: not available (please use g++ or clang)";
#endif
  size_t message_len = message.size() + 1;
  *__inline_c_cpp_error_message__ = static_cast<char*>(std::malloc(message_len));
  std::memcpy(*__inline_c_cpp_error_message__, message.c_str(), message_len);
}

void setMessageOfOtherException(char** __inline_c_cpp_error_message__){
#if defined(__GNUC__) || defined(__clang__)
  const char* message = currentExceptionTypeName();
  size_t message_len = strlen(message) + 1;
  *__inline_c_cpp_error_message__ = static_cast<char*>(std::malloc(message_len));
  std::memcpy(*__inline_c_cpp_error_message__, message, message_len);
#else
  *__inline_c_cpp_error_message__ = NULL;
#endif
}