libutil++  1.9.3
 All Classes Functions Variables
Exception.cpp
1 /*
2 ** libutil++
3 ** $Id: Exception.cpp 1664 2016-04-04 03:57:40Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Exception.cpp 1664 2016-04-04 03:57:40Z sella $";
10 
11 #include "Exception.h"
12 #include "util/Process.h"
13 
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdarg.h>
18 
19 #ifdef __GNUG__
20  #include <cxxabi.h>
21 #endif
22 
23 #include <string>
24 
25 #define BUFFER_SIZE 32768
26 
27 using namespace sella;
28 
29 /* Global Variables */
30 extern bool libutilxx__exception_stacktrace;
31 extern int errno;
32 
33 Exception::Exception(const char *function, const char *file, int line, int code) throw () :
34  function(function),
35  file(file),
36  line(line),
37  code(code)
38 {
39  if (libutilxx__exception_stacktrace) {
40  using namespace sella::util;
41 
42  try {
43  stack = Process::stackTrace(Process::getPath());
44  } catch (...) { }
45  }
46 }
47 
48 Exception::Exception(bool sysmsg, const char *function, const char *file, int line, int code, const char *format, ...) throw () :
49  function(function),
50  file(file),
51  line(line),
52  code(code)
53 {
54  EXCEPTION_BUILDMESSAGE_CODE
55 
56  if (libutilxx__exception_stacktrace) {
57  using namespace sella::util;
58 
59  try {
60  stack = Process::stackTrace(Process::getPath());
61  } catch (...) { }
62  }
63 }
64 
65 Exception::Exception(const Exception &other) throw () :
66  function(other.function),
67  file(other.file),
68  line(other.line),
69  code(other.code),
70  message(other.message),
71  stack(other.stack),
72  cache(other.cache)
73 { }
74 
75 Exception::Exception(const Exception &&other) throw () :
76  function(std::move(other.function)),
77  file(std::move(other.file)),
78  line(other.line),
79  code(other.code),
80  message(std::move(other.message)),
81  stack(std::move(other.stack)),
82  cache(std::move(other.cache))
83 { }
84 
85 Exception::~Exception() throw () { }
86 
87 Exception& sella::Exception::operator=(const Exception &other) throw () {
88  if (this != &other) {
89  this->function = other.function;
90  this->file = other.file;
91  this->line = other.line;
92  this->code = other.code;
93  this->message = other.message;
94  this->stack = other.stack;
95  this->cache = other.cache;
96  }
97 
98  return *this;
99 }
100 
101 Exception& sella::Exception::operator=(const Exception &&other) throw () {
102  if (this != &other) {
103  this->function = std::move(other.function);
104  this->file = std::move(other.file);
105  this->line = other.line;
106  this->code = other.code;
107  this->message = std::move(other.message);
108  this->stack = std::move(other.stack);
109  this->cache = std::move(other.cache);
110  }
111 
112  return *this;
113 }
114 
115 const std::string& Exception::getFunction() const throw () {
116  return this->function;
117 }
118 
119 const std::string& Exception::getFile() const throw () {
120  return this->file;
121 }
122 
123 int Exception::getLine() const throw () {
124  return this->line;
125 }
126 
127 int Exception::getCode() const throw () {
128  return this->code;
129 }
130 
131 const std::string& Exception::getMessage() const throw () {
132  return this->message;
133 }
134 
135 const char* Exception::what() const throw () {
136  return this->message.c_str();
137 }
138 
139 const std::string& Exception::getStackTrace() const throw () {
140  return stack;
141 }
142 
143 const std::string Exception::getName() const throw () {
144  return std::string("sella::Exception");
145 }
146 
147 const std::string& Exception::str() const throw () {
148  if (cache.empty()) {
149  char buf[20];
150 
151  snprintf(buf, sizeof(buf), ":%d]", this->line);
152 
153  cache = (this->message + " [" + this->file + buf);
154  }
155 
156  return cache;
157 }
158 
159 const char* Exception::c_str() const throw () {
160  return str().c_str();
161 }
162 
163 void Exception::enableStackTrace(bool on) throw () {
164  libutilxx__exception_stacktrace = on;
165 }
166 
167 void Exception::buildMessage(bool sysmsg, const char *format, va_list list) throw () {
168  char buffer[BUFFER_SIZE] = { 0 }; /* Prevent garbage output on empty error messages. */
169  std::string error;
170 
171  if (sysmsg) {
172  error = ": ";
173  error.append(strerror_r(errno, buffer, sizeof(buffer)));
174  }
175 
176  vsnprintf(buffer, sizeof(buffer), format, list);
177 
178  this->message = buffer;
179  this->message.append(error);
180 
181  cache.clear();
182 }
183 
184 const std::string Exception::demangle(const char *name) const throw () {
185 #ifdef __GNUG__
186  int s;
187  char *d;
188  std::string res;
189 
190  d = abi::__cxa_demangle(name, NULL, NULL, &s);
191 
192  if (s == 0) {
193  res = d;
194  std::free(d);
195  }
196 
197  return std::move(res);
198 #else
199  return std::string(name);
200 #endif
201 }
202 
203 /*
204 ** vim: noet ts=3 sw=3
205 */