Common.h
Go to the documentation of this file.
1 // (C) Copyright Renaud Detry 2007-2015.
2 // Distributed under the GNU General Public License and under the
3 // BSD 3-Clause License (See accompanying file LICENSE.txt).
4 
5 /** @file */
6 
7 #ifndef NUKLEI_COMMON_H
8 #define NUKLEI_COMMON_H
9 
10 #include <iostream>
11 #include <sstream>
12 #include <string>
13 #include <typeinfo>
14 #include <stdexcept>
15 #include <vector>
16 
17 #include <boost/filesystem.hpp>
18 #include <boost/config.hpp>
19 
20 #include <nuklei/Definitions.h>
21 #include <nuklei/Log.h>
22 #include <nuklei/LoggingMacros.h>
24 
25 // NUKLEI_UNIQUE_PTR_IMPL==0:
26 // use NUKLEI_UNIQUE_PTR if BOOST_NO_CXX11_SMART_PTR is defined
27 // use std::unique_ptr if BOOST_NO_CXX11_SMART_PTR is not defined
28 // NUKLEI_UNIQUE_PTR_IMPL==1:
29 // use NUKLEI_UNIQUE_PTR
30 // NUKLEI_UNIQUE_PTR_IMPL==2:
31 // use std::unique_ptr
32 
33 #define NUKLEI_UNIQUE_PTR_IMPL 2
34 
35 #if NUKLEI_UNIQUE_PTR_IMPL == 0
36 // Define unique pointer type, move and release according based on
37 // compile flags and capabilities (eg, std::unique_ptr when -std=c++11)
38 // If a client library is not compiled with the same flags, bad things
39 // can happen (eg the client will give an auto_ptr to a nuklei function
40 // that has been compiled to receive an unique_ptr).
41 # ifdef BOOST_NO_CXX11_SMART_PTR
42 # define NUKLEI_UNIQUE_PTR NUKLEI_UNIQUE_PTR
43 # define NUKLEI_MOVE(PTR) (PTR)
44 # define NUKLEI_RELEASE(PTR) (PTR)
45 # else
46 # define NUKLEI_UNIQUE_PTR std::unique_ptr
47 # define NUKLEI_MOVE(PTR) std::move(PTR)
48 # define NUKLEI_RELEASE(PTR) (PTR).release()
49 # endif
50 #elif NUKLEI_UNIQUE_PTR_IMPL == 1
51 # define NUKLEI_UNIQUE_PTR NUKLEI_UNIQUE_PTR
52 # define NUKLEI_MOVE(PTR) (PTR)
53 # define NUKLEI_RELEASE(PTR) (PTR)
54 #elif NUKLEI_UNIQUE_PTR_IMPL == 2
55 # ifdef BOOST_NO_CXX11_SMART_PTR
56 # error When NUKLEI_UNIQUE_PTR_IMPL==2, Boost support for C++11 is required
57 # endif
58 # define NUKLEI_UNIQUE_PTR std::unique_ptr
59 # define NUKLEI_MOVE(PTR) std::move(PTR)
60 # define NUKLEI_RELEASE(PTR) (PTR).release()
61 #else
62 # error NUKLEI_UNIQUE_PTR_IMPL must be 0, 1 or 2
63 #endif
64 
65 /** @brief Public namespace. */
66 namespace nuklei {
67 
68  // When using the macros below, remember that destructors should never
69  // throw!
70 
71  /**
72  * @brief Name-value pair.
73  *
74  * Example usage: NUKLEI_THROW( NUKLEI_NVP(variable) );
75  */
76 # define NUKLEI_NVP(x) #x << "=" << x
77 
78  /** @brief String file:line. */
79 # define NUKLEI_HERE() \
80 ((boost::filesystem::path(__FILE__).parent_path().filename().string() + "/" + \
81 boost::filesystem::path(__FILE__).filename().string() + ":" + \
82 nuklei::stringify(__LINE__)))
83 
84  /**
85  * @brief Throws an Error.
86  *
87  * Example usage: NUKLEI_THROW("int i is equal to " << i);
88  *
89  * Note that if a function throws, calling it is slow. Do not throw from
90  * functions that are supposed to execute fast.
91  *
92  * Do not use from within a destructor!
93  */
94 # define NUKLEI_THROW(x) \
95 { \
96 std::ostringstream oss; \
97 oss << x; \
98 throw nuklei::Error(oss.str()); \
99 }
100 
101  /**
102  * @brief Throws an Error if expression is not true.
103  *
104  * Example usage: NUKLEI_ASSERT(i != 0);
105  *
106  * Note that if a function throws, calling it is slow. Do not throw from
107  * functions that are supposed to execute fast.
108  *
109  * For functions that have to go fast, use NUKLEI_FAST_ASSERT instead.
110  *
111  * Do not use from within a destructor!
112  */
113 # define NUKLEI_ASSERT(expression) \
114 { \
115 if (!(expression)) \
116 throw nuklei::Error \
117 (NUKLEI_HERE() + \
118 ": failed to assert `" + #expression + "'"); \
119 }
120 
121 # ifdef NDEBUG
122 # define NUKLEI_DEBUG_ASSERT(expression) ((void)0)
123 # else
124 # define NUKLEI_DEBUG_ASSERT NUKLEI_ASSERT
125 # endif
126 
127  // Throwing slows down function calls.
128 # define NUKLEI_FAST_ASSERT(expression) \
129 assert(expression)
130 
131 # ifdef NDEBUG
132 # define NUKLEI_FAST_DEBUG_ASSERT(expression) ((void)0)
133 # else
134 # define NUKLEI_FAST_DEBUG_ASSERT NUKLEI_FAST_ASSERT
135 # endif
136 
137 # define NUKLEI_ASSERT_AFE(e1, e2) \
138 { \
139 double tol = 1e-6; \
140 if (!(nuklei::afe(e1, e2, tol))) \
141 NUKLEI_THROW(nuklei::stringify(e1, 20, 0) << " != " << nuklei::stringify(e2, 20, 0) << " (TOL=" << tol << ")"); \
142 }
143 
144 # define NUKLEI_ASSERT_AFE_TOL(e1, e2, tol) \
145 { \
146 if (!(nuklei::afe(e1, e2, tol))) \
147 NUKLEI_THROW(nuklei::stringify(e1, 20, 0) << " != " << nuklei::stringify(e2, 20, 0) << " (TOL=" << tol << ")"); \
148 }
149 
150 # ifdef NDEBUG
151 # define NUKLEI_TRACE_BEGIN() {}
152 # define NUKLEI_TRACE_END() {}
153 # else
154 # define NUKLEI_TRACE_BEGIN() try {
155 # define NUKLEI_TRACE_END() \
156 } catch (nuklei::Error &e) { \
157 e.addTrace(__PRETTY_FUNCTION__, NUKLEI_HERE()); \
158 throw; \
159 } \
160 catch (std::exception &e) { \
161 throw nuklei::Error(e, __PRETTY_FUNCTION__, NUKLEI_HERE()); \
162 }
163 # endif
164 
165  /*
166  # define NUKLEI_TRACE_CONTEXT_END() \
167  } catch (nuklei::TracedError &e) { \
168  e.addTrace(__PRETTY_FUNCTION__, NUKLEI_HERE(), context()); \
169  throw; \
170  } \
171  catch (std::exception &e) { \
172  throw nuklei::TracedError(e, __PRETTY_FUNCTION__, NUKLEI_HERE(), context()); \
173  }
174  */
175 
176 # define NUKLEI_LBLACK "\033[0;30m"
177 # define NUKLEI_LRED "\033[0;31m"
178 # define NUKLEI_LGREEN "\033[0;32m"
179 # define NUKLEI_LBROWN "\033[0;33m"
180 # define NUKLEI_LBLUE "\033[0;34m"
181 # define NUKLEI_LPURPLE "\033[0;35m"
182 # define NUKLEI_LCYAN "\033[0;36m"
183 # define NUKLEI_LWHITE "\033[0;37m"
184 # define NUKLEI_DBLACK "\033[1;30m"
185 # define NUKLEI_DRED "\033[1;31m"
186 # define NUKLEI_DGREEN "\033[1;32m"
187 # define NUKLEI_DBROWN "\033[1;33m"
188 # define NUKLEI_DBLUE "\033[1;34m"
189 # define NUKLEI_DPURPLE "\033[1;35m"
190 # define NUKLEI_DCYAN "\033[1;36m"
191 # define NUKLEI_DWHITE "\033[1;37m"
192 
193 # define NUKLEI_NOCOLOR "\033[0m"
194 
195  /** @brief Provides a const reference to an object. */
196  template<class T>
197  inline T const& as_const(T const& t)
198  { return t; }
199 
200  /** @brief Converts an object to a std::string using operator<<. */
201  template<typename T>
202  inline std::string stringify(const T& x, int precision = -1, int width = 0);
203 
204  /** @brief Nuklei-related errors. */
205  class Error : public std::exception
206  {
207  public:
208  Error() : count_(0)
209  {
210  init();
211  compileWhatString();
212  }
213  explicit Error(const std::string& msg) : msg_(msg), count_(0)
214  {
215  init();
216  compileWhatString();
217  }
218  explicit Error(const std::exception& error,
219  const std::string& function,
220  const std::string& file,
221  const std::string& msg = "") : count_(0)
222  {
223  init();
224  type_ = typeid(error).name();
225  msg_ = error.what();
226  addTrace(function, file, msg);
227  compileWhatString();
228  }
229 
230  // The constructor calls this method, keep it non-virtual.
231  void init()
232  {
233  if (INTERACTIVE_SHELL)
234  {
235  color_start_ = NUKLEI_LRED;
236  color_stop_ = NUKLEI_NOCOLOR;
237  }
238  }
239 
240  // The constructor calls this method, keep it non-virtual.
241  void addTrace(const std::string& function,
242  const std::string& file,
243  const std::string& msg = "")
244  {
245  trace_ += Log::breakLines(" " + color_start_ + stringify(count_++) +
246  ":\n " + color_stop_ + function +
247  color_start_ + " @[" + color_stop_ + file +
248  color_start_ + "] [" +
249  color_stop_ + msg + color_start_ + "]" +
250  color_stop_);
251  compileWhatString();
252  }
253 
254  void compileWhatString()
255  {
256  if (type_.empty()) type_ = typeid(*this).name();
257  what_ =
258  color_start_ + "[Exception Trace]" + color_stop_ +
259  Log::breakLines(color_start_ + "Type: " + color_stop_ + type_ +
260  color_start_ + "\nMessage:\n " + color_stop_ + msg_ +
261  color_start_ + "\nTrace:" + color_stop_) + trace_;
262  }
263 
264  // The following methods are virtual in std::exception.
265  ~Error() throw() {}
266  const char* what() const throw()
267  {
268  return what_.c_str();
269  }
270  private:
271  std::string type_;
272  std::string trace_;
273  std::string msg_;
274  std::string what_;
275  std::string color_start_;
276  std::string color_stop_;
277  int count_;
278  };
279 
280  class VerificationFailure : public Error
281  {
282  public:
283  VerificationFailure(const std::string& s) : Error(s) { }
284  };
285 
286  class BadStrNumConversion : public Error
287  {
288  public:
289  BadStrNumConversion(const std::string& s) : Error(s) { }
290  };
291 
292  inline std::istream& operator>>(std::istream &in, Vector3 &l);
293  inline std::istream& operator>>(std::istream &in, Quaternion &q);
294  inline std::ostream& operator<<(std::ostream &out, const Quaternion &q);
295  inline std::ostream& operator<<(std::ostream &out, const Matrix3 &m);
296  inline std::istream& operator>>(std::istream &in, Matrix3 &m);
297 
298 
299  /** @brief Converts a range to a std::string using operator<< on elements. */
300  template<typename ForwardIterator>
301  inline std::string stringifyRange(ForwardIterator first, ForwardIterator last,
302  int precision = -1, int width = 0)
303  {
304  std::ostringstream o;
305 
306  if (first != last)
307  {
308  if (precision != -1) o.precision(precision);
309  char fill = o.fill();
310  o.fill('0');
311  if (width != 0) o.width(width);
312 
313  ForwardIterator i = first;
314 
315  if (!(o << *i))
316  throw BadStrNumConversion
317  (std::string("stringify(") + typeid(*i).name() + ")");
318  i++;
319  for ( ; i != last; i++)
320  if (!(o << " " << *i))
321  throw BadStrNumConversion
322  (std::string("stringify(") + typeid(*i).name() + ")");
323 
324  o.fill(fill);
325  }
326 
327  return o.str();
328  }
329 
330 
331  /** @brief Converts an object to a std::string using operator<<. */
332  template<typename T>
333  inline std::string stringify(const T& x, int precision, int width)
334  {
335  std::ostringstream o;
336  if (precision != -1) o.precision(precision);
337  char fill = o.fill();
338  o.fill('0');
339  if (width != 0) o.width(width);
340  if (!(o << x))
341  throw BadStrNumConversion(std::string("stringify(")
342  + typeid(x).name() + ")");
343  o.fill(fill);
344  return o.str();
345  }
346 
347  /** @brief Converts a string to an object using operator>>. */
348  template<typename T>
349  inline T numify(const std::string& s,
350  bool failIfLeftoverChars = true)
351  {
352  T x;
353  std::istringstream i(s);
354  char c;
355  if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
356  throw BadStrNumConversion(s);
357  return x;
358  }
359 
360  inline std::string& cleanLine(std::string& line)
361  {
362  if(!line.empty() && *line.rbegin() == '\r')
363  line.erase( line.length()-1, 1);
364  return line;
365  }
366 
367  inline void copy_file(const std::string& input, const std::string& output)
368  {
369  std::ifstream src(input.c_str(), std::ios::binary);
370  std::ofstream dst(output.c_str(), std::ios::binary);
371  dst << src.rdbuf();
372  }
373 
374 }
375 
376 #endif
Public namespace.
Definition: Color.cpp:9
std::string stringify(const T &x, int precision=-1, int width=0)
Converts an object to a std::string using operator<<.
Definition: Common.h:333
Nuklei-related errors.
Definition: Common.h:205
Definition: Common.h:286
T numify(const std::string &s, bool failIfLeftoverChars=true)
Converts a string to an object using operator>>.
Definition: Common.h:349
std::string stringifyRange(ForwardIterator first, ForwardIterator last, int precision=-1, int width=0)
Converts a range to a std::string using operator<< on elements.
Definition: Common.h:301
Definition: Common.h:280
T const & as_const(T const &t)
Provides a const reference to an object.
Definition: Common.h:197
© Copyright 2007-2013 Renaud Detry.
Distributed under the terms of the GNU General Public License (GPL).
(See accompanying file LICENSE.txt or copy at http://www.gnu.org/copyleft/gpl.html.)
Revised Sun Sep 13 2020 19:10:06.