Add exception.h declaring some base exception classes. For the sake of experimenting and showing the concept, change one (probably never thrown) exception to use the new style exceptions.

No new source files to compile, just a new header.

Originally committed to SVN as r3190.
This commit is contained in:
Niels Martin Hansen 2009-07-22 00:10:36 +00:00
parent 8d5bae9558
commit ff8c8e1817
5 changed files with 140 additions and 4 deletions

View File

@ -1819,6 +1819,10 @@
RelativePath="..\..\src\include\aegisub\audio_provider.h"
>
</File>
<File
RelativePath="..\..\src\include\aegisub\exception.h"
>
</File>
<File
RelativePath="..\..\src\include\aegisub\spellchecker.h"
>

View File

@ -726,7 +726,7 @@ void AssDialogue::SetMarginString(const wxString origvalue,int which) {
if (value > 9999) value = 9999;
// Assign
if (which < 0 || which >= 4) throw _T("Invalid margin id");
if (which < 0 || which >= 4) throw new Aegisub::InvalidMarginIdError;
Margin[which] = value;
}
@ -734,7 +734,7 @@ void AssDialogue::SetMarginString(const wxString origvalue,int which) {
//////////////////////////
// Gets string for margin
wxString AssDialogue::GetMarginString(int which,bool pad) {
if (which < 0 || which >= 4) throw _T("Invalid margin id");
if (which < 0 || which >= 4) throw new Aegisub::InvalidMarginIdError;
int value = Margin[which];
if (pad) return wxString::Format(_T("%04i"),value);
else return wxString::Format(_T("%i"),value);

View File

@ -41,6 +41,7 @@
// Headers
#include <wx/wxprec.h>
#include <wx/string.h>
#include "include/aegisub/exception.h"
//////////////
@ -60,6 +61,17 @@ enum ASS_EntryType {
};
namespace Aegisub {
// Thrown when someone supplies an invalid margin ID to a function expecting one
// (Usually limited to range 0..3.)
class InvalidMarginIdError : public InternalError {
public:
InvalidMarginIdError() : InternalError(_T("Invalid margin id"), 0) { }
const wxChar *GetName() { return _T("internal_error/invalid_margin_id"); }
};
};
////////////////////////////////////
// Base class for each line in file
class AssEntry {

View File

@ -439,7 +439,7 @@ void AssStyle::UpdateData() {
/////////////////////////////
// Sets margin from a string
void AssStyle::SetMarginString(const wxString str,int which) {
if (which < 0 || which >= 4) throw _T("Invalid margin id");
if (which < 0 || which >= 4) throw new Aegisub::InvalidMarginIdError;
if (!str.IsNumber()) throw _T("Invalid margin value");
long value;
str.ToLong(&value);
@ -453,7 +453,7 @@ void AssStyle::SetMarginString(const wxString str,int which) {
//////////////////////////
// Gets string for margin
wxString AssStyle::GetMarginString(int which) {
if (which < 0 || which >= 4) throw _T("Invalid margin id");
if (which < 0 || which >= 4) throw new Aegisub::InvalidMarginIdError;
wxString result = wxString::Format(_T("%04i"),Margin[which]);
return result;
}

View File

@ -0,0 +1,120 @@
// Copyright (c) 2009, Niels Martin Hansen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <wx/string.h>
namespace Aegisub {
// Base class for exceptions
// No public creators, all exceptions throws must be specific
class Exception {
Exception *inner;
wxString message;
protected:
Exception(const wxString &msg, Exception *inr = 0) : message(msg), inner(inr) { }
Exception(); // not implemented, not wanted
virtual ~Exception() { if (inner) delete inner; }
public:
// Error message for outer exception
virtual wxString GetMessage() const { return message; }
// Error message for outer exception, and chained message for inner exception
wxString GetChainedMessage() const { if (inner) return inner->GetChainedMessage() + _T("\r\n") + GetMessage(); else return GetMessage(); }
// Name of exception class, should only be implemented by specific classes
virtual const wxChar * GetName() const = 0;
operator const wxChar * () { return GetMessage().c_str(); }
operator wxString () { return GetMessage(); }
};
// Macro to quickly add location information to an error message
#define AG_WHERE _T(" (at ") _T(__FILE__) _T(":") _T(#__LINE__) _T(")")
// Macros to define basic exception classes that do nothing fancy
// These should always be used inside the Aegisub namespace
#define DEFINE_SIMPLE_EXCEPTION_NOINNER(classname,baseclass,displayname) \
class classname : public baseclass { \
public: \
classname(const wxString &msg) : baseclass(msg) { } \
const wxChar * GetName() const { return _T(displayname); } \
};
#define DEFINE_SIMPLE_EXCEPTION(classname,baseclass,displayname) \
class classname : public baseclass { \
public: \
classname(const wxString &msg, Exception *inner) : baseclass(msg, inner) { } \
const wxChar * GetName() const { return _T(displayname); } \
};
#define DEFINE_BASE_EXCEPTION_NOINNER(classname,baseclass) \
class classname : public baseclass { \
public: \
classname(const wxString &msg) : baseclass(msg) { } \
};
#define DEFINE_BASE_EXCEPTION(classname,baseclass) \
class classname : public baseclass { \
public: \
classname(const wxString &msg, Exception *inner) : baseclass(msg, inner) { } \
};
// Exception for "user cancel" events
// I.e. when we want to abort an operation because the user requested that we do so
// Not actually an error and should not be handled as such
DEFINE_SIMPLE_EXCEPTION_NOINNER(UserCancelException,Exception,"nonerror/user_cancel")
// Errors that should never happen and point to some invalid assumption in the code
DEFINE_SIMPLE_EXCEPTION(InternalError, Exception, "internal_error")
// Some error related to the filesystem
// These should always be original causes and as such do not support inner exceptions
DEFINE_BASE_EXCEPTION_NOINNER(FileSystemError,Exception)
// A file can't be accessed for some reason
DEFINE_SIMPLE_EXCEPTION_NOINNER(FileNotAccessibleError,FileSystemError,"filesystem/not_accessible")
// A file isn't accessible because it doesn't exist
class FileNotFoundError : public FileNotAccessibleError {
public:
FileNotFoundError(const wxString &filename) : FileNotAccessibleError(wxString(_T("File not found: ")) + filename) { }
const wxChar * GetName() const { return _T("filesystem/not_accessible/not_found"); }
};
// A problem with some input data
DEFINE_BASE_EXCEPTION(InvalidInputException,Exception)
// There is no "generic exception" class, everything must be a specific one
// Define new classes if none fit the error you're reporting
};