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