pion  5.0.6
include/pion/error.hpp
00001 // ---------------------------------------------------------------------
00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
00003 // ---------------------------------------------------------------------
00004 // Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
00005 //
00006 // Distributed under the Boost Software License, Version 1.0.
00007 // See http://www.boost.org/LICENSE_1_0.txt
00008 //
00009 
00010 #ifndef __PION_ERROR_HEADER__
00011 #define __PION_ERROR_HEADER__
00012 
00013 #include <string>
00014 #include <sstream>
00015 #include <exception>
00016 #include <boost/version.hpp>
00017 #include <boost/throw_exception.hpp>
00018 #include <boost/exception/exception.hpp>
00019 #include <boost/exception/info.hpp>
00020 #include <boost/exception/error_info.hpp>
00021 #include <boost/exception/get_error_info.hpp>
00022 #if BOOST_VERSION >= 104700
00023 #include <boost/units/io.hpp>
00024 #endif
00025 #include <pion/config.hpp>
00026 
00027 
00028 namespace pion {    // begin namespace pion
00029 
00030     //
00031     // exception: simple exception class for pion errors that generates what()
00032     // strings with more descriptive messages and optionally arguments as well
00033     //
00034     class exception
00035         : public virtual std::exception, public virtual boost::exception
00036     {
00037     public:
00038         exception() {}
00039         exception(const std::string& msg) : m_what_msg(msg) {}
00040         exception(const char * const msg) : m_what_msg(msg) {}
00041         virtual ~exception() throw () {}
00042         virtual const char* what() const throw() {
00043             if (m_what_msg.empty()) update_what_msg();
00044             return m_what_msg.c_str();
00045         }
00046     protected:
00047         inline void set_what_msg(const char * const msg = NULL, const std::string * const arg1 = NULL, const std::string * const arg2 = NULL, const std::string * const arg3 = NULL) const {
00048             std::ostringstream tmp;
00049 #if BOOST_VERSION >= 104700
00050             tmp << ( msg ? msg : boost::units::detail::demangle(BOOST_EXCEPTION_DYNAMIC_TYPEID(*this).type_->name()) );
00051 #else
00052             tmp << ( msg ? msg : boost::units::detail::demangle(BOOST_EXCEPTION_DYNAMIC_TYPEID(*this).type_.name()) );
00053 #endif
00054             if (arg1 || arg2 || arg3) tmp << ':';
00055             if (arg1) tmp << ' ' << *arg1;
00056             if (arg2) tmp << ' ' << *arg2;
00057             if (arg3) tmp << ' ' << *arg3;
00058             m_what_msg = tmp.str();
00059         }
00060         virtual void update_what_msg() const { set_what_msg(); }
00061         mutable std::string m_what_msg;
00062     };
00063     
00064     
00071     template <class T>
00072     static inline std::string
00073     diagnostic_information( T const & e )
00074     {
00075         boost::exception const * const be = dynamic_cast<const boost::exception*>(&e);
00076         std::exception const * const se = dynamic_cast<const std::exception*>(&e);
00077         std::ostringstream tmp;
00078         if (se) {
00079             tmp << se->what();
00080         } else {
00081 #if BOOST_VERSION >= 104700
00082             tmp << boost::units::detail::demangle(BOOST_EXCEPTION_DYNAMIC_TYPEID(e).type_->name());
00083 #else
00084             tmp << boost::units::detail::demangle(BOOST_EXCEPTION_DYNAMIC_TYPEID(e).type_.name());
00085 #endif
00086         }
00087         if (be) {
00088             //char const * const * fn=boost::get_error_info<boost::throw_function>(*be);
00089             //if (fn) tmp << " at " << *fn;
00090             char const * const * f=boost::get_error_info<boost::throw_file>(*be);
00091             if (f) {
00092                 tmp << " [" << *f;
00093                 if (int const * l=boost::get_error_info<boost::throw_line>(*be))
00094                     tmp << ':' << *l;
00095                 tmp << "]";
00096             }
00097         }
00098         return tmp.str();
00099     }
00100 
00101     
00102     namespace error {    // begin namespace error
00103 
00104         //
00105         // pion error info types
00106         //
00107         
00109         typedef boost::error_info<struct errinfo_arg_name_,std::string> errinfo_message;
00110         
00112         typedef boost::error_info<struct errinfo_arg_name_,std::string> errinfo_arg_name;
00113         
00115         typedef boost::error_info<struct errinfo_file_name_,std::string> errinfo_file_name;
00116         
00118         typedef boost::error_info<struct errinfo_dir_name_,std::string> errinfo_dir_name;
00119         
00121         typedef boost::error_info<struct errinfo_plugin_name_,std::string> errinfo_plugin_name;
00122         
00124         typedef boost::error_info<struct errinfo_dir_name_,std::string> errinfo_symbol_name;
00125 
00126         
00127         //
00128         // pion exception types
00129         //
00130 
00132         class bad_arg : public pion::exception {
00133             virtual void update_what_msg() const {
00134                 set_what_msg("bad argument", boost::get_error_info<errinfo_arg_name>(*this));
00135             }
00136         };
00137         
00139         class bad_config : public pion::exception {
00140             virtual void update_what_msg() const {
00141                 set_what_msg("config parser error", boost::get_error_info<errinfo_file_name>(*this));
00142             }
00143         };
00144         
00146         class open_file : public pion::exception {
00147             virtual void update_what_msg() const {
00148                 set_what_msg("unable to open file", boost::get_error_info<errinfo_file_name>(*this));
00149             }
00150         };
00151         
00153         class open_plugin : public pion::exception {
00154             virtual void update_what_msg() const {
00155                 set_what_msg("unable to open plugin", boost::get_error_info<errinfo_plugin_name>(*this));
00156             }
00157         };
00158         
00160         class read_file : public pion::exception {
00161             virtual void update_what_msg() const {
00162                 set_what_msg("unable to read file", boost::get_error_info<errinfo_file_name>(*this));
00163             }
00164         };
00165         
00167         class file_not_found : public pion::exception {
00168             virtual void update_what_msg() const {
00169                 set_what_msg("file not found", boost::get_error_info<errinfo_file_name>(*this));
00170             }
00171         };
00172         
00174         class directory_not_found : public pion::exception {
00175             virtual void update_what_msg() const {
00176                 set_what_msg("directory not found", boost::get_error_info<errinfo_dir_name>(*this));
00177             }
00178         };
00179 
00181         class plugin_not_found : public pion::exception {
00182             virtual void update_what_msg() const {
00183                 set_what_msg("plugin not found", boost::get_error_info<errinfo_plugin_name>(*this));
00184             }
00185         };
00186         
00188         class duplicate_plugin : public pion::exception {
00189             virtual void update_what_msg() const {
00190                 set_what_msg("duplicate plugin", boost::get_error_info<errinfo_plugin_name>(*this));
00191             }
00192         };
00193 
00195         class plugin_missing_symbol : public pion::exception {
00196             virtual void update_what_msg() const {
00197                 set_what_msg("missing plugin symbol", boost::get_error_info<errinfo_symbol_name>(*this));
00198             }
00199         };
00200       
00202         class plugin_undefined : public pion::exception {
00203             virtual void update_what_msg() const {
00204                 set_what_msg("plugin has undefined state");
00205             }
00206         };
00207         
00209         class bad_password_hash : public pion::exception {
00210             virtual void update_what_msg() const {
00211                 set_what_msg("bad password hash");
00212             }
00213         };
00214     
00215     }   // end namespace error
00216     
00217 }   // end namespace pion
00218 
00219 #endif