Warning, file /sdk/codevis/thirdparty/soci/src/core/error.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
0003 // Copyright (C) 2015 Vadim Zeitlin
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 
0009 #define SOCI_SOURCE
0010 
0011 #include "soci/error.h"
0012 
0013 #include <sstream>
0014 #include <vector>
0015 
0016 namespace soci
0017 {
0018 
0019 class soci_error_extra_info
0020 {
0021 public:
0022     soci_error_extra_info()
0023     {
0024     }
0025 
0026     // Default copy ctor, assignment operator and dtor are fine.
0027 
0028     char const* get_full_message(std::string const& message)
0029     {
0030         if (full_message_.empty())
0031         {
0032             full_message_ = message;
0033 
0034             if (!contexts_.empty())
0035             {
0036                 // This is a hack, but appending the extra context to the
0037                 // message looks much better if we remove the full stop at its
0038                 // end first.
0039                 if (*full_message_.rbegin() == '.')
0040                     full_message_.erase(full_message_.size() - 1);
0041 
0042                 // Now do append all the extra context we have.
0043                 typedef std::vector<std::string>::const_iterator iter_type;
0044                 for (iter_type i = contexts_.begin(); i != contexts_.end(); ++i)
0045                 {
0046                     full_message_ += " ";
0047                     full_message_ += *i;
0048                 }
0049 
0050                 // It seems better to always terminate the full message with a
0051                 // full stop, even if the original error message didn't have it
0052                 // (and if it had, we just restore the one we chopped off).
0053                 full_message_ += ".";
0054             }
0055         }
0056 
0057         return full_message_.c_str();
0058     }
0059 
0060     void add_context(std::string const& context)
0061     {
0062         full_message_.clear();
0063         contexts_.push_back(context);
0064     }
0065 
0066 private:
0067     // The full error message, we need to store it as a string as we return a
0068     // pointer to its contents from get_full_message().
0069     std::string full_message_;
0070 
0071     // If non-empty, contains extra context for this exception, e.g.
0072     // information about the SQL statement that resulted in it, with the top
0073     // element corresponding to the most global context.
0074     std::vector<std::string> contexts_;
0075 };
0076 
0077 namespace
0078 {
0079 
0080 // Make a safe, even in presence of exceptions, heap-allocated copy of the
0081 // given object if it's non-null (otherwise just return null pointer).
0082 soci_error_extra_info *make_safe_copy(soci_error_extra_info* info)
0083 {
0084     try
0085     {
0086         return info ? new soci_error_extra_info(*info) : NULL;
0087     }
0088     catch (...)
0089     {
0090         // Copy ctor of an exception class shouldn't throw to avoid program
0091         // termination, so it's better to lose the extra information than allow
0092         // an exception to except from here.
0093         return NULL;
0094     }
0095 }
0096 
0097 } // anonymous namespace
0098 
0099 soci_error::soci_error(std::string const & msg)
0100      : std::runtime_error(msg)
0101 {
0102     info_ = NULL;
0103 }
0104 
0105 soci_error::soci_error(soci_error const& e) noexcept
0106     : std::runtime_error(e)
0107 {
0108     info_ = make_safe_copy(e.info_);
0109 }
0110 
0111 soci_error& soci_error::operator=(soci_error const& e) noexcept
0112 {
0113     if (this == &e)
0114     {
0115         return *this;
0116     }
0117 
0118     std::runtime_error::operator=(e);
0119 
0120     delete info_;
0121     info_ = make_safe_copy(e.info_);
0122 
0123     return *this;
0124 }
0125 
0126 soci_error::~soci_error() noexcept
0127 {
0128     delete info_;
0129 }
0130 
0131 std::string soci_error::get_error_message() const
0132 {
0133     return std::runtime_error::what();
0134 }
0135 
0136 char const* soci_error::what() const noexcept
0137 {
0138     if (info_)
0139         return info_->get_full_message(get_error_message());
0140 
0141     return std::runtime_error::what();
0142 }
0143 
0144 void soci_error::add_context(std::string const& context)
0145 {
0146     if (!info_)
0147         info_ = new soci_error_extra_info();
0148 
0149     info_->add_context(context);
0150 }
0151 
0152 } // namespace soci