/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//=============================================================================
//
// Universal error class, that may be used both as a return value or
// thrown as an exception.
//
//=============================================================================
#ifndef AGS_SHARED_UTIL_ERROR_H
#define AGS_SHARED_UTIL_ERROR_H
#include "common/std/memory.h"
#include "ags/shared/util/string.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
class Error;
typedef std::shared_ptr PError;
//
// A simple struct, that provides several fields to describe an error in the program.
// If wanted, may be reworked into subclass of std::exception.
//
class Error {
public:
Error(int code, String general, PError inner_error = PError()) : _code(code), _general(general), _innerError(inner_error) {
}
Error(int code, String general, String comment, PError inner_error = PError()) : _code(code), _general(general), _comment(comment), _innerError(inner_error) {
}
Error(String general, PError inner_error = PError()) : _code(0), _general(general), _innerError(inner_error) {
}
Error(String general, String comment, PError inner_error = PError()) : _code(0), _general(general), _comment(comment), _innerError(inner_error) {
}
// Error code is a number, defining error subtype. It is not much use to the end-user,
// but may be checked in the program to know more precise cause of the error.
int Code() const {
return _code;
}
// General description of this error type and subtype.
String General() const {
return _general;
}
// Any complementary information.
String Comment() const {
return _comment;
}
PError InnerError() const {
return _innerError;
}
// Full error message combines general description and comment.
// NOTE: if made a child of std::exception, FullMessage may be substituted
// or complemented with virtual const char* what().
String FullMessage() const {
String msg;
const Error *err = this;
do {
msg.Append(err->General());
if (!err->Comment().IsEmpty()) {
msg.AppendChar('\n');
msg.Append(err->Comment());
}
err = err->InnerError().get();
if (err)
msg.AppendChar('\n');
} while (err);
return msg;
}
private:
int _code; // numeric code, for specific uses
String _general; // general description of this error class
String _comment; // additional information about particular case
PError _innerError; // previous error that caused this one
};
// ErrorHandle is a helper class that lets you have an Error object
// wrapped in a smart pointer. ErrorHandle's only data member is a
// shared_ptr, which means that it does not cause too much data copying
// when used as a function's return value.
// Note, that the reason to have distinct class instead of a shared_ptr's
// typedef is an inverted boolean comparison:
// shared_ptr converts to 'true' when it contains an object, but ErrorHandle
// returns 'true' when it *does NOT* contain an object, meaning there
// is no error.
template class ErrorHandle {
public:
static ErrorHandle None() {
return ErrorHandle();
}
ErrorHandle() {}
ErrorHandle(T *err) : _error(err) {
}
ErrorHandle(std::shared_ptr err) : _error(err) {
}
bool HasError() const {
return _error.get() != NULL;
}
explicit operator bool() const {
return _error.get() == nullptr;
}
operator PError() const {
return _error;
}
T *operator ->() const {
return _error.operator->();
}
T &operator *() const {
return _error.operator * ();
}
private:
std::shared_ptr _error;
};
// Basic error handle, containing Error object
typedef ErrorHandle HError;
// TypedCodeError is the Error's subclass, which only purpose is to override
// error code type in constructor and Code() getter, that may be useful if
// you'd like to restrict code values to particular enumerator.
// TODO: a type identifier as a part of template (string, or perhaps a int16
// to be placed at high-bytes in Code) to be able to distinguish error group.
template
class TypedCodeError : public Error {
public:
TypedCodeError(CodeType code, PError inner_error = PError()) : Error(code, GetErrorText(code), inner_error) {
}
TypedCodeError(CodeType code, String comment, PError inner_error = PError()) :
Error(code, GetErrorText(code), comment, inner_error) {
}
CodeType Code() const {
return (CodeType)Error::Code();
}
};
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif