Generalized class Error, added class WError for use with Unicode-Paths.
This commit is contained in:
parent
dab01e73e9
commit
49e040ee8d
@ -70,6 +70,7 @@ BINSRC = addmoddel.cpp \
|
||||
prevtest.cpp \
|
||||
stringto-test.cpp \
|
||||
tiff-test.cpp \
|
||||
werror-test.cpp \
|
||||
write-test.cpp \
|
||||
write2-test.cpp \
|
||||
xmpparse.cpp \
|
||||
|
||||
25
samples/werror-test.cpp
Normal file
25
samples/werror-test.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
// werror-test.cpp, $Rev$
|
||||
// Simple tests for the wide-string error class WError
|
||||
|
||||
#include <iostream>
|
||||
#include <exiv2/error.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
throw Exiv2::Error(-1, "ARG1", "ARG2", "ARG3");
|
||||
}
|
||||
catch (const Exiv2::Error& e) {
|
||||
std::cout << "Caught Error '" << e.what() << "'\n";
|
||||
}
|
||||
|
||||
try {
|
||||
throw Exiv2::WError(-1, L"WARG1", L"WARG2", L"WARG3");
|
||||
}
|
||||
catch (const Exiv2::WError& e) {
|
||||
std::wcout << "Caught WError '" << e.wwhat() << "'\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -502,10 +502,10 @@ namespace Exiv2 {
|
||||
#ifdef EXV_UNICODE_PATH
|
||||
if (p_->wpMode_ == Impl::wpUnicode) {
|
||||
if (fileExists(wpf) && ::_wremove(wpf) != 0) {
|
||||
throw Error(2, wpf, strError(), "::_wremove");
|
||||
throw WError(2, wpf, strError(), "::_wremove");
|
||||
}
|
||||
if (::_wrename(fileIo->wpath().c_str(), wpf) == -1) {
|
||||
throw Error(17, ws2s(fileIo->wpath()), wpf, strError());
|
||||
throw WError(17, fileIo->wpath(), wpf, strError());
|
||||
}
|
||||
::_wremove(fileIo->wpath().c_str());
|
||||
// Check permissions of new file
|
||||
@ -513,14 +513,14 @@ namespace Exiv2 {
|
||||
if (statOk && ::_wstat(wpf, &buf2) == -1) {
|
||||
statOk = false;
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Warning: " << Error(2, wpf, strError(), "::_wstat") << "\n";
|
||||
std::cerr << "Warning: " << WError(2, wpf, strError(), "::_wstat") << "\n";
|
||||
#endif
|
||||
}
|
||||
if (statOk && origStMode != buf2.st_mode) {
|
||||
// Set original file permissions
|
||||
if (::_wchmod(wpf, origStMode) == -1) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Warning: " << Error(2, wpf, strError(), "::_wchmod") << "\n";
|
||||
std::cerr << "Warning: " << WError(2, wpf, strError(), "::_wchmod") << "\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -998,16 +998,16 @@ namespace Exiv2 {
|
||||
{
|
||||
FileIo file(wpath);
|
||||
if (file.open("rb") != 0) {
|
||||
throw Error(10, ws2s(wpath), "rb", strError());
|
||||
throw WError(10, wpath, "rb", strError());
|
||||
}
|
||||
struct _stat st;
|
||||
if (0 != ::_wstat(wpath.c_str(), &st)) {
|
||||
throw Error(2, ws2s(wpath), strError(), "::_wstat");
|
||||
throw WError(2, wpath, strError(), "::_wstat");
|
||||
}
|
||||
DataBuf buf(st.st_size);
|
||||
long len = file.read(buf.pData_, buf.size_);
|
||||
if (len != buf.size_) {
|
||||
throw Error(2, ws2s(wpath), strError(), "FileIo::read");
|
||||
throw WError(2, wpath, strError(), "FileIo::read");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@ -1027,7 +1027,7 @@ namespace Exiv2 {
|
||||
{
|
||||
FileIo file(wpath);
|
||||
if (file.open("wb") != 0) {
|
||||
throw Error(10, ws2s(wpath), "wb", strError());
|
||||
throw WError(10, wpath, "wb", strError());
|
||||
}
|
||||
return file.write(buf.pData_, buf.size_);
|
||||
}
|
||||
|
||||
@ -41,12 +41,16 @@ namespace {
|
||||
|
||||
//! Helper structure defining an error message.
|
||||
struct ErrMsg {
|
||||
//! Comparison operator
|
||||
bool operator==(int code) const { return code_ == code; }
|
||||
|
||||
int code_; //!< Error code
|
||||
const char* message_; //!< Error message
|
||||
};
|
||||
|
||||
const ErrMsg errMsg[] = {
|
||||
{ -1, N_("Error %0: arg1=%1, arg2=%2, arg3=%3.") },
|
||||
//! Complete list of Exiv2 exception error messages
|
||||
const ErrMsg errList[] = {
|
||||
{ -1, N_("Error %0: arg2=%2, arg3=%3, arg1=%1.") },
|
||||
{ 0, N_("Success") },
|
||||
{ 1, "%1" }, // %1=error message
|
||||
{ 2, "%1: Call to `%3' failed: %2" }, // %1=path, %2=strerror, %3=function that failed
|
||||
@ -98,9 +102,7 @@ namespace {
|
||||
{ 48, N_("Invalid XmpText type `%1'") }, // %1=type
|
||||
{ 49, N_("TIFF directory %1 has too many entries") }, // %1=TIFF directory name
|
||||
{ 50, N_("Multiple TIFF array element tags %1 in one directory") }, // %1=tag number
|
||||
{ 51, N_("TIFF array element tag %1 has wrong type") }, // %1=tag number
|
||||
// Last error message (message is not used)
|
||||
{ -2, N_("(Unknown Error)") }
|
||||
{ 51, N_("TIFF array element tag %1 has wrong type") } // %1=tag number
|
||||
};
|
||||
|
||||
}
|
||||
@ -113,62 +115,40 @@ namespace Exiv2 {
|
||||
{
|
||||
}
|
||||
|
||||
Error::Error(int code)
|
||||
: code_(code), count_(0)
|
||||
{
|
||||
setMsg();
|
||||
}
|
||||
|
||||
Error::~Error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
int Error::code() const throw()
|
||||
{
|
||||
return code_;
|
||||
}
|
||||
|
||||
const char* Error::what() const throw()
|
||||
//! Specialization for Error
|
||||
template<>
|
||||
const char* BasicError<char>::what() const throw()
|
||||
{
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
int Error::errorIdx(int code)
|
||||
//! Specialization for WError
|
||||
template<>
|
||||
const char* BasicError<wchar_t>::what() const throw()
|
||||
{
|
||||
int idx;
|
||||
for (idx = 0; errMsg[idx].code_ != code; ++idx) {
|
||||
if (errMsg[idx].code_ == -2) return 0;
|
||||
}
|
||||
return idx;
|
||||
// Todo: Return something more useful
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Error::setMsg()
|
||||
//! Specialization for Error
|
||||
template<>
|
||||
const wchar_t* BasicError<char>::wwhat() const throw()
|
||||
{
|
||||
int idx = errorIdx(code_);
|
||||
msg_ = std::string(_(errMsg[idx].message_));
|
||||
std::string::size_type pos;
|
||||
pos = msg_.find("%0");
|
||||
if (pos != std::string::npos) {
|
||||
msg_.replace(pos, 2, toString(code_));
|
||||
}
|
||||
if (count_ > 0) {
|
||||
pos = msg_.find("%1");
|
||||
if (pos != std::string::npos) {
|
||||
msg_.replace(pos, 2, arg1_);
|
||||
}
|
||||
}
|
||||
if (count_ > 1) {
|
||||
pos = msg_.find("%2");
|
||||
if (pos != std::string::npos) {
|
||||
msg_.replace(pos, 2, arg2_);
|
||||
}
|
||||
}
|
||||
if (count_ > 2) {
|
||||
pos = msg_.find("%3");
|
||||
if (pos != std::string::npos) {
|
||||
msg_.replace(pos, 2, arg3_);
|
||||
}
|
||||
}
|
||||
// Todo: Return something more useful
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Specialization for Error
|
||||
template<>
|
||||
const wchar_t* BasicError<wchar_t>::wwhat() const throw()
|
||||
{
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
const char* errMsg(int code)
|
||||
{
|
||||
const ErrMsg* em = find(errList, code);
|
||||
return em ? em->message_ : "";
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
129
src/error.hpp
129
src/error.hpp
@ -52,6 +52,15 @@ namespace Exiv2 {
|
||||
# pragma warning( disable : 4275 )
|
||||
#endif
|
||||
|
||||
//! Generalised toString function
|
||||
template<typename charT, typename T>
|
||||
std::basic_string<charT> toBasicString(const T& arg)
|
||||
{
|
||||
std::basic_ostringstream<charT> os;
|
||||
os << arg;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Error class interface. Allows the definition and use of a hierarchy
|
||||
of error classes which can all be handled in one catch block.
|
||||
@ -74,7 +83,7 @@ namespace Exiv2 {
|
||||
//@}
|
||||
}; // AnyError
|
||||
|
||||
//! %AnyBase output operator
|
||||
//! %AnyError output operator
|
||||
inline std::ostream& operator<<(std::ostream& os, const AnyError& error)
|
||||
{
|
||||
return os << error.what();
|
||||
@ -84,33 +93,39 @@ namespace Exiv2 {
|
||||
@brief Simple error class used for exceptions. An output operator is
|
||||
provided to print errors to a stream.
|
||||
*/
|
||||
class EXIV2API Error : public AnyError {
|
||||
template<typename charT>
|
||||
class EXIV2API BasicError : public AnyError {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor taking only an error code
|
||||
explicit Error(int code);
|
||||
explicit BasicError(int code);
|
||||
//! Constructor taking an error code and one argument
|
||||
template<typename A>
|
||||
EXV_DLLLOCAL Error(int code, const A& arg1);
|
||||
EXV_DLLLOCAL BasicError(int code, const A& arg1);
|
||||
//! Constructor taking an error code and two arguments
|
||||
template<typename A, typename B>
|
||||
EXV_DLLLOCAL Error(int code, const A& arg1, const B& arg2);
|
||||
EXV_DLLLOCAL BasicError(int code, const A& arg1, const B& arg2);
|
||||
//! Constructor taking an error code and three arguments
|
||||
template<typename A, typename B, typename C>
|
||||
EXV_DLLLOCAL Error(int code, const A& arg1, const B& arg2, const C& arg3);
|
||||
EXV_DLLLOCAL BasicError(int code, const A& arg1, const B& arg2, const C& arg3);
|
||||
//! Virtual destructor. (Needed because of throw())
|
||||
virtual ~Error() throw();
|
||||
virtual ~BasicError() throw();
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual int code() const throw();
|
||||
/*!
|
||||
@brief Return the error message. The pointer returned by what()
|
||||
is valid only as long as the Error object exists.
|
||||
@brief Return the error message as a C-string. The pointer returned by what()
|
||||
is valid only as long as the BasicError object exists.
|
||||
*/
|
||||
virtual const char* what() const throw();
|
||||
/*!
|
||||
@brief Return the error message as a wchar_t-string. The pointer returned by
|
||||
wwhat() is valid only as long as the BasicError object exists.
|
||||
*/
|
||||
virtual const wchar_t* wwhat() const throw();
|
||||
//@}
|
||||
|
||||
private:
|
||||
@ -119,44 +134,106 @@ namespace Exiv2 {
|
||||
void setMsg();
|
||||
//@}
|
||||
|
||||
static int errorIdx(int code);
|
||||
|
||||
// DATA
|
||||
int code_; //!< Error code
|
||||
int count_; //!< Number of arguments
|
||||
std::string arg1_; //!< First argument
|
||||
std::string arg2_; //!< Second argument
|
||||
std::string arg3_; //!< Third argument
|
||||
std::string msg_; //!< Complete error message
|
||||
std::basic_string<charT> arg1_; //!< First argument
|
||||
std::basic_string<charT> arg2_; //!< Second argument
|
||||
std::basic_string<charT> arg3_; //!< Third argument
|
||||
std::basic_string<charT> msg_; //!< Complete error message
|
||||
|
||||
}; // class Error
|
||||
}; // class BasicError
|
||||
|
||||
typedef BasicError<char> Error;
|
||||
typedef BasicError<wchar_t> WError;
|
||||
|
||||
// *****************************************************************************
|
||||
// template and inline definitions
|
||||
// free functions, template and inline definitions
|
||||
|
||||
template<typename A>
|
||||
Error::Error(int code, const A& arg1)
|
||||
: code_(code), count_(1), arg1_(toString(arg1))
|
||||
//! Return the error message for the error with code \em code.
|
||||
EXIV2API const char* errMsg(int code);
|
||||
|
||||
template<typename charT>
|
||||
BasicError<charT>::BasicError(int code)
|
||||
: code_(code), count_(0)
|
||||
{
|
||||
setMsg();
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
Error::Error(int code, const A& arg1, const B& arg2)
|
||||
template<typename charT>
|
||||
BasicError<charT>::~BasicError() throw()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
int BasicError<charT>::code() const throw()
|
||||
{
|
||||
return code_;
|
||||
}
|
||||
|
||||
template<typename charT> template<typename A>
|
||||
BasicError<charT>::BasicError(int code, const A& arg1)
|
||||
: code_(code), count_(1), arg1_(toBasicString<charT>(arg1))
|
||||
{
|
||||
setMsg();
|
||||
}
|
||||
|
||||
template<typename charT> template<typename A, typename B>
|
||||
BasicError<charT>::BasicError(int code, const A& arg1, const B& arg2)
|
||||
: code_(code), count_(2),
|
||||
arg1_(toString(arg1)), arg2_(toString(arg2))
|
||||
arg1_(toBasicString<charT>(arg1)),
|
||||
arg2_(toBasicString<charT>(arg2))
|
||||
{
|
||||
setMsg();
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C>
|
||||
Error::Error(int code, const A& arg1, const B& arg2, const C& arg3)
|
||||
template<typename charT> template<typename A, typename B, typename C>
|
||||
BasicError<charT>::BasicError(int code, const A& arg1, const B& arg2, const C& arg3)
|
||||
: code_(code), count_(3),
|
||||
arg1_(toString(arg1)), arg2_(toString(arg2)), arg3_(toString(arg3))
|
||||
arg1_(toBasicString<charT>(arg1)),
|
||||
arg2_(toBasicString<charT>(arg2)),
|
||||
arg3_(toBasicString<charT>(arg3))
|
||||
{
|
||||
setMsg();
|
||||
}
|
||||
|
||||
template<typename charT>
|
||||
void BasicError<charT>::setMsg()
|
||||
{
|
||||
std::string s(exvGettext(errMsg(code_)));
|
||||
msg_.assign(s.begin(), s.end());
|
||||
std::string ph("%0");
|
||||
std::basic_string<charT> tph(ph.begin(), ph.end());
|
||||
size_t pos = msg_.find(tph);
|
||||
if (pos != std::basic_string<charT>::npos) {
|
||||
msg_.replace(pos, 2, toBasicString<charT>(code_));
|
||||
}
|
||||
if (count_ > 0) {
|
||||
ph = "%1";
|
||||
tph.assign(ph.begin(), ph.end());
|
||||
pos = msg_.find(tph);
|
||||
if (pos != std::basic_string<charT>::npos) {
|
||||
msg_.replace(pos, 2, arg1_);
|
||||
}
|
||||
}
|
||||
if (count_ > 1) {
|
||||
ph = "%2";
|
||||
tph.assign(ph.begin(), ph.end());
|
||||
pos = msg_.find(tph);
|
||||
if (pos != std::basic_string<charT>::npos) {
|
||||
msg_.replace(pos, 2, arg2_);
|
||||
}
|
||||
}
|
||||
if (count_ > 2) {
|
||||
ph = "%3";
|
||||
tph.assign(ph.begin(), ph.end());
|
||||
pos = msg_.find(tph);
|
||||
if (pos != std::basic_string<charT>::npos) {
|
||||
msg_.replace(pos, 2, arg3_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( default : 4275 )
|
||||
#endif
|
||||
|
||||
@ -400,7 +400,7 @@ namespace Exiv2 {
|
||||
{
|
||||
BasicIo::AutoPtr io(new FileIo(wpath));
|
||||
Image::AutoPtr image = open(io); // may throw
|
||||
if (image.get() == 0) throw Error(11, ws2s(wpath));
|
||||
if (image.get() == 0) throw WError(11, wpath);
|
||||
return image;
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ namespace Exiv2 {
|
||||
std::auto_ptr<FileIo> fileIo(new FileIo(wpath));
|
||||
// Create or overwrite the file, then close it
|
||||
if (fileIo->open("w+b") != 0) {
|
||||
throw Error(10, ws2s(wpath), "w+b", strError());
|
||||
throw WError(10, wpath, "w+b", strError());
|
||||
}
|
||||
fileIo->close();
|
||||
BasicIo::AutoPtr io(fileIo);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user