From 27ff5f97792f897371d09cbbe7b12ab161dd8a7c Mon Sep 17 00:00:00 2001 From: Andreas Waidler Date: Tue, 9 Aug 2011 21:53:34 +0200 Subject: [PATCH] Doc/syntax work. --- source/Exception.cxx | 28 +++++----- source/Exception.hxx | 103 ++++++++++++++++------------------ source/utility.cxx | 41 +++++--------- source/utility.hxx | 153 +++++++++++++++++++++++++-------------------------- source/utility.ixx | 8 +-- 5 files changed, 154 insertions(+), 179 deletions(-) rewrite source/utility.hxx (89%) diff --git a/source/Exception.cxx b/source/Exception.cxx index e752c4f..20b0195 100644 --- a/source/Exception.cxx +++ b/source/Exception.cxx @@ -1,17 +1,17 @@ #include #include // strncpy() -namespace libsex { - -Exception::Exception(const char* const message) throw() +libsex::Exception::Exception(const char* const message) +throw() : _previous(0) { _initMessage(message); } -Exception::Exception( +libsex::Exception::Exception( const char* const message, - const Exception& previous) throw() + const Exception& previous) +throw() : _previous(0) { _initMessage(message); @@ -36,17 +36,20 @@ Exception::Exception( } } -Exception::~Exception() throw() +libsex::Exception::~Exception() +throw() { if (_previous) delete _previous; } -void Exception::write(std::ostream& out) const throw(std::ios_base::failure) +void libsex::Exception::write(std::ostream& out) const +throw(std::ios_base::failure) { out << what(); } -void Exception::backtrace(std::ostream& out) const throw(std::ios_base::failure) +void libsex::Exception::backtrace(std::ostream& out) const +throw(std::ios_base::failure) { write(out); if (_previous != 0) { @@ -55,7 +58,7 @@ void Exception::backtrace(std::ostream& out) const throw(std::ios_base::failure) } } -const Exception* Exception::clone() const +const libsex::Exception* libsex::Exception::clone() const throw(std::bad_alloc) { if (_previous) { @@ -65,12 +68,13 @@ throw(std::bad_alloc) } } -const char* Exception::what() const throw() +const char* libsex::Exception::what() const +throw() { return _message; } -void Exception::_initMessage(const char* const message) +void libsex::Exception::_initMessage(const char* const message) { strncpy(_message, message, Exception::LENGTH); // if |message| < |_message| @@ -79,5 +83,3 @@ void Exception::_initMessage(const char* const message) // strncpy() will NOT add a trailing 0! _message[Exception::LENGTH] = 0; } - -} // namespace diff --git a/source/Exception.hxx b/source/Exception.hxx index a9de5de..9aafa5d 100644 --- a/source/Exception.hxx +++ b/source/Exception.hxx @@ -5,48 +5,25 @@ #include // std::bad_alloc #include // std::ostream -namespace libsex { +namespace libsex +{ + /** + * Generic error made up of a message and + * (optional) references to previous one. + * + * Double-fault save (not throwing std::bad_alloc + * or other exceptions in critical situations) and + * allows exception chaining. + * + * For object-oriented error handling you should + * subclass this class for every type of error. + * There are elegant macros in @file declare.hxx + * and @file define.hxx. + */ + class Exception; +} -/** - * Resembles a generic error, stores a message and - * optionally references one previous error (linked list). - * - * The supplied character array must be terminated by a - * nullbyte. It will be copied into an internal array - * (stored on the stack) that is @ref LENGTH chars long, - * until a nullbyte is reached or the internal array is - * full. - * - * It is possible create chained exceptions. Since we have - * to assume that all exceptions are created on the stack, - * the previous exception will be copied to the heap and - * the current exception stores a pointer to this copy - * (singly linked list). - * - * Hence, it is possible that, while having a chain of - * exceptions "bubbling up", a std::bad_alloc is thrown. In - * this case, a notice is appended and both std::bad_alloc - * and previous exceptions are ignored. Instances that have - * already been copied on the heap will be deleted - * automatically when the latest exception (on the stack) - * gets out of scope (RAII). - * - * Constructors that accept instances of std::string as - * error messages have been left out. These strings utilize - * the heap which may result in above mentioned "double - * fault". Thus, accepting std::string is likely to turn - * out to be a pitfall. However, std::string responds to - * the message @c c_str by providing a pointer to the - * underlying character stringm so this design decision - * does not create any problems. - * - * @note For OO error handling you should subclass this - * class for every type of error. Inheriting by hand - * is tedious, you usally don't want to do this. - * There are some efficient macros in @file - * macros.hxx. - */ -class Exception : public std::exception +class libsex::Exception : public std::exception { public: /// Max payload of the internal character string. @@ -55,9 +32,18 @@ public: /** * Creates an exception. * - * The specified message is copied into an internal - * buffer of @ref LENGTH + 1 (nullbyte) characters - * length. + * Supplied character array should be null- + * terminated and should not exceed LENGTH + * characters (excl. null byte). Its contents will + * be copied into an internal buffer and can be + * overwritten/freed afterwards. + * + * The constructors do not accept std::string + * since that class uses the heap and may throw + * std::bad_alloc -- which might obviously happen + * even before this constructor is entered and + * thus might result in loss of the actual (chain + * of) exception(s) describing the error. */ Exception(const char* const message) throw(); @@ -65,17 +51,19 @@ public: * Creates a chained exception. * * Both the error message and the previous - * exception are copied. While @a message is copied - * into an internal buffer, clone() is send to @a - * previous which in turn dynamically creates a - * shallow copy of itsself on the heap and returns - * a pointer to it. + * exception are cloned. * - * Hence, it is possible that clone() may throw - * std::bad_alloc. In that case, a notice is - * appended to this message (as long as the - * internal buffer contains free fields) and the - * instance of std::bad_alloc is swallowed. + * Since exceptions should be created on the stack + * (see std::bad_alloc), the previous one will be + * internally copied to the heap by calling + * clone(). + * + * If clone() throws std::bad_alloc, a notice is + * appended to the internal message buffer of this + * exception (as long as space left) and + * std::bad_alloc is swallowed. + * + * @see Exception(message) */ Exception( const char* const message, @@ -106,7 +94,10 @@ public: void backtrace(std::ostream& out) const throw(std::ios_base::failure); /** - * Clones this exception. + * Creates a shallow copy of this exception. + * + * Copy is allocated on the heap. + * * @throws std::bad_alloc on memory shortage. */ virtual const Exception* clone() const throw(std::bad_alloc); @@ -129,6 +120,4 @@ private: void _initMessage(const char* const message); }; -} // namespace - #endif diff --git a/source/utility.cxx b/source/utility.cxx index fba45ac..e038ebf 100644 --- a/source/utility.cxx +++ b/source/utility.cxx @@ -1,56 +1,45 @@ #include #include -namespace libsex { - -bool vformat( - char* const buffer, - size_t length, +bool libsex::vformat( + char* const buf, + size_t len, const char* const file, unsigned short line, - const char* const message, + const char* const msg, va_list ap) throw() { - size_t chars - = snprintf( - buffer, length, - "%s:%d: ", file, line); + size_t chars = snprintf(buf, len, "%s:%d: ", file, line); // If buffer was too small, chars contains length // of chars that would've been written. Chars must // be lower than length or else we could not fit // the message into buffer, too. - bool didFitIntoBuffer = chars < length; + bool didFitIntoBuffer = chars < len; if (didFitIntoBuffer) { - size_t newLength = length - chars; - char* const newBuffer = buffer + chars; - chars = vsnprintf( - newBuffer, newLength, - message, ap); - // See comment above. + size_t newLength = len - chars; + char* const newBuffer = buf + chars; + chars = vsnprintf(newBuffer, newLength, msg, ap); didFitIntoBuffer = chars <= newLength; } return didFitIntoBuffer; } -bool format( - char* const buffer, - size_t length, +bool libsex::format( + char* const buf, + size_t len, const char* const file, unsigned short line, - const char* const message, + const char* const msg, ...) throw() { va_list ap; - va_start(ap, message); + va_start(ap, msg); - bool result = vformat( - buffer, length, file, line, message, ap); + bool result = vformat(buf, len, file, line, msg, ap); va_end(ap); return result; } - -} // namespace diff --git a/source/utility.hxx b/source/utility.hxx dissimilarity index 89% index 54d4cf6..bb921c7 100644 --- a/source/utility.hxx +++ b/source/utility.hxx @@ -1,77 +1,76 @@ -#ifndef LIBSEX_UTILITY_HXX -#define LIBSEX_UTILITY_HXX - -#include - -#include // variadic argument fun -#include // size_t - -namespace libsex { - -/** - * Formats a message and writes it into @a buffer. - * - * It is guaranteed that not more than @a length characters - * are written to @a buffer. - * - * @param buffer String to be filled. - * @param length Size of buffer. - * @param file Filename in which the error occured. - * @param line Line number in which the error occured. - * @param message printf formatstring template - * @param ap variadic argument list, holds parameters - * to be used when formatting (vsnprintf()). - * @return true if buffer was large enough, false otherwise - */ -bool vformat( - char* const buffer, - size_t length, - const char* const file, - unsigned short line, - const char* const message, - va_list ap) throw(); - -/// @see vformat() -bool format( - char* const buffer, - size_t length, - const char* const file, - unsigned short line, - const char* const message, - ...) throw(); - -/** - * Instanciates T with properly formatted message. - * - * T is supposed to have a static const char* TEMPLATE - * field, which will be used as formatstring for vformat(). - * - * @param file To be passed on to format(). - * @param line To be passed on to format(). - * @param ... Passed to vformat() (sprintf() like). - * @return Instance of T. - */ -template -T formatted( - const char* const file, - unsigned short line, - ...) throw(); - -/** - * Instanciates T with properly formatted message and - * a previous exception. - * - * @see formatted() - */ -template -T formatted( - const Exception& previous, - const char* const file, - unsigned short line, - ...) throw(); - -} // End of namespace. - -#include "utility.ixx" - -#endif +#ifndef LIBSEX_UTILITY_HXX +#define LIBSEX_UTILITY_HXX + +#include + +#include // variadic argument fun +#include // size_t + +namespace libsex +{ + /** + * Formats a message and writes it into @a buffer. + * + * It is guaranteed that not more than @a length + * characters are written to @a buffer. + * + * @param buffer String to be filled. + * @param length Size of buffer. + * @param file Filename in which the error occured. + * @param line Line number in which the error occured. + * @param message printf formatstring template + * @param ap variadic argument list, holds parameters + * to be used when formatting (vsnprintf()). + * @return true if buffer was large enough, false otherwise + */ + bool vformat( + char* const buffer, + size_t length, + const char* const file, + unsigned short line, + const char* const message, + va_list ap) throw(); + + /// @see vformat() + bool format( + char* const buffer, + size_t length, + const char* const file, + unsigned short line, + const char* const message, + ...) throw(); + + /** + * Instanciates T with properly formatted message. + * + * T is supposed to have a static const char* TEMPLATE + * field, which will be used as formatstring for vformat(). + * + * @param file To be passed on to format(). + * @param line To be passed on to format(). + * @param ... Passed to vformat() (sprintf() like). + * @return Instance of T. + */ + template + T formatted( + const char* const file, + unsigned short line, + ...) throw(); + + /** + * Instanciates T with properly formatted message and + * a previous exception. + * + * @see formatted() + */ + template + T formatted( + const Exception& previous, + const char* const file, + unsigned short line, + ...) throw(); +} + +#include "utility.ixx" + +#endif diff --git a/source/utility.ixx b/source/utility.ixx index 5dc8a22..d53b5cf 100644 --- a/source/utility.ixx +++ b/source/utility.ixx @@ -1,9 +1,7 @@ #include // Exception::LENGTH -namespace libsex { - template -T formatted( +T libsex::formatted( const char* const file, unsigned short line, ...) throw() @@ -25,7 +23,7 @@ T formatted( } template -T formatted( +T libsex::formatted( const Exception& previous, const char* const file, unsigned short line, @@ -42,5 +40,3 @@ T formatted( return T(buf, previous); } - -} // End of namespace. -- 2.11.4.GIT