TuttleOFX
1
|
00001 #ifndef _TUTTLE_COMMON_EXCEPTION_HPP_ 00002 #define _TUTTLE_COMMON_EXCEPTION_HPP_ 00003 00004 namespace boost { 00005 struct errinfo_file_name_ {}; 00006 } 00007 namespace tuttle { namespace exception { 00008 struct tag_userMessage {}; 00009 struct tag_devMessage {}; 00010 struct tag_backtraceMessage {}; 00011 struct tag_ofxContext {}; 00012 struct tag_ofxApi {}; 00013 struct tag_pluginIdentifier {}; 00014 struct tag_pluginName {}; 00015 struct tag_nodeName {}; 00016 struct tag_time {}; 00017 }} 00018 00019 #include "utils/boost_error_info_sstream.hpp" 00020 #include "utils/backtrace.hpp" 00021 00022 #include <tuttle/common/ofx/core.hpp> 00023 #include <tuttle/common/ofx/utilities.hpp> 00024 #include <boost/version.hpp> 00025 #include <boost/lexical_cast.hpp> 00026 #include <boost/exception/exception.hpp> 00027 #include <boost/exception/info.hpp> 00028 #include <boost/exception/errinfo_file_name.hpp> 00029 #include <boost/exception/diagnostic_information.hpp> 00030 #include <boost/exception/get_error_info.hpp> 00031 00032 #include <tuttle/common/utils/color.hpp> 00033 00034 #include <ofxCorePlugin.h> 00035 #include <ofxImageEffect.h> 00036 00037 #include <sstream> 00038 #include <string> 00039 #include <stdexcept> 00040 00041 #define TUTTLE_LOG_EXCEPTION( e ) \ 00042 TUTTLE_LOG_ERROR( "Exception:" ); \ 00043 TUTTLE_LOG_ERROR( TUTTLE_GET_INFOS_FILE ); \ 00044 TUTTLE_LOG_ERROR( TUTTLE_GET_INFOS_FUNCTION ); \ 00045 TUTTLE_LOG_ERROR( "\t" << ::boost::diagnostic_information( e ) ) 00046 00047 #define TUTTLE_LOG_CURRENT_EXCEPTION \ 00048 TUTTLE_LOG_ERROR( "Exception:" ); \ 00049 TUTTLE_LOG_ERROR( TUTTLE_GET_INFOS_FILE ); \ 00050 TUTTLE_LOG_ERROR( TUTTLE_GET_INFOS_FUNCTION ); \ 00051 TUTTLE_LOG_ERROR( "\t" << ::boost::current_exception_diagnostic_information() ) 00052 00053 #ifndef SWIG 00054 namespace OFX { 00055 typedef ::boost::error_info<struct tag_ofxStatus, ::OfxStatus> ofxStatus; 00056 inline std::string to_string( const ofxStatus& e ) 00057 { 00058 return ::tuttle::ofx::mapStatusToString( e.value() ); 00059 } 00060 } 00061 #endif 00062 00063 namespace tuttle { 00064 00065 /** 00066 * @brief To add quotes around a string. 00067 * @example quotes("toto") -> "\"toto\"" 00068 */ 00069 inline std::string quotes( const std::string& s ) 00070 { 00071 return "\"" + s + "\""; 00072 } 00073 00074 namespace exception { 00075 00076 #ifndef SWIG 00077 /** 00078 * @brief Like a stringstream but using "operator+" instead of "operator<<". 00079 * Use a stringstream internally. 00080 */ 00081 00082 /** 00083 * @brief Standard tags you can use to add informations to your exceptions. 00084 * 00085 * @remark We use lower camel case for tags, 00086 * to keep a difference between tags and exceptions. 00087 */ 00088 /// @{ 00089 /** 00090 * @brief If you catch an error at the top level, you can print this information to the user. 00091 * @remark User information. 00092 */ 00093 typedef ::boost::error_info<struct tag_userMessage, ::boost::error_info_sstream> user; 00094 00095 /** 00096 * @brief This is detailed informations for developpers. 00097 * Not always a real human readable message :) 00098 * @remark Dev information. 00099 */ 00100 //typedef ::boost::error_info<struct tag_message,std::string> dev; 00101 typedef ::boost::error_info<struct tag_devMessage, ::boost::error_info_sstream> dev; 00102 //typedef ::boost::error_info_sstream<struct tag_message> dev; 00103 00104 /** 00105 * @brief When we convert a C++ exception into a Python exception, 00106 * we put the C++ backtrace into the message. 00107 * 00108 * @remark Dev information. 00109 */ 00110 typedef ::boost::error_info<struct tag_backtraceMessage, ::boost::error_info_sstream> backtrace; 00111 00112 /** 00113 * @brief The ofx error status code. 00114 * @remark Dev information. 00115 */ 00116 typedef ::OFX::ofxStatus ofxStatus; 00117 00118 /** 00119 * @brief The ofx context name. 00120 * Each plugin can be instanciated in differents contexts (depending on the declaration of supported contexts). 00121 * @remark Dev information. 00122 */ 00123 typedef ::boost::error_info<struct tag_ofxContext, ::std::string> ofxContext; 00124 /** 00125 * @brief The ofx api string identification. 00126 * @remark Dev information. 00127 */ 00128 typedef ::boost::error_info<struct tag_ofxApi, ::std::string> ofxApi; 00129 /** 00130 * @brief Plugin string identifier. 00131 * @remark Dev information. 00132 */ 00133 typedef ::boost::error_info<struct tag_pluginIdentifier, ::std::string> pluginIdentifier; 00134 /** 00135 * @brief Plugin name. 00136 * @remark User information. 00137 */ 00138 typedef ::boost::error_info<struct tag_pluginName, ::std::string> pluginName; 00139 /** 00140 * @brief Node name. 00141 * @remark User information. 00142 */ 00143 typedef ::boost::error_info<struct tag_nodeName, ::std::string> nodeName; 00144 /** 00145 * @brief Time. 00146 * @remark Dev or user information. 00147 */ 00148 typedef ::boost::error_info<struct tag_time, OfxTime> time; 00149 /** 00150 * @brief Problem with a file. 00151 * @remark User information. 00152 */ 00153 typedef ::boost::errinfo_file_name filename; 00154 /// @} 00155 #endif 00156 00157 /** @brief Common exception for all tuttle plugin exceptions */ 00158 struct Common : virtual public ::std::exception 00159 , virtual public ::boost::exception 00160 , virtual public ::boost::backtrace 00161 {}; 00162 00163 /// @brief Ofx standard errors 00164 /// @{ 00165 00166 /** 00167 * @brief You have to specify the exception::ofxStatus(kOfxStatXXX) yourself. 00168 * When you call a base level function (C API) which returns an ofxStatus, you can use this exception and fill it with the returned value using ofxStatus tag. 00169 */ 00170 struct OfxCustom : virtual public Common 00171 { 00172 OfxCustom( const OfxStatus status ) 00173 { 00174 *this << ofxStatus( status ); 00175 } 00176 }; 00177 00178 /** @brief Status error code for a failed operation */ 00179 struct Failed : virtual public Common 00180 { 00181 Failed() 00182 { 00183 * this << ofxStatus( kOfxStatFailed ); 00184 } 00185 00186 }; 00187 00188 /** 00189 * @brief Status error code for a fatal error 00190 * 00191 * Only returned in the case where the plug-in or host cannot continue to function and needs to be restarted. 00192 */ 00193 struct Fatal : virtual public Common 00194 { 00195 Fatal() 00196 { 00197 * this << ofxStatus( kOfxStatErrFatal ); 00198 } 00199 00200 }; 00201 00202 /** @brief Status error code for an operation on or request for an unknown object */ 00203 struct Unknown : virtual public Common 00204 { 00205 Unknown() 00206 { 00207 * this << ofxStatus( kOfxStatErrUnknown ); 00208 } 00209 00210 }; 00211 00212 /** 00213 * @brief Status error code returned by plug-ins when they are missing host functionality, either an API or some optional functionality (eg: custom params). 00214 * 00215 * Plug-Ins returning this should post an appropriate error message stating what they are missing. 00216 */ 00217 struct MissingHostFeature : virtual Common 00218 { 00219 MissingHostFeature() 00220 { 00221 * this << ofxStatus( kOfxStatErrMissingHostFeature ); 00222 } 00223 MissingHostFeature( const std::string& feature ) 00224 { 00225 * this << ofxStatus( kOfxStatErrMissingHostFeature ); 00226 * this << user() + "Missing feature: " + quotes(feature); 00227 } 00228 }; 00229 00230 /** @brief Status error code for an unsupported feature/operation */ 00231 struct Unsupported : virtual public Common 00232 { 00233 Unsupported() 00234 { 00235 * this << ofxStatus( kOfxStatErrUnsupported ); 00236 } 00237 00238 }; 00239 00240 /** @brief Status error code for an operation attempting to create something that exists */ 00241 struct Exists : virtual public Common 00242 { 00243 Exists() 00244 { 00245 * this << ofxStatus( kOfxStatErrExists ); 00246 } 00247 00248 }; 00249 00250 /** @brief Status error code for an incorrect format */ 00251 struct Format : virtual public Common 00252 { 00253 Format() 00254 { 00255 * this << ofxStatus( kOfxStatErrFormat ); 00256 } 00257 00258 }; 00259 00260 /** @brief Status error code indicating that something failed due to memory shortage */ 00261 struct Memory : virtual public Common 00262 { 00263 Memory() 00264 { 00265 * this << ofxStatus( kOfxStatErrMemory ); 00266 } 00267 00268 }; 00269 00270 /** @brief Status error code for an operation on a bad handle */ 00271 struct BadHandle : virtual public Common 00272 { 00273 BadHandle() 00274 { 00275 * this << ofxStatus( kOfxStatErrBadHandle ); 00276 } 00277 00278 }; 00279 00280 /** @brief Status error code indicating that a given index was invalid or unavailable */ 00281 struct BadIndex : virtual public Common 00282 { 00283 BadIndex() 00284 { 00285 * this << ofxStatus( kOfxStatErrBadIndex ); 00286 } 00287 00288 }; 00289 00290 /** @brief Status error code indicating that something failed due an illegal value */ 00291 struct Value : virtual public Common 00292 { 00293 Value() 00294 { 00295 * this << ofxStatus( kOfxStatErrValue ); 00296 } 00297 00298 }; 00299 00300 /// @brief imageEffect specific errors 00301 /// @{ 00302 00303 /** @brief Error code for incorrect image formats */ 00304 struct ImageFormat : virtual public Common 00305 { 00306 ImageFormat() 00307 { 00308 * this << ofxStatus( kOfxStatErrImageFormat ); 00309 } 00310 00311 }; 00312 /// @} 00313 /// @} 00314 00315 /// @brief Other exceptions 00316 /// @{ 00317 00318 /** 00319 * @brief The class serves as the base class for all exceptions thrown to report errors presumably detectable before the program executes, such as violations of logical preconditions (cf. std::logic_error). 00320 * @remark With this exception, you normally have a "user" tag message. 00321 */ 00322 struct Logic : virtual public Failed {}; 00323 00324 /** 00325 * @brief Something that should never appends. 00326 * These exceptions may be replaced by assertions, 00327 * but we prefer to keep a runtime check even in release (for the moment). 00328 * @remark With this exception, you should have a "dev" tag message. 00329 */ 00330 struct Bug : virtual public Fatal {}; 00331 00332 /** @brief Unknown error inside a conversion. */ 00333 struct BadConversion : virtual public Failed {}; 00334 00335 /** @brief Error with a NULL image buffer. 00336 * * plugin: The host launch a process, but the input clips are not filled (eg. NULL buffer pointer). 00337 * The error comes from host. 00338 * * host: Error with memory cache or memory pool. 00339 */ 00340 struct ImageNotReady : virtual public Value {}; 00341 00342 /** 00343 * @brief A non optional input clip in not connected. 00344 * * plugin: Normally the host should not launch the render in this case. 00345 * The error comes from host. 00346 * * host: We can't launch the render in this case. 00347 */ 00348 struct ImageNotConnected : virtual public Failed {}; 00349 00350 /** 00351 * @brief Input property don't satisfy descriptor requirements. 00352 * * plugin: The error comes from host. 00353 * * host: We can't launch the render in this case. 00354 */ 00355 struct InputMismatch : virtual public Format {}; 00356 00357 /** 00358 * @brief Input and output properties mismatch. 00359 * * plugin: The error comes from host. 00360 * * host: We can't launch the render in this case. 00361 */ 00362 struct InOutMismatch : virtual public Format {}; 00363 00364 /** 00365 * @brief Input(s) and enventually output properties mismatch. 00366 * * plugin: The error comes from host. 00367 * * host: We can't launch the render in this case. 00368 */ 00369 struct BitDepthMismatch : virtual public ImageFormat {}; 00370 00371 /** 00372 * @brief Image raw bytes not valid. 00373 * * plugin: The error comes from host. 00374 * * host: We can't launch the render in this case. 00375 */ 00376 struct WrongRowBytes : virtual public ImageFormat {}; 00377 00378 /** @brief Status error code indicating that something failed due an illegal data. */ 00379 struct Data : virtual public Value {}; 00380 00381 /** @brief Something that could work, but is not implemeted. */ 00382 struct NotImplemented : virtual public Unsupported {}; 00383 00384 /** @brief The parameter doesn't make sense. */ 00385 struct WrongParameter : virtual public Value {}; 00386 00387 /** 00388 * @brief File manipulation error. 00389 * eg. read only, file doesn't exists, etc. 00390 */ 00391 struct File : virtual public Failed 00392 { 00393 File() 00394 {} 00395 File( const std::string& path ) 00396 { 00397 *this << user("File error."); 00398 *this << filename(path); 00399 } 00400 }; 00401 00402 /** 00403 * @brief File doesn't exist. 00404 */ 00405 struct FileNotExist : virtual public File 00406 { 00407 FileNotExist() 00408 {} 00409 FileNotExist( const std::string& path ) 00410 { 00411 *this << user("No such file."); 00412 *this << filename(path); 00413 } 00414 }; 00415 00416 /** 00417 * @brief File already exists. 00418 */ 00419 struct FileExist : virtual public File 00420 { 00421 FileExist() 00422 {} 00423 FileExist( const std::string& path ) 00424 { 00425 *this << user("File already exists."); 00426 *this << filename(path); 00427 } 00428 }; 00429 00430 /** 00431 * @brief File in sequence doesn't exist. 00432 */ 00433 struct FileInSequenceNotExist : virtual public File 00434 { 00435 FileInSequenceNotExist() 00436 {} 00437 FileInSequenceNotExist( const std::string& path ) 00438 { 00439 *this << user("No such file."); 00440 *this << filename(path); 00441 } 00442 }; 00443 00444 /** 00445 * @brief Directory doesn't exist. 00446 */ 00447 struct NoDirectory : virtual public File 00448 { 00449 NoDirectory() 00450 {} 00451 NoDirectory( const std::string& path ) 00452 { 00453 *this << user("No such directory."); 00454 *this << filename(path); 00455 } 00456 }; 00457 00458 /** 00459 * @brief Read only file. 00460 */ 00461 struct ReadOnlyFile : virtual public File 00462 { 00463 ReadOnlyFile() 00464 {} 00465 ReadOnlyFile( const std::string& path ) 00466 { 00467 *this << user("Read-only file."); 00468 *this << filename(path); 00469 } 00470 }; 00471 /// @} 00472 00473 std::string format_exception_message( const ::boost::exception& e ); 00474 std::string format_exception_info( const ::boost::exception& e ); 00475 std::string format_current_exception(); 00476 00477 } 00478 } 00479 00480 #endif