1 #ifndef mbl_exception_h_
2 #define mbl_exception_h_
3 //:
4 // \file
5 // \brief Exceptions thrown by mbl, and a mechanism for turning them off.
6 // \author Ian Scott.
7
8 #include <string>
9 #include <iostream>
10 #include <cstdlib>
11 #ifdef _MSC_VER
12 # include <vcl_msvc_warnings.h>
13 #endif
14 #include <stdexcept>
15
16
17 //: Throw an exception indicating a real problem.
18 // If exceptions have been disabled, this function
19 // may abort.
20 template <class T>
mbl_exception_error(T exception)21 void mbl_exception_error(T exception)
22 {
23 std::cerr << "\nERROR: " << exception.what() << std::endl;
24 #if !defined MBL_EXCEPTIONS_DISABLE
25 throw exception;
26 #else
27 std::abort();
28 #endif
29 }
30
31 //: Throw an exception indicating a potential problem.
32 // If exceptions have been disabled, this function
33 // may return.
34 template <class T>
mbl_exception_warning(T exception)35 void mbl_exception_warning(T exception)
36 {
37 std::cerr << "\nWARNING: " << exception.what() << std::endl;
38 #if !defined MBL_EXCEPTIONS_DISABLE
39 throw exception;
40 #endif
41 }
42
43 //: Indicates that mbl_cloneables_factory has not heard of value name.
44 class mbl_exception_no_name_in_factory : public std::logic_error
45 {
46 public:
47 std::string failed_value, valid_values;
mbl_exception_no_name_in_factory(const std::string & failed_name,const std::string & valid_names)48 mbl_exception_no_name_in_factory(const std::string& failed_name, const std::string& valid_names):
49 std::logic_error(std::string("No such value: ") +failed_name + "\nValid values are: ["+valid_names+"]"),
50 failed_value(failed_name), valid_values(valid_names) {}
51 ~mbl_exception_no_name_in_factory() throw() override = default;
52 };
53
54 //: General purpose - a replacement for std::abort.
55 // The only point of catching this exception, is to
56 // give you a chance to save your data. If this exception
57 // is thrown, then the program correctness is in doubt.
58 class mbl_exception_abort : public std::logic_error
59 {
60 public:
61 mbl_exception_abort(const std::string& comment);
62 ~mbl_exception_abort() throw() override = default;
63 };
64
65
66 //: Indicates a problem whilst parsing text configuration data.
67 class mbl_exception_parse_error: public std::runtime_error
68 {
69 public:
mbl_exception_parse_error(const std::string & msg)70 mbl_exception_parse_error(const std::string &msg)
71 : std::runtime_error(msg) {}
72 ~mbl_exception_parse_error() throw() override = default;
73 };
74
75 //: Indicates a problem whilst parsing a file.
76 class mbl_exception_parse_file_error: public mbl_exception_parse_error
77 {
78 std::string filename_;
79 public:
mbl_exception_parse_file_error(const std::string & msg,const std::string & filename)80 mbl_exception_parse_file_error(const std::string &msg, const std::string& filename):
81 mbl_exception_parse_error(filename.empty() ? msg : msg+" in "+filename), filename_(filename) {}
filename()82 const char * filename() const {return filename_.c_str();}
83 ~mbl_exception_parse_file_error() throw() override = default;
84 };
85
86 //: Data from two sources or files was inconsistent.
87 // This is distinct from a parse error, which can be used when the data within
88 // in a single config file is inconsistent. This is most useful at algorithm run time,
89 // when there are several external data files, and some external agent has broken the
90 // consistency invariant by modifying one of them. The application can then report that
91 // someone has messed up its data.
92 class mbl_exception_inconsistent_external_data: public std::runtime_error
93 {
94 std::string source1_, source2_;
95 public:
96 mbl_exception_inconsistent_external_data(const std::string &msg,
97 const std::string& source1 = "", const std::string& source2 = "")
98 : std::runtime_error( source1.empty() && source2.empty()
99 ? msg : msg+" between "+source1+" and "+source2),
100 source1_(source1), source2_(source2) {}
source1()101 const char * source1() const {return source1_.c_str();}
source2()102 const char * source2() const {return source2_.c_str();}
103 ~mbl_exception_inconsistent_external_data() throw() override = default;
104 };
105
106 //: Indicates a problem whilst parsing text configuration data.
107 class mbl_exception_missing_property: public mbl_exception_parse_error
108 {
109 public:
110 std::string missing_label;
mbl_exception_missing_property(const std::string & missing)111 mbl_exception_missing_property(const std::string &missing)
112 : mbl_exception_parse_error(
113 std::string("Couldn't find expected property label: \""+missing+'\"')),
114 missing_label(missing)
115 {}
116 ~mbl_exception_missing_property() throw() override = default;
117 };
118
119 //: Indicates that mbl_exception_look_for_unused_props found some unused properties.
120 class mbl_exception_unused_props : public mbl_exception_parse_error
121 {
122 public:
123 std::string function_name, unused_properties;
mbl_exception_unused_props(const std::string & fn_name,const std::string & unused_props)124 mbl_exception_unused_props(const std::string &fn_name, const std::string &unused_props)
125 : mbl_exception_parse_error(fn_name + ": Unused properties found:\n" + unused_props),
126 function_name(fn_name), unused_properties(unused_props) {}
127 ~mbl_exception_unused_props() throw() override = default;
128 };
129
130 //: Indicates a problem whilst parsing text configuration data into an mbl_read_props object.
131 class mbl_exception_read_props_parse_error: public mbl_exception_parse_error
132 {
133 public:
mbl_exception_read_props_parse_error(const std::string & msg)134 mbl_exception_read_props_parse_error(const std::string &msg)
135 : mbl_exception_parse_error(std::string("mbl_read_props: ") + msg) {}
136 ~mbl_exception_read_props_parse_error() throw() override = default;
137 };
138
139 //: Indicates a problem whilst parsing a block of text configuration data.
140 class mbl_exception_parse_block_parse_error: public mbl_exception_parse_error
141 {
142 public:
143 //: Description of problem
144 std::string msg;
145 //: Contents of string which failed to be parsed.
146 std::string contents;
mbl_exception_parse_block_parse_error(const std::string & msg,const std::string & contents)147 mbl_exception_parse_block_parse_error(const std::string &msg,
148 const std::string &contents)
149 : mbl_exception_parse_error(std::string("mbl_parse_block: ") + msg +
150 "Contents of block:\n" + contents), msg(msg), contents(contents) {}
151 ~mbl_exception_parse_block_parse_error() throw() override = default;
152 };
153
154 //:Throw mbl_exception_os_error or one of its derivatives, based on errno.
155 // If exceptions are disabled, this behaves like mbl_exception_warning() above.
156 void mbl_exception_throw_os_error(const std::string& filename,
157 const std::string& additional_comment="");
158
159
160 //: Indicates a problem reported during an OS call.
161 class mbl_exception_os_error: public std::runtime_error
162 {
163 public:
164 //: Reported errno
165 int err_no;
166 //: System supplied error message.
167 std::string error_message;
168 //: Filename or pathname or other id on which OS call failed.
169 std::string filename;
170 //: Optional additional comments.
171 std::string additional_comment;
172 mbl_exception_os_error(int errnum, const std::string &file_name,
173 const std::string &comment="");
174 ~mbl_exception_os_error() throw() override = default;
175 };
176
177 #define MACRO( E ) \
178 class E : public mbl_exception_os_error{ public: \
179 E (int err_no, const std::string &file_name, const std::string &comment=""): \
180 mbl_exception_os_error(err_no, file_name, comment) {} }
181
182 MACRO(mbl_exception_os_no_such_file_or_directory);
183 MACRO(mbl_exception_os_permission_denied);
184 MACRO(mbl_exception_os_file_exists);
185 MACRO(mbl_exception_os_not_a_directory);
186 MACRO(mbl_exception_os_is_a_directory);
187 MACRO(mbl_exception_os_no_space_left_on_device);
188 MACRO(mbl_exception_os_invalid_value);
189
190 #undef MACRO
191
192 #endif // mbl_exception_h_
193