more SonarLint cleanups

Signed-off-by: Rosen Penev <rosenp@gmail.com>
main
Rosen Penev 2 years ago
parent d29001f2a4
commit 22b12012a6

@ -1092,7 +1092,9 @@ cleanup:
// local implementations // local implementations
namespace { namespace {
bool parseTime(const std::string& ts, int64_t& time) { bool parseTime(const std::string& ts, int64_t& time) {
std::string hstr, mstr, sstr; std::string hstr;
std::string mstr;
std::string sstr;
auto cts = new char[ts.length() + 1]; auto cts = new char[ts.length() + 1];
strcpy(cts, ts.c_str()); strcpy(cts, ts.c_str());
auto tmp = ::strtok(cts, ":"); auto tmp = ::strtok(cts, ":");
@ -1107,7 +1109,9 @@ bool parseTime(const std::string& ts, int64_t& time) {
delete[] cts; delete[] cts;
int sign = 1; int sign = 1;
int64_t hh(0), mm(0), ss(0); int64_t hh = 0;
int64_t mm = 0;
int64_t ss = 0;
// [-]HH part // [-]HH part
if (!Util::strtol(hstr.c_str(), hh)) if (!Util::strtol(hstr.c_str(), hh))
return false; return false;

@ -177,7 +177,7 @@ class EXIV2API IptcData {
@return 0 if successful;<BR> @return 0 if successful;<BR>
6 if the dataset already exists and is not repeatable 6 if the dataset already exists and is not repeatable
*/ */
int add(const IptcKey& key, Value* value); int add(const IptcKey& key, const Value* value);
/*! /*!
@brief Add a copy of the Iptcdatum to the IPTC metadata. A check @brief Add a copy of the Iptcdatum to the IPTC metadata. A check
for non-repeatable datasets is performed. for non-repeatable datasets is performed.
@ -244,7 +244,7 @@ class EXIV2API IptcData {
[[nodiscard]] const_iterator findId(uint16_t dataset, uint16_t record = IptcDataSets::application2) const; [[nodiscard]] const_iterator findId(uint16_t dataset, uint16_t record = IptcDataSets::application2) const;
//! Return true if there is no IPTC metadata //! Return true if there is no IPTC metadata
[[nodiscard]] bool empty() const { [[nodiscard]] bool empty() const {
return count() == 0; return iptcMetadata_.empty();
} }
//! Get the number of metadata entries //! Get the number of metadata entries

@ -200,7 +200,8 @@ class EXIV2API QuickTimeVideo : public Image {
//! Variable to check the end of metadata traversing. //! Variable to check the end of metadata traversing.
bool continueTraversing_ = false; bool continueTraversing_ = false;
//! Variable to store height and width of a video frame. //! Variable to store height and width of a video frame.
uint64_t height_ = 0, width_ = 0; uint64_t height_ = 0;
uint64_t width_ = 0;
}; // QuickTimeVideo End }; // QuickTimeVideo End

@ -48,7 +48,7 @@ class EXIV2API RiffVideo : public Image {
uint64_t size_ = 0; uint64_t size_ = 0;
public: public:
explicit HeaderReader(BasicIo::UniquePtr& io); explicit HeaderReader(const BasicIo::UniquePtr& io);
[[nodiscard]] uint64_t getSize() const { [[nodiscard]] uint64_t getSize() const {
return size_; return size_;
@ -59,9 +59,9 @@ class EXIV2API RiffVideo : public Image {
} }
}; };
void readList(HeaderReader& header_); void readList(const HeaderReader& header_);
void readChunk(HeaderReader& header_); void readChunk(const HeaderReader& header_);
void decodeBlocks(); void decodeBlocks();

@ -48,7 +48,8 @@ struct SliceBase {
* lower and upper bounds of the slice with respect to the * lower and upper bounds of the slice with respect to the
* container/array stored in storage_ * container/array stored in storage_
*/ */
const size_t begin_, end_; size_t begin_;
size_t end_;
}; };
/*! /*!
@ -260,10 +261,13 @@ struct MutableSliceBase : public ConstSliceBase<storage_type, data_type> {
template <typename container> template <typename container>
struct ContainerStorage { struct ContainerStorage {
using iterator = typename container::iterator; using iterator = typename container::iterator;
using const_iterator = typename container::const_iterator; using const_iterator = typename container::const_iterator;
#if __cplusplus >= 201402L || _MSVC_LANG >= 201402L
using value_type = std::remove_cv_t<typename container::value_type>;
#else
using value_type = typename std::remove_cv<typename container::value_type>::type; using value_type = typename std::remove_cv<typename container::value_type>::type;
#endif
/*! /*!
* @throw std::out_of_range when end is larger than the container's * @throw std::out_of_range when end is larger than the container's
@ -324,7 +328,11 @@ struct ContainerStorage {
*/ */
template <typename storage_type> template <typename storage_type>
struct PtrSliceStorage { struct PtrSliceStorage {
#if __cplusplus >= 201402L || _MSVC_LANG >= 201402L
using value_type = std::remove_cv_t<std::remove_pointer_t<storage_type>>;
#else
using value_type = typename std::remove_cv<typename std::remove_pointer<storage_type>::type>::type; using value_type = typename std::remove_cv<typename std::remove_pointer<storage_type>::type>::type;
#endif
using iterator = value_type*; using iterator = value_type*;
using const_iterator = const value_type*; using const_iterator = const value_type*;
@ -423,7 +431,11 @@ struct Slice : public Internal::MutableSliceBase<Internal::ContainerStorage, con
using const_iterator = typename container::const_iterator; using const_iterator = typename container::const_iterator;
#if __cplusplus >= 201402L || _MSVC_LANG >= 201402L
using value_type = std::remove_cv_t<typename container::value_type>;
#else
using value_type = typename std::remove_cv<typename container::value_type>::type; using value_type = typename std::remove_cv<typename container::value_type>::type;
#endif
/*! /*!
* @brief Construct a slice of the container `cont` starting at `begin` * @brief Construct a slice of the container `cont` starting at `begin`
@ -476,7 +488,11 @@ struct Slice<const container> : public Internal::ConstSliceBase<Internal::Contai
using const_iterator = typename container::const_iterator; using const_iterator = typename container::const_iterator;
#if __cplusplus >= 201402L || _MSVC_LANG >= 201402L
using value_type = std::remove_cv_t<typename container::value_type>;
#else
using value_type = typename std::remove_cv<typename container::value_type>::type; using value_type = typename std::remove_cv<typename container::value_type>::type;
#endif
Slice(const container& cont, size_t begin, size_t end) : Slice(const container& cont, size_t begin, size_t end) :
Internal::ConstSliceBase<Internal::ContainerStorage, const container>(cont, begin, end) { Internal::ConstSliceBase<Internal::ContainerStorage, const container>(cont, begin, end) {

@ -1502,9 +1502,8 @@ template <typename T>
int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) { int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder) {
value_.clear(); value_.clear();
size_t ts = TypeInfo::typeSize(typeId()); size_t ts = TypeInfo::typeSize(typeId());
if (ts > 0) if (ts > 0 && len % ts != 0)
if (len % ts != 0) len = (len / ts) * ts;
len = (len / ts) * ts;
for (size_t i = 0; i < len; i += ts) { for (size_t i = 0; i < len; i += ts) {
value_.push_back(getValue<T>(buf + i, byteOrder)); value_.push_back(getValue<T>(buf + i, byteOrder));
} }

@ -362,22 +362,22 @@ void AsfVideo::DegradableJPEGMedia() {
void AsfVideo::streamProperties() { void AsfVideo::streamProperties() {
DataBuf streamTypedBuf = io_->read(GUID); DataBuf streamTypedBuf = io_->read(GUID);
enum streamTypeInfo { Audio = 1, Video = 2 }; enum class streamTypeInfo { Audio = 1, Video = 2 };
int stream = 0; auto stream = static_cast<streamTypeInfo>(0);
auto tag_stream_type = GUIDReferenceTags.find(GUIDTag(streamTypedBuf.data())); auto tag_stream_type = GUIDReferenceTags.find(GUIDTag(streamTypedBuf.data()));
if (tag_stream_type != GUIDReferenceTags.end()) { if (tag_stream_type != GUIDReferenceTags.end()) {
if (tag_stream_type->second == "Audio_Media") if (tag_stream_type->second == "Audio_Media")
stream = Audio; stream = streamTypeInfo::Audio;
else if (tag_stream_type->second == "Video_Media") else if (tag_stream_type->second == "Video_Media")
stream = Video; stream = streamTypeInfo::Video;
io_->seek(io_->tell() + GUID, BasicIo::beg); // ignore Error Correction Type io_->seek(io_->tell() + GUID, BasicIo::beg); // ignore Error Correction Type
uint64_t time_offset = readQWORDTag(io_); uint64_t time_offset = readQWORDTag(io_);
if (stream == Video) if (stream == streamTypeInfo::Video)
xmpData()["Xmp.video.TimeOffset"] = time_offset; xmpData()["Xmp.video.TimeOffset"] = time_offset;
else if (stream == Audio) else if (stream == streamTypeInfo::Audio)
xmpData()["Xmp.audio.TimeOffset"] = time_offset; xmpData()["Xmp.audio.TimeOffset"] = time_offset;
auto specific_data_length = readDWORDTag(io_); auto specific_data_length = readDWORDTag(io_);
@ -396,12 +396,10 @@ void AsfVideo::codecList() {
uint16_t codec_type = readWORDTag(io_) * 2; uint16_t codec_type = readWORDTag(io_) * 2;
std::string codec = (codec_type == 1) ? "Xmp.video" : "Xmp.audio"; std::string codec = (codec_type == 1) ? "Xmp.video" : "Xmp.audio";
uint16_t codec_name_length = readWORDTag(io_) * 2; if (uint16_t codec_name_length = readWORDTag(io_) * 2)
if (codec_name_length)
xmpData()[codec + std::string(".CodecName")] = readStringWcharTag(io_, codec_name_length); xmpData()[codec + std::string(".CodecName")] = readStringWcharTag(io_, codec_name_length);
uint16_t codec_desc_length = readWORDTag(io_); if (uint16_t codec_desc_length = readWORDTag(io_))
if (codec_desc_length)
xmpData()[codec + std::string(".CodecDescription")] = readStringWcharTag(io_, codec_desc_length); xmpData()[codec + std::string(".CodecDescription")] = readStringWcharTag(io_, codec_desc_length);
uint16_t codec_info_length = readWORDTag(io_); uint16_t codec_info_length = readWORDTag(io_);
@ -422,13 +420,11 @@ void AsfVideo::extendedContentDescription() {
std::string value; std::string value;
for (uint16_t i = 0; i < content_descriptor_count; i++) { for (uint16_t i = 0; i < content_descriptor_count; i++) {
uint16_t descriptor_name_length = readWORDTag(io_); if (uint16_t descriptor_name_length = readWORDTag(io_))
if (descriptor_name_length)
value += readStringWcharTag(io_, descriptor_name_length); // Descriptor Name value += readStringWcharTag(io_, descriptor_name_length); // Descriptor Name
uint16_t descriptor_value_data_type = readWORDTag(io_); uint16_t descriptor_value_data_type = readWORDTag(io_);
uint16_t descriptor_value_length = readWORDTag(io_); if (uint16_t descriptor_value_length = readWORDTag(io_)) {
if (descriptor_value_length) {
// Descriptor Value // Descriptor Value
switch (descriptor_value_data_type) { switch (descriptor_value_data_type) {
case 0 /*Unicode string */: case 0 /*Unicode string */:
@ -448,7 +444,6 @@ void AsfVideo::extendedContentDescription() {
break; break;
case 5 /*WORD*/: case 5 /*WORD*/:
value += std::string(": ") + std::to_string(readWORDTag(io_)); value += std::string(": ") + std::to_string(readWORDTag(io_));
;
break; break;
} }
} }

@ -159,7 +159,11 @@ int FileIo::Impl::switchMode(OpMode opMode) {
} }
// Reopen the file // Reopen the file
long offset = std::ftell(fp_); #ifdef _WIN32
auto offset = _ftelli64(fp_);
#else
auto offset = ftello(fp_);
#endif
if (offset == -1) if (offset == -1)
return -1; return -1;
// 'Manual' open("r+b") to avoid munmap() // 'Manual' open("r+b") to avoid munmap()
@ -172,7 +176,11 @@ int FileIo::Impl::switchMode(OpMode opMode) {
fp_ = std::fopen(path_.c_str(), openMode_.c_str()); fp_ = std::fopen(path_.c_str(), openMode_.c_str());
if (!fp_) if (!fp_)
return 1; return 1;
return std::fseek(fp_, offset, SEEK_SET); #ifdef _WIN32
return _fseeki64(fp_, offset, SEEK_SET);
#else
return fseeko(fp_, offset, SEEK_SET);
#endif
} // FileIo::Impl::switchMode } // FileIo::Impl::switchMode
int FileIo::Impl::stat(StructStat& buf) const { int FileIo::Impl::stat(StructStat& buf) const {
@ -460,15 +468,19 @@ int FileIo::seek(int64_t offset, Position pos) {
if (p_->switchMode(Impl::opSeek) != 0) if (p_->switchMode(Impl::opSeek) != 0)
return 1; return 1;
#ifdef _WIN64 #ifdef _WIN32
return _fseeki64(p_->fp_, offset, fileSeek); return _fseeki64(p_->fp_, offset, fileSeek);
#else #else
return std::fseek(p_->fp_, static_cast<long>(offset), fileSeek); return fseeko(p_->fp_, offset, fileSeek);
#endif #endif
} }
size_t FileIo::tell() const { size_t FileIo::tell() const {
const long pos = std::ftell(p_->fp_); #ifdef _WIN32
auto pos = _ftelli64(p_->fp_);
#else
auto pos = ftello(p_->fp_);
#endif
Internal::enforce(pos >= 0, ErrorCode::kerInputDataReadFailed); Internal::enforce(pos >= 0, ErrorCode::kerInputDataReadFailed);
return static_cast<size_t>(pos); return static_cast<size_t>(pos);
} }
@ -1069,7 +1081,8 @@ size_t RemoteIo::Impl::populateBlocks(size_t lowBlock, size_t highBlock) {
throw Error(ErrorCode::kerErrorMessage, "Data By Range is empty. Please check the permission."); throw Error(ErrorCode::kerErrorMessage, "Data By Range is empty. Please check the permission.");
} }
auto source = reinterpret_cast<byte*>(const_cast<char*>(data.c_str())); auto source = reinterpret_cast<byte*>(const_cast<char*>(data.c_str()));
size_t remain = rcount, totalRead = 0; size_t remain = rcount;
size_t totalRead = 0;
size_t iBlock = (rcount == size_) ? 0 : lowBlock; size_t iBlock = (rcount == size_) ? 0 : lowBlock;
while (remain) { while (remain) {
@ -1109,7 +1122,9 @@ int RemoteIo::open() {
p_->blocksMap_ = new BlockMap[nBlocks]; p_->blocksMap_ = new BlockMap[nBlocks];
p_->isMalloced_ = true; p_->isMalloced_ = true;
auto source = reinterpret_cast<byte*>(const_cast<char*>(data.c_str())); auto source = reinterpret_cast<byte*>(const_cast<char*>(data.c_str()));
size_t remain = p_->size_, iBlock = 0, totalRead = 0; size_t remain = p_->size_;
size_t iBlock = 0;
size_t totalRead = 0;
while (remain) { while (remain) {
auto allow = std::min<size_t>(remain, p_->blockSize_); auto allow = std::min<size_t>(remain, p_->blockSize_);
p_->blocksMap_[iBlock].populate(&source[totalRead], allow); p_->blocksMap_[iBlock].populate(&source[totalRead], allow);
@ -1465,8 +1480,7 @@ void HttpIo::HttpImpl::writeRemote(const byte* data, size_t size, size_t from, s
} }
// standardize the path without "/" at the beginning. // standardize the path without "/" at the beginning.
std::size_t protocolIndex = scriptPath.find("://"); if (scriptPath.find("://") == std::string::npos && scriptPath.front() != '/') {
if (protocolIndex == std::string::npos && scriptPath.front() != '/') {
scriptPath = "/" + scriptPath; scriptPath = "/" + scriptPath;
} }
@ -1651,8 +1665,7 @@ void CurlIo::CurlImpl::writeRemote(const byte* data, size_t size, size_t from, s
Exiv2::Uri hostInfo = Exiv2::Uri::Parse(path_); Exiv2::Uri hostInfo = Exiv2::Uri::Parse(path_);
// add the protocol and host to the path // add the protocol and host to the path
std::size_t protocolIndex = scriptPath.find("://"); if (scriptPath.find("://") == std::string::npos) {
if (protocolIndex == std::string::npos) {
if (scriptPath.front() != '/') if (scriptPath.front() != '/')
scriptPath = "/" + scriptPath; scriptPath = "/" + scriptPath;
scriptPath = hostInfo.Protocol + "://" + hostInfo.Host + scriptPath; scriptPath = hostInfo.Protocol + "://" + hostInfo.Host + scriptPath;

@ -137,18 +137,16 @@ std::string BmffImage::mimeType() const {
uint32_t BmffImage::pixelWidth() const { uint32_t BmffImage::pixelWidth() const {
auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension")); auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
if (imageWidth != exifData_.end() && imageWidth->count() > 0) { if (imageWidth == exifData_.end() || imageWidth->count() == 0)
return imageWidth->toUint32(); return pixelWidth_;
} return imageWidth->toUint32();
return pixelWidth_;
} }
uint32_t BmffImage::pixelHeight() const { uint32_t BmffImage::pixelHeight() const {
auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension")); auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
if (imageHeight != exifData_.end() && imageHeight->count() > 0) { if (imageHeight == exifData_.end() || imageHeight->count() == 0)
return imageHeight->toUint32(); return pixelHeight_;
} return imageHeight->toUint32();
return pixelHeight_;
} }
std::string BmffImage::uuidName(const Exiv2::DataBuf& uuid) { std::string BmffImage::uuidName(const Exiv2::DataBuf& uuid) {
@ -254,13 +252,13 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
size_t hdrsize = sizeof(hdrbuf); size_t hdrsize = sizeof(hdrbuf);
Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
if (io_->read(reinterpret_cast<byte*>(&hdrbuf), sizeof(hdrbuf)) != sizeof(hdrbuf)) if (io_->read(hdrbuf, sizeof(hdrbuf)) != sizeof(hdrbuf))
return pbox_end; return pbox_end;
// The box length is encoded as a uint32_t by default, but the special value 1 means // The box length is encoded as a uint32_t by default, but the special value 1 means
// that it's a uint64_t. // that it's a uint64_t.
uint64_t box_length = getULong(reinterpret_cast<byte*>(&hdrbuf[0]), endian_); uint64_t box_length = getULong(&hdrbuf[0], endian_);
uint32_t box_type = getULong(reinterpret_cast<byte*>(&hdrbuf[sizeof(uint32_t)]), endian_); uint32_t box_type = getULong(&hdrbuf[sizeof(uint32_t)], endian_);
bool bLF = true; bool bLF = true;
if (bTrace) { if (bTrace) {

@ -274,8 +274,8 @@ class Converter {
// DATA // DATA
static const Conversion conversion_[]; //<! Conversion rules static const Conversion conversion_[]; //<! Conversion rules
bool erase_; bool erase_{false};
bool overwrite_; bool overwrite_{true};
ExifData* exifData_; ExifData* exifData_;
IptcData* iptcData_; IptcData* iptcData_;
XmpData* xmpData_; XmpData* xmpData_;
@ -489,21 +489,11 @@ const Converter::Conversion Converter::conversion_[] = {
}; };
Converter::Converter(ExifData& exifData, XmpData& xmpData) : Converter::Converter(ExifData& exifData, XmpData& xmpData) :
erase_(false), exifData_(&exifData), iptcData_(nullptr), xmpData_(&xmpData), iptcCharset_(nullptr) {
overwrite_(true),
exifData_(&exifData),
iptcData_(nullptr),
xmpData_(&xmpData),
iptcCharset_(nullptr) {
} }
Converter::Converter(IptcData& iptcData, XmpData& xmpData, const char* iptcCharset) : Converter::Converter(IptcData& iptcData, XmpData& xmpData, const char* iptcCharset) :
erase_(false), exifData_(nullptr), iptcData_(&iptcData), xmpData_(&xmpData), iptcCharset_(iptcCharset) {
overwrite_(true),
exifData_(nullptr),
iptcData_(&iptcData),
xmpData_(&xmpData),
iptcCharset_(iptcCharset) {
} }
void Converter::cnvToXmp() { void Converter::cnvToXmp() {
@ -626,7 +616,12 @@ void Converter::cnvExifDate(const char* from, const char* to) {
return; return;
if (!prepareXmpTarget(to)) if (!prepareXmpTarget(to))
return; return;
int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int min = 0;
int sec = 0;
std::string subsec; std::string subsec;
char buf[30]; char buf[30];
@ -935,9 +930,8 @@ void Converter::cnvXmpDate(const char* from, const char* to) {
if (std::string(to) != "Exif.GPSInfo.GPSTimeStamp") { if (std::string(to) != "Exif.GPSInfo.GPSTimeStamp") {
SXMPUtils::ConvertToLocalTime(&datetime); SXMPUtils::ConvertToLocalTime(&datetime);
snprintf(buf, sizeof(buf), "%4d:%02d:%02d %02d:%02d:%02d", static_cast<int>(datetime.year), snprintf(buf, sizeof(buf), "%4d:%02d:%02d %02d:%02d:%02d", datetime.year, datetime.month, datetime.day,
static_cast<int>(datetime.month), static_cast<int>(datetime.day), static_cast<int>(datetime.hour), datetime.hour, datetime.minute, datetime.second);
static_cast<int>(datetime.minute), static_cast<int>(datetime.second));
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
(*exifData_)[to] = buf; (*exifData_)[to] = buf;
@ -978,8 +972,7 @@ void Converter::cnvXmpDate(const char* from, const char* to) {
(*exifData_)[to] = array.str(); (*exifData_)[to] = array.str();
prepareExifTarget("Exif.GPSInfo.GPSDateStamp", true); prepareExifTarget("Exif.GPSInfo.GPSDateStamp", true);
snprintf(buf, sizeof(buf), "%4d:%02d:%02d", static_cast<int>(datetime.year), static_cast<int>(datetime.month), snprintf(buf, sizeof(buf), "%4d:%02d:%02d", datetime.year, datetime.month, datetime.day);
static_cast<int>(datetime.day));
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
(*exifData_)["Exif.GPSInfo.GPSDateStamp"] = buf; (*exifData_)["Exif.GPSInfo.GPSDateStamp"] = buf;
} }

@ -22,7 +22,7 @@ class RotationMap {
private: private:
//! Helper structure for the mapping list //! Helper structure for the mapping list
using OmList = struct { struct OmList {
uint16_t orientation; uint16_t orientation;
int32_t degrees; int32_t degrees;
}; };

@ -20,7 +20,7 @@ namespace Exiv2::Internal {
class CiffHeader; class CiffHeader;
class CiffComponent; class CiffComponent;
struct CrwMapping; struct CrwMapping;
using CrwSubDir = struct { struct CrwSubDir {
uint16_t dir; uint16_t dir;
uint16_t parent; uint16_t parent;
}; };
@ -287,19 +287,7 @@ class CiffComponent {
a CRW (Canon Raw data) image. a CRW (Canon Raw data) image.
*/ */
class CiffEntry : public CiffComponent { class CiffEntry : public CiffComponent {
public: using CiffComponent::CiffComponent;
//! @name Creators
//@{
//! Default constructor
CiffEntry() = default;
//! Constructor taking a tag and directory
CiffEntry(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {
}
//@}
// Default assignment operator is fine
private:
//! @name Manipulators //! @name Manipulators
//@{ //@{
using CiffComponent::doAdd; using CiffComponent::doAdd;
@ -322,15 +310,11 @@ class CiffEntry : public CiffComponent {
//! This class models a CIFF directory of a CRW (Canon Raw data) image. //! This class models a CIFF directory of a CRW (Canon Raw data) image.
class CiffDirectory : public CiffComponent { class CiffDirectory : public CiffComponent {
using CiffComponent::CiffComponent;
public: public:
//! @name Creators //! @name Creators
//@{ //@{
//! Default constructor
CiffDirectory() = default;
//! Constructor taking a tag and directory
CiffDirectory(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {
}
//! Virtual destructor //! Virtual destructor
~CiffDirectory() override; ~CiffDirectory() override;
//@} //@}

@ -609,8 +609,7 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
switch (ptt) { switch (ptt) {
case pttLen: { case pttLen: {
delTags = false; delTags = false;
auto pos = ed.findKey(ExifKey(key)); if (auto pos = ed.findKey(ExifKey(key)); pos != ed.end() && sumToLong(*pos) > 32768) {
if (pos != ed.end() && sumToLong(*pos) > 32768) {
delTags = true; delTags = true;
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n"; EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
@ -621,8 +620,7 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
} }
case pttTag: { case pttTag: {
if (delTags) { if (delTags) {
auto pos = ed.findKey(ExifKey(key)); if (auto pos = ed.findKey(ExifKey(key)); pos != ed.end()) {
if (pos != ed.end()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n"; EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
#endif #endif

@ -105,7 +105,8 @@ std::string urlencode(const std::string& str) {
} }
void urldecode(std::string& str) { void urldecode(std::string& str) {
size_t idxIn{0}, idxOut{0}; size_t idxIn{0};
size_t idxOut{0};
size_t sizeStr = str.size(); size_t sizeStr = str.size();
while (idxIn < sizeStr) { while (idxIn < sizeStr) {
if (str[idxIn] == '%') { if (str[idxIn] == '%') {
@ -234,9 +235,8 @@ std::string strError() {
#ifdef EXV_HAVE_STRERROR_R #ifdef EXV_HAVE_STRERROR_R
const size_t n = 1024; const size_t n = 1024;
#ifdef EXV_STRERROR_R_CHAR_P #ifdef EXV_STRERROR_R_CHAR_P
char* buf = nullptr;
char buf2[n] = {}; char buf2[n] = {};
buf = strerror_r(error, buf2, n); auto buf = strerror_r(error, buf2, n);
#else #else
char buf[n] = {}; char buf[n] = {};
const int ret = strerror_r(error, buf, n); const int ret = strerror_r(error, buf, n);

@ -28,25 +28,25 @@ std::string utf16ToUtf8(const std::wstring& wstr) {
return str; return str;
} }
uint64_t readQWORDTag(BasicIo::UniquePtr& io) { uint64_t readQWORDTag(const BasicIo::UniquePtr& io) {
Internal::enforce(QWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(QWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(QWORD); DataBuf FieldBuf = io->read(QWORD);
return FieldBuf.read_uint64(0, littleEndian); return FieldBuf.read_uint64(0, littleEndian);
} }
uint32_t readDWORDTag(BasicIo::UniquePtr& io) { uint32_t readDWORDTag(const BasicIo::UniquePtr& io) {
Internal::enforce(DWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(DWORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(DWORD); DataBuf FieldBuf = io->read(DWORD);
return FieldBuf.read_uint32(0, littleEndian); return FieldBuf.read_uint32(0, littleEndian);
} }
uint16_t readWORDTag(BasicIo::UniquePtr& io) { uint16_t readWORDTag(const BasicIo::UniquePtr& io) {
Internal::enforce(WORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(WORD <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf = io->read(WORD); DataBuf FieldBuf = io->read(WORD);
return FieldBuf.read_uint16(0, littleEndian); return FieldBuf.read_uint16(0, littleEndian);
} }
std::string readStringWcharTag(BasicIo::UniquePtr& io, size_t length) { std::string readStringWcharTag(const BasicIo::UniquePtr& io, size_t length) {
Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf(length + 1); DataBuf FieldBuf(length + 1);
io->readOrThrow(FieldBuf.data(), length, ErrorCode::kerFailedToReadImageData); io->readOrThrow(FieldBuf.data(), length, ErrorCode::kerFailedToReadImageData);
@ -54,7 +54,7 @@ std::string readStringWcharTag(BasicIo::UniquePtr& io, size_t length) {
return utf16ToUtf8(wst); return utf16ToUtf8(wst);
} }
std::string readStringTag(BasicIo::UniquePtr& io, size_t length) { std::string readStringTag(const BasicIo::UniquePtr& io, size_t length) {
Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(length <= io->size() - io->tell(), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf FieldBuf(length + 1); DataBuf FieldBuf(length + 1);
io->readOrThrow(FieldBuf.data(), length, ErrorCode::kerFailedToReadImageData); io->readOrThrow(FieldBuf.data(), length, ErrorCode::kerFailedToReadImageData);

@ -43,15 +43,15 @@ static constexpr size_t GUID = 0x10;
*/ */
std::string utf16ToUtf8(const std::wstring& wstr); std::string utf16ToUtf8(const std::wstring& wstr);
[[nodiscard]] uint64_t readQWORDTag(Exiv2::BasicIo::UniquePtr& io); [[nodiscard]] uint64_t readQWORDTag(const Exiv2::BasicIo::UniquePtr& io);
[[nodiscard]] uint32_t readDWORDTag(Exiv2::BasicIo::UniquePtr& io); [[nodiscard]] uint32_t readDWORDTag(const Exiv2::BasicIo::UniquePtr& io);
[[nodiscard]] uint16_t readWORDTag(Exiv2::BasicIo::UniquePtr& io); [[nodiscard]] uint16_t readWORDTag(const Exiv2::BasicIo::UniquePtr& io);
[[nodiscard]] std::string readStringWcharTag(Exiv2::BasicIo::UniquePtr& io, size_t length); [[nodiscard]] std::string readStringWcharTag(const Exiv2::BasicIo::UniquePtr& io, size_t length);
[[nodiscard]] std::string readStringTag(Exiv2::BasicIo::UniquePtr& io, size_t length = DWORD); [[nodiscard]] std::string readStringTag(const Exiv2::BasicIo::UniquePtr& io, size_t length = DWORD);
/*! /*!
@brief Calculates Aspect Ratio of a video @brief Calculates Aspect Ratio of a video

@ -76,9 +76,7 @@ static int forgive(int n, int& err) {
if (n == 0) if (n == 0)
return FINISH; // server hungup return FINISH; // server hungup
#endif #endif
bool bForgive = err == WSAEWOULDBLOCK || err == WSAENOTCONN; if (n == SOCKET_ERROR && (err == WSAEWOULDBLOCK || err == WSAENOTCONN))
bool bError = n == SOCKET_ERROR;
if (bError && bForgive)
return 0; return 0;
return n; return n;
} }

@ -231,7 +231,7 @@ size_t IptcData::size() const {
return newSize; return newSize;
} }
int IptcData::add(const IptcKey& key, Value* value) { int IptcData::add(const IptcKey& key, const Value* value) {
return add(Iptcdatum(key, value)); return add(Iptcdatum(key, value));
} }
@ -439,8 +439,7 @@ DataBuf IptcParser::encode(const IptcData& iptcData) {
*pWrite++ = static_cast<byte>(iter.tag()); *pWrite++ = static_cast<byte>(iter.tag());
// extended or standard dataset? // extended or standard dataset?
size_t dataSize = iter.size(); if (size_t dataSize = iter.size(); dataSize > 32767) {
if (dataSize > 32767) {
// always use 4 bytes for extended length // always use 4 bytes for extended length
uint16_t sizeOfSize = 4 | 0x8000; uint16_t sizeOfSize = 4 | 0x8000;
us2Data(pWrite, sizeOfSize, bigEndian); us2Data(pWrite, sizeOfSize, bigEndian);

@ -353,8 +353,7 @@ void Jp2Image::readMetadata() {
throw Error(ErrorCode::kerInputDataReadFailed); throw Error(ErrorCode::kerInputDataReadFailed);
xmpPacket_.assign(rawData.c_str(), rawData.size()); xmpPacket_.assign(rawData.c_str(), rawData.size());
std::string::size_type idx = xmpPacket_.find_first_of('<'); if (auto idx = xmpPacket_.find_first_of('<'); idx != std::string::npos && idx > 0) {
if (idx != std::string::npos && idx > 0) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Removing " << static_cast<uint32_t>(idx) EXV_WARNING << "Removing " << static_cast<uint32_t>(idx)
<< " characters from the beginning of the XMP packet" << std::endl; << " characters from the beginning of the XMP packet" << std::endl;

@ -719,8 +719,7 @@ void JpegBase::doWriteMetadata(BasicIo& outIo) {
} }
const byte* pExifData = rawExif.c_data(); const byte* pExifData = rawExif.c_data();
size_t exifSize = rawExif.size(); size_t exifSize = rawExif.size();
WriteMethod wm = ExifParser::encode(blob, pExifData, exifSize, bo, exifData_); if (ExifParser::encode(blob, pExifData, exifSize, bo, exifData_) == wmIntrusive) {
if (wm == wmIntrusive) {
pExifData = !blob.empty() ? blob.data() : nullptr; pExifData = !blob.empty() ? blob.data() : nullptr;
exifSize = blob.size(); exifSize = blob.size();
} }

@ -150,8 +150,7 @@ TiffComponent* TiffMnCreator::create(uint16_t tag, IfdId group, const std::strin
} // TiffMnCreator::create } // TiffMnCreator::create
TiffComponent* TiffMnCreator::create(uint16_t tag, IfdId group, IfdId mnGroup) { TiffComponent* TiffMnCreator::create(uint16_t tag, IfdId group, IfdId mnGroup) {
auto tmr = Exiv2::find(registry_, mnGroup); if (auto tmr = Exiv2::find(registry_, mnGroup)) {
if (tmr) {
if (tmr->newMnFct2_) { if (tmr->newMnFct2_) {
return tmr->newMnFct2_(tag, group, mnGroup); return tmr->newMnFct2_(tag, group, mnGroup);
} }
@ -1055,7 +1054,7 @@ const Exiv2::Value* getExifValue(Exiv2::Internal::TiffComponent* pRoot, const ui
std::string getExifModel(Exiv2::Internal::TiffComponent* pRoot) { std::string getExifModel(Exiv2::Internal::TiffComponent* pRoot) {
// Lookup the Exif.Image.Model tag // Lookup the Exif.Image.Model tag
const auto value = getExifValue(pRoot, 0x0110, Exiv2::IfdId::ifd0Id); const auto value = getExifValue(pRoot, 0x0110, Exiv2::IfdId::ifd0Id);
return (!value || value->count() == 0) ? std::string("") : static_cast<std::string>(value->toString()); return (!value || value->count() == 0) ? std::string() : value->toString();
} }
void ncrypt(Exiv2::byte* pData, uint32_t size, uint32_t count, uint32_t serial) { void ncrypt(Exiv2::byte* pData, uint32_t size, uint32_t count, uint32_t serial) {

@ -1465,7 +1465,8 @@ static std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") {
// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c // https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
static std::vector<std::string> split(const std::string& str, const std::string& delim) { static std::vector<std::string> split(const std::string& str, const std::string& delim) {
std::vector<std::string> tokens; std::vector<std::string> tokens;
size_t prev = 0, pos = 0; size_t prev = 0;
size_t pos = 0;
do { do {
pos = str.find(delim, prev); pos = str.find(delim, prev);
if (pos == std::string::npos) if (pos == std::string::npos)

@ -3809,12 +3809,11 @@ std::ostream& Nikon3MakerNote::printLensId4ZMount(std::ostream& os, const Value&
} }
// from https://github.com/exiftool/exiftool/blob/12.44/lib/Image/ExifTool/Nikon.pm#L4969 // from https://github.com/exiftool/exiftool/blob/12.44/lib/Image/ExifTool/Nikon.pm#L4969
using lens = struct { static constexpr struct lens {
uint16_t l; uint16_t l;
const char* vendor; const char* vendor;
const char* name; const char* name;
}; } zmountlens[] = {
static constexpr lens zmountlens[] = {
{1, "Nikon", "Nikkor Z 24-70mm f/4 S"}, {1, "Nikon", "Nikkor Z 24-70mm f/4 S"},
{2, "Nikon", "Nikkor Z 14-30mm f/4 S"}, {2, "Nikon", "Nikkor Z 14-30mm f/4 S"},
{4, "Nikon", "Nikkor Z 35mm f/1.8 S"}, {4, "Nikon", "Nikkor Z 35mm f/1.8 S"},

@ -1426,7 +1426,7 @@ std::ostream& OlympusMakerNote::printEq0x0301(std::ostream& os, const Value& val
//! OlympusCs FocusMode, tag 0x0301 //! OlympusCs FocusMode, tag 0x0301
// (1 or 2 values) // (1 or 2 values)
std::ostream& OlympusMakerNote::printCs0x0301(std::ostream& os, const Value& value, const ExifData*) { std::ostream& OlympusMakerNote::printCs0x0301(std::ostream& os, const Value& value, const ExifData*) {
using mode = struct { struct mode {
uint16_t tag; uint16_t tag;
const char* name; const char* name;
}; };
@ -1538,20 +1538,18 @@ std::ostream& OlympusMakerNote::print0x0305(std::ostream& os, const Value& value
// Olympus FocusInfo tag 0x0308 AFPoint // Olympus FocusInfo tag 0x0308 AFPoint
std::ostream& OlympusMakerNote::print0x0308(std::ostream& os, const Value& value, const ExifData* metadata) { std::ostream& OlympusMakerNote::print0x0308(std::ostream& os, const Value& value, const ExifData* metadata) {
using point = struct { static constexpr struct point {
uint16_t p; uint16_t p;
const char* name; const char* name;
}; } afPoints[] = {
static constexpr point afPoints[] = {
{0, N_("Left (or n/a)")}, {1, N_("Center (horizontal)")}, {2, N_("Right")}, {3, N_("Center (vertical)")}, {0, N_("Left (or n/a)")}, {1, N_("Center (horizontal)")}, {2, N_("Right")}, {3, N_("Center (vertical)")},
{255, N_("None")}, {255, N_("None")},
}; };
using pointE3 = struct { static constexpr struct pointE3 {
byte p; byte p;
const char* name; const char* name;
}; } afPointsE3[] = {
static constexpr pointE3 afPointsE3[] = {
{0x00, N_("None")}, {0x00, N_("None")},
{0x01, N_("Top-left (horizontal)")}, {0x01, N_("Top-left (horizontal)")},
{0x02, N_("Top-center (horizontal)")}, {0x02, N_("Top-center (horizontal)")},

@ -964,9 +964,7 @@ std::ostream& PentaxMakerNote::printFlashCompensation(std::ostream& os, const Va
} }
std::ostream& PentaxMakerNote::printBracketing(std::ostream& os, const Value& value, const ExifData*) { std::ostream& PentaxMakerNote::printBracketing(std::ostream& os, const Value& value, const ExifData*) {
const auto l0 = value.toUint32(0); if (auto l0 = value.toUint32(0); l0 < 10) {
if (l0 < 10) {
os << std::setprecision(2) << static_cast<float>(l0) / 3 << " EV"; os << std::setprecision(2) << static_cast<float>(l0) / 3 << " EV";
} else { } else {
os << std::setprecision(2) << static_cast<float>(l0) - 9.5F << " EV"; os << std::setprecision(2) << static_cast<float>(l0) - 9.5F << " EV";

@ -70,8 +70,7 @@ std::ostream& printCombiTag(std::ostream& os, const Value& value, const ExifData
} }
l += (value.toUint32(c) << ((count - c - 1) * 8)); l += (value.toUint32(c) << ((count - c - 1) * 8));
} }
auto td = Exiv2::find(array, l); if (auto td = Exiv2::find(array, l)) {
if (td) {
os << exvGettext(td->label_); os << exvGettext(td->label_);
} else { } else {
os << exvGettext("Unknown") << " (0x" << std::setw(2 * count) << std::setfill('0') << std::hex << l << std::dec os << exvGettext("Unknown") << " (0x" << std::setw(2 * count) << std::setfill('0') << std::hex << l << std::dec

@ -149,7 +149,8 @@ void PgfImage::doWriteMetadata(BasicIo& outIo) {
readPgfHeaderSize(*io_); readPgfHeaderSize(*io_);
uint32_t w = 0, h = 0; uint32_t w = 0;
uint32_t h = 0;
DataBuf header = readPgfHeaderStructure(*io_, w, h); DataBuf header = readPgfHeaderStructure(*io_, w, h);
auto img = ImageFactory::create(ImageType::png); auto img = ImageFactory::create(ImageType::png);
@ -268,9 +269,8 @@ DataBuf PgfImage::readPgfHeaderStructure(BasicIo& iIo, uint32_t& width, uint32_t
byte bpp = buffer.pData_[10]; byte bpp = buffer.pData_[10];
byte channels = buffer.pData_[11]; byte channels = buffer.pData_[11];
*/ */
byte mode = header.read_uint8(12);
if (mode == 2) // Indexed color image. We pass color table (256 * 3 bytes). if (header.read_uint8(12) == 2) // Indexed color image. We pass color table (256 * 3 bytes).
{ {
header.alloc(16 + 256 * 3); header.alloc(16 + 256 * 3);

@ -136,8 +136,7 @@ DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const Iptc
} }
// Write new iptc record if we have it // Write new iptc record if we have it
DataBuf rawIptc = IptcParser::encode(iptcData); if (DataBuf rawIptc = IptcParser::encode(iptcData); !rawIptc.empty()) {
if (!rawIptc.empty()) {
std::array<byte, 12> tmpBuf; std::array<byte, 12> tmpBuf;
std::copy_n(Photoshop::irbId_.front(), 4, tmpBuf.data()); std::copy_n(Photoshop::irbId_.front(), 4, tmpBuf.data());
us2Data(tmpBuf.data() + 4, iptc_, bigEndian); us2Data(tmpBuf.data() + 4, iptc_, bigEndian);

@ -91,8 +91,7 @@ DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkTyp
// Extract a deflate compressed Latin-1 text chunk // Extract a deflate compressed Latin-1 text chunk
// we get the compression method after the key // we get the compression method after the key
const byte* compressionMethod = data.c_data(keysize + 1); if (*data.c_data(keysize + 1) != 0x00) {
if (*compressionMethod != 0x00) {
// then it isn't zlib compressed and we are sunk // then it isn't zlib compressed and we are sunk
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard zTXt compression method.\n"; std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard zTXt compression method.\n";
@ -271,8 +270,7 @@ void PngChunk::parseChunkContent(Image* pImage, const byte* key, size_t keySize,
if (length > 0) { if (length > 0) {
std::string& xmpPacket = pImage->xmpPacket(); std::string& xmpPacket = pImage->xmpPacket();
xmpPacket.assign(xmpBuf.c_str(), length); xmpPacket.assign(xmpBuf.c_str(), length);
std::string::size_type idx = xmpPacket.find_first_of('<'); if (auto idx = xmpPacket.find_first_of('<'); idx != std::string::npos && idx > 0) {
if (idx != std::string::npos && idx > 0) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Removing " << idx << " characters from the beginning of the XMP packet\n"; EXV_WARNING << "Removing " << idx << " characters from the beginning of the XMP packet\n";
#endif #endif
@ -291,8 +289,7 @@ void PngChunk::parseChunkContent(Image* pImage, const byte* key, size_t keySize,
if (keySize >= 17 && memcmp("XML:com.adobe.xmp", key, 17) == 0 && pImage->xmpData().empty() && !arr.empty()) { if (keySize >= 17 && memcmp("XML:com.adobe.xmp", key, 17) == 0 && pImage->xmpData().empty() && !arr.empty()) {
std::string& xmpPacket = pImage->xmpPacket(); std::string& xmpPacket = pImage->xmpPacket();
xmpPacket.assign(arr.c_str(), arr.size()); xmpPacket.assign(arr.c_str(), arr.size());
std::string::size_type idx = xmpPacket.find_first_of('<'); if (auto idx = xmpPacket.find_first_of('<'); idx != std::string::npos && idx > 0) {
if (idx != std::string::npos && idx > 0) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Removing " << idx << " characters " EXV_WARNING << "Removing " << idx << " characters "
<< "from the beginning of the XMP packet\n"; << "from the beginning of the XMP packet\n";

@ -408,8 +408,7 @@ void PngImage::readMetadata() {
// Decode chunk data length. // Decode chunk data length.
uint32_t chunkLength = cheaderBuf.read_uint32(0, Exiv2::bigEndian); uint32_t chunkLength = cheaderBuf.read_uint32(0, Exiv2::bigEndian);
const size_t pos = io_->tell(); if (chunkLength > imgSize - io_->tell()) {
if (chunkLength > imgSize - pos) {
throw Exiv2::Error(ErrorCode::kerFailedToReadImageData); throw Exiv2::Error(ErrorCode::kerFailedToReadImageData);
} }

@ -342,12 +342,7 @@ Loader::Loader(PreviewId id, const Image& image) : id_(id), image_(image) {
} }
PreviewProperties Loader::getProperties() const { PreviewProperties Loader::getProperties() const {
PreviewProperties prop; return {"", "", size_, width_, height_, id_};
prop.id_ = id_;
prop.size_ = size_;
prop.width_ = width_;
prop.height_ = height_;
return prop;
} }
PreviewId Loader::getNumLoaders() { PreviewId Loader::getNumLoaders() {
@ -548,8 +543,7 @@ bool LoaderExifJpeg::readDimensions() {
LoaderExifDataJpeg::LoaderExifDataJpeg(PreviewId id, const Image& image, int parIdx) : LoaderExifDataJpeg::LoaderExifDataJpeg(PreviewId id, const Image& image, int parIdx) :
Loader(id, image), dataKey_(param_[parIdx].dataKey_) { Loader(id, image), dataKey_(param_[parIdx].dataKey_) {
auto pos = image_.exifData().findKey(dataKey_); if (auto pos = image_.exifData().findKey(dataKey_); pos != image_.exifData().end()) {
if (pos != image_.exifData().end()) {
size_ = pos->sizeDataArea(); // indirect data size_ = pos->sizeDataArea(); // indirect data
if (size_ == 0 && pos->typeId() == undefined) if (size_ == 0 && pos->typeId() == undefined)
size_ = pos->size(); // direct data size_ = pos->size(); // direct data
@ -576,8 +570,7 @@ DataBuf LoaderExifDataJpeg::getData() const {
if (!valid()) if (!valid())
return {}; return {};
auto pos = image_.exifData().findKey(dataKey_); if (auto pos = image_.exifData().findKey(dataKey_); pos != image_.exifData().end()) {
if (pos != image_.exifData().end()) {
DataBuf buf = pos->dataArea(); // indirect data DataBuf buf = pos->dataArea(); // indirect data
if (buf.empty()) { // direct data if (buf.empty()) { // direct data
@ -706,7 +699,7 @@ DataBuf LoaderTiff::getData() const {
} }
} }
Value& dataValue = const_cast<Value&>(preview["Exif.Image." + offsetTag_].value()); auto& dataValue = const_cast<Value&>(preview["Exif.Image." + offsetTag_].value());
if (dataValue.sizeDataArea() == 0) { if (dataValue.sizeDataArea() == 0) {
// image data are not available via exifData, read them from image_.io() // image data are not available via exifData, read them from image_.io()
@ -868,7 +861,7 @@ DataBuf decodeBase64(const std::string& src) {
// calculate dest size // calculate dest size
auto validSrcSize = static_cast<unsigned long>( auto validSrcSize = static_cast<unsigned long>(
std::count_if(src.begin(), src.end(), [=](unsigned char c) { return decodeBase64Table.at(c) != invalid; })); std::count_if(src.begin(), src.end(), [&](unsigned char c) { return decodeBase64Table.at(c) != invalid; }));
if (validSrcSize > ULONG_MAX / 3) if (validSrcSize > ULONG_MAX / 3)
return {}; // avoid integer overflow return {}; // avoid integer overflow
const unsigned long destSize = (validSrcSize * 3) / 4; const unsigned long destSize = (validSrcSize * 3) / 4;
@ -936,8 +929,7 @@ DataBuf decodeAi7Thumbnail(const DataBuf& src) {
} }
DataBuf makePnm(size_t width, size_t height, const DataBuf& rgb) { DataBuf makePnm(size_t width, size_t height, const DataBuf& rgb) {
const size_t expectedSize = width * height * 3UL; if (size_t expectedSize = width * height * 3UL; rgb.size() != expectedSize) {
if (rgb.size() != expectedSize) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Invalid size of preview data. Expected " << expectedSize << " bytes, got " << rgb.size() EXV_WARNING << "Invalid size of preview data. Expected " << expectedSize << " bytes, got " << rgb.size()
<< " bytes.\n"; << " bytes.\n";

@ -4939,8 +4939,7 @@ void XmpProperties::registerNs(const std::string& ns, const std::string& prefix)
if (ns2.back() != '/' && ns2.back() != '#') if (ns2.back() != '/' && ns2.back() != '#')
ns2 += '/'; ns2 += '/';
// Check if there is already a registered namespace with this prefix // Check if there is already a registered namespace with this prefix
const XmpNsInfo* xnp = lookupNsRegistryUnsafe(XmpNsInfo::Prefix{prefix}); if (auto xnp = lookupNsRegistryUnsafe(XmpNsInfo::Prefix{prefix})) {
if (xnp) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
if (ns2 != xnp->ns_) if (ns2 != xnp->ns_)
EXV_WARNING << "Updating namespace URI for " << prefix << " from " << xnp->ns_ << " to " << ns2 << "\n"; EXV_WARNING << "Updating namespace URI for " << prefix << " from " << xnp->ns_ << " to " << ns2 << "\n";
@ -5006,8 +5005,7 @@ std::string XmpProperties::prefix(const std::string& ns) {
std::string XmpProperties::ns(const std::string& prefix) { std::string XmpProperties::ns(const std::string& prefix) {
auto scoped_read_lock = std::scoped_lock(mutex_); auto scoped_read_lock = std::scoped_lock(mutex_);
const XmpNsInfo* xn = lookupNsRegistryUnsafe(XmpNsInfo::Prefix{prefix}); if (auto xn = lookupNsRegistryUnsafe(XmpNsInfo::Prefix{prefix}))
if (xn)
return xn->ns_; return xn->ns_;
return nsInfoUnsafe(prefix)->ns_; return nsInfoUnsafe(prefix)->ns_;
} }
@ -5031,8 +5029,7 @@ const XmpPropertyInfo* XmpProperties::propertyInfo(const XmpKey& key) {
std::string prefix = key.groupName(); std::string prefix = key.groupName();
std::string property = key.tagName(); std::string property = key.tagName();
// If property is a path for a nested property, determines the innermost element // If property is a path for a nested property, determines the innermost element
std::string::size_type i = property.find_last_of('/'); if (auto i = property.find_last_of('/'); i != std::string::npos) {
if (i != std::string::npos) {
for (; i != std::string::npos && !isalpha(property.at(i)); ++i) { for (; i != std::string::npos && !isalpha(property.at(i)); ++i) {
} }
property = property.substr(i); property = property.substr(i);
@ -5212,8 +5209,7 @@ void XmpKey::Impl::decomposeKey(const std::string& key) {
std::string::size_type pos1 = key.find('.'); std::string::size_type pos1 = key.find('.');
if (pos1 == std::string::npos) if (pos1 == std::string::npos)
throw Error(ErrorCode::kerInvalidKey, key); throw Error(ErrorCode::kerInvalidKey, key);
std::string familyName = key.substr(0, pos1); if (key.substr(0, pos1) != familyName_)
if (familyName != familyName_)
throw Error(ErrorCode::kerInvalidKey, key); throw Error(ErrorCode::kerInvalidKey, key);
std::string::size_type pos0 = pos1 + 1; std::string::size_type pos0 = pos1 + 1;
pos1 = key.find('.', pos0); pos1 = key.find('.', pos0);

@ -157,8 +157,7 @@ void PsdImage::readMetadata() {
} }
// skip it // skip it
uint32_t colorDataLength = getULong(buf, bigEndian); if (io_->seek(getULong(buf, bigEndian), BasicIo::cur)) {
if (io_->seek(colorDataLength, BasicIo::cur)) {
throw Error(ErrorCode::kerNotAnImage, "Photoshop"); throw Error(ErrorCode::kerNotAnImage, "Photoshop");
} }
@ -547,7 +546,7 @@ uint32_t PsdImage::writeIptcData(const IptcData& iptcData, BasicIo& out) {
uint32_t resLength = 0; uint32_t resLength = 0;
byte buf[8]; byte buf[8];
if (iptcData.count() > 0) { if (!iptcData.empty()) {
DataBuf rawIptc = IptcParser::encode(iptcData); DataBuf rawIptc = IptcParser::encode(iptcData);
if (!rawIptc.empty()) { if (!rawIptc.empty()) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES

@ -599,11 +599,9 @@ void QuickTimeVideo::decodeBlock(std::string const& entered_from) {
hdrsize += 8; hdrsize += 8;
io_->readOrThrow(data.data(), data.size()); io_->readOrThrow(data.data(), data.size());
size = data.read_uint64(0, bigEndian); size = data.read_uint64(0, bigEndian);
} else if (size == 0) { } else if (size == 0 && entered_from == "meta") {
if (entered_from == "meta") { size = buf.read_uint32(0, bigEndian);
size = buf.read_uint32(0, bigEndian); io_->readOrThrow(buf.data(), 4, Exiv2::ErrorCode::kerCorruptedMetadata);
io_->readOrThrow(buf.data(), 4, Exiv2::ErrorCode::kerCorruptedMetadata);
}
} }
enforce(size >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata); enforce(size >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata);
@ -745,7 +743,8 @@ void QuickTimeVideo::keysTagDecoder(size_t size) {
} // QuickTimeVideo::keysTagDecoder } // QuickTimeVideo::keysTagDecoder
void QuickTimeVideo::trackApertureTagDecoder(size_t size) { void QuickTimeVideo::trackApertureTagDecoder(size_t size) {
DataBuf buf(4), buf2(2); DataBuf buf(4);
DataBuf buf2(2);
size_t cur_pos = io_->tell(); size_t cur_pos = io_->tell();
byte n = 3; byte n = 3;
@ -794,7 +793,8 @@ void QuickTimeVideo::trackApertureTagDecoder(size_t size) {
void QuickTimeVideo::CameraTagsDecoder(size_t size_external) { void QuickTimeVideo::CameraTagsDecoder(size_t size_external) {
size_t cur_pos = io_->tell(); size_t cur_pos = io_->tell();
DataBuf buf(50), buf2(4); DataBuf buf(50);
DataBuf buf2(4);
const TagDetails* td; const TagDetails* td;
io_->readOrThrow(buf.data(), 4); io_->readOrThrow(buf.data(), 4);
@ -839,7 +839,8 @@ void QuickTimeVideo::CameraTagsDecoder(size_t size_external) {
void QuickTimeVideo::userDataDecoder(size_t size_external) { void QuickTimeVideo::userDataDecoder(size_t size_external) {
size_t cur_pos = io_->tell(); size_t cur_pos = io_->tell();
const TagVocabulary* td; const TagVocabulary* td;
const TagVocabulary *tv, *tv_internal; const TagVocabulary* tv;
const TagVocabulary* tv_internal;
const long bufMinSize = 100; const long bufMinSize = 100;
DataBuf buf(bufMinSize); DataBuf buf(bufMinSize);
@ -905,10 +906,13 @@ void QuickTimeVideo::userDataDecoder(size_t size_external) {
void QuickTimeVideo::NikonTagsDecoder(size_t size_external) { void QuickTimeVideo::NikonTagsDecoder(size_t size_external) {
size_t cur_pos = io_->tell(); size_t cur_pos = io_->tell();
DataBuf buf(200), buf2(4 + 1); DataBuf buf(200);
DataBuf buf2(4 + 1);
uint32_t TagID = 0; uint32_t TagID = 0;
uint16_t dataLength = 0, dataType = 2; uint16_t dataLength = 0;
const TagDetails *td, *td2; uint16_t dataType = 2;
const TagDetails* td;
const TagDetails* td2;
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
io_->readOrThrow(buf.data(), 4); io_->readOrThrow(buf.data(), 4);
@ -1140,7 +1144,8 @@ void QuickTimeVideo::timeToSampleDecoder() {
DataBuf buf(4 + 1); DataBuf buf(4 + 1);
io_->readOrThrow(buf.data(), 4); io_->readOrThrow(buf.data(), 4);
io_->readOrThrow(buf.data(), 4); io_->readOrThrow(buf.data(), 4);
uint64_t totalframes = 0, timeOfFrames = 0; uint64_t totalframes = 0;
uint64_t timeOfFrames = 0;
const uint32_t noOfEntries = buf.read_uint32(0, bigEndian); const uint32_t noOfEntries = buf.read_uint32(0, bigEndian);
for (uint32_t i = 0; i < noOfEntries; i++) { for (uint32_t i = 0; i < noOfEntries; i++) {
@ -1604,8 +1609,7 @@ bool isQTimeType(BasicIo& iIo, bool advance) {
// we only match if we actually know the video type. This is done // we only match if we actually know the video type. This is done
// to avoid matching just on ftyp because bmffimage also has that // to avoid matching just on ftyp because bmffimage also has that
// header. // header.
auto td = Exiv2::find(qTimeFileType, std::string{buf.c_str(8), 4}); if (Exiv2::find(qTimeFileType, std::string{buf.c_str(8), 4})) {
if (td) {
matched = true; matched = true;
} }
break; break;

@ -28,18 +28,16 @@ std::string RafImage::mimeType() const {
uint32_t RafImage::pixelWidth() const { uint32_t RafImage::pixelWidth() const {
auto widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension")); auto widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
if (widthIter != exifData_.end() && widthIter->count() > 0) { if (widthIter == exifData_.end() || widthIter->count() == 0)
return widthIter->toUint32(); return 0;
} return widthIter->toUint32();
return 0;
} }
uint32_t RafImage::pixelHeight() const { uint32_t RafImage::pixelHeight() const {
auto heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension")); auto heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
if (heightIter != exifData_.end() && heightIter->count() > 0) { if (heightIter == exifData_.end() || heightIter->count() == 0)
return heightIter->toUint32(); return 0;
} return heightIter->toUint32();
return 0;
} }
void RafImage::setExifData(const ExifData& /*exifData*/) { void RafImage::setExifData(const ExifData& /*exifData*/) {
@ -72,7 +70,7 @@ void RafImage::printStructure(std::ostream& out, PrintStructureOption option, si
if (bPrint) { if (bPrint) {
io_->seek(0, BasicIo::beg); // rewind io_->seek(0, BasicIo::beg); // rewind
size_t address = io_->tell(); size_t address = io_->tell();
const char* format = " %8d | %8d | "; const auto format = " %8d | %8d | ";
{ {
out << Internal::indent(depth) << "STRUCTURE OF RAF FILE: " << io().path() << std::endl; out << Internal::indent(depth) << "STRUCTURE OF RAF FILE: " << io().path() << std::endl;

@ -389,7 +389,7 @@ void RiffVideo::readMetadata() {
decodeBlocks(); decodeBlocks();
} // RiffVideo::readMetadata } // RiffVideo::readMetadata
RiffVideo::HeaderReader::HeaderReader(BasicIo::UniquePtr& io) { RiffVideo::HeaderReader::HeaderReader(const BasicIo::UniquePtr& io) {
Internal::enforce(io->size() > io->tell() + DWORD + DWORD, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(io->size() > io->tell() + DWORD + DWORD, Exiv2::ErrorCode::kerCorruptedMetadata);
id_ = readStringTag(io); id_ = readStringTag(io);
size_ = readDWORDTag(io); size_ = readDWORDTag(io);
@ -402,7 +402,7 @@ bool RiffVideo::equal(const std::string& str1, const std::string& str2) {
return Internal::upper(str1) == str2; return Internal::upper(str1) == str2;
} }
void RiffVideo::readList(HeaderReader& header_) { void RiffVideo::readList(const HeaderReader& header_) {
std::string chunk_type = readStringTag(io_); std::string chunk_type = readStringTag(io_);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
@ -417,7 +417,7 @@ void RiffVideo::readList(HeaderReader& header_) {
} }
} }
void RiffVideo::readChunk(HeaderReader& header_) { void RiffVideo::readChunk(const HeaderReader& header_) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
if (header_.getSize()) if (header_.getSize())
EXV_INFO << "--> Reading Chunk : [" << header_.getId() << "] size= " << header_.getSize() << "(" << io_->tell() EXV_INFO << "--> Reading Chunk : [" << header_.getId() << "] size= " << header_.getSize() << "(" << io_->tell()
@ -457,8 +457,7 @@ void RiffVideo::readChunk(HeaderReader& header_) {
void RiffVideo::decodeBlocks() { void RiffVideo::decodeBlocks() {
do { do {
HeaderReader header(io_); if (HeaderReader header(io_); equal(header.getId(), CHUNK_ID_LIST)) {
if (equal(header.getId(), CHUNK_ID_LIST)) {
readList(header); readList(header);
} else { } else {
readChunk(header); readChunk(header);
@ -611,24 +610,20 @@ void RiffVideo::readStreamFormat(uint64_t size_) {
xmpData_["Xmp.video.ImageLength"] = readDWORDTag(io_); xmpData_["Xmp.video.ImageLength"] = readDWORDTag(io_);
xmpData_["Xmp.video.PixelPerMeterX"] = readQWORDTag(io_); xmpData_["Xmp.video.PixelPerMeterX"] = readQWORDTag(io_);
xmpData_["Xmp.video.PixelPerMeterY"] = readQWORDTag(io_); xmpData_["Xmp.video.PixelPerMeterY"] = readQWORDTag(io_);
uint32_t NumOfColours = readDWORDTag(io_); if (uint32_t NumOfColours = readDWORDTag(io_))
if (NumOfColours == 0)
xmpData_["Xmp.video.NumOfColours"] = "Unspecified";
else
xmpData_["Xmp.video.NumOfColours"] = NumOfColours; xmpData_["Xmp.video.NumOfColours"] = NumOfColours;
uint32_t NumIfImpColours = readDWORDTag(io_);
if (NumIfImpColours == 0)
xmpData_["Xmp.video.NumIfImpColours"] = "All";
else else
xmpData_["Xmp.video.NumOfColours"] = "Unspecified";
if (uint32_t NumIfImpColours = readDWORDTag(io_))
xmpData_["Xmp.video.NumIfImpColours"] = NumIfImpColours; xmpData_["Xmp.video.NumIfImpColours"] = NumIfImpColours;
else
xmpData_["Xmp.video.NumIfImpColours"] = "All";
} else if (streamType_ == Audio) { } else if (streamType_ == Audio) {
uint16_t format_tag = readWORDTag(io_); uint16_t format_tag = readWORDTag(io_);
auto it = Internal::audioEncodingValues.find(format_tag); if (auto it = Internal::audioEncodingValues.find(format_tag); it != Internal::audioEncodingValues.end())
if (it != Internal::audioEncodingValues.end()) {
xmpData_["Xmp.audio.Compressor"] = it->second; xmpData_["Xmp.audio.Compressor"] = it->second;
} else { else
xmpData_["Xmp.audio.Compressor"] = format_tag; xmpData_["Xmp.audio.Compressor"] = format_tag;
}
xmpData_["Xmp.audio.ChannelType"] = getStreamType(readDWORDTag(io_)); xmpData_["Xmp.audio.ChannelType"] = getStreamType(readDWORDTag(io_));
xmpData_["Xmp.audio.SampleRate"] = readDWORDTag(io_); // nSamplesPerSec xmpData_["Xmp.audio.SampleRate"] = readDWORDTag(io_); // nSamplesPerSec
@ -657,10 +652,8 @@ void RiffVideo::readInfoListChunk(uint64_t size_) {
std::string type = readStringTag(io_); std::string type = readStringTag(io_);
size_t size = readDWORDTag(io_); size_t size = readDWORDTag(io_);
std::string content = readStringTag(io_, size); std::string content = readStringTag(io_, size);
auto it = Internal::infoTags.find(type); if (auto it = Internal::infoTags.find(type); it != Internal::infoTags.end())
if (it != Internal::infoTags.end()) {
xmpData_[it->second] = content; xmpData_[it->second] = content;
}
current_size += DWORD * 2 + size; current_size += DWORD * 2 + size;
} }
} }

@ -32,18 +32,16 @@ std::string Rw2Image::mimeType() const {
uint32_t Rw2Image::pixelWidth() const { uint32_t Rw2Image::pixelWidth() const {
auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorWidth")); auto imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorWidth"));
if (imageWidth != exifData_.end() && imageWidth->count() > 0) { if (imageWidth == exifData_.end() || imageWidth->count() == 0)
return imageWidth->toUint32(); return 0;
} return imageWidth->toUint32();
return 0;
} }
uint32_t Rw2Image::pixelHeight() const { uint32_t Rw2Image::pixelHeight() const {
auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorHeight")); auto imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorHeight"));
if (imageHeight != exifData_.end() && imageHeight->count() > 0) { if (imageHeight == exifData_.end() || imageHeight->count() == 0)
return imageHeight->toUint32(); return 0;
} return imageHeight->toUint32();
return 0;
} }
void Rw2Image::setExifData(const ExifData& /*exifData*/) { void Rw2Image::setExifData(const ExifData& /*exifData*/) {

@ -54,8 +54,7 @@ static std::ostream& printFocalLength35(std::ostream& os, const Value& value, co
if (value.count() != 1 || value.typeId() != unsignedLong) { if (value.count() != 1 || value.typeId() != unsignedLong) {
return os << value; return os << value;
} }
const auto length = value.toInt64(); if (auto length = value.toInt64(); length == 0) {
if (length == 0) {
os << _("Unknown"); os << _("Unknown");
} else { } else {
std::ostringstream oss; std::ostringstream oss;

@ -73,8 +73,7 @@ const TagInfo* SigmaMakerNote::tagList() {
std::ostream& SigmaMakerNote::printStripLabel(std::ostream& os, const Value& value, const ExifData*) { std::ostream& SigmaMakerNote::printStripLabel(std::ostream& os, const Value& value, const ExifData*) {
std::string v = value.toString(); std::string v = value.toString();
std::string::size_type pos = v.find(':'); if (auto pos = v.find(':'); pos != std::string::npos) {
if (pos != std::string::npos) {
if (v.at(pos + 1) == ' ') if (v.at(pos + 1) == ' ')
++pos; ++pos;
v = v.substr(pos + 1); v = v.substr(pos + 1);

@ -1036,8 +1036,8 @@ std::ostream& SonyMakerNote::printWBShiftABGMPrecise(std::ostream& os, const Val
} }
std::ios::fmtflags f(os.flags()); std::ios::fmtflags f(os.flags());
const auto temp0 = static_cast<double>(value.toInt64(0)) / (1000.0); const auto temp0 = static_cast<double>(value.toInt64(0)) / 1000.0;
const auto temp1 = static_cast<double>(value.toInt64(1)) / (1000.0); const auto temp1 = static_cast<double>(value.toInt64(1)) / 1000.0;
os << "A/B: "; os << "A/B: ";
if (temp0 == 0) { if (temp0 == 0) {

@ -3013,12 +3013,10 @@ std::ostream& print0xa404(std::ostream& os, const Value& value, const ExifData*)
} }
std::ostream& print0xa405(std::ostream& os, const Value& value, const ExifData*) { std::ostream& print0xa405(std::ostream& os, const Value& value, const ExifData*) {
const auto length = value.toInt64(); if (auto length = value.toInt64(); length == 0)
if (length == 0) {
os << _("Unknown"); os << _("Unknown");
} else { else
os << length << ".0 mm"; os << length << ".0 mm";
}
return os; return os;
} }

@ -89,8 +89,7 @@ struct TagVocabulary {
*/ */
template <size_t N, const StringTagDetails (&array)[N]> template <size_t N, const StringTagDetails (&array)[N]>
std::ostream& printTagString(std::ostream& os, const std::string& value, const ExifData*) { std::ostream& printTagString(std::ostream& os, const std::string& value, const ExifData*) {
auto td = Exiv2::find(array, value); if (auto td = Exiv2::find(array, value)) {
if (td) {
os << exvGettext(td->label_); os << exvGettext(td->label_);
} else { } else {
os << "(" << value << ")"; os << "(" << value << ")";
@ -146,8 +145,7 @@ std::ostream& printTagString4(std::ostream& os, const Value& value, const ExifDa
*/ */
template <size_t N, const TagDetails (&array)[N]> template <size_t N, const TagDetails (&array)[N]>
std::ostream& printTagNoError(std::ostream& os, const int64_t value, const ExifData*) { std::ostream& printTagNoError(std::ostream& os, const int64_t value, const ExifData*) {
auto td = Exiv2::find(array, value); if (auto td = Exiv2::find(array, value)) {
if (td) {
os << exvGettext(td->label_); os << exvGettext(td->label_);
} else { } else {
os << value; os << value;
@ -173,8 +171,7 @@ std::ostream& printTagNoError(std::ostream& os, const Value& value, const ExifDa
*/ */
template <size_t N, const TagDetails (&array)[N]> template <size_t N, const TagDetails (&array)[N]>
std::ostream& printTag(std::ostream& os, const int64_t value, const ExifData*) { std::ostream& printTag(std::ostream& os, const int64_t value, const ExifData*) {
auto td = Exiv2::find(array, value); if (auto td = Exiv2::find(array, value)) {
if (td) {
os << exvGettext(td->label_); os << exvGettext(td->label_);
} else { } else {
os << "(" << value << ")"; os << "(" << value << ")";
@ -292,8 +289,7 @@ std::ostream& printTagBitlistAllLE(std::ostream& os, const Value& value, const E
*/ */
template <size_t N, const TagVocabulary (&array)[N]> template <size_t N, const TagVocabulary (&array)[N]>
std::ostream& printTagVocabulary(std::ostream& os, const Value& value, const ExifData*) { std::ostream& printTagVocabulary(std::ostream& os, const Value& value, const ExifData*) {
auto td = Exiv2::find(array, value.toString()); if (auto td = Exiv2::find(array, value.toString())) {
if (td) {
os << exvGettext(td->label_); os << exvGettext(td->label_);
} else { } else {
os << "(" << value << ")"; os << "(" << value << ")";

@ -92,9 +92,6 @@ TiffBinaryArray::TiffBinaryArray(uint16_t tag, IfdId group, const ArraySet* arra
// We'll figure out the correct cfg later // We'll figure out the correct cfg later
} }
TiffBinaryElement::TiffBinaryElement(uint16_t tag, IfdId group) : TiffEntryBase(tag, group) {
}
TiffDirectory::~TiffDirectory() { TiffDirectory::~TiffDirectory() {
for (auto&& component : components_) { for (auto&& component : components_) {
delete component; delete component;
@ -207,8 +204,7 @@ void TiffEntryBase::setData(byte* pData, size_t size, std::shared_ptr<DataBuf> s
void TiffEntryBase::updateValue(Value::UniquePtr value, ByteOrder byteOrder) { void TiffEntryBase::updateValue(Value::UniquePtr value, ByteOrder byteOrder) {
if (!value) if (!value)
return; return;
size_t newSize = value->size(); if (size_t newSize = value->size(); newSize > size_) {
if (newSize > size_) {
auto d = std::make_shared<DataBuf>(newSize); auto d = std::make_shared<DataBuf>(newSize);
setData(std::move(d)); setData(std::move(d));
} }
@ -488,19 +484,19 @@ TiffComponent* TiffSubIfd::doAddPath(uint16_t tag, TiffPath& tiffPath, TiffCompo
const TiffPathItem tpi2 = tiffPath.top(); const TiffPathItem tpi2 = tiffPath.top();
tiffPath.push(tpi1); tiffPath.push(tpi1);
auto it = std::find_if(ifds_.begin(), ifds_.end(), [&](auto&& ifd) { return ifd->group() == tpi2.group(); }); auto it = std::find_if(ifds_.begin(), ifds_.end(), [&](auto&& ifd) { return ifd->group() == tpi2.group(); });
if (it != ifds_.end()) if (it == ifds_.end()) {
return (*it)->addPath(tag, tiffPath, pRoot, std::move(object)); auto tc = [&] {
if (tiffPath.size() == 1 && object) {
auto tc = [&] { TiffComponent::UniquePtr tempObject;
if (tiffPath.size() == 1 && object) { std::swap(object, tempObject);
TiffComponent::UniquePtr tempObject; return addChild(std::move(tempObject));
std::swap(object, tempObject); }
return addChild(std::move(tempObject)); return addChild(std::make_unique<TiffDirectory>(tpi1.tag(), tpi2.group()));
} }();
return addChild(std::make_unique<TiffDirectory>(tpi1.tag(), tpi2.group())); setCount(ifds_.size());
}(); return tc->addPath(tag, tiffPath, pRoot, std::move(object));
setCount(ifds_.size()); }
return tc->addPath(tag, tiffPath, pRoot, std::move(object)); return (*it)->addPath(tag, tiffPath, pRoot, std::move(object));
} // TiffSubIfd::doAddPath } // TiffSubIfd::doAddPath
TiffComponent* TiffMnEntry::doAddPath(uint16_t tag, TiffPath& tiffPath, TiffComponent* pRoot, TiffComponent* TiffMnEntry::doAddPath(uint16_t tag, TiffPath& tiffPath, TiffComponent* pRoot,
@ -844,8 +840,7 @@ size_t TiffDirectory::doWrite(IoWrapper& ioWrapper, ByteOrder byteOrder, size_t
size_t sizeValue = 0; size_t sizeValue = 0;
size_t sizeData = 0; size_t sizeData = 0;
for (auto&& component : components_) { for (auto&& component : components_) {
size_t sv = component->size(); if (size_t sv = component->size(); sv > 4) {
if (sv > 4) {
sv += sv & 1; // Align value to word boundary sv += sv & 1; // Align value to word boundary
sizeValue += sv; sizeValue += sv;
} }
@ -873,8 +868,7 @@ size_t TiffDirectory::doWrite(IoWrapper& ioWrapper, ByteOrder byteOrder, size_t
// b) Directory entries - may contain pointers to the value or data // b) Directory entries - may contain pointers to the value or data
for (auto&& component : components_) { for (auto&& component : components_) {
idx += writeDirEntry(ioWrapper, byteOrder, offset, component, valueIdx, dataIdx, imageIdx); idx += writeDirEntry(ioWrapper, byteOrder, offset, component, valueIdx, dataIdx, imageIdx);
size_t sv = component->size(); if (size_t sv = component->size(); sv > 4) {
if (sv > 4) {
sv += sv & 1; // Align value to word boundary sv += sv & 1; // Align value to word boundary
valueIdx += sv; valueIdx += sv;
} }
@ -896,8 +890,7 @@ size_t TiffDirectory::doWrite(IoWrapper& ioWrapper, ByteOrder byteOrder, size_t
valueIdx = sizeDir; valueIdx = sizeDir;
dataIdx = sizeDir + sizeValue; dataIdx = sizeDir + sizeValue;
for (auto&& component : components_) { for (auto&& component : components_) {
size_t sv = component->size(); if (size_t sv = component->size(); sv > 4) {
if (sv > 4) {
size_t d = component->write(ioWrapper, byteOrder, offset, valueIdx, dataIdx, imageIdx); size_t d = component->write(ioWrapper, byteOrder, offset, valueIdx, dataIdx, imageIdx);
enforce(sv == d, ErrorCode::kerImageWriteFailed); enforce(sv == d, ErrorCode::kerImageWriteFailed);
if ((sv & 1) == 1) { if ((sv & 1) == 1) {
@ -1291,8 +1284,7 @@ size_t TiffDirectory::doSize() const {
size_t len = 2 + 12 * compCount + (hasNext_ ? 4 : 0); size_t len = 2 + 12 * compCount + (hasNext_ ? 4 : 0);
// Size of IFD values and data // Size of IFD values and data
for (auto&& component : components_) { for (auto&& component : components_) {
size_t sv = component->size(); if (size_t sv = component->size(); sv > 4) {
if (sv > 4) {
sv += sv & 1; // Align value to word boundary sv += sv & 1; // Align value to word boundary
len += sv; len += sv;
} }
@ -1459,11 +1451,12 @@ static const TagInfo* findTagInfo(uint16_t tag, IfdId group) {
return Internal::gpsTagList(); return Internal::gpsTagList();
return group == IfdId::exifId ? Internal::exifTagList() : nullptr; return group == IfdId::exifId ? Internal::exifTagList() : nullptr;
}(); }();
if (tags) { if (!tags)
for (size_t idx = 0; !result && tags[idx].tag_ != 0xffff; ++idx) { return result;
if (tags[idx].tag_ == tag) {
result = tags + idx; for (size_t idx = 0; !result && tags[idx].tag_ != 0xffff; ++idx) {
} if (tags[idx].tag_ == tag) {
result = tags + idx;
} }
} }
return result; return result;

@ -1409,13 +1409,9 @@ class TiffBinaryArray : public TiffEntryBase {
@brief Element of a TiffBinaryArray. @brief Element of a TiffBinaryArray.
*/ */
class TiffBinaryElement : public TiffEntryBase { class TiffBinaryElement : public TiffEntryBase {
public: using TiffEntryBase::TiffEntryBase;
//! @name Creators
//@{
//! Constructor
TiffBinaryElement(uint16_t tag, IfdId group);
//@}
public:
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! /*!

@ -12,9 +12,9 @@
#include <iostream> #include <iostream>
// Shortcuts for the newTiffBinaryArray templates. // Shortcuts for the newTiffBinaryArray templates.
#define EXV_BINARY_ARRAY(arrayCfg, arrayDef) (newTiffBinaryArray0<arrayCfg, std::size(arrayDef), arrayDef>) #define EXV_BINARY_ARRAY(arrayCfg, arrayDef) &newTiffBinaryArray0<arrayCfg, std::size(arrayDef), arrayDef>
#define EXV_SIMPLE_BINARY_ARRAY(arrayCfg) (newTiffBinaryArray1<arrayCfg>) #define EXV_SIMPLE_BINARY_ARRAY(arrayCfg) &newTiffBinaryArray1<arrayCfg>
#define EXV_COMPLEX_BINARY_ARRAY(arraySet, cfgSelFct) (newTiffBinaryArray2<std::size(arraySet), arraySet, cfgSelFct>) #define EXV_COMPLEX_BINARY_ARRAY(arraySet, cfgSelFct) &newTiffBinaryArray2<std::size(arraySet), arraySet, cfgSelFct>
namespace Exiv2::Internal { namespace Exiv2::Internal {
//! Constant for non-encrypted binary arrays //! Constant for non-encrypted binary arrays

@ -490,7 +490,12 @@ bool isHex(const std::string& str, size_t size, const std::string& prefix) {
int exifTime(const char* buf, tm* tm) { int exifTime(const char* buf, tm* tm) {
int rc = 1; int rc = 1;
int year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0; int year = 0;
int mon = 0;
int mday = 0;
int hour = 0;
int min = 0;
int sec = 0;
if (std::sscanf(buf, "%4d:%2d:%2d %2d:%2d:%2d", &year, &mon, &mday, &hour, &min, &sec) == 6) { if (std::sscanf(buf, "%4d:%2d:%2d %2d:%2d:%2d", &year, &mon, &mday, &hour, &min, &sec) == 6) {
tm->tm_year = year - 1900; tm->tm_year = year - 1900;
tm->tm_mon = mon - 1; tm->tm_mon = mon - 1;

@ -25,7 +25,7 @@
#ifndef lint #ifndef lint
#ifndef NOID #ifndef NOID
static char tzfilehid[] = "@(#)tzfile.h 7.14"; static char tzfilehid[] = "@(#)tzfile.h\t7.14";
#endif /* !defined NOID */ #endif /* !defined NOID */
#endif /* !defined lint */ #endif /* !defined lint */

@ -503,9 +503,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
Internal::enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf payload(size); if (DataBuf payload(size); payload.empty()) {
if (payload.empty()) {
io_->seek(size, BasicIo::cur); io_->seek(size, BasicIo::cur);
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) { } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) {
Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
@ -594,22 +592,22 @@ void WebPImage::decodeChunks(uint32_t filesize) {
bool s_header = false; bool s_header = false;
bool le_header = false; bool le_header = false;
bool be_header = false; bool be_header = false;
size_t pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifLongHeader), 4); size_t pos = getHeaderOffset(payload.c_data(), payload.size(), exifLongHeader, 4);
if (pos == std::string::npos) { if (pos == std::string::npos) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifLongHeader), 6); pos = getHeaderOffset(payload.c_data(), payload.size(), exifLongHeader, 6);
if (pos != std::string::npos) { if (pos != std::string::npos) {
s_header = true; s_header = true;
} }
} }
if (pos == std::string::npos) { if (pos == std::string::npos) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifTiffLEHeader), 3); pos = getHeaderOffset(payload.c_data(), payload.size(), exifTiffLEHeader, 3);
if (pos != std::string::npos) { if (pos != std::string::npos) {
le_header = true; le_header = true;
} }
} }
if (pos == std::string::npos) { if (pos == std::string::npos) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifTiffBEHeader), 4); pos = getHeaderOffset(payload.c_data(), payload.size(), exifTiffBEHeader, 4);
if (pos != std::string::npos) { if (pos != std::string::npos) {
be_header = true; be_header = true;
} }

@ -462,7 +462,7 @@ XmpData::const_iterator XmpData::end() const {
} }
bool XmpData::empty() const { bool XmpData::empty() const {
return count() == 0; return xmpMetadata_.empty();
} }
long XmpData::count() const { long XmpData::count() const {
@ -685,7 +685,9 @@ int XmpParser::decode(XmpData& xmpData, const std::string& xmpPacket) {
XMLValidator::check(xmpPacket.data(), len); XMLValidator::check(xmpPacket.data(), len);
SXMPMeta meta(xmpPacket.data(), static_cast<XMP_StringLen>(len)); SXMPMeta meta(xmpPacket.data(), static_cast<XMP_StringLen>(len));
SXMPIterator iter(meta); SXMPIterator iter(meta);
std::string schemaNs, propPath, propValue; std::string schemaNs;
std::string propPath;
std::string propValue;
XMP_OptionBits opt = 0; XMP_OptionBits opt = 0;
while (iter.Next(&schemaNs, &propPath, &propValue, &opt)) { while (iter.Next(&schemaNs, &propPath, &propValue, &opt)) {
printNode(schemaNs, propPath, propValue, opt); printNode(schemaNs, propPath, propValue, opt);
@ -734,7 +736,9 @@ int XmpParser::decode(XmpData& xmpData, const std::string& xmpPacket) {
// Check if all elements are simple // Check if all elements are simple
bool simpleArray = true; bool simpleArray = true;
SXMPIterator aIter(meta, schemaNs.c_str(), propPath.c_str()); SXMPIterator aIter(meta, schemaNs.c_str(), propPath.c_str());
std::string aSchemaNs, aPropPath, aPropValue; std::string aSchemaNs;
std::string aPropPath;
std::string aPropValue;
XMP_OptionBits aOpt = 0; XMP_OptionBits aOpt = 0;
while (aIter.Next(&aSchemaNs, &aPropPath, &aPropValue, &aOpt)) { while (aIter.Next(&aSchemaNs, &aPropPath, &aPropValue, &aOpt)) {
if (propPath == aPropPath) if (propPath == aPropPath)

@ -144,27 +144,27 @@ TEST(MemIo, readEmptyIoReturns0) {
} }
TEST(MemIo, readLessBytesThanAvailableReturnsRequestedBytes) { TEST(MemIo, readLessBytesThanAvailableReturnsRequestedBytes) {
std::array<byte, 10> buf1, buf2; std::array<byte, 10> buf1;
std::array<byte, 10> buf2 = {};
buf1.fill(1); buf1.fill(1);
buf2.fill(0);
MemIo io(buf1.data(), buf1.size()); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(5, io.read(buf2.data(), 5)); ASSERT_EQ(5, io.read(buf2.data(), 5));
} }
TEST(MemIo, readSameBytesThanAvailableReturnsRequestedBytes) { TEST(MemIo, readSameBytesThanAvailableReturnsRequestedBytes) {
std::array<byte, 10> buf1, buf2; std::array<byte, 10> buf1;
std::array<byte, 10> buf2 = {};
buf1.fill(1); buf1.fill(1);
buf2.fill(0);
MemIo io(buf1.data(), buf1.size()); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(10, io.read(buf2.data(), 10)); ASSERT_EQ(10, io.read(buf2.data(), 10));
} }
TEST(MemIo, readMoreBytesThanAvailableReturnsAvailableBytes) { TEST(MemIo, readMoreBytesThanAvailableReturnsAvailableBytes) {
std::array<byte, 10> buf1, buf2; std::array<byte, 10> buf1;
std::array<byte, 10> buf2 = {};
buf1.fill(1); buf1.fill(1);
buf2.fill(0);
MemIo io(buf1.data(), buf1.size()); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(10, io.read(buf2.data(), 15)); ASSERT_EQ(10, io.read(buf2.data(), 15));

Loading…
Cancel
Save