1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
/* 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 <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// 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<Error> 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 T> class ErrorHandle {
public:
static ErrorHandle<T> None() {
return ErrorHandle();
}
ErrorHandle() {}
ErrorHandle(T *err) : _error(err) {
}
ErrorHandle(std::shared_ptr<T> 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<T> _error;
};
// Basic error handle, containing Error object
typedef ErrorHandle<Error> 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 <typename CodeType, String(*GetErrorText)(CodeType)>
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
|