]> git.sesse.net Git - casparcg/blobdiff - common/except.h
Merge pull request #450 from SuperFlyTV/feature/documentation
[casparcg] / common / except.h
index d964360e2457798c3f17bde9c08adbfd1acdaa9d..f4319f6d3dd5108584d8f01218c3b5bfa6fef89a 100644 (file)
 
 #include "utf.h"
 
-#include "log.h"
+#include "os/stack_trace.h"
 
 #include <exception>
+#include <list>
+
 #include <boost/exception/all.hpp>
 #include <boost/exception/error_info.hpp>
 #include <boost/throw_exception.hpp>
-
-struct _EXCEPTION_RECORD;
-struct _EXCEPTION_POINTERS;
-
-typedef _EXCEPTION_RECORD EXCEPTION_RECORD;
-typedef _EXCEPTION_POINTERS EXCEPTION_POINTERS;
+#include <boost/noncopyable.hpp>
 
 namespace caspar {
 
-typedef boost::error_info<struct tag_arg_name_info, std::string>       arg_name_info_t;
-typedef boost::error_info<struct tag_arg_value_info, std::string>      arg_value_info_t;
-typedef boost::error_info<struct tag_msg_info, std::string>                    msg_info_t;
-typedef boost::error_info<struct tag_call_stack_info, std::string>     call_stack_info_t;
-typedef boost::error_info<struct tag_msg_info, std::string>                    error_info_t;
-typedef boost::error_info<struct tag_source_info, std::string>         source_info_t;
-typedef boost::error_info<struct tag_file_name_info, std::string>      file_name_info_t;
+typedef boost::error_info<struct tag_arg_name_info,            std::string>    arg_name_info_t;
+typedef boost::error_info<struct tag_arg_value_info,   std::string>    arg_value_info_t;
+typedef boost::error_info<struct tag_msg_info,                 std::string>    msg_info_t;
+typedef boost::error_info<struct tag_call_stack_info,  std::string>    call_stack_info_t;
+typedef boost::error_info<struct tag_error_info,               std::string>    error_info_t;
+typedef boost::error_info<struct tag_source_info,              std::string>    source_info_t;
+typedef boost::error_info<struct tag_file_name_info,   std::string>    file_name_info_t;
+typedef boost::error_info<struct tag_context_info,             std::string>    context_info_t;
 
 template<typename T>
 inline arg_name_info_t         arg_name_info(const T& str)             {return arg_name_info_t(u8(str));}
@@ -59,7 +57,9 @@ inline error_info_t                   error_info(const T& str)                {return error_info_t(u8(str));}
 template<typename T>
 inline source_info_t           source_info(const T& str)               {return source_info_t(u8(str));}
 template<typename T>
-inline file_name_info_t        file_name_info(const T& str)    {return file_name_info_t(u8(str));}
+inline file_name_info_t                file_name_info(const T& str)    {return file_name_info_t(u8(str));}
+template<typename T>
+inline context_info_t          context_info(const T& str)              {return context_info_t(u8(str));}
 
 typedef boost::error_info<struct tag_line_info, size_t>                                                line_info;
 typedef boost::error_info<struct tag_nested_exception_, std::exception_ptr> nested_exception;
@@ -67,7 +67,10 @@ typedef boost::error_info<struct tag_nested_exception_, std::exception_ptr> nest
 struct caspar_exception                        : virtual boost::exception, virtual std::exception 
 {
        caspar_exception(){}
-       explicit caspar_exception(const char* msg) : std::exception(msg) {}
+       const char* what() const throw() override
+       {
+               return boost::diagnostic_information_what(*this);
+       }
 };
 
 struct io_error                                        : virtual caspar_exception {};
@@ -79,76 +82,52 @@ struct file_write_error         : virtual io_error {};
 struct invalid_argument                        : virtual caspar_exception {};
 struct null_argument                   : virtual invalid_argument {};
 struct out_of_range                            : virtual invalid_argument {};
+struct programming_error               : virtual caspar_exception {};
 struct bad_alloc                               : virtual caspar_exception {};
 
 struct invalid_operation               : virtual caspar_exception {};
 struct operation_failed                        : virtual caspar_exception {};
 struct timed_out                               : virtual caspar_exception {};
 
-struct not_supported                   : virtual caspar_exception {};
 struct not_implemented                 : virtual caspar_exception {};
 
-class win32_exception : public std::exception
-{
-public:
-       typedef const void* address;
-       static void install_handler();
-       static void ensure_handler_installed_for_thread(
-                       const char* thread_description = nullptr);
-
-       address location() const { return location_; }
-       unsigned int error_code() const { return errorCode_; }
-       virtual const char* what() const { return message_;     }
-
-protected:
-       win32_exception(const EXCEPTION_RECORD& info);
-       static void Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo);
-
-private:
-       const char* message_;
+struct user_error                              : virtual caspar_exception {};
+struct expected_user_error             : virtual user_error {};
+struct not_supported                   : virtual user_error {};
 
-       address location_;
-       unsigned int errorCode_;
-};
+std::string get_context();
 
-class win32_access_violation : public win32_exception
+class scoped_context : boost::noncopyable
 {
-       mutable char messageBuffer_[256];
-
 public:
-       bool is_write() const { return isWrite_; }
-       address bad_address() const { return badAddress_;}
-       virtual const char* what() const;
-
-protected:
-       win32_access_violation(const EXCEPTION_RECORD& info);
-       friend void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo);
-
+       scoped_context();
+       scoped_context(std::string msg);
+       template <typename Str>
+       scoped_context(Str msg)
+               : scoped_context(u8(std::move(msg)))
+       {
+       }
+
+       ~scoped_context();
+       void replace_msg(std::string msg);
+       template <typename Str>
+       void replace_msg(std::string msg)
+       {
+               replace_msg(u8(std::move(msg)));
+       }
+       void clear_msg();
 private:
-       bool isWrite_;
-       address badAddress_;
+       std::list<std::string>& for_thread_;
+       std::string*                    msg_;
 };
 
-#define CASPAR_THROW_EXCEPTION(e) BOOST_THROW_EXCEPTION(e << call_stack_info(caspar::log::internal::get_call_stack()))
+#define _CASPAR_GENERATE_UNIQUE_IDENTIFIER_CAT(name, line) name##line
+#define _CASPAR_GENERATE_UNIQUE_IDENTIFIER(name, line) _CASPAR_GENERATE_UNIQUE_IDENTIFIER_CAT(name, line)
+#define CASPAR_SCOPED_CONTEXT_MSG(ctx_msg) ::caspar::scoped_context _CASPAR_GENERATE_UNIQUE_IDENTIFIER(SCOPED_CONTEXT, __LINE__)(u8(ctx_msg));
 
-}
+#define CASPAR_THROW_EXCEPTION(e) BOOST_THROW_EXCEPTION(e << call_stack_info(caspar::get_call_stack()) << context_info(get_context()))
 
-namespace std
-{
+std::string get_message_and_context(const caspar_exception& e);
 
-inline bool operator!=(const std::exception_ptr& lhs, const std::exception_ptr& rhs)
-{
-       return !(lhs == rhs);
-}
-
-inline bool operator!=(const std::exception_ptr& lhs, std::nullptr_t)
-{
-       return !(lhs == nullptr);
-}
-
-inline bool operator!=(std::nullptr_t, const std::exception_ptr& rhs)
-{
-       return !(nullptr == rhs);
 }
 
-}
\ No newline at end of file