diff --git a/app/actions.cpp b/app/actions.cpp index a4f3fac1..1f5502dd 100644 --- a/app/actions.cpp +++ b/app/actions.cpp @@ -179,7 +179,7 @@ int setModeAndPrintStructure(Exiv2::PrintStructureOption option, const std::stri ascii.write_uint8(str.size() * 3, 0); std::copy(str.begin(), str.end(), iccProfile.begin()); if (Exiv2::base64encode(iccProfile.c_data(), str.size(), reinterpret_cast(ascii.data()), str.size() * 3)) { - long chunk = 60; + const size_t chunk = 60; std::string code = std::string("data:") + ascii.c_str(); size_t length = code.size(); for (size_t start = 0; start < length; start += chunk) { @@ -364,8 +364,8 @@ int Print::printList() { auto image = Exiv2::ImageFactory::open(path_); image->readMetadata(); // Set defaults for metadata types and data columns - if (Params::instance().printTags_ == Exiv2::mdNone) { - Params::instance().printTags_ = Exiv2::mdExif | Exiv2::mdIptc | Exiv2::mdXmp; + if (Params::instance().printTags_ == MetadataId::invalid) { + Params::instance().printTags_ = MetadataId::exif | MetadataId::iptc | MetadataId::xmp; } if (Params::instance().printItems_ == 0) { Params::instance().printItems_ = Params::prKey | Params::prType | Params::prCount | Params::prTrans; @@ -376,7 +376,7 @@ int Print::printList() { int Print::printMetadata(const Exiv2::Image* image) { bool ret = false; bool noExif = false; - if (Params::instance().printTags_ & Exiv2::mdExif) { + if ((Params::instance().printTags_ & MetadataId::exif) == MetadataId::exif) { const Exiv2::ExifData& exifData = image->exifData(); for (auto&& md : exifData) { ret |= printMetadatum(md, image); @@ -386,7 +386,7 @@ int Print::printMetadata(const Exiv2::Image* image) { } bool noIptc = false; - if (Params::instance().printTags_ & Exiv2::mdIptc) { + if ((Params::instance().printTags_ & MetadataId::iptc) == MetadataId::iptc) { const Exiv2::IptcData& iptcData = image->iptcData(); for (auto&& md : iptcData) { ret |= printMetadatum(md, image); @@ -396,7 +396,7 @@ int Print::printMetadata(const Exiv2::Image* image) { } bool noXmp = false; - if (Params::instance().printTags_ & Exiv2::mdXmp) { + if ((Params::instance().printTags_ & MetadataId::xmp) == MetadataId::xmp) { const Exiv2::XmpData& xmpData = image->xmpData(); for (auto&& md : xmpData) { ret |= printMetadatum(md, image); @@ -1148,23 +1148,23 @@ int Modify::applyCommands(Exiv2::Image* pImage) { int ret = 0; for (auto&& cmd : modifyCmds) { switch (cmd.cmdId_) { - case add: + case CmdId::add: ret = addMetadatum(pImage, cmd); if (rc == 0) rc = ret; break; - case set: + case CmdId::set: ret = setMetadatum(pImage, cmd); if (rc == 0) rc = ret; break; - case del: + case CmdId::del: delMetadatum(pImage, cmd); break; - case reg: + case CmdId::reg: regNamespace(cmd); break; - case invalidCmdId: + case CmdId::invalid: break; } } @@ -1184,13 +1184,13 @@ int Modify::addMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd) { auto value = Exiv2::Value::create(modifyCmd.typeId_); int rc = value->read(modifyCmd.value_); if (0 == rc) { - if (modifyCmd.metadataId_ == exif) { + if (modifyCmd.metadataId_ == MetadataId::exif) { exifData.add(Exiv2::ExifKey(modifyCmd.key_), value.get()); } - if (modifyCmd.metadataId_ == iptc) { + if (modifyCmd.metadataId_ == MetadataId::iptc) { iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get()); } - if (modifyCmd.metadataId_ == xmp) { + if (modifyCmd.metadataId_ == MetadataId::xmp) { xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get()); } } else { @@ -1213,19 +1213,19 @@ int Modify::setMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd) { Exiv2::IptcData& iptcData = pImage->iptcData(); Exiv2::XmpData& xmpData = pImage->xmpData(); Exiv2::Metadatum* metadatum = nullptr; - if (modifyCmd.metadataId_ == exif) { + if (modifyCmd.metadataId_ == MetadataId::exif) { auto pos = exifData.findKey(Exiv2::ExifKey(modifyCmd.key_)); if (pos != exifData.end()) { metadatum = &(*pos); } } - if (modifyCmd.metadataId_ == iptc) { + if (modifyCmd.metadataId_ == MetadataId::iptc) { auto pos = iptcData.findKey(Exiv2::IptcKey(modifyCmd.key_)); if (pos != iptcData.end()) { metadatum = &(*pos); } } - if (modifyCmd.metadataId_ == xmp) { + if (modifyCmd.metadataId_ == MetadataId::xmp) { auto pos = xmpData.findKey(Exiv2::XmpKey(modifyCmd.key_)); if (pos != xmpData.end()) { metadatum = &(*pos); @@ -1246,13 +1246,13 @@ int Modify::setMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd) { if (metadatum) { metadatum->setValue(value.get()); } else { - if (modifyCmd.metadataId_ == exif) { + if (modifyCmd.metadataId_ == MetadataId::exif) { exifData.add(Exiv2::ExifKey(modifyCmd.key_), value.get()); } - if (modifyCmd.metadataId_ == iptc) { + if (modifyCmd.metadataId_ == MetadataId::iptc) { iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get()); } - if (modifyCmd.metadataId_ == xmp) { + if (modifyCmd.metadataId_ == MetadataId::xmp) { xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get()); } } @@ -1273,21 +1273,21 @@ void Modify::delMetadatum(Exiv2::Image* pImage, const ModifyCmd& modifyCmd) { Exiv2::ExifData& exifData = pImage->exifData(); Exiv2::IptcData& iptcData = pImage->iptcData(); Exiv2::XmpData& xmpData = pImage->xmpData(); - if (modifyCmd.metadataId_ == exif) { + if (modifyCmd.metadataId_ == MetadataId::exif) { Exiv2::ExifData::iterator pos; const Exiv2::ExifKey exifKey(modifyCmd.key_); while ((pos = exifData.findKey(exifKey)) != exifData.end()) { exifData.erase(pos); } } - if (modifyCmd.metadataId_ == iptc) { + if (modifyCmd.metadataId_ == MetadataId::iptc) { Exiv2::IptcData::iterator pos; const Exiv2::IptcKey iptcKey(modifyCmd.key_); while ((pos = iptcData.findKey(iptcKey)) != iptcData.end()) { iptcData.erase(pos); } } - if (modifyCmd.metadataId_ == xmp) { + if (modifyCmd.metadataId_ == MetadataId::xmp) { Exiv2::XmpData::iterator pos; const Exiv2::XmpKey xmpKey(modifyCmd.key_); if ((pos = xmpData.findKey(xmpKey)) != xmpData.end()) { @@ -1617,7 +1617,7 @@ int str2Tm(const std::string& timeStr, struct tm* tm) { std::memset(tm, 0x0, sizeof(struct tm)); tm->tm_isdst = -1; - long tmp = 0; + int64_t tmp = 0; if (!Util::strtol(timeStr.substr(0, 4).c_str(), tmp)) return 5; // tmp is a 4-digit number so this cast cannot overflow @@ -1759,7 +1759,7 @@ int metacopy(const std::string& source, const std::string& tgt, Exiv2::ImageType } // #1148 use Raw XMP packet if there are no XMP modification commands - int tRawSidecar = Params::ctXmpSidecar | Params::ctXmpRaw; // option -eXX + Params::CommonTarget tRawSidecar = Params::ctXmpSidecar | Params::ctXmpRaw; // option -eXX if (Params::instance().modifyCmds_.empty() && (Params::instance().target_ & tRawSidecar) == tRawSidecar) { // std::cout << "short cut" << std::endl; // http://www.cplusplus.com/doc/tutorial/files/ diff --git a/app/actions.hpp b/app/actions.hpp index ec89ef85..1a701157 100644 --- a/app/actions.hpp +++ b/app/actions.hpp @@ -189,10 +189,10 @@ class Adjust : public Task { private: int adjustDateTime(Exiv2::ExifData& exifData, const std::string& key, const std::string& path) const; - long adjustment_{0}; - long yearAdjustment_{0}; - long monthAdjustment_{0}; - long dayAdjustment_{0}; + int64_t adjustment_{0}; + int64_t yearAdjustment_{0}; + int64_t monthAdjustment_{0}; + int64_t dayAdjustment_{0}; }; // class Adjust diff --git a/app/app_utils.cpp b/app/app_utils.cpp index cc28ece2..d36694b2 100644 --- a/app/app_utils.cpp +++ b/app/app_utils.cpp @@ -1,19 +1,26 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include "app_utils.hpp" #include #include +#include namespace Util { -bool strtol(const char* nptr, long& n) { +bool strtol(const char* nptr, int64_t& n) { if (!nptr || *nptr == '\0') return false; char* endptr = nullptr; - long tmp = std::strtol(nptr, &endptr, 10); + long long tmp = std::strtoll(nptr, &endptr, 10); if (*endptr != '\0') return false; - if (tmp == LONG_MAX || tmp == LONG_MIN) + // strtoll returns LLONG_MAX or LLONG_MIN if an overflow occurs. + if (tmp == LLONG_MAX || tmp == LLONG_MIN) return false; - n = tmp; + if (tmp < std::numeric_limits::min()) + return false; + if (tmp > std::numeric_limits::max()) + return false; + n = static_cast(tmp); return true; } diff --git a/app/app_utils.hpp b/app/app_utils.hpp index 90a6a792..731a71af 100644 --- a/app/app_utils.hpp +++ b/app/app_utils.hpp @@ -3,13 +3,15 @@ #ifndef APP_UTILS_HPP_ #define APP_UTILS_HPP_ +#include + namespace Util { /*! - @brief Convert a C string to a long value, which is returned in n. + @brief Convert a C string to an int64_t value, which is returned in n. Returns true if the conversion is successful, else false. n is not modified if the conversion is unsuccessful. See strtol(2). */ -bool strtol(const char* nptr, long& n); +bool strtol(const char* nptr, int64_t& n); } // namespace Util #endif // #ifndef UTILS_HPP_ diff --git a/app/exiv2.cpp b/app/exiv2.cpp index 7ff23c61..a81f2123 100644 --- a/app/exiv2.cpp +++ b/app/exiv2.cpp @@ -42,7 +42,11 @@ const Params::YodAdjust emptyYodAdjust_[] = { //! List of all command identifiers and corresponding strings const CmdIdAndString cmdIdAndString[] = { - {add, "add"}, {set, "set"}, {del, "del"}, {reg, "reg"}, {invalidCmdId, "invalidCmd"}, // End of list marker + {CmdId::add, "add"}, + {CmdId::set, "set"}, + {CmdId::del, "del"}, + {CmdId::reg, "reg"}, + {CmdId::invalid, "invalidCmd"}, // End of list marker }; // Return a command Id for a command string @@ -50,7 +54,7 @@ CmdId commandId(const std::string& cmdString); // Evaluate [-]HH[:MM[:SS]], returns true and sets time to the value // in seconds if successful, else returns false. -bool parseTime(const std::string& ts, long& time); +bool parseTime(const std::string& ts, int64_t& time); /*! @brief Parse the oparg string into a bitmap of common targets. @@ -58,7 +62,7 @@ bool parseTime(const std::string& ts, long& time); @param action Action being processed @return A bitmap of common targets or -1 in case of a parse error */ -int parseCommonTargets(const std::string& optArg, const std::string& action); +int64_t parseCommonTargets(const std::string& optArg, const std::string& action); /*! @brief Parse numbers separated by commas into container @@ -672,13 +676,13 @@ int Params::evalPrintFlags(const std::string& optArg) { for (auto&& i : optArg) { switch (i) { case 'E': - printTags_ |= Exiv2::mdExif; + printTags_ |= MetadataId::exif; break; case 'I': - printTags_ |= Exiv2::mdIptc; + printTags_ |= MetadataId::iptc; break; case 'X': - printTags_ |= Exiv2::mdXmp; + printTags_ |= MetadataId::xmp; break; case 'x': printItems_ |= prTag; @@ -735,81 +739,71 @@ int Params::evalPrintFlags(const std::string& optArg) { } // Params::evalPrintFlags int Params::evalDelete(const std::string& optArg) { - int rc = 0; switch (action_) { case Action::none: action_ = Action::erase; - target_ = 0; + target_ = CommonTarget(0); // fallthrough - case Action::erase: - rc = parseCommonTargets(optArg, "erase"); + case Action::erase: { + const auto rc = parseCommonTargets(optArg, "erase"); if (rc > 0) { - target_ |= rc; - rc = 0; + target_ |= CommonTarget(rc); + return 0; } else { - rc = 1; + return 1; } - break; + } default: std::cerr << progname() << ": " << _("Option -d is not compatible with a previous option\n"); - rc = 1; - break; + return 1; } - return rc; } // Params::evalDelete int Params::evalExtract(const std::string& optArg) { - int rc = 0; switch (action_) { case Action::none: case Action::modify: action_ = Action::extract; - target_ = 0; + target_ = CommonTarget(0); // fallthrough - case Action::extract: - rc = parseCommonTargets(optArg, "extract"); + case Action::extract: { + const auto rc = parseCommonTargets(optArg, "extract"); if (rc > 0) { - target_ |= rc; - rc = 0; + target_ |= CommonTarget(rc); + return 0; } else { - rc = 1; + return 1; } - break; + } default: std::cerr << progname() << ": " << _("Option -e is not compatible with a previous option\n"); - rc = 1; - break; + return 1; } - return rc; } // Params::evalExtract int Params::evalInsert(const std::string& optArg) { - int rc = 0; switch (action_) { case Action::none: case Action::modify: action_ = Action::insert; - target_ = 0; + target_ = CommonTarget(0); // fallthrough - case Action::insert: - rc = parseCommonTargets(optArg, "insert"); + case Action::insert: { + const auto rc = parseCommonTargets(optArg, "insert"); if (rc > 0) { - target_ |= rc; - rc = 0; + target_ |= CommonTarget(rc); + return 0; } else { - rc = 1; + return 1; } - break; + } default: std::cerr << progname() << ": " << _("Option -i is not compatible with a previous option\n"); - rc = 1; - break; + return 1; } - return rc; } // Params::evalInsert int Params::evalModify(int opt, const std::string& optArg) { - int rc = 0; switch (action_) { case Action::none: action_ = Action::modify; @@ -823,14 +817,12 @@ int Params::evalModify(int opt, const std::string& optArg) { cmdFiles_.push_back(optArg); // parse the files later if (opt == 'M') cmdLines_.push_back(optArg); // parse the commands later - break; + return 0; default: std::cerr << progname() << ": " << _("Option") << " -" << static_cast(opt) << " " << _("is not compatible with a previous option\n"); - rc = 1; - break; + return 1; } - return rc; } // Params::evalModify int Params::nonoption(const std::string& argv) { @@ -1090,7 +1082,7 @@ cleanup: // ***************************************************************************** // local implementations namespace { -bool parseTime(const std::string& ts, long& time) { +bool parseTime(const std::string& ts, int64_t& time) { std::string hstr, mstr, sstr; auto cts = new char[ts.length() + 1]; strcpy(cts, ts.c_str()); @@ -1106,7 +1098,7 @@ bool parseTime(const std::string& ts, long& time) { delete[] cts; int sign = 1; - long hh(0), mm(0), ss(0); + int64_t hh(0), mm(0), ss(0); // [-]HH part if (!Util::strtol(hstr.c_str(), hh)) return false; @@ -1145,11 +1137,11 @@ void printUnrecognizedArgument(const char argc, const std::string& action) { << argc << "'\n"; } -int parseCommonTargets(const std::string& optArg, const std::string& action) { - int rc = 0; - int target = 0; - int all = Params::ctExif | Params::ctIptc | Params::ctComment | Params::ctXmp; - int extra = Params::ctXmpSidecar | Params::ctExif | Params::ctIptc | Params::ctXmp; +int64_t parseCommonTargets(const std::string& optArg, const std::string& action) { + int64_t rc = 0; + Params::CommonTarget target = Params::CommonTarget(0); + Params::CommonTarget all = Params::ctExif | Params::ctIptc | Params::ctComment | Params::ctXmp; + Params::CommonTarget extra = Params::ctXmpSidecar | Params::ctExif | Params::ctIptc | Params::ctXmp; for (size_t i = 0; rc == 0 && i < optArg.size(); ++i) { switch (optArg[i]) { case 'e': @@ -1183,7 +1175,7 @@ int parseCommonTargets(const std::string& optArg, const std::string& action) { target |= extra; // -eX if (i > 0) { // -eXX or -iXX target |= Params::ctXmpRaw; - target &= ~extra; // turn off those bits + target = Params::CommonTarget(target & ~extra); // turn off those bits } break; @@ -1204,7 +1196,7 @@ int parseCommonTargets(const std::string& optArg, const std::string& action) { break; } } - return rc ? rc : target; + return rc ? rc : int64_t(target); } int parsePreviewNumbers(Params::PreviewNumbers& previewNumbers, const std::string& optArg, int j) { @@ -1334,38 +1326,38 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) { std::string cmd(line.substr(cmdStart, cmdEnd - cmdStart)); CmdId cmdId = commandId(cmd); - if (cmdId == invalidCmdId) { + if (cmdId == CmdId::invalid) { throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, Exiv2::toString(num) + ": " + _("Invalid command") + " `" + cmd + "'"); } Exiv2::TypeId defaultType = Exiv2::invalidTypeId; std::string key(line.substr(keyStart, keyEnd - keyStart)); - MetadataId metadataId = invalidMetadataId; - if (cmdId != reg) { + MetadataId metadataId = MetadataId::invalid; + if (cmdId != CmdId::reg) { try { Exiv2::IptcKey iptcKey(key); - metadataId = iptc; + metadataId = MetadataId::iptc; defaultType = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record()); } catch (const Exiv2::Error&) { } - if (metadataId == invalidMetadataId) { + if (metadataId == MetadataId::invalid) { try { Exiv2::ExifKey exifKey(key); - metadataId = exif; + metadataId = MetadataId::exif; defaultType = exifKey.defaultTypeId(); } catch (const Exiv2::Error&) { } } - if (metadataId == invalidMetadataId) { + if (metadataId == MetadataId::invalid) { try { Exiv2::XmpKey xmpKey(key); - metadataId = xmp; + metadataId = MetadataId::xmp; defaultType = Exiv2::XmpProperties::propertyType(xmpKey); } catch (const Exiv2::Error&) { } } - if (metadataId == invalidMetadataId) { + if (metadataId == MetadataId::invalid) { throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, Exiv2::toString(num) + ": " + _("Invalid key") + " `" + key + "'"); } @@ -1373,7 +1365,7 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) { std::string value; Exiv2::TypeId type = defaultType; bool explicitType = false; - if (cmdId != del) { + if (cmdId != CmdId::del) { // Get type and value std::string::size_type typeStart = std::string::npos; if (keyEnd != std::string::npos) @@ -1386,12 +1378,12 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) { if (valStart != std::string::npos) valEnd = line.find_last_not_of(delim); - if (cmdId == reg && (keyEnd == std::string::npos || valStart == std::string::npos)) { + if (cmdId == CmdId::reg && (keyEnd == std::string::npos || valStart == std::string::npos)) { throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, Exiv2::toString(num) + ": " + _("Invalid command line") + " "); } - if (cmdId != reg && typeStart != std::string::npos && typeEnd != std::string::npos) { + if (cmdId != CmdId::reg && typeStart != std::string::npos && typeEnd != std::string::npos) { std::string typeStr(line.substr(typeStart, typeEnd - typeStart)); Exiv2::TypeId tmpType = Exiv2::TypeInfo::typeId(typeStr); if (tmpType != Exiv2::invalidTypeId) { @@ -1421,7 +1413,7 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) { modifyCmd.explicitType_ = explicitType; modifyCmd.value_ = value; - if (cmdId == reg) { + if (cmdId == CmdId::reg) { if (value.empty()) { throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, Exiv2::toString(num) + ": " + _("Empty value for key") + +" `" + key + "'"); @@ -1437,7 +1429,7 @@ bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num) { CmdId commandId(const std::string& cmdString) { int i = 0; - while (cmdIdAndString[i].first != invalidCmdId && cmdIdAndString[i].second != cmdString) { + while (cmdIdAndString[i].first != CmdId::invalid && cmdIdAndString[i].second != cmdString) { ++i; } return cmdIdAndString[i].first; diff --git a/app/exiv2app.hpp b/app/exiv2app.hpp index 8921045b..cae67770 100644 --- a/app/exiv2app.hpp +++ b/app/exiv2app.hpp @@ -21,28 +21,40 @@ #include //! Command identifiers -enum CmdId { - invalidCmdId, +enum class CmdId { + invalid, add, set, del, reg, }; //! Metadata identifiers -enum MetadataId { - invalidMetadataId = Exiv2::mdNone, // 0 - exif = Exiv2::mdExif, // 1 - iptc = Exiv2::mdIptc, // 2 - xmp = Exiv2::mdXmp, // 8 +enum class MetadataId : uint32_t { + invalid = Exiv2::mdNone, // 0 + exif = Exiv2::mdExif, // 1 + iptc = Exiv2::mdIptc, // 2 + xmp = Exiv2::mdXmp, // 8 }; +inline MetadataId operator&(MetadataId x, MetadataId y) { + return (MetadataId)(uint32_t(x) & uint32_t(y)); +} + +inline MetadataId operator|(MetadataId x, MetadataId y) { + return (MetadataId)(uint32_t(x) | uint32_t(y)); +} + +inline MetadataId& operator|=(MetadataId& x, MetadataId y) { + return x = x | y; +} + //! Structure for one parsed modification command struct ModifyCmd { //! C'tor ModifyCmd() = default; - CmdId cmdId_{invalidCmdId}; //!< Command identifier + CmdId cmdId_{CmdId::invalid}; //!< Command identifier std::string key_; //!< Exiv2 key string - MetadataId metadataId_{invalidMetadataId}; //!< Metadata identifier + MetadataId metadataId_{MetadataId::invalid}; //!< Metadata identifier Exiv2::TypeId typeId_{Exiv2::invalidTypeId}; //!< Exiv2 type identifier //! Flag to indicate if the type was explicitly specified (true) bool explicitType_{false}; @@ -127,7 +139,7 @@ class Params : public Util::Getopt { }; //! Individual items to print, bitmap - enum PrintItem { + enum PrintItem : uint32_t { prTag = 1, prGroup = 2, prKey = 4, @@ -143,7 +155,7 @@ class Params : public Util::Getopt { }; //! Enumerates common targets, bitmap - enum CommonTarget { + enum CommonTarget : uint32_t { ctExif = 1, ctIptc = 2, ctComment = 4, @@ -175,7 +187,7 @@ class Params : public Util::Getopt { struct YodAdjust { bool flag_; //!< Adjustment flag. const char* option_; //!< Adjustment option string. - long adjustment_; //!< Adjustment value. + int64_t adjustment_; //!< Adjustment value. }; bool help_{false}; //!< Help option flag. @@ -190,13 +202,13 @@ class Params : public Util::Getopt { FileExistsPolicy fileExistsPolicy_{askPolicy}; //!< What to do if file to rename exists. bool adjust_{false}; //!< Adjustment flag. PrintMode printMode_{pmSummary}; //!< Print mode. - unsigned long printItems_{0}; //!< Print items. - unsigned long printTags_{Exiv2::mdNone}; //!< Print tags (bitmap of MetadataId flags). + PrintItem printItems_{0}; //!< Print items. + MetadataId printTags_{Exiv2::mdNone}; //!< Print tags (bitmap of MetadataId flags). //! %Action (integer rather than TaskType to avoid dependency). int action_{0}; - int target_; //!< What common target to process. + CommonTarget target_; //!< What common target to process. - long adjustment_{0}; //!< Adjustment in seconds. + int64_t adjustment_{0}; //!< Adjustment in seconds. YodAdjust yodAdjust_[3]; //!< Year, month and day adjustment info. std::string format_; //!< Filename format (-r option arg). bool formatSet_{false}; //!< Whether the format is set with -r @@ -272,4 +284,20 @@ class Params : public Util::Getopt { }; // class Params +inline Params::CommonTarget operator|(Params::CommonTarget x, Params::CommonTarget y) { + return (Params::CommonTarget)(uint32_t(x) | uint32_t(y)); +} + +inline Params::CommonTarget& operator|=(Params::CommonTarget& x, Params::CommonTarget y) { + return x = x | y; +} + +inline Params::PrintItem operator|(Params::PrintItem x, Params::PrintItem y) { + return (Params::PrintItem)(uint32_t(x) | uint32_t(y)); +} + +inline Params::PrintItem& operator|=(Params::PrintItem& x, Params::PrintItem y) { + return x = x | y; +} + #endif // #ifndef EXIV2APP_HPP_ diff --git a/tests/bugfixes/github/test_pr_2244.py b/tests/bugfixes/github/test_pr_2244.py new file mode 100644 index 00000000..07f34c55 --- /dev/null +++ b/tests/bugfixes/github/test_pr_2244.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, CopyTmpFiles, path +@CopyTmpFiles("$data_path/test_issue_1180.exv") + +class test_pr_2244(metaclass=CaseMeta): + + filename = path("$tmp_path/test_issue_1180.exv") + commands = [ "$exiv2 -Y 10000000000 $filename", + "$exiv2 -Y -10000000000 $filename", + "$exiv2 -O 10000000000 $filename", + "$exiv2 -O -10000000000 $filename", + "$exiv2 -D 1000000000000000 $filename", + "$exiv2 -D -1000000000000000 $filename" + ] + stdout = [ "", + "", + "", + "", + "", + "" + ] + stderr = [ "Uncaught exception: year adjustment too high\n", + "Uncaught exception: year adjustment too low\n", + "Uncaught exception: month adjustment too high\n", + "Uncaught exception: month adjustment too low\n", + "Uncaught exception: day adjustment too high\n", + "Uncaught exception: day adjustment too low\n" + ] + retval = [ 1, + 1, + 1, + 1, + 1, + 1 + ]