libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNException.cpp
Go to the documentation of this file.
1 /* Copyright 2009-2014 INSA Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNException.cpp
19  * \author Yann LEYDIER, Guillaume ETIENVENT
20  */
21 
22 #include <CRNException.h>
23 #include <CRNStringUTF8.h>
24 #ifdef CRN_PF_UNIX
25 # ifndef CRN_PF_ANDROID
26 # include <execinfo.h>
27 # include <cxxabi.h>
28 # include <cstring>
29 # endif
30 #endif
31 #include <iostream>
32 #ifdef __GNUG__
33 # if !defined(CRN_PF_ANDROID) && !defined(_MSC_VER)
34 # define DEMANGLE
35 # endif
36 #endif
37 
38 using namespace crn;
39 
40 static const std::string getCallStack()
41 {
42  if (!Exception::TraceStack())
43  return "";
44 #ifdef _MSC_VER
45  return "";
46 #else
47 # ifdef CRN_PF_ANDROID
48  return "";
49 # else
50  const size_t maxdepth = 20;
51  void *array[maxdepth];
52  size_t size = backtrace(array, maxdepth);
53  char **strings = backtrace_symbols(array, int(size));
54  std::string str;
55  if (size > 1)
56  for (size_t tmp = 1; tmp < size; ++tmp)
57  {
58  std::string line(strings[tmp]);
59  char *begin = nullptr, *end = nullptr;
60  for (char *j = strings[tmp]; *j != '\0'; ++j)
61  {
62  if (*j == '(')
63  {
64  begin = j;
65  }
66  else if (*j == '+')
67  {
68  end = j;
69  break;
70  }
71  }
72  if (begin && end)
73  {
74  *end = '\0';
75  begin += 1;
76  int status = -1;
77  char *ret = abi::__cxa_demangle(begin, nullptr, nullptr, &status);
78  if (status == 0)
79  {
80  const char *excstring = "crn::Exception";
81  if (strncmp(ret, excstring, strlen(excstring)) != 0)
82  line = ret;
83  else
84  line = "";
85  }
86  free(ret);
87  *end = '+';
88  }
89  if (line.size())
90  {
91  str += line;
92  str += "\n";
93  }
94  }
95  free(strings);
96  if (size == maxdepth)
97  str += "…";
98  return str;
99 # endif
100 #endif
101 }
102 
108 {
109  static bool trace = false;
110  return trace;
111 }
112 
115  context(getCallStack())
116 {
117 }
118 
123  message(msg.Std()),
124  context(getCallStack())
125 {
126 }
127 
131 Exception::Exception(const char *msg) noexcept:
132  message(msg),
133  context(getCallStack())
134 {
135 }
136 
140 Exception::Exception(const Exception &ex) noexcept:
141  std::exception(ex),
142  message(ex.message),
143  context(ex.context)
144 {
145 }
146 
149 {
150 }
151 
153 const std::string& Exception::GetContext() const noexcept
154 {
155  return context;
156 }
157 
159 const std::string& Exception::GetMessage() const noexcept
160 {
161  return message;
162 }
163 
165 const char* Exception::what() const noexcept
166 {
167  return message.c_str();
168 }
169 
170 static void crnterminate()
171 {
172  try
173  {
174  throw;
175  }
176  catch (const Exception &ex)
177  {
178  const char *exname = typeid(ex).name();
179 #ifdef DEMANGLE
180  int status = -1;
181  char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status);
182  if (status == 0)
183  {
184  exname = ret;
185  }
186 #endif
187  std::cerr << "Unhandled <" << exname << ">: " << std::endl;
188 #ifdef DEMANGLE
189  free(ret);
190 #endif
191  std::cerr << "what: " << ex.what() << std::endl;
192  std::cerr << "context: " << ex.GetContext().c_str() << std::endl;
193  }
194  catch (const std::exception &ex)
195  {
196  const char *exname = typeid(ex).name();
197 #ifdef DEMANGLE
198  int status = -1;
199  char *ret = abi::__cxa_demangle(exname, nullptr, nullptr, &status);
200  if (status == 0)
201  {
202  exname = ret;
203  }
204 #endif
205  std::cerr << "Unhandled <" << exname << ">: " << std::endl;
206 #ifdef DEMANGLE
207  free(ret);
208 #endif
209  std::cerr << "what: " << ex.what() << std::endl;
210  }
211  catch (...)
212  {
213  std::cerr << "Unexpected exception!" << std::endl;
214  }
215  abort();
216 }
217 
220 {
221  std::set_terminate(crnterminate);
222 }
223 
229 ExceptionLogic::ExceptionLogic(const char *msg) noexcept:Exception(msg) { }
230 
236 ExceptionDomain::ExceptionDomain(const char *msg) noexcept:ExceptionLogic(msg) { }
237 
243 ExceptionNotFound::ExceptionNotFound(const char *msg) noexcept:ExceptionLogic(msg) { }
244 
251 
257 ExceptionDimension::ExceptionDimension(const char *msg) noexcept:ExceptionLogic(msg) { }
258 
264 ExceptionRuntime::ExceptionRuntime(const char *msg) noexcept:Exception(msg) {}
265 
271 ExceptionProtocol::ExceptionProtocol(const char *msg) noexcept:ExceptionRuntime(msg) { }
272 
279 
285 ExceptionTODO::ExceptionTODO(const char *msg) noexcept:ExceptionRuntime(msg) { }
286 
292 ExceptionIO::ExceptionIO(const char *msg) noexcept:ExceptionRuntime(msg) { }
293 
ExceptionRuntime() noexcept
Default constructor.
virtual ~Exception() noexceptoverride
Destructor.
A generic runtime error.
Definition: CRNException.h:131
const std::string & GetMessage() const noexcept
String containing a description of the exception.
ExceptionInvalidArgument() noexcept
Default constructor.
ExceptionDimension() noexcept
Default constructor.
A generic logic error.
Definition: CRNException.h:71
ExceptionIO() noexcept
Default constructor.
const std::string & GetContext() const noexcept
String containing the call stack at the moment of throw.
static bool & TraceStack()
Shall the stack be traced at each exception thrown? (very slow)
ExceptionUninitialized() noexcept
Default constructor.
static void SetDefaultHandler()
Sets the default exception handler to print message and context to the standard error.
Exception() noexcept
Default constructor.
virtual const char * what() const noexceptoverride
String containing a description of the exception.
ExceptionTODO() noexcept
Default constructor.
A character string class.
Definition: CRNStringUTF8.h:49
ExceptionNotFound() noexcept
Default constructor.
Base class for exceptions.
Definition: CRNException.h:39
ExceptionLogic() noexcept
Default constructor.
ExceptionDomain() noexcept
Default constructor.
ExceptionProtocol() noexcept
Default constructor.