00001
00002
00003
00004
00005
00006
00007
00008
00009
00030 #ifndef _NSXException_
00031 #define _NSXException_
00032
00033 #include <Cocoa/Cocoa.h>
00034 #include <exception>
00035 #include <typeinfo>
00036
00037
00038
00039
00040
00041
00042 #pragma mark (Classes)
00043
00044
00049 class NSXException : public std::exception {
00050 public:
00052 NSXException(
00053 NSException *nsexception )
00054 : nsexception_( nsexception ){}
00055
00057 NSException*
00058 nsexception() const
00059 { return nsexception_; }
00060
00062 void
00063 raise() const {
00064 [nsexception_ raise];
00065 }
00066
00068 virtual
00069 const char*
00070 what() const throw() {
00071 return "NSXException";
00072 }
00073
00074
00085 static
00086 NSException*
00087 NSExceptionForException(
00088 const std::exception *cppException )
00089 {
00090 const NSXException *nsxexception = dynamic_cast<const NSXException*>( cppException );
00091 if( nsxexception ) {
00092
00093 return nsxexception->nsexception();
00094 } else {
00095
00096 NSData *cppExceptionWrapper = [NSData dataWithBytes:&cppException length:sizeof(cppException)];
00097 NSDictionary *userInfo = [NSDictionary
00098 dictionaryWithObject: cppExceptionWrapper
00099 forKey:@"std::exception"];
00100 NSString *reason = [NSString stringWithFormat:@"%s: %s", typeid(cppException).name(), cppException->what()];
00101 return [NSException
00102 exceptionWithName:@"NSException-wrapped std::exception"
00103 reason:reason
00104 userInfo:userInfo];
00105 }
00106 }
00107
00108
00115 static
00116 void
00117 Raise(
00118 const std::exception *cppException )
00119 {
00120 [NSXException::NSExceptionForException( cppException ) raise];
00121 }
00122
00123
00130 static
00131 void
00132 Throw(
00133 NSException *objCException )
00134 {
00135 NSDictionary *userInfo = [objCException userInfo];
00136 NSData *cppException = [userInfo valueForKey:@"std::exception"];
00137 if( cppException ) {
00138 std::exception *exception;
00139 [cppException getBytes:&exception];
00140 throw exception;
00141 } else {
00142 throw new NSXException( objCException );
00143 }
00144 }
00145 private:
00146 NSException *nsexception_;
00147 };
00148
00149
00162 class AutoNSExceptionHandler : public _NSHandler2 {
00163 public:
00165 AutoNSExceptionHandler()
00166 : installed_( true ) {
00167 _NSAddHandler2( this );
00168 }
00169
00172 ~AutoNSExceptionHandler() {
00173 if( installed_ ) {
00174 _NSRemoveHandler2( this );
00175 installed_ = false;
00176 }
00177 }
00178
00182 NSException* localException() {
00183 installed_ = false;
00184 return _NSExceptionObjectFromHandler2( this );
00185 }
00186 private:
00187 bool installed_;
00188 };
00189
00190
00216 class NSXRaisingDestructor {
00217 public:
00219 NSXRaisingDestructor()
00220 : nsexception_( nil ){}
00221
00223 ~NSXRaisingDestructor() {
00224 if( nsexception_ != nil )
00225 [nsexception_ raise];
00226 }
00227
00229 void arm( NSException *exception ) {
00230 nsexception_ = exception;
00231 }
00232
00235 void arm( const std::exception *exception ) {
00236 nsexception_ = NSXException::NSExceptionForException( exception );
00237 }
00238 private:
00239 NSException *nsexception_;
00240 };
00241
00242
00243
00244
00245
00246
00247 #pragma mark -
00248 #pragma mark (Multiline Exception Morphing Macros)
00249
00250
00284 #define NSX_THROW \
00285 { \
00286 AutoNSExceptionHandler handler_; \
00287 if( !_NSSETJMP( handler_._state, 0 ) ) {
00288
00289
00296 #define NSX_ENDTHROW \
00297 } else { \
00298 NSXException::Throw( handler_.localException() ); \
00299 } \
00300 }
00301
00302
00326 #define NSX_RAISE \
00327 { \
00328 NSXRaisingDestructor raisingDestructor; \
00329 try {
00330
00331
00338 #define NSX_ENDRAISE \
00339 } catch( const std::exception *x ) { \
00340 raisingDestructor.arm( x ); \
00341 } \
00342 }
00343
00344
00345
00346
00347
00348
00349 #pragma mark -
00350 #pragma mark (Single-line Exception Morphing Macros)
00351
00352
00377 #define ThrowNSX( CODE ) \
00378 { \
00379 AutoNSExceptionHandler handler_; \
00380 if( !_NSSETJMP( handler_._state, 0 ) ) { \
00381 CODE; \
00382 } else { \
00383 NSXException::Throw( handler_.localException() ); \
00384 } \
00385 }
00386
00387
00410 #define RaiseNSX( CODE ) \
00411 { \
00412 NSXRaisingDestructor raisingDestructor; \
00413 try { \
00414 CODE; \
00415 } catch( const std::exception *x ) { \
00416 raisingDestructor.arm( x ); \
00417 } \
00418 }
00419
00420
00421
00422
00423
00424
00425 #pragma mark -
00426 #pragma mark (Scope-Aware Version of NS_DURING)
00427
00428
00436 #define NSX_DURING \
00437 { \
00438 AutoNSExceptionHandler handler_; \
00439 if( !_NSSETJMP( handler_._state, 0 ) ) {
00440
00441
00448 #define NSX_HANDLER \
00449 } else { \
00450 NSException *localException = handler_.localException();
00451
00452
00459 #define NSX_ENDHANDLER \
00460 localException = localException; \
00461 } \
00462 }
00463
00464 #endif // _NSXException_