-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomException.h
More file actions
125 lines (102 loc) · 4.16 KB
/
CustomException.h
File metadata and controls
125 lines (102 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once
#include <exception>
#include "core.h"
#include "character_encoding.h"
namespace tbx {
//////////////////////////////////////////////////////////////////////////
// CCustomExeception
//
// Provides a set of classes to express various error conditions
// The focus here is on providing an easy mechanism for the programmer
// to present their error message information, rather than on classifying
// the error by exception class.
//
// One can always subclass the appropriate CCustomException subclass
// in order to provide a classification for their exception type.
//
// We store the underlying strings using the std lib's std::runtime_error's internal mechanism (char)
// The assumption being that this is encoded appropriately for your needs (e.g. UTF-8)
// We provide wchar_t helpers that assume that the wchar_t is using native UCS-2 or -4 for the current platform
// which convert the encoding to UTF-8 internally
//
// Please see character_encoding.h
class CCustomException : public std::exception
{
public:
// from narrow strings
explicit CCustomException(const char * psz) : std::exception(psz) {}
explicit CCustomException(const std::string & str) : CCustomException(str.c_str()) {}
// from wide strings
explicit CCustomException(const wchar_t * psz) : CCustomException(narrow(psz)) {}
explicit CCustomException(const std::wstring & str) : CCustomException(narrow(str)) {}
// from a std::exception
explicit CCustomException(const std::exception & e)
: CCustomException(e.what())
{
}
// get narrow string
const char * what() const override { return std::exception::what(); }
// get wide string
const std::wstring wwhat() const { return widen(what()); }
};
class CContextException : public CCustomException
{
public:
// import ctors
using CCustomException::CCustomException;
// convenience: __FUNCTION__ + context message
// narrow + narrow
CContextException(const char * function, const std::string & message)
: CCustomException(std::string(function) + "() : " + message)
{
}
// wide + wide
CContextException(const wchar_t * function, const std::wstring & message)
: CCustomException(narrow(function) + "() : " + narrow(message))
{
}
// narrow + wide
CContextException(const char * function, const std::wstring & message)
: CCustomException(std::string(function) + "() : " + narrow(message))
{
}
// wide + narrow
CContextException(const wchar_t * function, const std::string & message)
: CCustomException(narrow(function) + "() : " + message)
{
}
// convenience: __FUNCTION__ + std::exception
// narrow + std::exception
CContextException(const char * function, const std::exception & ex)
: CCustomException(std::string(function) + "() : " + ex.what())
{
}
// wide + std::exception
CContextException(const wchar_t * function, const std::exception & ex)
: CCustomException(narrow(function) + "() : " + ex.what())
{
}
};
// previous projects had a separate CLabeledException that is now merged into CContextException
using CLabeledException = CContextException;
}
// !! is used to ensure that any overloaded operators used to evaluate 'expr' do not end up at &&.
#define TBX_ASSERT_MESSAGE(expr, msg) (void)((!!expr) || (throw CContextException(__FUNCTION__, MESSAGE(msg)), true))
#define TBX_ASSERT_ALWAYS(expr) TBX_ASSERT_MESSAGE((expr), _STRINGIZE(expr))
#define TBX_ASSERT(expr) TBX_ASSERT_ALWAYS(expr)
// simply throw a context exception for now
// at some point I can revisit all of these and possibly convert them to C++20 precondition / postcondition contracts
#define TBX_PRECONDITION(expr) TBX_ASSERT_MESSAGE((expr), "precondition violated: " _STRINGIZE(expr))
#define TBX_POSTCONDITION(expr) TBX_ASSERT_MESSAGE((expr), "postcondition violated: " _STRINGIZE(expr))
// TBX_ASSERT_DEBUG_ONLY is only executed in a debug build (it is elided for release builds)
#ifdef _DEBUG
#define TBX_ASSERT_DEBUG_ONLY(expr) TBX_ASSERT_ALWAYS(expr)
#else
#define TBX_ASSERT_DEBUG_ONLY(expr)
#endif // _DEBUG
// TBX_VERIFY always executes, but only throws on failure in a debug build
#ifdef _DEBUG
#define TBX_VERIFY(expr) TBX_ASSERT(expr)
#else
#define TBX_VERIFY(expr) (expr)
#endif