From 6b9a3a534071ef84c121c406559f8fc7ad546104 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 11 Dec 2015 09:42:06 -0500 Subject: Reroot the exception hierarchy into a toplevel Exception class As the alternatives are unfortunate for applications trying to catch all library errors, and it seems deriving from std::runtime_error causes problems with MSVC DLLs (GH #340) Effectively reverts 2837e915d82e43 --- src/lib/utils/assert.cpp | 2 +- src/lib/utils/dyn_load/dyn_load.cpp | 4 ++-- src/lib/utils/exceptn.h | 33 ++++++++++++++++++++++----------- src/lib/utils/http_util/http_util.cpp | 16 ++++++++-------- src/lib/utils/http_util/http_util.h | 2 +- src/lib/utils/parsing.cpp | 2 +- src/lib/utils/read_cfg.cpp | 2 +- src/lib/utils/sqlite3/sqlite3.cpp | 16 ++++++++-------- 8 files changed, 44 insertions(+), 33 deletions(-) (limited to 'src/lib/utils') diff --git a/src/lib/utils/assert.cpp b/src/lib/utils/assert.cpp index 978fc12a1..d729a8368 100644 --- a/src/lib/utils/assert.cpp +++ b/src/lib/utils/assert.cpp @@ -30,7 +30,7 @@ void assertion_failure(const char* expr_str, format << "@" << file << ":" << line; - throw std::runtime_error(format.str()); + throw Exception(format.str()); } } diff --git a/src/lib/utils/dyn_load/dyn_load.cpp b/src/lib/utils/dyn_load/dyn_load.cpp index 723d2502e..9b99331d1 100644 --- a/src/lib/utils/dyn_load/dyn_load.cpp +++ b/src/lib/utils/dyn_load/dyn_load.cpp @@ -22,7 +22,7 @@ namespace { void raise_runtime_loader_exception(const std::string& lib_name, const char* msg) { - throw std::runtime_error("Failed to load " + lib_name + ": " + + throw Exception("Failed to load " + lib_name + ": " + (msg ? msg : "Unknown error")); } @@ -70,7 +70,7 @@ void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol) #endif if(!addr) - throw std::runtime_error("Failed to resolve symbol " + symbol + + throw Exception("Failed to resolve symbol " + symbol + " in " + lib_name); return addr; diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h index eef1b4d43..c9b45f916 100644 --- a/src/lib/utils/exceptn.h +++ b/src/lib/utils/exceptn.h @@ -16,8 +16,28 @@ namespace Botan { -typedef std::runtime_error Exception; -typedef std::invalid_argument Invalid_Argument; +/** +* Base class for all exceptions thrown by the library +*/ +class BOTAN_DLL Exception : public std::exception + { + public: + Exception(const std::string& what) : m_what(what) {} + Exception(const char* prefix, const std::string& what) : m_what(std::string(prefix) + " " + what) {} + const char* what() const override { return m_what.c_str(); } + private: + std::string m_what; + }; + +/** +* An invalid argument which caused +*/ +class BOTAN_DLL Invalid_Argument : public Exception + { + public: + Invalid_Argument(const std::string& what) : + Exception("Invalid argument", what) {} + }; /** * Unsupported_Argument Exception @@ -196,15 +216,6 @@ struct BOTAN_DLL Self_Test_Failure : public Internal_Error {} }; -/** -* Memory Allocation Exception -*/ -struct BOTAN_DLL Memory_Exhaustion : public std::bad_alloc - { - const char* what() const BOTAN_NOEXCEPT override - { return "Ran out of memory, allocation failed"; } - }; - } #endif diff --git a/src/lib/utils/http_util/http_util.cpp b/src/lib/utils/http_util/http_util.cpp index 1a15d6418..c437d0148 100644 --- a/src/lib/utils/http_util/http_util.cpp +++ b/src/lib/utils/http_util/http_util.cpp @@ -30,7 +30,7 @@ std::string http_transact_asio(const std::string& hostname, tcp.connect(hostname, "http"); if(!tcp) - throw std::runtime_error("HTTP connection to " + hostname + " failed"); + throw Exception("HTTP connection to " + hostname + " failed"); tcp << message; tcp.flush(); @@ -45,7 +45,7 @@ std::string http_transact_asio(const std::string& hostname, std::string http_transact_fail(const std::string& hostname, const std::string&) { - throw std::runtime_error("Cannot connect to " + hostname + + throw Exception("Cannot connect to " + hostname + ": network code disabled in build"); } @@ -89,7 +89,7 @@ Response http_sync(http_exch_fn http_transact, { const auto protocol_host_sep = url.find("://"); if(protocol_host_sep == std::string::npos) - throw std::runtime_error("Invalid URL " + url); + throw Exception("Invalid URL " + url); const std::string protocol = url.substr(0, protocol_host_sep); const auto host_loc_sep = url.find('/', protocol_host_sep + 3); @@ -130,7 +130,7 @@ Response http_sync(http_exch_fn http_transact, std::string line1; std::getline(io, line1); if(!io || line1.empty()) - throw std::runtime_error("No response"); + throw Exception("No response"); std::stringstream response_stream(line1); std::string http_version; @@ -142,7 +142,7 @@ Response http_sync(http_exch_fn http_transact, std::getline(response_stream, status_message); if(!response_stream || http_version.substr(0,5) != "HTTP/") - throw std::runtime_error("Not an HTTP response"); + throw Exception("Not an HTTP response"); std::map headers; std::string header_line; @@ -150,7 +150,7 @@ Response http_sync(http_exch_fn http_transact, { auto sep = header_line.find(": "); if(sep == std::string::npos || sep > header_line.size() - 2) - throw std::runtime_error("Invalid HTTP header " + header_line); + throw Exception("Invalid HTTP header " + header_line); const std::string key = header_line.substr(0, sep); if(sep + 2 < header_line.size() - 1) @@ -163,7 +163,7 @@ Response http_sync(http_exch_fn http_transact, if(status_code == 301 && headers.count("Location")) { if(allowable_redirects == 0) - throw std::runtime_error("HTTP redirection count exceeded"); + throw Exception("HTTP redirection count exceeded"); return GET_sync(headers["Location"], allowable_redirects - 1); } @@ -180,7 +180,7 @@ Response http_sync(http_exch_fn http_transact, if(header_size != "") { if(resp_body.size() != to_u32bit(header_size)) - throw std::runtime_error("Content-Length disagreement, header says " + + throw Exception("Content-Length disagreement, header says " + header_size + " got " + std::to_string(resp_body.size())); } diff --git a/src/lib/utils/http_util/http_util.h b/src/lib/utils/http_util/http_util.h index 2acb6c6e4..746b790f1 100644 --- a/src/lib/utils/http_util/http_util.h +++ b/src/lib/utils/http_util/http_util.h @@ -43,7 +43,7 @@ struct Response void throw_unless_ok() { if(status_code() != 200) - throw std::runtime_error("HTTP error: " + status_message()); + throw Exception("HTTP error: " + status_message()); } private: diff --git a/src/lib/utils/parsing.cpp b/src/lib/utils/parsing.cpp index 40eae656a..179e2e546 100644 --- a/src/lib/utils/parsing.cpp +++ b/src/lib/utils/parsing.cpp @@ -45,7 +45,7 @@ u32bit to_u32bit(const std::string& str) auto message = std::string("Could not read '" + str + "' as decimal string"); auto exceptionMessage = std::string(e.what()); if (!exceptionMessage.empty()) message += ": " + exceptionMessage; - throw std::runtime_error(message); + throw Exception(message); } } diff --git a/src/lib/utils/read_cfg.cpp b/src/lib/utils/read_cfg.cpp index 22e725328..0719ee681 100644 --- a/src/lib/utils/read_cfg.cpp +++ b/src/lib/utils/read_cfg.cpp @@ -49,7 +49,7 @@ std::map read_cfg(std::istream& is) auto eq = s.find("="); if(eq == std::string::npos || eq == 0 || eq == s.size() - 1) - throw std::runtime_error("Bad read_cfg input '" + s + "' on line " + std::to_string(line)); + throw Exception("Bad read_cfg input '" + s + "' on line " + std::to_string(line)); const std::string key = clean_ws(s.substr(0, eq)); const std::string val = clean_ws(s.substr(eq + 1, std::string::npos)); diff --git a/src/lib/utils/sqlite3/sqlite3.cpp b/src/lib/utils/sqlite3/sqlite3.cpp index 267d7530a..fde89b91d 100644 --- a/src/lib/utils/sqlite3/sqlite3.cpp +++ b/src/lib/utils/sqlite3/sqlite3.cpp @@ -20,7 +20,7 @@ Sqlite3_Database::Sqlite3_Database(const std::string& db_filename) const std::string err_msg = ::sqlite3_errmsg(m_db); ::sqlite3_close(m_db); m_db = nullptr; - throw std::runtime_error("sqlite3_open failed - " + err_msg); + throw Exception("sqlite3_open failed - " + err_msg); } } @@ -43,7 +43,7 @@ size_t Sqlite3_Database::row_count(const std::string& table_name) if(stmt->step()) return stmt->get_size_t(0); else - throw std::runtime_error("Querying size of table " + table_name + " failed"); + throw Exception("Querying size of table " + table_name + " failed"); } void Sqlite3_Database::create_table(const std::string& table_schema) @@ -57,7 +57,7 @@ void Sqlite3_Database::create_table(const std::string& table_schema) ::sqlite3_free(errmsg); ::sqlite3_close(m_db); m_db = nullptr; - throw std::runtime_error("sqlite3_exec for table failed - " + err_msg); + throw Exception("sqlite3_exec for table failed - " + err_msg); } } @@ -66,7 +66,7 @@ Sqlite3_Database::Sqlite3_Statement::Sqlite3_Statement(sqlite3* db, const std::s int rc = ::sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, nullptr); if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_prepare failed " + base_sql + + throw Exception("sqlite3_prepare failed " + base_sql + ", code " + std::to_string(rc)); } @@ -74,16 +74,16 @@ void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::string& va { int rc = ::sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT); if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + throw Exception("sqlite3_bind_text failed, code " + std::to_string(rc)); } void Sqlite3_Database::Sqlite3_Statement::bind(int column, size_t val) { if(val != static_cast(static_cast(val))) // is this legit? - throw std::runtime_error("sqlite3 cannot store " + std::to_string(val) + " without truncation"); + throw Exception("sqlite3 cannot store " + std::to_string(val) + " without truncation"); int rc = ::sqlite3_bind_int(m_stmt, column, val); if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc)); + throw Exception("sqlite3_bind_int failed, code " + std::to_string(rc)); } void Sqlite3_Database::Sqlite3_Statement::bind(int column, std::chrono::system_clock::time_point time) @@ -96,7 +96,7 @@ void Sqlite3_Database::Sqlite3_Statement::bind(int column, const std::vector Sqlite3_Database::Sqlite3_Statement::get_blob(int column) -- cgit v1.2.3