1 /***************************************************************************
2  *  foxxll/common/error_handling.hpp
3  *
4  *  Part of FOXXLL. See http://foxxll.org
5  *
6  *  Copyright (C) 2007-2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
7  *  Copyright (C) 2013 Timo Bingmann <tb@panthema.net>
8  *
9  *  Distributed under the Boost Software License, Version 1.0.
10  *  (See accompanying file LICENSE_1_0.txt or copy at
11  *  http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 #ifndef FOXXLL_COMMON_ERROR_HANDLING_HEADER
15 #define FOXXLL_COMMON_ERROR_HANDLING_HEADER
16 
17 /** \file error_handling.hpp
18  * Macros for convenient error checking and reporting via exception.
19  */
20 
21 #include <cerrno>
22 #include <cstring>
23 #include <sstream>
24 
25 #include <foxxll/common/exceptions.hpp>
26 #include <foxxll/config.hpp>
27 
28 namespace foxxll {
29 
30 #if FOXXLL_MSVC
31  #define FOXXLL_PRETTY_FUNCTION_NAME __FUNCTION__
32 #else
33  #define FOXXLL_PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
34 #endif
35 
36 ////////////////////////////////////////////////////////////////////////////
37 
38 //! Throws exception_type with "Error in [location] : [error_message]"
39 #define FOXXLL_THROW2(exception_type, location, error_message)    \
40     do {                                                          \
41         std::ostringstream msg;                                   \
42         msg << "Error in " << location << " : " << error_message; \
43         throw exception_type(msg.str());                          \
44     } while (false)
45 
46 //! Throws exception_type with "Error in [function] : [error_message]"
47 #define FOXXLL_THROW(exception_type, error_message) \
48     FOXXLL_THROW2(                                  \
49         exception_type,                             \
50         FOXXLL_PRETTY_FUNCTION_NAME,                \
51         error_message                               \
52     )
53 
54 //! Throws exception_type with "Error in [function] : [error_message] : [errno_value message]"
55 #define FOXXLL_THROW_ERRNO2(exception_type, error_message, errno_value) \
56     FOXXLL_THROW2(                                                      \
57         exception_type,                                                 \
58         FOXXLL_PRETTY_FUNCTION_NAME,                                    \
59         error_message << " : " << strerror(errno_value)                 \
60     )
61 
62 //! Throws exception_type with "Error in [function] : [error_message] : [errno message]"
63 #define FOXXLL_THROW_ERRNO(exception_type, error_message) \
64     FOXXLL_THROW_ERRNO2(exception_type, error_message, errno)
65 
66 //! Throws std::invalid_argument with "Error in [function] : [error_message]"
67 #define FOXXLL_THROW_INVALID_ARGUMENT(error_message) \
68     FOXXLL_THROW2(                                   \
69         std::invalid_argument,                       \
70         FOXXLL_PRETTY_FUNCTION_NAME,                 \
71         error_message                                \
72     )
73 
74 //! Throws foxxll::unreachable with "Error in file [file], line [line] : this code should never be reachable"
75 #define FOXXLL_THROW_UNREACHABLE()                    \
76     FOXXLL_THROW2(                                    \
77         foxxll::unreachable,                          \
78         "file " << __FILE__ << ", line " << __LINE__, \
79             "this code should never be reachable"     \
80     )
81 
82 ////////////////////////////////////////////////////////////////////////////
83 
84 //! Throws exception_type if (expr) with "Error in [function] : [error_message]"
85 #define FOXXLL_THROW_IF(expr, exception_type, error_message) \
86     do {                                                     \
87         if (expr) {                                          \
88             FOXXLL_THROW(exception_type, error_message);     \
89         }                                                    \
90     } while (false)
91 
92 //! Throws exception_type if (expr) with "Error in [function] : [error_message] : [errno message]"
93 #define FOXXLL_THROW_ERRNO_IF(expr, exception_type, error_message) \
94     do {                                                           \
95         if (expr) {                                                \
96             FOXXLL_THROW_ERRNO(exception_type, error_message);     \
97         }                                                          \
98     } while (false)
99 
100 //! Throws exception_type if (expr != 0) with "Error in [function] : [error_message] : [errno message]"
101 #define FOXXLL_THROW_ERRNO_NE_0(expr, exception_type, error_message) \
102     FOXXLL_THROW_ERRNO_IF((expr) != 0, exception_type, error_message)
103 
104 #if FOXXLL_WINDOWS || defined(__MINGW32__)
105 
106 //! Throws exception_type with "Error in [function] : [error_message] : [formatted GetLastError()]"
107 #define FOXXLL_THROW_WIN_LASTERROR(exception_type, error_message)        \
108     do {                                                                 \
109         LPVOID lpMsgBuf;                                                 \
110         DWORD dw = GetLastError();                                       \
111         FormatMessage(                                                   \
112             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \
113             nullptr, dw,                                                 \
114             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),                   \
115             (LPTSTR)&lpMsgBuf,                                           \
116             0, nullptr                                                   \
117         );                                                               \
118         std::ostringstream msg;                                          \
119         msg << "Error in " << FOXXLL_PRETTY_FUNCTION_NAME                \
120             << " : " << error_message                                    \
121             << " : error code " << dw << " : " << ((char*)lpMsgBuf);     \
122         LocalFree(lpMsgBuf);                                             \
123         throw exception_type(msg.str());                                 \
124     } while (false)
125 
126 #endif
127 
128 } // namespace foxxll
129 
130 #endif // !FOXXLL_COMMON_ERROR_HANDLING_HEADER
131 
132 /**************************************************************************/
133