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

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 // Macro for convenient exception throwing
00052 // (includes message, file, line #)
00053 #define THROW(Type, txt) \
00054     throw Type ( std::string( __FILE__ ## ":Line " ## LIBSMBIOS_STRINGIZE(__LINE__)) + txt)
00055 
00056 namespace smbios
00057 {
00058     // TODO: all this needs to be hidden to preserve ABI.
00059     template <class S>
00060     class Exception : public S
00061     {
00062     public:
00063         // destructor
00064         virtual ~Exception() throw() {};
00065         // constructors
00066         Exception( const std::string initMessage ) : S(), messageStr( initMessage ), outputStr("") {};
00067         Exception( ) : S(), messageStr( "" ), outputStr("")  {};
00068         Exception( const Exception<S> &source );
00069         // overloaded assignment
00070         Exception<S> &operator =( const Exception<S> &source );
00071 
00072         virtual const char *what() const throw() ;
00073         virtual std::string getParameterString( const std::string &name ) const;
00074         virtual u32 getParameterNumber( const std::string &name ) const;
00075 
00076         virtual void setMessageString( const std::string &newMsgString );
00077         virtual void setParameter( const std::string &name, const std::string &value );
00078         virtual void setParameter( const std::string &name, const u32 value );
00079     private:
00080         std::string messageStr;
00081         mutable std::string outputStr;
00082 
00083         std::map< std::string, std::string > r_ptrStrMap;
00084         std::map< std::string, u32 > r_ptrNumMap;
00085     };
00086 
00087     // copy constructor
00088     template <class S>
00089     Exception<S>::Exception( const Exception<S> &source )
00090             : S(), messageStr( source.messageStr ), outputStr("")
00091     {
00092         // copy parameters over from source
00093         std::map< std::string, u32 >::const_iterator iter = source.r_ptrNumMap.begin();
00094         while ( iter != source.r_ptrNumMap.end() )
00095         {
00096             setParameter( iter->first, iter->second );
00097             ++iter;
00098         }
00099 
00100         std::map< std::string, std::string >::const_iterator iterStr = source.r_ptrStrMap.begin();
00101         while ( iterStr != source.r_ptrStrMap.end() )
00102         {
00103             setParameter( iterStr->first, iterStr->second );
00104             ++iterStr;
00105         }
00106     }
00107 
00108     // overloaded assignment
00109     template <class S>
00110     Exception<S> &Exception<S>::operator =( const Exception<S> &source )
00111     {
00112         if (this == &source)
00113             return *this;
00114         
00115         messageStr = source.messageStr;
00116         outputStr = "";
00117 
00118         // copy parameters over from source
00119         std::map< std::string, u32 >::const_iterator iter = source.r_ptrNumMap.begin();
00120         while ( iter != source.r_ptrNumMap.end() )
00121         {
00122             setParameter( iter->first, iter->second );
00123             ++iter;
00124         }
00125 
00126         std::map< std::string, std::string >::const_iterator iterStr = source.r_ptrStrMap.begin();
00127         while ( iterStr != source.r_ptrStrMap.end() )
00128         {
00129             setParameter( iterStr->first, iterStr->second );
00130             ++iterStr;
00131         }
00132 
00133         return *this;
00134     }
00135 
00136     template <class S>
00137     const char * Exception<S>::what() const throw()
00138     {
00139         outputStr = messageStr;
00140 
00141         size_t strLen = outputStr.length();
00142         size_t pos = 0;
00143         while(pos < strLen)
00144         {
00145             std::string varName = "";
00146             size_t replaceLen = 0;
00147             char varType;
00148             size_t endVar = 0;
00149             std::ostringstream rep;
00150 
00151             pos = outputStr.find( "%", pos );
00152             if( pos >= strLen )  // no more occurences
00153                 break;
00154 
00155             // handle '%' as last character
00156             if( pos == strLen-1 )
00157                 break;  // this is an error. maybe throw?
00158 
00159             // handle %%
00160             if( outputStr[pos+1] == '%' )
00161             {
00162                 outputStr.replace(pos, 2, "%");
00163                 goto next_pos;
00164             }
00165 
00166             if( outputStr[pos+1] != '(' )
00167             {
00168                 // somebody lost their mind. Ignore them
00169                 //   Only legal sequences with '%' are: "%%" and "%("
00170                 goto next_pos;  // this is an error. maybe throw?
00171             }
00172 
00173             endVar = outputStr.find( ")", pos );
00174             if( endVar >= strLen )
00175             {
00176                 // again with the crazy people.
00177                 goto next_pos;  // this is an error. maybe throw?
00178             }
00179 
00180             // handle "%(xXx)" at end with no var type.
00181             if( endVar == strLen-1 )
00182                 break;  // this is an error. maybe throw?
00183 
00184             varType = outputStr[endVar + 1];
00185 
00186             replaceLen = endVar - pos + 2;
00187             varName = outputStr.substr( pos+2, replaceLen - 4 );
00188 
00189             // limit vars to 32 chars (limit accidental runaway vars.)
00190             if( replaceLen > 32 )
00191                 goto next_pos;
00192 
00193             switch( varType )
00194             {
00195             case 'i':
00196                 rep <<  getParameterNumber(varName);
00197                 outputStr.replace( pos, replaceLen, rep.str() );
00198                 goto loop_end; // go back to start of while(), lets us recursively substitute
00199             case 's':
00200                 outputStr.replace( pos, replaceLen, getParameterString(varName));
00201                 goto loop_end; // go back to start of while(), lets us recursively substitute
00202             }
00203 
00204 next_pos:
00205             ++pos;
00206 
00207 loop_end:
00208             strLen = outputStr.length(); // in case string changed
00209         }
00210 
00211         return outputStr.c_str();
00212     }
00213 
00214     template <class S>
00215     void Exception<S>::setMessageString( const std::string &newStr )
00216     {
00217         messageStr = newStr;
00218     }
00219 
00220 
00221     template <class S>
00222     void Exception<S>::setParameter( const std::string &name, const std::string &value)
00223     {
00224         r_ptrStrMap[ name ] = value;
00225     }
00226 
00227     template <class S>
00228     void Exception<S>::setParameter( const std::string &name, const u32 value)
00229     {
00230         r_ptrNumMap[ name ] = value;
00231     }
00232 
00233 
00234     template <class S>
00235     u32 Exception<S>::getParameterNumber( const std::string &name ) const
00236     {
00237         std::map< std::string, u32 >::const_iterator iterStr = r_ptrNumMap.find(name);
00238         return iterStr->second;
00239     }
00240 
00241     template <class S>
00242     std::string Exception<S>::getParameterString( const std::string &name ) const
00243     {
00244         std::map< std::string, std::string >::const_iterator iterStr = r_ptrStrMap.find(name);
00245         return iterStr->second;
00246     }
00247 
00248 
00249 
00250     // some standard exceptions
00251 
00256     DEFINE_EXCEPTION_EX( NotImplementedImpl, smbios, NotImplemented );
00257 
00262     DEFINE_EXCEPTION_EX( InternalErrorImpl, smbios, InternalError );
00263 
00265     DEFINE_EXCEPTION_EX( PermissionExceptionImpl, smbios, PermissionException );
00266 }
00267 
00268 // always should be last thing in header file
00269 #include "smbios/config/abi_suffix.hpp"
00270 
00271 #endif /* EXCEPTIONIMPL_H */

Generated on Wed Apr 11 16:25:10 2007 for SMBIOS Library by doxygen 1.3.5