Lunchbox  1.10.0
 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 template< class T > inline std::string format( const std::vector< T >& data )
127  { return format< T >( &data[0], data.size( )); }
128 
129 } // namespace lunchbox
130 
131 #ifdef NDEBUG
132 # ifdef LB_RELEASE_ASSERT
133 # define LBASSERT(x) \
134  { \
135  if( !(x) ) \
136  LBERROR << "##### Assert: " << #x << " #####" << std::endl \
137  << lunchbox::forceFlush; \
138  lunchbox::checkHeap(); \
139  }
140 # define LBASSERTINFO(x, info) \
141  { \
142  if( !(x) ) \
143  LBERROR << "##### Assert: " << #x << " [" << info << "] #####" \
144  << std::endl << lunchbox::forceFlush; \
145  lunchbox::checkHeap(); \
146  }
147 # define LBCHECK(x) { const bool eqOk = x; LBASSERTINFO( eqOk, #x ) }
148 # else
149 # define LBASSERT(x)
150 # define LBASSERTINFO(x, info)
151 # define LBCHECK(x) { x; }
152 # endif
153 
154 # define LBUNIMPLEMENTED { LBERROR << "Unimplemented code" << std::endl \
155  << lunchbox::forceFlush; }
156 # define LBUNREACHABLE { LBERROR << "Unreachable code" << std::endl \
157  << lunchbox::forceFlush; }
158 # define LBDONTCALL \
159  { LBERROR << "Code is not supposed to be called in this context" \
160  << std::endl << lunchbox::forceFlush; }
161 # define LBABORT( info ) { \
162  LBERROR << "##### Abort: " << info << " #####" << std::endl \
163  << lunchbox::forceFlush; }
164 
165 #else // NDEBUG
166 
167 # define LBASSERT(x) \
168  { \
169  if( !(x) ) \
170  { \
171  LBERROR << "Assert: " << #x << " "; \
172  lunchbox::abort(); \
173  } \
174  lunchbox::checkHeap(); \
175  }
176 # define LBASSERTINFO(x, info) \
177  { \
178  if( !(x) ) \
179  { \
180  LBERROR << "Assert: " << #x << " [" << info << "] "; \
181  lunchbox::abort(); \
182  } \
183  lunchbox::checkHeap(); \
184  }
185 
186 # define LBUNIMPLEMENTED \
187  { LBERROR << "Unimplemented code in " << lunchbox::className( this ) \
188  << " "; \
189  lunchbox::abort(); }
190 # define LBUNREACHABLE \
191  { LBERROR << "Unreachable code in " << lunchbox::className( this ) \
192  << " "; \
193  lunchbox::abort(); }
194 # define LBDONTCALL \
195  { LBERROR << "Code is not supposed to be called in this context, type " \
196  << lunchbox::className( this ) << " " ; \
197  lunchbox::abort(); }
198 
199 # define LBCHECK(x) { const bool eqOk = x; LBASSERTINFO( eqOk, #x ) }
200 # define LBABORT( info ) { \
201  LBERROR << "Abort: " << info; \
202  lunchbox::abort(); }
203 #endif // NDEBUG
204 
205 #define LBSAFECAST( to, in ) static_cast< to >( in ); \
206  LBASSERT( in == 0 || dynamic_cast< to >( static_cast< to >( in )))
207 
208 #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.