Lunchbox  1.9.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
debug.h
1 
2 /* Copyright (c) 2007-2012, Stefan Eilemann <eile@equalizergraphics.com>
3  * 2013, Daniel Nachbaur <danielnachbaur@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License version 2.1 as published
7  * by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef LUNCHBOX_DEBUG_H
20 #define LUNCHBOX_DEBUG_H
21 
22 #include <lunchbox/defines.h>
23 #include <lunchbox/log.h>
24 
25 #include <typeinfo>
26 
27 // assertions
28 // #define LB_RELEASE_ASSERT
29 
30 namespace lunchbox
31 {
36 LUNCHBOX_API void abort();
37 
42 LUNCHBOX_API void checkHeap();
43 
50 LUNCHBOX_API std::ostream& sysError( std::ostream& os );
51 
53 LUNCHBOX_API std::string sysError();
54 
63 LUNCHBOX_API std::string backtrace( const size_t skipFrames );
64 
66 LUNCHBOX_API std::ostream& backtrace( std::ostream& os );
67 
68 LUNCHBOX_API std::string demangleTypeID( const char* mangled );
69 
70 #ifdef _WIN32
71 # pragma warning( disable: 4100 ) // VS Bug
72 #endif
73 
74 template< class T > inline std::string className( const T* object )
75  { return demangleTypeID( typeid( *object ).name( )); }
76 
78 template< class T > inline std::string className( const T& object )
79  { return demangleTypeID( typeid( object ).name( )); }
80 #ifdef _WIN32
81 # pragma warning( default: 4100 )
82 #endif
83 
93 template< class T > inline std::string format( const T* data, const size_t num )
94 {
95  std::ostringstream os;
96  os << num << " " << className( data ) << " @ " << std::hex
97  << (const void*)data << ": 0x";
98  for( size_t i = 0; i < num; ++i )
99  {
100  if( (i % 8) == 0 )
101  os << " " << std::endl;
102  os << ' ' << data[i];
103  }
104  return os.str();
105 }
106 
107 template<> inline std::string format( const uint8_t* data, const size_t num )
108 {
109  std::ostringstream os;
110  os << num << " bytes @ " << std::hex << (const void*)data << ": 0x";
111  os.precision( 2 );
112  for( size_t i = 0; i < num; ++i )
113  {
114  if( (i % 32) == 0 )
115  os << " " << std::endl;
116  else if( (i % 8) == 0 )
117  os << ' ';
118  os << ' ' << std::setw(2) << int( data[i] );
119  }
120  return os.str();
121 }
122 
123 template<> inline std::string format( const void* data, const size_t num )
124  { return format( reinterpret_cast< const uint8_t* >( data ), num ); }
125 
126 } // namespace lunchbox
127 
128 #ifdef NDEBUG
129 # ifdef LB_RELEASE_ASSERT
130 # define LBASSERT(x) \
131  { \
132  if( !(x) ) \
133  LBERROR << "##### Assert: " << #x << " #####" << std::endl \
134  << lunchbox::forceFlush; \
135  lunchbox::checkHeap(); \
136  }
137 # define LBASSERTINFO(x, info) \
138  { \
139  if( !(x) ) \
140  LBERROR << "##### Assert: " << #x << " [" << info << "] #####" \
141  << std::endl << lunchbox::forceFlush; \
142  lunchbox::checkHeap(); \
143  }
144 # define LBCHECK(x) { const bool eqOk = x; LBASSERTINFO( eqOk, #x ) }
145 # else
146 # define LBASSERT(x)
147 # define LBASSERTINFO(x, info)
148 # define LBCHECK(x) { x; }
149 # endif
150 
151 # define LBUNIMPLEMENTED { LBERROR << "Unimplemented code" << std::endl \
152  << lunchbox::forceFlush; }
153 # define LBUNREACHABLE { LBERROR << "Unreachable code" << std::endl \
154  << lunchbox::forceFlush; }
155 # define LBDONTCALL \
156  { LBERROR << "Code is not supposed to be called in this context" \
157  << std::endl << lunchbox::forceFlush; }
158 # define LBABORT( info ) { \
159  LBERROR << "##### Abort: " << info << " #####" << std::endl \
160  << lunchbox::forceFlush; }
161 
162 #else // NDEBUG
163 
164 # define LBASSERT(x) \
165  { \
166  if( !(x) ) \
167  { \
168  LBERROR << "Assert: " << #x << " "; \
169  lunchbox::abort(); \
170  } \
171  lunchbox::checkHeap(); \
172  }
173 # define LBASSERTINFO(x, info) \
174  { \
175  if( !(x) ) \
176  { \
177  LBERROR << "Assert: " << #x << " [" << info << "] "; \
178  lunchbox::abort(); \
179  } \
180  lunchbox::checkHeap(); \
181  }
182 
183 # define LBUNIMPLEMENTED \
184  { LBERROR << "Unimplemented code in " << lunchbox::className( this ) \
185  << " "; \
186  lunchbox::abort(); }
187 # define LBUNREACHABLE \
188  { LBERROR << "Unreachable code in " << lunchbox::className( this ) \
189  << " "; \
190  lunchbox::abort(); }
191 # define LBDONTCALL \
192  { LBERROR << "Code is not supposed to be called in this context, type " \
193  << lunchbox::className( this ) << " " ; \
194  lunchbox::abort(); }
195 
196 # define LBCHECK(x) { const bool eqOk = x; LBASSERTINFO( eqOk, #x ) }
197 # define LBABORT( info ) { \
198  LBERROR << "Abort: " << info; \
199  lunchbox::abort(); }
200 #endif // NDEBUG
201 
202 #define LBSAFECAST( to, in ) static_cast< to >( in ); \
203  LBASSERT( in == 0 || dynamic_cast< to >( static_cast< to >( in )))
204 
205 #endif //LUNCHBOX_DEBUG_H
LUNCHBOX_API std::ostream & sysError(std::ostream &os)
Print a textual description of the current system error.
LUNCHBOX_API std::string backtrace(const size_t skipFrames)
Get the current call stack.
std::string className(const T *object)
Print the RTTI name of the given class.
Definition: debug.h:74
std::string format(const T *data, const size_t num)
Format the given array in a human-readable form.
Definition: debug.h:93
This file contains logging classes.