SMBIOS Library
ExceptionImpl.h
Go to the documentation of this file.
1 // vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:
2 /*
3  * Copyright (C) 2005 Dell Inc.
4  * by Michael Brown <Michael_E_Brown@dell.com>
5  * Licensed under the Open Software License version 2.1
6  *
7  * Alternatively, you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation; either version 2 of the License,
10  * or (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  * See the GNU General Public License for more details.
16  */
17 
18 
19 #ifndef EXCEPTIONIMPL_H
20 #define EXCEPTIONIMPL_H
21 
22 
23 
24 // compat header should always be first header
25 #include "smbios/compat.h"
26 
27 #include <map>
28 #include <string>
29 #include <sstream>
30 #include <exception>
31 
32 // types.h should be first user-defined header.
33 #include "smbios/types.h"
34 #include "smbios/IException.h"
35 
36 // abi_prefix should be last header included before declarations
38 
39 #define DEFINE_EXCEPTION_EX( excName, ns, superclass ) \
40  class excName : public smbios::Exception< ns :: superclass > \
41  { \
42  public: \
43  ~excName() throw() {}; \
44  excName( const std::string initMessage ) : smbios::Exception< ns :: superclass >(initMessage) {} ;\
45  excName( const excName &src ) : smbios::Exception< ns :: superclass >(src) {} ;\
46  excName( ) : smbios::Exception< ns :: superclass >() {} ;\
47  }
48 
49  /*commented out fragment above is valid code but hits a bug in MSVC++ and emits C2437 diagnostic erroneously*/
50 
51 // Macro for convenient exception throwing
52 // (includes message, file, line #)
53 #define THROW(Type, txt) \
54  throw Type ( std::string( __FILE__ ## ":Line " ## LIBSMBIOS_STRINGIZE(__LINE__)) + txt)
55 
56 namespace smbios
57 {
58  // TODO: all this needs to be hidden to preserve ABI.
59  template <class S>
60  class Exception : public S
61  {
62  public:
63  // destructor
64  virtual ~Exception() throw() {};
65  // constructors
66  Exception( const std::string initMessage ) : S(), messageStr( initMessage ), outputStr("") {};
67  Exception( ) : S(), messageStr( "" ), outputStr("") {};
68  Exception( const Exception<S> &source );
69  // overloaded assignment
70  Exception<S> &operator =( const Exception<S> &source );
71 
72  virtual const char *what() const throw() ;
73  virtual std::string getParameterString( const std::string &name ) const;
74  virtual u32 getParameterNumber( const std::string &name ) const;
75 
76  virtual void setMessageString( const std::string &newMsgString );
77  virtual void setParameter( const std::string &name, const std::string &value );
78  virtual void setParameter( const std::string &name, const u32 value );
79  private:
80  std::string messageStr;
81  mutable std::string outputStr;
82 
83  std::map< std::string, std::string > r_ptrStrMap;
84  std::map< std::string, u32 > r_ptrNumMap;
85  };
86 
87  // copy constructor
88  template <class S>
89  Exception<S>::Exception( const Exception<S> &source )
90  : S(), messageStr( source.messageStr ), outputStr("")
91  {
92  // copy parameters over from source
93  std::map< std::string, u32 >::const_iterator iter = source.r_ptrNumMap.begin();
94  while ( iter != source.r_ptrNumMap.end() )
95  {
96  setParameter( iter->first, iter->second );
97  ++iter;
98  }
99 
100  std::map< std::string, std::string >::const_iterator iterStr = source.r_ptrStrMap.begin();
101  while ( iterStr != source.r_ptrStrMap.end() )
102  {
103  setParameter( iterStr->first, iterStr->second );
104  ++iterStr;
105  }
106  }
107 
108  // overloaded assignment
109  template <class S>
111  {
112  if (this == &source)
113  return *this;
114 
115  messageStr = source.messageStr;
116  outputStr = "";
117 
118  // copy parameters over from source
119  std::map< std::string, u32 >::const_iterator iter = source.r_ptrNumMap.begin();
120  while ( iter != source.r_ptrNumMap.end() )
121  {
122  setParameter( iter->first, iter->second );
123  ++iter;
124  }
125 
126  std::map< std::string, std::string >::const_iterator iterStr = source.r_ptrStrMap.begin();
127  while ( iterStr != source.r_ptrStrMap.end() )
128  {
129  setParameter( iterStr->first, iterStr->second );
130  ++iterStr;
131  }
132 
133  return *this;
134  }
135 
136  template <class S>
137  const char * Exception<S>::what() const throw()
138  {
140 
141  size_t strLen = outputStr.length();
142  size_t pos = 0;
143  while(pos < strLen)
144  {
145  std::string varName = "";
146  size_t replaceLen = 0;
147  char varType;
148  size_t endVar = 0;
149  std::ostringstream rep;
150 
151  pos = outputStr.find( "%", pos );
152  if( pos >= strLen ) // no more occurences
153  break;
154 
155  // handle '%' as last character
156  if( pos == strLen-1 )
157  break; // this is an error. maybe throw?
158 
159  // handle %%
160  if( outputStr[pos+1] == '%' )
161  {
162  outputStr.replace(pos, 2, "%");
163  goto next_pos;
164  }
165 
166  if( outputStr[pos+1] != '(' )
167  {
168  // somebody lost their mind. Ignore them
169  // Only legal sequences with '%' are: "%%" and "%("
170  goto next_pos; // this is an error. maybe throw?
171  }
172 
173  endVar = outputStr.find( ")", pos );
174  if( endVar >= strLen )
175  {
176  // again with the crazy people.
177  goto next_pos; // this is an error. maybe throw?
178  }
179 
180  // handle "%(xXx)" at end with no var type.
181  if( endVar == strLen-1 )
182  break; // this is an error. maybe throw?
183 
184  varType = outputStr[endVar + 1];
185 
186  replaceLen = endVar - pos + 2;
187  varName = outputStr.substr( pos+2, replaceLen - 4 );
188 
189  // limit vars to 32 chars (limit accidental runaway vars.)
190  if( replaceLen > 32 )
191  goto next_pos;
192 
193  switch( varType )
194  {
195  case 'i':
196  rep << getParameterNumber(varName);
197  outputStr.replace( pos, replaceLen, rep.str() );
198  goto loop_end; // go back to start of while(), lets us recursively substitute
199  case 's':
200  outputStr.replace( pos, replaceLen, getParameterString(varName));
201  goto loop_end; // go back to start of while(), lets us recursively substitute
202  }
203 
204 next_pos:
205  ++pos;
206 
207 loop_end:
208  strLen = outputStr.length(); // in case string changed
209  }
210 
211  return outputStr.c_str();
212  }
213 
214  template <class S>
215  void Exception<S>::setMessageString( const std::string &newStr )
216  {
217  messageStr = newStr;
218  }
219 
220 
221  template <class S>
222  void Exception<S>::setParameter( const std::string &name, const std::string &value)
223  {
224  r_ptrStrMap[ name ] = value;
225  }
226 
227  template <class S>
228  void Exception<S>::setParameter( const std::string &name, const u32 value)
229  {
230  r_ptrNumMap[ name ] = value;
231  }
232 
233 
234  template <class S>
235  u32 Exception<S>::getParameterNumber( const std::string &name ) const
236  {
237  std::map< std::string, u32 >::const_iterator iterStr = r_ptrNumMap.find(name);
238  return iterStr->second;
239  }
240 
241  template <class S>
242  std::string Exception<S>::getParameterString( const std::string &name ) const
243  {
244  std::map< std::string, std::string >::const_iterator iterStr = r_ptrStrMap.find(name);
245  return iterStr->second;
246  }
247 
248 
249 
250  // some standard exceptions
251 
256  DEFINE_EXCEPTION_EX( NotImplementedImpl, smbios, NotImplemented );
257 
262  DEFINE_EXCEPTION_EX( InternalErrorImpl, smbios, InternalError );
263 
265  DEFINE_EXCEPTION_EX( PermissionExceptionImpl, smbios, PermissionException );
266 }
267 
268 // always should be last thing in header file
270 
271 #endif /* EXCEPTIONIMPL_H */