blob: 79fbeaf304a4642be794edf315983ef625caaee6 [file] [log] [blame]
// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_EXCEPTION_H_
#define CHROMEOS_EXCEPTION_H_
#include <base/logging.h>
#include <algorithm>
#include <exception>
#include <string>
#include <typeinfo>
/******************************************************************************/
namespace chromeos {
using std::swap;
/******************************************************************************/
// \brief AnyException is a runtime polymophic type which can hold any
// std::exception derived exception.
//
// AnyException supports a safe bool cast, return true iff it contains an
// exception (a default constructed AnyException contains no exception.
//
// AnyException is useful for error handling which doesn't use try/catch - but
// may be converted to use try/catch in the future. I can also be used to
// marshal an exception across a non exception safe boundary.
//
// \example
// AnyException error;
// int x = SomeFunction(error);
// if (error) return;
//
// // ...
//
// int SomeFunction(AnyException& error) {
// // ...
// if (something_failed) {
// error = std::logic_error("Something Failed.");
// return 0;
// }
// // ...
// \end_example
class AnyException : public std::exception {
public:
AnyException()
: object_(NULL) {
}
template <typename T> // T is derived from std::exception
explicit AnyException(const T& x)
: object_(new Model<T>(x)) {
}
AnyException(const AnyException& x)
: object_(x.object_ ? x.object_->Copy() : NULL) {
}
~AnyException() throw() {
delete object_;
}
AnyException& operator=(AnyException x) {
swap(*this, x);
}
template <typename T> // T is derived from std::exception
AnyException& operator=(const T& x) {
*this = AnyException(x);
}
inline friend void swap(AnyException& x, AnyException& y) {
swap(x.object_, y.object_);
}
const char* what() throw() {
return object_ ? object_->what() : "empty AnyException";
}
operator bool() const {
return object_;
}
private:
operator int() const; // for safe bool cast.
class Concept : public std::exception {
public:
virtual Concept* Copy() const = 0;
};
template <class T> // T is derived from std::exception
class Model : public Concept {
public:
explicit Model(const T& x)
: object_(x) {
}
Concept* Copy() const {
return new Model(object_);
}
const char* what() throw() {
return object_.what();
}
private:
T object_;
};
Concept* object_;
};
/******************************************************************************/
// \brief BadCast is an std::bad_cast which report the \param from and \param to
// name of types for better error reporting.
//
// \note Consider moving bad cast into a typeinfo.h file.
//
// \example
// template <typaname R,
// typename T>
// R Cast(const T& x, AnyException& error) {
// if (!Compatible<T, R>()) {
// error = BadCast(typeid(T).name(), typeid(R).name());
// return R();
// }
// // ...
// \end_example
class BadCast : public std::bad_cast {
public:
BadCast(const char* from, const char* to)
: what_("BadCast from '") {
what_ += from;
what_ += "' to '";
what_ += to;
what_ += "'.";
}
~BadCast() throw() {
}
const char* what() const throw() {
return what_.c_str();
}
private:
std::string what_;
};
/******************************************************************************/
// \brief SquelchError logs a warning noting the x.what().
//
// In a system using exception handling, SquelchError would become a throw.
template <typename T> // T is derived from std::exception
void SquelchError(const T& x) {
LOG(WARNING) << "error squelched:" << x.what();
}
/******************************************************************************/
// \brief TerminalError logs a fatal error causing the process to terminate.
//
// x.what() is noted in the log. In a system using exceptino handling,
// TerminalError would become a throw.
template <typename T> // T is derived from std::exception
void TerminalError(const T& x) {
LOG(FATAL) << "terminal error:" << x.what();
}
/******************************************************************************/
} // namespace chromeos
/******************************************************************************/
#endif // CHROMEOS_EXCEPTION_H_