v0.3.5:
[mldemos:mldemos.git] / _3rdParty / dlib / error.h
1 // Copyright (C) 2003  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #ifndef DLIB_ERROr_ 
4 #define DLIB_ERROr_ 
5
6 #include <string>
7 #include <new>          // for std::bad_alloc
8 #include <iostream>
9 #include <cassert>
10 #include <cstdlib>
11 #include <exception>
12
13 // -------------------------------
14 // ------ exception classes ------
15 // -------------------------------
16
17 namespace dlib
18 {
19
20 // ----------------------------------------------------------------------------------------
21
22     enum error_type
23     {
24         EOTHER,        
25         EPORT_IN_USE,  
26         ETIMEOUT,     
27         ECONNECTION, 
28         ELISTENER, 
29         ERESOLVE,     
30         EMONITOR,   
31         ECREATE_THREAD,    
32         ECREATE_MUTEX,    
33         ECREATE_SIGNALER,
34         EUNSPECIFIED,   
35         EGENERAL_TYPE1,
36         EGENERAL_TYPE2,  
37         EGENERAL_TYPE3,  
38         EINVALID_OPTION,
39         ETOO_FEW_ARGS,
40         ETOO_MANY_ARGS,
41         ESOCKET,
42         ETHREAD,
43         EGUI,
44         EFATAL,
45         EBROKEN_ASSERT,
46         EIMAGE_LOAD,
47         EDIR_CREATE,
48         EINCOMPATIBLE_OPTIONS,
49         EMISSING_REQUIRED_OPTION,
50         EINVALID_OPTION_ARG,
51         EMULTIPLE_OCCURANCES,
52         ECONFIG_READER,
53         EIMAGE_SAVE,
54         ECAST_TO_STRING,
55         ESTRING_CAST,
56         EUTF8_TO_UTF32
57     };
58
59 // ----------------------------------------------------------------------------------------
60
61     // the base exception class
62     class error : public std::exception
63     {
64         /*!
65             WHAT THIS OBJECT REPRESENTS
66                 This is the base exception class for the dlib library.  i.e. all 
67                 exceptions in this library inherit from this class.
68         !*/
69
70     public:
71         error(
72             error_type t,
73             const std::string& a
74         ): info(a), type(t) {}
75         /*!
76             ensures
77                 - #type == t
78                 - #info == a
79         !*/
80
81         error(
82             error_type t
83         ): type(t) {}
84         /*!
85             ensures
86                 - #type == t
87                 - #info == ""
88         !*/
89
90         error(
91             const std::string& a
92         ): info(a), type(EUNSPECIFIED) {}
93         /*!
94             ensures
95                 - #type == EUNSPECIFIED
96                 - #info == a
97         !*/
98
99         error(
100         ): type(EUNSPECIFIED) {}
101         /*!
102             ensures
103                 - #type == EUNSPECIFIED
104                 - #info == ""
105         !*/
106
107         virtual ~error(
108         ) throw() {}
109         /*!
110             ensures
111                 - does nothing
112         !*/
113
114         const char* what(
115         ) const throw()
116         /*!
117             ensures
118                 - if (info.size() != 0) then
119                     - returns info.c_str()
120                 - else
121                     - returns type_to_string(type)
122         !*/
123         {
124             if (info.size() > 0)
125                 return info.c_str(); 
126             else
127                 return type_to_string();
128         }
129
130         const char* type_to_string (
131         ) const throw()
132         /*!
133             ensures
134                 - returns a string that names the contents of the type member.
135         !*/
136         {
137             if (type == EOTHER) return "EOTHER";
138             else if ( type == EPORT_IN_USE) return "EPORT_IN_USE";
139             else if ( type == ETIMEOUT) return "ETIMEOUT";
140             else if ( type == ECONNECTION) return "ECONNECTION"; 
141             else if ( type == ELISTENER) return "ELISTENER"; 
142             else if ( type == ERESOLVE) return "ERESOLVE";     
143             else if ( type == EMONITOR) return "EMONITOR";   
144             else if ( type == ECREATE_THREAD) return "ECREATE_THREAD";    
145             else if ( type == ECREATE_MUTEX) return "ECREATE_MUTEX";    
146             else if ( type == ECREATE_SIGNALER) return "ECREATE_SIGNALER";
147             else if ( type == EUNSPECIFIED) return "EUNSPECIFIED";   
148             else if ( type == EGENERAL_TYPE1) return "EGENERAL_TYPE1";
149             else if ( type == EGENERAL_TYPE2) return "EGENERAL_TYPE2";  
150             else if ( type == EGENERAL_TYPE3) return "EGENERAL_TYPE3";  
151             else if ( type == EINVALID_OPTION) return "EINVALID_OPTION";
152             else if ( type == ETOO_FEW_ARGS) return "ETOO_FEW_ARGS";
153             else if ( type == ETOO_MANY_ARGS) return "ETOO_MANY_ARGS";
154             else if ( type == ESOCKET) return "ESOCKET";
155             else if ( type == ETHREAD) return "ETHREAD";
156             else if ( type == EGUI) return "EGUI";
157             else if ( type == EFATAL) return "EFATAL";
158             else if ( type == EBROKEN_ASSERT) return "EBROKEN_ASSERT";
159             else if ( type == EIMAGE_LOAD) return "EIMAGE_LOAD";
160             else if ( type == EDIR_CREATE) return "EDIR_CREATE";
161             else if ( type == EINCOMPATIBLE_OPTIONS) return "EINCOMPATIBLE_OPTIONS";
162             else if ( type == EMISSING_REQUIRED_OPTION) return "EMISSING_REQUIRED_OPTION";
163             else if ( type == EINVALID_OPTION_ARG) return "EINVALID_OPTION_ARG";
164             else if ( type == EMULTIPLE_OCCURANCES) return "EMULTIPLE_OCCURANCES";
165             else if ( type == ECONFIG_READER) return "ECONFIG_READER";
166             else if ( type == EIMAGE_SAVE) return "EIMAGE_SAVE";
167             else if ( type == ECAST_TO_STRING) return "ECAST_TO_STRING";
168             else if ( type == ESTRING_CAST) return "ESTRING_CAST";
169             else if ( type == EUTF8_TO_UTF32) return "EUTF8_TO_UTF32";
170             else return "undefined error type";
171         }
172
173         const std::string info;  // info about the error
174         const error_type type; // the type of the error
175
176     private:
177         const error& operator=(const error&);
178     };
179
180 // ----------------------------------------------------------------------------------------
181
182     class fatal_error : public error
183     {
184         /*!
185             WHAT THIS OBJECT REPRESENTS
186                 As the name says, this object represents some kind of fatal error.  
187                 That is, it represents an unrecoverable error and any program that
188                 throws this exception is, by definition, buggy and needs to be fixed.
189
190                 Note that a fatal_error exception can only be thrown once.  The second
191                 time an application attempts to construct a fatal_error it will be 
192                 immediately aborted and an error message will be printed to std::cerr. 
193                 The reason for this is because the first fatal_error was apparently ignored
194                 so the second fatal_error is going to make itself impossible to ignore 
195                 by calling abort.  The lesson here is that you should not try to ignore 
196                 fatal errors.
197
198                 This is also the exception thrown by the DLIB_ASSERT and DLIB_CASSERT macros.
199         !*/
200
201     public:
202         fatal_error(
203             error_type t,
204             const std::string& a
205         ): error(t,a) {check_for_previous_fatal_errors();}
206         /*!
207             ensures
208                 - #type == t
209                 - #info == a
210         !*/
211
212         fatal_error(
213             error_type t
214         ): error(t) {check_for_previous_fatal_errors();}
215         /*!
216             ensures
217                 - #type == t
218                 - #info == ""
219         !*/
220
221         fatal_error(
222             const std::string& a
223         ): error(EFATAL,a) {check_for_previous_fatal_errors();}
224         /*!
225             ensures
226                 - #type == EFATAL
227                 - #info == a
228         !*/
229
230         fatal_error(
231         ): error(EFATAL) {check_for_previous_fatal_errors();}
232         /*!
233             ensures
234                 - #type == EFATAL
235                 - #info == ""
236         !*/
237
238     private:
239
240         static inline char* message ()
241         { 
242             static char buf[2000];
243             buf[1999] = '\0'; // just to be extra safe
244             return buf;
245         }
246
247         static inline void dlib_fatal_error_terminate (
248         )
249         {
250             std::cerr << "\n**************************** FATAL ERROR DETECTED ****************************";
251             std::cerr << message() << "\n";
252             std::cerr << "******************************************************************************\n" << "\n";
253         }
254
255         void check_for_previous_fatal_errors()
256         {
257             static bool is_first_fatal_error = true;
258             if (is_first_fatal_error == false)
259             {
260                 std::cerr << "\n\n ************************** FATAL ERROR DETECTED ************************** " << "\n";
261                 std::cerr << " ************************** FATAL ERROR DETECTED ************************** " << "\n";
262                 std::cerr << " ************************** FATAL ERROR DETECTED ************************** \n" << "\n";
263                 std::cerr << "Two fatal errors have been detected, the first was inappropriately ignored. \n"
264                           << "To prevent further fatal errors from being ignored this application will be \n"
265                           << "terminated immediately and you should go fix this buggy program.\n\n"
266                           << "The error message from this fatal error was:\n" << this->what() << "\n\n" << "\n";
267                 using namespace std;
268                 assert(false);
269                 abort();
270             }
271             else
272             {
273                 // copy the message into the fixed message buffer so that it can be recalled by dlib_fatal_error_terminate
274                 // if needed.
275                 char* msg = message();
276                 unsigned long i;
277                 for (i = 0; i < 2000-1 && i < this->info.size(); ++i)
278                     msg[i] = info[i];
279                 msg[i] = '\0';
280
281                 // set this termination handler so that if the user doesn't catch this dlib::fatal_error that is being
282                 // thrown then it will eventually be printed to standard error
283                 std::set_terminate(&dlib_fatal_error_terminate);
284             }
285             is_first_fatal_error = false;
286         }
287     };
288
289 // ----------------------------------------------------------------------------------------
290
291     class gui_error : public error
292     {
293     public:
294         gui_error(
295             error_type t,
296             const std::string& a
297         ): error(t,a) {}
298         /*!
299             ensures
300                 - #type == t
301                 - #info == a
302         !*/
303
304         gui_error(
305             error_type t
306         ): error(t) {}
307         /*!
308             ensures
309                 - #type == t
310                 - #info == ""
311         !*/
312
313         gui_error(
314             const std::string& a
315         ): error(EGUI,a) {}
316         /*!
317             ensures
318                 - #type == EGUI 
319                 - #info == a
320         !*/
321
322         gui_error(
323         ): error(EGUI) {}
324         /*!
325             ensures
326                 - #type == EGUI
327                 - #info == ""
328         !*/
329     };
330
331 // ----------------------------------------------------------------------------------------
332
333     class socket_error : public error
334     {
335     public:
336         socket_error(
337             error_type t,
338             const std::string& a
339         ): error(t,a) {}
340         /*!
341             ensures
342                 - #type == t
343                 - #info == a
344         !*/
345
346         socket_error(
347             error_type t
348         ): error(t) {}
349         /*!
350             ensures
351                 - #type == t
352                 - #info == ""
353         !*/
354
355         socket_error(
356             const std::string& a
357         ): error(ESOCKET,a) {}
358         /*!
359             ensures
360                 - #type == ESOCKET
361                 - #info == a
362         !*/
363
364         socket_error(
365         ): error(ESOCKET) {}
366         /*!
367             ensures
368                 - #type == ESOCKET
369                 - #info == ""
370         !*/
371     };
372
373 // ----------------------------------------------------------------------------------------
374
375     class thread_error : public error
376     {
377     public:
378         thread_error(
379             error_type t,
380             const std::string& a
381         ): error(t,a) {}
382         /*!
383             ensures
384                 - #type == t
385                 - #info == a
386         !*/
387
388         thread_error(
389             error_type t
390         ): error(t) {}
391         /*!
392             ensures
393                 - #type == t
394                 - #info == ""
395         !*/
396
397         thread_error(
398             const std::string& a
399         ): error(ETHREAD,a) {}
400         /*!
401             ensures
402                 - #type == ETHREAD
403                 - #info == a
404         !*/
405
406         thread_error(
407         ): error(ETHREAD) {}
408         /*!
409             ensures
410                 - #type == ETHREAD
411                 - #info == ""
412         !*/
413     };
414
415 // ----------------------------------------------------------------------------------------
416
417 }
418
419 #endif // DLIB_ERROr_
420