Merge utils/exceptions into single file

Summary: Update documentation of `utils/exceptions.hpp`

Reviewers: mislav.bradac, florijan, buda

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D300
This commit is contained in:
Teon Banek 2017-04-19 15:52:20 +02:00
parent e5cc3f1561
commit 893df584f6
34 changed files with 302 additions and 225 deletions

View File

@ -6,6 +6,7 @@
#include "communication/bolt/v1/state.hpp"
#include "logging/default.hpp"
#include "query/exceptions.hpp"
#include "utils/exceptions.hpp"
namespace communication::bolt {
@ -91,7 +92,7 @@ State StateExecutorRun(Session &session) {
return State::Executor;
}
} catch (const BasicException &e) {
} catch (const utils::BasicException &e) {
// clear header success message
session.encoder_buffer_.Clear();
db_accessor->abort();
@ -104,7 +105,7 @@ State StateExecutorRun(Session &session) {
}
return State::Error;
} catch (const StacktraceException &e) {
} catch (const utils::StacktraceException &e) {
// clear header success message
session.encoder_buffer_.Clear();
db_accessor->abort();

View File

@ -8,7 +8,7 @@ namespace fs = std::experimental::filesystem;
#include "logging/streams/stdout.hpp"
#include "query/preprocessor.hpp"
#include "utils/command_line/arguments.hpp"
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions.hpp"
#include "utils/file.hpp"
#include "utils/string.hpp"
@ -43,7 +43,7 @@ std::string ExtractQuery(const fs::path &path) {
return query;
}
throw BasicException("Unable to find query!");
throw utils::BasicException("Unable to find query!");
}
int main(int argc, char **argv) {

View File

@ -5,13 +5,13 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
/**
* Thrown when something (Edge or a Vertex) can not
* be created. Typically due to database overload.
*/
class CreationException : public StacktraceException {
class CreationException : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};

View File

@ -5,13 +5,14 @@
#include "io/network/socket.hpp"
#include "logging/default.hpp"
#include "utils/exceptions.hpp"
#include "utils/likely.hpp"
namespace io::network {
class EpollError : StacktraceException {
class EpollError : utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
/**

View File

@ -1,15 +1,15 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions.hpp"
#include <netinet/in.h>
#include <string>
namespace io::network {
class NetworkEndpointException : public BasicException {
class NetworkEndpointException : public utils::BasicException {
public:
using BasicException::BasicException;
using utils::BasicException::BasicException;
};
/**

View File

@ -1,13 +1,11 @@
#pragma once
#include <stdexcept>
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
namespace io::network {
class NetworkError : public StacktraceException {
class NetworkError : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
}

View File

@ -13,7 +13,7 @@
#include "query/interpreter.hpp"
#include "query/typed_value.hpp"
#include "utils/algorithm.hpp"
#include "utils/exceptions/not_yet_implemented.hpp"
#include "utils/exceptions.hpp"
#ifdef HAS_READLINE
@ -153,7 +153,7 @@ void query::Repl(Dbms &dbms) {
std::cout << "RUNTIME EXCEPTION: " << e.what() << std::endl;
} catch (const query::TypedValueException &e) {
std::cout << "TYPED VALUE EXCEPTION: " << e.what() << std::endl;
} catch (const NotYetImplemented &e) {
} catch (const utils::NotYetImplemented &e) {
std::cout << e.what() << std::endl;
}
}

View File

@ -29,7 +29,7 @@ namespace fs = std::experimental::filesystem;
template <typename Stream>
class QueryEngine : public Loggable {
private:
using QueryPlanLib = DynamicLib<QueryPlanTrait<Stream>>;
using QueryPlanLib = utils::DynamicLib<QueryPlanTrait<Stream>>;
public:
QueryEngine() : Loggable("QueryEngine") {}

View File

@ -1,7 +1,6 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
#include <fmt/format.h>
@ -9,8 +8,8 @@ namespace query {
/** @brief Base class of all query language related exceptions.
*/
class QueryException : public BasicException {
using BasicException::BasicException;
class QueryException : public utils::BasicException {
using utils::BasicException::BasicException;
};
class SyntaxException : public QueryException {
@ -65,19 +64,19 @@ class QueryRuntimeException : public QueryException {
};
// TODO: Move this elsewhere, it has no place in query.
class DecoderException : public StacktraceException {
class DecoderException : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
class PlanCompilationException : public StacktraceException {
class PlanCompilationException : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
class PlanExecutionException : public StacktraceException {
class PlanExecutionException : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
} // namespace query

View File

@ -13,6 +13,7 @@
#include "query/exceptions.hpp"
#include "query/interpret/awesome_memgraph_functions.hpp"
#include "utils/assert.hpp"
#include "utils/exceptions.hpp"
namespace query {
namespace frontend {
@ -117,7 +118,7 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
return static_cast<Clause *>(ctx->with()->accept(this).as<With *>());
}
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
return 0;
}
@ -126,7 +127,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherMatch(
auto *match = storage_.Create<Match>();
if (ctx->OPTIONAL()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
if (ctx->where()) {
match->where_ = ctx->where()->accept(this);
@ -147,7 +148,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherReturn(
auto *return_clause = storage_.Create<Return>();
if (ctx->DISTINCT()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return_clause->body_.named_expressions =
ctx->returnBody()->accept(this).as<std::vector<NamedExpression *>>();
@ -158,7 +159,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnBody(
CypherParser::ReturnBodyContext *ctx) {
if (ctx->order() || ctx->skip() || ctx->limit()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return ctx->returnItems()->accept(this);
}
@ -167,7 +168,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnItems(
CypherParser::ReturnItemsContext *ctx) {
if (ctx->getTokens(kReturnAllTokenId).size()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
std::vector<NamedExpression *> named_expressions;
for (auto *item : ctx->returnItem()) {
@ -230,7 +231,7 @@ antlrcpp::Any CypherMainVisitor::visitProperties(
// better logical plan if we have an information about properties at
// compile time.
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return ctx->mapLiteral()->accept(this);
}
@ -257,7 +258,7 @@ antlrcpp::Any CypherMainVisitor::visitSymbolicName(
// because we would have t ofigure out how escaping works since same
// variable can be referenced in two ways: escaped and unescaped.
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
// TODO: We should probably escape string.
return std::string(ctx->getText());
@ -333,7 +334,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
}
if (ctx->relationshipDetail()->rangeLiteral()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
}
// relationship.has_range = true;
@ -521,7 +522,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression5(
if (ctx->expression4().size() > 1u) {
// TODO: implement power operator. In neo4j power is left associative and
// int^int -> float.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return visitChildren(ctx);
}
@ -555,7 +556,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression3(
storage_.Create<IsNullOperator>(expression)));
}
if (ctx->children.size() > 1U) {
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return static_cast<Expression *>(visitChildren(ctx));
}
@ -565,7 +566,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression2(
if (ctx->nodeLabels().size()) {
// TODO: Implement this. We don't currently support label checking in
// expresssion.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
Expression *expression = ctx->atom()->accept(this);
for (auto *lookup : ctx->propertyLookup()) {
@ -581,7 +582,7 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
return static_cast<Expression *>(visitChildren(ctx).as<Literal *>());
} else if (ctx->parameter()) {
// TODO: implement other clauses.
throw NotYetImplemented();
throw utils::NotYetImplemented();
} else if (ctx->parenthesizedExpression()) {
return static_cast<Expression *>(
ctx->parenthesizedExpression()->accept(this));
@ -594,7 +595,7 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
}
// TODO: Implement this. We don't support comprehensions, functions,
// filtering... at the moment.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
antlrcpp::Any CypherMainVisitor::visitLiteral(
@ -612,7 +613,7 @@ antlrcpp::Any CypherMainVisitor::visitLiteral(
ctx->numberLiteral()->accept(this).as<TypedValue>());
} else {
// TODO: Implement map and list literals.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
return visitChildren(ctx);
}
@ -639,7 +640,7 @@ antlrcpp::Any CypherMainVisitor::visitNumberLiteral(
antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(
CypherParser::FunctionInvocationContext *ctx) {
if (ctx->DISTINCT()) {
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
std::string function_name = ctx->functionName()->accept(this);
std::vector<Expression *> expressions;
@ -908,7 +909,7 @@ antlrcpp::Any CypherMainVisitor::visitWith(CypherParser::WithContext *ctx) {
auto *with = storage_.Create<With>();
if (ctx->DISTINCT()) {
// TODO: implement this
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
with->body_.named_expressions =
ctx->returnBody()->accept(this).as<std::vector<NamedExpression *>>();

View File

@ -9,7 +9,7 @@
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/ast/named_antlr_tokens.hpp"
#include "query/frontend/opencypher/generated/CypherBaseVisitor.h"
#include "utils/exceptions/not_yet_implemented.hpp"
#include "utils/exceptions.hpp"
namespace query {
namespace frontend {
@ -55,7 +55,7 @@ class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
case kGeTokenId:
return storage_.Create<GreaterEqualOperator>(e1, e2);
default:
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
}
@ -68,7 +68,7 @@ class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
case kUnaryMinusTokenId:
return storage_.Create<UnaryMinusOperator>(e);
default:
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
}

View File

@ -8,7 +8,7 @@
#include "query/interpret/frame.hpp"
#include "query/typed_value.hpp"
#include "utils/assert.hpp"
#include "utils/exceptions/not_yet_implemented.hpp"
#include "utils/exceptions.hpp"
namespace query {
@ -117,7 +117,7 @@ class ExpressionEvaluator : public TreeVisitorBase {
}
case TypedValue::Type::Map:
// TODO implement me
throw NotYetImplemented();
throw utils::NotYetImplemented();
break;
default:

View File

@ -917,7 +917,7 @@ void ReconstructTypedValue(TypedValue &value) {
break;
case TypedValue::Type::Path:
// TODO implement path reconstruct?
throw NotYetImplemented("Path reconstruction not yet supported");
throw utils::NotYetImplemented("Path reconstruction not yet supported");
default:
break;
}

View File

@ -7,7 +7,6 @@
#include <query/exceptions.hpp>
#include <tuple>
#include <unordered_map>
#include <utils/exceptions/not_yet_implemented.hpp>
#include <vector>
#include "database/graph_db_accessor.hpp"

View File

@ -4,7 +4,7 @@
#include <unordered_set>
#include "query/frontend/ast/ast.hpp"
#include "utils/exceptions/not_yet_implemented.hpp"
#include "utils/exceptions.hpp"
namespace query {
namespace plan {
@ -309,7 +309,7 @@ auto GenWith(With &with, LogicalOperator *input_op,
// optional Filter.
if (with.body_.distinct) {
// TODO: Plan distinct with, when operator available.
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
// In case of update and aggregation, we want to accumulate first, so that
// when aggregating, we get the latest results. Similar to RETURN clause.
@ -407,7 +407,7 @@ std::unique_ptr<LogicalOperator> MakeLogicalPlan(
is_write = true;
input_op = op;
} else {
throw NotYetImplemented();
throw utils::NotYetImplemented();
}
}
return std::unique_ptr<LogicalOperator>(input_op);

View File

@ -6,7 +6,7 @@
#include <memory>
#include "utils/assert.hpp"
#include "utils/exceptions/not_yet_implemented.hpp"
#include "utils/exceptions.hpp"
#include "utils/hashing/fnv.hpp"
namespace query {
@ -505,7 +505,7 @@ TypedValue operator==(const TypedValue &a, const TypedValue &b) {
return true;
}
case TypedValue::Type::Path:
throw NotYetImplemented();
throw utils::NotYetImplemented();
default:
permanent_fail("Unhandled comparison for types");
}
@ -784,7 +784,7 @@ size_t TypedValue::Hash::operator()(const TypedValue &value) const {
case TypedValue::Type::Edge:
return value.Value<EdgeAccessor>().temporary_id();
case TypedValue::Type::Path:
throw NotYetImplemented();
throw utils::NotYetImplemented();
break;
}
permanent_fail("Unhandled TypedValue.type() in hash function");

View File

@ -12,7 +12,7 @@
#include "storage/property_value.hpp"
#include "storage/vertex_accessor.hpp"
#include "traversal/path.hpp"
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions.hpp"
#include "utils/total_ordering.hpp"
namespace query {
@ -171,9 +171,9 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
* trying to perform operations (such as addition) on TypedValues
* of incompatible Types.
*/
class TypedValueException : public BasicException {
class TypedValueException : public utils::BasicException {
public:
using ::BasicException::BasicException;
using utils::BasicException::BasicException;
};
// comparison operators

View File

@ -6,7 +6,7 @@
#include <string>
#include <vector>
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
#include "utils/total_ordering.hpp"
/**
@ -90,9 +90,9 @@ class PropertyValue {
* trying to perform operations (such as addition) on PropertyValues
* of incompatible Types.
*/
class PropertyValueException : public StacktraceException {
class PropertyValueException : public utils::StacktraceException {
public:
using ::StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};
// stream output

View File

@ -1,8 +1,8 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions.hpp"
class LockTimeoutException : public BasicException {
class LockTimeoutException : public utils::BasicException {
public:
using BasicException::BasicException;
using utils::BasicException::BasicException;
};

View File

@ -9,7 +9,7 @@
#include <string>
#include <vector>
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
#include "utils/option.hpp"
#define REGISTER_ARGS(argc, argv) \
@ -29,10 +29,10 @@ namespace {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
class ProgramArgumentException : public StacktraceException {
class ProgramArgumentException : public utils::StacktraceException {
public:
ProgramArgumentException(const std::string &mess)
: StacktraceException("ProgramArgumentException: " + mess + ".") {}
: utils::StacktraceException("ProgramArgumentException: " + mess + ".") {}
};
class ProgramArguments {

View File

@ -1,6 +1,6 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/datetime/datetime_error.hpp"
class Datetime {
public:

View File

@ -1,8 +1,8 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
class DatetimeError : public StacktraceException {
class DatetimeError : public utils::StacktraceException {
public:
using StacktraceException::StacktraceException;
using utils::StacktraceException::StacktraceException;
};

View File

@ -4,11 +4,21 @@
#include <experimental/filesystem>
#include <stdexcept>
#include <string>
#include "utils/exceptions/dynamic_lib_exception.hpp"
#include "utils/exceptions.hpp"
namespace fs = std::experimental::filesystem;
#include "logging/loggable.hpp"
namespace utils {
/**
* @brief Exception raised by @c DynamicLib.
*/
class DynamicLibException : public utils::BasicException {
public:
using utils::BasicException::BasicException;
};
/**
* DynamicLib is a wrapper aroung dynamic object returned by dlopen.
*
@ -116,3 +126,5 @@ class DynamicLib : public Loggable {
typename T::ProducePrototype produce_method;
typename T::DestructPrototype destruct_method;
};
} // namespace utils

195
src/utils/exceptions.hpp Normal file
View File

@ -0,0 +1,195 @@
/**
* @file
* @brief This file stores the common exceptions used across the project.
*/
#pragma once
#include <exception>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include "utils/stacktrace/stacktrace.hpp"
namespace utils {
/**
* @brief Base class for all regular exceptions.
*
* All custom exceptions should inherit from this class. It stores the message
* with which it was constructed. To retrieve the message, use
* @c BasicException::what method. In case you need to store a stack trace, you
* should use @c StacktraceException
*
* @sa StacktraceException
* @sa NotYetImplemented
*/
class BasicException : public std::exception {
public:
/**
* @brief Constructor (C strings).
*
* @param message C-style string error message.
* The string contents are copied upon construction.
* Hence, responsibility for deleting the `char*` lies
* with the caller.
*/
explicit BasicException(const char *message) noexcept : msg_(message) {}
/**
* @brief Constructor (C++ STL strings).
*
* @param message The error message.
*/
explicit BasicException(const std::string &message) noexcept : msg_(message) {
}
/**
* @brief Constructor with format string (C++ STL strings).
*
* @param format The error format message.
* @param args Arguments for format string.
*/
template <class... Args>
explicit BasicException(const std::string &format, Args &&... args) noexcept
: BasicException(fmt::format(format, std::forward<Args>(args)...)) {}
/**
* @brief Constructor with format string (C strings).
*
* @param format The error format message. The string contents are copied upon
* construction. Hence, the responsibility for deleting `char*` lies with the
* caller.
* @param args Arguments for format string.
*/
template <class... Args>
explicit BasicException(const char *format, Args &&... args) noexcept
: BasicException(fmt::format(std::string(format),
std::forward<Args>(args)...)) {}
/**
* @brief Virtual destructor to allow for subclassing.
*/
virtual ~BasicException() {}
/**
* @brief Returns a pointer to the (constant) error description.
*
* @return A pointer to a `const char*`. The underlying memory
* is in possession of the @c BasicException object. Callers must
* not attempt to free the memory.
*/
const char *what() const noexcept override { return msg_.c_str(); }
protected:
/**
* @brief Error message.
*/
std::string msg_;
};
/**
* @brief Base class for all exceptions which need to store the stack trace.
*
* When you need to store the stack trace from the place this exception is
* created, you should use this class. The error message can be obtained using
* @c StacktraceException::what method, while the stack trace itself can be
* obtained via @c StacktraceException::trace method. If the stack trace is not
* needed, you should use @c BasicException.
*
* @sa BasicException
* @sa NotYetImplemented
*/
class StacktraceException : public std::exception {
public:
/**
* @brief Constructor (C strings).
*
* @param message C-style string error message.
* The string contents are copied upon construction.
* Hence, responsibility for deleting the `char*` lies
* with the caller.
*/
explicit StacktraceException(const char *message) noexcept
: message_(message) {
Stacktrace stacktrace;
stacktrace_ = stacktrace.dump();
}
/**
* @brief Constructor (C++ STL strings).
*
* @param message The error message.
*/
explicit StacktraceException(const std::string &message) noexcept
: message_(message) {
Stacktrace stacktrace;
stacktrace_ = stacktrace.dump();
}
/**
* @brief Constructor with format string (C++ STL strings).
*
* @param format The error format message.
* @param args Arguments for format string.
*/
template <class... Args>
explicit StacktraceException(const std::string &format,
Args &&... args) noexcept
: StacktraceException(fmt::format(format, std::forward<Args>(args)...)) {}
/**
* @brief Constructor with format string (C strings).
*
* @param format The error format message. The string contents are copied upon
* construction. Hence, the responsibility for deleting `char*` lies with the
* caller.
* @param args Arguments for format string.
*/
template <class... Args>
explicit StacktraceException(const char *format, Args &&... args) noexcept
: StacktraceException(fmt::format(std::string(format),
std::forward<Args>(args)...)) {}
/**
* @brief Virtual destructor to allow for subclassing.
*/
virtual ~StacktraceException() {}
/**
* @brief Returns a pointer to the (constant) error description.
*
* @return A pointer to a `const char*`. The underlying memory
* is in possession of the @c StacktraceException object. Callers must
* not attempt to free the memory.
*/
const char *what() const noexcept override { return message_.c_str(); }
/**
* @brief Returns a pointer to the (constant) stack trace message.
*
* @return A pointer to a `const char*`. The underlying memory
* is in possession of the @c StacktraceException object. Callers must
* not attempt to free the memory.
*/
const char *trace() const noexcept { return stacktrace_.c_str(); }
private:
std::string message_;
std::string stacktrace_;
};
/**
* @brief Raise this exception for functionality which is yet to be implemented.
*/
class NotYetImplemented final : public StacktraceException {
public:
using StacktraceException::StacktraceException;
/**
* @brief Construct with the default "Not yet implemented!" message.
*/
NotYetImplemented() noexcept : StacktraceException("Not yet implemented!") {}
};
} // namespace utils

View File

@ -1,72 +0,0 @@
//
// Created by buda on 18/02/17.
//
#pragma once
#include <fmt/format.h>
#include <stdexcept>
/**
* @brief BasicException
*
* Just a wrapper around std::exception.
*/
class BasicException : public std::exception {
public:
/** Constructor (C strings).
*
* @param message C-style string error message.
* The string contents are copied upon construction.
* Hence, responsibility for deleting the char* lies
* with the caller.
*/
explicit BasicException(const char *message) : msg_(message) {}
/**
* Constructor (C++ STL strings).
*
* @param message The error message.
*/
explicit BasicException(const std::string &message) : msg_(message) {}
/** Constructor with format string (C++ STL strings).
*
* @param format The error format message.
* @param args Arguments for format string.
*/
template <class... Args>
explicit BasicException(const std::string &format, Args &&... args) noexcept
: BasicException(fmt::format(format, std::forward<Args>(args)...)) {}
/** Constructor with format string (C strings).
*
* @param format The error format message. The string contents are copied upon
* construction. Hence, the responsibility for deleting char* lies with the
* caller.
* @param args Arguments for format string.
*/
template <class... Args>
explicit BasicException(const char *format, Args &&... args) noexcept
: BasicException(fmt::format(std::string(format),
std::forward<Args>(args)...)) {}
/**
* Destructor. Virtual to allow for subclassing.
*/
virtual ~BasicException() {}
/**
* Returns a pointer to the (constant) error description.
*
* @return A pointer to a const char*. The underlying memory
* is in possession of the BasicException object. Callers must
* not attempt to free the memory.
*/
const char *what() const noexcept override { return msg_.c_str(); }
protected:
/**
* Error message.
*/
std::string msg_;
};

View File

@ -1,9 +0,0 @@
#pragma once
#include <dlfcn.h>
#include "utils/exceptions/basic_exception.hpp"
class DynamicLibException : public BasicException {
public:
using BasicException::BasicException;
};

View File

@ -1,8 +0,0 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
class NonExhaustiveSwitch : public StacktraceException {
public:
using StacktraceException::StacktraceException;
};

View File

@ -1,10 +0,0 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
class NotYetImplemented : public StacktraceException {
public:
using StacktraceException::StacktraceException;
NotYetImplemented() : StacktraceException("Not yet implemented!") {}
};

View File

@ -1,8 +0,0 @@
#pragma once
#include "utils/exceptions/stacktrace_exception.hpp"
class OutOfMemory : public StacktraceException {
public:
using StacktraceException::StacktraceException;
};

View File

@ -1,33 +0,0 @@
#pragma once
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <stdexcept>
#include "utils/auto_scope.hpp"
#include "utils/stacktrace/stacktrace.hpp"
class StacktraceException : public std::exception {
public:
StacktraceException(const std::string &message) noexcept : message_(message) {
Stacktrace stacktrace;
stacktrace_ = stacktrace.dump();
}
template <class... Args>
StacktraceException(const std::string &format, Args &&... args) noexcept
: StacktraceException(fmt::format(format, std::forward<Args>(args)...)) {}
template <class... Args>
StacktraceException(const char *format, Args &&... args) noexcept
: StacktraceException(fmt::format(std::string(format),
std::forward<Args>(args)...)) {}
const char *what() const noexcept override { return message_.c_str(); }
const char *trace() const noexcept { return stacktrace_.c_str(); }
private:
std::string message_;
std::string stacktrace_;
};

View File

@ -24,7 +24,7 @@ namespace fs = std::experimental::filesystem;
#include "logging/loggable.hpp"
#include "utils/algorithm.hpp"
#include "utils/assert.hpp"
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions.hpp"
#include "utils/likely.hpp"
#include "utils/underlying_cast.hpp"

View File

@ -2,12 +2,22 @@
#include <cmath>
#include "utils/exceptions/out_of_memory.hpp"
#include "utils/exceptions.hpp"
#include "utils/likely.hpp"
#include "utils/memory/block_allocator.hpp"
// http://en.cppreference.com/w/cpp/language/new
namespace utils {
///
/// @brief Raised by @c StackAllocator when it cannot allocate the object.
///
class OutOfMemory : public StacktraceException {
public:
using StacktraceException::StacktraceException;
};
// Useful for allocating memory which can be freed with one call.
// Most performant for data which need to be present to the end.
class StackAllocator {
@ -107,3 +117,5 @@ class StackAllocator {
char *head = {nullptr};
char *end = {nullptr};
};
} // namespace utils

View File

@ -1,16 +1,15 @@
#include "gtest/gtest.h"
#include "utils/exceptions/basic_exception.hpp"
#include "utils/exceptions/stacktrace_exception.hpp"
#include "utils/exceptions.hpp"
void i_will_throw() { throw BasicException("this is not ok"); }
void i_will_throw() { throw utils::BasicException("this is not ok"); }
void bar() { i_will_throw(); }
void foo() { bar(); }
void i_will_throw_stacktrace_exception() {
throw StacktraceException("this is not {}", "ok!");
throw utils::StacktraceException("this is not {}", "ok!");
}
void bar_stacktrace() { i_will_throw_stacktrace_exception(); }
@ -18,8 +17,8 @@ void bar_stacktrace() { i_will_throw_stacktrace_exception(); }
void foo_stacktrace() { bar_stacktrace(); }
TEST(ExceptionsTest, ThrowBasicAndStackExceptions) {
ASSERT_THROW(foo(), BasicException);
ASSERT_THROW(foo_stacktrace(), StacktraceException);
ASSERT_THROW(foo(), utils::BasicException);
ASSERT_THROW(foo_stacktrace(), utils::StacktraceException);
}
int main(int argc, char **argv) {

View File

@ -10,7 +10,7 @@ struct Object {
};
TEST(StackAllocatorTest, AllocationAndObjectValidity) {
StackAllocator allocator;
utils::StackAllocator allocator;
for (int i = 0; i < 64 * 1024; ++i) {
auto object = allocator.make<Object>(1, 2);
ASSERT_EQ(object->a, 1);