From 854f733c4931f8b227e940e2375bc5f99fbb11b0 Mon Sep 17 00:00:00 2001 From: Willi Goesgens Date: Wed, 21 Jan 2015 15:03:21 +0100 Subject: [PATCH] Exceptions: - Assert that the associated errorcode has format options so if you call a THROW-macro with parameters these don't get lost unheard. - Add new macro which offers format strings, so you can throw standard errors with custom messages. --- arangod/Utils/Exception.cpp | 34 ++++++++++++++++++++++++++++++++++ arangod/Utils/Exception.h | 17 +++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/arangod/Utils/Exception.cpp b/arangod/Utils/Exception.cpp index a699010f61..94c376909c 100644 --- a/arangod/Utils/Exception.cpp +++ b/arangod/Utils/Exception.cpp @@ -117,6 +117,9 @@ char const* Exception::what () const throw () { return _errorMessage.c_str(); } + + + //////////////////////////////////////////////////////////////////////////////// /// @brief construct an error message from a template string //////////////////////////////////////////////////////////////////////////////// @@ -126,6 +129,11 @@ std::string Exception::FillExceptionString (int code, char const* format = TRI_errno_string(code); TRI_ASSERT(format != nullptr); +#ifdef TRI_ENABLE_MAINTAINER_MODE + // Obviously the formatstring of the error code has to support parameters. + TRI_ASSERT(strchr(format, '%') != nullptr); +#endif + char buffer[1024]; va_list ap; va_start(ap, code); @@ -136,6 +144,32 @@ std::string Exception::FillExceptionString (int code, return std::string(buffer); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief construct an error message from a template string +//////////////////////////////////////////////////////////////////////////////// + +std::string Exception::FillFormatExceptionString (char const* format, + ...) { + TRI_ASSERT(format != nullptr); + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // Format #1 should come from the macro... + TRI_ASSERT(strchr(format, '%') != nullptr); + // Obviously the user has to give us a format string. + TRI_ASSERT(strchr(strchr(format, '%'), '%') != nullptr); +#endif + + char buffer[1024]; + va_list ap; + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer) - 1, format, ap); + va_end(ap); + buffer[sizeof(buffer) - 1] = '\0'; // Windows + + return std::string(buffer); +} + + //////////////////////////////////////////////////////////////////////////////// /// @brief controls whether a backtrace is created for each exception //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/Exception.h b/arangod/Utils/Exception.h index 2c1430097c..a4e8fa98fd 100644 --- a/arangod/Utils/Exception.h +++ b/arangod/Utils/Exception.h @@ -54,6 +54,21 @@ #define THROW_ARANGO_EXCEPTION_PARAMS(code, ...) \ throw triagens::arango::Exception(code, triagens::arango::Exception::FillExceptionString(code, __VA_ARGS__), __FILE__, __LINE__) + + +//////////////////////////////////////////////////////////////////////////////// +/// @brief throws an arango exception with an error code and arbitrary +/// arguments (to be inserted in printf-style manner) +//////////////////////////////////////////////////////////////////////////////// + +#define THROW_ARANGO_EXCEPTION_FORMAT(code, format, ...) \ + throw triagens::arango::Exception(code, \ + triagens::arango::Exception::FillFormatExceptionString( \ + "%s: " format,\ + TRI_errno_string(code), \ + __VA_ARGS__),\ + __FILE__, __LINE__) + //////////////////////////////////////////////////////////////////////////////// /// @brief throws an arango exception with an error code and an already-built /// error message @@ -105,6 +120,8 @@ namespace triagens { } static std::string FillExceptionString (int, ...); + static std::string FillFormatExceptionString (char const * format, + ...); //////////////////////////////////////////////////////////////////////////////// /// @brief controls whether a backtrace is created for each exception