remove templating & simplify error message

+ clang-format in Error files
+ Remove AnyError
This commit is contained in:
Luis Díaz Más 2022-03-08 19:52:21 +01:00 committed by Luis Diaz
parent 96f7f2e4c5
commit 7119b7676f
37 changed files with 288 additions and 351 deletions

View File

@ -220,7 +220,7 @@ namespace Action {
}
return rc;
}
catch(const Exiv2::AnyError& e) {
catch(const Exiv2::Error& e) {
std::cerr << "Exiv2 exception in print action for file "
<< path << ":\n" << e << "\n";
return 1;
@ -684,7 +684,7 @@ namespace Action {
}
return rc;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in rename action for file " << path
<< ":\n" << e << "\n";
@ -744,7 +744,7 @@ namespace Action {
return rc;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in erase action for file " << path
<< ":\n" << e << "\n";
@ -854,7 +854,7 @@ namespace Action {
rc = metacopy(path_, exvPath, Exiv2::ImageType::exv, false);
}
return rc;
} catch (const Exiv2::AnyError& e) {
} catch (const Exiv2::Error& e) {
std::cerr << "Exiv2 exception in extract action for file " << path << ":\n" << e << "\n";
return 1;
}
@ -1050,7 +1050,7 @@ namespace Action {
if (Params::instance().preserve_) ts.touch(path);
return rc;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in insert action for file " << path
<< ":\n" << e << "\n";
@ -1201,7 +1201,7 @@ namespace Action {
return rc;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in modify action for file " << path
<< ":\n" << e << "\n";
@ -1440,7 +1440,7 @@ namespace Action {
}
return rc?1:0;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in adjust action for file " << path
<< ":\n" << e << "\n";
@ -1576,7 +1576,7 @@ namespace Action {
return 0;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in fixiso action for file " << path
<< ":\n" << e << "\n";
@ -1642,7 +1642,7 @@ namespace Action {
return 0;
}
catch(const Exiv2::AnyError& e)
catch(const Exiv2::Error& e)
{
std::cerr << "Exiv2 exception in fixcom action for file " << path
<< ":\n" << e << "\n";
@ -1886,7 +1886,7 @@ namespace {
targetImage->writeMetadata();
rc=0;
}
catch (const Exiv2::AnyError& e) {
catch (const Exiv2::Error& e) {
std::cerr << tgt <<
": " << _("Could not write metadata to file") << ": " << e << "\n";
rc=1;

View File

@ -1316,7 +1316,7 @@ namespace {
}
}
}
catch (const Exiv2::AnyError& error) {
catch (const Exiv2::Error& error) {
std::cerr << filename << ", " << _("line") << " " << error << "\n";
return false;
}
@ -1337,7 +1337,7 @@ namespace {
}
return true;
}
catch (const Exiv2::AnyError& error) {
catch (const Exiv2::Error& error) {
std::cerr << _("-M option") << " " << error << "\n";
return false;
}
@ -1406,14 +1406,14 @@ namespace {
defaultType = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(),
iptcKey.record());
}
catch (const Exiv2::AnyError&) {}
catch (const Exiv2::Error&) {}
if (metadataId == invalidMetadataId) {
try {
Exiv2::ExifKey exifKey(key);
metadataId = exif;
defaultType = exifKey.defaultTypeId();
}
catch (const Exiv2::AnyError&) {}
catch (const Exiv2::Error&) {}
}
if (metadataId == invalidMetadataId) {
try {
@ -1421,7 +1421,7 @@ namespace {
metadataId = xmp;
defaultType = Exiv2::XmpProperties::propertyType(xmpKey);
}
catch (const Exiv2::AnyError&) {}
catch (const Exiv2::Error&) {}
}
if (metadataId == invalidMetadataId) {
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, Exiv2::toString(num)

View File

@ -22,10 +22,10 @@
// *****************************************************************************
// namespace extensions
namespace Exiv2 {
// *****************************************************************************
// class definitions
namespace Exiv2
{
// *****************************************************************************
// class definitions
/*!
@brief Class for a log message, used by the library. Applications can set
@ -54,7 +54,8 @@ namespace Exiv2 {
Caveat: The entire log message is not processed in this case. So don't
make that call any logic that always needs to be executed.
*/
class EXIV2API LogMsg {
class EXIV2API LogMsg
{
public:
//! Prevent copy-construction: not implemented.
LogMsg(const LogMsg&) = delete;
@ -64,7 +65,14 @@ namespace Exiv2 {
@brief Defined log levels. To suppress all log messages, either set the
log level to \c mute or set the log message handler to 0.
*/
enum Level { debug = 0, info = 1, warn = 2, error = 3, mute = 4 };
enum Level
{
debug = 0,
info = 1,
warn = 2,
error = 3,
mute = 4
};
/*!
@brief Type for a log message handler function. The function receives
the log level and message and can process it in an application
@ -119,26 +127,34 @@ namespace Exiv2 {
// Holds the log message until it is passed to the message handler
std::ostringstream os_;
}; // class LogMsg
}; // class LogMsg
// Macros for simple access
//! Shorthand to create a temp debug log message object and return its ostringstream
#define EXV_DEBUG if (LogMsg::debug >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::debug).os()
#define EXV_DEBUG \
if (LogMsg::debug >= LogMsg::level() && LogMsg::handler()) \
LogMsg(LogMsg::debug).os()
//! Shorthand for a temp info log message object and return its ostringstream
#define EXV_INFO if (LogMsg::info >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::info).os()
#define EXV_INFO \
if (LogMsg::info >= LogMsg::level() && LogMsg::handler()) \
LogMsg(LogMsg::info).os()
//! Shorthand for a temp warning log message object and return its ostringstream
#define EXV_WARNING if (LogMsg::warn >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::warn).os()
#define EXV_WARNING \
if (LogMsg::warn >= LogMsg::level() && LogMsg::handler()) \
LogMsg(LogMsg::warn).os()
//! Shorthand for a temp error log message object and return its ostringstream
#define EXV_ERROR if (LogMsg::error >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::error).os()
#define EXV_ERROR \
if (LogMsg::error >= LogMsg::level() && LogMsg::handler()) \
LogMsg(LogMsg::error).os()
#ifdef _MSC_VER
// Disable MSVC warnings "non - DLL-interface classkey 'identifier' used as base
// for DLL-interface classkey 'identifier'"
# pragma warning( disable : 4275 )
#pragma warning(disable : 4275)
#endif
//! Generalised toString function
template<typename charT, typename T>
template <typename charT, typename T>
std::basic_string<charT> toBasicString(const T& arg)
{
std::basic_ostringstream<charT> os;
@ -147,7 +163,8 @@ namespace Exiv2 {
}
//! Complete list of all Exiv2 error codes
enum class ErrorCode {
enum class ErrorCode
{
kerSuccess = 0,
kerGeneralError,
kerErrorMessage,
@ -173,9 +190,7 @@ namespace Exiv2 {
kerImageWriteFailed,
kerNoImageInInputData,
kerInvalidIfdId,
//! Entry::setValue: Value too large
kerValueTooLarge,
//! Entry::setDataArea: Value too large
kerDataAreaValueTooLarge,
kerOffsetOutOfRange,
kerUnsupportedDataAreaOffsetType,
@ -213,144 +228,86 @@ namespace Exiv2 {
kerCorruptedMetadata,
kerArithmeticOverflow,
kerMallocFailed,
kerErrorCount,
};
/*!
@brief Error class interface. Allows the definition and use of a hierarchy
of error classes which can all be handled in one catch block.
Inherits from the standard exception base-class, to make life
easier for library users (they have the option of catching most
things via std::exception).
*/
class EXIV2API AnyError : public std::exception {
public:
AnyError() = default;
AnyError(const AnyError& o) = default;
~AnyError() noexcept override = default;
///@brief Return the error code.
virtual ErrorCode code() const noexcept = 0;
};
//! %AnyError output operator
inline std::ostream& operator<<(std::ostream& os, const AnyError& error)
{
return os << error.what();
}
/*!
@brief Simple error class used for exceptions. An output operator is
provided to print errors to a stream.
*/
template<typename charT>
class EXIV2API BasicError : public AnyError {
class EXIV2API Error : public std::exception
{
public:
//! @name Creators
//@{
//! Constructor taking only an error code
explicit inline BasicError(ErrorCode code);
explicit Error(ErrorCode code);
//! Constructor taking an error code and one argument
template<typename A>
inline BasicError(ErrorCode code, const A& arg1);
template <typename A>
Error(ErrorCode code, const A& arg1) : code_(code), arg1_(toBasicString<char>(arg1))
{
setMsg(1);
}
//! Constructor taking an error code and two arguments
template<typename A, typename B>
inline BasicError(ErrorCode code, const A& arg1, const B& arg2);
template <typename A, typename B>
Error(ErrorCode code, const A& arg1, const B& arg2)
: code_(code), arg1_(toBasicString<char>(arg1)), arg2_(toBasicString<char>(arg2))
{
setMsg(2);
}
//! Constructor taking an error code and three arguments
template<typename A, typename B, typename C>
inline BasicError(ErrorCode code, const A& arg1, const B& arg2, const C& arg3);
template <typename A, typename B, typename C>
Error(ErrorCode code, const A& arg1, const B& arg2, const C& arg3)
: code_(code),
arg1_(toBasicString<char>(arg1)),
arg2_(toBasicString<char>(arg2)),
arg3_(toBasicString<char>(arg3))
{
setMsg(3);
}
//! Virtual destructor. (Needed because of throw())
inline ~BasicError() noexcept override;
virtual ~Error() noexcept;
//@}
//! @name Accessors
//@{
inline ErrorCode code() const noexcept override;
ErrorCode code() const noexcept;
/*!
@brief Return the error message as a C-string. The pointer returned by what()
is valid only as long as the BasicError object exists.
*/
inline const char* what() const noexcept override;
const char* what() const noexcept override;
//@}
private:
//! @name Manipulators
//@{
//! Assemble the error message from the arguments
void setMsg();
void setMsg(int count);
//@}
// DATA
ErrorCode code_; //!< Error code
int count_; //!< Number of arguments
std::basic_string<charT> arg1_; //!< First argument
std::basic_string<charT> arg2_; //!< Second argument
std::basic_string<charT> arg3_; //!< Third argument
std::string msg_; //!< Complete error message
}; // class BasicError
const ErrorCode code_; //!< Error code
const std::string arg1_; //!< First argument
const std::string arg2_; //!< Second argument
const std::string arg3_; //!< Third argument
std::string msg_; //!< Complete error message
}; // class BasicError
//! Error class used for exceptions (std::string based)
using Error = BasicError<char>;
// *****************************************************************************
// free functions, template and inline definitions
//! Return the error message for the error with code \em code.
const char* errMsg(ErrorCode code);
template<typename charT>
BasicError<charT>::BasicError(ErrorCode code)
: code_(code), count_(0)
//! %Error output operator
inline std::ostream& operator<<(std::ostream& os, const Error& error)
{
setMsg();
}
template<typename charT> template<typename A>
BasicError<charT>::BasicError(ErrorCode code, const A& arg1)
: code_(code), count_(1), arg1_(toBasicString<charT>(arg1))
{
setMsg();
}
template<typename charT> template<typename A, typename B>
BasicError<charT>::BasicError(ErrorCode code, const A& arg1, const B& arg2)
: code_(code), count_(2),
arg1_(toBasicString<charT>(arg1)),
arg2_(toBasicString<charT>(arg2))
{
setMsg();
}
template<typename charT> template<typename A, typename B, typename C>
BasicError<charT>::BasicError(ErrorCode code, const A& arg1, const B& arg2, const C& arg3)
: code_(code), count_(3),
arg1_(toBasicString<charT>(arg1)),
arg2_(toBasicString<charT>(arg2)),
arg3_(toBasicString<charT>(arg3))
{
setMsg();
}
template <typename charT>
BasicError<charT>::~BasicError() noexcept = default;
template <typename charT>
ErrorCode BasicError<charT>::code() const noexcept
{
return code_;
}
template <typename charT>
const char* BasicError<charT>::what() const noexcept
{
return msg_.c_str();
return os << error.what();
}
#ifdef _MSC_VER
# pragma warning( default : 4275 )
#pragma warning(default : 4275)
#endif
} // namespace Exiv2
#endif // #ifndef ERROR_HPP_
} // namespace Exiv2
#endif // #ifndef ERROR_HPP_

View File

@ -109,7 +109,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -102,7 +102,7 @@ int main(int argc,const char** argv)
httpcon(url, useHttp1_0);
isOk = true;
}
} catch (const Exiv2::AnyError& e) {
} catch (const Exiv2::Error& e) {
std::cout << "Error: '" << e << "'" << std::endl;
return -1;
}

View File

@ -34,7 +34,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -81,7 +81,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -49,7 +49,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -88,7 +88,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -198,7 +198,7 @@ int main(int argc,const char* argv[])
result = 3;
break;
}
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cerr << "*** error exiv2 exception '" << e << "' ***" << std::endl;
result = 4;
} catch ( ... ) {

View File

@ -118,7 +118,7 @@ try {
return rc;
}
//catch (std::exception& e) {
//catch (Exiv2::AnyError& e) {
//catch (Exiv2::Error& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e.what() << "'\n";
return -1;

View File

@ -32,7 +32,7 @@ int main(int argc, char* const argv[])
try {
std::cout << exifData[key] << std::endl;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'" << std::endl;
exit(3);
} catch ( ... ) {

View File

@ -137,7 +137,7 @@ int main(int argc, char* const argv[])
}
return 0;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return 20;
}

View File

@ -44,7 +44,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -45,7 +45,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return 1;
}

View File

@ -45,7 +45,7 @@ int main(int argc, char* const argv[])
return 0;
}
catch (AnyError& e) {
catch (Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -72,7 +72,7 @@ int main(int argc, char* const argv[])
image->writeMetadata();
return 0;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -57,7 +57,7 @@ try {
try {
writeImg->writeMetadata();
}
catch (const Exiv2::AnyError&) {
catch (const Exiv2::Error&) {
std::cerr << params.progname() <<
": Could not write metadata to (" << params.write_ << ")\n";
return 8;
@ -65,7 +65,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return 10;
}

View File

@ -39,6 +39,6 @@ try {
return 0;
}
catch (const AnyError& e) {
catch (const Error& e) {
std::cout << e << "\n";
}

View File

@ -46,7 +46,7 @@ int main(int argc, char* const argv[])
}
return 0;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -38,7 +38,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -101,7 +101,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -80,7 +80,7 @@ int main()
std::cout << "nok";
std::cout << std::endl;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -76,7 +76,7 @@ int main(int argc, char* argv[])
try {
XmpProperties::printProperties(std::cout, item);
break;
} catch (const AnyError&) {
} catch (const Error&) {
rc = 2;
}
std::cerr << "Unexpected argument " << argv[1] << std::endl;
@ -135,7 +135,7 @@ int main(int argc, char* argv[])
<< "Print Exif tags, MakerNote tags, or Iptc datasets" << std::endl
;
}
} catch (AnyError& e) {
} catch (Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
rc = EXIT_FAILURE ;
}

View File

@ -35,7 +35,7 @@ try {
return 0;
}
catch (const AnyError& e) {
catch (const Error& e) {
std::cout << e << "\n";
}

View File

@ -132,7 +132,7 @@ int main(int argc, char* const argv[])
return rc;
}
catch (AnyError& e) {
catch (Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return 1;
}

View File

@ -189,7 +189,7 @@ int main(int argc, char* const argv[])
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -30,7 +30,7 @@ int main(int argc, char* const argv[])
std::cout << xmpPacket << "\n";
return 0;
} catch (Exiv2::AnyError& e) {
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -39,7 +39,7 @@ try {
Exiv2::XmpParser::terminate();
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -54,7 +54,7 @@ try {
Exiv2::XmpParser::terminate();
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -49,7 +49,7 @@ int main(int argc, char** argv)
return 0;
}
catch (Exiv2::AnyError& e)
catch (Exiv2::Error& e)
{
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;

View File

@ -205,7 +205,7 @@ try {
return 0;
}
catch (Exiv2::AnyError& e) {
catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

View File

@ -523,7 +523,7 @@ namespace Exiv2 {
}
if (i == 0) {
if (!isHex(recordName, 4, "0x"))
throw Error(kerInvalidRecord, recordName);
throw Error(ErrorCode::kerInvalidRecord, recordName);
std::istringstream is(recordName);
is >> std::hex >> i;
}

View File

@ -2,164 +2,109 @@
// included header files
#include "error.hpp"
#include "types.hpp"
#include "i18n.h" // NLS support.
#include "types.hpp"
// + standard includes
#include <iostream>
#include <array>
#include <cassert>
#include <iostream>
// *****************************************************************************
namespace {
//! Helper structure defining an error message.
struct ErrMsg {
//! Comparison operator
bool operator==(Exiv2::ErrorCode code) const { return code_ == code; }
Exiv2::ErrorCode code_; //!< Error code
const char* message_; //!< Error message
};
namespace
{
//! Complete list of Exiv2 exception error messages
const ErrMsg errList[] = {
{ Exiv2::ErrorCode::kerGeneralError,
N_("Error %0: arg2=%2, arg3=%3, arg1=%1.") },
{ Exiv2::ErrorCode::kerSuccess,
N_("Success") },
{ Exiv2::ErrorCode::kerErrorMessage,
"%1" }, // %1=error message
{ Exiv2::ErrorCode::kerCallFailed,
"%1: Call to `%3' failed: %2" }, // %1=path, %2=strerror, %3=function that failed
{ Exiv2::ErrorCode::kerNotAnImage,
N_("This does not look like a %1 image") }, // %1=Image type
{ Exiv2::ErrorCode::kerInvalidDataset,
N_("Invalid dataset name '%1'") }, // %1=dataset name
{ Exiv2::ErrorCode::kerInvalidRecord,
N_("Invalid record name '%1'") }, // %1=record name
{ Exiv2::ErrorCode::kerInvalidKey,
N_("Invalid key '%1'") }, // %1=key
{ Exiv2::ErrorCode::kerInvalidTag,
N_("Invalid tag name or ifdId `%1', ifdId %2") }, // %1=tag name, %2=ifdId
{ Exiv2::ErrorCode::kerValueNotSet,
N_("Value not set") },
{ Exiv2::ErrorCode::kerDataSourceOpenFailed,
N_("%1: Failed to open the data source: %2") }, // %1=path, %2=strerror
{ Exiv2::ErrorCode::kerFileOpenFailed,
N_("%1: Failed to open file (%2): %3") }, // %1=path, %2=mode, %3=strerror
{ Exiv2::ErrorCode::kerFileContainsUnknownImageType,
N_("%1: The file contains data of an unknown image type") }, // %1=path
{ Exiv2::ErrorCode::kerMemoryContainsUnknownImageType,
N_("The memory contains data of an unknown image type") },
{ Exiv2::ErrorCode::kerUnsupportedImageType,
N_("Image type %1 is not supported") }, // %1=image type
{ Exiv2::ErrorCode::kerFailedToReadImageData,
N_("Failed to read image data") },
{ Exiv2::ErrorCode::kerNotAJpeg,
N_("This does not look like a JPEG image") },
{ Exiv2::ErrorCode::kerFailedToMapFileForReadWrite,
N_("%1: Failed to map file for reading and writing: %2") }, // %1=path, %2=strerror
{ Exiv2::ErrorCode::kerFileRenameFailed,
N_("%1: Failed to rename file to %2: %3") }, // %1=old path, %2=new path, %3=strerror
{ Exiv2::ErrorCode::kerTransferFailed,
N_("%1: Transfer failed: %2") }, // %1=path, %2=strerror
{ Exiv2::ErrorCode::kerMemoryTransferFailed,
N_("Memory transfer failed: %1") }, // %1=strerror
{ Exiv2::ErrorCode::kerInputDataReadFailed,
N_("Failed to read input data") },
{ Exiv2::ErrorCode::kerImageWriteFailed,
N_("Failed to write image") },
{ Exiv2::ErrorCode::kerNoImageInInputData,
N_("Input data does not contain a valid image") },
{ Exiv2::ErrorCode::kerInvalidIfdId,
N_("Invalid ifdId %1") }, // %1=ifdId
{ Exiv2::ErrorCode::kerValueTooLarge,
N_("Entry::setValue: Value too large (tag=%1, size=%2, requested=%3)") }, // %1=tag, %2=dataSize, %3=required size
{ Exiv2::ErrorCode::kerDataAreaValueTooLarge,
N_("Entry::setDataArea: Value too large (tag=%1, size=%2, requested=%3)") }, // %1=tag, %2=dataAreaSize, %3=required size
{ Exiv2::ErrorCode::kerOffsetOutOfRange,
N_("Offset out of range") },
{ Exiv2::ErrorCode::kerUnsupportedDataAreaOffsetType,
N_("Unsupported data area offset type") },
{ Exiv2::ErrorCode::kerInvalidCharset,
N_("Invalid charset: `%1'") }, // %1=charset name
{ Exiv2::ErrorCode::kerUnsupportedDateFormat,
N_("Unsupported date format") },
{ Exiv2::ErrorCode::kerUnsupportedTimeFormat,
N_("Unsupported time format") },
{ Exiv2::ErrorCode::kerWritingImageFormatUnsupported,
N_("Writing to %1 images is not supported") }, // %1=image format
{ Exiv2::ErrorCode::kerInvalidSettingForImage,
N_("Setting %1 in %2 images is not supported") }, // %1=metadata type, %2=image format
{ Exiv2::ErrorCode::kerNotACrwImage,
N_("This does not look like a CRW image") },
{ Exiv2::ErrorCode::kerFunctionNotSupported,
N_("%1: Not supported") }, // %1=function
{ Exiv2::ErrorCode::kerNoNamespaceInfoForXmpPrefix,
N_("No namespace info available for XMP prefix `%1'") }, // %1=prefix
{ Exiv2::ErrorCode::kerNoPrefixForNamespace,
N_("No prefix registered for namespace `%2', needed for property path `%1'") }, // %1=namespace
{ Exiv2::ErrorCode::kerTooLargeJpegSegment,
N_("Size of %1 JPEG segment is larger than 65535 bytes") }, // %1=type of metadata (Exif, IPTC, JPEG comment)
{ Exiv2::ErrorCode::kerUnhandledXmpdatum,
N_("Unhandled Xmpdatum %1 of type %2") }, // %1=key, %2=value type
{ Exiv2::ErrorCode::kerUnhandledXmpNode,
N_("Unhandled XMP node %1 with opt=%2") }, // %1=key, %2=XMP Toolkit option flags
{ Exiv2::ErrorCode::kerXMPToolkitError,
N_("XMP Toolkit error %1: %2") }, // %1=XMP_Error::GetID(), %2=XMP_Error::GetErrMsg()
{ Exiv2::ErrorCode::kerDecodeLangAltPropertyFailed,
N_("Failed to decode Lang Alt property %1 with opt=%2") }, // %1=property path, %3=XMP Toolkit option flags
{ Exiv2::ErrorCode::kerDecodeLangAltQualifierFailed,
N_("Failed to decode Lang Alt qualifier %1 with opt=%2") }, // %1=qualifier path, %3=XMP Toolkit option flags
{ Exiv2::ErrorCode::kerEncodeLangAltPropertyFailed,
N_("Failed to encode Lang Alt property %1") }, // %1=key
{ Exiv2::ErrorCode::kerPropertyNameIdentificationFailed,
N_("Failed to determine property name from path %1, namespace %2") }, // %1=property path, %2=namespace
{ Exiv2::ErrorCode::kerSchemaNamespaceNotRegistered,
N_("Schema namespace %1 is not registered with the XMP Toolkit") }, // %1=namespace
{ Exiv2::ErrorCode::kerNoNamespaceForPrefix,
N_("No namespace registered for prefix `%1'") }, // %1=prefix
{ Exiv2::ErrorCode::kerAliasesNotSupported,
N_("Aliases are not supported. Please send this XMP packet to ahuggel@gmx.net `%1', `%2', `%3'") }, // %1=namespace, %2=property path, %3=value
{ Exiv2::ErrorCode::kerInvalidXmpText,
N_("Invalid XmpText type `%1'") }, // %1=type
{ Exiv2::ErrorCode::kerTooManyTiffDirectoryEntries,
N_("TIFF directory %1 has too many entries") }, // %1=TIFF directory name
{ Exiv2::ErrorCode::kerMultipleTiffArrayElementTagsInDirectory,
N_("Multiple TIFF array element tags %1 in one directory") }, // %1=tag number
{ Exiv2::ErrorCode::kerWrongTiffArrayElementTagType,
N_("TIFF array element tag %1 has wrong type") }, // %1=tag number
{ Exiv2::ErrorCode::kerInvalidKeyXmpValue,
N_("%1 has invalid XMP value type `%2'") }, // %1=key, %2=value type
{ Exiv2::ErrorCode::kerInvalidIccProfile,
N_("Not a valid ICC Profile") },
{ Exiv2::ErrorCode::kerTiffDirectoryTooLarge,
N_("tiff directory length is too large") },
{ Exiv2::ErrorCode::kerInvalidTypeValue,
N_("invalid type in tiff structure") },
{ Exiv2::ErrorCode::kerInvalidLangAltValue,
N_("Invalid LangAlt value `%1'") }, // %1=value
{ Exiv2::ErrorCode::kerInvalidMalloc,
N_("invalid memory allocation request") },
{ Exiv2::ErrorCode::kerCorruptedMetadata,
N_("corrupted image metadata") },
{ Exiv2::ErrorCode::kerArithmeticOverflow,
N_("Arithmetic operation overflow") },
{ Exiv2::ErrorCode::kerMallocFailed,
N_("Memory allocation failed")}
constexpr std::array<const char*, static_cast<size_t>(Exiv2::ErrorCode::kerErrorCount)> errList{
N_("Success"), // kerSuccess
N_("Error %0: arg2=%2, arg3=%3, arg1=%1."), // KerGeneralError
"%1", // kerErrorMessage,
"%1: Call to `%3' failed: %2", // KerCallFailed, %1=path, %2=strerror, %3=function that failed
N_("This does not look like a %1 image"), // kerNotAnImage, %1=Image type
N_("Invalid dataset name '%1'"), // kerInvalidDataset %1=dataset name
N_("Invalid record name '%1'"), // kerInvalidRecord %1=record name
N_("Invalid key '%1'"), // kerInvalidKey %1=key
N_("Invalid tag name or ifdId `%1', ifdId %2"), // kerInvalidTag %1=tag name, %2=ifdId
N_("Value not set"), // kerValueNotSet
N_("%1: Failed to open the data source: %2"), // kerDataSourceOpenFailed %1=path, %2=strerror
N_("%1: Failed to open file (%2): %3"), // kerFileOpenFailed %1=path, %2=mode, %3=strerror
N_("%1: The file contains data of an unknown image type"), // kerFileContainsUnknownImageType %1=path
N_("The memory contains data of an unknown image type"), // kerMemoryContainsUnknownImageType
N_("Image type %1 is not supported"), // kerUnsupportedImageType %1=image type
N_("Failed to read image data"), // kerFailedToReadImageData
N_("This does not look like a JPEG image"), // kerNotAJpeg
N_("%1: Failed to map file for reading and writing: %2"), // kerFailedToMapFileForReadWrite %1=path,
// %2=strerror
N_("%1: Failed to rename file to %2: %3"), // kerFileRenameFailed %1=old path, %2=new path, %3=strerror
N_("%1: Transfer failed: %2"), // kerTransferFailed %1=path, %2=strerror
N_("Memory transfer failed: %1"), // kerMemoryTransferFailed %1=strerror
N_("Failed to read input data"), // kerInputDataReadFailed
N_("Failed to write image"), // kerImageWriteFailed
N_("Input data does not contain a valid image"), // kerNoImageInInputData
N_("Invalid ifdId %1"), // kerInvalidIfdId %1=ifdId
N_("Entry::setValue: Value too large (tag=%1, size=%2, requested=%3)"), // kerValueTooLarge %1=tag,
// %2=dataSize, %3=required size
N_("Entry::setDataArea: Value too large (tag=%1, size=%2, requested=%3)"), // kerDataAreaValueTooLarge %1=tag,
// %2=dataAreaSize, %3=required size
N_("Offset out of range"), // kerOffsetOutOfRange
N_("Unsupported data area offset type"), // kerUnsupportedDataAreaOffsetType
N_("Invalid charset: `%1'"), // kerInvalidCharset %1=charset name
N_("Unsupported date format"), // kerUnsupportedDateFormat
N_("Unsupported time format"), // kerUnsupportedTimeFormat
N_("Writing to %1 images is not supported"), // kerWritingImageFormatUnsupported %1=image format
N_("Setting %1 in %2 images is not supported"), // kerInvalidSettingForImage %1=metadata type, %2=image format
N_("This does not look like a CRW image"), // kerNotACrwImage
N_("%1: Not supported"), // kerFunctionNotSupported %1=function
N_("No namespace info available for XMP prefix `%1'"), // kerNoNamespaceInfoForXmpPrefix %1=prefix
N_("No prefix registered for namespace `%2', needed for property path `%1'"), // kerNoPrefixForNamespace
// %1=namespace
N_("Size of %1 JPEG segment is larger than 65535 bytes"), // kerTooLargeJpegSegment %1=type of metadata (Exif,
// IPTC, JPEG comment)
N_("Unhandled Xmpdatum %1 of type %2"), // kerUnhandledXmpdatum %1=key, %2=value type
N_("Unhandled XMP node %1 with opt=%2"), // kerUnhandledXmpNode %1=key, %2=XMP Toolkit option flags
N_("XMP Toolkit error %1: %2"), // kerXMPToolkitError %1=XMP_Error::GetID(), %2=XMP_Error::GetErrMsg()
N_("Failed to decode Lang Alt property %1 with opt=%2"), // kerDecodeLangAltPropertyFailed %1=property path,
// %3=XMP Toolkit option flags
N_("Failed to decode Lang Alt qualifier %1 with opt=%2"), // kerDecodeLangAltQualifierFailed %1=qualifier path,
// %3=XMP Toolkit option flags
N_("Failed to encode Lang Alt property %1"), // kerEncodeLangAltPropertyFailed %1=key
N_("Failed to determine property name from path %1, namespace %2"), // kerPropertyNameIdentificationFailed
// %1=property path, %2=namespace
N_("Schema namespace %1 is not registered with the XMP Toolkit"), // kerSchemaNamespaceNotRegistered
// %1=namespace
N_("No namespace registered for prefix `%1'"), // kerNoNamespaceForPrefix %1=prefix
N_("Aliases are not supported. Please send this XMP packet to ahuggel@gmx.net `%1', `%2', `%3'"), // kerAliasesNotSupported
// %1=namespace,
// %2=property
// path,
// %3=value
N_("Invalid XmpText type `%1'"), // kerInvalidXmpText %1=type
N_("TIFF directory %1 has too many entries"), // kerTooManyTiffDirectoryEntries %1=TIFF directory name
N_("Multiple TIFF array element tags %1 in one directory"), // kerMultipleTiffArrayElementTagsInDirectory
// %1=tag number
N_("TIFF array element tag %1 has wrong type"), // kerWrongTiffArrayElementTagType %1=tag number
N_("%1 has invalid XMP value type `%2'"), // kerInvalidKeyXmpValue %1=key, %2=value type
N_("Not a valid ICC Profile"), // kerInvalidIccProfile
N_("Not valid XMP"), // kerInvalidXMP
N_("tiff directory length is too large"), // kerTiffDirectoryTooLarge
N_("invalid type in tiff structure"), // kerInvalidTypeValue
N_("Invalid LangAlt value `%1'"), // kerInvalidLangAltValue %1=value
N_("invalid memory allocation request"), // kerInvalidMalloc
N_("corrupted image metadata"), // kerCorruptedMetadata
N_("Arithmetic operation overflow"), // kerArithmeticOverflow
N_("Memory allocation failed"), // kerMallocFailed
};
} // namespace
// *****************************************************************************
// class member definitions
namespace Exiv2 {
LogMsg::Level LogMsg::level_ = LogMsg::warn; // Default output level
namespace Exiv2
{
LogMsg::Level LogMsg::level_ = LogMsg::warn; // Default output level
LogMsg::Handler LogMsg::handler_ = LogMsg::defaultHandler;
LogMsg::LogMsg(LogMsg::Level msgType) : msgType_(msgType)
{}
{
}
LogMsg::~LogMsg()
{
@ -167,50 +112,91 @@ namespace Exiv2 {
handler_(msgType_, os_.str().c_str());
}
std::ostringstream &LogMsg::os() { return os_; }
std::ostringstream& LogMsg::os()
{
return os_;
}
void LogMsg::setLevel(LogMsg::Level level) { level_ = level; }
void LogMsg::setLevel(LogMsg::Level level)
{
level_ = level;
}
void LogMsg::setHandler(LogMsg::Handler handler) { handler_ = handler; }
void LogMsg::setHandler(LogMsg::Handler handler)
{
handler_ = handler;
}
LogMsg::Level LogMsg::level() { return level_; }
LogMsg::Level LogMsg::level()
{
return level_;
}
LogMsg::Handler LogMsg::handler() { return handler_; }
LogMsg::Handler LogMsg::handler()
{
return handler_;
}
void LogMsg::defaultHandler(int level, const char* s)
{
switch (static_cast<LogMsg::Level>(level)) {
case LogMsg::debug: std::cerr << "Debug: "; break;
case LogMsg::info: std::cerr << "Info: "; break;
case LogMsg::warn: std::cerr << "Warning: "; break;
case LogMsg::error: std::cerr << "Error: "; break;
case LogMsg::mute: assert(false);
case LogMsg::debug:
std::cerr << "Debug: ";
break;
case LogMsg::info:
std::cerr << "Info: ";
break;
case LogMsg::warn:
std::cerr << "Warning: ";
break;
case LogMsg::error:
std::cerr << "Error: ";
break;
case LogMsg::mute:
assert(false);
}
std::cerr << s;
}
template<>
void EXIV2API BasicError<char>::setMsg()
Error::Error(ErrorCode code) : code_(code)
{
std::string msg = _(errMsg(code_));
std::string::size_type pos;
pos = msg.find("%0");
setMsg(0);
}
Error::~Error() noexcept
{
}
ErrorCode Error::code() const noexcept
{
return code_;
}
const char* Error::what() const noexcept
{
return msg_.c_str();
}
void Error::setMsg(int count)
{
std::string msg {errList.at(static_cast<size_t>(code_))};
auto pos = msg.find("%0");
if (pos != std::string::npos) {
msg.replace(pos, 2, toString(static_cast<int>(code_)));
}
if (count_ > 0) {
if (count > 0) {
pos = msg.find("%1");
if (pos != std::string::npos) {
msg.replace(pos, 2, arg1_);
}
}
if (count_ > 1) {
if (count > 1) {
pos = msg.find("%2");
if (pos != std::string::npos) {
msg.replace(pos, 2, arg2_);
}
}
if (count_ > 2) {
if (count > 2) {
pos = msg.find("%3");
if (pos != std::string::npos) {
msg.replace(pos, 2, arg3_);
@ -218,14 +204,5 @@ namespace Exiv2 {
}
msg_ = msg;
}
#ifdef __APPLE__
template class EXIV2API BasicError<char>;
#endif
const char* errMsg(ErrorCode code)
{
const ErrMsg* em = find(errList, code);
return em ? em->message_ : "";
}
} // namespace Exiv2
} // namespace Exiv2

View File

@ -486,7 +486,7 @@ namespace {
width_ = image->pixelWidth();
height_ = image->pixelHeight();
} catch (const AnyError& /* error */) {
} catch (const Error& /* error */) {
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Invalid native preview image.\n";
#endif
@ -575,7 +575,7 @@ namespace {
width_ = image->pixelWidth();
height_ = image->pixelHeight();
}
catch (const AnyError& /* error */ ) {
catch (const Error& /* error */ ) {
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Invalid JPEG preview image.\n";
#endif
@ -654,7 +654,7 @@ namespace {
width_ = image->pixelWidth();
height_ = image->pixelHeight();
}
catch (const AnyError& /* error */ ) {
catch (const Error& /* error */ ) {
return false;
}

View File

@ -19,7 +19,7 @@ TEST(LangAltValueReadTest, noLanguageValBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang= test1-1";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -36,7 +36,7 @@ TEST(LangAltValueReadTest, quoteThenNoLanguageValBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=\" test1-2";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -54,7 +54,7 @@ TEST(LangAltValueReadTest, emptyDoubleQuotesLanguageValBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=\"\" test2";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -72,7 +72,7 @@ TEST(LangAltValueReadTest, emptyDoubleQuotesLanguageValNoSpace)
try {
xmpData["Xmp.dc.title"] = "lang=\"\"test3-1";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -89,7 +89,7 @@ TEST(LangAltValueReadTest, oneDoubleQuotesLanguageValNoSpace)
try {
xmpData["Xmp.dc.title"] = "lang=\"test3-2";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -106,7 +106,7 @@ TEST(LangAltValueReadTest, oneDoubleQuotesLanguageValBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=\"en-UK test3-3";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -123,7 +123,7 @@ TEST(LangAltValueReadTest, languageValOneDoubleQuotesBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=en-US\" test3-4";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -140,7 +140,7 @@ TEST(LangAltValueReadTest, languageValOneDoubleQuotesNoSpace)
try {
xmpData["Xmp.dc.title"] = "lang=test3-5\"";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -157,7 +157,7 @@ TEST(LangAltValueReadTest, languageValTwoDoubleQuotesNoSpace)
try {
xmpData["Xmp.dc.title"] = "lang=test3-6\"\"";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -175,7 +175,7 @@ TEST(LangAltValueReadTest, languageValExtraHyphenBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=en-UK- test4-1";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {
@ -192,7 +192,7 @@ TEST(LangAltValueReadTest, languageValWithInvalidCharBeforeSpace)
try {
xmpData["Xmp.dc.title"] = "lang=en=UK test4-2";
}
catch (AnyError& e) {
catch (Error& e) {
ASSERT_EQ(e.code(),Exiv2::ErrorCode::kerInvalidLangAltValue);
}
catch (...) {

View File

@ -7,7 +7,7 @@
#include <stdexcept>
TEST(enforce, errMessage)
TEST(enforce, errMessageCanBeRetrievedFromErrorException)
{
try {
enforce(false, Exiv2::ErrorCode::kerErrorMessage, "an error occurred");
@ -16,14 +16,17 @@ TEST(enforce, errMessage)
}
}
TEST(enforce, exceptionThrown)
TEST(enforce, withTrueConditionDoesNotThrow)
{
ASSERT_NO_THROW(enforce(true, Exiv2::ErrorCode::kerErrorMessage));
}
TEST(enforce, withFalseConditionThrows)
{
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage), Exiv2::Error);
ASSERT_THROW(enforce<std::overflow_error>(false, "error message"), std::overflow_error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage, "error message"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerDataSourceOpenFailed, "path", "strerror"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerCallFailed, "path", "strerror", "function"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error);
ASSERT_THROW(enforce<std::overflow_error>(false, "error message"), std::overflow_error);
}