ExceptionImpl.h

Go to the documentation of this file.
00001 // vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:
00002 /*
00003  * Copyright (C) 2005 Dell Inc.
00004  *  by Michael Brown <Michael_E_Brown@dell.com>
00005  * Licensed under the Open Software License version 2.1
00006  *
00007  * Alternatively, you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published
00009  * by the Free Software Foundation; either version 2 of the License,
00010  * or (at your option) any later version.
00011 
00012  * This program is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00015  * See the GNU General Public License for more details.
00016  */
00017 
00018 
00019 #ifndef EXCEPTIONIMPL_H
00020 #define EXCEPTIONIMPL_H
00021 
00022 
00023 
00024 // compat header should always be first header
00025 #include "smbios/compat.h"
00026 
00027 #include <map>
00028 #include <string>
00029 #include <sstream>
00030 #include <exception>
00031 
00032 // types.h should be first user-defined header.
00033 #include "smbios/types.h"
00034 #include "smbios/IException.h"
00035 
00036 // abi_prefix should be last header included before declarations
00037 #include "smbios/config/abi_prefix.hpp"
00038 
00039 #define DEFINE_EXCEPTION_EX( excName, ns, superclass )   \
00040     class excName : public smbios::Exception< ns :: superclass >  \
00041     {                                       \
00042     public:                                 \
00043         ~excName() throw() {};  \
00044         excName( const std::string initMessage ) : smbios::Exception< ns :: superclass >(initMessage) {} ;\
00045         excName( const excName &src ) : smbios::Exception< ns :: superclass >(src) {} ;\
00046         excName( ) : smbios::Exception< ns :: superclass >() {} ;\
00047     }
00048 
00049     /*commented out fragment above is valid code but hits a bug in MSVC++ and emits C2437 diagnostic erroneously*/
00050 
00051 
00052 namespace smbios
00053 {
00054     // TODO: all this needs to be hidden to preserve ABI.
00055     template <class S>
00056     class Exception : public S
00057     {
00058     public:
00059         // destructor
00060         virtual ~Exception() throw() { deAllocateMaps(); };
00061         // constructors
00062         Exception( const std::string initMessage ) : S(), messageStr( initMessage ), outputStr("") { allocateMaps(); };
00063         Exception( ) : S(), messageStr( "" ), outputStr("") { allocateMaps(); };
00064         Exception( const Exception<S> &source );
00065         // overloaded assignment
00066         Exception<S> &operator =( const Exception<S> &source );
00067 
00068         virtual const char *what() const throw() ;
00069         virtual std::string getParameterString( const std::string &name ) const;
00070         virtual u32 getParameterNumber( const std::string &name ) const;
00071 
00072         virtual void setMessageString( const std::string &newMsgString );
00073         virtual void setParameter( const std::string &name, const std::string &value );
00074         virtual void setParameter( const std::string &name, const u32 value );
00075     private:
00076         void allocateMaps();
00077         void deAllocateMaps();
00078         std::string messageStr;
00079         mutable std::string outputStr;
00080 
00081         // cannot export STL across a DLL in Windows using MSVC++ 6
00082         // This is the workaround:
00083         void * ptrStrMap;
00084         void * ptrNumMap;
00085         //   yes, it sucks.
00086     };
00087 
00088     // copy constructor
00089     template <class S>
00090     Exception<S>::Exception( const Exception<S> &source )
00091             : S(), messageStr( source.messageStr ), outputStr("")
00092     {
00093         allocateMaps();
00094 
00095         // everything is a void*, cast to what it really is.
00096         std::map< std::string, std::string > r_ptrStrMap =
00097             *reinterpret_cast< std::map< std::string, std::string > * >(ptrStrMap);
00098 
00099         std::map< std::string, u32 > r_ptrNumMap =
00100             *reinterpret_cast< std::map< std::string, u32 > * >(ptrNumMap);
00101 
00102         std::map< std::string, std::string > r_ptrStrMapSource =
00103             *reinterpret_cast< std::map< std::string, std::string > * >(source.ptrStrMap);
00104 
00105         std::map< std::string, u32 > r_ptrNumMapSource =
00106             *reinterpret_cast< std::map< std::string, u32 > * >(source.ptrNumMap);
00107 
00108         // copy parameters over from source
00109         std::map< std::string, u32 >::iterator iter = r_ptrNumMapSource.begin();
00110         while ( iter != r_ptrNumMapSource.end() )
00111         {
00112             setParameter( iter->first, iter->second );
00113             ++iter;
00114         }
00115 
00116         std::map< std::string, std::string >::iterator iterStr = r_ptrStrMapSource.begin();
00117         while ( iterStr != r_ptrStrMapSource.end() )
00118         {
00119             setParameter( iterStr->first, iterStr->second );
00120             ++iterStr;
00121         }
00122     }
00123 
00124     // overloaded assignment
00125     template <class S>
00126     Exception<S> &Exception<S>::operator =( const Exception<S> &source )
00127     {
00128         messageStr = source.messageStr;
00129         outputStr = "";
00130 
00131         deAllocateMaps(); // out with the old
00132         allocateMaps();   // in with the new
00133 
00134         // everything is a void*, cast to what it really is.
00135         std::map< std::string, std::string > r_ptrStrMap =
00136             *reinterpret_cast< std::map< std::string, std::string > * >(ptrStrMap);
00137 
00138         std::map< std::string, u32 > r_ptrNumMap =
00139             *reinterpret_cast< std::map< std::string, u32 > * >(ptrNumMap);
00140 
00141         std::map< std::string, std::string > r_ptrStrMapSource =
00142             *reinterpret_cast< std::map< std::string, std::string > * >(source.ptrStrMap);
00143 
00144         std::map< std::string, u32 > r_ptrNumMapSource =
00145             *reinterpret_cast< std::map< std::string, u32 > * >(source.ptrNumMap);
00146 
00147         // copy parameters over from source
00148         std::map< std::string, u32 >::iterator iter = r_ptrNumMapSource.begin();
00149         while ( iter != r_ptrNumMapSource.end() )
00150         {
00151             setParameter( iter->first, iter->second );
00152             ++iter;
00153         }
00154 
00155         std::map< std::string, std::string >::iterator iterStr = r_ptrStrMapSource.begin();
00156         while ( iterStr != r_ptrStrMapSource.end() )
00157         {
00158             setParameter( iterStr->first, iterStr->second );
00159             ++iterStr;
00160         }
00161 
00162         return *this;
00163     }
00164 
00165     template <class S>
00166     void Exception<S>::allocateMaps()
00167     {
00168         // careful of exceptions
00169         try
00170         {
00171             std::map< std::string, std::string > *r_ptrStrMap =
00172                 new std::map< std::string, std::string >;
00173 
00174             ptrStrMap = reinterpret_cast<void*>(r_ptrStrMap);
00175 
00176             std::map< std::string, u32 > *r_ptrNumMap =
00177                 new std::map< std::string, u32 >;
00178 
00179             ptrNumMap = reinterpret_cast<void*>(r_ptrNumMap);
00180         }
00181         catch( const std::exception & )
00182         {
00183             // destructor is not called if constructor throws, free mem ourselves.
00184             deAllocateMaps();
00185             throw;
00186         }
00187     }
00188 
00189     template <class S>
00190     void Exception<S>::deAllocateMaps()
00191     {
00192         if( ptrStrMap )
00193         {
00194             std::map< std::string, std::string > *r_ptrStrMap =
00195                 reinterpret_cast< std::map< std::string, std::string > * >(ptrStrMap);
00196             delete r_ptrStrMap;
00197         }
00198         ptrStrMap = 0;
00199 
00200         if( ptrNumMap )
00201         {
00202             std::map< std::string, u32 > *r_ptrNumMap =
00203                 reinterpret_cast< std::map< std::string, u32 > * >(ptrNumMap);
00204             delete r_ptrNumMap;
00205         }
00206         ptrNumMap = 0;
00207     }
00208 
00209 
00210 
00211 
00212 
00213 
00214     template <class S>
00215     const char * Exception<S>::what() const throw()
00216     {
00217         outputStr = messageStr;
00218 
00219         size_t strLen = outputStr.length();
00220         size_t pos = 0;
00221         while(pos < strLen)
00222         {
00223             std::string varName = "";
00224             size_t replaceLen = 0;
00225             char varType;
00226             size_t endVar = 0;
00227             std::ostringstream rep;
00228 
00229             pos = outputStr.find( "%", pos );
00230             if( pos >= strLen )  // no more occurences
00231                 break;
00232 
00233             // handle '%' as last character
00234             if( pos == strLen-1 )
00235                 break;  // this is an error. maybe throw?
00236 
00237             // handle %%
00238             if( outputStr[pos+1] == '%' )
00239             {
00240                 outputStr.replace(pos, 2, "%");
00241                 goto next_pos;
00242             }
00243 
00244             if( outputStr[pos+1] != '(' )
00245             {
00246                 // somebody lost their mind. Ignore them
00247                 //   Only legal sequences with '%' are: "%%" and "%("
00248                 goto next_pos;  // this is an error. maybe throw?
00249             }
00250 
00251             endVar = outputStr.find( ")", pos );
00252             if( endVar >= strLen )
00253             {
00254                 // again with the crazy people.
00255                 goto next_pos;  // this is an error. maybe throw?
00256             }
00257 
00258             // handle "%(xXx)" at end with no var type.
00259             if( endVar == strLen-1 )
00260                 break;  // this is an error. maybe throw?
00261 
00262             varType = outputStr[endVar + 1];
00263 
00264             replaceLen = endVar - pos + 2;
00265             varName = outputStr.substr( pos+2, replaceLen - 4 );
00266 
00267             // limit vars to 32 chars (limit accidental runaway vars.)
00268             if( replaceLen > 32 )
00269                 goto next_pos;
00270 
00271             switch( varType )
00272             {
00273             case 'i':
00274                 rep <<  getParameterNumber(varName);
00275                 outputStr.replace( pos, replaceLen, rep.str() );
00276                 goto loop_end; // go back to start of while(), lets us recursively substitute
00277             case 's':
00278                 outputStr.replace( pos, replaceLen, getParameterString(varName));
00279                 goto loop_end; // go back to start of while(), lets us recursively substitute
00280             }
00281 
00282 next_pos:
00283             ++pos;
00284 
00285 loop_end:
00286             strLen = outputStr.length(); // in case string changed
00287         }
00288 
00289         return outputStr.c_str();
00290     }
00291 
00292     template <class S>
00293     void Exception<S>::setMessageString( const std::string &newStr )
00294     {
00295         messageStr = newStr;
00296     }
00297 
00298 
00299     template <class S>
00300     void Exception<S>::setParameter( const std::string &name, const std::string &value)
00301     {
00302         std::map< std::string, std::string > *r_ptrStrMap =
00303             reinterpret_cast< std::map< std::string, std::string > * >(ptrStrMap);
00304 
00305         (*r_ptrStrMap)[ name ] = value;
00306     }
00307 
00308     template <class S>
00309     void Exception<S>::setParameter( const std::string &name, const u32 value)
00310     {
00311         std::map< std::string, u32 > *r_ptrNumMap =
00312             reinterpret_cast< std::map< std::string, u32 > * >(ptrNumMap);
00313 
00314         (*r_ptrNumMap)[ name ] = value;
00315     }
00316 
00317 
00318     template <class S>
00319     u32 Exception<S>::getParameterNumber( const std::string &name ) const
00320     {
00321         std::map< std::string, u32 > r_ptrNumMap =
00322             *reinterpret_cast< std::map< std::string, u32 > * >(ptrNumMap);
00323 
00324         //cout << "num param map: ";
00325         //std::map< std::string, u32 >::iterator iter = r_ptrNumMap.begin();
00326         //while ( iter != r_ptrNumMap.end() )
00327         //{
00328         //cout << "\tName: " << iter->first << "\tValue: " << iter->second << endl;
00329         //++iter;
00330         //}
00331         //cout << endl;
00332         return r_ptrNumMap[ name ];
00333     }
00334 
00335     template <class S>
00336     std::string Exception<S>::getParameterString( const std::string &name ) const
00337     {
00338         std::map< std::string, std::string > r_ptrStrMap =
00339             *reinterpret_cast< std::map< std::string, std::string > * >(ptrStrMap);
00340 
00341         //cout << "str param map: ";
00342         //std::map< std::string, std::string >::iterator iter = r_ptrStrMap.begin();
00343         //while ( iter != r_ptrStrMap.end() )
00344         //{
00345         //cout << "\tName: " << iter->first << "\tValue: " << iter->second << endl;
00346         //++iter;
00347         //}
00348         //cout << endl;
00349         return r_ptrStrMap[ name ];
00350     }
00351 
00352 
00353 
00354     // some standard exceptions
00355 
00360     DEFINE_EXCEPTION_EX( NotImplementedImpl, smbios, NotImplemented );
00361 
00366     DEFINE_EXCEPTION_EX( InternalErrorImpl, smbios, InternalError );
00367 
00369     DEFINE_EXCEPTION_EX( PermissionExceptionImpl, smbios, PermissionException );
00370 }
00371 
00372 // always should be last thing in header file
00373 #include "smbios/config/abi_suffix.hpp"
00374 
00375 #endif /* EXCEPTIONIMPL_H */

Generated on Tue Jul 11 20:46:46 2006 for SMBIOS Library by  doxygen 1.4.7