summaryrefslogtreecommitdiffstats
path: root/xbmc/commons/Exception.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/commons/Exception.h')
-rw-r--r--xbmc/commons/Exception.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/xbmc/commons/Exception.h b/xbmc/commons/Exception.h
new file mode 100644
index 0000000..ea2c9bc
--- /dev/null
+++ b/xbmc/commons/Exception.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+//---------------------------------------------------------
+// This include should be moved to commons but even as it is,
+// it wont cause a linker circular dependency since it's just
+// a header.
+#include "utils/StringUtils.h"
+//---------------------------------------------------------
+#include <stdarg.h>
+
+
+#ifdef __GNUC__
+// The 'this' pointer counts as a parameter on member methods.
+#define XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT __attribute__((format(printf,2,3)))
+#else
+#define XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT
+#endif
+
+#define XBMCCOMMONS_COPYVARARGS(fmt) va_list argList; va_start(argList, fmt); Set(fmt, argList); va_end(argList)
+#define XBMCCOMMONS_STANDARD_EXCEPTION(E) \
+ class E : public XbmcCommons::Exception \
+ { \
+ public: \
+ inline E(const char* message,...) XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT : Exception(#E) { XBMCCOMMONS_COPYVARARGS(message); } \
+ \
+ inline E(const E& other) : Exception(other) {} \
+ }
+
+namespace XbmcCommons
+{
+ /**
+ * This class a superclass for exceptions that want to utilize some
+ * utility functionality including autologging with the specific
+ * exception name.
+ */
+ class Exception
+ {
+ private:
+
+ std::string classname;
+ std::string message;
+
+ protected:
+
+ inline explicit Exception(const char* classname_) : classname(classname_) { }
+ inline Exception(const char* classname_, const char* message_) : classname(classname_), message(message_) { }
+ inline Exception(const Exception& other) = default;
+
+ /**
+ * This method is called from the constructor of subclasses. It
+ * will set the message from varargs as well as call log message
+ */
+ inline void Set(const char* fmt, va_list& argList)
+ {
+ message = StringUtils::FormatV(fmt, argList);
+ }
+
+ /**
+ * This message can be called from the constructor of subclasses.
+ * It will set the message and log the throwing.
+ */
+ inline void SetMessage(const char* fmt, ...) XBMCCOMMONS_ATTRIB_EXCEPTION_FORMAT
+ {
+ // calls 'set'
+ XBMCCOMMONS_COPYVARARGS(fmt);
+ }
+
+ inline void setClassname(const char* cn) { classname = cn; }
+
+ public:
+ virtual ~Exception();
+
+ virtual void LogThrowMessage(const char* prefix = NULL) const;
+
+ inline virtual const char* GetExMessage() const { return message.c_str(); }
+ };
+
+ /**
+ * This class forms the base class for unchecked exceptions. Unchecked exceptions
+ * are those that really shouldn't be handled explicitly. For example, on windows
+ * when a access violation is converted to a win32_exception, there's nothing
+ * that can be done in most code. The outer most stack frame might try to
+ * do some error logging prior to shutting down, but that's really it.
+ */
+ XBMCCOMMONS_STANDARD_EXCEPTION(UncheckedException);
+
+/**
+ * In cases where you catch(...){} you will (may) inadvertently be
+ * catching UncheckedException's. Therefore this macro will allow
+ * you to do something equivalent to:
+ * catch (anything except UncheckedException) {}
+ *
+ * In order to avoid catching UncheckedException, use the macro as follows:
+ *
+ * try { ... }
+ * XBMCCOMMONS_HANDLE_UNCHECKED
+ * catch(...){ ... }
+ */
+// Yes. I recognize that the name of this macro is an oxymoron.
+#define XBMCCOMMONS_HANDLE_UNCHECKED \
+ catch (const XbmcCommons::UncheckedException& ) { throw; } \
+ catch (const XbmcCommons::UncheckedException* ) { throw; }
+
+}
+