Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/base

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: base 1045 2004-02-27 19:18:29Z jungd $
00019  
00020 ****************************************************************************/
00021 
00022 #ifndef _BASE_
00023 #define _BASE_
00024 
00025 #include <iostream>
00026 #include <string>
00027 #include <sstream>
00028 #include <list>
00029 #include <stdexcept>
00030 #include <algorithm>
00031 #include <typeinfo>
00032 #include <functional>
00033 
00034 #include <base/reflist>
00035 
00036 extern "C" {
00037 #include <string.h>
00038 #include <math.h>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <GL/gl.h>
00042 }
00043 
00044 // instantiate unit tests
00045 #ifdef DEBUG
00046 #define INSTANTIATE_TEST_SUITES
00047 extern bool _abortOnAssertionFailure;
00048 #endif
00049 
00050 // add support for conversion to/from some Open Scene Graph (OSG) types
00051 #define USE_OSG
00052 
00053 
00054 
00055 namespace base {
00056   typedef unsigned char     Byte;
00057   typedef int               SInt;
00058   typedef unsigned int      Int;
00059   typedef long unsigned int LInt;
00060   typedef std::string       String;
00061   typedef double            Real;   // Real & GLreal must be the same built-in type
00062   typedef GLdouble          GLreal;
00063   const GLenum GL_REAL = GL_DOUBLE;
00064   const GLenum GL_UINT = GL_UNSIGNED_INT; // GL_UINT must match Int
00065 
00066 
00067   /// throw a std::runtime_error(errorstring).  If DEBUG, output an assertion failure message
00068   ///  to the Log and abort() if abortOnAssertionFailure mode set
00069   void assertionFailure(const String& errorstring);
00070   
00071   template<typename A> inline void tassert(A assertion, const String& errorstring)
00072   {
00073     if (!assertion) 
00074       assertionFailure(errorstring);
00075   }
00076 
00077   template<typename T> void clearMemory(T* start, Int length)
00078   { memset(start, 0, size_t(length*sizeof(T))); }
00079 
00080   template<typename T> void copyMemory(const T* src, T* dest, Int length)
00081   { memcpy(dest, src, length*sizeof(T)); }
00082 
00083   // convenience: subscripting & indexing for list ( O(n) )
00084   template<typename T> const T& elementAt(const std::list<T>& l, typename std::list<T>::size_type i) 
00085   {
00086     typename std::list<T>::const_iterator it = l.begin();
00087     while ((it != l.end()) && (i > 0)) {
00088       ++it; --i;
00089     }
00090     if (it == l.end()) throw std::out_of_range("elementAt - specified index not present");
00091     return *it;
00092   }
00093 
00094   template<typename T> T& elementAt(std::list<T>& l, typename std::list<T>::size_type i) 
00095   {
00096     typename std::list<T>::iterator it = l.begin();
00097     while ((it != l.end()) && (i > 0)) {
00098       ++it; --i;
00099     }
00100     if (it == l.end()) throw std::out_of_range("elementAt - specified index not present");
00101     return *it;
00102   }
00103 
00104 
00105   template<typename T> const ref<T> elementAt(const reflist<T>& l, typename reflist<T>::size_type i) 
00106   {
00107     typename reflist<T>::const_iterator it = l.begin();
00108     while ((it != l.end()) && (i > 0)) {
00109       ++it; --i;
00110     }
00111     if (it == l.end()) throw std::out_of_range("elementAt - specified index not present");
00112     return *it;
00113   }
00114 
00115   template<typename T> ref<T> elementAt(reflist<T>& l, typename reflist<T>::size_type i) 
00116   {
00117     typename reflist<T>::iterator it = l.begin();
00118     while ((it != l.end()) && (i > 0)) {
00119       ++it; --i;
00120     }
00121     if (it == l.end()) throw std::out_of_range("elementAt - specified index not present");
00122     return *it;
00123   }
00124 
00125   template<typename T> typename std::list<T>::size_type indexOf(const std::list<T>& l, const T& t)
00126   {
00127     typename std::list<T>::const_iterator it = l.begin();
00128     typename std::list<T>::size_type index=0;
00129     while ((it != l.end()) && (*it != t)) {
00130       ++it; ++index;
00131     }
00132     if (it == l.end()) throw std::invalid_argument("indexOf - specificed element not in the list");
00133     return index;
00134   }
00135 
00136   template<typename T> bool contains(const std::list<T>& l, const T& e)
00137   {
00138     typename std::list<T>::const_iterator it = std::find(l.begin(), l.end(), e);
00139     return (it != l.end());
00140   }
00141 
00142   template<typename T> bool contains(const reflist<T>& l, ref<T> e)
00143   {
00144     typename reflist<T>::const_iterator_const it = std::find(l.const_begin(), l.const_end(), e);
00145     return (it != l.const_end());
00146   }
00147 
00148   
00149   template<typename T> void swap(T& a, T& b)
00150   {
00151     const T temp(a);
00152     a = b;
00153     b = temp;
00154   }
00155 
00156 
00157   template<typename C, typename Op> Op for_all(C& c, Op f)
00158   {
00159     typename C::const_iterator b = c.begin();
00160     typename C::const_iterator e = c.end();
00161     return std::for_each(b,e,f);
00162   }
00163 
00164 
00165   class DeleteObject {
00166   public:
00167     template<typename T> void operator()(const T* ptr) const { delete ptr; }
00168   };
00169 
00170   template<typename C> void delete_all(C& c)
00171   {
00172     for_all(c, DeleteObject());
00173   }
00174 
00175   
00176   template<typename InputIterator, typename OutputIterator, typename Predicate>
00177   OutputIterator copy_if(InputIterator begin, InputIterator end,
00178                          OutputIterator destBegin, Predicate p)
00179   {
00180     while(begin!=end) {
00181       if (p(*begin)) *destBegin++=*begin;
00182       ++begin;
00183     }
00184     return destBegin;
00185   }
00186 
00187   String intToString(Int i);
00188   String realToString(Real r);
00189   Int stringToInt(const String& s);
00190   Real stringToReal(const String& s);
00191 
00192   template<typename T> String toString(const T& t)
00193   {
00194     std::ostringstream oss;
00195     oss << t;
00196     return oss.str();
00197   }
00198 
00199   template<typename T> T fromString(const String& s)
00200   {
00201     std::istringstream iss(s);
00202     T t;
00203     iss >> t;
00204     return t;
00205   }
00206 
00207   
00208 
00209   class Cloneable;
00210   template<typename C> C& clone(const C& c) 
00211   {
00212     return dynamic_cast<C&>( static_cast<const Cloneable&>(c).clone());
00213   }
00214   
00215 
00216 
00217   extern std::ostream& _Debug;
00218   extern std::ostream& _Log;
00219   extern std::ostream& _Console;
00220 
00221   
00222   /// convert typeid().name() string into demangled form (e.g. "base::Object")
00223   String demangleTypeidName(const String& typeidName);
00224 
00225   /// convert type_info into qualified class name (calls demangleTypeidName() )
00226   String className(const std::type_info& ti);
00227 
00228   extern int _currentDebugVerbosity;
00229 
00230   // make narrow casting explicit for readability
00231   template <
00232     typename Sub,
00233     typename Super>
00234   //inline Sub* narrow_cast(Select< SUPERSUBCLASS_STRICT(Super,Sub),Super*,NullType>::Result p) { return static_cast<Sub*>(p); }
00235   inline Sub* narrow_cast(Super* p) { return static_cast<Sub*>(p); }
00236 
00237   template <
00238     typename Sub,
00239     typename Super>
00240   //inline Sub& narrow_cast(Select< SUPERSUBCLASS_STRICT(Super,Sub),Super&,NullType>::Result p) { return static_cast<Sub&>(p); }
00241   inline Sub& narrow_cast(Super& p) { return static_cast<Sub&>(p); }
00242   
00243 } // base
00244 
00245 
00246 #include <base/MemoryTracer>
00247 
00248 
00249 // global names
00250 using std::for_each;
00251 using std::mem_fun;
00252 
00253 //using base::Byte;
00254 using base::Int;
00255 using base::SInt;
00256 using base::LInt;
00257 using base::String;
00258 using base::Real;
00259 using base::GLreal;
00260 using base::GL_REAL;
00261 using base::GL_UINT;
00262 using base::clone;
00263 using base::for_all;
00264 using base::narrow_cast;
00265 
00266 
00267 
00268 // Use Log() funcions to output to the log file.  This will remain in
00269 //  release code.  Use Debug() if you want output that will dissapear
00270 //  in release code.  Use Console() to write on the graphical console
00271 //  (e.g. for user status messages etc.)
00272 // NB: see debugtools header for Debug() usage.
00273 
00274 #include <base/debugtools>
00275 
00276 #ifdef __mips
00277 #define __func__ String("unknown")
00278 #endif
00279 
00280 #ifdef __GNUC_
00281 #define _LOG_CALLER_NAME __PRETTY_FUNCTION__ << " -- "
00282 #else
00283 #define _LOG_CALLER_NAME base::className(typeid(*this)) << "::" << __func__ << " -- "
00284 #endif
00285 
00286 #define Log(o) { base::_Log << _LOG_CALLER_NAME << o; }
00287 #define Logln(o) { base::_Log << _LOG_CALLER_NAME << o << "\n"; }
00288 #define Logc(o) { base::_Log << o; }
00289 #define Logcln(o) { base::_Log << o << "\n"; }
00290 
00291 #define Logf(o) { base::_Log << __func__ << " -- " << o; }
00292 #define Logfln(o) { base::_Log << __func__ << " -- " << o << "\n"; }
00293 #define Logfc(o) Logc(o)
00294 #define Logfcln(o) Logcln(o)
00295 
00296 #define Console(o) { base::_Console << o; }
00297 #define Consoleln(o) { base::_Console << o << std::endl; }
00298 
00299 
00300 
00301 // Often, when an Assert() fails, it is not clear where the exception
00302 //  was raised from the message alone.  Enabling this flag will cause
00303 //  the program to abort() from inside Assert() so that a debugger 
00304 //  stack trace can show the point of failure.
00305 #ifdef DEBUG
00306   extern bool _abortOnAssertionFailure;
00307   #define abortOnAssertionFailureEnabled(e) _abortOnAssertionFailure=(e)
00308 #else
00309   #define abortOnAssertionFailureEnabled(e)
00310 #endif
00311 
00312 
00313 // During development it is not unusual for exceptions to be thrown in unexpected places. For example,
00314 //  from a function declared with throw().  It also happens when an exception tries to propagate
00315 //  through C code in the call stack.  For example, this is common if the main loop of the app
00316 //  is being executed from a C library callback (e.g. from GLUT).
00317 //  This typically results in a call to abort() before the exception is caught.  The only way to trace where
00318 //  the exception was thrown in that case is via the debugger.  To make life a little easier, in DEBUG mode
00319 //  the Exception() macro is defined to print the exception text upon construction - so it can be seen even if
00320 //  the exception is not caught.  However, this can be annoying in circumstances when exceptions are
00321 //  expected (for example, in test cases that test for correct exception throwing).  Consequently, it may
00322 //  be disabled.
00323 #ifdef DEBUG
00324   extern bool _outputExceptionOnConstruction;
00325   #define exceptionOutputEnabled(e) _outputExceptionOnConstruction=(e)
00326 #else
00327   #define exceptionOutputEnabled(e)
00328 #endif
00329 
00330 // If an exception is caught and the program exits normally, it may still be useful for
00331 //  debugging to know where it was originally constructed.  For this reason, it is possible
00332 //  to cause an abort() at the construction point.
00333 #ifdef DEBUG
00334   extern bool _abortOnExceptionConstruction;
00335   #define abortOnExceptionConstructionEnabled(e) _abortOnExceptionConstruction=(e)
00336 #else
00337   #define abortOnExceptionConstructionEnabled(e)
00338 #endif
00339 
00340 
00341 
00342 #ifdef __GNUC__
00343 
00344   #ifdef DEBUG
00345     #define _PrintConstructingException(o) \
00346               printf("constructing exception: %s\n", \
00347                (String(__PRETTY_FUNCTION__)+" (line "+base::intToString(__LINE__)+") - "+String(o)).c_str())
00348   
00349   
00350     #define Exception(o) ( \
00351                           ( (_abortOnExceptionConstruction? \
00352                               (_PrintConstructingException(o),::abort(),0) \
00353                             : (_outputExceptionOnConstruction?(_PrintConstructingException(o)):(0)) \
00354                             ) \
00355                           ), \
00356                              String(String("exception thrown: ")+__PRETTY_FUNCTION__+":\n - "+String(o)) \
00357                          )
00358 
00359 
00360   #else   // ndef DEBUG
00361     #define Exception(o) String(String("exception thrown: ")+__PRETTY_FUNCTION__+" - "+String(o))
00362   #endif  // DEBUG
00363 
00364   #define Exceptionf(o) String(String("exception thrown: ")+__PRETTY_FUNCTION__+":\n - "+String(o))
00365   #define Assertion(o) String(String("assertion failed: ")+__PRETTY_FUNCTION__+" (line "+base::intToString(__LINE__)+") - "+String(o))
00366   #define Assertionf(o) String(String("assertion failed: ")+__PRETTY_FUNCTION__+" (line "+base::intToString(__LINE__)+") - "+String(o))
00367 
00368 
00369 #else // ndef __GNUC__
00370 
00371   #ifdef DEBUG
00372 
00373     #define _PrintConstructingException(o) \
00374               printf("constructing exception: %s\n", \
00375                (String(base::className(typeid(*this)))+"::"+String(__func__)+" - "+String(o)).c_str())
00376   
00377     #define Exception(o) ( \
00378                            ( (_abortOnExceptionConstruction? \
00379                                (_PrintConstructingException(o),::abort(),0) \
00380                              : (_outputExceptionOnConstruction?(_PrintConstructingException(o)):(0)) \
00381                              ) \
00382                            ), \
00383                               String(String("exception thrown: ")+String(base::className(typeid(*this)))+"::"+String(__func__)+":\n - "+String(o)) \
00384                          )
00385   #else
00386     #define Exception(o) String(String("exception thrown: ")+String(base::className(typeid(*this)))+"::"+String(__func__)+":\n - "+String(o))
00387   #endif
00388   #define Exceptionf(o) String(String("exception thrown: ")+String(__func__)+":\n - "+String(o))
00389   #define Assertion(o) String(String("assertion failed: ")+String(base::className(typeid(*this)))+"::"+String(__func__)+" - "+String(o))
00390   #define Assertionf(o) String(String("assertion failed: ")+String(__func__)+" - "+String(o))
00391 
00392 #endif // __GNUC__
00393 
00394 #ifdef DEBUG
00395 
00396   #define Assert(a) { if (!(a)) base::assertionFailure(Assertion(#a)); }
00397   #define Assertf(a) { if (!(a)) base::assertionFailure(Assertionf(#a)); }
00398   #define Assertm(a,s) { if (!(a)) base::assertionFailure(Assertion(s)); }
00399   #define Assertmf(a,s) { if (!(a)) base::assertionFailure(Assertionf(s)); }
00400 #else // ndef DEBUG
00401   #define Assert(a) 
00402   #define Assertf(a) 
00403   #define Assertm(a,s) 
00404   #define Assertmf(a,s) 
00405 #endif // DEBUG
00406 
00407 #define Assertifm(f,a,s) Assertm(!f || a,s)
00408 #define Assertifmf(f,a,s) Assertmf(!f || a,s)
00409 
00410 #define instanceof(var,type) (dynamic_cast<type*>(&var) != 0)
00411 
00412 
00413 
00414 // More globals
00415 
00416 #include <base/array>
00417 #include <base/ref>
00418 using base::array;
00419 using base::ref;
00420 
00421 
00422 #endif
00423 

Generated on Thu Jul 29 15:56:04 2004 for OpenSim by doxygen 1.3.6