Merge pull request #2118 from Exiv2/main_NewDelete

Refactoring & Cleanup (Moving to size_t usage & less naked new/deletes)
main
Luis Díaz Más 3 years ago committed by GitHub
commit 5ca423d292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -59,9 +59,12 @@
#ifdef EXV_HAVE_UNISTD_H #ifdef EXV_HAVE_UNISTD_H
# include <unistd.h> // for stat() # include <unistd.h> // for stat()
#endif #endif
#ifdef _MSC_VER
#if defined(_WIN32) || defined(__CYGWIN__)
# include <sys/utime.h> # include <sys/utime.h>
#include <Windows.h> #include <Windows.h>
#include <fcntl.h>
#include <io.h>
#else #else
# include <utime.h> # include <utime.h>
#endif #endif
@ -204,17 +207,17 @@ namespace Action {
std::stringstream output(std::stringstream::out|std::stringstream::binary); std::stringstream output(std::stringstream::out|std::stringstream::binary);
result = printStructure(output, option, path); result = printStructure(output, option, path);
if ( result == 0 ) { if ( result == 0 ) {
size_t size = static_cast<long>(output.str().size()); size_t size = output.str().size();
Exiv2::DataBuf iccProfile(static_cast<long>(size)); Exiv2::DataBuf iccProfile(size);
Exiv2::DataBuf ascii(static_cast<long>(size * 3 + 1)); Exiv2::DataBuf ascii(size * 3 + 1);
ascii.write_uint8(size * 3, 0); ascii.write_uint8(size * 3, 0);
iccProfile.copyBytes(0,output.str().c_str(),size); iccProfile.copyBytes(0,output.str().c_str(),size);
if (Exiv2::base64encode(iccProfile.c_data(), size, reinterpret_cast<char*>(ascii.data()), size * 3)) { if (Exiv2::base64encode(iccProfile.c_data(), size, reinterpret_cast<char*>(ascii.data()), size * 3)) {
long chunk = 60 ; long chunk = 60 ;
std::string code = std::string("data:") + std::string(ascii.c_str()); std::string code = std::string("data:") + ascii.c_str();
long length = static_cast<long>(code.size()); size_t length = code.size();
for ( long start = 0 ; start < length ; start += chunk ) { for ( size_t start = 0 ; start < length ; start += chunk ) {
long count = (start+chunk) < length ? chunk : length - start ; size_t count = (start+chunk) < length ? chunk : length - start ;
std::cout << code.substr(start,count) << std::endl; std::cout << code.substr(start,count) << std::endl;
} }
} }
@ -304,7 +307,7 @@ namespace Action {
} }
else { else {
auto dataBuf = exifThumb.copy(); auto dataBuf = exifThumb.copy();
if (dataBuf.size() == 0) { if (dataBuf.empty()) {
std::cout << _("None"); std::cout << _("None");
} }
else { else {
@ -567,7 +570,7 @@ namespace Action {
std::ostringstream os; std::ostringstream os;
// #1114 - show negative values for SByte // #1114 - show negative values for SByte
if (md.typeId() == Exiv2::signedByte) { if (md.typeId() == Exiv2::signedByte) {
for ( long c = 0 ; c < md.value().count() ; c++ ) { for ( size_t c = 0 ; c < md.value().count() ; c++ ) {
const auto value = md.value().toInt64(c); const auto value = md.value().toInt64(c);
os << (c?" ":"") << std::dec << (value < 128 ? value : value - 256); os << (c?" ":"") << std::dec << (value < 128 ? value : value - 256);
} }
@ -589,7 +592,7 @@ namespace Action {
std::cout << std::endl; std::cout << std::endl;
Exiv2::DataBuf buf(md.size()); Exiv2::DataBuf buf(md.size());
md.copy(buf.data(), pImage->byteOrder()); md.copy(buf.data(), pImage->byteOrder());
Exiv2::hexdump(std::cout, buf.c_data(), buf.size()); Exiv2::hexdump(std::cout, buf.c_data(), static_cast<long>(buf.size()));
} }
std::cout << std::endl; std::cout << std::endl;
return true; return true;
@ -911,8 +914,7 @@ namespace Action {
else { else {
if ( (Params::instance().target_ & Params::ctStdInOut) != 0 ) { if ( (Params::instance().target_ & Params::ctStdInOut) != 0 ) {
Exiv2::DataBuf buf = exifThumb.copy(); Exiv2::DataBuf buf = exifThumb.copy();
std::cout.write(reinterpret_cast<char*>(buf.data()), std::cout.write(buf.c_str(), buf.size());
buf.size());
return 0; return 0;
} }
@ -927,7 +929,7 @@ namespace Action {
<< thumbPath << std::endl; << thumbPath << std::endl;
} }
} }
rc = exifThumb.writeFile(thumb); rc = static_cast<int>(exifThumb.writeFile(thumb));
if (rc == 0) { if (rc == 0) {
std::cerr << path_ << ": " << _("Exif data doesn't contain a thumbnail\n"); std::cerr << path_ << ": " << _("Exif data doesn't contain a thumbnail\n");
} }
@ -990,15 +992,14 @@ namespace Action {
} else { } else {
if ( bStdout ) { // -eC- if ( bStdout ) { // -eC-
std::cout.write(image->iccProfile().c_str(), std::cout.write(image->iccProfile().c_str(), image->iccProfile().size());
image->iccProfile().size());
} else { } else {
if (Params::instance().verbose_) { if (Params::instance().verbose_) {
std::cout << _("Writing iccProfile: ") << target << std::endl; std::cout << _("Writing iccProfile: ") << target << std::endl;
} }
Exiv2::FileIo iccFile(target); Exiv2::FileIo iccFile(target);
iccFile.open("wb") ; iccFile.open("wb") ;
iccFile.write(image->iccProfile().c_data(),image->iccProfile().size()); iccFile.write(image->iccProfile().c_data(), image->iccProfile().size());
iccFile.close(); iccFile.close();
} }
} }
@ -1022,7 +1023,7 @@ namespace Action {
std::cout << pvImg.size() << " " << _("bytes") << ") " std::cout << pvImg.size() << " " << _("bytes") << ") "
<< _("to file") << " " << pvPath << std::endl; << _("to file") << " " << pvPath << std::endl;
} }
long rc = pvImg.writeFile(pvFile); auto rc = pvImg.writeFile(pvFile);
if (rc == 0) { if (rc == 0) {
std::cerr << path_ << ": " << _("Image does not have preview") std::cerr << path_ << ": " << _("Image does not have preview")
<< " " << num << "\n"; << " " << num << "\n";
@ -1087,7 +1088,7 @@ namespace Action {
return 1; return 1;
} // Insert::run } // Insert::run
int Insert::insertXmpPacket(const std::string& path,const std::string& xmpPath) int Insert::insertXmpPacket(const std::string& path,const std::string& xmpPath)
{ {
int rc = 0; int rc = 0;
bool bStdin = xmpPath == "-" ; bool bStdin = xmpPath == "-" ;
@ -1118,7 +1119,7 @@ namespace Action {
int Insert::insertXmpPacket(const std::string& path, const Exiv2::DataBuf& xmpBlob, bool usePacket) int Insert::insertXmpPacket(const std::string& path, const Exiv2::DataBuf& xmpBlob, bool usePacket)
{ {
std::string xmpPacket; std::string xmpPacket;
for ( long i = 0 ; i < xmpBlob.size() ; i++ ) { for ( size_t i = 0 ; i < xmpBlob.size() ; i++ ) {
xmpPacket += static_cast<char>(xmpBlob.read_uint8(i)); xmpPacket += static_cast<char>(xmpBlob.read_uint8(i));
} }
auto image = Exiv2::ImageFactory::open(path); auto image = Exiv2::ImageFactory::open(path);
@ -1132,7 +1133,7 @@ namespace Action {
return 0; return 0;
} }
int Insert::insertIccProfile(const std::string& path,const std::string& iccPath) int Insert::insertIccProfile(const std::string& path,const std::string& iccPath)
{ {
int rc = 0; int rc = 0;
// for path "foo.XXX", do a binary copy of "foo.icc" // for path "foo.XXX", do a binary copy of "foo.icc"
@ -1820,11 +1821,15 @@ namespace {
bool bStdout = tgt == "-"; bool bStdout = tgt == "-";
Exiv2::DataBuf stdIn; Exiv2::DataBuf stdIn;
if ( bStdin ) Exiv2::Image::UniquePtr sourceImage;
if ( bStdin ) {
Params::instance().getStdin(stdIn); Params::instance().getStdin(stdIn);
auto ioStdin = std::make_unique<Exiv2::MemIo>(stdIn.c_data(), stdIn.size());
sourceImage = Exiv2::ImageFactory::open(std::move(ioStdin));
} else {
sourceImage = Exiv2::ImageFactory::open(source);
}
auto ioStdin = std::make_unique<Exiv2::MemIo>(stdIn.c_data(),stdIn.size());
auto sourceImage = bStdin ? Exiv2::ImageFactory::open(std::move(ioStdin)) : Exiv2::ImageFactory::open(source);
assert(sourceImage); assert(sourceImage);
sourceImage->readMetadata(); sourceImage->readMetadata();

@ -37,16 +37,24 @@
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#include <regex> #include <regex>
#if defined(_MSC_VER) #if defined(_WIN32) || defined(__CYGWIN__)
#include <Windows.h> #include <Windows.h>
#include <fcntl.h>
#include <io.h>
#else
#include <unistd.h>
#endif #endif
// ***************************************************************************** // *****************************************************************************
// local declarations // local declarations
namespace { namespace {
const Params::YodAdjust emptyYodAdjust_[] = {
{ false, "-Y", 0 },
{ false, "-O", 0 },
{ false, "-D", 0 },
};
//! List of all command identifiers and corresponding strings //! List of all command identifiers and corresponding strings
const CmdIdAndString cmdIdAndString[] = { const CmdIdAndString cmdIdAndString[] = {
@ -181,7 +189,6 @@ int main(int argc, char* const argv[])
} }
taskFactory.cleanup(); taskFactory.cleanup();
Params::cleanup();
Exiv2::XmpParser::terminate(); Exiv2::XmpParser::terminate();
} }
} catch (const std::exception& exc) { } catch (const std::exception& exc) {
@ -195,26 +202,38 @@ int main(int argc, char* const argv[])
// ***************************************************************************** // *****************************************************************************
// class Params // class Params
Params* Params::instance_ = nullptr;
const Params::YodAdjust Params::emptyYodAdjust_[] = { Params::Params() : optstring_(":hVvqfbuktTFa:Y:O:D:r:p:P:d:e:i:c:m:M:l:S:g:K:n:Q:"),
{ false, "-Y", 0 }, help_(false),
{ false, "-O", 0 }, version_(false),
{ false, "-D", 0 }, verbose_(false),
}; force_(false),
binary_(false),
Params& Params::instance() unknown_(true),
preserve_(false),
timestamp_(false),
timestampOnly_(false),
fileExistsPolicy_(askPolicy),
adjust_(false),
printMode_(pmSummary),
printItems_(0),
printTags_(Exiv2::mdNone),
action_(0),
target_(ctExif|ctIptc|ctComment|ctXmp),
adjustment_(0),
format_("%Y%m%d_%H%M%S"),
formatSet_(false),
first_(true)
{ {
if (nullptr == instance_) { yodAdjust_[yodYear] = emptyYodAdjust_[yodYear];
instance_ = new Params; yodAdjust_[yodMonth] = emptyYodAdjust_[yodMonth];
} yodAdjust_[yodDay] = emptyYodAdjust_[yodDay];
return *instance_;
} }
void Params::cleanup() Params& Params::instance()
{ {
delete instance_; static Params instance_;
instance_ = nullptr; return instance_;
} }
void Params::version(bool verbose, std::ostream& os) void Params::version(bool verbose, std::ostream& os)
@ -968,7 +987,7 @@ static int readFileToBuf(FILE* f,Exiv2::DataBuf& buf)
void Params::getStdin(Exiv2::DataBuf& buf) void Params::getStdin(Exiv2::DataBuf& buf)
{ {
// copy stdin to stdinBuf // copy stdin to stdinBuf
if ( stdinBuf.size() == 0 ) { if (stdinBuf.empty()) {
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MSC_VER) #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MSC_VER)
DWORD fdwMode; DWORD fdwMode;
_setmode(fileno(stdin), O_BINARY); _setmode(fileno(stdin), O_BINARY);
@ -993,7 +1012,7 @@ void Params::getStdin(Exiv2::DataBuf& buf)
// this is only used to simulate reading from stdin when debugging // this is only used to simulate reading from stdin when debugging
// to simulate exiv2 -pX foo.jpg | exiv2 -iXX- bar.jpg // to simulate exiv2 -pX foo.jpg | exiv2 -iXX- bar.jpg
// exiv2 -pX foo.jpg > ~/temp/stdin ; exiv2 -iXX- bar.jpg // exiv2 -pX foo.jpg > ~/temp/stdin ; exiv2 -iXX- bar.jpg
if ( stdinBuf.size() == 0 ) { if ( stdinBuf.empty()) {
const char* path = "/Users/rmills/temp/stdin"; const char* path = "/Users/rmills/temp/stdin";
FILE* f = fopen(path,"rb"); FILE* f = fopen(path,"rb");
if ( f ) { if ( f ) {
@ -1019,56 +1038,55 @@ void Params::getStdin(Exiv2::DataBuf& buf)
} // Params::getStdin() } // Params::getStdin()
using long_t = std::map<std::string, std::string>;
int Params::getopt(int argc, char* const Argv[]) int Params::getopt(int argc, char* const Argv[])
{ {
auto argv = new char*[argc + 1]; std::vector<char *> argv(argc+1);
argv[argc] = nullptr; argv[argc] = nullptr;
long_t longs;
const std::unordered_map<std::string, std::string> longs {
longs["--adjust" ] = "-a"; {"--adjust" , "-a"},
longs["--binary" ] = "-b"; {"--binary" , "-b"},
longs["--comment" ] = "-c"; {"--comment" , "-c"},
longs["--delete" ] = "-d"; {"--delete" , "-d"},
longs["--days" ] = "-D"; {"--days" , "-D"},
longs["--extract" ] = "-e"; {"--extract" , "-e"},
longs["--force" ] = "-f"; {"--force" , "-f"},
longs["--Force" ] = "-F"; {"--Force" , "-F"},
longs["--grep" ] = "-g"; {"--grep" , "-g"},
longs["--help" ] = "-h"; {"--help" , "-h"},
longs["--insert" ] = "-i"; {"--insert" , "-i"},
longs["--keep" ] = "-k"; {"--keep" , "-k"},
longs["--key" ] = "-K"; {"--key" , "-K"},
longs["--location" ] = "-l"; {"--location" , "-l"},
longs["--modify" ] = "-m"; {"--modify" , "-m"},
longs["--Modify" ] = "-M"; {"--Modify" , "-M"},
longs["--encode" ] = "-n"; {"--encode" , "-n"},
longs["--months" ] = "-O"; {"--months" , "-O"},
longs["--print" ] = "-p"; {"--print" , "-p"},
longs["--Print" ] = "-P"; {"--Print" , "-P"},
longs["--quiet" ] = "-q"; {"--quiet" , "-q"},
longs["--log" ] = "-Q"; {"--log" , "-Q"},
longs["--rename" ] = "-r"; {"--rename" , "-r"},
longs["--suffix" ] = "-S"; {"--suffix" , "-S"},
longs["--timestamp"] = "-t"; {"--timestamp", "-t"},
longs["--Timestamp"] = "-T"; {"--Timestamp", "-T"},
longs["--unknown" ] = "-u"; {"--unknown" , "-u"},
longs["--verbose" ] = "-v"; {"--verbose" , "-v"},
longs["--Version" ] = "-V"; {"--Version" , "-V"},
longs["--version" ] = "-V"; {"--version" , "-V"},
longs["--years" ] = "-Y"; {"--years" , "-Y"},
};
for ( int i = 0 ; i < argc ; i++ ) { for ( int i = 0 ; i < argc ; i++ ) {
std::string arg(Argv[i]); std::string arg(Argv[i]);
if (longs.find(arg) != longs.end() ) { if (longs.find(arg) != longs.end() ) {
argv[i] = ::strdup(longs[arg].c_str()); argv[i] = ::strdup(longs.at(arg).c_str());
} else { } else {
argv[i] = ::strdup(Argv[i]); argv[i] = ::strdup(Argv[i]);
} }
} }
int rc = Util::Getopt::getopt(argc, argv, optstring_); int rc = Util::Getopt::getopt(argc, argv.data(), optstring_);
// Further consistency checks // Further consistency checks
if (help_ || version_) { if (help_ || version_) {
goto cleanup; goto cleanup;
@ -1141,10 +1159,9 @@ int Params::getopt(int argc, char* const Argv[])
// cleanup the argument vector // cleanup the argument vector
for (int i = 0; i < argc; i++) for (int i = 0; i < argc; i++)
::free(argv[i]); ::free(argv[i]);
delete [] argv;
return rc; return rc;
} // Params::getopt }
// ***************************************************************************** // *****************************************************************************
// local implementations // local implementations

@ -35,21 +35,15 @@
#include "getopt.hpp" #include "getopt.hpp"
// + standard includes // + standard includes
#include <string>
#include <vector> #include <vector>
#include <set> #include <set>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#ifdef EXV_HAVE_UNISTD_H
#include <unistd.h>
#endif
// stdin handler includes // stdin handler includes
#ifndef _MSC_VER #ifndef _MSC_VER
#include <cstdlib> #include <cstdlib>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#if defined(__CYGWIN__) || defined(__MINGW__) #if defined(__CYGWIN__) || defined(__MINGW__)
#include <windows.h> #include <windows.h>
#else #else
@ -57,12 +51,6 @@
#endif #endif
#endif #endif
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MSC_VER)
#include <fcntl.h>
#include <io.h>
#endif
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
@ -160,9 +148,6 @@ public:
//! Prevent copy-construction: not implemented. //! Prevent copy-construction: not implemented.
Params(const Params& rhs) = delete; Params(const Params& rhs) = delete;
//! Destructor
static void cleanup();
//! Enumerates print modes //! Enumerates print modes
enum PrintMode { enum PrintMode {
pmSummary, pmSummary,
@ -256,44 +241,11 @@ public:
Exiv2::DataBuf stdinBuf; //!< DataBuf with the binary bytes from stdin Exiv2::DataBuf stdinBuf; //!< DataBuf with the binary bytes from stdin
private: private:
//! Pointer to the global Params object.
static Params* instance_;
//! Initializer for year, month and day adjustment info.
static const YodAdjust emptyYodAdjust_[];
bool first_; bool first_;
Params();
private: private:
/*!
@brief Default constructor. Note that optstring_ is initialized here.
The c'tor is private to force instantiation through instance().
*/
Params() : optstring_(":hVvqfbuktTFa:Y:O:D:r:p:P:d:e:i:c:m:M:l:S:g:K:n:Q:"),
help_(false),
version_(false),
verbose_(false),
force_(false),
binary_(false),
unknown_(true),
preserve_(false),
timestamp_(false),
timestampOnly_(false),
fileExistsPolicy_(askPolicy),
adjust_(false),
printMode_(pmSummary),
printItems_(0),
printTags_(Exiv2::mdNone),
action_(0),
target_(ctExif|ctIptc|ctComment|ctXmp),
adjustment_(0),
format_("%Y%m%d_%H%M%S"),
formatSet_(false),
first_(true)
{
yodAdjust_[yodYear] = emptyYodAdjust_[yodYear];
yodAdjust_[yodMonth] = emptyYodAdjust_[yodMonth];
yodAdjust_[yodDay] = emptyYodAdjust_[yodDay];
}
//! @name Helpers //! @name Helpers
//@{ //@{

@ -100,7 +100,7 @@ namespace Exiv2 {
@return Number of bytes written to IO source successfully;<BR> @return Number of bytes written to IO source successfully;<BR>
0 if failure; 0 if failure;
*/ */
virtual long write(const byte* data, long wcount) = 0; virtual size_t write(const byte* data, size_t wcount) = 0;
/*! /*!
@brief Write data that is read from another BasicIo instance to @brief Write data that is read from another BasicIo instance to
the IO source. Current IO position is advanced by the number the IO source. Current IO position is advanced by the number
@ -110,7 +110,7 @@ namespace Exiv2 {
@return Number of bytes written to IO source successfully;<BR> @return Number of bytes written to IO source successfully;<BR>
0 if failure; 0 if failure;
*/ */
virtual long write(BasicIo& src) = 0; virtual size_t write(BasicIo& src) = 0;
/*! /*!
@brief Write one byte to the IO source. Current IO position is @brief Write one byte to the IO source. Current IO position is
advanced by one byte. advanced by one byte.
@ -129,7 +129,7 @@ namespace Exiv2 {
DataBuf::size_ member to find the number of bytes read. DataBuf::size_ member to find the number of bytes read.
DataBuf::size_ will be 0 on failure. DataBuf::size_ will be 0 on failure.
*/ */
virtual DataBuf read(long rcount) = 0; virtual DataBuf read(size_t rcount) = 0;
/*! /*!
@brief Read data from the IO source. Reading starts at the current @brief Read data from the IO source. Reading starts at the current
IO position and the position is advanced by the number of bytes IO position and the position is advanced by the number of bytes
@ -142,7 +142,7 @@ namespace Exiv2 {
@return Number of bytes read from IO source successfully;<BR> @return Number of bytes read from IO source successfully;<BR>
0 if failure; 0 if failure;
*/ */
virtual long read(byte* buf, long rcount) = 0; virtual size_t read(byte* buf, size_t rcount) = 0;
/*! /*!
@brief Safe version of `read()` that checks for errors and throws @brief Safe version of `read()` that checks for errors and throws
an exception if the read was unsuccessful. an exception if the read was unsuccessful.
@ -153,7 +153,7 @@ namespace Exiv2 {
read if \em rcount bytes are not available. read if \em rcount bytes are not available.
@param err Error code to use if an exception is thrown. @param err Error code to use if an exception is thrown.
*/ */
void readOrThrow(byte* buf, long rcount, ErrorCode err); void readOrThrow(byte* buf, size_t rcount, ErrorCode err);
/*! /*!
@brief Read one byte from the IO source. Current IO position is @brief Read one byte from the IO source. Current IO position is
advanced by one byte. advanced by one byte.
@ -352,7 +352,7 @@ namespace Exiv2 {
@return Number of bytes written to the file successfully;<BR> @return Number of bytes written to the file successfully;<BR>
0 if failure; 0 if failure;
*/ */
long write(const byte* data, long wcount) override; size_t write(const byte* data, size_t wcount) override;
/*! /*!
@brief Write data that is read from another BasicIo instance to @brief Write data that is read from another BasicIo instance to
the file. The file position is advanced by the number the file. The file position is advanced by the number
@ -362,7 +362,7 @@ namespace Exiv2 {
@return Number of bytes written to the file successfully;<BR> @return Number of bytes written to the file successfully;<BR>
0 if failure; 0 if failure;
*/ */
long write(BasicIo& src) override; size_t write(BasicIo& src) override;
/*! /*!
@brief Write one byte to the file. The file position is @brief Write one byte to the file. The file position is
advanced by one byte. advanced by one byte.
@ -381,7 +381,7 @@ namespace Exiv2 {
DataBuf::size_ member to find the number of bytes read. DataBuf::size_ member to find the number of bytes read.
DataBuf::size_ will be 0 on failure. DataBuf::size_ will be 0 on failure.
*/ */
DataBuf read(long rcount) override; DataBuf read(size_t rcount) override;
/*! /*!
@brief Read data from the file. Reading starts at the current @brief Read data from the file. Reading starts at the current
file position and the position is advanced by the number of file position and the position is advanced by the number of
@ -394,7 +394,7 @@ namespace Exiv2 {
@return Number of bytes read from the file successfully;<BR> @return Number of bytes read from the file successfully;<BR>
0 if failure; 0 if failure;
*/ */
long read(byte* buf, long rcount) override; size_t read(byte* buf, size_t rcount) override;
/*! /*!
@brief Read one byte from the file. The file position is @brief Read one byte from the file. The file position is
advanced by one byte. advanced by one byte.
@ -519,11 +519,10 @@ namespace Exiv2 {
@brief Constructor that accepts a block of memory. A copy-on-write @brief Constructor that accepts a block of memory. A copy-on-write
algorithm allows read operations directly from the original data algorithm allows read operations directly from the original data
and will create a copy of the buffer on the first write operation. and will create a copy of the buffer on the first write operation.
@param data Pointer to data. Data must be at least \em size @param data Pointer to data. Data must be at least \em size bytes long
bytes long
@param size Number of bytes to copy. @param size Number of bytes to copy.
*/ */
MemIo(const byte* data, long size); MemIo(const byte* data, size_t size);
//! Destructor. Releases all managed memory //! Destructor. Releases all managed memory
~MemIo() override; ~MemIo() override;
//@} //@}
@ -552,7 +551,7 @@ namespace Exiv2 {
@return Number of bytes written to the memory block successfully;<BR> @return Number of bytes written to the memory block successfully;<BR>
0 if failure; 0 if failure;
*/ */
long write(const byte* data, long wcount) override; size_t write(const byte* data, size_t wcount) override;
/*! /*!
@brief Write data that is read from another BasicIo instance to @brief Write data that is read from another BasicIo instance to
the memory block. If needed, the size of the internal memory the memory block. If needed, the size of the internal memory
@ -563,7 +562,7 @@ namespace Exiv2 {
@return Number of bytes written to the memory block successfully;<BR> @return Number of bytes written to the memory block successfully;<BR>
0 if failure; 0 if failure;
*/ */
long write(BasicIo& src) override; size_t write(BasicIo& src) override;
/*! /*!
@brief Write one byte to the memory block. The IO position is @brief Write one byte to the memory block. The IO position is
advanced by one byte. advanced by one byte.
@ -582,7 +581,7 @@ namespace Exiv2 {
DataBuf::size_ member to find the number of bytes read. DataBuf::size_ member to find the number of bytes read.
DataBuf::size_ will be 0 on failure. DataBuf::size_ will be 0 on failure.
*/ */
DataBuf read(long rcount) override; DataBuf read(size_t rcount) override;
/*! /*!
@brief Read data from the memory block. Reading starts at the current @brief Read data from the memory block. Reading starts at the current
IO position and the position is advanced by the number of IO position and the position is advanced by the number of
@ -595,7 +594,7 @@ namespace Exiv2 {
@return Number of bytes read from the memory block successfully;<BR> @return Number of bytes read from the memory block successfully;<BR>
0 if failure; 0 if failure;
*/ */
long read(byte* buf, long rcount) override; size_t read(byte* buf, size_t rcount) override;
/*! /*!
@brief Read one byte from the memory block. The IO position is @brief Read one byte from the memory block. The IO position is
advanced by one byte. advanced by one byte.
@ -764,6 +763,7 @@ namespace Exiv2 {
class EXIV2API RemoteIo : public BasicIo { class EXIV2API RemoteIo : public BasicIo {
public: public:
//! Destructor. Releases all managed memory. //! Destructor. Releases all managed memory.
RemoteIo();
~RemoteIo() override; ~RemoteIo() override;
//@} //@}
@ -790,7 +790,7 @@ namespace Exiv2 {
@brief Not support this method. @brief Not support this method.
@return 0 means failure @return 0 means failure
*/ */
long write(const byte* data, long wcount) override; size_t write(const byte* data, size_t wcount) override;
/*! /*!
@brief Write data that is read from another BasicIo instance to the remote file. @brief Write data that is read from another BasicIo instance to the remote file.
@ -805,7 +805,7 @@ namespace Exiv2 {
@note The write access is only supported by http, https, ssh. @note The write access is only supported by http, https, ssh.
*/ */
long write(BasicIo& src) override; size_t write(BasicIo& src) override;
/*! /*!
@brief Not support @brief Not support
@ -824,7 +824,7 @@ namespace Exiv2 {
DataBuf::size_ member to find the number of bytes read. DataBuf::size_ member to find the number of bytes read.
DataBuf::size_ will be 0 on failure. DataBuf::size_ will be 0 on failure.
*/ */
DataBuf read(long rcount) override; DataBuf read(size_t rcount) override;
/*! /*!
@brief Read data from the memory blocks. Reading starts at the current @brief Read data from the memory blocks. Reading starts at the current
IO position and the position is advanced by the number of IO position and the position is advanced by the number of
@ -839,7 +839,7 @@ namespace Exiv2 {
@return Number of bytes read from the memory block successfully;<BR> @return Number of bytes read from the memory block successfully;<BR>
0 if failure; 0 if failure;
*/ */
long read(byte* buf, long rcount) override; size_t read(byte* buf, size_t rcount) override;
/*! /*!
@brief Read one byte from the memory blocks. The IO position is @brief Read one byte from the memory blocks. The IO position is
advanced by one byte. advanced by one byte.
@ -916,7 +916,7 @@ namespace Exiv2 {
// Pimpl idiom // Pimpl idiom
class Impl; class Impl;
//! Pointer to implementation //! Pointer to implementation
Impl* p_ {nullptr}; std::unique_ptr<Impl> p_;
}; // class RemoteIo }; // class RemoteIo
/*! /*!
@ -973,13 +973,13 @@ namespace Exiv2 {
will call RemoteIo::write(const byte* data, long wcount) if the write will call RemoteIo::write(const byte* data, long wcount) if the write
access is available for the protocol. Otherwise, it throws the Error. access is available for the protocol. Otherwise, it throws the Error.
*/ */
long write(const byte* data, long wcount) override; size_t write(const byte* data, size_t wcount) override;
/*! /*!
@brief Write access is only available for some protocols. This method @brief Write access is only available for some protocols. This method
will call RemoteIo::write(BasicIo& src) if the write access is available will call RemoteIo::write(BasicIo& src) if the write access is available
for the protocol. Otherwise, it throws the Error. for the protocol. Otherwise, it throws the Error.
*/ */
long write(BasicIo& src) override; size_t write(BasicIo& src) override;
// NOT IMPLEMENTED // NOT IMPLEMENTED
//! Copy constructor //! Copy constructor
@ -1007,7 +1007,7 @@ namespace Exiv2 {
@return Return the number of bytes written. @return Return the number of bytes written.
@throw Error In case of failure. @throw Error In case of failure.
*/ */
EXIV2API long writeFile(const DataBuf& buf, const std::string& path); EXIV2API size_t writeFile(const DataBuf& buf, const std::string& path);
#ifdef EXV_USE_CURL #ifdef EXV_USE_CURL
/*! /*!
@brief The callback function is called by libcurl to write the data @brief The callback function is called by libcurl to write the data

@ -118,10 +118,10 @@ namespace Exiv2
std::ostream &out, std::ostream &out,
bool bTrace, bool bTrace,
uint8_t version, uint8_t version,
uint32_t width_offset, size_t width_offset,
uint32_t height_offset, size_t height_offset,
uint32_t size_offset, size_t size_offset,
uint32_t relative_position); size_t relative_position);
//@} //@}
//! @name Manipulators //! @name Manipulators
@ -138,7 +138,7 @@ namespace Exiv2
uint32_t pixelWidth() const override; uint32_t pixelWidth() const override;
uint32_t pixelHeight() const override; uint32_t pixelHeight() const override;
//@} //@}
Exiv2::ByteOrder endian_{Exiv2::bigEndian}; Exiv2::ByteOrder endian_{Exiv2::bigEndian};
private: private:

@ -145,7 +145,7 @@ namespace Exiv2 {
@return Return -1 if the %Exifdatum does not have a value yet or the @return Return -1 if the %Exifdatum does not have a value yet or the
value has no data area, else 0. value has no data area, else 0.
*/ */
int setDataArea(const byte* buf, long len); int setDataArea(const byte* buf, size_t len);
//@} //@}
//! @name Accessors //! @name Accessors
@ -183,7 +183,7 @@ namespace Exiv2 {
//! Return the size in bytes of one component of this type //! Return the size in bytes of one component of this type
long typeSize() const override; long typeSize() const override;
//! Return the number of components in the value //! Return the number of components in the value
long count() const override; size_t count() const override;
//! Return the size of the value in bytes //! Return the size of the value in bytes
long size() const override; long size() const override;
//! Return the value as a string. //! Return the value as a string.
@ -195,7 +195,7 @@ namespace Exiv2 {
Value::UniquePtr getValue() const override; Value::UniquePtr getValue() const override;
const Value& value() const override; const Value& value() const override;
//! Return the size of the data area. //! Return the size of the data area.
long sizeDataArea() const; size_t sizeDataArea() const;
/*! /*!
@brief Return a copy of the data area of the value. The caller owns @brief Return a copy of the data area of the value. The caller owns
this copy and %DataBuf ensures that it will be deleted. this copy and %DataBuf ensures that it will be deleted.
@ -254,7 +254,7 @@ namespace Exiv2 {
@param path File name of the thumbnail without extension. @param path File name of the thumbnail without extension.
@return The number of bytes written. @return The number of bytes written.
*/ */
long writeFile(const std::string& path) const; size_t writeFile(const std::string& path) const;
/*! /*!
@brief Return the MIME type of the thumbnail, either \c "image/tiff" @brief Return the MIME type of the thumbnail, either \c "image/tiff"
or \c "image/jpeg". or \c "image/jpeg".
@ -311,12 +311,7 @@ namespace Exiv2 {
applications may have problems with that. (The preview applications may have problems with that. (The preview
application that comes with OS X for one.) - David Harvey. application that comes with OS X for one.) - David Harvey.
*/ */
void setJpegThumbnail( void setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit);
const std::string& path,
URational xres,
URational yres,
uint16_t unit
);
/*! /*!
@brief Set the Exif thumbnail to the JPEG image pointed to by \em buf, @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,
and size \em size. Set XResolution, YResolution and and size \em size. Set XResolution, YResolution and
@ -334,13 +329,7 @@ namespace Exiv2 {
applications may have problems with that. (The preview applications may have problems with that. (The preview
application that comes with OS X for one.) - David Harvey. application that comes with OS X for one.) - David Harvey.
*/ */
void setJpegThumbnail( void setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit);
const byte* buf,
long size,
URational xres,
URational yres,
uint16_t unit
);
/*! /*!
@brief Set the Exif thumbnail to the JPEG image \em path. @brief Set the Exif thumbnail to the JPEG image \em path.
@ -367,7 +356,7 @@ namespace Exiv2 {
@note No checks on the image format or size are performed. @note No checks on the image format or size are performed.
@note Additional existing Exif thumbnail tags are not modified. @note Additional existing Exif thumbnail tags are not modified.
*/ */
void setJpegThumbnail(const byte* buf, long size); void setJpegThumbnail(const byte* buf, size_t size);
/*! /*!
@brief Delete the thumbnail from the Exif data. Removes all @brief Delete the thumbnail from the Exif data. Removes all
Exif.%Thumbnail.*, i.e., Exif IFD1 tags. Exif.%Thumbnail.*, i.e., Exif IFD1 tags.
@ -474,15 +463,14 @@ namespace Exiv2 {
*/ */
const_iterator findKey(const ExifKey& key) const; const_iterator findKey(const ExifKey& key) const;
//! Return true if there is no Exif metadata //! Return true if there is no Exif metadata
bool empty() const { return count() == 0; } bool empty() const { return exifMetadata_.empty(); }
//! Get the number of metadata entries //! Get the number of metadata entries
long count() const { return static_cast<long>(exifMetadata_.size()); } size_t count() const { return exifMetadata_.size(); }
//@} //@}
private: private:
// DATA // DATA
ExifMetadata exifMetadata_; ExifMetadata exifMetadata_;
}; // class ExifData }; // class ExifData
/*! /*!
@ -506,11 +494,7 @@ namespace Exiv2 {
@param size Length of the data buffer @param size Length of the data buffer
@return Byte order in which the data is encoded. @return Byte order in which the data is encoded.
*/ */
static ByteOrder decode( static ByteOrder decode(ExifData& exifData, const byte* pData, size_t size);
ExifData& exifData,
const byte* pData,
uint32_t size
);
/*! /*!
@brief Encode Exif metadata from the provided metadata to binary Exif @brief Encode Exif metadata from the provided metadata to binary Exif
format. format.
@ -552,7 +536,7 @@ namespace Exiv2 {
static WriteMethod encode( static WriteMethod encode(
Blob& blob, Blob& blob,
const byte* pData, const byte* pData,
uint32_t size, size_t size,
ByteOrder byteOrder, ByteOrder byteOrder,
const ExifData& exifData const ExifData& exifData
); );

@ -561,7 +561,7 @@ namespace Exiv2 {
matches that of the data buffer. matches that of the data buffer.
@throw Error If the memory contains data of an unknown image type. @throw Error If the memory contains data of an unknown image type.
*/ */
static Image::UniquePtr open(const byte* data, long size); static Image::UniquePtr open(const byte* data, size_t size);
/*! /*!
@brief Create an Image subclass of the appropriate type by reading @brief Create an Image subclass of the appropriate type by reading
the provided BasicIo instance. %Image type is derived from the the provided BasicIo instance. %Image type is derived from the
@ -630,7 +630,7 @@ namespace Exiv2 {
@param size Number of bytes pointed to by \em data. @param size Number of bytes pointed to by \em data.
@return %Image type or Image::none if the type is not recognized. @return %Image type or Image::none if the type is not recognized.
*/ */
static ImageType getType(const byte* data, long size); static ImageType getType(const byte* data, size_t size);
/*! /*!
@brief Returns the image type of data provided by a BasicIo instance. @brief Returns the image type of data provided by a BasicIo instance.
The passed in \em io instance is (re)opened by this method. The passed in \em io instance is (re)opened by this method.
@ -684,7 +684,7 @@ namespace Exiv2 {
// template, inline and free functions // template, inline and free functions
//! Append \em len bytes pointed to by \em buf to \em blob. //! Append \em len bytes pointed to by \em buf to \em blob.
EXIV2API void append(Exiv2::Blob& blob, const byte* buf, uint32_t len); EXIV2API void append(Exiv2::Blob& blob, const byte* buf, size_t len);
} // namespace Exiv2 } // namespace Exiv2

@ -136,7 +136,7 @@ namespace Exiv2 {
TypeId typeId() const override; TypeId typeId() const override;
const char* typeName() const override; const char* typeName() const override;
long typeSize() const override; long typeSize() const override;
long count() const override; size_t count() const override;
long size() const override; long size() const override;
std::string toString() const override; std::string toString() const override;
std::string toString(long n) const override; std::string toString(long n) const override;
@ -291,23 +291,17 @@ namespace Exiv2 {
@return 0 if successful;<BR> @return 0 if successful;<BR>
5 if the binary IPTC data is invalid or corrupt 5 if the binary IPTC data is invalid or corrupt
*/ */
static int decode( static int decode(IptcData& iptcData, const byte* pData, uint32_t size);
IptcData& iptcData,
const byte* pData,
uint32_t size
);
/*! /*!
@brief Encode the IPTC datasets from \em iptcData to a binary @brief Encode the IPTC datasets from \em iptcData to a binary representation in IPTC IIM4 format.
representation in IPTC IIM4 format.
Convert the IPTC datasets to binary format and return it. Caller owns Convert the IPTC datasets to binary format and return it. Caller owns
the returned buffer. The copied data follows the IPTC IIM4 standard. the returned buffer. The copied data follows the IPTC IIM4 standard.
@return Data buffer containing the binary IPTC data in IPTC IIM4 format. @return Data buffer containing the binary IPTC data in IPTC IIM4 format.
*/ */
static DataBuf encode( static DataBuf encode(const IptcData& iptcData);
const IptcData& iptcData
);
private: private:
// Constant data // Constant data

@ -57,8 +57,7 @@ namespace Exiv2 {
@return true if the IRB marker is known and the buffer is big enough to check this;<BR> @return true if the IRB marker is known and the buffer is big enough to check this;<BR>
false otherwise false otherwise
*/ */
static bool isIrb(const byte* pPsData, static bool isIrb(const byte* pPsData, size_t sizePsData);
long sizePsData);
/*! /*!
@brief Validates all IRBs @brief Validates all IRBs
@ -67,8 +66,7 @@ namespace Exiv2 {
@return true if all IRBs are valid;<BR> @return true if all IRBs are valid;<BR>
false otherwise false otherwise
*/ */
static bool valid(const byte* pPsData, static bool valid(const byte* pPsData, size_t sizePsData);
long sizePsData);
/*! /*!
@brief Locates the data for a %Photoshop tag in a %Photoshop formated memory @brief Locates the data for a %Photoshop tag in a %Photoshop formated memory
buffer. Operates on raw data to simplify reuse. buffer. Operates on raw data to simplify reuse.
@ -87,7 +85,7 @@ namespace Exiv2 {
-2 if the pPsData buffer does not contain valid data. -2 if the pPsData buffer does not contain valid data.
*/ */
static int locateIrb(const byte *pPsData, static int locateIrb(const byte *pPsData,
long sizePsData, size_t sizePsData,
uint16_t psTag, uint16_t psTag,
const byte **record, const byte **record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
@ -96,7 +94,7 @@ namespace Exiv2 {
@brief Forwards to locateIrb() with \em psTag = \em iptc_ @brief Forwards to locateIrb() with \em psTag = \em iptc_
*/ */
static int locateIptcIrb(const byte *pPsData, static int locateIptcIrb(const byte *pPsData,
long sizePsData, size_t sizePsData,
const byte **record, const byte **record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
uint32_t *const sizeData); uint32_t *const sizeData);
@ -104,7 +102,7 @@ namespace Exiv2 {
@brief Forwards to locatePreviewIrb() with \em psTag = \em preview_ @brief Forwards to locatePreviewIrb() with \em psTag = \em preview_
*/ */
static int locatePreviewIrb(const byte *pPsData, static int locatePreviewIrb(const byte *pPsData,
long sizePsData, size_t sizePsData,
const byte **record, const byte **record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
uint32_t *const sizeData); uint32_t *const sizeData);
@ -117,9 +115,7 @@ namespace Exiv2 {
@param iptcData Iptc data to embed, may be empty @param iptcData Iptc data to embed, may be empty
@return A data buffer containing the new IRB buffer, may have 0 size @return A data buffer containing the new IRB buffer, may have 0 size
*/ */
static DataBuf setIptcIrb(const byte* pPsData, static DataBuf setIptcIrb(const byte* pPsData, size_t sizePsData, const IptcData& iptcData);
long sizePsData,
const IptcData& iptcData);
}; // class Photoshop }; // class Photoshop
@ -132,13 +128,6 @@ namespace Exiv2 {
//@{ //@{
void readMetadata() override; void readMetadata() override;
void writeMetadata() override; void writeMetadata() override;
/*!
@brief Print out the structure of image file.
@throw Error if reading of the file fails or the image data is
not valid (does not look like data of the specific image type).
@warning This function is not thread safe and intended for exiv2 -pS for debugging.
*/
void printStructure(std::ostream& out, PrintStructureOption option, int depth) override; void printStructure(std::ostream& out, PrintStructureOption option, int depth) override;
//@} //@}
@ -177,7 +166,7 @@ namespace Exiv2 {
BasicIo::UniquePtr io, BasicIo::UniquePtr io,
bool create, bool create,
const byte initData[], const byte initData[],
long dataSize); size_t dataSize);
//@} //@}
//! @name Accessors //! @name Accessors
@ -254,7 +243,7 @@ namespace Exiv2 {
@return 0 if successful;<BR> @return 0 if successful;<BR>
4 if the image can not be written to. 4 if the image can not be written to.
*/ */
int initImage(const byte initData[], long dataSize); int initImage(const byte initData[], size_t dataSize);
/*! /*!
@brief Provides the main implementation of writeMetadata() by @brief Provides the main implementation of writeMetadata() by
writing all buffered metadata to the provided BasicIo. writing all buffered metadata to the provided BasicIo.
@ -279,6 +268,8 @@ namespace Exiv2 {
byte advanceToMarker(ErrorCode err) const; byte advanceToMarker(ErrorCode err) const;
//@} //@}
DataBuf readNextSegment(byte marker);
/*! /*!
@brief Is the marker followed by a non-zero payload? @brief Is the marker followed by a non-zero payload?
@param marker The marker at the start of a segment @param marker The marker at the start of a segment

@ -206,7 +206,7 @@ namespace Exiv2 {
//! Return the size in bytes of one component of this type //! Return the size in bytes of one component of this type
virtual long typeSize() const =0; virtual long typeSize() const =0;
//! Return the number of components in the value //! Return the number of components in the value
virtual long count() const =0; virtual size_t count() const =0;
//! Return the size of the value in bytes //! Return the size of the value in bytes
virtual long size() const =0; virtual long size() const =0;
//! Return the value as a string. //! Return the value as a string.

@ -44,7 +44,7 @@ namespace Exiv2 {
//! Preview image extension. //! Preview image extension.
std::string extension_; std::string extension_;
//! Preview image size in bytes. //! Preview image size in bytes.
uint32_t size_; size_t size_;
//! Preview image width in pixels or 0 for unknown width. //! Preview image width in pixels or 0 for unknown width.
uint32_t width_; uint32_t width_;
//! Preview image height in pixels or 0 for unknown height. //! Preview image height in pixels or 0 for unknown height.
@ -99,7 +99,7 @@ namespace Exiv2 {
@param path File name of the preview image without extension. @param path File name of the preview image without extension.
@return The number of bytes written. @return The number of bytes written.
*/ */
long writeFile(const std::string& path) const; size_t writeFile(const std::string& path) const;
/*! /*!
@brief Return the MIME type of the preview image, usually either @brief Return the MIME type of the preview image, usually either
\c "image/tiff" or \c "image/jpeg". \c "image/tiff" or \c "image/jpeg".

@ -135,7 +135,7 @@ namespace Exiv2 {
IptcData& iptcData, IptcData& iptcData,
XmpData& xmpData, XmpData& xmpData,
const byte* pData, const byte* pData,
uint32_t size size_t size
); );
/*! /*!
@brief Encode metadata from the provided metadata to TIFF format. @brief Encode metadata from the provided metadata to TIFF format.

@ -152,7 +152,7 @@ namespace Exiv2 {
//! Return the type id for a type name //! Return the type id for a type name
static TypeId typeId(const std::string& typeName); static TypeId typeId(const std::string& typeName);
//! Return the size in bytes of one element of this type //! Return the size in bytes of one element of this type
static long typeSize(TypeId typeId); static size_t typeSize(TypeId typeId);
}; };
@ -166,56 +166,39 @@ namespace Exiv2 {
//! @name Creators //! @name Creators
//@{ //@{
//! Default constructor //! Default constructor
DataBuf(); DataBuf() = default;
//! Constructor with an initial buffer size //! Constructor with an initial buffer size
explicit DataBuf(long size); explicit DataBuf(size_t size);
//! Constructor, copies an existing buffer //! Constructor, copies an existing buffer
DataBuf(const byte* pData, long size); DataBuf(const byte* pData, size_t size);
/*!
@brief Copy constructor. Copies an existing DataBuf.
*/
DataBuf(const DataBuf& rhs);
/*!
@brief Move constructor. Transfers the buffer to the newly created
object similar to std::unique_ptr, i.e., the original object is
modified.
*/
DataBuf(DataBuf&& rhs);
//! Destructor, deletes the allocated buffer
~DataBuf();
//@} //@}
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Assignment operator. Transfers the buffer and releases the
buffer at the original object similar to std::unique_ptr, i.e.,
the original object is modified.
*/
DataBuf& operator=(DataBuf&& rhs);
// No copy assignment.
DataBuf& operator=(const DataBuf&) = delete;
/*! /*!
@brief Allocate a data buffer of at least the given size. Note that if @brief Allocate a data buffer of at least the given size. Note that if
the requested \em size is less than the current buffer size, no the requested \em size is less than the current buffer size, no
new memory is allocated and the buffer size doesn't change. new memory is allocated and the buffer size doesn't change.
*/ */
void alloc(long size); void alloc(size_t size);
/*! /*!
@brief Resize the buffer. Existing data is preserved (like std::realloc()). @brief Resize the buffer. Existing data is preserved (like std::realloc()).
*/ */
void resize(long size); void resize(size_t size);
//! Reset value //! Reset value
void reset(); void reset();
//@} //@}
//! Fill the buffer with zeros. using iterator = std::vector<byte>::iterator;
void clear(); using const_iterator = std::vector<byte>::const_iterator;
inline iterator begin() noexcept { return pData_.begin(); }
inline const_iterator cbegin() const noexcept { return pData_.cbegin(); }
inline iterator end() noexcept { return pData_.end(); }
inline const_iterator cend() const noexcept { return pData_.end(); }
long size() const { return size_; } size_t size() const { return pData_.size(); }
uint8_t read_uint8(size_t offset) const; uint8_t read_uint8(size_t offset) const;
void write_uint8(size_t offset, uint8_t x); void write_uint8(size_t offset, uint8_t x);
@ -244,13 +227,11 @@ namespace Exiv2 {
//! Returns a (read-only) C-style string pointer. //! Returns a (read-only) C-style string pointer.
const char* c_str(size_t offset = 0) const; const char* c_str(size_t offset = 0) const;
bool empty() const {return pData_.empty(); }
private: private:
// DATA std::vector<byte> pData_;
//! Pointer to the buffer, 0 if none has been allocated };
byte* pData_;
//! The current size of the buffer
long size_;
}; // class DataBuf
/*! /*!
* @brief Create a new Slice from a DataBuf given the bounds. * @brief Create a new Slice from a DataBuf given the bounds.

@ -58,18 +58,17 @@ namespace Exiv2 {
//! Virtual destructor. //! Virtual destructor.
virtual ~Value() = default; virtual ~Value() = default;
//@} //@}
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Read the value from a character buffer.
@param buf Pointer to the data buffer to read from /// @brief Read the value from a character buffer.
@param len Number of bytes in the data buffer /// @param buf Pointer to the data buffer to read from
@param byteOrder Applicable byte order (little or big endian). /// @param len Number of bytes in the data buffer
/// @param byteOrder Applicable byte order (little or big endian).
/// @return 0 if successful.
virtual int read(const byte* buf, size_t len, ByteOrder byteOrder) =0;
@return 0 if successful.
*/
virtual int read(const byte* buf, long len, ByteOrder byteOrder) =0;
/*! /*!
@brief Set the value from a string buffer. The format of the string @brief Set the value from a string buffer. The format of the string
corresponds to that of the write() method, i.e., a string corresponds to that of the write() method, i.e., a string
@ -93,7 +92,7 @@ namespace Exiv2 {
@param len Size of the data area @param len Size of the data area
@return Return -1 if the value has no data area, else 0. @return Return -1 if the value has no data area, else 0.
*/ */
virtual int setDataArea(const byte* buf, long len); virtual int setDataArea(const byte* buf, size_t len);
//@} //@}
//! @name Accessors //! @name Accessors
@ -118,9 +117,9 @@ namespace Exiv2 {
*/ */
virtual long copy(byte* buf, ByteOrder byteOrder) const =0; virtual long copy(byte* buf, ByteOrder byteOrder) const =0;
//! Return the number of components of the value //! Return the number of components of the value
virtual long count() const =0; virtual size_t count() const =0;
//! Return the size of the value in bytes //! Return the size of the value in bytes
virtual long size() const =0; virtual size_t size() const =0;
/*! /*!
@brief Write the value to an output stream. You do not usually have @brief Write the value to an output stream. You do not usually have
to use this function; it is used for the implementation of to use this function; it is used for the implementation of
@ -139,7 +138,7 @@ namespace Exiv2 {
of this method may be undefined if there is no <EM>n</EM>-th of this method may be undefined if there is no <EM>n</EM>-th
component. component.
*/ */
virtual std::string toString(long n) const; virtual std::string toString(size_t n) const;
/*! /*!
@brief Convert the <EM>n</EM>-th component of the value to an int64_t. @brief Convert the <EM>n</EM>-th component of the value to an int64_t.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
@ -147,7 +146,7 @@ namespace Exiv2 {
@return The converted value. @return The converted value.
*/ */
virtual int64_t toInt64(long n =0) const =0; virtual int64_t toInt64(size_t n =0) const =0;
/*! /*!
@brief Convert the <EM>n</EM>-th component of the value to a float. @brief Convert the <EM>n</EM>-th component of the value to a float.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
@ -155,7 +154,7 @@ namespace Exiv2 {
@return The converted value. @return The converted value.
*/ */
virtual uint32_t toUint32(long n =0) const =0; virtual uint32_t toUint32(size_t n =0) const =0;
/*! /*!
@brief Convert the <EM>n</EM>-th component of the value to a float. @brief Convert the <EM>n</EM>-th component of the value to a float.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
@ -163,7 +162,7 @@ namespace Exiv2 {
@return The converted value. @return The converted value.
*/ */
virtual float toFloat(long n =0) const =0; virtual float toFloat(size_t n =0) const =0;
/*! /*!
@brief Convert the <EM>n</EM>-th component of the value to a Rational. @brief Convert the <EM>n</EM>-th component of the value to a Rational.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
@ -171,9 +170,9 @@ namespace Exiv2 {
@return The converted value. @return The converted value.
*/ */
virtual Rational toRational(long n =0) const =0; virtual Rational toRational(size_t n =0) const =0;
//! Return the size of the data area, 0 if there is none. //! Return the size of the data area, 0 if there is none.
virtual long sizeDataArea() const; virtual size_t sizeDataArea() const;
/*! /*!
@brief Return a copy of the data area if the value has one. The @brief Return a copy of the data area if the value has one. The
caller owns this copy and DataBuf ensures that it will be caller owns this copy and DataBuf ensures that it will be
@ -246,8 +245,7 @@ namespace Exiv2 {
virtual Value* clone_() const =0; virtual Value* clone_() const =0;
// DATA // DATA
TypeId type_; //!< Type of the data TypeId type_; //!< Type of the data
};
}; // class Value
//! Output operator for Value types //! Output operator for Value types
inline std::ostream& operator<<(std::ostream& os, const Value& value) inline std::ostream& operator<<(std::ostream& os, const Value& value)
@ -271,19 +269,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
@brief Read the value from a character buffer.
@note The byte order is required by the interface but not
used by this method, so just use the default.
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful.
*/
int read(const byte* buf, long len, ByteOrder byteOrder = invalidByteOrder) override;
//! Set the data from a string of integer values (e.g., "0 1 2 3") //! Set the data from a string of integer values (e.g., "0 1 2 3")
int read(const std::string& buf) override; int read(const std::string& buf) override;
//@} //@}
@ -305,19 +291,19 @@ namespace Exiv2 {
@return Number of characters written. @return Number of characters written.
*/ */
long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override; long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
long count() const override; size_t count() const override;
long size() const override; size_t size() const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
/*! /*!
@brief Return the <EM>n</EM>-th component of the value as a string. @brief Return the <EM>n</EM>-th component of the value as a string.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
<EM>n</EM>-th component. <EM>n</EM>-th component.
*/ */
std::string toString(long n) const override; std::string toString(size_t n) const override;
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
//@} //@}
private: private:
@ -358,19 +344,7 @@ namespace Exiv2 {
//@{ //@{
//! Read the value from buf. This default implementation uses buf as it is. //! Read the value from buf. This default implementation uses buf as it is.
int read(const std::string& buf) override; int read(const std::string& buf) override;
/*! int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
@brief Read the value from a character buffer.
@note The byte order is required by the interface but not used by this
method, so just use the default.
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful.
*/
int read(const byte* buf, long len, ByteOrder byteOrder = invalidByteOrder) override;
//@} //@}
//! @name Accessors //! @name Accessors
@ -390,12 +364,12 @@ namespace Exiv2 {
@return Number of characters written. @return Number of characters written.
*/ */
long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override; long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
long count() const override; size_t count() const override;
long size() const override; size_t size() const override;
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
//@} //@}
@ -568,10 +542,7 @@ namespace Exiv2 {
1 if an invalid character set is encountered 1 if an invalid character set is encountered
*/ */
int read(const std::string& comment) override; int read(const std::string& comment) override;
/*! int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
@brief Read the comment from a byte buffer.
*/
int read(const byte* buf, long len, ByteOrder byteOrder) override;
//@} //@}
//! @name Accessors //! @name Accessors
@ -646,7 +617,7 @@ namespace Exiv2 {
XmpArrayType xmpArrayType() const; XmpArrayType xmpArrayType() const;
//! Return XMP struct, indicates if an XMP value is a structure. //! Return XMP struct, indicates if an XMP value is a structure.
XmpStruct xmpStruct() const; XmpStruct xmpStruct() const;
long size() const override; size_t size() const override;
/*! /*!
@brief Write value to a character data buffer. @brief Write value to a character data buffer.
@ -669,21 +640,9 @@ namespace Exiv2 {
void setXmpArrayType(XmpArrayType xmpArrayType); void setXmpArrayType(XmpArrayType xmpArrayType);
//! Set the XMP struct type to indicate that an XMP value is a structure. //! Set the XMP struct type to indicate that an XMP value is a structure.
void setXmpStruct(XmpStruct xmpStruct =xsStruct); void setXmpStruct(XmpStruct xmpStruct =xsStruct);
/*!
@brief Read the value from a character buffer.
Uses read(const std::string& buf)
@note The byte order is required by the interface but not used by this /// @note Uses read(const std::string& buf)
method, so just use the default. int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful.
*/
int read(const byte* buf, long len, ByteOrder byteOrder = invalidByteOrder) override;
int read(const std::string& buf) override = 0; int read(const std::string& buf) override = 0;
//@} //@}
@ -744,36 +703,36 @@ namespace Exiv2 {
//! @name Accessors //! @name Accessors
//@{ //@{
UniquePtr clone() const; UniquePtr clone() const;
long size() const override; size_t size() const override;
long count() const override; size_t count() const override;
/*! /*!
@brief Convert the value to an int64_t. @brief Convert the value to an int64_t.
The optional parameter \em n is not used and is ignored. The optional parameter \em n is not used and is ignored.
@return The converted value. @return The converted value.
*/ */
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
/*! /*!
@brief Convert the value to an uint32_t. @brief Convert the value to an uint32_t.
The optional parameter \em n is not used and is ignored. The optional parameter \em n is not used and is ignored.
@return The converted value. @return The converted value.
*/ */
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
/*! /*!
@brief Convert the value to a float. @brief Convert the value to a float.
The optional parameter \em n is not used and is ignored. The optional parameter \em n is not used and is ignored.
@return The converted value. @return The converted value.
*/ */
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
/*! /*!
@brief Convert the value to a Rational. @brief Convert the value to a Rational.
The optional parameter \em n is not used and is ignored. The optional parameter \em n is not used and is ignored.
@return The converted value. @return The converted value.
*/ */
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
//@} //@}
@ -826,17 +785,17 @@ namespace Exiv2 {
//! @name Accessors //! @name Accessors
//@{ //@{
UniquePtr clone() const; UniquePtr clone() const;
long count() const override; size_t count() const override;
/*! /*!
@brief Return the <EM>n</EM>-th component of the value as a string. @brief Return the <EM>n</EM>-th component of the value as a string.
The behaviour of this method may be undefined if there is no The behaviour of this method may be undefined if there is no
<EM>n</EM>-th component. <EM>n</EM>-th component.
*/ */
std::string toString(long n) const override; std::string toString(size_t n) const override;
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
/*! /*!
@brief Write all elements of the value to \em os, separated by commas. @brief Write all elements of the value to \em os, separated by commas.
@ -925,7 +884,7 @@ namespace Exiv2 {
//! @name Accessors //! @name Accessors
//@{ //@{
UniquePtr clone() const; UniquePtr clone() const;
long count() const override; size_t count() const override;
/*! /*!
@brief Return the text value associated with the default language @brief Return the text value associated with the default language
qualifier \c x-default. The parameter \em n is not used, but qualifier \c x-default. The parameter \em n is not used, but
@ -933,17 +892,17 @@ namespace Exiv2 {
string and sets the ok-flag to \c false if there is no string and sets the ok-flag to \c false if there is no
default value. default value.
*/ */
std::string toString(long n) const override; std::string toString(size_t n) const override;
/*! /*!
@brief Return the text value associated with the language qualifier @brief Return the text value associated with the language qualifier
\em qualifier. Returns an empty string and sets the ok-flag \em qualifier. Returns an empty string and sets the ok-flag
to \c false if there is no entry for the language qualifier. to \c false if there is no entry for the language qualifier.
*/ */
std::string toString(const std::string& qualifier) const; std::string toString(const std::string& qualifier) const;
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
/*! /*!
@brief Write all elements of the value to \em os, separated by commas. @brief Write all elements of the value to \em os, separated by commas.
@ -999,20 +958,10 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Read the value from a character buffer.
@note The byte order is required by the interface but not used by this
method, so just use the default.
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful<BR> /// @return 0 if successful<BR>
1 in case of an unsupported date format /// 1 in case of an unsupported date format
*/ int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
int read(const byte* buf, long len, ByteOrder byteOrder = invalidByteOrder) override;
/*! /*!
@brief Set the value to that of the string buf. @brief Set the value to that of the string buf.
@ -1046,17 +995,17 @@ namespace Exiv2 {
//! Return date struct containing date information //! Return date struct containing date information
virtual const Date& getDate() const; virtual const Date& getDate() const;
long count() const override; size_t count() const override;
long size() const override; size_t size() const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
//! Return the value as a UNIX calender time converted to int64_t. //! Return the value as a UNIX calender time converted to int64_t.
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
//! Return the value as a UNIX calender time converted to uint32_t. //! Return the value as a UNIX calender time converted to uint32_t.
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
//! Return the value as a UNIX calender time converted to float. //! Return the value as a UNIX calender time converted to float.
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
//! Return the value as a UNIX calender time converted to Rational. //! Return the value as a UNIX calender time converted to Rational.
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
//@} //@}
private: private:
@ -1107,20 +1056,10 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Read the value from a character buffer.
@note The byte order is required by the interface but not used by this
method, so just use the default.
@param buf Pointer to the data buffer to read from /// @return 0 if successful<BR>
@param len Number of bytes in the data buffer /// 1 in case of an unsupported time format
@param byteOrder Byte order. Not needed. int read(const byte* buf, size_t len, ByteOrder byteOrder = invalidByteOrder) override;
@return 0 if successful<BR>
1 in case of an unsupported time format
*/
int read(const byte* buf, long len, ByteOrder byteOrder = invalidByteOrder) override;
/*! /*!
@brief Set the value to that of the string buf. @brief Set the value to that of the string buf.
@ -1153,17 +1092,17 @@ namespace Exiv2 {
long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override; long copy(byte* buf, ByteOrder byteOrder = invalidByteOrder) const override;
//! Return time struct containing time information //! Return time struct containing time information
virtual const Time& getTime() const; virtual const Time& getTime() const;
long count() const override; size_t count() const override;
long size() const override; size_t size() const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
//! Returns number of seconds in the day in UTC. //! Returns number of seconds in the day in UTC.
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
//! Returns number of seconds in the day in UTC. //! Returns number of seconds in the day in UTC.
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
//! Returns number of seconds in the day in UTC converted to float. //! Returns number of seconds in the day in UTC converted to float.
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
//! Returns number of seconds in the day in UTC converted to Rational. //! Returns number of seconds in the day in UTC converted to Rational.
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
//@} //@}
private: private:
@ -1233,7 +1172,7 @@ namespace Exiv2 {
//@{ //@{
//! Assignment operator. //! Assignment operator.
ValueType<T>& operator=(const ValueType<T>& rhs); ValueType<T>& operator=(const ValueType<T>& rhs);
int read(const byte* buf, long len, ByteOrder byteOrder) override; int read(const byte* buf, size_t len, ByteOrder byteOrder) override;
/*! /*!
@brief Set the data from a string of values of type T (e.g., @brief Set the data from a string of values of type T (e.g.,
"0 1 2 3" or "1/2 1/3 1/4" depending on what T is). "0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
@ -1245,15 +1184,15 @@ namespace Exiv2 {
@brief Set the data area. This method copies (clones) the buffer @brief Set the data area. This method copies (clones) the buffer
pointed to by buf. pointed to by buf.
*/ */
int setDataArea(const byte* buf, long len) override; int setDataArea(const byte* buf, size_t len) override;
//@} //@}
//! @name Accessors //! @name Accessors
//@{ //@{
UniquePtr clone() const { return UniquePtr(clone_()); } UniquePtr clone() const { return UniquePtr(clone_()); }
long copy(byte* buf, ByteOrder byteOrder) const override; long copy(byte* buf, ByteOrder byteOrder) const override;
long count() const override; size_t count() const override;
long size() const override; size_t size() const override;
std::ostream& write(std::ostream& os) const override; std::ostream& write(std::ostream& os) const override;
/*! /*!
@brief Return the <EM>n</EM>-th component of the value as a string. @brief Return the <EM>n</EM>-th component of the value as a string.
@ -1261,13 +1200,13 @@ namespace Exiv2 {
<EM>n</EM>-th <EM>n</EM>-th
component. component.
*/ */
std::string toString(long n) const override; std::string toString(size_t n) const override;
int64_t toInt64(long n = 0) const override; int64_t toInt64(size_t n = 0) const override;
uint32_t toUint32(long n = 0) const override; uint32_t toUint32(size_t n = 0) const override;
float toFloat(long n = 0) const override; float toFloat(size_t n = 0) const override;
Rational toRational(long n = 0) const override; Rational toRational(size_t n = 0) const override;
//! Return the size of the data area. //! Return the size of the data area.
long sizeDataArea() const override; size_t sizeDataArea() const override;
/*! /*!
@brief Return a copy of the data area in a DataBuf. The caller owns @brief Return a copy of the data area in a DataBuf. The caller owns
this copy and DataBuf ensures that it will be deleted. this copy and DataBuf ensures that it will be deleted.
@ -1294,7 +1233,7 @@ namespace Exiv2 {
private: private:
//! Utility for toInt64, toUint32, etc. //! Utility for toInt64, toUint32, etc.
template<typename I> template<typename I>
inline I float_to_integer_helper(long n) const { inline I float_to_integer_helper(size_t n) const {
const auto v = value_.at(n); const auto v = value_.at(n);
if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v && if (static_cast<decltype(v)>(std::numeric_limits<I>::min()) <= v &&
v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) { v <= static_cast<decltype(v)>(std::numeric_limits<I>::max())) {
@ -1306,7 +1245,7 @@ namespace Exiv2 {
//! Utility for toInt64, toUint32, etc. //! Utility for toInt64, toUint32, etc.
template<typename I> template<typename I>
inline I rational_to_integer_helper(long n) const { inline I rational_to_integer_helper(size_t n) const {
const auto& t = value_.at(n); const auto& t = value_.at(n);
const auto a = t.first; const auto a = t.first;
const auto b = t.second; const auto b = t.second;
@ -1355,7 +1294,7 @@ namespace Exiv2 {
//! Pointer to the buffer, nullptr if none has been allocated //! Pointer to the buffer, nullptr if none has been allocated
byte* pDataArea_{nullptr}; byte* pDataArea_{nullptr};
//! The current size of the buffer //! The current size of the buffer
long sizeDataArea_{0}; size_t sizeDataArea_{0};
}; // class ValueType }; // class ValueType
//! Unsigned short value type //! Unsigned short value type
@ -1586,13 +1525,13 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
int ValueType<T>::read(const byte* buf, long len, ByteOrder byteOrder) int ValueType<T>::read(const byte* buf, size_t len, ByteOrder byteOrder)
{ {
value_.clear(); value_.clear();
long ts = TypeInfo::typeSize(typeId()); size_t ts = TypeInfo::typeSize(typeId());
if (ts > 0) if (ts > 0)
if (len % ts != 0) len = (len / ts) * ts; if (len % ts != 0) len = (len / ts) * ts;
for (long 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));
} }
return 0; return 0;
@ -1624,13 +1563,13 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
long ValueType<T>::count() const size_t ValueType<T>::count() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
template<typename T> template<typename T>
long ValueType<T>::size() const size_t ValueType<T>::size() const
{ {
return static_cast<long>(TypeInfo::typeSize(typeId()) * value_.size()); return static_cast<long>(TypeInfo::typeSize(typeId()) * value_.size());
} }
@ -1655,7 +1594,7 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
std::string ValueType<T>::toString(long n) const std::string ValueType<T>::toString(size_t n) const
{ {
ok_ = true; ok_ = true;
return Exiv2::toString<T>(value_.at(n)); return Exiv2::toString<T>(value_.at(n));
@ -1663,13 +1602,13 @@ namespace Exiv2 {
// Default implementation // Default implementation
template<typename T> template<typename T>
int64_t ValueType<T>::toInt64(long n) const int64_t ValueType<T>::toInt64(size_t n) const
{ {
ok_ = true; ok_ = true;
return static_cast<int64_t>(value_.at(n)); return static_cast<int64_t>(value_.at(n));
} }
template<typename T> template<typename T>
uint32_t ValueType<T>::toUint32(long n) const uint32_t ValueType<T>::toUint32(size_t n) const
{ {
ok_ = true; ok_ = true;
return static_cast<uint32_t>(value_.at(n)); return static_cast<uint32_t>(value_.at(n));
@ -1678,58 +1617,59 @@ namespace Exiv2 {
#define LARGE_INT 1000000 #define LARGE_INT 1000000
// Specialization for double // Specialization for double
template<> template<>
inline int64_t ValueType<double>::toInt64(long n) const inline int64_t ValueType<double>::toInt64(size_t n) const
{ {
return float_to_integer_helper<int64_t>(n); return float_to_integer_helper<int64_t>(n);
} }
template<> template<>
inline uint32_t ValueType<double>::toUint32(long n) const inline uint32_t ValueType<double>::toUint32(size_t n) const
{ {
return float_to_integer_helper<uint32_t>(n); return float_to_integer_helper<uint32_t>(n);
} }
// Specialization for float // Specialization for float
template<> template<>
inline int64_t ValueType<float>::toInt64(long n) const inline int64_t ValueType<float>::toInt64(size_t n) const
{ {
return float_to_integer_helper<int64_t>(n); return float_to_integer_helper<int64_t>(n);
} }
template<> template<>
inline uint32_t ValueType<float>::toUint32(long n) const inline uint32_t ValueType<float>::toUint32(size_t n) const
{ {
return float_to_integer_helper<uint32_t>(n); return float_to_integer_helper<uint32_t>(n);
} }
// Specialization for rational // Specialization for rational
template<> template<>
inline int64_t ValueType<Rational>::toInt64(long n) const inline int64_t ValueType<Rational>::toInt64(size_t n) const
{ {
return rational_to_integer_helper<int64_t>(n); return rational_to_integer_helper<int64_t>(n);
} }
template<> template<>
inline uint32_t ValueType<Rational>::toUint32(long n) const inline uint32_t ValueType<Rational>::toUint32(size_t n) const
{ {
return rational_to_integer_helper<uint32_t>(n); return rational_to_integer_helper<uint32_t>(n);
} }
// Specialization for unsigned rational // Specialization for unsigned rational
template<> template<>
inline int64_t ValueType<URational>::toInt64(long n) const inline int64_t ValueType<URational>::toInt64(size_t n) const
{ {
return rational_to_integer_helper<int64_t>(n); return rational_to_integer_helper<int64_t>(n);
} }
template<> template<>
inline uint32_t ValueType<URational>::toUint32(long n) const inline uint32_t ValueType<URational>::toUint32(size_t n) const
{ {
return rational_to_integer_helper<uint32_t>(n); return rational_to_integer_helper<uint32_t>(n);
} }
// Default implementation // Default implementation
template<typename T> template<typename T>
float ValueType<T>::toFloat(long n) const float ValueType<T>::toFloat(size_t n) const
{ {
ok_ = true; ok_ = true;
return static_cast<float>(value_.at(n)); return static_cast<float>(value_.at(n));
} }
// Specialization for rational // Specialization for rational
template<> template<>
inline float ValueType<Rational>::toFloat(long n) const inline float ValueType<Rational>::toFloat(size_t n) const
{ {
ok_ = (value_.at(n).second != 0); ok_ = (value_.at(n).second != 0);
if (!ok_) return 0.0f; if (!ok_) return 0.0f;
@ -1737,7 +1677,7 @@ namespace Exiv2 {
} }
// Specialization for unsigned rational // Specialization for unsigned rational
template<> template<>
inline float ValueType<URational>::toFloat(long n) const inline float ValueType<URational>::toFloat(size_t n) const
{ {
ok_ = (value_.at(n).second != 0); ok_ = (value_.at(n).second != 0);
if (!ok_) return 0.0f; if (!ok_) return 0.0f;
@ -1745,28 +1685,28 @@ namespace Exiv2 {
} }
// Default implementation // Default implementation
template<typename T> template<typename T>
Rational ValueType<T>::toRational(long n) const Rational ValueType<T>::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
return {value_.at(n), 1}; return {value_.at(n), 1};
} }
// Specialization for rational // Specialization for rational
template<> template<>
inline Rational ValueType<Rational>::toRational(long n) const inline Rational ValueType<Rational>::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
return {value_.at(n).first, value_.at(n).second}; return {value_.at(n).first, value_.at(n).second};
} }
// Specialization for unsigned rational // Specialization for unsigned rational
template<> template<>
inline Rational ValueType<URational>::toRational(long n) const inline Rational ValueType<URational>::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
return {value_.at(n).first, value_.at(n).second}; return {value_.at(n).first, value_.at(n).second};
} }
// Specialization for float. // Specialization for float.
template<> template<>
inline Rational ValueType<float>::toRational(long n) const inline Rational ValueType<float>::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
// Warning: This is a very simple conversion, see floatToRationalCast() // Warning: This is a very simple conversion, see floatToRationalCast()
@ -1774,7 +1714,7 @@ namespace Exiv2 {
} }
// Specialization for double. // Specialization for double.
template<> template<>
inline Rational ValueType<double>::toRational(long n) const inline Rational ValueType<double>::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
// Warning: This is a very simple conversion, see floatToRationalCast() // Warning: This is a very simple conversion, see floatToRationalCast()
@ -1782,7 +1722,7 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
long ValueType<T>::sizeDataArea() const size_t ValueType<T>::sizeDataArea() const
{ {
return sizeDataArea_; return sizeDataArea_;
} }
@ -1794,7 +1734,7 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
int ValueType<T>::setDataArea(const byte* buf, long len) int ValueType<T>::setDataArea(const byte* buf, size_t len)
{ {
byte* tmp = nullptr; byte* tmp = nullptr;
if (len > 0) { if (len > 0) {

@ -131,7 +131,7 @@ namespace Exiv2 {
// Todo: Remove this method from the baseclass // Todo: Remove this method from the baseclass
//! The Exif typeSize doesn't make sense here. Return 0. //! The Exif typeSize doesn't make sense here. Return 0.
long typeSize() const override; long typeSize() const override;
long count() const override; size_t count() const override;
long size() const override; long size() const override;
std::string toString() const override; std::string toString() const override;
std::string toString(long n) const override; std::string toString(long n) const override;

@ -57,7 +57,7 @@ try {
std::cout << "Added a few tags the quick way.\n"; std::cout << "Added a few tags the quick way.\n";
// Create a ASCII string value (note the use of create) // Create a ASCII string value (note the use of create)
Exiv2::Value::UniquePtr v = Exiv2::Value::create(Exiv2::asciiString); auto v = Exiv2::Value::create(Exiv2::asciiString);
// Set the value to a string // Set the value to a string
v->read("1999:12:31 23:59:59"); v->read("1999:12:31 23:59:59");
// Add the value together with its key to the Exif data container // Add the value together with its key to the Exif data container
@ -66,16 +66,16 @@ try {
std::cout << "Added key \"" << key << "\", value \"" << *v << "\"\n"; std::cout << "Added key \"" << key << "\", value \"" << *v << "\"\n";
// Now create a more interesting value (without using the create method) // Now create a more interesting value (without using the create method)
Exiv2::URationalValue::UniquePtr rv(new Exiv2::URationalValue); Exiv2::URationalValue rv;
// Set two rational components from a string // Set two rational components from a string
rv->read("1/2 1/3"); rv.read("1/2 1/3");
// Add more elements through the extended interface of rational value // Add more elements through the extended interface of rational value
rv->value_.emplace_back(2, 3); rv.value_.emplace_back(2, 3);
rv->value_.emplace_back(3, 4); rv.value_.emplace_back(3, 4);
// Add the key and value pair to the Exif data // Add the key and value pair to the Exif data
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities"); key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
exifData.add(key, rv.get()); exifData.add(key, &rv);
std::cout << "Added key \"" << key << "\", value \"" << *rv << "\"\n"; std::cout << "Added key \"" << key << "\", value \"" << rv << "\"\n";
// ************************************************************************* // *************************************************************************
// Modify Exif data // Modify Exif data
@ -92,18 +92,21 @@ try {
// Alternatively, we can use findKey() // Alternatively, we can use findKey()
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities"); key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
auto pos = exifData.findKey(key); auto pos = exifData.findKey(key);
if (pos == exifData.end()) throw Exiv2::Error(Exiv2::kerErrorMessage, "Key not found"); if (pos == exifData.end())
throw Exiv2::Error(Exiv2::kerErrorMessage, "Key not found");
// Get a pointer to a copy of the value // Get a pointer to a copy of the value
v = pos->getValue(); v = pos->getValue();
// Downcast the Value pointer to its actual type // Downcast the Value pointer to its actual type
auto prv = dynamic_cast<Exiv2::URationalValue*>(v.release()); auto prv = dynamic_cast<Exiv2::URationalValue*>(v.get());
if (prv == nullptr) if (prv == nullptr)
throw Exiv2::Error(Exiv2::kerErrorMessage, "Downcast failed"); throw Exiv2::Error(Exiv2::kerErrorMessage, "Downcast failed");
rv = Exiv2::URationalValue::UniquePtr(prv);
rv = Exiv2::URationalValue(*prv);
// Modify the value directly through the interface of URationalValue // Modify the value directly through the interface of URationalValue
rv->value_.at(2) = {88, 77}; rv.value_.at(2) = {88, 77};
// Copy the modified value back to the metadatum // Copy the modified value back to the metadatum
pos->setValue(rv.get()); pos->setValue(&rv);
std::cout << "Modified key \"" << key std::cout << "Modified key \"" << key
<< "\", new value \"" << pos->value() << "\"\n"; << "\", new value \"" << pos->value() << "\"\n";

@ -65,8 +65,10 @@ int main(int argc, char* const argv[])
if ( argc >= 5 ) { if ( argc >= 5 ) {
int blocksize = argc==6 ? atoi(ba) : 10000; int blocksize = argc==6 ? atoi(ba) : 10000;
// ensure blocksize is sane // ensure blocksize is sane
if (blocksize>1024*1024) blocksize=10000; if (blocksize>1024*1024)
Exiv2::byte* bytes = blocksize > 0 ? new Exiv2::byte[blocksize] : nullptr; blocksize=10000;
std::vector<Exiv2::byte> bytes (blocksize);
// copy fileIn from a remote location. // copy fileIn from a remote location.
BasicIo::UniquePtr io = Exiv2::ImageFactory::createIo(fr); BasicIo::UniquePtr io = Exiv2::ImageFactory::createIo(fr);
@ -78,11 +80,11 @@ int main(int argc, char* const argv[])
Error(Exiv2::kerFileOpenFailed, output.path() , "w+b", strError()); Error(Exiv2::kerFileOpenFailed, output.path() , "w+b", strError());
} }
size_t l = 0; size_t l = 0;
if ( bytes ) { if ( !bytes.empty() ) {
int r ; size_t r ;
while ( (r=io->read(bytes,blocksize)) > 0 ) { while ( (r=io->read(bytes.data(),blocksize)) > 0 ) {
l += r; l += r;
output.write(bytes,r) ; output.write(bytes.data(),r) ;
} }
} else { } else {
// read/write byte-wise (#1029) // read/write byte-wise (#1029)
@ -90,7 +92,6 @@ int main(int argc, char* const argv[])
output.putb(io->getb()) ; output.putb(io->getb()) ;
} }
} }
delete[] bytes;
output.close(); output.close();
} }
@ -142,7 +143,7 @@ int main(int argc, char* const argv[])
throw Error(Exiv2::kerFileOpenFailed, f2, "w+b", strError()); throw Error(Exiv2::kerFileOpenFailed, f2, "w+b", strError());
} }
long readCount = 0; size_t readCount = 0;
byte buf[32]; byte buf[32];
while ((readCount=fileOut1.read(buf, sizeof(buf)))) { while ((readCount=fileOut1.read(buf, sizeof(buf)))) {
if (memIo2.write(buf, readCount) != readCount) { if (memIo2.write(buf, readCount) != readCount) {
@ -179,7 +180,7 @@ int WriteReadSeek(BasicIo &io)
throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError()); throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError());
} }
IoCloser closer(io); IoCloser closer(io);
if (static_cast<size_t>(io.write(reinterpret_cast<const byte*>(tester1), static_cast<long>(size1))) != size1) { if (io.write(reinterpret_cast<const byte*>(tester1), size1) != size1) {
std::cerr << ": WRS initial write failed\n"; std::cerr << ": WRS initial write failed\n";
return 2; return 2;
} }
@ -232,7 +233,7 @@ int WriteReadSeek(BasicIo &io)
} }
io.seek(insert, BasicIo::beg); io.seek(insert, BasicIo::beg);
if (static_cast<size_t>(io.write(reinterpret_cast<const byte*>(tester2), static_cast<long>(size2))) != size2) { if (io.write(reinterpret_cast<const byte*>(tester2), size2) != size2) {
std::cerr << ": WRS bad write 1\n"; std::cerr << ": WRS bad write 1\n";
return 9; return 9;
} }
@ -242,7 +243,7 @@ int WriteReadSeek(BasicIo &io)
throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError()); throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError());
} }
std::memset(buf, -1, sizeof(buf)); std::memset(buf, -1, sizeof(buf));
if (static_cast<size_t>(io.read(buf, sizeof(buf))) != insert + size2) { if (io.read(buf, sizeof(buf)) != insert + size2) {
std::cerr << ": WRS something went wrong\n"; std::cerr << ": WRS something went wrong\n";
return 10; return 10;
} }

@ -47,7 +47,7 @@ int main(int argc, char* const argv[])
} }
Exiv2::DataBuf buf(static_cast<long>(io.size())); Exiv2::DataBuf buf(static_cast<long>(io.size()));
std::cout << "Reading " << buf.size() << " bytes from " << data << "\n"; std::cout << "Reading " << buf.size() << " bytes from " << data << "\n";
long readBytes = io.read(buf.data(), buf.size()); const size_t readBytes = io.read(buf.data(), buf.size());
if (readBytes != buf.size() || io.error() || io.eof()) { if (readBytes != buf.size() || io.error() || io.eof()) {
throw Exiv2::Error(Exiv2::kerFailedToReadImageData); throw Exiv2::Error(Exiv2::kerFailedToReadImageData);
} }

@ -49,9 +49,9 @@ try {
} }
// Use MemIo to increase test coverage. // Use MemIo to increase test coverage.
Exiv2::BasicIo::UniquePtr fileIo(new Exiv2::FileIo(params.read_)); Exiv2::FileIo fileIo(params.read_);
Exiv2::BasicIo::UniquePtr memIo(new Exiv2::MemIo); auto memIo = std::make_unique<Exiv2::MemIo>();
memIo->transfer(*fileIo); memIo->transfer(fileIo);
Exiv2::Image::UniquePtr readImg = Exiv2::ImageFactory::open(std::move(memIo)); Exiv2::Image::UniquePtr readImg = Exiv2::ImageFactory::open(std::move(memIo));
assert(readImg.get() != 0); assert(readImg.get() != 0);
@ -59,7 +59,9 @@ try {
Exiv2::Image::UniquePtr writeImg = Exiv2::ImageFactory::open(params.write_); Exiv2::Image::UniquePtr writeImg = Exiv2::ImageFactory::open(params.write_);
assert(writeImg.get() != 0); assert(writeImg.get() != 0);
if (params.preserve_) writeImg->readMetadata(); if (params.preserve_) {
writeImg->readMetadata();
}
if (params.iptc_) { if (params.iptc_) {
writeImg->setIptcData(readImg->iptcData()); writeImg->setIptcData(readImg->iptcData());
} }

@ -84,14 +84,14 @@ void mini1(const char* path)
enforce(wm == wmIntrusive, Exiv2::kerErrorMessage, "encode returned an unexpected value"); enforce(wm == wmIntrusive, Exiv2::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 3: Wrote non-empty Exif data without original binary data:\n"; std::cout << "Test 3: Wrote non-empty Exif data without original binary data:\n";
exifData.clear(); exifData.clear();
ByteOrder bo = ExifParser::decode(exifData, &blob[0], static_cast<uint32_t>(blob.size())); ByteOrder bo = ExifParser::decode(exifData, &blob[0], blob.size());
enforce(bo == bigEndian, Exiv2::kerErrorMessage, "decode returned an unexpected value"); enforce(bo == bigEndian, Exiv2::kerErrorMessage, "decode returned an unexpected value");
print(exifData); print(exifData);
} }
void mini9(const char* path) void mini9(const char* path)
{ {
TiffImage tiffImage(BasicIo::UniquePtr(new FileIo(path)), false); TiffImage tiffImage(std::make_unique<FileIo>(path), false);
tiffImage.readMetadata(); tiffImage.readMetadata();
std::cout << "MIME type: " << tiffImage.mimeType() << "\n"; std::cout << "MIME type: " << tiffImage.mimeType() << "\n";

@ -69,7 +69,7 @@ try {
if (file.open("wb") != 0) { if (file.open("wb") != 0) {
throw Exiv2::Error(Exiv2::kerFileOpenFailed, filename, "wb", Exiv2::strError()); throw Exiv2::Error(Exiv2::kerFileOpenFailed, filename, "wb", Exiv2::strError());
} }
if (file.write(reinterpret_cast<const Exiv2::byte*>(xmpPacket.data()), static_cast<long>(xmpPacket.size())) == 0) { if (file.write(reinterpret_cast<const Exiv2::byte*>(xmpPacket.data()), xmpPacket.size()) == 0) {
throw Exiv2::Error(Exiv2::kerCallFailed, filename, Exiv2::strError(), "FileIo::write"); throw Exiv2::Error(Exiv2::kerCallFailed, filename, Exiv2::strError(), "FileIo::write");
} }
Exiv2::XmpParser::terminate(); Exiv2::XmpParser::terminate();

@ -87,8 +87,8 @@ namespace {
} }
namespace Exiv2 { namespace Exiv2 {
void BasicIo::readOrThrow(byte* buf, long rcount, ErrorCode err) { void BasicIo::readOrThrow(byte* buf, size_t rcount, ErrorCode err) {
const long nread = read(buf, rcount); const size_t nread = read(buf, rcount);
enforce(nread == rcount, err); enforce(nread == rcount, err);
enforce(!error(), err); enforce(!error(), err);
} }
@ -219,7 +219,7 @@ namespace Exiv2 {
} // FileIo::Impl::stat } // FileIo::Impl::stat
FileIo::FileIo(const std::string& path) FileIo::FileIo(const std::string& path)
: p_(new Impl(path)) : p_(std::make_unique<Impl>(path))
{ {
} }
@ -336,25 +336,29 @@ namespace Exiv2 {
p_->path_ = path; p_->path_ = path;
} }
long FileIo::write(const byte* data, long wcount) size_t FileIo::write(const byte* data, size_t wcount)
{ {
assert(p_->fp_ != 0); assert(p_->fp_ != 0);
if (p_->switchMode(Impl::opWrite) != 0) return 0; if (p_->switchMode(Impl::opWrite) != 0)
return static_cast<long>(std::fwrite(data, 1, wcount, p_->fp_)); return 0;
return std::fwrite(data, 1, wcount, p_->fp_);
} }
long FileIo::write(BasicIo& src) size_t FileIo::write(BasicIo& src)
{ {
assert(p_->fp_ != 0); assert(p_->fp_ != 0);
if (static_cast<BasicIo*>(this) == &src) return 0; if (static_cast<BasicIo*>(this) == &src)
if (!src.isopen()) return 0; return 0;
if (p_->switchMode(Impl::opWrite) != 0) return 0; if (!src.isopen())
return 0;
if (p_->switchMode(Impl::opWrite) != 0)
return 0;
byte buf[4096]; byte buf[4096];
long readCount = 0; size_t readCount = 0;
long writeTotal = 0; size_t writeTotal = 0;
while ((readCount = src.read(buf, sizeof(buf)))) { while ((readCount = src.read(buf, sizeof(buf)))) {
long writeCount = static_cast<long>(std::fwrite(buf, 1, readCount, p_->fp_)); size_t writeCount = std::fwrite(buf, 1, readCount, p_->fp_);
writeTotal += writeCount; writeTotal += writeCount;
if (writeCount != readCount) { if (writeCount != readCount) {
// try to reset back to where write stopped // try to reset back to where write stopped
@ -548,35 +552,37 @@ namespace Exiv2 {
int FileIo::close() int FileIo::close()
{ {
int rc = 0; int rc = 0;
if (munmap() != 0) rc = 2; if (munmap() != 0)
rc = 2;
if (p_->fp_ != nullptr) { if (p_->fp_ != nullptr) {
if (std::fclose(p_->fp_) != 0) rc |= 1; if (std::fclose(p_->fp_) != 0)
rc |= 1;
p_->fp_ = nullptr; p_->fp_ = nullptr;
} }
return rc; return rc;
} }
DataBuf FileIo::read(long rcount) DataBuf FileIo::read(size_t rcount)
{ {
assert(p_->fp_ != 0); assert(p_->fp_ != 0);
if (static_cast<size_t>(rcount) > size()) if (static_cast<size_t>(rcount) > size())
throw Error(kerInvalidMalloc); throw Error(kerInvalidMalloc);
DataBuf buf(rcount); DataBuf buf(rcount);
long readCount = read(buf.data(), buf.size()); size_t readCount = read(buf.data(), buf.size());
if (readCount < 0) { if (readCount == 0) {
throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
} }
buf.resize(readCount); buf.resize(readCount);
return buf; return buf;
} }
long FileIo::read(byte* buf, long rcount) size_t FileIo::read(byte* buf, size_t rcount)
{ {
assert(p_->fp_ != 0); assert(p_->fp_ != 0);
if (p_->switchMode(Impl::opRead) != 0) { if (p_->switchMode(Impl::opRead) != 0) {
return 0; return 0;
} }
return static_cast<long>(std::fread(buf, 1, rcount, p_->fp_)); return std::fread(buf, 1, rcount, p_->fp_);
} }
int FileIo::getb() int FileIo::getb()
@ -609,25 +615,25 @@ namespace Exiv2 {
class MemIo::Impl final{ class MemIo::Impl final{
public: public:
Impl() = default; //!< Default constructor Impl() = default; //!< Default constructor
Impl(const byte* data, long size); //!< Constructor 2 Impl(const byte* data, size_t size); //!< Constructor 2
// DATA // DATA
byte* data_{nullptr}; //!< Pointer to the start of the memory area byte* data_{nullptr}; //!< Pointer to the start of the memory area
long idx_{0}; //!< Index into the memory area size_t idx_{0}; //!< Index into the memory area
long size_{0}; //!< Size of the memory area size_t size_{0}; //!< Size of the memory area
long sizeAlloced_{0}; //!< Size of the allocated buffer size_t sizeAlloced_{0}; //!< Size of the allocated buffer
bool isMalloced_{false}; //!< Was the buffer allocated? bool isMalloced_{false}; //!< Was the buffer allocated?
bool eof_{false}; //!< EOF indicator bool eof_{false}; //!< EOF indicator
// METHODS // METHODS
void reserve(long wcount); //!< Reserve memory void reserve(size_t wcount); //!< Reserve memory
// NOT IMPLEMENTED // NOT IMPLEMENTED
Impl(const Impl& rhs) = delete; //!< Copy constructor Impl(const Impl& rhs) = delete; //!< Copy constructor
Impl& operator=(const Impl& rhs) = delete; //!< Assignment Impl& operator=(const Impl& rhs) = delete; //!< Assignment
}; // class MemIo::Impl }; // class MemIo::Impl
MemIo::Impl::Impl(const byte* data, long size) : data_(const_cast<byte*>(data)), size_(size) MemIo::Impl::Impl(const byte* data, size_t size) : data_(const_cast<byte*>(data)), size_(size)
{ {
} }
@ -700,15 +706,15 @@ namespace Exiv2 {
size_t size_{0}; size_t size_{0};
}; // class BlockMap }; // class BlockMap
void MemIo::Impl::reserve(long wcount) void MemIo::Impl::reserve(size_t wcount)
{ {
const long need = wcount + idx_; const size_t need = wcount + idx_;
long blockSize = 32*1024; // 32768 ` size_t blockSize = 32*1024; // 32768
const long maxBlockSize = 4*1024*1024; const size_t maxBlockSize = 4*1024*1024;
if (!isMalloced_) { if (!isMalloced_) {
// Minimum size for 1st block // Minimum size for 1st block
long size = std::max(blockSize * (1 + need / blockSize), size_); size_t size = std::max(blockSize * (1 + need / blockSize), size_);
auto data = static_cast<byte*>(std::malloc(size)); auto data = static_cast<byte*>(std::malloc(size));
if (data == nullptr) { if (data == nullptr) {
throw Error(kerMallocFailed); throw Error(kerMallocFailed);
@ -726,7 +732,7 @@ namespace Exiv2 {
blockSize = 2*sizeAlloced_ ; blockSize = 2*sizeAlloced_ ;
if ( blockSize > maxBlockSize ) blockSize = maxBlockSize ; if ( blockSize > maxBlockSize ) blockSize = maxBlockSize ;
// Allocate in blocks // Allocate in blocks
long want = blockSize * (1 + need / blockSize ); size_t want = blockSize * (1 + need / blockSize );
data_ = static_cast<byte*>(std::realloc(data_, want)); data_ = static_cast<byte*>(std::realloc(data_, want));
if (data_ == nullptr) { if (data_ == nullptr) {
throw Error(kerMallocFailed); throw Error(kerMallocFailed);
@ -738,12 +744,12 @@ namespace Exiv2 {
} }
MemIo::MemIo() MemIo::MemIo()
: p_(new Impl()) : p_(std::make_unique<Impl>())
{ {
} }
MemIo::MemIo(const byte* data, long size) MemIo::MemIo(const byte* data, size_t size)
: p_(new Impl(data, size)) : p_(std::make_unique<Impl>(data, size))
{ {
} }
@ -754,7 +760,7 @@ namespace Exiv2 {
} }
} }
long MemIo::write(const byte* data, long wcount) size_t MemIo::write(const byte* data, size_t wcount)
{ {
p_->reserve(wcount); p_->reserve(wcount);
assert(p_->isMalloced_); assert(p_->isMalloced_);
@ -794,14 +800,14 @@ namespace Exiv2 {
if (error() || src.error()) throw Error(kerMemoryTransferFailed, strError()); if (error() || src.error()) throw Error(kerMemoryTransferFailed, strError());
} }
long MemIo::write(BasicIo& src) size_t MemIo::write(BasicIo& src)
{ {
if (static_cast<BasicIo*>(this) == &src) return 0; if (static_cast<BasicIo*>(this) == &src) return 0;
if (!src.isopen()) return 0; if (!src.isopen()) return 0;
byte buf[4096]; byte buf[4096];
long readCount = 0; size_t readCount = 0;
long writeTotal = 0; size_t writeTotal = 0;
while ((readCount = src.read(buf, sizeof(buf)))) { while ((readCount = src.read(buf, sizeof(buf)))) {
write(buf, readCount); write(buf, readCount);
writeTotal += readCount; writeTotal += readCount;
@ -831,7 +837,7 @@ namespace Exiv2 {
if (newIdx < 0) if (newIdx < 0)
return 1; return 1;
if (newIdx > p_->size_) { if (newIdx > static_cast<int64_t>(p_->size_)) {
p_->eof_ = true; p_->eof_ = true;
return 1; return 1;
} }
@ -853,7 +859,7 @@ namespace Exiv2 {
long MemIo::tell() const long MemIo::tell() const
{ {
return p_->idx_; return static_cast<long>(p_->idx_);
} }
size_t MemIo::size() const size_t MemIo::size() const
@ -878,18 +884,18 @@ namespace Exiv2 {
return 0; return 0;
} }
DataBuf MemIo::read(long rcount) DataBuf MemIo::read(size_t rcount)
{ {
DataBuf buf(rcount); DataBuf buf(rcount);
long readCount = read(buf.data(), buf.size()); size_t readCount = read(buf.data(), buf.size());
buf.resize(readCount); buf.resize(readCount);
return buf; return buf;
} }
long MemIo::read(byte* buf, long rcount) size_t MemIo::read(byte* buf, size_t rcount)
{ {
const long avail = std::max(p_->size_ - p_->idx_, 0L); const size_t avail = std::max(p_->size_ - p_->idx_, static_cast<size_t>(0));
const long allow = std::min(rcount, avail); const size_t allow = std::min(rcount, avail);
if (allow > 0) { if (allow > 0) {
std::memcpy(buf, &p_->data_[p_->idx_], allow); std::memcpy(buf, &p_->data_[p_->idx_], allow);
} }
@ -1073,11 +1079,11 @@ namespace Exiv2 {
size_t blockSize_; //!< Size of the block memory. size_t blockSize_; //!< Size of the block memory.
BlockMap* blocksMap_; //!< An array contains all blocksMap BlockMap* blocksMap_; //!< An array contains all blocksMap
size_t size_; //!< The file size size_t size_; //!< The file size
long idx_; //!< Index into the memory area size_t idx_; //!< Index into the memory area
bool isMalloced_; //!< Was the blocksMap_ allocated? bool isMalloced_; //!< Was the blocksMap_ allocated?
bool eof_; //!< EOF indicator bool eof_; //!< EOF indicator
Protocol protocol_; //!< the protocol of url Protocol protocol_; //!< the protocol of url
uint32_t totalRead_; //!< bytes requested from host size_t totalRead_; //!< bytes requested from host
// METHODS // METHODS
/*! /*!
@ -1168,11 +1174,12 @@ namespace Exiv2 {
delete[] blocksMap_; delete[] blocksMap_;
} }
RemoteIo::RemoteIo() = default;
RemoteIo::~RemoteIo() RemoteIo::~RemoteIo()
{ {
if (p_) { if (p_) {
close(); close();
delete p_;
} }
} }
@ -1226,12 +1233,12 @@ namespace Exiv2 {
return 0; return 0;
} }
long RemoteIo::write(const byte* /* unused data*/, long /* unused wcount*/) size_t RemoteIo::write(const byte* /* unused data*/, size_t /* unused wcount*/)
{ {
return 0; // means failure return 0; // means failure
} }
long RemoteIo::write(BasicIo& src) size_t RemoteIo::write(BasicIo& src)
{ {
assert(p_->isMalloced_); assert(p_->isMalloced_);
if (!src.isopen()) return 0; if (!src.isopen()) return 0;
@ -1255,7 +1262,7 @@ namespace Exiv2 {
while (blockIndex < nBlocks && !src.eof() && !findDiff) { while (blockIndex < nBlocks && !src.eof() && !findDiff) {
size_t blockSize = p_->blocksMap_[blockIndex].getSize(); size_t blockSize = p_->blocksMap_[blockIndex].getSize();
bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data
size_t readCount = static_cast<size_t>(src.read(buf.data(), static_cast<long>(blockSize))); size_t readCount = src.read(buf.data(), blockSize);
byte* blockData = p_->blocksMap_[blockIndex].getData(); byte* blockData = p_->blocksMap_[blockIndex].getData();
for (size_t i = 0; (i < readCount) && (i < blockSize) && !findDiff; i++) { for (size_t i = 0; (i < readCount) && (i < blockSize) && !findDiff; i++) {
if ((!isFakeData && buf[i] != blockData[i]) || (isFakeData && buf[i] != 0)) { if ((!isFakeData && buf[i] != blockData[i]) || (isFakeData && buf[i] != 0)) {
@ -1277,7 +1284,7 @@ namespace Exiv2 {
findDiff = true; findDiff = true;
} else { } else {
bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data
size_t readCount = src.read(buf.data(), static_cast<long>(blockSize)); size_t readCount = src.read(buf.data(), blockSize);
byte* blockData = p_->blocksMap_[blockIndex].getData(); byte* blockData = p_->blocksMap_[blockIndex].getData();
for (size_t i = 0; (i < readCount) && (i < blockSize) && !findDiff; i++) { for (size_t i = 0; (i < readCount) && (i < blockSize) && !findDiff; i++) {
if ((!isFakeData && buf[readCount - i - 1] != blockData[blockSize - i - 1]) || (isFakeData && buf[readCount - i - 1] != 0)) { if ((!isFakeData && buf[readCount - i - 1] != blockData[blockSize - i - 1]) || (isFakeData && buf[readCount - i - 1] != 0)) {
@ -1295,9 +1302,9 @@ namespace Exiv2 {
auto data = static_cast<byte*>(std::malloc(dataSize)); auto data = static_cast<byte*>(std::malloc(dataSize));
src.seek(left, BasicIo::beg); src.seek(left, BasicIo::beg);
src.read(data, dataSize); src.read(data, dataSize);
p_->writeRemote(data, static_cast<size_t>(dataSize), static_cast<long>(left), p_->writeRemote(data, dataSize, static_cast<long>(left), static_cast<long>(p_->size_ - right));
static_cast<long>(p_->size_ - right)); if (data)
if (data) std::free(data); std::free(data);
} }
return static_cast<long>(src.size()); return static_cast<long>(src.size());
} }
@ -1307,24 +1314,25 @@ namespace Exiv2 {
return 0; return 0;
} }
DataBuf RemoteIo::read(long rcount) DataBuf RemoteIo::read(size_t rcount)
{ {
DataBuf buf(rcount); DataBuf buf(rcount);
long readCount = read(buf.data(), buf.size()); size_t readCount = read(buf.data(), buf.size());
if (readCount < 0) { if (readCount == 0) {
throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
} }
buf.resize(readCount); buf.resize(readCount);
return buf; return buf;
} }
long RemoteIo::read(byte* buf, long rcount) size_t RemoteIo::read(byte* buf, size_t rcount)
{ {
assert(p_->isMalloced_); assert(p_->isMalloced_);
if (p_->eof_) return 0; if (p_->eof_)
return 0;
p_->totalRead_ += rcount; p_->totalRead_ += rcount;
size_t allow = std::min(rcount, (long)( p_->size_ - p_->idx_)); size_t allow = std::min(rcount, ( p_->size_ - p_->idx_));
size_t lowBlock = p_->idx_ /p_->blockSize_; size_t lowBlock = p_->idx_ /p_->blockSize_;
size_t highBlock = (p_->idx_ + allow)/p_->blockSize_; size_t highBlock = (p_->idx_ + allow)/p_->blockSize_;
@ -1351,16 +1359,16 @@ namespace Exiv2 {
std::free(fakeData); std::free(fakeData);
p_->idx_ += static_cast<long>(totalRead); p_->idx_ += totalRead;
p_->eof_ = (p_->idx_ == static_cast<long>(p_->size_)); p_->eof_ = (p_->idx_ == p_->size_);
return static_cast<long>(totalRead); return totalRead;
} }
int RemoteIo::getb() int RemoteIo::getb()
{ {
assert(p_->isMalloced_); assert(p_->isMalloced_);
if (p_->idx_ == static_cast<long>(p_->size_)) { if (p_->idx_ == p_->size_) {
p_->eof_ = true; p_->eof_ = true;
return EOF; return EOF;
} }
@ -1395,10 +1403,10 @@ namespace Exiv2 {
// #1198. Don't return 1 when asked to seek past EOF. Stay calm and set eof_ // #1198. Don't return 1 when asked to seek past EOF. Stay calm and set eof_
// if (newIdx < 0 || newIdx > (long) p_->size_) return 1; // if (newIdx < 0 || newIdx > (long) p_->size_) return 1;
p_->idx_ = static_cast<long>(newIdx); p_->idx_ = static_cast<size_t>(newIdx);
p_->eof_ = newIdx > static_cast<long>(p_->size_); p_->eof_ = newIdx > static_cast<int64_t>(p_->size_);
if (p_->idx_ > static_cast<long>(p_->size_)) if (p_->idx_ > p_->size_)
p_->idx_ = static_cast<long>(p_->size_); p_->idx_ = p_->size_;
return 0; return 0;
} }
@ -1432,7 +1440,7 @@ namespace Exiv2 {
long RemoteIo::tell() const long RemoteIo::tell() const
{ {
return p_->idx_; return static_cast<long>(p_->idx_);
} }
size_t RemoteIo::size() const size_t RemoteIo::size() const
@ -1588,11 +1596,10 @@ namespace Exiv2 {
// encode base64 // encode base64
size_t encodeLength = ((size + 2) / 3) * 4 + 1; size_t encodeLength = ((size + 2) / 3) * 4 + 1;
auto encodeData = new char[encodeLength]; std::vector<char> encodeData (encodeLength);
base64encode(data, size, encodeData, encodeLength); base64encode(data, size, encodeData.data(), encodeLength);
// url encode // url encode
const std::string urlencodeData = urlencode(encodeData); const std::string urlencodeData = urlencode(encodeData.data());
delete[] encodeData;
std::stringstream ss; std::stringstream ss;
ss << "path=" << hostInfo_.Path << "&" ss << "path=" << hostInfo_.Path << "&"
@ -1613,9 +1620,10 @@ namespace Exiv2 {
throw Error(kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode), hostInfo_.Path); throw Error(kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode), hostInfo_.Path);
} }
} }
HttpIo::HttpIo(const std::string& url, size_t blockSize) HttpIo::HttpIo(const std::string& url, size_t blockSize)
{ {
p_ = new HttpImpl(url, blockSize); p_ = std::make_unique<HttpImpl>(url, blockSize);
} }
#ifdef EXV_USE_CURL #ifdef EXV_USE_CURL
@ -1776,11 +1784,10 @@ namespace Exiv2 {
// encode base64 // encode base64
size_t encodeLength = ((size + 2) / 3) * 4 + 1; size_t encodeLength = ((size + 2) / 3) * 4 + 1;
auto encodeData = new char[encodeLength]; std::vector<char> encodeData (encodeLength);
base64encode(data, size, encodeData, encodeLength); base64encode(data, size, encodeData.data(), encodeLength);
// url encode // url encode
const std::string urlencodeData = urlencode(encodeData); const std::string urlencodeData = urlencode(encodeData.data());
delete[] encodeData;
std::stringstream ss; std::stringstream ss;
ss << "path=" << hostInfo.Path << "&" ss << "path=" << hostInfo.Path << "&"
<< "from=" << from << "&" << "from=" << from << "&"
@ -1806,7 +1813,7 @@ namespace Exiv2 {
curl_easy_cleanup(curl_); curl_easy_cleanup(curl_);
} }
long CurlIo::write(const byte* data, long wcount) size_t CurlIo::write(const byte* data, size_t wcount)
{ {
if (p_->protocol_ == pHttp || p_->protocol_ == pHttps) { if (p_->protocol_ == pHttp || p_->protocol_ == pHttps) {
return RemoteIo::write(data, wcount); return RemoteIo::write(data, wcount);
@ -1814,7 +1821,7 @@ namespace Exiv2 {
throw Error(kerErrorMessage, "doesnt support write for this protocol."); throw Error(kerErrorMessage, "doesnt support write for this protocol.");
} }
long CurlIo::write(BasicIo& src) size_t CurlIo::write(BasicIo& src)
{ {
if (p_->protocol_ == pHttp || p_->protocol_ == pHttps) { if (p_->protocol_ == pHttp || p_->protocol_ == pHttps) {
return RemoteIo::write(src); return RemoteIo::write(src);
@ -1824,7 +1831,7 @@ namespace Exiv2 {
CurlIo::CurlIo(const std::string& url, size_t blockSize) CurlIo::CurlIo(const std::string& url, size_t blockSize)
{ {
p_ = new CurlImpl(url, blockSize); p_ = std::make_unique<CurlImpl>(url, blockSize);
} }
#endif #endif
@ -1843,14 +1850,14 @@ namespace Exiv2 {
throw Error(kerCallFailed, path, strError(), "::stat"); throw Error(kerCallFailed, path, strError(), "::stat");
} }
DataBuf buf(st.st_size); DataBuf buf(st.st_size);
long len = file.read(buf.data(), buf.size()); const size_t len = file.read(buf.data(), buf.size());
if (len != buf.size()) { if (len != buf.size()) {
throw Error(kerCallFailed, path, strError(), "FileIo::read"); throw Error(kerCallFailed, path, strError(), "FileIo::read");
} }
return buf; return buf;
} }
long writeFile(const DataBuf& buf, const std::string& path) size_t writeFile(const DataBuf& buf, const std::string& path)
{ {
FileIo file(path); FileIo file(path);
if (file.open("wb") != 0) { if (file.open("wb") != 0) {

@ -237,24 +237,24 @@ namespace Exiv2
// read data in box and restore file position // read data in box and restore file position
long restore = io_->tell(); long restore = io_->tell();
enforce(box_length >= hdrsize, Exiv2::kerCorruptedMetadata); enforce(box_length >= hdrsize, Exiv2::kerCorruptedMetadata);
enforce(box_length - hdrsize <= static_cast<size_t>(pbox_end - restore), Exiv2::kerCorruptedMetadata); enforce(box_length - hdrsize <= static_cast<uint64_t>(pbox_end - restore), Exiv2::kerCorruptedMetadata);
const long buffer_size = static_cast<long>(box_length - hdrsize); const size_t buffer_size = static_cast<size_t>(box_length - hdrsize);
if (skipBox(box_type)) { if (skipBox(box_type)) {
if (bTrace) { if (bTrace) {
out << std::endl; out << std::endl;
} }
// The enforce() above checks that restore + buffer_size won't // The enforce() above checks that restore + buffer_size won't
// exceed pbox_end, and by implication, won't exceed LONG_MAX // exceed pbox_end, and by implication, won't exceed LONG_MAX
return restore + buffer_size; return restore + static_cast<long>(buffer_size);
} }
DataBuf data(buffer_size); DataBuf data(buffer_size);
const long box_end = restore + data.size(); const long box_end = restore + static_cast<long>(data.size());
io_->read(data.data(), data.size()); io_->read(data.data(), data.size());
io_->seek(restore, BasicIo::beg); io_->seek(restore, BasicIo::beg);
long skip = 0; // read position in data.pData_ size_t skip = 0; // read position in data.pData_
uint8_t version = 0; uint8_t version = 0;
uint32_t flags = 0; uint32_t flags = 0;
@ -303,8 +303,8 @@ namespace Exiv2
std::string id; std::string id;
// Check that the string has a '\0' terminator. // Check that the string has a '\0' terminator.
const char* str = data.c_str(skip); const char* str = data.c_str(skip);
const auto maxlen = static_cast<size_t>(data.size() - skip); const size_t maxlen = data.size() - skip;
enforce(strnlen(str, maxlen) < maxlen, Exiv2::kerCorruptedMetadata); enforce(maxlen > 0 && strnlen(str, maxlen) < maxlen, Exiv2::kerCorruptedMetadata);
std::string name(str); std::string name(str);
if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif" if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif"
exifID_ = ID; exifID_ = ID;
@ -366,7 +366,7 @@ namespace Exiv2
#else #else
skip++; skip++;
#endif #endif
enforce(data.size() - skip >= (version < 2 ? 2 : 4), Exiv2::kerCorruptedMetadata); enforce(data.size() - skip >= (version < 2u ? 2u : 4u), Exiv2::kerCorruptedMetadata);
uint32_t itemCount = version < 2 ? data.read_uint16(skip, endian_) uint32_t itemCount = version < 2 ? data.read_uint16(skip, endian_)
: data.read_uint32(skip, endian_); : data.read_uint32(skip, endian_);
skip += version < 2 ? 2 : 4; skip += version < 2 ? 2 : 4;
@ -376,11 +376,11 @@ namespace Exiv2
out << std::endl; out << std::endl;
bLF = false; bLF = false;
} }
long step = static_cast<long>((box_length - 16) / itemCount); // length of data per item. size_t step = (static_cast<size_t>(box_length) - 16) / itemCount; // length of data per item.
long base = skip; size_t base = skip;
for (uint32_t i = 0; i < itemCount; i++) { for (uint32_t i = 0; i < itemCount; i++) {
skip = base + i * step; // move in 14, 16 or 18 byte steps skip = base + i * step; // move in 14, 16 or 18 byte steps
enforce(data.size() - skip >= (version > 2 ? 4 : 2), Exiv2::kerCorruptedMetadata); enforce(data.size() - skip >= (version > 2u ? 4u : 2u), Exiv2::kerCorruptedMetadata);
enforce(data.size() - skip >= step, Exiv2::kerCorruptedMetadata); enforce(data.size() - skip >= step, Exiv2::kerCorruptedMetadata);
uint32_t ID = version > 2 ? data.read_uint32(skip, endian_) uint32_t ID = version > 2 ? data.read_uint32(skip, endian_)
: data.read_uint16(skip, endian_); : data.read_uint16(skip, endian_);
@ -423,8 +423,7 @@ namespace Exiv2
// 12.1.5.2 // 12.1.5.2
case TAG_colr: { case TAG_colr: {
if (data.size() >= if (data.size() >= (skip + 4 + 8)) { // .____.HLino..__mntrR 2 0 0 0 0 12 72 76 105 110 111 2 16 ...
static_cast<long>(skip + 4 + 8)) { // .____.HLino..__mntrR 2 0 0 0 0 12 72 76 105 110 111 2 16 ...
// https://www.ics.uci.edu/~dan/class/267/papers/jpeg2000.pdf // https://www.ics.uci.edu/~dan/class/267/papers/jpeg2000.pdf
uint8_t meth = data.read_uint8(skip+0); uint8_t meth = data.read_uint8(skip+0);
uint8_t prec = data.read_uint8(skip+1); uint8_t prec = data.read_uint8(skip+1);
@ -518,26 +517,26 @@ namespace Exiv2
{ {
enforce(start <= io_->size(), kerCorruptedMetadata); enforce(start <= io_->size(), kerCorruptedMetadata);
enforce(length <= io_->size() - start, kerCorruptedMetadata); enforce(length <= io_->size() - start, kerCorruptedMetadata);
enforce(start <= static_cast<unsigned long>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(start <= std::numeric_limits<uint64_t>::max(), kerCorruptedMetadata);
enforce(length <= static_cast<unsigned long>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(length <= std::numeric_limits<uint64_t>::max(), kerCorruptedMetadata);
// read and parse exif data // read and parse exif data
long restore = io_->tell(); long restore = io_->tell();
DataBuf exif(static_cast<long>(length)); DataBuf exif(static_cast<size_t>(length));
io_->seek(static_cast<long>(start),BasicIo::beg); io_->seek(static_cast<long>(start),BasicIo::beg);
if ( exif.size() > 8 && io_->read(exif.data(),exif.size()) == exif.size() ) { if ( exif.size() > 8 && io_->read(exif.data(),exif.size()) == exif.size() ) {
// hunt for "II" or "MM" // hunt for "II" or "MM"
long eof = 0xffffffff; // impossible value for punt long eof = 0xffffffff; // impossible value for punt
long punt = eof; long punt = eof;
for ( long i = 0 ; i < exif.size() -8 && punt==eof ; i+=2) { for ( size_t i = 0 ; i < exif.size() -8 && punt==eof ; i+=2) {
if ( exif.read_uint8(i) == exif.read_uint8(i+1) ) if ( exif.read_uint8(i) == exif.read_uint8(i+1) )
if ( exif.read_uint8(i) == 'I' || exif.read_uint8(i) == 'M' ) if ( exif.read_uint8(i) == 'I' || exif.read_uint8(i) == 'M' )
punt = i; punt = static_cast<long>(i);
} }
if ( punt != eof ) { if ( punt != eof ) {
Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), exif.c_data(punt),
exif.c_data(punt), exif.size()-punt, root_tag, static_cast<uint32_t>(exif.size()-punt), root_tag,
Internal::TiffMapping::findDecoder); Internal::TiffMapping::findDecoder);
} }
} }
io_->seek(restore,BasicIo::beg); io_->seek(restore,BasicIo::beg);
@ -547,9 +546,9 @@ namespace Exiv2
{ {
if (length > 8) { if (length > 8) {
enforce(length - 8 <= io_->size() - io_->tell(), kerCorruptedMetadata); enforce(length - 8 <= io_->size() - io_->tell(), kerCorruptedMetadata);
enforce(length - 8 <= static_cast<unsigned long>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(length - 8 <= std::numeric_limits<uint64_t>::max(), kerCorruptedMetadata);
DataBuf data(static_cast<long>(length - 8)); DataBuf data(static_cast<size_t>(length) - 8);
long bufRead = io_->read(data.data(), data.size()); const size_t bufRead = io_->read(data.data(), data.size());
if (io_->error()) if (io_->error())
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
@ -557,7 +556,7 @@ namespace Exiv2
throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(),
data.c_data(), data.size(), root_tag, data.c_data(), static_cast<uint32_t>(data.size()), root_tag,
Internal::TiffMapping::findDecoder); Internal::TiffMapping::findDecoder);
} }
} }
@ -569,13 +568,13 @@ namespace Exiv2
enforce(length <= io_->size() - start, kerCorruptedMetadata); enforce(length <= io_->size() - start, kerCorruptedMetadata);
long restore = io_->tell() ; long restore = io_->tell() ;
enforce(start <= static_cast<unsigned long>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(start <= std::numeric_limits<uint64_t>::max(), kerCorruptedMetadata);
io_->seek(static_cast<long>(start),BasicIo::beg); io_->seek(static_cast<long>(start),BasicIo::beg);
enforce(length < static_cast<unsigned long>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(length < std::numeric_limits<uint64_t>::max(), kerCorruptedMetadata);
DataBuf xmp(static_cast<long>(length+1)); DataBuf xmp(static_cast<size_t>(length+1));
xmp.write_uint8(static_cast<size_t>(length), 0); // ensure xmp is null terminated! xmp.write_uint8(static_cast<size_t>(length), 0); // ensure xmp is null terminated!
if ( io_->read(xmp.data(), static_cast<long>(length)) != static_cast<long>(length) ) if ( io_->read(xmp.data(), static_cast<size_t>(length)) != length )
throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
if ( io_->error() ) if ( io_->error() )
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
@ -589,14 +588,15 @@ namespace Exiv2
} }
} }
/// \todo instead of passing the last 4 parameters, pass just one and build the different offsets inside
void BmffImage::parseCr3Preview(DataBuf &data, void BmffImage::parseCr3Preview(DataBuf &data,
std::ostream& out, std::ostream& out,
bool bTrace, bool bTrace,
uint8_t version, uint8_t version,
uint32_t width_offset, size_t width_offset,
uint32_t height_offset, size_t height_offset,
uint32_t size_offset, size_t size_offset,
uint32_t relative_position) size_t relative_position)
{ {
// Derived from https://github.com/lclevy/canon_cr3 // Derived from https://github.com/lclevy/canon_cr3
long here = io_->tell(); long here = io_->tell();
@ -604,7 +604,7 @@ namespace Exiv2
here <= std::numeric_limits<long>::max() - static_cast<long>(relative_position), here <= std::numeric_limits<long>::max() - static_cast<long>(relative_position),
kerCorruptedMetadata); kerCorruptedMetadata);
NativePreview nativePreview; NativePreview nativePreview;
nativePreview.position_ = here + relative_position; nativePreview.position_ = here + static_cast<long>(relative_position);
nativePreview.width_ = data.read_uint16(width_offset, endian_); nativePreview.width_ = data.read_uint16(width_offset, endian_);
nativePreview.height_ = data.read_uint16(height_offset, endian_); nativePreview.height_ = data.read_uint16(height_offset, endian_);
nativePreview.size_ = data.read_uint32(size_offset, endian_); nativePreview.size_ = data.read_uint32(size_offset, endian_);

@ -225,14 +225,15 @@ namespace Exiv2 {
{ {
// format is: "YYMM#00#00DDHH#00#00MM#00#00#00#00" or "YYMM#00#00DDHH#00#00MMSS#00#00#00" // format is: "YYMM#00#00DDHH#00#00MM#00#00#00#00" or "YYMM#00#00DDHH#00#00MMSS#00#00#00"
std::vector<char> numbers; std::vector<char> numbers;
for(long i=0; i<value.size(); i++) for(size_t i=0; i<value.size(); i++)
{ {
const auto l = value.toInt64(i); const auto l = value.toInt64(i);
if(l!=0) if(l!=0)
{ {
numbers.push_back(static_cast<char>(l)); numbers.push_back(static_cast<char>(l));
}; }
}; }
if(numbers.size()>=10) if(numbers.size()>=10)
{ {
//year //year
@ -544,14 +545,15 @@ namespace Exiv2 {
{ {
// format is: "YYMM#00#00DDHH#00#00MM#00#00#00#00" // format is: "YYMM#00#00DDHH#00#00MM#00#00#00#00"
std::vector<char> numbers; std::vector<char> numbers;
for(long i=0; i<value.size(); i++) for(size_t i=0; i<value.size(); i++)
{ {
const auto l = value.toInt64(i); const char l = static_cast<char>(value.toInt64(i));
if(l!=0) if(l!=0)
{ {
numbers.push_back(static_cast<char>(l)); numbers.push_back(l);
}; }
}; }
if(numbers.size()>=10) if(numbers.size()>=10)
{ {
//year //year

@ -483,8 +483,10 @@ namespace Exiv2 {
bool Converter::prepareExifTarget(const char* to, bool force) bool Converter::prepareExifTarget(const char* to, bool force)
{ {
auto pos = exifData_->findKey(ExifKey(to)); auto pos = exifData_->findKey(ExifKey(to));
if (pos == exifData_->end()) return true; if (pos == exifData_->end())
if (!overwrite_ && !force) return false; return true;
if (!overwrite_ && !force)
return false;
exifData_->erase(pos); exifData_->erase(pos);
return true; return true;
} }
@ -492,8 +494,10 @@ namespace Exiv2 {
bool Converter::prepareIptcTarget(const char* to, bool force) bool Converter::prepareIptcTarget(const char* to, bool force)
{ {
auto pos = iptcData_->findKey(IptcKey(to)); auto pos = iptcData_->findKey(IptcKey(to));
if (pos == iptcData_->end()) return true; if (pos == iptcData_->end())
if (!overwrite_ && !force) return false; return true;
if (!overwrite_ && !force)
return false;
while ((pos = iptcData_->findKey(IptcKey(to))) != iptcData_->end()) { while ((pos = iptcData_->findKey(IptcKey(to))) != iptcData_->end()) {
iptcData_->erase(pos); iptcData_->erase(pos);
} }
@ -503,8 +507,10 @@ namespace Exiv2 {
bool Converter::prepareXmpTarget(const char* to, bool force) bool Converter::prepareXmpTarget(const char* to, bool force)
{ {
auto pos = xmpData_->findKey(XmpKey(to)); auto pos = xmpData_->findKey(XmpKey(to));
if (pos == xmpData_->end()) return true; if (pos == xmpData_->end())
if (!overwrite_ && !force) return false; return true;
if (!overwrite_ && !force)
return false;
xmpData_->erase(pos); xmpData_->erase(pos);
return true; return true;
} }
@ -512,7 +518,8 @@ namespace Exiv2 {
void Converter::cnvExifValue(const char* from, const char* to) void Converter::cnvExifValue(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
return;
std::string value = pos->toString(); std::string value = pos->toString();
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -520,7 +527,8 @@ namespace Exiv2 {
#endif #endif
return; return;
} }
if (!prepareXmpTarget(to)) return; if (!prepareXmpTarget(to))
return;
(*xmpData_)[to] = value; (*xmpData_)[to] = value;
if (erase_) exifData_->erase(pos); if (erase_) exifData_->erase(pos);
} }
@ -528,8 +536,10 @@ namespace Exiv2 {
void Converter::cnvExifComment(const char* from, const char* to) void Converter::cnvExifComment(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
const auto cv = dynamic_cast<const CommentValue*>(&pos->value()); const auto cv = dynamic_cast<const CommentValue*>(&pos->value());
if (cv == nullptr) { if (cv == nullptr) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -545,10 +555,12 @@ namespace Exiv2 {
void Converter::cnvExifArray(const char* from, const char* to) void Converter::cnvExifArray(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
for (long i = 0; i < pos->count(); ++i) { if (!prepareXmpTarget(to))
std::string value = pos->toString(i); return;
for (size_t i = 0; i < pos->count(); ++i) {
std::string value = pos->toString(static_cast<long>(i));
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n"; EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
@ -563,8 +575,10 @@ namespace Exiv2 {
void Converter::cnvExifDate(const char* from, const char* to) void Converter::cnvExifDate(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
int year=0, month=0, day=0, hour=0, min=0, sec=0; int year=0, month=0, day=0, hour=0, min=0, sec=0;
std::string subsec; std::string subsec;
char buf[30]; char buf[30];
@ -692,11 +706,13 @@ namespace Exiv2 {
void Converter::cnvExifVersion(const char* from, const char* to) void Converter::cnvExifVersion(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
std::ostringstream value; std::ostringstream value;
for (long i = 0; i < pos->count(); ++i) { for (size_t i = 0; i < pos->count(); ++i) {
value << static_cast<char>(pos->toInt64(i)); value << static_cast<char>(pos->toInt64(static_cast<long>(i)));
} }
(*xmpData_)[to] = value.str(); (*xmpData_)[to] = value.str();
if (erase_) exifData_->erase(pos); if (erase_) exifData_->erase(pos);
@ -705,12 +721,14 @@ namespace Exiv2 {
void Converter::cnvExifGPSVersion(const char* from, const char* to) void Converter::cnvExifGPSVersion(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
std::ostringstream value; std::ostringstream value;
for (long i = 0; i < pos->count(); ++i) { for (size_t i = 0; i < pos->count(); ++i) {
if (i > 0) value << '.'; if (i > 0) value << '.';
value << pos->toInt64(i); value << pos->toInt64(static_cast<long>(i));
} }
(*xmpData_)[to] = value.str(); (*xmpData_)[to] = value.str();
if (erase_) exifData_->erase(pos); if (erase_) exifData_->erase(pos);
@ -719,8 +737,10 @@ namespace Exiv2 {
void Converter::cnvExifFlash(const char* from, const char* to) void Converter::cnvExifFlash(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end() || pos->count() == 0) return; if (pos == exifData_->end() || pos->count() == 0)
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
auto value = pos->toInt64(); auto value = pos->toInt64();
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -741,8 +761,10 @@ namespace Exiv2 {
void Converter::cnvExifGPSCoord(const char* from, const char* to) void Converter::cnvExifGPSCoord(const char* from, const char* to)
{ {
auto pos = exifData_->findKey(ExifKey(from)); auto pos = exifData_->findKey(ExifKey(from));
if (pos == exifData_->end()) return; if (pos == exifData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
if (pos->count() != 3) { if (pos->count() != 3) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n"; EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
@ -785,8 +807,10 @@ namespace Exiv2 {
void Converter::cnvXmpValue(const char* from, const char* to) void Converter::cnvXmpValue(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
std::string value; std::string value;
if (!getTextValue(value, pos)) { if (!getTextValue(value, pos)) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -805,9 +829,11 @@ namespace Exiv2 {
void Converter::cnvXmpComment(const char* from, const char* to) void Converter::cnvXmpComment(const char* from, const char* to)
{ {
if (!prepareExifTarget(to)) return; if (!prepareExifTarget(to))
return;
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
return;
std::string value; std::string value;
if (!getTextValue(value, pos)) { if (!getTextValue(value, pos)) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -822,12 +848,14 @@ namespace Exiv2 {
void Converter::cnvXmpArray(const char* from, const char* to) void Converter::cnvXmpArray(const char* from, const char* to)
{ {
if (!prepareExifTarget(to)) return; if (!prepareExifTarget(to))
return;
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
return;
std::ostringstream array; std::ostringstream array;
for (long i = 0; i < pos->count(); ++i) { for (size_t i = 0; i < pos->count(); ++i) {
std::string value = pos->toString(i); std::string value = pos->toString(static_cast<long>(i));
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n"; EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
@ -835,17 +863,21 @@ namespace Exiv2 {
return; return;
} }
array << value; array << value;
if (i != pos->count() - 1) array << " "; if (i != pos->count() - 1)
array << " ";
} }
(*exifData_)[to] = array.str(); (*exifData_)[to] = array.str();
if (erase_) xmpData_->erase(pos); if (erase_)
xmpData_->erase(pos);
} }
void Converter::cnvXmpDate(const char* from, const char* to) void Converter::cnvXmpDate(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
#ifdef EXV_HAVE_XMP_TOOLKIT #ifdef EXV_HAVE_XMP_TOOLKIT
std::string value = pos->toString(); std::string value = pos->toString();
if (!pos->value().ok()) { if (!pos->value().ok()) {
@ -859,9 +891,9 @@ namespace Exiv2 {
SXMPUtils::ConvertToDate(value, &datetime); SXMPUtils::ConvertToDate(value, &datetime);
char buf[30]; char buf[30];
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", snprintf(buf, sizeof(buf), "%4d:%02d:%02d %02d:%02d:%02d",
static_cast<int>(datetime.year), static_cast<int>(datetime.year),
static_cast<int>(datetime.month), static_cast<int>(datetime.month),
@ -871,7 +903,7 @@ namespace Exiv2 {
static_cast<int>(datetime.second)); static_cast<int>(datetime.second));
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
(*exifData_)[to] = buf; (*exifData_)[to] = buf;
if (datetime.nanoSecond) { if (datetime.nanoSecond) {
const char* subsecTag = nullptr; const char* subsecTag = nullptr;
if (std::string(to) == "Exif.Image.DateTime") { if (std::string(to) == "Exif.Image.DateTime") {
@ -890,9 +922,9 @@ namespace Exiv2 {
} }
} }
else { // "Exif.GPSInfo.GPSTimeStamp" else { // "Exif.GPSInfo.GPSTimeStamp"
// Ignore the time zone, assuming the time is in UTC as it should be // Ignore the time zone, assuming the time is in UTC as it should be
URational rhour(datetime.hour, 1); URational rhour(datetime.hour, 1);
URational rmin(datetime.minute, 1); URational rmin(datetime.minute, 1);
URational rsec(datetime.second, 1); URational rsec(datetime.second, 1);
@ -906,11 +938,11 @@ namespace Exiv2 {
rsec.second = 1000000000; rsec.second = 1000000000;
rsec.first = datetime.nanoSecond; rsec.first = datetime.nanoSecond;
} }
std::ostringstream array; std::ostringstream array;
array << rhour << " " << rmin << " " << rsec; array << rhour << " " << rmin << " " << rsec;
(*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", snprintf(buf, sizeof(buf), "%4d:%02d:%02d",
static_cast<int>(datetime.year), static_cast<int>(datetime.year),
@ -942,8 +974,10 @@ namespace Exiv2 {
void Converter::cnvXmpVersion(const char* from, const char* to) void Converter::cnvXmpVersion(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
std::string value = pos->toString(); std::string value = pos->toString();
if (!pos->value().ok() || value.length() < 4) { if (!pos->value().ok() || value.length() < 4) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -965,8 +999,10 @@ namespace Exiv2 {
void Converter::cnvXmpGPSVersion(const char* from, const char* to) void Converter::cnvXmpGPSVersion(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
std::string value = pos->toString(); std::string value = pos->toString();
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -984,8 +1020,10 @@ namespace Exiv2 {
void Converter::cnvXmpFlash(const char* from, const char* to) void Converter::cnvXmpFlash(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(std::string(from) + "/exif:Fired")); auto pos = xmpData_->findKey(XmpKey(std::string(from) + "/exif:Fired"));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
unsigned short value = 0; unsigned short value = 0;
if (pos != xmpData_->end() && pos->count() > 0) { if (pos != xmpData_->end() && pos->count() > 0) {
@ -1047,8 +1085,10 @@ namespace Exiv2 {
void Converter::cnvXmpGPSCoord(const char* from, const char* to) void Converter::cnvXmpGPSCoord(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareExifTarget(to)) return; return;
if (!prepareExifTarget(to))
return;
std::string value = pos->toString(); std::string value = pos->toString();
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -1110,8 +1150,10 @@ namespace Exiv2 {
void Converter::cnvIptcValue(const char* from, const char* to) void Converter::cnvIptcValue(const char* from, const char* to)
{ {
auto pos = iptcData_->findKey(IptcKey(from)); auto pos = iptcData_->findKey(IptcKey(from));
if (pos == iptcData_->end()) return; if (pos == iptcData_->end())
if (!prepareXmpTarget(to)) return; return;
if (!prepareXmpTarget(to))
return;
while (pos != iptcData_->end()) { while (pos != iptcData_->end()) {
if (pos->key() == from) { if (pos->key() == from) {
std::string value = pos->toString(); std::string value = pos->toString();
@ -1136,8 +1178,10 @@ namespace Exiv2 {
void Converter::cnvXmpValueToIptc(const char* from, const char* to) void Converter::cnvXmpValueToIptc(const char* from, const char* to)
{ {
auto pos = xmpData_->findKey(XmpKey(from)); auto pos = xmpData_->findKey(XmpKey(from));
if (pos == xmpData_->end()) return; if (pos == xmpData_->end())
if (!prepareIptcTarget(to)) return; return;
if (!prepareIptcTarget(to))
return;
if (pos->typeId() == langAlt || pos->typeId() == xmpText) { if (pos->typeId() == langAlt || pos->typeId() == xmpText) {
std::string value; std::string value;
@ -1153,10 +1197,10 @@ namespace Exiv2 {
return; return;
} }
int count = pos->count(); size_t count = pos->count();
bool added = false; bool added = false;
for (int i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
std::string value = pos->toString(i); std::string value = pos->toString(static_cast<long>(i));
if (!pos->value().ok()) { if (!pos->value().ok()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n"; EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
@ -1193,7 +1237,7 @@ namespace Exiv2 {
if (pos == exifData_->end()) continue; if (pos == exifData_->end()) continue;
DataBuf data(pos->size()); DataBuf data(pos->size());
pos->copy(data.data(), littleEndian /* FIXME ? */); pos->copy(data.data(), littleEndian /* FIXME ? */);
MD5Update ( &context, data.c_data(), data.size()); MD5Update ( &context, data.c_data(), static_cast<uint32_t>(data.size()));
} }
} }
MD5Final(digest, &context); MD5Final(digest, &context);
@ -1326,7 +1370,8 @@ namespace Exiv2 {
bool convertStringCharset(std::string &str, const char* from, const char* to) bool convertStringCharset(std::string &str, const char* from, const char* to)
{ {
if (0 == strcmp(from, to)) return true; // nothing to do if (0 == strcmp(from, to))
return true; // nothing to do
bool ret = false; bool ret = false;
#if defined EXV_HAVE_ICONV #if defined EXV_HAVE_ICONV
ret = convertStringCharsetIconv(str, from, to); ret = convertStringCharsetIconv(str, from, to);
@ -1368,7 +1413,8 @@ namespace {
bool mb2wc(UINT cp, std::string& str) bool mb2wc(UINT cp, std::string& str)
{ {
if (str.empty()) return true; if (str.empty())
return true;
int len = MultiByteToWideChar(cp, 0, str.c_str(), (int)str.size(), 0, 0); int len = MultiByteToWideChar(cp, 0, str.c_str(), (int)str.size(), 0, 0);
if (len == 0) { if (len == 0) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
@ -1391,7 +1437,8 @@ namespace {
bool wc2mb(UINT cp, std::string& str) bool wc2mb(UINT cp, std::string& str)
{ {
if (str.empty()) return true; if (str.empty())
return true;
if (str.size() & 1) { if (str.size() & 1) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
EXV_DEBUG << "wc2mb: Size " << str.size() << " of input string is not even.\n"; EXV_DEBUG << "wc2mb: Size " << str.size() << " of input string is not even.\n";
@ -1506,7 +1553,8 @@ namespace {
#if defined EXV_HAVE_ICONV #if defined EXV_HAVE_ICONV
bool convertStringCharsetIconv(std::string& str, const char* from, const char* to) bool convertStringCharsetIconv(std::string& str, const char* from, const char* to)
{ {
if (0 == strcmp(from, to)) return true; // nothing to do if (0 == strcmp(from, to))
return true; // nothing to do
bool ret = true; bool ret = true;
iconv_t cd; iconv_t cd;

@ -177,7 +177,7 @@ namespace Exiv2 {
ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end()); ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end());
} }
std::unique_ptr<TiffHeaderBase> header(new Cr2Header(byteOrder)); Cr2Header header(byteOrder);
OffsetWriter offsetWriter; OffsetWriter offsetWriter;
offsetWriter.setOrigin(OffsetWriter::cr2RawIfdOffset, Cr2Header::offset2addr(), byteOrder); offsetWriter.setOrigin(OffsetWriter::cr2RawIfdOffset, Cr2Header::offset2addr(), byteOrder);
return TiffParserWorker::encode(io, return TiffParserWorker::encode(io,
@ -188,7 +188,7 @@ namespace Exiv2 {
xmpData, xmpData,
Tag::root, Tag::root,
TiffMapping::findEncoder, TiffMapping::findEncoder,
header.get(), &header,
&offsetWriter); &offsetWriter);
} }

@ -101,7 +101,7 @@ namespace Exiv2 {
throw Error(kerNotACrwImage); throw Error(kerNotACrwImage);
} }
clearMetadata(); clearMetadata();
DataBuf file(static_cast<long>(io().size())); DataBuf file(io().size());
io_->read(file.data(), file.size()); io_->read(file.data(), file.size());
CrwParser::decode(this, io_->mmap(), static_cast<uint32_t>(io_->size())); CrwParser::decode(this, io_->mmap(), static_cast<uint32_t>(io_->size()));
@ -120,7 +120,7 @@ namespace Exiv2 {
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (isCrwType(*io_, false)) { if (isCrwType(*io_, false)) {
// Read the image into a memory buffer // Read the image into a memory buffer
buf.alloc(static_cast<long>(io_->size())); buf.alloc(io_->size());
io_->read(buf.data(), buf.size()); io_->read(buf.data(), buf.size());
if (io_->error() || io_->eof()) { if (io_->error() || io_->eof()) {
buf.reset(); buf.reset();
@ -129,7 +129,7 @@ namespace Exiv2 {
} }
Blob blob; Blob blob;
CrwParser::encode(blob, buf.c_data(), buf.size(), this); CrwParser::encode(blob, buf.c_data(), static_cast<uint32_t>(buf.size()), this);
// Write new buffer to file // Write new buffer to file
auto tempIo = std::make_unique<MemIo>(); auto tempIo = std::make_unique<MemIo>();

@ -169,8 +169,6 @@ namespace Exiv2 {
CiffHeader::~CiffHeader() CiffHeader::~CiffHeader()
{ {
delete pRootDir_;
delete[] pPadding_;
} }
CiffDirectory::~CiffDirectory() CiffDirectory::~CiffDirectory()
@ -214,12 +212,12 @@ namespace Exiv2 {
throw Error(kerNotACrwImage); throw Error(kerNotACrwImage);
} }
delete[] pPadding_; pPadding_.clear();
pPadding_ = new byte[offset_ - 14]; pPadding_.resize(offset_ - 14);
padded_ = offset_ - 14; padded_ = offset_ - 14;
std::memcpy(pPadding_, pData + 14, padded_); std::copy_n(pData+14, padded_, pPadding_.begin());
pRootDir_ = new CiffDirectory; pRootDir_ = std::make_unique<CiffDirectory>();
pRootDir_->readDirectory(pData + offset_, size - offset_, byteOrder_); pRootDir_->readDirectory(pData + offset_, size - offset_, byteOrder_);
} // CiffHeader::read } // CiffHeader::read
@ -329,8 +327,9 @@ namespace Exiv2 {
void CiffHeader::decode(Image& image) const void CiffHeader::decode(Image& image) const
{ {
// Nothing to decode from the header itself, just add correct byte order // Nothing to decode from the header itself, just add correct byte order
if (pRootDir_) pRootDir_->decode(image, byteOrder_); if (pRootDir_)
} // CiffHeader::decode pRootDir_->decode(image, byteOrder_);
}
void CiffComponent::decode(Image& image, ByteOrder byteOrder) const void CiffComponent::decode(Image& image, ByteOrder byteOrder) const
{ {
@ -369,9 +368,9 @@ namespace Exiv2 {
append(blob, reinterpret_cast<const byte*>(signature_), 8); append(blob, reinterpret_cast<const byte*>(signature_), 8);
o += 8; o += 8;
// Pad as needed // Pad as needed
if (pPadding_) { if (pPadding_.empty() == false) {
assert(padded_ == offset_ - o); assert(padded_ == offset_ - o);
append(blob, pPadding_, padded_); append(blob, pPadding_.data(), padded_);
} }
else { else {
for (uint32_t i = o; i < offset_; ++i) { for (uint32_t i = o; i < offset_; ++i) {
@ -544,7 +543,7 @@ namespace Exiv2 {
{ {
storage_ = std::move(buf); storage_ = std::move(buf);
pData_ = storage_.c_data(); pData_ = storage_.c_data();
size_ = storage_.size(); size_ = static_cast<uint32_t>(storage_.size());
if (size_ > 8 && dataLocation() == directoryData) { if (size_ > 8 && dataLocation() == directoryData) {
tag_ &= 0x3fff; tag_ &= 0x3fff;
} }
@ -622,7 +621,7 @@ namespace Exiv2 {
assert(rootDirectory == 0x0000); assert(rootDirectory == 0x0000);
crwDirs.pop(); crwDirs.pop();
if (!pRootDir_) { if (!pRootDir_) {
pRootDir_ = new CiffDirectory; pRootDir_ = std::make_unique<CiffDirectory>();
} }
CiffComponent* child = pRootDir_->add(crwDirs, crwTagId); CiffComponent* child = pRootDir_->add(crwDirs, crwTagId);
if (child) { if (child) {
@ -683,7 +682,7 @@ namespace Exiv2 {
} }
if (cc_ == nullptr) { if (cc_ == nullptr) {
// Tag doesn't exist yet, add it // Tag doesn't exist yet, add it
m_ = UniquePtr(new CiffEntry(crwTagId, tag())); m_ = std::make_unique<CiffEntry>(crwTagId, tag());
cc_ = m_.get(); cc_ = m_.get();
add(std::move(m_)); add(std::move(m_));
} }
@ -1020,7 +1019,6 @@ namespace Exiv2 {
auto size = static_cast<uint32_t>(comment.size()); auto size = static_cast<uint32_t>(comment.size());
if (cc && cc->size() > size) size = cc->size(); if (cc && cc->size() > size) size = cc->size();
DataBuf buf(size); DataBuf buf(size);
buf.clear();
buf.copyBytes(0, comment.data(), comment.size()); buf.copyBytes(0, comment.data(), comment.size());
pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, std::move(buf)); pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, std::move(buf));
} }
@ -1028,7 +1026,6 @@ namespace Exiv2 {
if (cc) { if (cc) {
// Just delete the value, do not remove the tag // Just delete the value, do not remove the tag
DataBuf buf(cc->size()); DataBuf buf(cc->size());
buf.clear();
cc->setValue(std::move(buf)); cc->setValue(std::move(buf));
} }
} }
@ -1085,7 +1082,7 @@ namespace Exiv2 {
} }
assert(ifdId != ifdIdNotSet); assert(ifdId != ifdIdNotSet);
DataBuf buf = packIfdId(image.exifData(), ifdId, pHead->byteOrder()); DataBuf buf = packIfdId(image.exifData(), ifdId, pHead->byteOrder());
if (buf.size() == 0) { if (buf.empty()) {
// Try the undecoded tag // Try the undecoded tag
encodeBasic(image, pCrwMapping, pHead); encodeBasic(image, pCrwMapping, pHead);
} }
@ -1118,7 +1115,6 @@ namespace Exiv2 {
} }
if (t != 0) { if (t != 0) {
DataBuf buf(12); DataBuf buf(12);
buf.clear();
buf.write_uint32(0, static_cast<uint32_t>(t), pHead->byteOrder()); buf.write_uint32(0, static_cast<uint32_t>(t), pHead->byteOrder());
pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, std::move(buf)); pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, std::move(buf));
} }
@ -1153,7 +1149,6 @@ namespace Exiv2 {
size = cc->size(); size = cc->size();
} }
DataBuf buf(size); DataBuf buf(size);
buf.clear();
if (cc) buf.copyBytes(8, cc->pData() + 8, cc->size() - 8); if (cc) buf.copyBytes(8, cc->pData() + 8, cc->size() - 8);
if (edX != edEnd && edX->size() == 4) { if (edX != edEnd && edX->size() == 4) {
edX->copy(buf.data(), pHead->byteOrder()); edX->copy(buf.data(), pHead->byteOrder());
@ -1198,7 +1193,6 @@ namespace Exiv2 {
{ {
const uint16_t size = 1024; const uint16_t size = 1024;
DataBuf buf(size); DataBuf buf(size);
buf.clear();
uint16_t len = 0; uint16_t len = 0;

@ -493,10 +493,10 @@ namespace Exiv2 {
// DATA // DATA
static const char signature_[]; //!< Canon CRW signature "HEAPCCDR" static const char signature_[]; //!< Canon CRW signature "HEAPCCDR"
CiffDirectory* pRootDir_ = nullptr; //!< Pointer to the root directory std::unique_ptr<CiffDirectory> pRootDir_; //!< Pointer to the root directory
ByteOrder byteOrder_ = littleEndian; //!< Applicable byte order ByteOrder byteOrder_ = littleEndian; //!< Applicable byte order
uint32_t offset_ = 0; //!< Offset to the start of the root dir uint32_t offset_ = 0; //!< Offset to the start of the root dir
byte* pPadding_ = nullptr; //!< Pointer to the (unknown) remainder std::vector<byte> pPadding_; //!< the (unknown) remainder
uint32_t padded_ = 0; //!< Number of padding-bytes uint32_t padded_ = 0; //!< Number of padding-bytes
}; // class CiffHeader }; // class CiffHeader

@ -107,8 +107,9 @@ namespace {
//! Write data into temp file, taking care of errors //! Write data into temp file, taking care of errors
void writeTemp(BasicIo& tempIo, const byte* data, size_t size) void writeTemp(BasicIo& tempIo, const byte* data, size_t size)
{ {
if (size == 0) return; if (size == 0)
if (tempIo.write(data, static_cast<long>(size)) != static_cast<long>(size)) { return;
if (tempIo.write(data, size) != size) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to write to temporary file.\n"; EXV_WARNING << "Failed to write to temporary file.\n";
#endif #endif
@ -1079,7 +1080,7 @@ namespace Exiv2
EXV_DEBUG << "Exiv2::EpsImage:: Creating blank EPS image\n"; EXV_DEBUG << "Exiv2::EpsImage:: Creating blank EPS image\n";
#endif #endif
IoCloser closer(*io_); IoCloser closer(*io_);
if (io_->write(reinterpret_cast<const byte*>(epsBlank.data()), static_cast<long>(epsBlank.size())) != static_cast<long>(epsBlank.size())) { if (io_->write(reinterpret_cast<const byte*>(epsBlank.data()), epsBlank.size()) != epsBlank.size()) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to write blank EPS image.\n"; EXV_WARNING << "Failed to write blank EPS image.\n";
#endif #endif
@ -1157,10 +1158,10 @@ namespace Exiv2
bool isEpsType(BasicIo& iIo, bool advance) bool isEpsType(BasicIo& iIo, bool advance)
{ {
// read as many bytes as needed for the longest (DOS) EPS signature // read as many bytes as needed for the longest (DOS) EPS signature
long bufSize = static_cast<long>(dosEpsSignature.size()); size_t bufSize = dosEpsSignature.size();
for (auto&& i : epsFirstLine) { for (auto&& i : epsFirstLine) {
if (bufSize < static_cast<long>(i.size())) { if (bufSize < i.size()) {
bufSize = static_cast<long>(i.size()); bufSize = i.size();
} }
} }
const long restore = iIo.tell(); // save const long restore = iIo.tell(); // save

@ -181,7 +181,7 @@ namespace Exiv2 {
template<typename T> template<typename T>
Exiv2::Exifdatum& setValue(Exiv2::Exifdatum& exifDatum, const T& value) Exiv2::Exifdatum& setValue(Exiv2::Exifdatum& exifDatum, const T& value)
{ {
auto v = std::unique_ptr<Exiv2::ValueType<T> >(new Exiv2::ValueType<T>); auto v = std::make_unique<Exiv2::ValueType<T>>();
v->value_.push_back(value); v->value_.push_back(value);
exifDatum.value_ = std::move(v); exifDatum.value_ = std::move(v);
return exifDatum; return exifDatum;
@ -315,7 +315,7 @@ namespace Exiv2 {
return value_->read(value); return value_->read(value);
} }
int Exifdatum::setDataArea(const byte* buf, long len) int Exifdatum::setDataArea(const byte* buf, size_t len)
{ {
return value_.get() == nullptr ? -1 : value_->setDataArea(buf, len); return value_.get() == nullptr ? -1 : value_->setDataArea(buf, len);
} }
@ -382,17 +382,17 @@ namespace Exiv2 {
long Exifdatum::typeSize() const long Exifdatum::typeSize() const
{ {
return TypeInfo::typeSize(typeId()); return static_cast<long>(TypeInfo::typeSize(typeId()));
} }
long Exifdatum::count() const size_t Exifdatum::count() const
{ {
return value_.get() == nullptr ? 0 : value_->count(); return value_.get() == nullptr ? 0 : value_->count();
} }
long Exifdatum::size() const long Exifdatum::size() const
{ {
return value_.get() == nullptr ? 0 : value_->size(); return value_.get() == nullptr ? 0 : static_cast<long>(value_->size());
} }
std::string Exifdatum::toString() const std::string Exifdatum::toString() const
@ -425,7 +425,7 @@ namespace Exiv2 {
return value_.get() == nullptr ? nullptr : value_->clone(); return value_.get() == nullptr ? nullptr : value_->clone();
} }
long Exifdatum::sizeDataArea() const size_t Exifdatum::sizeDataArea() const
{ {
return value_.get() == nullptr ? 0 : value_->sizeDataArea(); return value_.get() == nullptr ? 0 : value_->sizeDataArea();
} }
@ -448,7 +448,7 @@ namespace Exiv2 {
return thumbnail->copy(exifData_); return thumbnail->copy(exifData_);
} }
long ExifThumbC::writeFile(const std::string& path) const size_t ExifThumbC::writeFile(const std::string& path) const
{ {
auto thumbnail = Thumbnail::create(exifData_); auto thumbnail = Thumbnail::create(exifData_);
if (!thumbnail.get()) if (!thumbnail.get())
@ -456,7 +456,7 @@ namespace Exiv2 {
std::string name = path + thumbnail->extension(); std::string name = path + thumbnail->extension();
DataBuf buf(thumbnail->copy(exifData_)); DataBuf buf(thumbnail->copy(exifData_));
if (buf.size() == 0) if (buf.empty())
return 0; return 0;
return Exiv2::writeFile(buf, name); return Exiv2::writeFile(buf, name);
@ -483,24 +483,13 @@ namespace Exiv2 {
{ {
} }
void ExifThumb::setJpegThumbnail( void ExifThumb::setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit)
const std::string& path,
URational xres,
URational yres,
uint16_t unit
)
{ {
DataBuf thumb = readFile(path); // may throw DataBuf thumb = readFile(path); // may throw
setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit); setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit);
} }
void ExifThumb::setJpegThumbnail( void ExifThumb::setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit)
const byte* buf,
long size,
URational xres,
URational yres,
uint16_t unit
)
{ {
setJpegThumbnail(buf, size); setJpegThumbnail(buf, size);
exifData_["Exif.Thumbnail.XResolution"] = xres; exifData_["Exif.Thumbnail.XResolution"] = xres;
@ -514,7 +503,7 @@ namespace Exiv2 {
setJpegThumbnail(thumb.c_data(), thumb.size()); setJpegThumbnail(thumb.c_data(), thumb.size());
} }
void ExifThumb::setJpegThumbnail(const byte* buf, long size) void ExifThumb::setJpegThumbnail(const byte* buf, size_t size)
{ {
exifData_["Exif.Thumbnail.Compression"] = uint16_t(6); exifData_["Exif.Thumbnail.Compression"] = uint16_t(6);
Exifdatum& format = exifData_["Exif.Thumbnail.JPEGInterchangeFormat"]; Exifdatum& format = exifData_["Exif.Thumbnail.JPEGInterchangeFormat"];
@ -587,19 +576,11 @@ namespace Exiv2 {
return exifMetadata_.erase(pos); return exifMetadata_.erase(pos);
} }
ByteOrder ExifParser::decode( ByteOrder ExifParser::decode(ExifData& exifData, const byte* pData, size_t size)
ExifData& exifData,
const byte* pData,
uint32_t size
)
{ {
IptcData iptcData; IptcData iptcData;
XmpData xmpData; XmpData xmpData;
ByteOrder bo = TiffParser::decode(exifData, ByteOrder bo = TiffParser::decode(exifData, iptcData, xmpData, pData, size);
iptcData,
xmpData,
pData,
size);
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
if (!iptcData.empty()) { if (!iptcData.empty()) {
EXV_WARNING << "Ignoring IPTC information encoded in the Exif data.\n"; EXV_WARNING << "Ignoring IPTC information encoded in the Exif data.\n";
@ -609,7 +590,7 @@ namespace Exiv2 {
} }
#endif #endif
return bo; return bo;
} // ExifParser::decode }
//! @cond IGNORE //! @cond IGNORE
enum Ptt { pttLen, pttTag, pttIfd }; enum Ptt { pttLen, pttTag, pttIfd };
@ -619,13 +600,8 @@ namespace Exiv2 {
}; };
//! @endcond //! @endcond
WriteMethod ExifParser::encode( WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteOrder byteOrder,
Blob& blob, const ExifData& exifData)
const byte* pData,
uint32_t size,
ByteOrder byteOrder,
const ExifData& exifData
)
{ {
ExifData ed = exifData; ExifData ed = exifData;
@ -696,9 +672,9 @@ namespace Exiv2 {
// Encode and check if the result fits into a JPEG Exif APP1 segment // Encode and check if the result fits into a JPEG Exif APP1 segment
MemIo mio1; MemIo mio1;
std::unique_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder, 0x00000008, false)); TiffHeader header(byteOrder, 0x00000008, false);
WriteMethod wm = TiffParserWorker::encode(mio1, pData, size, ed, emptyIptc, emptyXmp, Tag::root, WriteMethod wm = TiffParserWorker::encode(mio1, pData, static_cast<uint32_t>(size), ed, emptyIptc, emptyXmp,
TiffMapping::findEncoder, header.get(), nullptr); Tag::root, TiffMapping::findEncoder, &header, nullptr);
if (mio1.size() <= 65527) { if (mio1.size() <= 65527) {
append(blob, mio1.mmap(), static_cast<uint32_t>(mio1.size())); append(blob, mio1.mmap(), static_cast<uint32_t>(mio1.size()));
return wm; return wm;
@ -795,8 +771,8 @@ namespace Exiv2 {
// Encode the remaining Exif tags again, don't care if it fits this time // Encode the remaining Exif tags again, don't care if it fits this time
MemIo mio2; MemIo mio2;
wm = TiffParserWorker::encode(mio2, pData, size, ed, emptyIptc, emptyXmp, Tag::root, TiffMapping::findEncoder, wm = TiffParserWorker::encode(mio2, pData, static_cast<uint32_t>(size), ed, emptyIptc, emptyXmp, Tag::root,
header.get(), nullptr); TiffMapping::findEncoder, &header, nullptr);
append(blob, mio2.mmap(), static_cast<uint32_t>(mio2.size())); append(blob, mio2.mmap(), static_cast<uint32_t>(mio2.size()));
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
if (wm == wmIntrusive) { if (wm == wmIntrusive) {
@ -868,7 +844,7 @@ namespace {
Exiv2::IptcData emptyIptc; Exiv2::IptcData emptyIptc;
Exiv2::XmpData emptyXmp; Exiv2::XmpData emptyXmp;
Exiv2::TiffParser::encode(io, nullptr, 0, Exiv2::littleEndian, thumb, emptyIptc, emptyXmp); Exiv2::TiffParser::encode(io, nullptr, 0, Exiv2::littleEndian, thumb, emptyIptc, emptyXmp);
return io.read(static_cast<long>(io.size())); return io.read(io.size());
} }
const char* JpegThumbnail::mimeType() const const char* JpegThumbnail::mimeType() const
@ -892,8 +868,8 @@ namespace {
int64_t sumToLong(const Exiv2::Exifdatum& md) int64_t sumToLong(const Exiv2::Exifdatum& md)
{ {
int64_t sum = 0; int64_t sum = 0;
for (long i = 0; i < md.count(); ++i) { for (size_t i = 0; i < md.count(); ++i) {
sum += md.toInt64(i); sum += md.toInt64(static_cast<long>(i));
} }
return sum; return sum;
} }

@ -23,7 +23,9 @@
std::string string_from_unterminated(const char* data, size_t data_length) std::string string_from_unterminated(const char* data, size_t data_length)
{ {
if (data_length == 0) {
return {};
}
const size_t StringLength = strnlen(data, data_length); const size_t StringLength = strnlen(data, data_length);
return std::string(data, StringLength); return std::string(data, StringLength);
} }

@ -406,7 +406,6 @@ namespace Exiv2 {
enforce(allocate64 <= static_cast<uint64_t>(std::numeric_limits<long>::max()), kerCorruptedMetadata); enforce(allocate64 <= static_cast<uint64_t>(std::numeric_limits<long>::max()), kerCorruptedMetadata);
const long allocate = static_cast<long>(allocate64); const long allocate = static_cast<long>(allocate64);
DataBuf buf(allocate); // allocate a buffer DataBuf buf(allocate); // allocate a buffer
buf.clear();
buf.copyBytes(0, dir.c_data(8), 4); // copy dir[8:11] into buffer (short strings) buf.copyBytes(0, dir.c_data(8), 4); // copy dir[8:11] into buffer (short strings)
// We have already checked that this multiplication cannot overflow. // We have already checked that this multiplication cannot overflow.
@ -416,7 +415,7 @@ namespace Exiv2 {
if ( bOffsetIsPointer ) { // read into buffer if ( bOffsetIsPointer ) { // read into buffer
const long restore = io.tell(); // save const long restore = io.tell(); // save
io.seekOrThrow(offset, BasicIo::beg, kerCorruptedMetadata); // position io.seekOrThrow(offset, BasicIo::beg, kerCorruptedMetadata); // position
io.readOrThrow(buf.data(), static_cast<long>(count_x_size), kerCorruptedMetadata); // read io.readOrThrow(buf.data(), count_x_size, kerCorruptedMetadata); // read
io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); // restore io.seekOrThrow(restore, BasicIo::beg, kerCorruptedMetadata); // restore
} }
@ -673,7 +672,7 @@ namespace Exiv2 {
if (iccProfile.size() < static_cast<long>(sizeof(long))) { if (iccProfile.size() < static_cast<long>(sizeof(long))) {
throw Error(kerInvalidIccProfile); throw Error(kerInvalidIccProfile);
} }
const long size = iccProfile.read_uint32(0, bigEndian); const size_t size = iccProfile.read_uint32(0, bigEndian);
if (size != iccProfile.size()) { if (size != iccProfile.size()) {
throw Error(kerInvalidIccProfile); throw Error(kerInvalidIccProfile);
} }
@ -827,7 +826,7 @@ namespace Exiv2 {
return getType(fileIo); return getType(fileIo);
} }
ImageType ImageFactory::getType(const byte* data, long size) ImageType ImageFactory::getType(const byte* data, size_t size)
{ {
MemIo memIo(data, size); MemIo memIo(data, size);
return getType(memIo); return getType(memIo);
@ -876,7 +875,7 @@ namespace Exiv2 {
return image; return image;
} }
Image::UniquePtr ImageFactory::open(const byte* data, long size) Image::UniquePtr ImageFactory::open(const byte* data, size_t size)
{ {
auto io = std::make_unique<MemIo>(data, size); auto io = std::make_unique<MemIo>(data, size);
auto image = open(std::move(io)); // may throw auto image = open(std::move(io)); // may throw
@ -938,7 +937,7 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// template, inline and free functions // template, inline and free functions
void append(Blob& blob, const byte* buf, uint32_t len) void append(Blob& blob, const byte* buf, size_t len)
{ {
if (len != 0) { if (len != 0) {
assert(buf != 0); assert(buf != 0);

@ -158,17 +158,17 @@ namespace Exiv2 {
long Iptcdatum::typeSize() const long Iptcdatum::typeSize() const
{ {
return TypeInfo::typeSize(typeId()); return static_cast<long>(TypeInfo::typeSize(typeId()));
} }
long Iptcdatum::count() const size_t Iptcdatum::count() const
{ {
return value_.get() == nullptr ? 0 : value_->count(); return value_.get() == nullptr ? 0 : value_->count();
} }
long Iptcdatum::size() const long Iptcdatum::size() const
{ {
return value_.get() == nullptr ? 0 : value_->size(); return value_.get() == nullptr ? 0 : static_cast<long>(value_->size());
} }
std::string Iptcdatum::toString() const std::string Iptcdatum::toString() const
@ -505,6 +505,9 @@ namespace Exiv2 {
DataBuf IptcParser::encode(const IptcData& iptcData) DataBuf IptcParser::encode(const IptcData& iptcData)
{ {
if (iptcData.empty())
return {};
DataBuf buf(iptcData.size()); DataBuf buf(iptcData.size());
byte *pWrite = buf.data(); byte *pWrite = buf.data();

@ -35,6 +35,7 @@
#include "safe_op.hpp" #include "safe_op.hpp"
// + standard includes // + standard includes
#include <array>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -283,9 +284,9 @@ static void boxes_check(size_t b,size_t m)
if (data_length > io_->size() - io_->tell()) { if (data_length > io_->size() - io_->tell()) {
throw Error(kerCorruptedMetadata); throw Error(kerCorruptedMetadata);
} }
DataBuf data(static_cast<long>(data_length)); DataBuf data(data_length);
io_->read(data.data(), data.size()); io_->read(data.data(), data.size());
const long iccLength = data.read_uint32(pad, bigEndian); const size_t iccLength = data.read_uint32(pad, bigEndian);
// subtracting pad from data.size() is safe: // subtracting pad from data.size() is safe:
// data.size() is at least 8 and pad = 3 // data.size() is at least 8 and pad = 3
if (iccLength > data.size() - pad) { if (iccLength > data.size() - pad) {
@ -338,7 +339,7 @@ static void boxes_check(size_t b,size_t m)
if (io_->read(reinterpret_cast<byte*>(&uuid), sizeof(uuid)) == sizeof(uuid)) { if (io_->read(reinterpret_cast<byte*>(&uuid), sizeof(uuid)) == sizeof(uuid)) {
DataBuf rawData; DataBuf rawData;
long bufRead; size_t bufRead;
bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0; bool bIsExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0;
bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0; bool bIsIPTC = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0;
bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0; bool bIsXMP = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0;
@ -362,12 +363,11 @@ static void boxes_check(size_t b,size_t m)
long pos = (a == b && (a=='I' || a=='M')) ? 0 : -1; long pos = (a == b && (a=='I' || a=='M')) ? 0 : -1;
// #1242 Forgive having Exif\0\0 in rawData.pData_ // #1242 Forgive having Exif\0\0 in rawData.pData_
const byte exifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; std::array<byte, 6> exifHeader { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
for (long i = 0; pos < 0 && i < rawData.size() - static_cast<long>(sizeof(exifHeader)); for (size_t i = 0; pos < 0 && i < (rawData.size() - exifHeader.size()); i++) {
i++) { if (rawData.cmpBytes(i, exifHeader.data(), exifHeader.size()) == 0)
if (rawData.cmpBytes(i, exifHeader, sizeof(exifHeader)) == 0)
{ {
pos = i+sizeof(exifHeader); pos = static_cast<long>(i+sizeof(exifHeader));
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Reading non-standard UUID-EXIF_bad box in " << io_->path() << std::endl; EXV_WARNING << "Reading non-standard UUID-EXIF_bad box in " << io_->path() << std::endl;
#endif #endif
@ -409,7 +409,7 @@ static void boxes_check(size_t b,size_t m)
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error()) throw Error(kerFailedToReadImageData);
if (bufRead != rawData.size()) throw Error(kerInputDataReadFailed); if (bufRead != rawData.size()) throw Error(kerInputDataReadFailed);
if (IptcParser::decode(iptcData_, rawData.c_data(), rawData.size())) if (IptcParser::decode(iptcData_, rawData.c_data(), static_cast<uint32_t>(rawData.size())))
{ {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode IPTC metadata." << std::endl; EXV_WARNING << "Failed to decode IPTC metadata." << std::endl;
@ -530,15 +530,14 @@ static void boxes_check(size_t b,size_t m)
DataBuf data(subBox.length - sizeof(box)); DataBuf data(subBox.length - sizeof(box));
io_->read(data.data(), data.size()); io_->read(data.data(), data.size());
if (bPrint) { if (bPrint) {
out << Internal::stringFormat("%8ld | %8ld | sub:", static_cast<size_t>(address), out << Internal::stringFormat("%8ld | %8ld | sub:", address, subBox.length)
static_cast<size_t>(subBox.length))
<< toAscii(subBox.type) << " | " << toAscii(subBox.type) << " | "
<< Internal::binaryToString(makeSlice(data, 0, std::min(30L, data.size()))); << Internal::binaryToString(makeSlice(data, 0, std::min(static_cast<size_t>(30), data.size())));
bLF = true; bLF = true;
} }
if (subBox.type == kJp2BoxTypeColorHeader) { if (subBox.type == kJp2BoxTypeColorHeader) {
long pad = 3; // don't know why there are 3 padding bytes const size_t pad = 3; // don't know why there are 3 padding bytes
// Bounds-check for the `getULong()` below, which reads 4 bytes, starting at `pad`. // Bounds-check for the `getULong()` below, which reads 4 bytes, starting at `pad`.
enforce(data.size() >= pad + 4, kerCorruptedMetadata); enforce(data.size() >= pad + 4, kerCorruptedMetadata);
@ -548,7 +547,8 @@ static void boxes_check(size_t b,size_t m)
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
out << " " << static_cast<int>(data.read_uint8(i)); out << " " << static_cast<int>(data.read_uint8(i));
} }
long iccLength = data.read_uint32(pad, bigEndian);
const size_t iccLength = data.read_uint32(pad, bigEndian);
if (bPrint) { if (bPrint) {
out << " | iccLength:" << iccLength; out << " | iccLength:" << iccLength;
} }
@ -583,7 +583,7 @@ static void boxes_check(size_t b,size_t m)
DataBuf rawData; DataBuf rawData;
enforce(box.length >= sizeof(uuid) + sizeof(box), kerCorruptedMetadata); enforce(box.length >= sizeof(uuid) + sizeof(box), kerCorruptedMetadata);
rawData.alloc(box.length - sizeof(uuid) - sizeof(box)); rawData.alloc(box.length - sizeof(uuid) - sizeof(box));
long bufRead = io_->read(rawData.data(), rawData.size()); const size_t bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error()) if (io_->error())
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
if (bufRead != rawData.size()) if (bufRead != rawData.size())
@ -655,10 +655,10 @@ static void boxes_check(size_t b,size_t m)
DataBuf output(boxBuf.size() + iccProfile_.size() + 100); // allocate sufficient space DataBuf output(boxBuf.size() + iccProfile_.size() + 100); // allocate sufficient space
long outlen = sizeof(Jp2BoxHeader) ; // now many bytes have we written to output? long outlen = sizeof(Jp2BoxHeader) ; // now many bytes have we written to output?
long inlen = sizeof(Jp2BoxHeader) ; // how many bytes have we read from boxBuf? long inlen = sizeof(Jp2BoxHeader) ; // how many bytes have we read from boxBuf?
enforce(sizeof(Jp2BoxHeader) <= static_cast<size_t>(output.size()), Exiv2::kerCorruptedMetadata); enforce(sizeof(Jp2BoxHeader) <= output.size(), Exiv2::kerCorruptedMetadata);
auto pBox = reinterpret_cast<const Jp2BoxHeader*>(boxBuf.c_data()); auto pBox = reinterpret_cast<const Jp2BoxHeader*>(boxBuf.c_data());
uint32_t length = getLong(reinterpret_cast<const byte*>(&pBox->length), bigEndian); uint32_t length = getLong(reinterpret_cast<const byte*>(&pBox->length), bigEndian);
enforce(length <= static_cast<size_t>(output.size()), Exiv2::kerCorruptedMetadata); enforce(length <= output.size(), Exiv2::kerCorruptedMetadata);
uint32_t count = sizeof (Jp2BoxHeader); uint32_t count = sizeof (Jp2BoxHeader);
auto p = boxBuf.c_str(); auto p = boxBuf.c_str();
bool bWroteColor = false ; bool bWroteColor = false ;
@ -694,7 +694,7 @@ static void boxes_check(size_t b,size_t m)
const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid"; const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid";
uint32_t psize = 15; uint32_t psize = 15;
newlen = sizeof(newBox) + psize ; newlen = sizeof(newBox) + psize ;
enforce(newlen <= static_cast<size_t>(output.size() - outlen), Exiv2::kerCorruptedMetadata); enforce(newlen <= output.size() - outlen, Exiv2::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), psize, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.length), psize, bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
output.copyBytes(outlen ,&newBox ,sizeof(newBox)); output.copyBytes(outlen ,&newBox ,sizeof(newBox));
@ -702,7 +702,7 @@ static void boxes_check(size_t b,size_t m)
} else { } else {
const char* pad = "\x02\x00\x00"; const char* pad = "\x02\x00\x00";
uint32_t psize = 3; uint32_t psize = 3;
newlen = sizeof(newBox) + psize + iccProfile_.size(); newlen = sizeof(newBox) + psize + static_cast<uint32_t>(iccProfile_.size());
enforce(newlen <= static_cast<size_t>(output.size() - outlen), Exiv2::kerCorruptedMetadata); enforce(newlen <= static_cast<size_t>(output.size() - outlen), Exiv2::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), newlen, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.length), newlen, bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
@ -766,11 +766,11 @@ static void boxes_check(size_t b,size_t m)
#endif #endif
// Read chunk header. // Read chunk header.
size_t bufRead = io_->read(bheaderBuf.data(), bheaderBuf.size());
bheaderBuf.clear(); if (io_->error())
long bufRead = io_->read(bheaderBuf.data(), bheaderBuf.size()); throw Error(kerFailedToReadImageData);
if (io_->error()) throw Error(kerFailedToReadImageData); if (bufRead != bheaderBuf.size())
if (bufRead != bheaderBuf.size()) throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
// Decode box header. // Decode box header.
@ -812,7 +812,7 @@ static void boxes_check(size_t b,size_t m)
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
} }
if (bufRead != static_cast<long>(box.length - 8)) { if (bufRead != (box.length - 8)) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: Cannot read source file data" << std::endl; std::cout << "Exiv2::Jp2Image::doWriteMetadata: Cannot read source file data" << std::endl;
#endif #endif
@ -828,7 +828,8 @@ static void boxes_check(size_t b,size_t m)
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (length: " << box.length << ")" << std::endl; std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (length: " << box.length << ")" << std::endl;
#endif #endif
if (outIo.write(newBuf.data(), newBuf.size()) != newBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(newBuf.data(), newBuf.size()) != newBuf.size())
throw Error(kerImageWriteFailed);
// Write all updated metadata here, just after JP2Header. // Write all updated metadata here, just after JP2Header.
@ -843,7 +844,7 @@ static void boxes_check(size_t b,size_t m)
rawExif.copyBytes(0, &blob[0], blob.size()); rawExif.copyBytes(0, &blob[0], blob.size());
DataBuf boxData(8 + 16 + rawExif.size()); DataBuf boxData(8 + 16 + rawExif.size());
ul2Data(boxDataSize, boxData.size(), Exiv2::bigEndian); ul2Data(boxDataSize, static_cast<uint32_t>(boxData.size()), Exiv2::bigEndian);
ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian);
boxData.copyBytes(0, boxDataSize, 4); boxData.copyBytes(0, boxDataSize, 4);
boxData.copyBytes(4, boxUUIDtype, 4); boxData.copyBytes(4, boxUUIDtype, 4);
@ -854,7 +855,8 @@ static void boxes_check(size_t b,size_t m)
std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Exif metadata (length: " std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Exif metadata (length: "
<< boxData.size() << std::endl; << boxData.size() << std::endl;
#endif #endif
if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size()) throw Error(kerImageWriteFailed); if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size())
throw Error(kerImageWriteFailed);
} }
} }
@ -866,7 +868,7 @@ static void boxes_check(size_t b,size_t m)
if (rawIptc.size() > 0) if (rawIptc.size() > 0)
{ {
DataBuf boxData(8 + 16 + rawIptc.size()); DataBuf boxData(8 + 16 + rawIptc.size());
ul2Data(boxDataSize, boxData.size(), Exiv2::bigEndian); ul2Data(boxDataSize, static_cast<uint32_t>(boxData.size()), Exiv2::bigEndian);
ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian);
boxData.copyBytes(0, boxDataSize, 4); boxData.copyBytes(0, boxDataSize, 4);
boxData.copyBytes(4, boxUUIDtype, 4); boxData.copyBytes(4, boxUUIDtype, 4);
@ -877,7 +879,8 @@ static void boxes_check(size_t b,size_t m)
std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Iptc metadata (length: " std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Iptc metadata (length: "
<< boxData.size() << std::endl; << boxData.size() << std::endl;
#endif #endif
if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size()) throw Error(kerImageWriteFailed); if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size())
throw Error(kerImageWriteFailed);
} }
} }
@ -894,7 +897,7 @@ static void boxes_check(size_t b,size_t m)
DataBuf xmp(reinterpret_cast<const byte*>(xmpPacket_.data()), static_cast<long>(xmpPacket_.size())); DataBuf xmp(reinterpret_cast<const byte*>(xmpPacket_.data()), static_cast<long>(xmpPacket_.size()));
DataBuf boxData(8 + 16 + xmp.size()); DataBuf boxData(8 + 16 + xmp.size());
ul2Data(boxDataSize, boxData.size(), Exiv2::bigEndian); ul2Data(boxDataSize, static_cast<uint32_t>(boxData.size()), Exiv2::bigEndian);
ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian);
boxData.copyBytes(0, boxDataSize, 4); boxData.copyBytes(0, boxDataSize, 4);
boxData.copyBytes(4, boxUUIDtype, 4); boxData.copyBytes(4, boxUUIDtype, 4);
@ -905,7 +908,8 @@ static void boxes_check(size_t b,size_t m)
std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with XMP metadata (length: " std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with XMP metadata (length: "
<< boxData.size() << ")" << std::endl; << boxData.size() << ")" << std::endl;
#endif #endif
if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size()) throw Error(kerImageWriteFailed); if (outIo.write(boxData.c_data(), boxData.size()) != boxData.size())
throw Error(kerImageWriteFailed);
} }
break; break;
@ -937,7 +941,8 @@ static void boxes_check(size_t b,size_t m)
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: write Uuid box (length: " << box.length << ")" << std::endl; std::cout << "Exiv2::Jp2Image::doWriteMetadata: write Uuid box (length: " << box.length << ")" << std::endl;
#endif #endif
if (outIo.write(boxBuf.c_data(), boxBuf.size()) != boxBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(boxBuf.c_data(), boxBuf.size()) != boxBuf.size())
throw Error(kerImageWriteFailed);
} }
break; break;
} }
@ -947,7 +952,8 @@ static void boxes_check(size_t b,size_t m)
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: write box (length: " << box.length << ")" << std::endl; std::cout << "Exiv2::Jp2Image::doWriteMetadata: write box (length: " << box.length << ")" << std::endl;
#endif #endif
if (outIo.write(boxBuf.c_data(), boxBuf.size()) != boxBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(boxBuf.c_data(), boxBuf.size()) != boxBuf.size())
throw Error(kerImageWriteFailed);
break; break;
} }

@ -41,6 +41,7 @@
#include "fff.h" #include "fff.h"
// + standard includes // + standard includes
#include <algorithm> // for EOF
#include <cstdio> // for EOF #include <cstdio> // for EOF
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
@ -99,10 +100,10 @@ namespace Exiv2 {
return inRange(lo1,value,hi1) || inRange(lo2,value,hi2); return inRange(lo1,value,hi1) || inRange(lo2,value,hi2);
} }
bool Photoshop::isIrb(const byte* pPsData, bool Photoshop::isIrb(const byte* pPsData, size_t sizePsData)
long sizePsData)
{ {
if (sizePsData < 4) return false; if (sizePsData < 4)
return false;
for (auto&& i : irbId_) { for (auto&& i : irbId_) {
assert(strlen(i) == 4); assert(strlen(i) == 4);
if (memcmp(pPsData, i, 4) == 0) if (memcmp(pPsData, i, 4) == 0)
@ -111,8 +112,7 @@ namespace Exiv2 {
return false; return false;
} }
bool Photoshop::valid(const byte* pPsData, bool Photoshop::valid(const byte* pPsData, size_t sizePsData)
long sizePsData)
{ {
const byte* record = nullptr; const byte* record = nullptr;
uint32_t sizeIptc = 0; uint32_t sizeIptc = 0;
@ -121,8 +121,7 @@ namespace Exiv2 {
const byte* pEnd = pPsData + sizePsData; const byte* pEnd = pPsData + sizePsData;
int ret = 0; int ret = 0;
while (pCur < pEnd while (pCur < pEnd
&& 0 == (ret = Photoshop::locateIptcIrb(pCur, static_cast<long>(pEnd - pCur), && 0 == (ret = Photoshop::locateIptcIrb(pCur, (pEnd - pCur), &record, &sizeHdr, &sizeIptc))) {
&record, &sizeHdr, &sizeIptc))) {
pCur = record + sizeHdr + sizeIptc + (sizeIptc & 1); pCur = record + sizeHdr + sizeIptc + (sizeIptc & 1);
} }
return ret >= 0; return ret >= 0;
@ -132,7 +131,7 @@ namespace Exiv2 {
// the format (in particular the header). So it remains to be confirmed // the format (in particular the header). So it remains to be confirmed
// if this also makes sense for psTag != Photoshop::iptc // if this also makes sense for psTag != Photoshop::iptc
int Photoshop::locateIrb(const byte* pPsData, int Photoshop::locateIrb(const byte* pPsData,
long sizePsData, size_t sizePsData,
uint16_t psTag, uint16_t psTag,
const byte** record, const byte** record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
@ -141,8 +140,12 @@ namespace Exiv2 {
assert(record); assert(record);
assert(sizeHdr); assert(sizeHdr);
assert(sizeData); assert(sizeData);
if (sizePsData < 12) {
return 3;
}
// Used for error checking // Used for error checking
long position = 0; size_t position = 0;
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Photoshop::locateIrb: "; std::cerr << "Photoshop::locateIrb: ";
#endif #endif
@ -168,7 +171,7 @@ namespace Exiv2 {
} }
uint32_t dataSize = getULong(pPsData + position, bigEndian); uint32_t dataSize = getULong(pPsData + position, bigEndian);
position += 4; position += 4;
if (dataSize > static_cast<uint32_t>(sizePsData - position)) { if (dataSize > (sizePsData - position)) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Warning: " std::cerr << "Warning: "
<< "Invalid Photoshop IRB data size " << "Invalid Photoshop IRB data size "
@ -206,10 +209,10 @@ namespace Exiv2 {
return -2; return -2;
} }
return 3; return 3;
} // Photoshop::locateIrb }
int Photoshop::locateIptcIrb(const byte* pPsData, int Photoshop::locateIptcIrb(const byte* pPsData,
long sizePsData, size_t sizePsData,
const byte** record, const byte** record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
uint32_t *const sizeData) uint32_t *const sizeData)
@ -219,7 +222,7 @@ namespace Exiv2 {
} }
int Photoshop::locatePreviewIrb(const byte* pPsData, int Photoshop::locatePreviewIrb(const byte* pPsData,
long sizePsData, size_t sizePsData,
const byte** record, const byte** record,
uint32_t *const sizeHdr, uint32_t *const sizeHdr,
uint32_t *const sizeData) uint32_t *const sizeData)
@ -228,11 +231,10 @@ namespace Exiv2 {
record, sizeHdr, sizeData); record, sizeHdr, sizeData);
} }
DataBuf Photoshop::setIptcIrb(const byte* pPsData, DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const IptcData& iptcData)
long sizePsData,
const IptcData& iptcData)
{ {
if (sizePsData > 0) assert(pPsData); if (sizePsData > 0)
assert(pPsData);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "IRB block at the beginning of Photoshop::setIptcIrb\n"; std::cerr << "IRB block at the beginning of Photoshop::setIptcIrb\n";
if (sizePsData == 0) std::cerr << " None.\n"; if (sizePsData == 0) std::cerr << " None.\n";
@ -243,36 +245,35 @@ namespace Exiv2 {
uint32_t sizeHdr = 0; uint32_t sizeHdr = 0;
DataBuf rc; DataBuf rc;
// Safe to call with zero psData.size_ // Safe to call with zero psData.size_
if (0 > Photoshop::locateIptcIrb(pPsData, sizePsData, if (0 > Photoshop::locateIptcIrb(pPsData, sizePsData, &record, &sizeHdr, &sizeIptc)) {
&record, &sizeHdr, &sizeIptc)) {
return rc; return rc;
} }
Blob psBlob; Blob psBlob;
const auto sizeFront = static_cast<uint32_t>(record - pPsData); const auto sizeFront = static_cast<size_t>(record - pPsData);
// Write data before old record. // Write data before old record.
if (sizePsData > 0 && sizeFront > 0) { if (sizePsData > 0 && sizeFront > 0) {
append(psBlob, pPsData, sizeFront); append(psBlob, pPsData, sizeFront);
} }
// Write new iptc record if we have it // Write new iptc record if we have it
DataBuf rawIptc = IptcParser::encode(iptcData); DataBuf rawIptc = IptcParser::encode(iptcData);
if (rawIptc.size() > 0) { if (!rawIptc.empty()) {
byte tmpBuf[12]; std::array<byte, 12> tmpBuf;
std::memcpy(tmpBuf, Photoshop::irbId_[0], 4); std::copy_n(Photoshop::irbId_[0], 4, tmpBuf.data());
us2Data(tmpBuf + 4, iptc_, bigEndian); us2Data(tmpBuf.data() + 4, iptc_, bigEndian);
tmpBuf[6] = 0; tmpBuf[6] = 0;
tmpBuf[7] = 0; tmpBuf[7] = 0;
ul2Data(tmpBuf + 8, rawIptc.size(), bigEndian); ul2Data(tmpBuf.data() + 8, static_cast<uint32_t>(rawIptc.size()), bigEndian);
append(psBlob, tmpBuf, 12); append(psBlob, tmpBuf.data(), 12);
append(psBlob, rawIptc.c_data(), rawIptc.size()); append(psBlob, rawIptc.c_data(), rawIptc.size());
// Data is padded to be even (but not included in size) // Data is padded to be even (but not included in size)
if (rawIptc.size() & 1) psBlob.push_back(0x00); if (rawIptc.size() & 1)
psBlob.push_back(0x00);
} }
// Write existing stuff after record, // Write existing stuff after record,
// skip the current and all remaining IPTC blocks // skip the current and all remaining IPTC blocks
long pos = sizeFront; size_t pos = sizeFront;
while (0 == Photoshop::locateIptcIrb(pPsData + pos, sizePsData - pos, while (0 == Photoshop::locateIptcIrb(pPsData + pos, sizePsData - pos, &record, &sizeHdr, &sizeIptc)) {
&record, &sizeHdr, &sizeIptc)) { const auto newPos = static_cast<size_t>(record - pPsData);
const long newPos = static_cast<long>(record - pPsData);
// Copy data up to the IPTC IRB // Copy data up to the IPTC IRB
if (newPos > pos) { if (newPos > pos) {
append(psBlob, pPsData + pos, newPos - pos); append(psBlob, pPsData + pos, newPos - pos);
@ -285,15 +286,16 @@ namespace Exiv2 {
} }
// Data is rounded to be even // Data is rounded to be even
if (!psBlob.empty()) if (!psBlob.empty())
rc = DataBuf(&psBlob[0], static_cast<long>(psBlob.size())); rc = DataBuf(&psBlob[0], psBlob.size());
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "IRB block at the end of Photoshop::setIptcIrb\n"; std::cerr << "IRB block at the end of Photoshop::setIptcIrb\n";
if (rc.size() == 0) std::cerr << " None.\n"; if (rc.empty())
std::cerr << " None.\n";
else hexdump(std::cerr, rc.c_data(), rc.size()); else hexdump(std::cerr, rc.c_data(), rc.size());
#endif #endif
return rc; return rc;
} // Photoshop::setIptcIrb }
bool JpegBase::markerHasLength(byte marker) { bool JpegBase::markerHasLength(byte marker) {
return (marker >= sof0_ && marker <= sof15_) || return (marker >= sof0_ && marker <= sof15_) ||
@ -306,7 +308,7 @@ namespace Exiv2 {
} }
JpegBase::JpegBase(ImageType type, BasicIo::UniquePtr io, bool create, JpegBase::JpegBase(ImageType type, BasicIo::UniquePtr io, bool create,
const byte initData[], long dataSize) const byte initData[], size_t dataSize)
: Image(type, mdExif | mdIptc | mdXmp | mdComment, std::move(io)) : Image(type, mdExif | mdIptc | mdXmp | mdComment, std::move(io))
{ {
if (create) { if (create) {
@ -314,7 +316,7 @@ namespace Exiv2 {
} }
} }
int JpegBase::initImage(const byte initData[], long dataSize) int JpegBase::initImage(const byte initData[], size_t dataSize)
{ {
if (io_->open() != 0) { if (io_->open() != 0) {
return 4; return 4;
@ -369,17 +371,16 @@ namespace Exiv2 {
while (marker != sos_ && marker != eoi_ && search > 0) { while (marker != sos_ && marker != eoi_ && search > 0) {
// 2-byte buffer for reading the size. // 2-byte buffer for reading the size.
byte sizebuf[2]; byte sizebuf[2];
uint16_t size = 0; uint16_t size = 0; // Size of the segment, including the 2-byte size field
if (markerHasLength(marker)) { if (markerHasLength(marker)) {
io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData); io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData);
size = getUShort(sizebuf, bigEndian); size = getUShort(sizebuf, bigEndian);
// `size` is the size of the segment, including the 2-byte size field
// that we just read.
enforce(size >= 2, kerFailedToReadImageData); enforce(size >= 2, kerFailedToReadImageData);
} }
// Read the rest of the segment. // Read the rest of the segment.
DataBuf buf(size); DataBuf buf(size);
/// \todo check if it makes sense to check for size
if (size > 0) { if (size > 0) {
io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData); io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData);
buf.copyBytes(0, sizebuf, 2); buf.copyBytes(0, sizebuf, 2);
@ -424,7 +425,7 @@ namespace Exiv2 {
// Append to psBlob // Append to psBlob
append(psBlob, buf.c_data(16), size - 16); append(psBlob, buf.c_data(16), size - 16);
// Check whether psBlob is complete // Check whether psBlob is complete
if (!psBlob.empty() && Photoshop::valid(&psBlob[0], static_cast<long>(psBlob.size()))) { if (!psBlob.empty() && Photoshop::valid(&psBlob[0], psBlob.size())) {
--search; --search;
foundCompletePsData = true; foundCompletePsData = true;
} }
@ -467,7 +468,7 @@ namespace Exiv2 {
<< std::endl ; << std::endl ;
#endif #endif
// #1286 profile can be padded // #1286 profile can be padded
long icc_size = size-2-14; size_t icc_size = size-2-14;
if (chunk==1 && chunks==1) { if (chunk==1 && chunks==1) {
enforce(s <= static_cast<uint32_t>(icc_size), kerInvalidIccProfile); enforce(s <= static_cast<uint32_t>(icc_size), kerInvalidIccProfile);
icc_size = s; icc_size = s;
@ -509,8 +510,7 @@ namespace Exiv2 {
const byte* pCur = &psBlob[0]; const byte* pCur = &psBlob[0];
const byte* pEnd = pCur + psBlob.size(); const byte* pEnd = pCur + psBlob.size();
while ( pCur < pEnd while ( pCur < pEnd
&& 0 == Photoshop::locateIptcIrb(pCur, static_cast<long>(pEnd - pCur), && 0 == Photoshop::locateIptcIrb(pCur, pEnd - pCur, &record, &sizeHdr, &sizeIptc)) {
&record, &sizeHdr, &sizeIptc)) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n"; std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
#endif #endif
@ -526,7 +526,7 @@ namespace Exiv2 {
#endif #endif
iptcData_.clear(); iptcData_.clear();
} }
} // psBlob.size() > 0 }
if (rc != 0) { if (rc != 0) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -621,8 +621,7 @@ namespace Exiv2 {
assert(markerHasLength(marker)); assert(markerHasLength(marker));
assert(size >= 2); // Because this marker has a length field. assert(size >= 2); // Because this marker has a length field.
// http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf p75 // http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf p75
const std::string signature = const std::string signature = string_from_unterminated(buf.c_str(2), size - 2);
string_from_unterminated(buf.c_str(2), size - 2);
// 728 rmills@rmillsmbp:~/gnu/exiv2/ttt $ exiv2 -pS test/data/exiv2-bug922.jpg // 728 rmills@rmillsmbp:~/gnu/exiv2/ttt $ exiv2 -pS test/data/exiv2-bug922.jpg
// STRUCTURE OF JPEG FILE: test/data/exiv2-bug922.jpg // STRUCTURE OF JPEG FILE: test/data/exiv2-bug922.jpg
@ -848,13 +847,35 @@ namespace Exiv2 {
throw Error(kerDataSourceOpenFailed, io_->path(), strError()); throw Error(kerDataSourceOpenFailed, io_->path(), strError());
} }
IoCloser closer(*io_); IoCloser closer(*io_);
BasicIo::UniquePtr tempIo(new MemIo); auto tempIo = std::make_unique<MemIo>();
assert (tempIo.get() != 0);
doWriteMetadata(*tempIo); // may throw doWriteMetadata(*tempIo); // may throw
io_->close(); io_->close();
io_->transfer(*tempIo); // may throw io_->transfer(*tempIo); // may throw
} // JpegBase::writeMetadata }
DataBuf JpegBase::readNextSegment(byte marker)
{
// 2-byte buffer for reading the size.
byte sizebuf[2];
uint16_t size = 0;
if (markerHasLength(marker)) {
io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData);
size = getUShort(sizebuf, bigEndian);
// `size` is the size of the segment, including the 2-byte size field
// that we just read.
enforce(size >= 2, kerFailedToReadImageData);
}
// Read the rest of the segment.
DataBuf buf(size);
if (size > 0) {
assert(size >= 2); // enforced above
io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData);
buf.copyBytes(0, sizebuf, 2);
}
return buf;
}
void JpegBase::doWriteMetadata(BasicIo& outIo) void JpegBase::doWriteMetadata(BasicIo& outIo)
{ {
@ -900,47 +921,28 @@ namespace Exiv2 {
// to insert after it. But if app0 comes after com, app1 and app13 then // to insert after it. But if app0 comes after com, app1 and app13 then
// don't bother. // don't bother.
while (marker != sos_ && marker != eoi_ && search < 6) { while (marker != sos_ && marker != eoi_ && search < 6) {
// 2-byte buffer for reading the size. DataBuf buf = readNextSegment(marker);
byte sizebuf[2];
uint16_t size = 0;
if (markerHasLength(marker)) {
io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData);
size = getUShort(sizebuf, bigEndian);
// `size` is the size of the segment, including the 2-byte size field
// that we just read.
enforce(size >= 2, kerFailedToReadImageData);
}
// Read the rest of the segment.
DataBuf buf(size);
if (size > 0) {
assert(size >= 2); // enforced above
io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData);
buf.copyBytes(0, sizebuf, 2);
}
if (marker == app0_) { if (marker == app0_) {
assert(markerHasLength(marker));
assert(size >= 2); // Because this marker has a length field.
insertPos = count + 1; insertPos = count + 1;
} else if (skipApp1Exif == notfound && } else if (skipApp1Exif == notfound &&
marker == app1_ && marker == app1_ &&
size >= 8 && // prevent out-of-bounds read in memcmp on next line buf.size() >= 8 && // prevent out-of-bounds read in memcmp on next line
buf.cmpBytes(2, exifId_, 6) == 0) { buf.cmpBytes(2, exifId_, 6) == 0) {
skipApp1Exif = count; skipApp1Exif = count;
++search; ++search;
if (size > 8) { if (buf.size() > 8) {
rawExif.alloc(size - 8); rawExif.alloc(buf.size() - 8);
rawExif.copyBytes(0, buf.c_data(8), size - 8); rawExif.copyBytes(0, buf.c_data(8), buf.size() - 8);
} }
} else if (skipApp1Xmp == notfound && } else if (skipApp1Xmp == notfound &&
marker == app1_ && marker == app1_ &&
size >= 31 && // prevent out-of-bounds read in memcmp on next line buf.size() >= 31 && // prevent out-of-bounds read in memcmp on next line
buf.cmpBytes(2, xmpId_, 29) == 0) { buf.cmpBytes(2, xmpId_, 29) == 0) {
skipApp1Xmp = count; skipApp1Xmp = count;
++search; ++search;
} else if (marker == app2_ && } else if (marker == app2_ &&
size >= 13 && // prevent out-of-bounds read in memcmp on next line buf.size() >= 13 && // prevent out-of-bounds read in memcmp on next line
buf.cmpBytes(2, iccId_, 11) == 0) { buf.cmpBytes(2, iccId_, 11) == 0) {
skipApp2Icc.push_back(count); skipApp2Icc.push_back(count);
if (!foundIccData) { if (!foundIccData) {
@ -949,21 +951,19 @@ namespace Exiv2 {
} }
} else if (!foundCompletePsData && } else if (!foundCompletePsData &&
marker == app13_ && marker == app13_ &&
size >= 16 && // prevent out-of-bounds read in memcmp on next line buf.size() >= 16 && // prevent out-of-bounds read in memcmp on next line
buf.cmpBytes(2, Photoshop::ps3Id_, 14) == 0) { buf.cmpBytes(2, Photoshop::ps3Id_, 14) == 0) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Found APP13 Photoshop PS3 segment\n"; std::cerr << "Found APP13 Photoshop PS3 segment\n";
#endif #endif
skipApp13Ps3.push_back(count); skipApp13Ps3.push_back(count);
// Append to psBlob // Append to psBlob
append(psBlob, buf.c_data(16), size - 16); append(psBlob, buf.c_data(16), buf.size() - 16);
// Check whether psBlob is complete // Check whether psBlob is complete
if (!psBlob.empty() && Photoshop::valid(&psBlob[0], static_cast<long>(psBlob.size()))) { if (!psBlob.empty() && Photoshop::valid(&psBlob[0], psBlob.size())) {
foundCompletePsData = true; foundCompletePsData = true;
} }
} else if (marker == com_ && skipCom == notfound) { } else if (marker == com_ && skipCom == notfound) {
assert(markerHasLength(marker));
assert(size >= 2); // Because this marker has a length field.
// Jpegs can have multiple comments, but for now only handle // Jpegs can have multiple comments, but for now only handle
// the first one (most jpegs only have one anyway). // the first one (most jpegs only have one anyway).
skipCom = count; skipCom = count;
@ -1014,24 +1014,7 @@ namespace Exiv2 {
// potential to change segment ordering (which is allowed). // potential to change segment ordering (which is allowed).
// Segments are erased if there is no assigned metadata. // Segments are erased if there is no assigned metadata.
while (marker != sos_ && search > 0) { while (marker != sos_ && search > 0) {
// 2-byte buffer for reading the size. DataBuf buf = readNextSegment(marker);
byte sizebuf[2];
uint16_t size = 0;
if (markerHasLength(marker)) {
io_->readOrThrow(sizebuf, 2, kerFailedToReadImageData);
size = getUShort(sizebuf, bigEndian);
// `size` is the size of the segment, including the 2-byte size field
// that we just read.
enforce(size >= 2, kerFailedToReadImageData);
}
// Read the rest of the segment.
DataBuf buf(size);
if (size > 0) {
assert(size >= 2); // enforced above
io_->readOrThrow(buf.data(2), size - 2, kerFailedToReadImageData);
buf.copyBytes(0, sizebuf, 2);
}
if (insertPos == count) { if (insertPos == count) {
// Write Exif data first so that - if there is no app0 - we // Write Exif data first so that - if there is no app0 - we
@ -1051,20 +1034,20 @@ namespace Exiv2 {
exifSize = blob.size(); exifSize = blob.size();
} }
if (exifSize > 0) { if (exifSize > 0) {
byte tmpBuf[10]; std::array<byte, 10> tmpBuf;
// Write APP1 marker, size of APP1 field, Exif id and Exif data // Write APP1 marker, size of APP1 field, Exif id and Exif data
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = app1_; tmpBuf[1] = app1_;
if (exifSize > 0xffff - 8) if (exifSize > 0xffff - 8)
throw Error(kerTooLargeJpegSegment, "Exif"); throw Error(kerTooLargeJpegSegment, "Exif");
us2Data(tmpBuf + 2, static_cast<uint16_t>(exifSize + 8), bigEndian); us2Data(tmpBuf.data() + 2, static_cast<uint16_t>(exifSize + 8), bigEndian);
std::memcpy(tmpBuf + 4, exifId_, 6); std::memcpy(tmpBuf.data() + 4, exifId_, 6);
if (outIo.write(tmpBuf, 10) != 10) if (outIo.write(tmpBuf.data(), 10) != 10)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
// Write new Exif data buffer // Write new Exif data buffer
if (outIo.write(pExifData, static_cast<long>(exifSize)) != static_cast<long>(exifSize)) if (outIo.write(pExifData, exifSize) != exifSize)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.error()) if (outIo.error())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
@ -1080,21 +1063,21 @@ namespace Exiv2 {
} }
} }
if (!xmpPacket_.empty()) { if (!xmpPacket_.empty()) {
byte tmpBuf[33]; std::array<byte, 33> tmpBuf;
// Write APP1 marker, size of APP1 field, XMP id and XMP packet // Write APP1 marker, size of APP1 field, XMP id and XMP packet
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = app1_; tmpBuf[1] = app1_;
if (xmpPacket_.size() > 0xffff - 31) if (xmpPacket_.size() > 0xffff - 31)
throw Error(kerTooLargeJpegSegment, "XMP"); throw Error(kerTooLargeJpegSegment, "XMP");
us2Data(tmpBuf + 2, static_cast<uint16_t>(xmpPacket_.size() + 31), bigEndian); us2Data(tmpBuf.data() + 2, static_cast<uint16_t>(xmpPacket_.size() + 31), bigEndian);
std::memcpy(tmpBuf + 4, xmpId_, 29); std::memcpy(tmpBuf.data() + 4, xmpId_, 29);
if (outIo.write(tmpBuf, 33) != 33) if (outIo.write(tmpBuf.data(), 33) != 33)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
// Write new XMP packet // Write new XMP packet
if (outIo.write(reinterpret_cast<const byte*>(xmpPacket_.data()), if (outIo.write(reinterpret_cast<const byte*>(xmpPacket_.data()),
static_cast<long>(xmpPacket_.size())) != static_cast<long>(xmpPacket_.size())) xmpPacket_.size()) != xmpPacket_.size())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.error()) if (outIo.error())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
@ -1102,29 +1085,29 @@ namespace Exiv2 {
} }
if (iccProfileDefined()) { if (iccProfileDefined()) {
byte tmpBuf[4]; std::array<byte, 4> tmpBuf;
// Write APP2 marker, size of APP2 field, and IccProfile // Write APP2 marker, size of APP2 field, and IccProfile
// See comments in readMetadata() about the ICC embedding specification // See comments in readMetadata() about the ICC embedding specification
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = app2_; tmpBuf[1] = app2_;
const long chunk_size = 256 * 256 - 40; // leave bytes for marker, header and padding const long chunk_size = 256 * 256 - 40; // leave bytes for marker, header and padding
long size = iccProfile_.size(); size_t size = iccProfile_.size();
assert(size > 0); // Because iccProfileDefined() == true assert(size > 0); // Because iccProfileDefined() == true
if (size >= 255 * chunk_size) if (size >= 255 * chunk_size)
throw Error(kerTooLargeJpegSegment, "IccProfile"); throw Error(kerTooLargeJpegSegment, "IccProfile");
const long chunks = 1 + (size - 1) / chunk_size; const size_t chunks = 1 + (size - 1) / chunk_size;
assert(chunks <= 255); // Because size < 255 * chunk_size assert(chunks <= 255); // Because size < 255 * chunk_size
for (long chunk = 0; chunk < chunks; chunk++) { for (size_t chunk = 0; chunk < chunks; chunk++) {
long bytes = size > chunk_size ? chunk_size : size; // bytes to write size_t bytes = size > chunk_size ? chunk_size : size; // bytes to write
size -= bytes; size -= bytes;
// write JPEG marker (2 bytes) // write JPEG marker (2 bytes)
if (outIo.write(tmpBuf, 2) != 2) if (outIo.write(tmpBuf.data(), 2) != 2)
throw Error(kerImageWriteFailed); // JPEG Marker throw Error(kerImageWriteFailed); // JPEG Marker
// write length (2 bytes). length includes the 2 bytes for the length // write length (2 bytes). length includes the 2 bytes for the length
us2Data(tmpBuf + 2, static_cast<uint16_t>(2 + 14 + bytes), bigEndian); us2Data(tmpBuf.data() + 2, static_cast<uint16_t>(2 + 14 + bytes), bigEndian);
if (outIo.write(tmpBuf + 2, 2) != 2) if (outIo.write(tmpBuf.data() + 2, 2) != 2)
throw Error(kerImageWriteFailed); // JPEG Length throw Error(kerImageWriteFailed); // JPEG Length
// write the ICC_PROFILE header (14 bytes) // write the ICC_PROFILE header (14 bytes)
@ -1144,14 +1127,14 @@ namespace Exiv2 {
if (foundCompletePsData || iptcData_.count() > 0) { if (foundCompletePsData || iptcData_.count() > 0) {
// Set the new IPTC IRB, keeps existing IRBs but removes the // Set the new IPTC IRB, keeps existing IRBs but removes the
// IPTC block if there is no new IPTC data to write // IPTC block if there is no new IPTC data to write
DataBuf newPsData = Photoshop::setIptcIrb(!psBlob.empty() ? &psBlob[0] : nullptr, DataBuf newPsData = Photoshop::setIptcIrb(!psBlob.empty() ? psBlob.data() : nullptr,
static_cast<long>(psBlob.size()), iptcData_); psBlob.size(), iptcData_);
const long maxChunkSize = 0xffff - 16; const long maxChunkSize = 0xffff - 16;
const byte* chunkStart = newPsData.c_data(); const byte* chunkStart = newPsData.c_data();
const byte* chunkEnd = newPsData.c_data(newPsData.size()); const byte* chunkEnd = newPsData.empty() ? nullptr : newPsData.c_data(newPsData.size()-1);
while (chunkStart < chunkEnd) { while (chunkStart < chunkEnd) {
// Determine size of next chunk // Determine size of next chunk
long chunkSize = static_cast<long>(chunkEnd - chunkStart); size_t chunkSize = (chunkEnd + 1 - chunkStart);
if (chunkSize > maxChunkSize) { if (chunkSize > maxChunkSize) {
chunkSize = maxChunkSize; chunkSize = maxChunkSize;
// Don't break at a valid IRB boundary // Don't break at a valid IRB boundary
@ -1164,12 +1147,12 @@ namespace Exiv2 {
} }
// Write APP13 marker, chunk size, and ps3Id // Write APP13 marker, chunk size, and ps3Id
byte tmpBuf[18]; std::array<byte, 18> tmpBuf;
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = app13_; tmpBuf[1] = app13_;
us2Data(tmpBuf + 2, static_cast<uint16_t>(chunkSize + 16), bigEndian); us2Data(tmpBuf.data() + 2, static_cast<uint16_t>(chunkSize + 16), bigEndian);
std::memcpy(tmpBuf + 4, Photoshop::ps3Id_, 14); std::memcpy(tmpBuf.data() + 4, Photoshop::ps3Id_, 14);
if (outIo.write(tmpBuf, 18) != 18) if (outIo.write(tmpBuf.data(), 18) != 18)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.error()) if (outIo.error())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
@ -1187,19 +1170,19 @@ namespace Exiv2 {
} }
if (comPos == count) { if (comPos == count) {
if (!comment_.empty()) { if (!comment_.empty()) {
byte tmpBuf[4]; std::array<byte, 4> tmpBuf;
// Write COM marker, size of comment, and string // Write COM marker, size of comment, and string
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = com_; tmpBuf[1] = com_;
if (comment_.length() > 0xffff - 3) if (comment_.length() > 0xffff - 3)
throw Error(kerTooLargeJpegSegment, "JPEG comment"); throw Error(kerTooLargeJpegSegment, "JPEG comment");
us2Data(tmpBuf + 2, static_cast<uint16_t>(comment_.length() + 3), bigEndian); us2Data(tmpBuf.data() + 2, static_cast<uint16_t>(comment_.length() + 3), bigEndian);
if (outIo.write(tmpBuf, 4) != 4) if (outIo.write(tmpBuf.data(), 4) != 4)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.write(reinterpret_cast<byte*>(const_cast<char*>(comment_.data())), if (outIo.write(reinterpret_cast<byte*>(const_cast<char*>(comment_.data())),
static_cast<long>(comment_.length())) != static_cast<long>(comment_.length())) comment_.length()) != comment_.length())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.putb(0) == EOF) if (outIo.putb(0) == EOF)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
@ -1217,13 +1200,13 @@ namespace Exiv2 {
std::find(skipApp2Icc.begin(), skipApp2Icc.end(), count) != skipApp2Icc.end() || skipCom == count) { std::find(skipApp2Icc.begin(), skipApp2Icc.end(), count) != skipApp2Icc.end() || skipCom == count) {
--search; --search;
} else { } else {
byte tmpBuf[2]; std::array<byte, 2> tmpBuf;
// Write marker and a copy of the segment. // Write marker and a copy of the segment.
tmpBuf[0] = 0xff; tmpBuf[0] = 0xff;
tmpBuf[1] = marker; tmpBuf[1] = marker;
if (outIo.write(tmpBuf, 2) != 2) if (outIo.write(tmpBuf.data(), 2) != 2)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.write(buf.c_data(), size) != size) if (outIo.write(buf.c_data(), buf.size()) != buf.size())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (outIo.error()) if (outIo.error())
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
@ -1246,7 +1229,7 @@ namespace Exiv2 {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
DataBuf buf(4096); DataBuf buf(4096);
long readSize = 0; size_t readSize = 0;
while ((readSize = io_->read(buf.data(), buf.size()))) { while ((readSize = io_->read(buf.data(), buf.size()))) {
if (outIo.write(buf.c_data(), readSize) != readSize) if (outIo.write(buf.c_data(), readSize) != readSize)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);

@ -241,7 +241,7 @@ namespace Exiv2 {
uint32_t OlympusMnHeader::size() const uint32_t OlympusMnHeader::size() const
{ {
return header_.size(); return static_cast<uint32_t>(header_.size());
} }
uint32_t OlympusMnHeader::ifdOffset() const uint32_t OlympusMnHeader::ifdOffset() const
@ -283,7 +283,7 @@ namespace Exiv2 {
uint32_t Olympus2MnHeader::size() const uint32_t Olympus2MnHeader::size() const
{ {
return header_.size(); return static_cast<uint32_t>(header_.size());
} }
uint32_t Olympus2MnHeader::ifdOffset() const uint32_t Olympus2MnHeader::ifdOffset() const
@ -331,7 +331,7 @@ namespace Exiv2 {
uint32_t FujiMnHeader::size() const uint32_t FujiMnHeader::size() const
{ {
return header_.size(); return static_cast<uint32_t>(header_.size());
} }
uint32_t FujiMnHeader::ifdOffset() const uint32_t FujiMnHeader::ifdOffset() const
@ -470,12 +470,11 @@ namespace Exiv2 {
assert(buf_.size() >= 10); assert(buf_.size() >= 10);
ioWrapper.write(buf_.c_data(), 10); ioWrapper.write(buf_.c_data(), 10);
// Todo: This removes any gap between the header and /// \todo: This removes any gap between the header and makernote IFD. The gap should be copied too.
// makernote IFD. The gap should be copied too.
TiffHeader th(byteOrder); TiffHeader th(byteOrder);
DataBuf buf = th.write(); DataBuf buf = th.write();
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return 10 + buf.size(); return 10 + static_cast<uint32_t>(buf.size());
} // Nikon3MnHeader::write } // Nikon3MnHeader::write
void Nikon3MnHeader::setByteOrder(ByteOrder byteOrder) void Nikon3MnHeader::setByteOrder(ByteOrder byteOrder)
@ -542,7 +541,7 @@ namespace Exiv2 {
uint32_t PentaxDngMnHeader::size() const uint32_t PentaxDngMnHeader::size() const
{ {
return header_.size(); return static_cast<uint32_t>(header_.size());
} }
uint32_t PentaxDngMnHeader::baseOffset(uint32_t mnOffset) const uint32_t PentaxDngMnHeader::baseOffset(uint32_t mnOffset) const
@ -589,7 +588,7 @@ namespace Exiv2 {
uint32_t PentaxMnHeader::size() const uint32_t PentaxMnHeader::size() const
{ {
return header_.size(); return static_cast<uint32_t>(header_.size());
} }
uint32_t PentaxMnHeader::ifdOffset() const uint32_t PentaxMnHeader::ifdOffset() const
@ -1163,7 +1162,7 @@ namespace Exiv2 {
} }
buf.alloc(size); buf.alloc(size);
buf.copyBytes(0, pData, buf.size()); buf.copyBytes(0, pData, buf.size());
ncrypt(buf.data(nci->start_), buf.size() - nci->start_, count, serial); ncrypt(buf.data(nci->start_), static_cast<uint32_t>(buf.size()) - nci->start_, count, serial);
return buf; return buf;
} }

@ -141,7 +141,7 @@ namespace Exiv2 {
iptcData_, iptcData_,
xmpData_, xmpData_,
buf.c_data(), buf.c_data(),
buf.size()); static_cast<uint32_t>(buf.size()));
setByteOrder(bo); setByteOrder(bo);
} // MrwImage::readMetadata } // MrwImage::readMetadata

@ -1400,8 +1400,8 @@ namespace Exiv2 {
} }
char ch; char ch;
int size = value.size(); size_t size = value.size();
for (int i = 0; i < size && ((ch = static_cast<char>(value.toInt64(i))) != '\0'); i++) { for (size_t i = 0; i < size && ((ch = static_cast<char>(value.toInt64(i))) != '\0'); i++) {
os << ch; os << ch;
} }
return os; return os;

@ -183,9 +183,9 @@ namespace Exiv2 {
ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end()); ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end());
} }
std::unique_ptr<TiffHeaderBase> header(new OrfHeader(byteOrder)); OrfHeader header(byteOrder);
return TiffParserWorker::encode(io, pData, size, ed, iptcData, xmpData, Tag::root, TiffMapping::findEncoder, return TiffParserWorker::encode(io, pData, size, ed, iptcData, xmpData, Tag::root, TiffMapping::findEncoder,
header.get(), nullptr); &header, nullptr);
} }
// ************************************************************************* // *************************************************************************

@ -659,19 +659,18 @@ namespace Exiv2 {
{ {
if(value.size()>0 && value.typeId() == undefined) if(value.size()>0 && value.typeId() == undefined)
{ {
for(long i=0; i< value.size(); i++) for(size_t i=0; i< value.size(); i++)
{ {
if(value.toInt64(i)==0) if(value.toInt64(i)==0)
{ {
break; break;
}; }
os << static_cast<char>(value.toInt64(i)); os << static_cast<char>(value.toInt64(i));
}; }
return os; return os;
} }
return os << value; return os << value;
;
} // PanasonicMakerNote::printPanasonicText } // PanasonicMakerNote::printPanasonicText
// Manometer Pressure // Manometer Pressure

@ -134,14 +134,17 @@ namespace Exiv2 {
std::cout << "Exiv2::PgfImage::readMetadata: Found Image data (" << size << " bytes)\n"; std::cout << "Exiv2::PgfImage::readMetadata: Found Image data (" << size << " bytes)\n";
#endif #endif
if (size < 0 || static_cast<size_t>(size) > io_->size()) throw Error(kerInputDataReadFailed); if (size < 0 || static_cast<size_t>(size) > io_->size())
if (size == 0) return; throw Error(kerInputDataReadFailed);
if (size == 0)
return;
DataBuf imgData(size); DataBuf imgData(size);
imgData.clear(); const size_t bufRead = io_->read(imgData.data(), imgData.size());
long bufRead = io_->read(imgData.data(), imgData.size()); if (io_->error())
if (io_->error()) throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
if (bufRead != imgData.size()) throw Error(kerInputDataReadFailed); if (bufRead != imgData.size())
throw Error(kerInputDataReadFailed);
auto image = Exiv2::ImageFactory::open(imgData.c_data(), imgData.size()); auto image = Exiv2::ImageFactory::open(imgData.c_data(), imgData.size());
image->readMetadata(); image->readMetadata();
@ -212,7 +215,7 @@ namespace Exiv2 {
if (outIo.putb(mnb) == EOF) throw Error(kerImageWriteFailed); if (outIo.putb(mnb) == EOF) throw Error(kerImageWriteFailed);
// Write new Header size. // Write new Header size.
uint32_t newHeaderSize = header.size() + imgSize; uint32_t newHeaderSize = static_cast<uint32_t>(header.size()) + imgSize;
DataBuf buffer(4); DataBuf buffer(4);
buffer.copyBytes(0, &newHeaderSize, 4); buffer.copyBytes(0, &newHeaderSize, 4);
byteSwap_(buffer,0,bSwap_); byteSwap_(buffer,0,bSwap_);
@ -228,15 +231,17 @@ namespace Exiv2 {
#endif #endif
// Write Header data. // Write Header data.
if (outIo.write(header.c_data(), header.size()) != header.size()) throw Error(kerImageWriteFailed); if (outIo.write(header.c_data(), header.size()) != header.size())
throw Error(kerImageWriteFailed);
// Write new metadata byte array. // Write new metadata byte array.
if (outIo.write(imgBuf.c_data(), imgBuf.size()) != imgBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(imgBuf.c_data(), imgBuf.size()) != imgBuf.size())
throw Error(kerImageWriteFailed);
// Copy the rest of PGF image data. // Copy the rest of PGF image data.
DataBuf buf(4096); DataBuf buf(4096);
long readSize = 0; size_t readSize = 0;
while ((readSize=io_->read(buf.data(), buf.size()))) while ((readSize=io_->read(buf.data(), buf.size())))
{ {
if (outIo.write(buf.c_data(), readSize) != readSize) throw Error(kerImageWriteFailed); if (outIo.write(buf.c_data(), readSize) != readSize) throw Error(kerImageWriteFailed);
@ -264,9 +269,11 @@ namespace Exiv2 {
uint32_t PgfImage::readPgfHeaderSize(BasicIo& iIo) const uint32_t PgfImage::readPgfHeaderSize(BasicIo& iIo) const
{ {
DataBuf buffer(4); DataBuf buffer(4);
long bufRead = iIo.read(buffer.data(), buffer.size()); const size_t bufRead = iIo.read(buffer.data(), buffer.size());
if (iIo.error()) throw Error(kerFailedToReadImageData); if (iIo.error())
if (bufRead != buffer.size()) throw Error(kerInputDataReadFailed); throw Error(kerFailedToReadImageData);
if (bufRead != buffer.size())
throw Error(kerInputDataReadFailed);
int headerSize = static_cast<int>(byteSwap_(buffer, 0, bSwap_)); int headerSize = static_cast<int>(byteSwap_(buffer, 0, bSwap_));
if (headerSize <= 0 ) throw Error(kerNoImageInInputData); if (headerSize <= 0 ) throw Error(kerNoImageInInputData);
@ -281,9 +288,11 @@ namespace Exiv2 {
DataBuf PgfImage::readPgfHeaderStructure(BasicIo& iIo, uint32_t& width, uint32_t& height) const DataBuf PgfImage::readPgfHeaderStructure(BasicIo& iIo, uint32_t& width, uint32_t& height) const
{ {
DataBuf header(16); DataBuf header(16);
long bufRead = iIo.read(header.data(), header.size()); size_t bufRead = iIo.read(header.data(), header.size());
if (iIo.error()) throw Error(kerFailedToReadImageData); if (iIo.error())
if (bufRead != header.size()) throw Error(kerInputDataReadFailed); throw Error(kerFailedToReadImageData);
if (bufRead != header.size())
throw Error(kerInputDataReadFailed);
DataBuf work(8); // don't disturb the binary data - doWriteMetadata reuses it DataBuf work(8); // don't disturb the binary data - doWriteMetadata reuses it
work.copyBytes(0,header.c_data(),8); work.copyBytes(0,header.c_data(),8);

@ -56,7 +56,7 @@ PNG tags : http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG
*/ */
namespace namespace
{ {
constexpr int nullSeparators = 2; constexpr size_t nullSeparators = 2;
} }
// ***************************************************************************** // *****************************************************************************
@ -101,24 +101,18 @@ namespace Exiv2
DataBuf PngChunk::keyTXTChunk(const DataBuf& data, bool stripHeader) DataBuf PngChunk::keyTXTChunk(const DataBuf& data, bool stripHeader)
{ {
// From a tEXt, zTXt, or iTXt chunk, we get the keyword which is null terminated. // From a tEXt, zTXt, or iTXt chunk, we get the keyword which is null terminated.
const int offset = stripHeader ? 8 : 0; const size_t offset = stripHeader ? 8ul : 0ul;
if (data.size() <= offset) if (data.size() <= offset)
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
// Search for null char until the end of the DataBuf auto it = std::find(data.cbegin() + offset, data.cend(), 0);
const byte* dataPtr = data.c_data(); if (it == data.cend())
int keysize = offset;
while (keysize < data.size() && dataPtr[keysize] != 0) {
keysize++;
}
if (keysize == data.size())
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
return DataBuf(dataPtr + offset, keysize - offset); return DataBuf(data.c_data() + offset, std::distance(data.cbegin(), it)- offset);
} }
DataBuf PngChunk::parseTXTChunk(const DataBuf& data, int keysize, TxtChunkType type) DataBuf PngChunk::parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkType type)
{ {
DataBuf arr; DataBuf arr;
@ -139,22 +133,22 @@ namespace Exiv2
// compressed string after the compression technique spec // compressed string after the compression technique spec
const byte* compressedText = data.c_data(keysize + nullSeparators); const byte* compressedText = data.c_data(keysize + nullSeparators);
long compressedTextSize = data.size() - keysize - nullSeparators; size_t compressedTextSize = data.size() - keysize - nullSeparators;
enforce(compressedTextSize < data.size(), kerCorruptedMetadata); enforce(compressedTextSize < data.size(), kerCorruptedMetadata);
zlibUncompress(compressedText, compressedTextSize, arr); zlibUncompress(compressedText, static_cast<uint32_t>(compressedTextSize), arr);
} else if (type == tEXt_Chunk) { } else if (type == tEXt_Chunk) {
enforce(data.size() >= Safe::add(keysize, 1), Exiv2::kerCorruptedMetadata); enforce(data.size() >= Safe::add(keysize, static_cast<size_t>(1)), Exiv2::kerCorruptedMetadata);
// Extract a non-compressed Latin-1 text chunk // Extract a non-compressed Latin-1 text chunk
// the text comes after the key, but isn't null terminated // the text comes after the key, but isn't null terminated
const byte* text = data.c_data(keysize + 1); const byte* text = data.c_data(keysize + 1);
long textsize = data.size() - keysize - 1; size_t textsize = data.size() - keysize - 1;
arr = DataBuf(text, textsize); arr = DataBuf(text, textsize);
} else if (type == iTXt_Chunk) { } else if (type == iTXt_Chunk) {
enforce(data.size() >= Safe::add(keysize, 3), Exiv2::kerCorruptedMetadata); enforce(data.size() > Safe::add(keysize, static_cast<size_t>(3)), Exiv2::kerCorruptedMetadata);
const size_t nullCount = std::count(data.c_data(keysize + 3), data.c_data(data.size()), '\0'); const size_t nullCount = std::count(data.c_data(keysize + 3), data.c_data(data.size()-1), '\0');
enforce(nullCount >= nullSeparators, Exiv2::kerCorruptedMetadata); enforce(nullCount >= nullSeparators, Exiv2::kerCorruptedMetadata);
// Extract a deflate compressed or uncompressed UTF-8 text chunk // Extract a deflate compressed or uncompressed UTF-8 text chunk
@ -169,21 +163,19 @@ namespace Exiv2
// language description string after the compression technique spec // language description string after the compression technique spec
const size_t languageTextMaxSize = data.size() - keysize - 3; const size_t languageTextMaxSize = data.size() - keysize - 3;
std::string languageText = std::string languageText = string_from_unterminated(data.c_str(keysize+3), languageTextMaxSize);
string_from_unterminated(data.c_str(Safe::add(keysize, 3)), languageTextMaxSize);
const size_t languageTextSize = languageText.size(); const size_t languageTextSize = languageText.size();
enforce(static_cast<unsigned long>(data.size()) >= enforce(data.size() >= Safe::add(Safe::add(keysize, static_cast<size_t>(4)), languageTextSize),
Safe::add(static_cast<size_t>(Safe::add(keysize, 4)), languageTextSize), Exiv2::kerCorruptedMetadata);
Exiv2::kerCorruptedMetadata);
// translated keyword string after the language description // translated keyword string after the language description
std::string translatedKeyText = string_from_unterminated( std::string translatedKeyText = string_from_unterminated(
data.c_str(keysize + 3 + languageTextSize + 1), data.size() - (keysize + 3 + languageTextSize + 1)); data.c_str(keysize + 3 + languageTextSize + 1), data.size() - (keysize + 3 + languageTextSize + 1));
const auto translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size()); const size_t translatedKeyTextSize = translatedKeyText.size();
if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) { if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) {
enforce(Safe::add(static_cast<unsigned int>(keysize + 3 + languageTextSize + 1), enforce(Safe::add(keysize + 3 + languageTextSize + 1,
Safe::add(translatedKeyTextSize, 1U)) <= static_cast<size_t>(data.size()), Safe::add(translatedKeyTextSize, static_cast<size_t>(1))) <= data.size(),
Exiv2::kerCorruptedMetadata); Exiv2::kerCorruptedMetadata);
const byte* text = data.c_data(keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1); const byte* text = data.c_data(keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
@ -195,8 +187,6 @@ namespace Exiv2
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n"; std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n";
#endif #endif
arr.alloc(textsize);
arr = DataBuf(text, textsize); arr = DataBuf(text, textsize);
} else if (compressionFlag == 0x01 && compressionMethod == 0x00) { } else if (compressionFlag == 0x01 && compressionMethod == 0x00) {
// then it's a zlib compressed iTXt chunk // then it's a zlib compressed iTXt chunk
@ -224,7 +214,7 @@ namespace Exiv2
return arr; return arr;
} }
void PngChunk::parseChunkContent(Image* pImage, const byte* key, long keySize, const DataBuf& arr) void PngChunk::parseChunkContent(Image* pImage, const byte* key, size_t keySize, const DataBuf& arr)
{ {
// We look if an ImageMagick EXIF raw profile exist. // We look if an ImageMagick EXIF raw profile exist.
@ -232,16 +222,16 @@ namespace Exiv2
(memcmp("Raw profile type exif", key, 21) == 0 || memcmp("Raw profile type APP1", key, 21) == 0) && (memcmp("Raw profile type exif", key, 21) == 0 || memcmp("Raw profile type APP1", key, 21) == 0) &&
pImage->exifData().empty()) { pImage->exifData().empty()) {
DataBuf exifData = readRawProfile(arr, false); DataBuf exifData = readRawProfile(arr, false);
long length = exifData.size(); size_t length = exifData.size();
if (length > 0) { if (length >= 6) { // length should have at least the size of exifHeader
// Find the position of Exif header in bytes array. // Find the position of Exif header in bytes array.
const std::array<byte,6> exifHeader {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
size_t pos = std::numeric_limits<size_t>::max();
const byte exifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; /// \todo Find substring inside an string
long pos = -1; for (size_t i = 0; i < length - exifHeader.size(); i++) {
if (exifData.cmpBytes(i, exifHeader.data(), exifHeader.size()) == 0) {
for (long i = 0; i < length - static_cast<long>(sizeof(exifHeader)); i++) {
if (exifData.cmpBytes(i, exifHeader, sizeof(exifHeader)) == 0) {
pos = i; pos = i;
break; break;
} }
@ -249,14 +239,14 @@ namespace Exiv2
// If found it, store only these data at from this place. // If found it, store only these data at from this place.
if (pos != -1) { if (pos != std::numeric_limits<size_t>::max()) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngChunk::parseChunkContent: Exif header found at position " << pos std::cout << "Exiv2::PngChunk::parseChunkContent: Exif header found at position " << pos
<< "\n"; << "\n";
#endif #endif
pos = pos + sizeof(exifHeader); pos = pos + sizeof(exifHeader);
ByteOrder bo = TiffParser::decode(pImage->exifData(), pImage->iptcData(), pImage->xmpData(), ByteOrder bo = TiffParser::decode(pImage->exifData(), pImage->iptcData(), pImage->xmpData(),
exifData.c_data(pos), length - pos); exifData.c_data(pos), static_cast<uint32_t>(length - pos));
pImage->setByteOrder(bo); pImage->setByteOrder(bo);
} else { } else {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -277,10 +267,9 @@ namespace Exiv2
uint32_t sizeIptc = 0; uint32_t sizeIptc = 0;
uint32_t sizeHdr = 0; uint32_t sizeHdr = 0;
const byte* pEnd = psData.c_data(psData.size()); const byte* pEnd = psData.c_data(psData.size()-1);
const byte* pCur = psData.c_data(); const byte* pCur = psData.c_data();
while (pCur < pEnd && 0 == Photoshop::locateIptcIrb(pCur, static_cast<long>(pEnd - pCur), &record, while (pCur < pEnd && 0 == Photoshop::locateIptcIrb(pCur, pEnd - pCur, &record, &sizeHdr, &sizeIptc)) {
&sizeHdr, &sizeIptc)) {
if (sizeIptc) { if (sizeIptc) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n"; std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
@ -298,7 +287,8 @@ namespace Exiv2
pImage->clearIptcData(); pImage->clearIptcData();
} }
// If there is no IRB, try to decode the complete chunk data // If there is no IRB, try to decode the complete chunk data
if (iptcBlob.empty() && IptcParser::decode(pImage->iptcData(), psData.c_data(), psData.size())) { if (iptcBlob.empty() && IptcParser::decode(pImage->iptcData(), psData.c_data(),
static_cast<uint32_t>(psData.size()))) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode IPTC metadata.\n"; EXV_WARNING << "Failed to decode IPTC metadata.\n";
#endif #endif
@ -311,7 +301,7 @@ namespace Exiv2
if (keySize >= 20 && memcmp("Raw profile type xmp", key, 20) == 0 && pImage->xmpData().empty()) { if (keySize >= 20 && memcmp("Raw profile type xmp", key, 20) == 0 && pImage->xmpData().empty()) {
DataBuf xmpBuf = readRawProfile(arr, false); DataBuf xmpBuf = readRawProfile(arr, false);
long length = xmpBuf.size(); size_t length = xmpBuf.size();
if (length > 0) { if (length > 0) {
std::string& xmpPacket = pImage->xmpPacket(); std::string& xmpPacket = pImage->xmpPacket();
@ -534,15 +524,16 @@ namespace Exiv2
DataBuf PngChunk::readRawProfile(const DataBuf& text, bool iTXt) DataBuf PngChunk::readRawProfile(const DataBuf& text, bool iTXt)
{ {
if (text.size() <= 1) {
return DataBuf();
}
DataBuf info; DataBuf info;
unsigned char unhex[103] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, unsigned char unhex[103] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15}; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
if (text.size() == 0) {
return DataBuf();
}
if (iTXt) { if (iTXt) {
info.alloc(text.size()); info.alloc(text.size());
@ -551,7 +542,7 @@ namespace Exiv2
} }
const char* sp = text.c_str(1); // current byte (space pointer) const char* sp = text.c_str(1); // current byte (space pointer)
const char* eot = text.c_str(text.size()); // end of text const char* eot = text.c_str(text.size()-1); // end of text
if (sp >= eot) { if (sp >= eot) {
return DataBuf(); return DataBuf();
@ -578,15 +569,14 @@ namespace Exiv2
} }
// Parse the length. // Parse the length.
long length = 0; size_t length = 0;
while ('0' <= *sp && *sp <= '9') { while ('0' <= *sp && *sp <= '9') {
// Compute the new length using unsigned long, so that we can // Compute the new length using unsigned long, so that we can check for overflow.
// check for overflow. const size_t newlength = (10 * length) + (*sp - '0');
const unsigned long newlength = (10 * static_cast<unsigned long>(length)) + (*sp - '0'); if (newlength > std::numeric_limits<size_t>::max()) {
if (newlength > static_cast<unsigned long>(std::numeric_limits<long>::max())) {
return DataBuf(); // Integer overflow. return DataBuf(); // Integer overflow.
} }
length = static_cast<long>(newlength); length = newlength;
sp++; sp++;
if (sp == eot) { if (sp == eot) {
return DataBuf(); return DataBuf();
@ -597,7 +587,7 @@ namespace Exiv2
return DataBuf(); return DataBuf();
} }
enforce(length <= (eot - sp) / 2, Exiv2::kerCorruptedMetadata); enforce(length <= static_cast<size_t>(eot - sp) / 2, Exiv2::kerCorruptedMetadata);
// Allocate space // Allocate space
if (length == 0) { if (length == 0) {
@ -616,9 +606,9 @@ namespace Exiv2
// Copy profile, skipping white space and column 1 "=" signs // Copy profile, skipping white space and column 1 "=" signs
unsigned char* dp = info.data(); // decode pointer unsigned char* dp = info.data(); // decode pointer
unsigned int nibbles = length * 2; size_t nibbles = length * 2;
for (long i = 0; i < static_cast<long>(nibbles); i++) { for (size_t i = 0; i < nibbles; i++) {
enforce(sp < eot, Exiv2::kerCorruptedMetadata); enforce(sp < eot, Exiv2::kerCorruptedMetadata);
while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') { while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') {
if (*sp == '\0') { if (*sp == '\0') {

@ -113,9 +113,7 @@ namespace Exiv2 {
@brief Parse PNG Text chunk to determine type and extract content. @brief Parse PNG Text chunk to determine type and extract content.
Supported Chunk types are tTXt, zTXt, and iTXt. Supported Chunk types are tTXt, zTXt, and iTXt.
*/ */
static DataBuf parseTXTChunk(const DataBuf& data, static DataBuf parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkType type);
int keysize,
TxtChunkType type);
/*! /*!
@brief Parse PNG chunk contents to extract metadata container and assign it to image. @brief Parse PNG chunk contents to extract metadata container and assign it to image.
@ -126,7 +124,7 @@ namespace Exiv2 {
Xmp packet generated by Adobe ==> Image Xmp metadata. Xmp packet generated by Adobe ==> Image Xmp metadata.
Description string ==> Image Comments. Description string ==> Image Comments.
*/ */
static void parseChunkContent(Image* pImage, const byte* key, long keySize, const DataBuf& arr); static void parseChunkContent(Image* pImage, const byte* key, size_t keySize, const DataBuf& arr);
/*! /*!
@brief Return a compressed (zTXt) or uncompressed (tEXt) PNG ASCII text chunk @brief Return a compressed (zTXt) or uncompressed (tEXt) PNG ASCII text chunk
@ -157,9 +155,7 @@ namespace Exiv2 {
/*! /*!
@brief Wrapper around zlib to uncompress a PNG chunk content. @brief Wrapper around zlib to uncompress a PNG chunk content.
*/ */
static void zlibUncompress(const byte* compressedText, static void zlibUncompress(const byte* compressedText, unsigned int compressedTextSize, DataBuf& arr);
unsigned int compressedTextSize,
DataBuf& arr);
/*! /*!
@brief Wrapper around zlib to compress a PNG chunk content. @brief Wrapper around zlib to compress a PNG chunk content.

@ -62,7 +62,7 @@ namespace
inline bool compare(const char* str, const Exiv2::DataBuf& buf, size_t length) inline bool compare(const char* str, const Exiv2::DataBuf& buf, size_t length)
{ {
assert(strlen(str) <= length); assert(strlen(str) <= length);
const long minlen = std::min(static_cast<long>(length), buf.size()); const auto minlen = std::min(length, buf.size());
return buf.cmpBytes(0, str, minlen) == 0; return buf.cmpBytes(0, str, minlen) == 0;
} }
} // namespace } // namespace
@ -108,7 +108,7 @@ namespace Exiv2 {
result.alloc(uncompressedLen); result.alloc(uncompressedLen);
zlibResult = uncompress(result.data(),&uncompressedLen,bytes,length); zlibResult = uncompress(result.data(),&uncompressedLen,bytes,length);
// if result buffer is large than necessary, redo to fit perfectly. // if result buffer is large than necessary, redo to fit perfectly.
if (zlibResult == Z_OK && static_cast<long>(uncompressedLen) < result.size()) { if (zlibResult == Z_OK && uncompressedLen < result.size()) {
result.reset(); result.reset();
result.alloc(uncompressedLen); result.alloc(uncompressedLen);
@ -240,16 +240,17 @@ namespace Exiv2 {
out << " address | chunk | length | data | checksum" << std::endl; out << " address | chunk | length | data | checksum" << std::endl;
} }
const long imgSize = static_cast<long>(io_->size()); const size_t imgSize = io_->size();
DataBuf cheaderBuf(8); DataBuf cheaderBuf(8);
while( !io_->eof() && ::strcmp(chType,"IEND") ) { while( !io_->eof() && ::strcmp(chType,"IEND") ) {
size_t address = io_->tell(); size_t address = io_->tell();
cheaderBuf.clear(); size_t bufRead = io_->read(cheaderBuf.data(), cheaderBuf.size());
long bufRead = io_->read(cheaderBuf.data(), cheaderBuf.size()); if (io_->error())
if (io_->error()) throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
if (bufRead != cheaderBuf.size()) throw Error(kerInputDataReadFailed); if (bufRead != cheaderBuf.size())
throw Error(kerInputDataReadFailed);
// Decode chunk data length. // Decode chunk data length.
const uint32_t dataOffset = cheaderBuf.read_uint32(0, Exiv2::bigEndian); const uint32_t dataOffset = cheaderBuf.read_uint32(0, Exiv2::bigEndian);
@ -261,14 +262,14 @@ namespace Exiv2 {
long restore = io_->tell(); long restore = io_->tell();
if( restore == -1 if( restore == -1
|| dataOffset > uint32_t(0x7FFFFFFF) || dataOffset > uint32_t(0x7FFFFFFF)
|| static_cast<long>(dataOffset) > imgSize - restore || dataOffset > imgSize - restore
){ ){
throw Exiv2::Error(kerFailedToReadImageData); throw Exiv2::Error(kerFailedToReadImageData);
} }
DataBuf buff(dataOffset); DataBuf buff(dataOffset);
bufRead = io_->read(buff.data(),dataOffset); bufRead = io_->read(buff.data(),dataOffset);
enforce(bufRead == static_cast<long>(dataOffset), kerFailedToReadImageData); enforce(bufRead == dataOffset, kerFailedToReadImageData);
io_->seek(restore, BasicIo::beg); io_->seek(restore, BasicIo::beg);
// format output // format output
@ -320,11 +321,11 @@ namespace Exiv2 {
if( bDump ) { if( bDump ) {
DataBuf dataBuf; DataBuf dataBuf;
enforce(static_cast<uint64_t>(dataOffset) < static_cast<unsigned long>(std::numeric_limits<long>::max()), kerFailedToReadImageData); enforce(dataOffset < std::numeric_limits<uint32_t>::max(), kerFailedToReadImageData);
DataBuf data(static_cast<long>(dataOffset) + 1); DataBuf data(dataOffset + 1ul);
data.write_uint8(dataOffset, 0); data.write_uint8(dataOffset, 0);
bufRead = io_->read(data.data(), static_cast<long>(dataOffset)); bufRead = io_->read(data.data(), dataOffset);
enforce(bufRead == static_cast<long>(dataOffset), kerFailedToReadImageData); enforce(bufRead == dataOffset, kerFailedToReadImageData);
io_->seek(restore, BasicIo::beg); io_->seek(restore, BasicIo::beg);
size_t name_l = std::strlen(data.c_str()) + size_t name_l = std::strlen(data.c_str()) +
1; // leading string length 1; // leading string length
@ -336,10 +337,10 @@ namespace Exiv2 {
// decode the chunk // decode the chunk
bool bGood = false; bool bGood = false;
if ( tEXt ) { if ( tEXt ) {
bGood = tEXtToDataBuf(data.c_data(name_l), static_cast<unsigned long>(dataOffset - name_l), dataBuf); bGood = tEXtToDataBuf(data.c_data(name_l), static_cast<long>(dataOffset - name_l), dataBuf);
} }
if ( zTXt || iCCP ) { if ( zTXt || iCCP ) {
bGood = zlibToDataBuf(data.c_data(name_l + 1), static_cast<unsigned long>(dataOffset - name_l - 1), dataBuf); // +1 = 'compressed' flag bGood = zlibToDataBuf(data.c_data(name_l + 1), static_cast<long>(dataOffset - name_l - 1), dataBuf); // +1 = 'compressed' flag
} }
if ( iTXt ) { if ( iTXt ) {
bGood = (3 <= dataOffset) && (start < dataOffset-3); // good if not a nul chunk bGood = (3 <= dataOffset) && (start < dataOffset-3); // good if not a nul chunk
@ -363,7 +364,7 @@ namespace Exiv2 {
if ( parsedBuf.size() ) { if ( parsedBuf.size() ) {
if ( bExif ) { if ( bExif ) {
// create memio object with the data, then print the structure // create memio object with the data, then print the structure
MemIo p(parsedBuf.c_data(6),parsedBuf.size()-6); MemIo p(parsedBuf.c_data(6), parsedBuf.size()-6);
printTiffStructure(p,out,option,depth); printTiffStructure(p,out,option,depth);
} }
if ( bIptc ) { if ( bIptc ) {
@ -401,7 +402,8 @@ namespace Exiv2 {
} }
} }
io_->seek(dataOffset+4, BasicIo::cur);// jump past checksum io_->seek(dataOffset+4, BasicIo::cur);// jump past checksum
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error())
throw Error(kerFailedToReadImageData);
} }
} }
} }
@ -411,7 +413,7 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngImage::readMetadata: Position: " << io.tell() << std::endl; std::cout << "Exiv2::PngImage::readMetadata: Position: " << io.tell() << std::endl;
#endif #endif
long bufRead = io.read(buffer.data(), buffer.size()); const size_t bufRead = io.read(buffer.data(), buffer.size());
if (io.error()) { if (io.error()) {
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
} }
@ -435,12 +437,11 @@ namespace Exiv2 {
} }
clearMetadata(); clearMetadata();
const long imgSize = static_cast<long>(io_->size()); const size_t imgSize = io_->size();
DataBuf cheaderBuf(8); // Chunk header: 4 bytes (data size) + 4 bytes (chunk type). DataBuf cheaderBuf(8); // Chunk header: 4 bytes (data size) + 4 bytes (chunk type).
while(!io_->eof()) while(!io_->eof())
{ {
cheaderBuf.clear();
readChunk(cheaderBuf, *io_); // Read chunk header. readChunk(cheaderBuf, *io_); // Read chunk header.
// Decode chunk data length. // Decode chunk data length.
@ -448,7 +449,7 @@ namespace Exiv2 {
long pos = io_->tell(); long pos = io_->tell();
if (pos == -1 || if (pos == -1 ||
chunkLength > uint32_t(0x7FFFFFFF) || chunkLength > uint32_t(0x7FFFFFFF) ||
static_cast<long>(chunkLength) > imgSize - pos) { chunkLength > imgSize - pos) {
throw Exiv2::Error(kerFailedToReadImageData); throw Exiv2::Error(kerFailedToReadImageData);
} }
@ -484,7 +485,7 @@ namespace Exiv2 {
iptcData(), iptcData(),
xmpData(), xmpData(),
chunkData.c_data(), chunkData.c_data(),
chunkData.size()); static_cast<uint32_t>(chunkData.size()));
setByteOrder(bo); setByteOrder(bo);
} else if (chunkType == "iCCP") { } else if (chunkType == "iCCP") {
// The ICC profile name can vary from 1-79 characters. // The ICC profile name can vary from 1-79 characters.
@ -540,8 +541,10 @@ namespace Exiv2 {
void PngImage::doWriteMetadata(BasicIo& outIo) void PngImage::doWriteMetadata(BasicIo& outIo)
{ {
if (!io_->isopen()) throw Error(kerInputDataReadFailed); if (!io_->isopen())
if (!outIo.isopen()) throw Error(kerImageWriteFailed); throw Error(kerInputDataReadFailed);
if (!outIo.isopen())
throw Error(kerImageWriteFailed);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngImage::doWriteMetadata: Writing PNG file " << io_->path() << "\n"; std::cout << "Exiv2::PngImage::doWriteMetadata: Writing PNG file " << io_->path() << "\n";
@ -553,31 +556,34 @@ namespace Exiv2 {
} }
// Write PNG Signature. // Write PNG Signature.
if (outIo.write(pngSignature, 8) != 8) throw Error(kerImageWriteFailed); if (outIo.write(pngSignature, 8) != 8)
throw Error(kerImageWriteFailed);
DataBuf cheaderBuf(8); // Chunk header : 4 bytes (data size) + 4 bytes (chunk type). DataBuf cheaderBuf(8); // Chunk header : 4 bytes (data size) + 4 bytes (chunk type).
while(!io_->eof()) while(!io_->eof())
{ {
// Read chunk header. // Read chunk header.
size_t bufRead = io_->read(cheaderBuf.data(), 8);
cheaderBuf.clear(); if (io_->error())
long bufRead = io_->read(cheaderBuf.data(), 8); throw Error(kerFailedToReadImageData);
if (io_->error()) throw Error(kerFailedToReadImageData); if (bufRead != 8)
if (bufRead != 8) throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
// Decode chunk data length. // Decode chunk data length.
uint32_t dataOffset = cheaderBuf.read_uint32(0, Exiv2::bigEndian); uint32_t dataOffset = cheaderBuf.read_uint32(0, Exiv2::bigEndian);
if (dataOffset > 0x7FFFFFFF) throw Exiv2::Error(kerFailedToReadImageData); if (dataOffset > 0x7FFFFFFF)
throw Exiv2::Error(kerFailedToReadImageData);
// Read whole chunk : Chunk header + Chunk data (not fixed size - can be null) + CRC (4 bytes). // Read whole chunk : Chunk header + Chunk data (not fixed size - can be null) + CRC (4 bytes).
DataBuf chunkBuf(8 + dataOffset + 4); // Chunk header (8 bytes) + Chunk data + CRC (4 bytes). DataBuf chunkBuf(8 + dataOffset + 4); // Chunk header (8 bytes) + Chunk data + CRC (4 bytes).
chunkBuf.copyBytes(0, cheaderBuf.c_data(), 8); // Copy header. chunkBuf.copyBytes(0, cheaderBuf.c_data(), 8); // Copy header.
bufRead = io_->read(chunkBuf.data(8), dataOffset + 4); // Extract chunk data + CRC bufRead = io_->read(chunkBuf.data(8), dataOffset + 4); // Extract chunk data + CRC
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error())
if (bufRead != static_cast<long>(dataOffset) + 4L) throw Error(kerFailedToReadImageData);
if (bufRead != static_cast<size_t>(dataOffset) + 4)
throw Error(kerInputDataReadFailed); throw Error(kerInputDataReadFailed);
char szChunk[5]; char szChunk[5];
@ -601,15 +607,15 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngImage::doWriteMetadata: Write IHDR chunk (length: " << dataOffset << ")\n"; std::cout << "Exiv2::PngImage::doWriteMetadata: Write IHDR chunk (length: " << dataOffset << ")\n";
#endif #endif
if (outIo.write(chunkBuf.data(), chunkBuf.size()) != chunkBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(chunkBuf.data(), chunkBuf.size()) != chunkBuf.size())
throw Error(kerImageWriteFailed);
// Write all updated metadata here, just after IHDR. // Write all updated metadata here, just after IHDR.
if (!comment_.empty()) if (!comment_.empty())
{ {
// Update Comment data to a new PNG chunk // Update Comment data to a new PNG chunk
std::string chunk = PngChunk::makeMetadataChunk(comment_, mdComment); std::string chunk = PngChunk::makeMetadataChunk(comment_, mdComment);
if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), static_cast<long>(chunk.size())) != if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), chunk.size()) != chunk.size()) {
static_cast<long>(chunk.size())) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
} }
@ -624,8 +630,7 @@ namespace Exiv2 {
std::string rawExif = std::string(exifHeader, 6) + std::string rawExif = std::string(exifHeader, 6) +
std::string(reinterpret_cast<const char*>(&blob[0]), blob.size()); std::string(reinterpret_cast<const char*>(&blob[0]), blob.size());
std::string chunk = PngChunk::makeMetadataChunk(rawExif, mdExif); std::string chunk = PngChunk::makeMetadataChunk(rawExif, mdExif);
if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), static_cast<long>(chunk.size())) != if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), chunk.size()) != chunk.size()) {
static_cast<long>(chunk.size())) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
} }
@ -639,8 +644,7 @@ namespace Exiv2 {
{ {
std::string rawIptc(newPsData.c_str(), newPsData.size()); std::string rawIptc(newPsData.c_str(), newPsData.size());
std::string chunk = PngChunk::makeMetadataChunk(rawIptc, mdIptc); std::string chunk = PngChunk::makeMetadataChunk(rawIptc, mdIptc);
if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), static_cast<long>(chunk.size())) != if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), chunk.size()) != chunk.size()) {
static_cast<long>(chunk.size())) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
} }
@ -648,9 +652,9 @@ namespace Exiv2 {
if ( iccProfileDefined() ) { if ( iccProfileDefined() ) {
DataBuf compressed; DataBuf compressed;
if ( zlibToCompressed(iccProfile_.c_data(),iccProfile_.size(),compressed) ) { if ( zlibToCompressed(iccProfile_.c_data(), static_cast<long>(iccProfile_.size()), compressed) ) {
const auto nameLength = static_cast<uint32_t>(profileName_.size()); const auto nameLength = static_cast<uint32_t>(profileName_.size());
const uint32_t chunkLength = nameLength + 2 + compressed.size() ; const uint32_t chunkLength = nameLength + 2 + static_cast<uint32_t>(compressed.size());
byte length[4]; byte length[4];
ul2Data (length,chunkLength,bigEndian); ul2Data (length,chunkLength,bigEndian);
@ -659,7 +663,7 @@ namespace Exiv2 {
tmp = crc32(tmp, typeICCP, 4); tmp = crc32(tmp, typeICCP, 4);
tmp = crc32(tmp, (const Bytef*)profileName_.data(), nameLength); tmp = crc32(tmp, (const Bytef*)profileName_.data(), nameLength);
tmp = crc32(tmp, nullComp, 2); tmp = crc32(tmp, nullComp, 2);
tmp = crc32(tmp, compressed.c_data(), compressed.size()); tmp = crc32(tmp, compressed.c_data(), static_cast<uint32_t>(compressed.size()));
byte crc[4]; byte crc[4];
ul2Data(crc, tmp, bigEndian); ul2Data(crc, tmp, bigEndian);
@ -689,22 +693,23 @@ namespace Exiv2 {
if (!xmpPacket_.empty()) { if (!xmpPacket_.empty()) {
// Update XMP data to a new PNG chunk // Update XMP data to a new PNG chunk
std::string chunk = PngChunk::makeMetadataChunk(xmpPacket_, mdXmp); std::string chunk = PngChunk::makeMetadataChunk(xmpPacket_, mdXmp);
if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), static_cast<long>(chunk.size())) != if (outIo.write(reinterpret_cast<const byte*>(chunk.data()), chunk.size()) !=
static_cast<long>(chunk.size())) { chunk.size()) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
} }
} else if (!strcmp(szChunk, "tEXt") || !strcmp(szChunk, "zTXt") || !strcmp(szChunk, "iTXt") || } else if (!strcmp(szChunk, "tEXt") || !strcmp(szChunk, "zTXt") || !strcmp(szChunk, "iTXt") ||
!strcmp(szChunk, "iCCP")) { !strcmp(szChunk, "iCCP")) {
DataBuf key = PngChunk::keyTXTChunk(chunkBuf, true); DataBuf key = PngChunk::keyTXTChunk(chunkBuf, true);
if (compare("Raw profile type exif", key, 21) || if (key.empty() == false && (
compare("Raw profile type exif", key, 21) ||
compare("Raw profile type APP1", key, 21) || compare("Raw profile type APP1", key, 21) ||
compare("Raw profile type iptc", key, 21) || compare("Raw profile type iptc", key, 21) ||
compare("Raw profile type xmp", key, 20) || compare("Raw profile type xmp", key, 20) ||
compare("XML:com.adobe.xmp", key, 17) || compare("XML:com.adobe.xmp", key, 17) ||
compare("icc", key, 3) || // see test/data/imagemagick.png compare("icc", key, 3) || // see test/data/imagemagick.png
compare("ICC", key, 3) || compare("ICC", key, 3) ||
compare("Description", key, 11)) compare("Description", key, 11)))
{ {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngImage::doWriteMetadata: strip " << szChunk std::cout << "Exiv2::PngImage::doWriteMetadata: strip " << szChunk
@ -725,7 +730,8 @@ namespace Exiv2 {
std::cout << "Exiv2::PngImage::doWriteMetadata: copy " << szChunk std::cout << "Exiv2::PngImage::doWriteMetadata: copy " << szChunk
<< " chunk (length: " << dataOffset << ")" << std::endl; << " chunk (length: " << dataOffset << ")" << std::endl;
#endif #endif
if (outIo.write(chunkBuf.c_data(), chunkBuf.size()) != chunkBuf.size()) throw Error(kerImageWriteFailed); if (outIo.write(chunkBuf.c_data(), chunkBuf.size()) != chunkBuf.size())
throw Error(kerImageWriteFailed);
} }
} }

@ -140,7 +140,7 @@ namespace {
uint32_t height_; uint32_t height_;
//! Preview image size in bytes //! Preview image size in bytes
uint32_t size_; size_t size_;
//! True if the source image contains a preview image of given type //! True if the source image contains a preview image of given type
bool valid_; bool valid_;
@ -197,7 +197,7 @@ namespace {
static const Param param_[]; static const Param param_[];
//! Offset value //! Offset value
uint32_t offset_; size_t offset_;
}; };
//! Function to create new LoaderExifJpeg //! Function to create new LoaderExifJpeg
@ -424,7 +424,7 @@ namespace {
if (nativePreview_.filter_.empty()) { if (nativePreview_.filter_.empty()) {
size_ = nativePreview_.size_; size_ = nativePreview_.size_;
} else { } else {
size_ = getData().size(); size_ = static_cast<uint32_t>(getData().size());
} }
} }
@ -496,11 +496,15 @@ namespace {
bool LoaderNative::readDimensions() bool LoaderNative::readDimensions()
{ {
if (!valid()) return false; if (!valid())
if (width_ != 0 || height_ != 0) return true; return false;
if (width_ != 0 || height_ != 0)
return true;
const DataBuf data = getData(); const DataBuf data = getData();
if (data.size() == 0) return false; if (data.empty())
return false;
try { try {
auto image = ImageFactory::open(data.c_data(), data.size()); auto image = ImageFactory::open(data.c_data(), data.size());
if (!image) if (!image)
@ -618,7 +622,8 @@ namespace {
size_ = pos->size(); // direct data size_ = pos->size(); // direct data
} }
if (size_ == 0) return; if (size_ == 0)
return;
valid_ = true; valid_ = true;
} }
@ -644,7 +649,7 @@ namespace {
if (pos != image_.exifData().end()) { if (pos != image_.exifData().end()) {
DataBuf buf = pos->dataArea(); // indirect data DataBuf buf = pos->dataArea(); // indirect data
if (buf.size() == 0) { // direct data if (buf.empty()) { // direct data
buf = DataBuf(pos->size()); buf = DataBuf(pos->size());
pos->copy(buf.data(), invalidByteOrder); pos->copy(buf.data(), invalidByteOrder);
} }
@ -658,10 +663,12 @@ namespace {
bool LoaderExifDataJpeg::readDimensions() bool LoaderExifDataJpeg::readDimensions()
{ {
if (!valid()) return false; if (!valid())
return false;
DataBuf buf = getData(); DataBuf buf = getData();
if (buf.size() == 0) return false; if (buf.empty())
return false;
try { try {
auto image = ImageFactory::open(buf.c_data(), buf.size()); auto image = ImageFactory::open(buf.c_data(), buf.size());
@ -685,14 +692,16 @@ namespace {
{ {
const ExifData &exifData = image_.exifData(); const ExifData &exifData = image_.exifData();
int offsetCount = 0; size_t offsetCount = 0;
ExifData::const_iterator pos; ExifData::const_iterator pos;
// check if the group_ contains a preview image // check if the group_ contains a preview image
if (param_[parIdx].checkTag_) { if (param_[parIdx].checkTag_) {
pos = exifData.findKey(ExifKey(param_[parIdx].checkTag_)); pos = exifData.findKey(ExifKey(param_[parIdx].checkTag_));
if (pos == exifData.end()) return; if (pos == exifData.end())
if (param_[parIdx].checkValue_ && pos->toString() != param_[parIdx].checkValue_) return; return;
if (param_[parIdx].checkValue_ && pos->toString() != param_[parIdx].checkValue_)
return;
} }
pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".StripOffsets")); pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".StripOffsets"));
@ -703,20 +712,24 @@ namespace {
} }
else { else {
pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".TileOffsets")); pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".TileOffsets"));
if (pos == exifData.end()) return; if (pos == exifData.end())
return;
offsetTag_ = "TileOffsets"; offsetTag_ = "TileOffsets";
sizeTag_ = "TileByteCounts"; sizeTag_ = "TileByteCounts";
offsetCount = pos->value().count(); offsetCount = pos->value().count();
} }
pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + '.' + sizeTag_)); pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + '.' + sizeTag_));
if (pos == exifData.end()) return; if (pos == exifData.end())
if (offsetCount != pos->value().count()) return; return;
for (int i = 0; i < offsetCount; i++) { if (offsetCount != pos->value().count())
size_ += pos->toUint32(i); return;
for (size_t i = 0; i < offsetCount; i++) {
size_ += pos->toUint32(static_cast<long>(i));
} }
if (size_ == 0) return; if (size_ == 0)
return;
pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".ImageWidth")); pos = exifData.findKey(ExifKey(std::string("Exif.") + group_ + ".ImageWidth"));
if (pos != exifData.end() && pos->count() > 0) { if (pos != exifData.end() && pos->count() > 0) {
@ -728,7 +741,8 @@ namespace {
height_ = pos->toUint32(); height_ = pos->toUint32();
} }
if (width_ == 0 || height_ == 0) return; if (width_ == 0 || height_ == 0)
return;
valid_ = true; valid_ = true;
} }
@ -797,7 +811,7 @@ namespace {
enforce(size_ <= static_cast<uint32_t>(io.size()), kerCorruptedMetadata); enforce(size_ <= static_cast<uint32_t>(io.size()), kerCorruptedMetadata);
DataBuf buf(size_); DataBuf buf(size_);
uint32_t idxBuf = 0; uint32_t idxBuf = 0;
for (long i = 0; i < sizes.count(); i++) { for (size_t i = 0; i < sizes.count(); i++) {
uint32_t offset = dataValue.toUint32(i); uint32_t offset = dataValue.toUint32(i);
uint32_t size = sizes.toUint32(i); uint32_t size = sizes.toUint32(i);
@ -843,15 +857,20 @@ namespace {
} }
auto imageDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":image")); auto imageDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":image"));
if (imageDatum == xmpData.end()) return; if (imageDatum == xmpData.end())
return;
auto formatDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":format")); auto formatDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":format"));
if (formatDatum == xmpData.end()) return; if (formatDatum == xmpData.end())
return;
auto widthDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":width")); auto widthDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":width"));
if (widthDatum == xmpData.end()) return; if (widthDatum == xmpData.end())
return;
auto heightDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":height")); auto heightDatum = xmpData.findKey(XmpKey("Xmp.xmp.Thumbnails[1]/" + prefix + ":height"));
if (heightDatum == xmpData.end()) return; if (heightDatum == xmpData.end())
return;
if (formatDatum->toString() != "JPEG") return; if (formatDatum->toString() != "JPEG")
return;
width_ = widthDatum->toUint32(); width_ = widthDatum->toUint32();
height_ = heightDatum->toUint32(); height_ = heightDatum->toUint32();
@ -875,7 +894,8 @@ namespace {
DataBuf LoaderXmpJpeg::getData() const DataBuf LoaderXmpJpeg::getData() const
{ {
if (!valid()) return DataBuf(); if (!valid())
return DataBuf();
return DataBuf(preview_.c_data(), preview_.size()); return DataBuf(preview_.c_data(), preview_.size());
} }
@ -937,11 +957,13 @@ namespace {
if (decodeBase64Table[static_cast<unsigned char>(src[srcPos])] != invalid) if (decodeBase64Table[static_cast<unsigned char>(src[srcPos])] != invalid)
validSrcSize++; validSrcSize++;
} }
if (validSrcSize > ULONG_MAX / 3) return DataBuf(); // avoid integer overflow if (validSrcSize > ULONG_MAX / 3)
return DataBuf(); // avoid integer overflow
const unsigned long destSize = (validSrcSize * 3) / 4; const unsigned long destSize = (validSrcSize * 3) / 4;
// allocate dest buffer // allocate dest buffer
if (destSize > LONG_MAX) return DataBuf(); // avoid integer overflow if (destSize > LONG_MAX)
return DataBuf(); // avoid integer overflow
DataBuf dest(static_cast<long>(destSize)); DataBuf dest(static_cast<long>(destSize));
// decode // decode
@ -971,7 +993,7 @@ namespace {
return DataBuf(); return DataBuf();
} }
const byte *imageData = src.c_data(colorTableSize); const byte *imageData = src.c_data(colorTableSize);
const long imageDataSize = src.size() - colorTableSize; const long imageDataSize = static_cast<long>(src.size()) - colorTableSize;
const bool rle = (imageDataSize >= 3 && imageData[0] == 'R' && imageData[1] == 'L' && imageData[2] == 'E'); const bool rle = (imageDataSize >= 3 && imageData[0] == 'R' && imageData[1] == 'L' && imageData[2] == 'E');
std::string dest; std::string dest;
for (long i = rle ? 3 : 0; i < imageDataSize;) { for (long i = rle ? 3 : 0; i < imageDataSize;) {
@ -1005,7 +1027,7 @@ namespace {
DataBuf makePnm(uint32_t width, uint32_t height, const DataBuf &rgb) DataBuf makePnm(uint32_t width, uint32_t height, const DataBuf &rgb)
{ {
const long expectedSize = static_cast<long>(width) * static_cast<long>(height) * 3L; const size_t expectedSize = width * height * 3UL;
if (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() << " bytes.\n"; EXV_WARNING << "Invalid size of preview data. Expected " << expectedSize << " bytes, got " << rgb.size() << " bytes.\n";
@ -1037,13 +1059,14 @@ namespace Exiv2 {
PreviewImage& PreviewImage::operator=(const PreviewImage& rhs) PreviewImage& PreviewImage::operator=(const PreviewImage& rhs)
{ {
if (this == &rhs) return *this; if (this == &rhs)
return *this;
properties_ = rhs.properties_; properties_ = rhs.properties_;
preview_ = DataBuf(rhs.pData(), rhs.size()); preview_ = DataBuf(rhs.pData(), rhs.size());
return *this; return *this;
} }
long PreviewImage::writeFile(const std::string& path) const size_t PreviewImage::writeFile(const std::string& path) const
{ {
std::string name = path + extension(); std::string name = path + extension();
// Todo: Creating a DataBuf here unnecessarily copies the memory // Todo: Creating a DataBuf here unnecessarily copies the memory
@ -1063,7 +1086,7 @@ namespace Exiv2 {
uint32_t PreviewImage::size() const uint32_t PreviewImage::size() const
{ {
return preview_.size(); return static_cast<uint32_t>(preview_.size());
} }
std::string PreviewImage::mimeType() const std::string PreviewImage::mimeType() const
@ -1105,7 +1128,7 @@ namespace Exiv2 {
if (loader && loader->readDimensions()) { if (loader && loader->readDimensions()) {
PreviewProperties props = loader->getProperties(); PreviewProperties props = loader->getProperties();
DataBuf buf = loader->getData(); // #16 getPreviewImage() DataBuf buf = loader->getData(); // #16 getPreviewImage()
props.size_ = buf.size(); // update the size props.size_ = static_cast<uint32_t>(buf.size()); // update the size
list.push_back(props) ; list.push_back(props) ;
} }
} }

@ -4186,19 +4186,20 @@ namespace Exiv2 {
prefix_ = prefix; prefix_ = prefix;
} }
XmpKey::XmpKey(const std::string& key) : p_(new Impl) XmpKey::XmpKey(const std::string& key) : p_(std::make_unique<Impl>())
{ {
p_->decomposeKey(key); p_->decomposeKey(key);
} }
XmpKey::XmpKey(const std::string& prefix, const std::string& property) : p_(new Impl(prefix, property)) XmpKey::XmpKey(const std::string& prefix, const std::string& property)
: p_(std::make_unique<Impl>(prefix, property))
{ {
} }
XmpKey::~XmpKey() = default; XmpKey::~XmpKey() = default;
XmpKey::XmpKey(const XmpKey& rhs) XmpKey::XmpKey(const XmpKey& rhs)
: p_(new Impl(*rhs.p_)) : p_(std::make_unique<Impl>(*rhs.p_))
{ {
} }

@ -146,7 +146,8 @@ namespace Exiv2 {
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (!isPsdType(*io_, false)) if (!isPsdType(*io_, false))
{ {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "Photoshop"); throw Error(kerNotAnImage, "Photoshop");
} }
clearMetadata(); clearMetadata();
@ -248,8 +249,9 @@ namespace Exiv2 {
{ {
DataBuf rawIPTC(resourceSize); DataBuf rawIPTC(resourceSize);
io_->read(rawIPTC.data(), rawIPTC.size()); io_->read(rawIPTC.data(), rawIPTC.size());
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
if (IptcParser::decode(iptcData_, rawIPTC.c_data(), rawIPTC.size())) { throw Error(kerFailedToReadImageData);
if (IptcParser::decode(iptcData_, rawIPTC.c_data(), static_cast<uint32_t>(rawIPTC.size()))) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode IPTC metadata.\n"; EXV_WARNING << "Failed to decode IPTC metadata.\n";
#endif #endif
@ -262,7 +264,8 @@ namespace Exiv2 {
{ {
DataBuf rawExif(resourceSize); DataBuf rawExif(resourceSize);
io_->read(rawExif.data(), rawExif.size()); io_->read(rawExif.data(), rawExif.size());
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
ByteOrder bo = ExifParser::decode(exifData_, rawExif.c_data(), rawExif.size()); ByteOrder bo = ExifParser::decode(exifData_, rawExif.c_data(), rawExif.size());
setByteOrder(bo); setByteOrder(bo);
if (rawExif.size() > 0 && byteOrder() == invalidByteOrder) { if (rawExif.size() > 0 && byteOrder() == invalidByteOrder) {
@ -278,7 +281,8 @@ namespace Exiv2 {
{ {
DataBuf xmpPacket(resourceSize); DataBuf xmpPacket(resourceSize);
io_->read(xmpPacket.data(), xmpPacket.size()); io_->read(xmpPacket.data(), xmpPacket.size());
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
xmpPacket_.assign(xmpPacket.c_str(), xmpPacket.size()); xmpPacket_.assign(xmpPacket.c_str(), xmpPacket.size());
if (!xmpPacket_.empty() && XmpParser::decode(xmpData_, xmpPacket_)) { if (!xmpPacket_.empty() && XmpParser::decode(xmpData_, xmpPacket_)) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
@ -323,7 +327,8 @@ namespace Exiv2 {
if (nativePreview.size_ > 0 && nativePreview.position_ >= 0) { if (nativePreview.size_ > 0 && nativePreview.position_ >= 0) {
io_->seek(static_cast<long>(nativePreview.size_), BasicIo::cur); io_->seek(static_cast<long>(nativePreview.size_), BasicIo::cur);
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
if (format == 1) { if (format == 1) {
nativePreview.filter_ = ""; nativePreview.filter_ = "";
@ -360,8 +365,10 @@ namespace Exiv2 {
void PsdImage::doWriteMetadata(BasicIo& outIo) void PsdImage::doWriteMetadata(BasicIo& outIo)
{ {
if (!io_->isopen()) throw Error(kerInputDataReadFailed); if (!io_->isopen())
if (!outIo.isopen()) throw Error(kerImageWriteFailed); throw Error(kerInputDataReadFailed);
if (!outIo.isopen())
throw Error(kerImageWriteFailed);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PsdImage::doWriteMetadata: Writing PSD file " << io_->path() << "\n"; std::cout << "Exiv2::PsdImage::doWriteMetadata: Writing PSD file " << io_->path() << "\n";
@ -370,7 +377,8 @@ namespace Exiv2 {
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (!isPsdType(*io_, true)) { if (!isPsdType(*io_, true)) {
if (io_->error() || io_->eof()) throw Error(kerInputDataReadFailed); if (io_->error() || io_->eof())
throw Error(kerInputDataReadFailed);
throw Error(kerNoImageInInputData); throw Error(kerNoImageInInputData);
} }
@ -381,47 +389,54 @@ namespace Exiv2 {
// Get Photoshop header from original file // Get Photoshop header from original file
byte psd_head[26]; byte psd_head[26];
if (io_->read(psd_head, 26) != 26) throw Error(kerNotAnImage, "Photoshop"); if (io_->read(psd_head, 26) != 26)
throw Error(kerNotAnImage, "Photoshop");
// Write Photoshop header data out to new PSD file // Write Photoshop header data out to new PSD file
if (outIo.write(psd_head, 26) != 26) throw Error(kerImageWriteFailed); if (outIo.write(psd_head, 26) != 26)
throw Error(kerImageWriteFailed);
// Read colorDataLength from original PSD // Read colorDataLength from original PSD
if (io_->read(buf, 4) != 4) throw Error(kerNotAnImage, "Photoshop"); if (io_->read(buf, 4) != 4)
throw Error(kerNotAnImage, "Photoshop");
uint32_t colorDataLength = getULong(buf, bigEndian); uint32_t colorDataLength = getULong(buf, bigEndian);
// Write colorDataLength // Write colorDataLength
ul2Data(buf, colorDataLength, bigEndian); ul2Data(buf, colorDataLength, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (outIo.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << std::dec << "colorDataLength: " << colorDataLength << "\n"; std::cerr << std::dec << "colorDataLength: " << colorDataLength << "\n";
#endif #endif
// Copy colorData // Copy colorData
uint32_t readTotal = 0; size_t readTotal = 0;
while (readTotal < colorDataLength) { while (readTotal < colorDataLength) {
long toRead = static_cast<long>(colorDataLength - readTotal) < lbuf.size() size_t toRead = (colorDataLength - readTotal) < lbuf.size()
? static_cast<long>(colorDataLength - readTotal) ? static_cast<size_t>(colorDataLength) - readTotal
: lbuf.size(); : lbuf.size();
if (io_->read(lbuf.data(), toRead) != toRead) if (io_->read(lbuf.data(), toRead) != toRead)
throw Error(kerNotAnImage, "Photoshop"); throw Error(kerNotAnImage, "Photoshop");
readTotal += toRead; readTotal += toRead;
if (outIo.write(lbuf.c_data(), toRead) != toRead) if (outIo.write(lbuf.c_data(), toRead) != toRead)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
if (outIo.error()) throw Error(kerImageWriteFailed); if (outIo.error())
throw Error(kerImageWriteFailed);
uint32_t resLenOffset = io_->tell(); // remember for later update uint32_t resLenOffset = io_->tell(); // remember for later update
// Read length of all resource blocks from original PSD // Read length of all resource blocks from original PSD
if (io_->read(buf, 4) != 4) throw Error(kerNotAnImage, "Photoshop"); if (io_->read(buf, 4) != 4)
throw Error(kerNotAnImage, "Photoshop");
uint32_t oldResLength = getULong(buf, bigEndian); uint32_t oldResLength = getULong(buf, bigEndian);
uint32_t newResLength = 0; uint32_t newResLength = 0;
// Write oldResLength (will be updated later) // Write oldResLength (will be updated later)
ul2Data(buf, oldResLength, bigEndian); ul2Data(buf, oldResLength, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (outIo.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << std::dec << "oldResLength: " << oldResLength << "\n"; std::cerr << std::dec << "oldResLength: " << oldResLength << "\n";
@ -435,7 +450,8 @@ namespace Exiv2 {
bool exifDone = false; bool exifDone = false;
bool xmpDone = false; bool xmpDone = false;
while (oldResLength > 0) { while (oldResLength > 0) {
if (io_->read(buf, 8) != 8) throw Error(kerNotAnImage, "Photoshop"); if (io_->read(buf, 8) != 8)
throw Error(kerNotAnImage, "Photoshop");
// read resource type and ID // read resource type and ID
uint32_t resourceType = getULong(buf, bigEndian); uint32_t resourceType = getULong(buf, bigEndian);
@ -451,11 +467,12 @@ namespace Exiv2 {
// read rest of resource name, plus any padding // read rest of resource name, plus any padding
DataBuf resName(256); DataBuf resName(256);
if ( io_->read(resName.data(), adjResourceNameLen) if (io_->read(resName.data(), adjResourceNameLen) != adjResourceNameLen)
!= static_cast<long>(adjResourceNameLen)) throw Error(kerNotAnImage, "Photoshop"); throw Error(kerNotAnImage, "Photoshop");
// read resource size (actual length w/o padding!) // read resource size (actual length w/o padding!)
if (io_->read(buf, 4) != 4) throw Error(kerNotAnImage, "Photoshop"); if (io_->read(buf, 4) != 4)
throw Error(kerNotAnImage, "Photoshop");
uint32_t resourceSize = getULong(buf, bigEndian); uint32_t resourceSize = getULong(buf, bigEndian);
uint32_t pResourceSize = (resourceSize + 1) & ~1; // padded resource size uint32_t pResourceSize = (resourceSize + 1) & ~1; // padded resource size
@ -493,25 +510,30 @@ namespace Exiv2 {
#endif #endif
// Copy resource block to new PSD file // Copy resource block to new PSD file
ul2Data(buf, resourceType, bigEndian); ul2Data(buf, resourceType, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (outIo.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
us2Data(buf, resourceId, bigEndian); us2Data(buf, resourceId, bigEndian);
if (outIo.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (outIo.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
// Write resource name as Pascal string // Write resource name as Pascal string
buf[0] = resourceNameLength & 0x00ff; buf[0] = resourceNameLength & 0x00ff;
if (outIo.write(buf, 1) != 1) throw Error(kerImageWriteFailed); if (outIo.write(buf, 1) != 1)
throw Error(kerImageWriteFailed);
buf[0] = resourceNameFirstChar; buf[0] = resourceNameFirstChar;
if (outIo.write(buf, 1) != 1) throw Error(kerImageWriteFailed); if (outIo.write(buf, 1) != 1)
if ( outIo.write(resName.c_data(), adjResourceNameLen) throw Error(kerImageWriteFailed);
!= static_cast<long>(adjResourceNameLen)) throw Error(kerImageWriteFailed); if (outIo.write(resName.c_data(), adjResourceNameLen) != static_cast<size_t>(adjResourceNameLen))
throw Error(kerImageWriteFailed);
ul2Data(buf, resourceSize, bigEndian); ul2Data(buf, resourceSize, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (outIo.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
readTotal = 0; readTotal = 0;
while (readTotal < pResourceSize) { while (readTotal < pResourceSize) {
/// \todo almost same code as in lines 403-410. Factor out & reuse! /// \todo almost same code as in lines 403-410. Factor out & reuse!
long toRead = static_cast<long>(pResourceSize - readTotal) < lbuf.size() size_t toRead = (pResourceSize - readTotal) < lbuf.size()
? static_cast<long>(pResourceSize - readTotal) ? static_cast<long>(pResourceSize - readTotal)
: lbuf.size(); : static_cast<long>(lbuf.size());
if (io_->read(lbuf.data(), toRead) != toRead) { if (io_->read(lbuf.data(), toRead) != toRead) {
throw Error(kerNotAnImage, "Photoshop"); throw Error(kerNotAnImage, "Photoshop");
} }
@ -519,7 +541,8 @@ namespace Exiv2 {
if (outIo.write(lbuf.c_data(), toRead) != toRead) if (outIo.write(lbuf.c_data(), toRead) != toRead)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
if (outIo.error()) throw Error(kerImageWriteFailed); if (outIo.error())
throw Error(kerImageWriteFailed);
newResLength += pResourceSize + adjResourceNameLen + 12; newResLength += pResourceSize + adjResourceNameLen + 12;
} }
@ -548,11 +571,13 @@ namespace Exiv2 {
io_->populateFakeData(); io_->populateFakeData();
// Copy remaining data // Copy remaining data
long readSize = 0; size_t readSize = 0;
while ((readSize=io_->read(lbuf.data(), lbuf.size()))) { while ((readSize=io_->read(lbuf.data(), lbuf.size()))) {
if (outIo.write(lbuf.c_data(), readSize) != readSize) throw Error(kerImageWriteFailed); if (outIo.write(lbuf.c_data(), readSize) != readSize)
throw Error(kerImageWriteFailed);
} }
if (outIo.error()) throw Error(kerImageWriteFailed); if (outIo.error())
throw Error(kerImageWriteFailed);
// Update length of resources // Update length of resources
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
@ -560,7 +585,8 @@ namespace Exiv2 {
#endif #endif
outIo.seek(resLenOffset, BasicIo::beg); outIo.seek(resLenOffset, BasicIo::beg);
ul2Data(buf, newResLength, bigEndian); ul2Data(buf, newResLength, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (outIo.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
} // PsdImage::doWriteMetadata } // PsdImage::doWriteMetadata
@ -576,20 +602,26 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_IPTC_NAA << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_IPTC_NAA << "\n";
std::cerr << std::dec << "Writing IPTC_NAA: size: " << rawIptc.size() << "\n"; std::cerr << std::dec << "Writing IPTC_NAA: size: " << rawIptc.size() << "\n";
#endif #endif
if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(kerImageWriteFailed); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4)
throw Error(kerImageWriteFailed);
us2Data(buf, kPhotoshopResourceID_IPTC_NAA, bigEndian); us2Data(buf, kPhotoshopResourceID_IPTC_NAA, bigEndian);
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
ul2Data(buf, rawIptc.size(), bigEndian); throw Error(kerImageWriteFailed);
if (out.write(buf, 4) != 4) throw Error(kerImageWriteFailed); ul2Data(buf, static_cast<uint32_t>(rawIptc.size()), bigEndian);
if (out.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
// Write encoded Iptc data // Write encoded Iptc data
if (out.write(rawIptc.c_data(), rawIptc.size()) != rawIptc.size()) throw Error(kerImageWriteFailed); if (out.write(rawIptc.c_data(), rawIptc.size()) != rawIptc.size())
resLength += rawIptc.size() + 12; throw Error(kerImageWriteFailed);
resLength += static_cast<uint32_t>(rawIptc.size()) + 12;
if (rawIptc.size() & 1) // even padding if (rawIptc.size() & 1) // even padding
{ {
buf[0] = 0; buf[0] = 0;
if (out.write(buf, 1) != 1) throw Error(kerImageWriteFailed); if (out.write(buf, 1) != 1)
throw Error(kerImageWriteFailed);
resLength++; resLength++;
} }
} }
@ -616,20 +648,26 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_ExifInfo << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_ExifInfo << "\n";
std::cerr << std::dec << "Writing ExifInfo: size: " << blob.size() << "\n"; std::cerr << std::dec << "Writing ExifInfo: size: " << blob.size() << "\n";
#endif #endif
if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(kerImageWriteFailed); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4)
throw Error(kerImageWriteFailed);
us2Data(buf, kPhotoshopResourceID_ExifInfo, bigEndian); us2Data(buf, kPhotoshopResourceID_ExifInfo, bigEndian);
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
ul2Data(buf, static_cast<uint32_t>(blob.size()), bigEndian); ul2Data(buf, static_cast<uint32_t>(blob.size()), bigEndian);
if (out.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (out.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
// Write encoded Exif data // Write encoded Exif data
if (out.write(&blob[0], static_cast<long>(blob.size())) != static_cast<long>(blob.size())) throw Error(kerImageWriteFailed); if (out.write(&blob[0], blob.size()) != blob.size())
throw Error(kerImageWriteFailed);
resLength += static_cast<long>(blob.size()) + 12; resLength += static_cast<long>(blob.size()) + 12;
if (blob.size() & 1) // even padding if (blob.size() & 1) // even padding
{ {
buf[0] = 0; buf[0] = 0;
if (out.write(buf, 1) != 1) throw Error(kerImageWriteFailed); if (out.write(buf, 1) != 1)
throw Error(kerImageWriteFailed);
resLength++; resLength++;
} }
} }
@ -660,22 +698,28 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_XMPPacket << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_XMPPacket << "\n";
std::cerr << std::dec << "Writing XMPPacket: size: " << xmpPacket.size() << "\n"; std::cerr << std::dec << "Writing XMPPacket: size: " << xmpPacket.size() << "\n";
#endif #endif
if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(kerImageWriteFailed); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4)
throw Error(kerImageWriteFailed);
us2Data(buf, kPhotoshopResourceID_XMPPacket, bigEndian); us2Data(buf, kPhotoshopResourceID_XMPPacket, bigEndian);
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name
if (out.write(buf, 2) != 2) throw Error(kerImageWriteFailed); if (out.write(buf, 2) != 2)
throw Error(kerImageWriteFailed);
ul2Data(buf, static_cast<uint32_t>(xmpPacket.size()), bigEndian); ul2Data(buf, static_cast<uint32_t>(xmpPacket.size()), bigEndian);
if (out.write(buf, 4) != 4) throw Error(kerImageWriteFailed); if (out.write(buf, 4) != 4)
throw Error(kerImageWriteFailed);
// Write XMPPacket // Write XMPPacket
if (out.write(reinterpret_cast<const byte*>(xmpPacket.data()), static_cast<long>(xmpPacket.size())) if (out.write(reinterpret_cast<const byte*>(xmpPacket.data()), xmpPacket.size()) != xmpPacket.size())
!= static_cast<long>(xmpPacket.size())) throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (out.error()) throw Error(kerImageWriteFailed); if (out.error())
throw Error(kerImageWriteFailed);
resLength += static_cast<uint32_t>(xmpPacket.size()) + 12; resLength += static_cast<uint32_t>(xmpPacket.size()) + 12;
if (xmpPacket.size() & 1) // even padding if (xmpPacket.size() & 1) // even padding
{ {
buf[0] = 0; buf[0] = 0;
if (out.write(buf, 1) != 1) throw Error(kerImageWriteFailed); if (out.write(buf, 1) != 1)
throw Error(kerImageWriteFailed);
resLength++; resLength++;
} }
} }

@ -86,14 +86,15 @@ namespace Exiv2 {
// not supported // not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "RAF")); throw(Error(kerInvalidSettingForImage, "Image comment", "RAF"));
} }
void RafImage::printStructure(std::ostream& out, PrintStructureOption option, int depth) { void RafImage::printStructure(std::ostream& out, PrintStructureOption option, int depth) {
if (io_->open() != 0) { if (io_->open() != 0) {
throw Error(kerDataSourceOpenFailed, io_->path(), strError()); throw Error(kerDataSourceOpenFailed, io_->path(), strError());
} }
// Ensure this is the correct image type // Ensure this is the correct image type
if (!isRafType(*io_, true)) { if (!isRafType(*io_, true)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "RAF"); throw Error(kerNotAnImage, "RAF");
} }
@ -159,7 +160,7 @@ namespace Exiv2 {
address = io_->tell(); address = io_->tell();
DataBuf unknown(20); DataBuf unknown(20);
io_->read(unknown.data(),unknown.size()); io_->read(unknown.data(), unknown.size());
{ {
out << Internal::indent(depth) out << Internal::indent(depth)
<< Internal::stringFormat(format,address, 20) << Internal::stringFormat(format,address, 20)
@ -286,21 +287,26 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Reading RAF file " << io_->path() << "\n"; std::cerr << "Reading RAF file " << io_->path() << "\n";
#endif #endif
if (io_->open() != 0) throw Error(kerDataSourceOpenFailed, io_->path(), strError()); if (io_->open() != 0)
throw Error(kerDataSourceOpenFailed, io_->path(), strError());
IoCloser closer(*io_); IoCloser closer(*io_);
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (!isRafType(*io_, false)) { if (!isRafType(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "RAF"); throw Error(kerNotAnImage, "RAF");
} }
clearMetadata(); clearMetadata();
if (io_->seek(84,BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); if (io_->seek(84,BasicIo::beg) != 0)
throw Error(kerFailedToReadImageData);
byte jpg_img_offset [4]; byte jpg_img_offset [4];
if (io_->read(jpg_img_offset, 4) != 4) throw Error(kerFailedToReadImageData); if (io_->read(jpg_img_offset, 4) != 4)
throw Error(kerFailedToReadImageData);
byte jpg_img_length [4]; byte jpg_img_length [4];
if (io_->read(jpg_img_length, 4) != 4) throw Error(kerFailedToReadImageData); if (io_->read(jpg_img_length, 4) != 4)
throw Error(kerFailedToReadImageData);
uint32_t jpg_img_off_u32 = Exiv2::getULong(jpg_img_offset, bigEndian); uint32_t jpg_img_off_u32 = Exiv2::getULong(jpg_img_offset, bigEndian);
uint32_t jpg_img_len_u32 = Exiv2::getULong(jpg_img_length, bigEndian); uint32_t jpg_img_len_u32 = Exiv2::getULong(jpg_img_length, bigEndian);
@ -319,9 +325,12 @@ namespace Exiv2 {
enforce(jpg_img_len >= 12, kerCorruptedMetadata); enforce(jpg_img_len >= 12, kerCorruptedMetadata);
DataBuf buf(jpg_img_len - 12); DataBuf buf(jpg_img_len - 12);
if (io_->seek(jpg_img_off + 12,BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); if (io_->seek(jpg_img_off + 12,BasicIo::beg) != 0)
throw Error(kerFailedToReadImageData);
io_->read(buf.data(), buf.size()); io_->read(buf.data(), buf.size());
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
io_->seek(0,BasicIo::beg); // rewind io_->seek(0,BasicIo::beg); // rewind
@ -329,7 +338,7 @@ namespace Exiv2 {
iptcData_, iptcData_,
xmpData_, xmpData_,
buf.c_data(), buf.c_data(),
buf.size()); static_cast<uint32_t>(buf.size()));
exifData_["Exif.Image2.JPEGInterchangeFormat"] = getULong(jpg_img_offset, bigEndian); exifData_["Exif.Image2.JPEGInterchangeFormat"] = getULong(jpg_img_offset, bigEndian);
exifData_["Exif.Image2.JPEGInterchangeFormatLength"] = getULong(jpg_img_length, bigEndian); exifData_["Exif.Image2.JPEGInterchangeFormatLength"] = getULong(jpg_img_length, bigEndian);
@ -338,22 +347,27 @@ namespace Exiv2 {
// parse the tiff // parse the tiff
byte readBuff[4]; byte readBuff[4];
if (io_->seek(100, BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); if (io_->seek(100, BasicIo::beg) != 0)
if (io_->read(readBuff, 4) != 4 ) throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
if (io_->read(readBuff, 4) != 4 )
throw Error(kerFailedToReadImageData);
uint32_t tiffOffset = Exiv2::getULong(readBuff, bigEndian); uint32_t tiffOffset = Exiv2::getULong(readBuff, bigEndian);
if (io_->read(readBuff, 4) != 4) throw Error(kerFailedToReadImageData); if (io_->read(readBuff, 4) != 4)
throw Error(kerFailedToReadImageData);
uint32_t tiffLength = Exiv2::getULong(readBuff, bigEndian); uint32_t tiffLength = Exiv2::getULong(readBuff, bigEndian);
// sanity check. Does tiff lie inside the file? // sanity check. Does tiff lie inside the file?
enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), kerCorruptedMetadata); enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), kerCorruptedMetadata);
if (io_->seek(tiffOffset, BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); if (io_->seek(tiffOffset, BasicIo::beg) != 0)
throw Error(kerFailedToReadImageData);
// Check if this really is a tiff and then call the tiff parser. // Check if this really is a tiff and then call the tiff parser.
// Check is needed because some older models just embed a raw bitstream. // Check is needed because some older models just embed a raw bitstream.
// For those files we skip the parsing step. // For those files we skip the parsing step.
if (io_->read(readBuff, 4) != 4) { throw Error(kerFailedToReadImageData); } if (io_->read(readBuff, 4) != 4) {
throw Error(kerFailedToReadImageData); }
io_->seek(-4, BasicIo::cur); io_->seek(-4, BasicIo::cur);
if (memcmp(readBuff, "\x49\x49\x2A\x00", 4) == 0 || if (memcmp(readBuff, "\x49\x49\x2A\x00", 4) == 0 ||
memcmp(readBuff, "\x4D\x4D\x00\x2A", 4) == 0) memcmp(readBuff, "\x4D\x4D\x00\x2A", 4) == 0)
@ -367,7 +381,7 @@ namespace Exiv2 {
iptcData_, iptcData_,
xmpData_, xmpData_,
tiff.c_data(), tiff.c_data(),
tiff.size()); static_cast<uint32_t>(tiff.size()));
} }
} }
} // RafImage::readMetadata } // RafImage::readMetadata

@ -295,7 +295,7 @@ namespace Exiv2 {
} }
ExifKey::ExifKey(uint16_t tag, const std::string& groupName) ExifKey::ExifKey(uint16_t tag, const std::string& groupName)
: p_(new Impl) : p_(std::make_unique<Impl>())
{ {
IfdId ifdId = groupId(groupName); IfdId ifdId = groupId(groupName);
// Todo: Test if this condition can be removed // Todo: Test if this condition can be removed
@ -311,7 +311,7 @@ namespace Exiv2 {
} }
ExifKey::ExifKey(const TagInfo& ti) ExifKey::ExifKey(const TagInfo& ti)
: p_(new Impl) : p_(std::make_unique<Impl>())
{ {
auto ifdId = static_cast<IfdId>(ti.ifdId_); auto ifdId = static_cast<IfdId>(ti.ifdId_);
if (!Internal::isExifIfd(ifdId) && !Internal::isMakerIfd(ifdId)) { if (!Internal::isExifIfd(ifdId) && !Internal::isMakerIfd(ifdId)) {
@ -322,13 +322,13 @@ namespace Exiv2 {
} }
ExifKey::ExifKey(const std::string& key) ExifKey::ExifKey(const std::string& key)
: p_(new Impl) : p_(std::make_unique<Impl>())
{ {
p_->decomposeKey(key); p_->decomposeKey(key);
} }
ExifKey::ExifKey(const ExifKey& rhs) ExifKey::ExifKey(const ExifKey& rhs)
: p_(new Impl(*rhs.p_)) : p_(std::make_unique<Impl>(*rhs.p_))
{ {
} }

@ -2601,7 +2601,7 @@ namespace Exiv2 {
{ {
uint16_t bit = 0; uint16_t bit = 0;
uint16_t comma = 0; uint16_t comma = 0;
for (long i = 0; i < value.count(); i++ ) { // for each element in value array for (size_t i = 0; i < value.count(); i++ ) { // for each element in value array
auto bits = static_cast<uint16_t>(value.toInt64(i)); auto bits = static_cast<uint16_t>(value.toInt64(i));
for (uint16_t b = 0; b < 16; ++b) { // for every bit for (uint16_t b = 0; b < 16; ++b) { // for every bit
if (bits & (1 << b)) { if (bits & (1 << b)) {
@ -2949,7 +2949,7 @@ namespace Exiv2 {
std::ostream& print0x9101(std::ostream& os, const Value& value, const ExifData*) std::ostream& print0x9101(std::ostream& os, const Value& value, const ExifData*)
{ {
for (long i = 0; i < value.count(); ++i) { for (size_t i = 0; i < value.count(); ++i) {
const auto l = value.toInt64(i); const auto l = value.toInt64(i);
switch (l) { switch (l) {
case 0: break; case 0: break;

@ -344,7 +344,7 @@ namespace Exiv2 {
return os; return os;
} }
for (int i=0; i< value.count(); i++) { for (size_t i=0; i< value.count(); i++) {
if (i != 0) if (i != 0)
os << ", "; os << ", ";
const TagVocabulary* td = find(array, value.toString(i)); const TagVocabulary* td = find(array, value.toString(i));

@ -56,14 +56,14 @@ namespace Exiv2 {
&& key.g_ == group_; && key.g_ == group_;
} }
IoWrapper::IoWrapper(BasicIo& io, const byte* pHeader, long size, OffsetWriter* pow) IoWrapper::IoWrapper(BasicIo& io, const byte* pHeader, size_t size, OffsetWriter* pow)
: io_(io), pHeader_(pHeader), size_(size), wroteHeader_(false), pow_(pow) : io_(io), pHeader_(pHeader), size_(size), wroteHeader_(false), pow_(pow)
{ {
if (pHeader_ == nullptr || size_ == 0) if (pHeader_ == nullptr || size_ == 0)
wroteHeader_ = true; wroteHeader_ = true;
} }
long IoWrapper::write(const byte* pData, long wcount) size_t IoWrapper::write(const byte* pData, size_t wcount)
{ {
if (!wroteHeader_ && wcount > 0) { if (!wroteHeader_ && wcount > 0) {
io_.write(pHeader_, size_); io_.write(pHeader_, size_);
@ -319,7 +319,7 @@ namespace Exiv2 {
{ {
storage_ = buf; storage_ = buf;
pData_ = buf->data(); pData_ = buf->data();
size_ = buf->size(); size_ = static_cast<uint32_t>(buf->size());
} }
void TiffEntryBase::setData(byte* pData, uint32_t size, void TiffEntryBase::setData(byte* pData, uint32_t size,
@ -336,7 +336,7 @@ namespace Exiv2 {
{ {
if (value.get() == nullptr) if (value.get() == nullptr)
return; return;
uint32_t newSize = value->size(); size_t newSize = value->size();
if (newSize > size_) { if (newSize > size_) {
setData(std::make_shared<DataBuf>(newSize)); setData(std::make_shared<DataBuf>(newSize));
} }
@ -392,14 +392,14 @@ namespace Exiv2 {
return; return;
} }
uint32_t size = 0; uint32_t size = 0;
for (long i = 0; i < pSize->count(); ++i) { for (size_t i = 0; i < pSize->count(); ++i) {
size += pSize->toUint32(i); size += pSize->toUint32(i);
} }
auto offset = pValue()->toUint32(0); auto offset = pValue()->toUint32(0);
// Todo: Remove limitation of JPEG writer: strips must be contiguous // Todo: Remove limitation of JPEG writer: strips must be contiguous
// Until then we check: last offset + last size - first offset == size? // Until then we check: last offset + last size - first offset == size?
if ( pValue()->toUint32(pValue()->count()-1) if ( pValue()->toUint32(static_cast<long>(pValue()->count())-1)
+ pSize->toUint32(pSize->count()-1) + pSize->toUint32(static_cast<long>(pSize->count())-1)
- offset != size) { - offset != size) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Directory " << groupName(group()) EXV_WARNING << "Directory " << groupName(group())
@ -449,7 +449,7 @@ namespace Exiv2 {
#endif #endif
return; return;
} }
for (long i = 0; i < pValue()->count(); ++i) { for (size_t i = 0; i < pValue()->count(); ++i) {
const auto offset = pValue()->toUint32(i); const auto offset = pValue()->toUint32(i);
const byte* pStrip = pData + baseOffset + offset; const byte* pStrip = pData + baseOffset + offset;
const auto size = pSize->toUint32(i); const auto size = pSize->toUint32(i);
@ -525,7 +525,7 @@ namespace Exiv2 {
uint32_t ArrayDef::size(uint16_t tag, IfdId group) const uint32_t ArrayDef::size(uint16_t tag, IfdId group) const
{ {
TypeId typeId = toTypeId(tiffType_, tag, group); TypeId typeId = toTypeId(tiffType_, tag, group);
return count_ * TypeInfo::typeSize(typeId); return static_cast<uint32_t>(count_ * TypeInfo::typeSize(typeId));
} }
bool TiffBinaryArray::initialize(IfdId group) bool TiffBinaryArray::initialize(IfdId group)
@ -985,7 +985,7 @@ namespace Exiv2 {
uint32_t TiffEntryBase::doCount() const uint32_t TiffEntryBase::doCount() const
{ {
return count_; return static_cast<uint32_t>(count_);
} }
uint32_t TiffMnEntry::doCount() const uint32_t TiffMnEntry::doCount() const
@ -1019,7 +1019,7 @@ namespace Exiv2 {
if (elements_.empty()) return 0; if (elements_.empty()) return 0;
TypeId typeId = toTypeId(tiffType(), tag(), group()); TypeId typeId = toTypeId(tiffType(), tag(), group());
long typeSize = TypeInfo::typeSize(typeId); size_t typeSize = TypeInfo::typeSize(typeId);
if (0 == typeSize) { if (0 == typeSize) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Directory " << groupName(group()) EXV_WARNING << "Directory " << groupName(group())
@ -1097,7 +1097,7 @@ namespace Exiv2 {
} }
// Also add the size of data, but only if needed // Also add the size of data, but only if needed
if (isRootDir) { if (isRootDir) {
uint32_t sd = component->sizeData(); uint32_t sd = static_cast<uint32_t>(component->sizeData());
sd += sd & 1; // Align data to word boundary sd += sd & 1; // Align data to word boundary
sizeData += sd; sizeData += sd;
} }
@ -1124,7 +1124,7 @@ namespace Exiv2 {
sv += sv & 1; // Align value to word boundary sv += sv & 1; // Align value to word boundary
valueIdx += sv; valueIdx += sv;
} }
uint32_t sd = component->sizeData(); uint32_t sd = static_cast<uint32_t>(component->sizeData());
sd += sd & 1; // Align data to word boundary sd += sd & 1; // Align data to word boundary
dataIdx += sd; dataIdx += sd;
} }
@ -1154,7 +1154,7 @@ namespace Exiv2 {
idx += sv; idx += sv;
valueIdx += sv; valueIdx += sv;
} }
uint32_t sd = component->sizeData(); uint32_t sd = static_cast<uint32_t>(component->sizeData());
sd += sd & 1; // Align data to word boundary sd += sd & 1; // Align data to word boundary
dataIdx += sd; dataIdx += sd;
} }
@ -1227,7 +1227,7 @@ namespace Exiv2 {
DataBuf buf(pValue_->size()); DataBuf buf(pValue_->size());
pValue_->copy(buf.data(), byteOrder); pValue_->copy(buf.data(), byteOrder);
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return buf.size(); return static_cast<uint32_t>(buf.size());
} // TiffEntryBase::doWrite } // TiffEntryBase::doWrite
uint32_t TiffEntryBase::writeOffset(byte* buf, uint32_t TiffEntryBase::writeOffset(byte* buf,
@ -1260,7 +1260,8 @@ namespace Exiv2 {
uint32_t dataIdx, uint32_t dataIdx,
uint32_t& /*imageIdx*/) uint32_t& /*imageIdx*/)
{ {
if (!pValue() || pValue()->count() == 0) return 0; if (!pValue() || pValue()->count() == 0)
return 0;
DataBuf buf(pValue()->size()); DataBuf buf(pValue()->size());
uint32_t idx = 0; uint32_t idx = 0;
@ -1274,7 +1275,7 @@ namespace Exiv2 {
byteOrder); byteOrder);
} }
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return buf.size(); return static_cast<uint32_t>(buf.size());
} // TiffDataEntry::doWrite } // TiffDataEntry::doWrite
uint32_t TiffImageEntry::doWrite(IoWrapper& ioWrapper, uint32_t TiffImageEntry::doWrite(IoWrapper& ioWrapper,
@ -1293,8 +1294,7 @@ namespace Exiv2 {
<< std::setfill('0') << std::hex << tag() << std::dec << std::setfill('0') << std::hex << tag() << std::dec
<< ": Writing offset " << o2 << "\n"; << ": Writing offset " << o2 << "\n";
#endif #endif
DataBuf buf(static_cast<long>(strips_.size()) * 4); DataBuf buf(strips_.size() * 4);
buf.clear();
uint32_t idx = 0; uint32_t idx = 0;
for (auto&& strip : strips_) { for (auto&& strip : strips_) {
idx += writeOffset(buf.data(idx), o2, tiffType(), byteOrder); idx += writeOffset(buf.data(idx), o2, tiffType(), byteOrder);
@ -1306,7 +1306,7 @@ namespace Exiv2 {
} }
} }
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return buf.size(); return static_cast<uint32_t>(buf.size());
} // TiffImageEntry::doWrite } // TiffImageEntry::doWrite
uint32_t TiffSubIfd::doWrite(IoWrapper& ioWrapper, uint32_t TiffSubIfd::doWrite(IoWrapper& ioWrapper,
@ -1316,7 +1316,7 @@ namespace Exiv2 {
uint32_t dataIdx, uint32_t dataIdx,
uint32_t& /*imageIdx*/) uint32_t& /*imageIdx*/)
{ {
DataBuf buf(static_cast<long>(ifds_.size()) * 4); DataBuf buf(ifds_.size() * 4);
uint32_t idx = 0; uint32_t idx = 0;
// Sort IFDs by group, needed if image data tags were copied first // Sort IFDs by group, needed if image data tags were copied first
std::sort(ifds_.begin(), ifds_.end(), cmpGroupLt); std::sort(ifds_.begin(), ifds_.end(), cmpGroupLt);
@ -1325,7 +1325,7 @@ namespace Exiv2 {
dataIdx += ifd->size(); dataIdx += ifd->size();
} }
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return buf.size(); return static_cast<uint32_t>(buf.size());
} // TiffSubIfd::doWrite } // TiffSubIfd::doWrite
uint32_t TiffMnEntry::doWrite(IoWrapper& ioWrapper, uint32_t TiffMnEntry::doWrite(IoWrapper& ioWrapper,
@ -1376,7 +1376,7 @@ namespace Exiv2 {
// Some array entries need to have the size in the first element // Some array entries need to have the size in the first element
if (cfg()->hasSize_) { if (cfg()->hasSize_) {
byte buf[4]; byte buf[4];
long elSize = TypeInfo::typeSize(toTypeId(cfg()->elTiffType_, 0, cfg()->group_)); size_t elSize = TypeInfo::typeSize(toTypeId(cfg()->elTiffType_, 0, cfg()->group_));
switch (elSize) { switch (elSize) {
case 2: case 2:
idx += us2Data(buf, size(), byteOrder); idx += us2Data(buf, size(), byteOrder);
@ -1416,7 +1416,7 @@ namespace Exiv2 {
mio.write(buf.c_data(), buf.size()); mio.write(buf.c_data(), buf.size());
} }
} }
ioWrapper.write(mio.mmap(), static_cast<uint32_t>(mio.size())); ioWrapper.write(mio.mmap(), mio.size());
return idx; return idx;
} // TiffBinaryArray::doWrite } // TiffBinaryArray::doWrite
@ -1429,11 +1429,12 @@ namespace Exiv2 {
uint32_t& /*imageIdx*/) uint32_t& /*imageIdx*/)
{ {
Value const* pv = pValue(); Value const* pv = pValue();
if (!pv || pv->count() == 0) return 0; if (!pv || pv->count() == 0)
return 0;
DataBuf buf(pv->size()); DataBuf buf(pv->size());
pv->copy(buf.data(), byteOrder); pv->copy(buf.data(), byteOrder);
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return buf.size(); return static_cast<uint32_t>(buf.size());
} // TiffBinaryElement::doWrite } // TiffBinaryElement::doWrite
uint32_t TiffComponent::writeData(IoWrapper& ioWrapper, uint32_t TiffComponent::writeData(IoWrapper& ioWrapper,
@ -1493,9 +1494,10 @@ namespace Exiv2 {
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
// Align data to word boundary // Align data to word boundary
uint32_t align = (buf.size() & 1); uint32_t align = (buf.size() & 1);
if (align) ioWrapper.putb(0x0); if (align)
ioWrapper.putb(0x0);
return buf.size() + align; return static_cast<uint32_t>(buf.size() + align);
} // TiffDataEntry::doWriteData } // TiffDataEntry::doWriteData
uint32_t TiffSubIfd::doWriteData(IoWrapper& ioWrapper, uint32_t TiffSubIfd::doWriteData(IoWrapper& ioWrapper,
@ -1587,9 +1589,10 @@ namespace Exiv2 {
uint32_t TiffImageEntry::doWriteImage(IoWrapper& ioWrapper, uint32_t TiffImageEntry::doWriteImage(IoWrapper& ioWrapper,
ByteOrder /*byteOrder*/) const ByteOrder /*byteOrder*/) const
{ {
if ( !pValue() ) throw Error(kerImageWriteFailed); // #1296 if ( !pValue() )
throw Error(kerImageWriteFailed); // #1296
uint32_t len = pValue()->sizeDataArea(); size_t len = pValue()->sizeDataArea();
if (len > 0) { if (len > 0) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "TiffImageEntry, Directory " << groupName(group()) std::cerr << "TiffImageEntry, Directory " << groupName(group())
@ -1599,8 +1602,9 @@ namespace Exiv2 {
#endif #endif
DataBuf buf = pValue()->dataArea(); DataBuf buf = pValue()->dataArea();
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
uint32_t align = len & 1; // Align image data to word boundary size_t align = len & 1; // Align image data to word boundary
if (align) ioWrapper.putb(0x0); if (align)
ioWrapper.putb(0x0);
len += align; len += align;
} }
else { else {
@ -1622,7 +1626,7 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << ", len = " << len << " bytes\n"; std::cerr << ", len = " << len << " bytes\n";
#endif #endif
return len; return static_cast<uint32_t>(len);
} // TiffImageEntry::doWriteImage } // TiffImageEntry::doWriteImage
uint32_t TiffComponent::size() const uint32_t TiffComponent::size() const
@ -1642,7 +1646,7 @@ namespace Exiv2 {
sv += sv & 1; // Align value to word boundary sv += sv & 1; // Align value to word boundary
len += sv; len += sv;
} }
uint32_t sd = component->sizeData(); uint32_t sd = static_cast<uint32_t>(component->sizeData());
sd += sd & 1; // Align data to word boundary sd += sd & 1; // Align data to word boundary
len += sd; len += sd;
} }
@ -1716,65 +1720,67 @@ namespace Exiv2 {
uint32_t TiffBinaryElement::doSize() const uint32_t TiffBinaryElement::doSize() const
{ {
if (!pValue()) return 0; if (!pValue())
return pValue()->size(); return 0;
} // TiffBinaryElement::doSize return static_cast<uint32_t>(pValue()->size());
}
uint32_t TiffComponent::sizeData() const size_t TiffComponent::sizeData() const
{ {
return doSizeData(); return doSizeData();
} // TiffComponent::sizeData }
uint32_t TiffDirectory::doSizeData() const size_t TiffDirectory::doSizeData() const
{ {
assert(false); assert(false);
return 0; return 0;
} // TiffDirectory::doSizeData }
uint32_t TiffEntryBase::doSizeData() const size_t TiffEntryBase::doSizeData() const
{ {
return 0; return 0;
} // TiffEntryBase::doSizeData }
uint32_t TiffImageEntry::doSizeData() const size_t TiffImageEntry::doSizeData() const
{ {
uint32_t len = 0; size_t len = 0;
// For makernotes, TIFF image data is written to the data area // For makernotes, TIFF image data is written to the data area
if (group() > mnId) { // Todo: Fix this hack!! if (group() > mnId) { // Todo: Fix this hack!!
len = sizeImage(); len = sizeImage();
} }
return len; return len;
} // TiffImageEntry::doSizeData }
uint32_t TiffDataEntry::doSizeData() const size_t TiffDataEntry::doSizeData() const
{ {
if (!pValue()) return 0; if (!pValue())
return pValue()->sizeDataArea(); return 0;
} // TiffDataEntry::doSizeData return static_cast<uint32_t>(pValue()->sizeDataArea());
}
uint32_t TiffSubIfd::doSizeData() const size_t TiffSubIfd::doSizeData() const
{ {
uint32_t len = 0; uint32_t len = 0;
for (auto&& ifd : ifds_) { for (auto&& ifd : ifds_) {
len += ifd->size(); len += ifd->size();
} }
return len; return len;
} // TiffSubIfd::doSizeData }
uint32_t TiffIfdMakernote::doSizeData() const size_t TiffIfdMakernote::doSizeData() const
{ {
assert(false); assert(false);
return 0; return 0;
} // TiffIfdMakernote::doSizeData }
uint32_t TiffComponent::sizeImage() const size_t TiffComponent::sizeImage() const
{ {
return doSizeImage(); return doSizeImage();
} // TiffComponent::sizeImage }
uint32_t TiffDirectory::doSizeImage() const size_t TiffDirectory::doSizeImage() const
{ {
uint32_t len = 0; size_t len = 0;
for (auto&& component : components_) { for (auto&& component : components_) {
len += component->sizeImage(); len += component->sizeImage();
} }
@ -1782,31 +1788,32 @@ namespace Exiv2 {
len += pNext_->sizeImage(); len += pNext_->sizeImage();
} }
return len; return len;
} // TiffDirectory::doSizeImage }
uint32_t TiffSubIfd::doSizeImage() const size_t TiffSubIfd::doSizeImage() const
{ {
uint32_t len = 0; size_t len = 0;
for (auto&& ifd : ifds_) { for (auto&& ifd : ifds_) {
len += ifd->sizeImage(); len += ifd->sizeImage();
} }
return len; return len;
} // TiffSubIfd::doSizeImage } // TiffSubIfd::doSizeImage
uint32_t TiffIfdMakernote::doSizeImage() const size_t TiffIfdMakernote::doSizeImage() const
{ {
return ifd_.sizeImage(); return ifd_.sizeImage();
} // TiffIfdMakernote::doSizeImage } // TiffIfdMakernote::doSizeImage
uint32_t TiffEntryBase::doSizeImage() const size_t TiffEntryBase::doSizeImage() const
{ {
return 0; return 0;
} // TiffEntryBase::doSizeImage } // TiffEntryBase::doSizeImage
uint32_t TiffImageEntry::doSizeImage() const size_t TiffImageEntry::doSizeImage() const
{ {
if (!pValue()) return 0; if (!pValue())
uint32_t len = pValue()->sizeDataArea(); return 0;
auto len = pValue()->sizeDataArea();
if (len == 0) { if (len == 0) {
for (auto&& strip : strips_) { for (auto&& strip : strips_) {
len += strip.second; len += strip.second;
@ -1905,11 +1912,10 @@ namespace {
{ {
if (curr < tobe) { if (curr < tobe) {
Exiv2::DataBuf buf(tobe - curr); Exiv2::DataBuf buf(tobe - curr);
buf.clear();
ioWrapper.write(buf.c_data(), buf.size()); ioWrapper.write(buf.c_data(), buf.size());
return tobe - curr; return tobe - curr;
} }
return 0; return 0;
} // fillGap }
} // namespace } // namespace

@ -122,7 +122,7 @@ namespace Exiv2 {
The IO wrapper owns none of the objects passed in so the caller is The IO wrapper owns none of the objects passed in so the caller is
responsible to keep them alive. responsible to keep them alive.
*/ */
IoWrapper(BasicIo& io, const byte* pHeader, long size, OffsetWriter* pow); IoWrapper(BasicIo& io, const byte* pHeader, size_t size, OffsetWriter* pow);
//@} //@}
//! @name Manipulators //! @name Manipulators
@ -133,7 +133,7 @@ namespace Exiv2 {
Writes the TIFF header to the IO, if it hasn't been written yet, followed Writes the TIFF header to the IO, if it hasn't been written yet, followed
by the data passed in the arguments. by the data passed in the arguments.
*/ */
long write(const byte* pData, long wcount); size_t write(const byte* pData, size_t wcount);
/*! /*!
@brief Wraps the corresponding BasicIo::putb() method. @brief Wraps the corresponding BasicIo::putb() method.
@ -149,7 +149,7 @@ namespace Exiv2 {
// DATA // DATA
BasicIo& io_; //! Reference for the IO instance. BasicIo& io_; //! Reference for the IO instance.
const byte* pHeader_; //! Pointer to the header data. const byte* pHeader_; //! Pointer to the header data.
long size_; //! Size of the header data. size_t size_; //! Size of the header data.
bool wroteHeader_; //! Indicates if the header has been written. bool wroteHeader_; //! Indicates if the header has been written.
OffsetWriter* pow_; //! Pointer to an offset-writer, if any, or 0 OffsetWriter* pow_; //! Pointer to an offset-writer, if any, or 0
}; // class IoWrapper }; // class IoWrapper
@ -289,14 +289,14 @@ namespace Exiv2 {
write(). Components derived from TiffEntryBase implement this write(). Components derived from TiffEntryBase implement this
method corresponding to their implementation of writeData(). method corresponding to their implementation of writeData().
*/ */
uint32_t sizeData() const; size_t sizeData() const;
/*! /*!
@brief Return the size in bytes of the image data of this component @brief Return the size in bytes of the image data of this component
when written to a binary image. This is a support function for when written to a binary image. This is a support function for
write(). TIFF components implement this method corresponding to write(). TIFF components implement this method corresponding to
their implementation of writeImage(). their implementation of writeImage().
*/ */
uint32_t sizeImage() const; size_t sizeImage() const;
/*! /*!
@brief Return the unique id of the entry in the image. @brief Return the unique id of the entry in the image.
*/ */
@ -346,9 +346,9 @@ namespace Exiv2 {
//! Implements count(). //! Implements count().
virtual uint32_t doCount() const =0; virtual uint32_t doCount() const =0;
//! Implements sizeData(). //! Implements sizeData().
virtual uint32_t doSizeData() const =0; virtual size_t doSizeData() const =0;
//! Implements sizeImage(). //! Implements sizeImage().
virtual uint32_t doSizeImage() const =0; virtual size_t doSizeImage() const =0;
//@} //@}
private: private:
@ -529,9 +529,9 @@ namespace Exiv2 {
//! Implements size(). Return the size of a standard TIFF entry //! Implements size(). Return the size of a standard TIFF entry
uint32_t doSize() const override; uint32_t doSize() const override;
//! Implements sizeData(). Return 0. //! Implements sizeData(). Return 0.
uint32_t doSizeData() const override; size_t doSizeData() const override;
//! Implements sizeImage(). Return 0. //! Implements sizeImage(). Return 0.
uint32_t doSizeImage() const override; size_t doSizeImage() const override;
//@} //@}
//! Helper function to write an \em offset to a preallocated binary buffer //! Helper function to write an \em offset to a preallocated binary buffer
@ -552,7 +552,7 @@ namespace Exiv2 {
// DATA // DATA
TiffType tiffType_; //!< Field TIFF type TiffType tiffType_; //!< Field TIFF type
uint32_t count_; //!< The number of values of the indicated type size_t count_; //!< The number of values of the indicated type
int64_t offset_; //!< Offset to the data area int64_t offset_; //!< Offset to the data area
/*! /*!
Size of the data buffer holding the value in bytes, there is no Size of the data buffer holding the value in bytes, there is no
@ -717,7 +717,7 @@ namespace Exiv2 {
// Using doWriteImage from base class // Using doWriteImage from base class
// Using doSize() from base class // Using doSize() from base class
//! Implements sizeData(). Return the size of the data area. //! Implements sizeData(). Return the size of the data area.
uint32_t doSizeData() const override; size_t doSizeData() const override;
// Using doSizeImage from base class // Using doSizeImage from base class
//@} //@}
@ -792,9 +792,9 @@ namespace Exiv2 {
//! Implements size(). Return the size of the strip pointers. //! Implements size(). Return the size of the strip pointers.
uint32_t doSize() const override; uint32_t doSize() const override;
//! Implements sizeData(). Return the size of the image data area. //! Implements sizeData(). Return the size of the image data area.
uint32_t doSizeData() const override; size_t doSizeData() const override;
//! Implements sizeImage(). Return the size of the image data area. //! Implements sizeImage(). Return the size of the image data area.
uint32_t doSizeImage() const override; size_t doSizeImage() const override;
//@} //@}
private: private:
@ -926,12 +926,12 @@ namespace Exiv2 {
@brief This class does not really implement sizeData(), it only has @brief This class does not really implement sizeData(), it only has
size(). This method must not be called; it commits suicide. size(). This method must not be called; it commits suicide.
*/ */
uint32_t doSizeData() const override; size_t doSizeData() const override;
/*! /*!
@brief Implements sizeImage(). Return the sum of the image sizes of @brief Implements sizeImage(). Return the sum of the image sizes of
all components plus that of the next-IFD, if there is any. all components plus that of the next-IFD, if there is any.
*/ */
uint32_t doSizeImage() const override; size_t doSizeImage() const override;
//@} //@}
private: private:
@ -1015,9 +1015,9 @@ namespace Exiv2 {
//! Implements size(). Return the size of the sub-Ifd pointers. //! Implements size(). Return the size of the sub-Ifd pointers.
uint32_t doSize() const override; uint32_t doSize() const override;
//! Implements sizeData(). Return the sum of the sizes of all sub-IFDs. //! Implements sizeData(). Return the sum of the sizes of all sub-IFDs.
uint32_t doSizeData() const override; size_t doSizeData() const override;
//! Implements sizeImage(). Return the sum of the image sizes of all sub-IFDs. //! Implements sizeImage(). Return the sum of the image sizes of all sub-IFDs.
uint32_t doSizeImage() const override; size_t doSizeImage() const override;
//@} //@}
private: private:
@ -1228,12 +1228,12 @@ namespace Exiv2 {
@brief This class does not really implement sizeData(), it only has @brief This class does not really implement sizeData(), it only has
size(). This method must not be called; it commits suicide. size(). This method must not be called; it commits suicide.
*/ */
uint32_t doSizeData() const override; size_t doSizeData() const override;
/*! /*!
@brief Implements sizeImage(). Return the total image data size of the @brief Implements sizeImage(). Return the total image data size of the
makernote IFD. makernote IFD.
*/ */
uint32_t doSizeImage() const override; size_t doSizeImage() const override;
//@} //@}
private: private:

@ -194,7 +194,7 @@ namespace Exiv2 {
Exiv2::ExifKey key("Exif.Image.InterColorProfile"); Exiv2::ExifKey key("Exif.Image.InterColorProfile");
auto pos = exifData_.findKey(key); auto pos = exifData_.findKey(key);
if ( pos != exifData_.end() ) { if ( pos != exifData_.end() ) {
long size = pos->count() * pos->typeSize(); size_t size = pos->count() * pos->typeSize();
if (size == 0) { if (size == 0) {
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
} }
@ -234,7 +234,7 @@ namespace Exiv2 {
auto pos = exifData_.findKey(key); auto pos = exifData_.findKey(key);
bool found = pos != exifData_.end(); bool found = pos != exifData_.end();
if ( iccProfileDefined() ) { if ( iccProfileDefined() ) {
Exiv2::DataValue value(iccProfile_.c_data(), iccProfile_.size()); Exiv2::DataValue value(iccProfile_.c_data(), static_cast<long>(iccProfile_.size()));
if ( found ) pos->setValue(&value); if ( found ) pos->setValue(&value);
else exifData_.add(key,&value); else exifData_.add(key,&value);
} else { } else {
@ -247,12 +247,11 @@ namespace Exiv2 {
TiffParser::encode(*io_, pData, size, bo, exifData_, iptcData_, xmpData_); // may throw TiffParser::encode(*io_, pData, size, bo, exifData_, iptcData_, xmpData_); // may throw
} // TiffImage::writeMetadata } // TiffImage::writeMetadata
ByteOrder TiffParser::decode( ByteOrder TiffParser::decode(ExifData& exifData,
ExifData& exifData,
IptcData& iptcData, IptcData& iptcData,
XmpData& xmpData, XmpData& xmpData,
const byte* pData, const byte* pData,
uint32_t size size_t size
) )
{ {
uint32_t root = Tag::root; uint32_t root = Tag::root;
@ -269,7 +268,7 @@ namespace Exiv2 {
iptcData, iptcData,
xmpData, xmpData,
pData, pData,
size, static_cast<uint32_t>(size),
root, root,
TiffMapping::findDecoder); TiffMapping::findDecoder);
} // TiffParser::decode } // TiffParser::decode
@ -298,9 +297,9 @@ namespace Exiv2 {
ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end()); ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(filteredIfd)), ed.end());
} }
std::unique_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder)); TiffHeader header(byteOrder);
return TiffParserWorker::encode(io, pData, size, ed, iptcData, xmpData, Tag::root, TiffMapping::findEncoder, return TiffParserWorker::encode(io, pData, size, ed, iptcData, xmpData, Tag::root, TiffMapping::findEncoder,
header.get(), nullptr); &header, nullptr);
} // TiffParser::encode } // TiffParser::encode
// ************************************************************************* // *************************************************************************

@ -50,7 +50,7 @@ namespace Exiv2 {
false, // Don't concatenate gaps false, // Don't concatenate gaps
{ 0, ttUnsignedShort, 1 } { 0, ttUnsignedShort, 1 }
}; };
//! Canon Camera Settings binary array - definition //! Canon Camera Settings binary array - definition
constexpr ArrayDef canonCsDef[] = { constexpr ArrayDef canonCsDef[] = {
{ 46, ttUnsignedShort, 3 } // Exif.CanonCs.Lens { 46, ttUnsignedShort, 3 } // Exif.CanonCs.Lens
@ -259,7 +259,7 @@ namespace Exiv2 {
{ 0, ttSignedLong, 1 } { 0, ttSignedLong, 1 }
}; };
//! Canon RawBurst Info binary array - configuration //! Canon RawBurst Info binary array - configuration
@ -1303,13 +1303,13 @@ namespace Exiv2 {
{ Tag::root, fujiId, exifId, 0x927c }, { Tag::root, fujiId, exifId, 0x927c },
{ Tag::root, canonId, exifId, 0x927c }, { Tag::root, canonId, exifId, 0x927c },
{ Tag::root, canonCsId, canonId, 0x0001 }, { Tag::root, canonCsId, canonId, 0x0001 },
{ Tag::root, canonSiId, canonId, 0x0004 }, { Tag::root, canonSiId, canonId, 0x0004 },
{ Tag::root, canonPaId, canonId, 0x0005 }, { Tag::root, canonPaId, canonId, 0x0005 },
{ Tag::root, canonCfId, canonId, 0x000f }, { Tag::root, canonCfId, canonId, 0x000f },
{ Tag::root, canonPiId, canonId, 0x0012 }, { Tag::root, canonPiId, canonId, 0x0012 },
{ Tag::root, canonTiId, canonId, 0x0035 }, { Tag::root, canonTiId, canonId, 0x0035 },
{ Tag::root, canonFiId, canonId, 0x0093 }, { Tag::root, canonFiId, canonId, 0x0093 },
{ Tag::root, canonPrId, canonId, 0x00a0 }, { Tag::root, canonPrId, canonId, 0x00a0 },
{ Tag::root, canonAfMiAdjId, canonId, 0x4013 }, { Tag::root, canonAfMiAdjId, canonId, 0x4013 },
{ Tag::root, canonVigCor2Id, canonId, 0x4016 }, { Tag::root, canonVigCor2Id, canonId, 0x4016 },
{ Tag::root, canonLiOpId, canonId, 0x4018 }, { Tag::root, canonLiOpId, canonId, 0x4018 },
@ -1676,7 +1676,7 @@ namespace Exiv2 {
{ 0x0012, canonId, EXV_SIMPLE_BINARY_ARRAY(canonPiCfg) }, { 0x0012, canonId, EXV_SIMPLE_BINARY_ARRAY(canonPiCfg) },
{ 0x0035, canonId, EXV_SIMPLE_BINARY_ARRAY(canonTiCfg) }, { 0x0035, canonId, EXV_SIMPLE_BINARY_ARRAY(canonTiCfg) },
{ 0x0093, canonId, EXV_BINARY_ARRAY(canonFiCfg, canonFiDef) }, { 0x0093, canonId, EXV_BINARY_ARRAY(canonFiCfg, canonFiDef) },
{ 0x00a0, canonId, EXV_SIMPLE_BINARY_ARRAY(canonPrCfg) }, { 0x00a0, canonId, EXV_SIMPLE_BINARY_ARRAY(canonPrCfg) },
{ 0x4013, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAfMiAdjCfg) }, { 0x4013, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAfMiAdjCfg) },
// { 0x4015, canonId, EXV_SIMPLE_BINARY_ARRAY(canonVigCorCfg) }, // { 0x4015, canonId, EXV_SIMPLE_BINARY_ARRAY(canonVigCorCfg) },
{ 0x4016, canonId, EXV_SIMPLE_BINARY_ARRAY(canonVigCor2Cfg) }, { 0x4016, canonId, EXV_SIMPLE_BINARY_ARRAY(canonVigCor2Cfg) },
@ -1684,9 +1684,9 @@ namespace Exiv2 {
{ 0x4019, canonId, EXV_SIMPLE_BINARY_ARRAY(canonLeCfg) }, { 0x4019, canonId, EXV_SIMPLE_BINARY_ARRAY(canonLeCfg) },
{ 0x4020, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAmCfg) }, { 0x4020, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAmCfg) },
{ 0x4021, canonId, EXV_SIMPLE_BINARY_ARRAY(canonMeCfg) }, { 0x4021, canonId, EXV_SIMPLE_BINARY_ARRAY(canonMeCfg) },
{ 0x4024, canonId, EXV_SIMPLE_BINARY_ARRAY(canonFilCfg) }, { 0x4024, canonId, EXV_SIMPLE_BINARY_ARRAY(canonFilCfg) },
{ 0x4025, canonId, EXV_SIMPLE_BINARY_ARRAY(canonHdrCfg) }, { 0x4025, canonId, EXV_SIMPLE_BINARY_ARRAY(canonHdrCfg) },
{ 0x4028, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAfCCfg) }, { 0x4028, canonId, EXV_SIMPLE_BINARY_ARRAY(canonAfCCfg) },
{ 0x403f, canonId, EXV_SIMPLE_BINARY_ARRAY(canonRawBCfg) }, { 0x403f, canonId, EXV_SIMPLE_BINARY_ARRAY(canonRawBCfg) },
{ Tag::next, canonId, ignoreTiffComponent }, { Tag::next, canonId, ignoreTiffComponent },
{ Tag::all, canonId, newTiffEntry }, { Tag::all, canonId, newTiffEntry },
@ -2041,7 +2041,7 @@ namespace Exiv2 {
group = ts->parentGroup_; group = ts->parentGroup_;
} while (!(ts->root_ == root && ts->group_ == ifdIdNotSet)); } while (!(ts->root_ == root && ts->group_ == ifdIdNotSet));
} // TiffCreator::getPath }
ByteOrder TiffParserWorker::decode( ByteOrder TiffParserWorker::decode(
ExifData& exifData, ExifData& exifData,
@ -2057,7 +2057,7 @@ namespace Exiv2 {
// Create standard TIFF header if necessary // Create standard TIFF header if necessary
std::unique_ptr<TiffHeaderBase> ph; std::unique_ptr<TiffHeaderBase> ph;
if (!pHeader) { if (!pHeader) {
ph = std::unique_ptr<TiffHeaderBase>(new TiffHeader); ph = std::make_unique<TiffHeader>();
pHeader = ph.get(); pHeader = ph.get();
} }

@ -427,8 +427,7 @@ namespace Exiv2 {
byte const* record = nullptr; byte const* record = nullptr;
uint32_t sizeHdr = 0; uint32_t sizeHdr = 0;
uint32_t sizeData = 0; uint32_t sizeData = 0;
if (0 != Photoshop::locateIptcIrb(pData, size, if (0 != Photoshop::locateIptcIrb(pData, size, &record, &sizeHdr, &sizeData)) {
&record, &sizeHdr, &sizeData)) {
return; return;
} }
if (0 == IptcParser::decode(iptcData_, record + sizeHdr, sizeData)) { if (0 == IptcParser::decode(iptcData_, record + sizeHdr, sizeData)) {
@ -456,12 +455,13 @@ namespace Exiv2 {
// create vector of signedShorts from unsignedShorts in Exif.Canon.AFInfo // create vector of signedShorts from unsignedShorts in Exif.Canon.AFInfo
std::vector<int16_t> ints; std::vector<int16_t> ints;
std::vector<uint16_t> uint; std::vector<uint16_t> uint;
for (long i = 0; i < object->pValue()->count(); i++) { for (size_t i = 0; i < object->pValue()->count(); i++) {
ints.push_back(static_cast<int16_t>(object->pValue()->toInt64(i))); ints.push_back(static_cast<int16_t>(object->pValue()->toInt64(i)));
uint.push_back(static_cast<uint16_t>(object->pValue()->toInt64(i))); uint.push_back(static_cast<uint16_t>(object->pValue()->toInt64(i)));
} }
// Check this is AFInfo2 (ints[0] = bytes in object) // Check this is AFInfo2 (ints[0] = bytes in object)
if ( ints.at(0) != object->pValue()->count()*2 ) return ; if ( ints.at(0) != static_cast<int16_t>(object->pValue()->count())*2 )
return ;
std::string familyGroup(std::string("Exif.") + groupName(object->group()) + "."); std::string familyGroup(std::string("Exif.") + groupName(object->group()) + ".");
@ -624,13 +624,12 @@ namespace Exiv2 {
if (rawIptc.size() % 4 != 0) { if (rawIptc.size() % 4 != 0) {
// Pad the last unsignedLong value with 0s // Pad the last unsignedLong value with 0s
buf.alloc((rawIptc.size() / 4) * 4 + 4); buf.alloc((rawIptc.size() / 4) * 4 + 4);
buf.clear();
buf.copyBytes(0, rawIptc.c_data(), rawIptc.size()); buf.copyBytes(0, rawIptc.c_data(), rawIptc.size());
} }
else { else {
buf = std::move(rawIptc); // Note: This resets rawIptc buf = std::move(rawIptc); // Note: This resets rawIptc
} }
value->read(buf.data(), buf.size(), byteOrder_); value->read(buf.data(), static_cast<long>(buf.size()), byteOrder_);
Exifdatum iptcDatum(iptcNaaKey, value.get()); Exifdatum iptcDatum(iptcNaaKey, value.get());
exifData_.add(iptcDatum); exifData_.add(iptcDatum);
pos = exifData_.findKey(irbKey); // needed after add() pos = exifData_.findKey(irbKey); // needed after add()
@ -644,7 +643,7 @@ namespace Exiv2 {
exifData_.erase(pos); exifData_.erase(pos);
if (irbBuf.size() != 0) { if (irbBuf.size() != 0) {
auto value = Value::create(unsignedByte); auto value = Value::create(unsignedByte);
value->read(irbBuf.data(), irbBuf.size(), invalidByteOrder); value->read(irbBuf.data(), static_cast<long>(irbBuf.size()), invalidByteOrder);
Exifdatum iptcDatum(irbKey, value.get()); Exifdatum iptcDatum(irbKey, value.get());
exifData_.add(iptcDatum); exifData_.add(iptcDatum);
} }
@ -822,8 +821,10 @@ namespace Exiv2 {
if (object->cfg() == nullptr || !object->decoded()) if (object->cfg() == nullptr || !object->decoded())
return; return;
int32_t size = object->TiffEntryBase::doSize(); int32_t size = object->TiffEntryBase::doSize();
if (size == 0) return; if (size == 0)
if (!object->initialize(pRoot_)) return; return;
if (!object->initialize(pRoot_))
return;
// Re-encrypt buffer if necessary // Re-encrypt buffer if necessary
CryptFct cryptFct = object->cfg()->cryptFct_; CryptFct cryptFct = object->cfg()->cryptFct_;
@ -835,7 +836,7 @@ namespace Exiv2 {
DataBuf buf = cryptFct(object->tag(), pData, size, pRoot_); DataBuf buf = cryptFct(object->tag(), pData, size, pRoot_);
if (buf.size() > 0) { if (buf.size() > 0) {
pData = buf.c_data(); pData = buf.c_data();
size = buf.size(); size = static_cast<int32_t>(buf.size());
} }
if (!object->updOrigDataBuf(pData, size)) { if (!object->updOrigDataBuf(pData, size)) {
setDirty(); setDirty();
@ -969,7 +970,7 @@ namespace Exiv2 {
{ {
encodeOffsetEntry(object, datum); encodeOffsetEntry(object, datum);
uint32_t sizeDataArea = object->pValue()->sizeDataArea(); size_t sizeDataArea = object->pValue()->sizeDataArea();
if (sizeDataArea > 0 && writeMethod() == wmNonIntrusive) { if (sizeDataArea > 0 && writeMethod() == wmNonIntrusive) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
@ -992,13 +993,13 @@ namespace Exiv2 {
<< " not found. Writing only one strip.\n"; << " not found. Writing only one strip.\n";
#endif #endif
object->strips_.clear(); object->strips_.clear();
object->strips_.emplace_back(zero, sizeDataArea); object->strips_.emplace_back(zero, static_cast<uint32_t>(sizeDataArea));
} }
else { else {
uint32_t sizeTotal = 0; uint32_t sizeTotal = 0;
object->strips_.clear(); object->strips_.clear();
for (long i = 0; i < pos->count(); ++i) { for (size_t i = 0; i < pos->count(); ++i) {
uint32_t len = pos->toUint32(i); uint32_t len = pos->toUint32(static_cast<long>(i));
object->strips_.emplace_back(zero, len); object->strips_.emplace_back(zero, len);
sizeTotal += len; sizeTotal += len;
} }
@ -1510,7 +1511,7 @@ namespace Exiv2 {
p += 2; p += 2;
TiffType tiffType = getUShort(p, byteOrder()); TiffType tiffType = getUShort(p, byteOrder());
TypeId typeId = toTypeId(tiffType, object->tag(), object->group()); TypeId typeId = toTypeId(tiffType, object->tag(), object->group());
long typeSize = TypeInfo::typeSize(typeId); size_t typeSize = TypeInfo::typeSize(typeId);
if (0 == typeSize) { if (0 == typeSize) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Directory " << groupName(object->group()) EXV_WARNING << "Directory " << groupName(object->group())
@ -1539,7 +1540,7 @@ namespace Exiv2 {
if (count > std::numeric_limits<uint32_t>::max() / typeSize) { if (count > std::numeric_limits<uint32_t>::max() / typeSize) {
throw Error(kerArithmeticOverflow); throw Error(kerArithmeticOverflow);
} }
uint32_t size = typeSize * count; uint32_t size = static_cast<uint32_t>(typeSize * count);
uint32_t offset = getLong(p, byteOrder()); uint32_t offset = getLong(p, byteOrder());
byte* pData = p; byte* pData = p;
if ( size > 4 if ( size > 4

@ -49,7 +49,7 @@ namespace {
struct TypeInfoTable { struct TypeInfoTable {
Exiv2::TypeId typeId_; //!< Type id Exiv2::TypeId typeId_; //!< Type id
const char* name_; //!< Name of the type const char* name_; //!< Name of the type
long size_; //!< Bytes per data entry size_t size_; //!< Bytes per data entry
//! Comparison operator for \em typeId //! Comparison operator for \em typeId
bool operator==(Exiv2::TypeId typeId) const bool operator==(Exiv2::TypeId typeId) const
{ {
@ -111,164 +111,124 @@ namespace Exiv2 {
return tit->typeId_; return tit->typeId_;
} }
long TypeInfo::typeSize(TypeId typeId) size_t TypeInfo::typeSize(TypeId typeId)
{ {
const TypeInfoTable* tit = find(typeInfoTable, typeId); const TypeInfoTable* tit = find(typeInfoTable, typeId);
if (!tit) return 0; if (!tit)
return 0;
return tit->size_; return tit->size_;
} }
DataBuf::DataBuf(DataBuf&& rhs) DataBuf::DataBuf(size_t size) : pData_(size)
: pData_(rhs.pData_), size_(rhs.size_)
{
rhs.pData_ = nullptr;
rhs.size_ = 0;
}
DataBuf::~DataBuf()
{ delete[] pData_; }
DataBuf::DataBuf() : pData_(nullptr), size_(0)
{}
DataBuf::DataBuf(long size) : pData_(new byte[size]()), size_(size)
{}
DataBuf::DataBuf(const byte* pData, long size) : pData_(nullptr), size_(0)
{
if (size > 0) {
pData_ = new byte[size];
std::memcpy(pData_, pData, size);
size_ = size;
}
}
DataBuf::DataBuf(const DataBuf& rhs)
: DataBuf(rhs.pData_, rhs.size_)
{} {}
DataBuf& DataBuf::operator=(DataBuf&& rhs) DataBuf::DataBuf(const byte* pData, size_t size) : pData_(size)
{ {
if (this == &rhs) return *this; std::copy_n(pData, size, pData_.begin());
reset();
std::swap(pData_, rhs.pData_);
std::swap(size_, rhs.size_);
return *this;
} }
void DataBuf::alloc(long size) void DataBuf::alloc(size_t size)
{ {
if (size > size_) { pData_.resize(size);
delete[] pData_;
pData_ = new byte[size];
size_ = size;
}
} }
void DataBuf::resize(long size) void DataBuf::resize(size_t size)
{ {
if (size > size_) { pData_.resize(size);
byte* newbuf = new byte[size];
if (size_ > 0) {
memcpy(newbuf, pData_, size_);
}
delete[] pData_;
pData_ = newbuf;
}
size_ = size;
} }
void DataBuf::reset() void DataBuf::reset()
{ {
delete[] pData_; pData_.clear();
pData_ = nullptr;
size_ = 0;
}
void DataBuf::clear() {
memset(pData_, 0, size_);
} }
uint8_t Exiv2::DataBuf::read_uint8(size_t offset) const { uint8_t Exiv2::DataBuf::read_uint8(size_t offset) const {
if (offset >= static_cast<size_t>(size_)) { if (offset >= pData_.size()) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint8"); throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint8");
} }
return pData_[offset]; return pData_[offset];
} }
void Exiv2::DataBuf::write_uint8(size_t offset, uint8_t x) { void Exiv2::DataBuf::write_uint8(size_t offset, uint8_t x) {
if (offset >= static_cast<size_t>(size_)) { if (offset >= pData_.size()) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint8"); throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint8");
} }
pData_[offset] = x; pData_[offset] = x;
} }
uint16_t Exiv2::DataBuf::read_uint16(size_t offset, ByteOrder byteOrder) const { uint16_t Exiv2::DataBuf::read_uint16(size_t offset, ByteOrder byteOrder) const {
if (size_ < 2 || offset > static_cast<size_t>(size_ - 2)) { if (pData_.size() < 2 || offset > (pData_.size() - 2)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint16"); throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint16");
} }
return getUShort(&pData_[offset], byteOrder); return getUShort(&pData_[offset], byteOrder);
} }
void Exiv2::DataBuf::write_uint16(size_t offset, uint16_t x, ByteOrder byteOrder) { void Exiv2::DataBuf::write_uint16(size_t offset, uint16_t x, ByteOrder byteOrder) {
if (size_ < 2 || offset > static_cast<size_t>(size_ - 2)) { if (pData_.size() < 2 || offset > (pData_.size() - 2)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint16"); throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint16");
} }
us2Data(&pData_[offset], x, byteOrder); us2Data(&pData_[offset], x, byteOrder);
} }
uint32_t Exiv2::DataBuf::read_uint32(size_t offset, ByteOrder byteOrder) const { uint32_t Exiv2::DataBuf::read_uint32(size_t offset, ByteOrder byteOrder) const {
if (size_ < 4 || offset > static_cast<size_t>(size_ - 4)) { if (pData_.size() < 4 || offset > (pData_.size() - 4)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint32"); throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint32");
} }
return getULong(&pData_[offset], byteOrder); return getULong(&pData_[offset], byteOrder);
} }
void Exiv2::DataBuf::write_uint32(size_t offset, uint32_t x, ByteOrder byteOrder) { void Exiv2::DataBuf::write_uint32(size_t offset, uint32_t x, ByteOrder byteOrder) {
if (size_ < 4 || offset > static_cast<size_t>(size_ - 4)) { if (pData_.size() < 4 || offset > (pData_.size() - 4)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint32"); throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint32");
} }
ul2Data(&pData_[offset], x, byteOrder); ul2Data(&pData_[offset], x, byteOrder);
} }
uint64_t Exiv2::DataBuf::read_uint64(size_t offset, ByteOrder byteOrder) const { uint64_t Exiv2::DataBuf::read_uint64(size_t offset, ByteOrder byteOrder) const {
if (size_ < 8 || offset > static_cast<size_t>(size_ - 8)) { if (pData_.size() < 8 || offset > (pData_.size() - 8)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint64"); throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint64");
} }
return getULongLong(&pData_[offset], byteOrder); return getULongLong(&pData_[offset], byteOrder);
} }
void Exiv2::DataBuf::write_uint64(size_t offset, uint64_t x, ByteOrder byteOrder) { void Exiv2::DataBuf::write_uint64(size_t offset, uint64_t x, ByteOrder byteOrder) {
if (size_ < 8 || offset > static_cast<size_t>(size_ - 8)) { if (pData_.size() < 8 || offset > (pData_.size() - 8)) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint64"); throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint64");
} }
ull2Data(&pData_[offset], x, byteOrder); ull2Data(&pData_[offset], x, byteOrder);
} }
void Exiv2::DataBuf::copyBytes(size_t offset, const void* buf, size_t bufsize) { void Exiv2::DataBuf::copyBytes(size_t offset, const void* buf, size_t bufsize) {
if (static_cast<size_t>(size_) < bufsize || offset > size_ - bufsize) { if (pData_.size() < bufsize || offset > pData_.size() - bufsize) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::copyBytes"); throw std::overflow_error("Overflow in Exiv2::DataBuf::copyBytes");
} if (bufsize > 0) {
memcpy(&pData_[offset], buf, bufsize);
} }
memcpy(&pData_[offset], buf, bufsize);
} }
int Exiv2::DataBuf::cmpBytes(size_t offset, const void* buf, size_t bufsize) const { int Exiv2::DataBuf::cmpBytes(size_t offset, const void* buf, size_t bufsize) const {
if (static_cast<size_t>(size_) < bufsize || offset > size_ - bufsize) { if (pData_.size() < bufsize || offset > pData_.size() - bufsize) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::cmpBytes"); throw std::overflow_error("Overflow in Exiv2::DataBuf::cmpBytes");
} }
return memcmp(&pData_[offset], buf, bufsize); return memcmp(&pData_[offset], buf, bufsize);
} }
byte* Exiv2::DataBuf::data(size_t offset) { byte* Exiv2::DataBuf::data(size_t offset) {
if (static_cast<size_t>(size_) < offset) { /// \todo this first check should be for <= offset
if (pData_.size() < offset) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::c_data"); throw std::overflow_error("Overflow in Exiv2::DataBuf::c_data");
} else if (pData_.empty() || pData_.size() == offset) {
return nullptr;
} }
return &pData_[offset]; return &pData_[offset];
} }
const byte* Exiv2::DataBuf::c_data(size_t offset) const { const byte* Exiv2::DataBuf::c_data(size_t offset) const {
if (static_cast<size_t>(size_) < offset) { /// \todo this first check should be for <= offset
if (pData_.size() < offset) {
throw std::overflow_error("Overflow in Exiv2::DataBuf::c_data"); throw std::overflow_error("Overflow in Exiv2::DataBuf::c_data");
} else if (pData_.empty() || pData_.size() == offset) {
return nullptr;
} }
return &pData_[offset]; return &pData_[offset];
} }
@ -283,7 +243,7 @@ namespace Exiv2 {
static void checkDataBufBounds(const DataBuf& buf, size_t end) { static void checkDataBufBounds(const DataBuf& buf, size_t end) {
enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()), enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()),
"end of slice too large to be compared with DataBuf bounds."); "end of slice too large to be compared with DataBuf bounds.");
enforce<std::out_of_range>(static_cast<long>(end) <= buf.size(), "Invalid slice bounds specified"); enforce<std::out_of_range>(end <= buf.size(), "Invalid slice bounds specified");
} }
Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end) Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end)

@ -118,7 +118,7 @@ namespace Exiv2 {
return value; return value;
} // Value::create } // Value::create
int Value::setDataArea(const byte* /*buf*/, long /*len*/) int Value::setDataArea(const byte* /*buf*/, size_t /*len*/)
{ {
return -1; return -1;
} }
@ -131,12 +131,12 @@ namespace Exiv2 {
return os.str(); return os.str();
} }
std::string Value::toString(long /*n*/) const std::string Value::toString(size_t /*n*/) const
{ {
return toString(); return toString();
} }
long Value::sizeDataArea() const size_t Value::sizeDataArea() const
{ {
return 0; return 0;
} }
@ -158,12 +158,12 @@ namespace Exiv2 {
read(buf, len, byteOrder); read(buf, len, byteOrder);
} }
long DataValue::count() const size_t DataValue::count() const
{ {
return size(); return size();
} }
int DataValue::read(const byte* buf, long len, ByteOrder /*byteOrder*/) int DataValue::read(const byte* buf, size_t len, ByteOrder /*byteOrder*/)
{ {
// byteOrder not needed // byteOrder not needed
value_.assign(buf, buf + len); value_.assign(buf, buf + len);
@ -190,9 +190,9 @@ namespace Exiv2 {
return static_cast<long>(std::copy(value_.begin(), value_.end(), buf) - buf); return static_cast<long>(std::copy(value_.begin(), value_.end(), buf) - buf);
} }
long DataValue::size() const size_t DataValue::size() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
DataValue* DataValue::clone_() const DataValue* DataValue::clone_() const
@ -210,7 +210,7 @@ namespace Exiv2 {
return os; return os;
} }
std::string DataValue::toString(long n) const std::string DataValue::toString(size_t n) const
{ {
std::ostringstream os; std::ostringstream os;
os << static_cast<int>(value_.at(n)); os << static_cast<int>(value_.at(n));
@ -218,25 +218,25 @@ namespace Exiv2 {
return os.str(); return os.str();
} }
int64_t DataValue::toInt64(long n) const int64_t DataValue::toInt64(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
uint32_t DataValue::toUint32(long n) const uint32_t DataValue::toUint32(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
float DataValue::toFloat(long n) const float DataValue::toFloat(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
Rational DataValue::toRational(long n) const Rational DataValue::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
return {value_.at(n), 1}; return {value_.at(n), 1};
@ -267,7 +267,7 @@ namespace Exiv2 {
return 0; return 0;
} }
int StringValueBase::read(const byte* buf, long len, ByteOrder /*byteOrder*/) int StringValueBase::read(const byte* buf, size_t len, ByteOrder /*byteOrder*/)
{ {
// byteOrder not needed // byteOrder not needed
if (buf) value_ = std::string(reinterpret_cast<const char*>(buf), len); if (buf) value_ = std::string(reinterpret_cast<const char*>(buf), len);
@ -285,14 +285,14 @@ namespace Exiv2 {
); );
} }
long StringValueBase::count() const size_t StringValueBase::count() const
{ {
return size(); return size();
} }
long StringValueBase::size() const size_t StringValueBase::size() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
std::ostream& StringValueBase::write(std::ostream& os) const std::ostream& StringValueBase::write(std::ostream& os) const
@ -300,25 +300,25 @@ namespace Exiv2 {
return os << value_; return os << value_;
} }
int64_t StringValueBase::toInt64(long n) const int64_t StringValueBase::toInt64(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
uint32_t StringValueBase::toUint32(long n) const uint32_t StringValueBase::toUint32(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
float StringValueBase::toFloat(long n) const float StringValueBase::toFloat(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
Rational StringValueBase::toRational(long n) const Rational StringValueBase::toRational(size_t n) const
{ {
ok_ = true; ok_ = true;
return {value_.at(n), 1}; return {value_.at(n), 1};
@ -458,7 +458,7 @@ namespace Exiv2 {
return StringValueBase::read(code + c); return StringValueBase::read(code + c);
} }
int CommentValue::read(const byte* buf, long len, ByteOrder byteOrder) int CommentValue::read(const byte* buf, size_t len, ByteOrder byteOrder)
{ {
byteOrder_ = byteOrder; byteOrder_ = byteOrder;
return StringValueBase::read(buf, len, byteOrder); return StringValueBase::read(buf, len, byteOrder);
@ -601,19 +601,17 @@ namespace Exiv2 {
return static_cast<long>(s.size()); return static_cast<long>(s.size());
} }
int XmpValue::read(const byte* buf, int XmpValue::read(const byte* buf, size_t len, ByteOrder /*byteOrder*/)
long len,
ByteOrder /*byteOrder*/)
{ {
std::string s(reinterpret_cast<const char*>(buf), len); std::string s(reinterpret_cast<const char*>(buf), len);
return read(s); return read(s);
} }
long XmpValue::size() const size_t XmpValue::size() const
{ {
std::ostringstream os; std::ostringstream os;
write(os); write(os);
return static_cast<long>(os.str().size()); return os.str().size();
} }
XmpTextValue::XmpTextValue() XmpTextValue::XmpTextValue()
@ -667,12 +665,12 @@ namespace Exiv2 {
return UniquePtr(clone_()); return UniquePtr(clone_());
} }
long XmpTextValue::size() const size_t XmpTextValue::size() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
long XmpTextValue::count() const size_t XmpTextValue::count() const
{ {
return size(); return size();
} }
@ -700,22 +698,22 @@ namespace Exiv2 {
return os << value_; return os << value_;
} }
int64_t XmpTextValue::toInt64(long /*n*/) const int64_t XmpTextValue::toInt64(size_t /*n*/) const
{ {
return parseInt64(value_, ok_); return parseInt64(value_, ok_);
} }
uint32_t XmpTextValue::toUint32(long /*n*/) const uint32_t XmpTextValue::toUint32(size_t /*n*/) const
{ {
return parseUint32(value_, ok_); return parseUint32(value_, ok_);
} }
float XmpTextValue::toFloat(long /*n*/) const float XmpTextValue::toFloat(size_t /*n*/) const
{ {
return parseFloat(value_, ok_); return parseFloat(value_, ok_);
} }
Rational XmpTextValue::toRational(long /*n*/) const Rational XmpTextValue::toRational(size_t /*n*/) const
{ {
return parseRational(value_, ok_); return parseRational(value_, ok_);
} }
@ -742,9 +740,9 @@ namespace Exiv2 {
return UniquePtr(clone_()); return UniquePtr(clone_());
} }
long XmpArrayValue::count() const size_t XmpArrayValue::count() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
std::ostream& XmpArrayValue::write(std::ostream& os) const std::ostream& XmpArrayValue::write(std::ostream& os) const
@ -756,28 +754,28 @@ namespace Exiv2 {
return os; return os;
} }
std::string XmpArrayValue::toString(long n) const std::string XmpArrayValue::toString(size_t n) const
{ {
ok_ = true; ok_ = true;
return value_.at(n); return value_.at(n);
} }
int64_t XmpArrayValue::toInt64(long n) const int64_t XmpArrayValue::toInt64(size_t n) const
{ {
return parseInt64(value_.at(n), ok_); return parseInt64(value_.at(n), ok_);
} }
uint32_t XmpArrayValue::toUint32(long n) const uint32_t XmpArrayValue::toUint32(size_t n) const
{ {
return parseUint32(value_.at(n), ok_); return parseUint32(value_.at(n), ok_);
} }
float XmpArrayValue::toFloat(long n) const float XmpArrayValue::toFloat(size_t n) const
{ {
return parseFloat(value_.at(n), ok_); return parseFloat(value_.at(n), ok_);
} }
Rational XmpArrayValue::toRational(long n) const Rational XmpArrayValue::toRational(size_t n) const
{ {
return parseRational(value_.at(n), ok_); return parseRational(value_.at(n), ok_);
} }
@ -846,9 +844,9 @@ namespace Exiv2 {
return UniquePtr(clone_()); return UniquePtr(clone_());
} }
long LangAltValue::count() const size_t LangAltValue::count() const
{ {
return static_cast<long>(value_.size()); return value_.size();
} }
static const std::string x_default = "x-default"; static const std::string x_default = "x-default";
@ -875,7 +873,7 @@ namespace Exiv2 {
return os; return os;
} }
std::string LangAltValue::toString(long /*n*/) const std::string LangAltValue::toString(size_t /*n*/) const
{ {
return toString(x_default); return toString(x_default);
} }
@ -891,25 +889,25 @@ namespace Exiv2 {
return ""; return "";
} }
int64_t LangAltValue::toInt64(long /*n*/) const int64_t LangAltValue::toInt64(size_t /*n*/) const
{ {
ok_ = false; ok_ = false;
return 0; return 0;
} }
uint32_t LangAltValue::toUint32(long /*n*/) const uint32_t LangAltValue::toUint32(size_t /*n*/) const
{ {
ok_ = false; ok_ = false;
return 0; return 0;
} }
float LangAltValue::toFloat(long /*n*/) const float LangAltValue::toFloat(size_t /*n*/) const
{ {
ok_ = false; ok_ = false;
return 0.0F; return 0.0F;
} }
Rational LangAltValue::toRational(long /*n*/) const Rational LangAltValue::toRational(size_t /*n*/) const
{ {
ok_ = false; ok_ = false;
return {0, 0}; return {0, 0};
@ -933,7 +931,7 @@ namespace Exiv2 {
date_.day = day; date_.day = day;
} }
int DateValue::read(const byte* buf, long len, ByteOrder /*byteOrder*/) int DateValue::read(const byte* buf, size_t len, ByteOrder /*byteOrder*/)
{ {
const std::string str(reinterpret_cast<const char*>(buf), len); const std::string str(reinterpret_cast<const char*>(buf), len);
return read(str); return read(str);
@ -986,12 +984,12 @@ namespace Exiv2 {
return date_; return date_;
} }
long DateValue::count() const size_t DateValue::count() const
{ {
return size(); return size();
} }
long DateValue::size() const size_t DateValue::size() const
{ {
return 8; return 8;
} }
@ -1012,7 +1010,7 @@ namespace Exiv2 {
return os; return os;
} }
int64_t DateValue::toInt64(long /*n*/) const int64_t DateValue::toInt64(size_t /*n*/) const
{ {
// Range of tm struct is limited to about 1970 to 2038 // Range of tm struct is limited to about 1970 to 2038
// This will return -1 if outside that range // This will return -1 if outside that range
@ -1026,7 +1024,7 @@ namespace Exiv2 {
return l; return l;
} }
uint32_t DateValue::toUint32(long /*n*/) const uint32_t DateValue::toUint32(size_t /*n*/) const
{ {
const int64_t t = toInt64(); const int64_t t = toInt64();
if (t < 0 || t > std::numeric_limits<uint32_t>::max()) { if (t < 0 || t > std::numeric_limits<uint32_t>::max()) {
@ -1035,12 +1033,12 @@ namespace Exiv2 {
return static_cast<uint32_t>(t); return static_cast<uint32_t>(t);
} }
float DateValue::toFloat(long n) const float DateValue::toFloat(size_t n) const
{ {
return static_cast<float>(toInt64(n)); return static_cast<float>(toInt64(n));
} }
Rational DateValue::toRational(long n) const Rational DateValue::toRational(size_t n) const
{ {
return {static_cast<int32_t>(toInt64(n)), 1}; return {static_cast<int32_t>(toInt64(n)), 1};
} }
@ -1062,7 +1060,7 @@ namespace Exiv2 {
time_.tzMinute = tzMinute; time_.tzMinute = tzMinute;
} }
int TimeValue::read(const byte* buf, long len, ByteOrder /*byteOrder*/) int TimeValue::read(const byte* buf, size_t len, ByteOrder /*byteOrder*/)
{ {
const std::string str(reinterpret_cast<const char*>(buf), len); const std::string str(reinterpret_cast<const char*>(buf), len);
return read(str); return read(str);
@ -1140,12 +1138,12 @@ namespace Exiv2 {
return time_; return time_;
} }
long TimeValue::count() const size_t TimeValue::count() const
{ {
return size(); return size();
} }
long TimeValue::size() const size_t TimeValue::size() const
{ {
return 11; return 11;
} }
@ -1174,7 +1172,7 @@ namespace Exiv2 {
return os; return os;
} }
int64_t TimeValue::toInt64(long /*n*/) const int64_t TimeValue::toInt64(size_t /*n*/) const
{ {
// Returns number of seconds in the day in UTC. // Returns number of seconds in the day in UTC.
int64_t result = (time_.hour - time_.tzHour) * 60 * 60; int64_t result = (time_.hour - time_.tzHour) * 60 * 60;
@ -1187,7 +1185,7 @@ namespace Exiv2 {
return result; return result;
} }
uint32_t TimeValue::toUint32(long /*n*/) const uint32_t TimeValue::toUint32(size_t /*n*/) const
{ {
const int64_t t = toInt64(); const int64_t t = toInt64();
if (t < 0 || t > std::numeric_limits<uint32_t>::max()) { if (t < 0 || t > std::numeric_limits<uint32_t>::max()) {
@ -1196,12 +1194,12 @@ namespace Exiv2 {
return static_cast<uint32_t>(t); return static_cast<uint32_t>(t);
} }
float TimeValue::toFloat(long n) const float TimeValue::toFloat(size_t n) const
{ {
return static_cast<float>(toInt64(n)); return static_cast<float>(toInt64(n));
} }
Rational TimeValue::toRational(long n) const Rational TimeValue::toRational(size_t n) const
{ {
return {static_cast<int32_t>(toInt64(n)), 1}; return {static_cast<int32_t>(toInt64(n)), 1};
} }

@ -411,7 +411,8 @@ namespace Exiv2 {
WEBP_TAG_SIZE) WEBP_TAG_SIZE)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
ul2Data(data, static_cast<uint32_t>(iccProfile_.size()), littleEndian); ul2Data(data, static_cast<uint32_t>(iccProfile_.size()), littleEndian);
if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) throw Error(kerImageWriteFailed); if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE)
throw Error(kerImageWriteFailed);
if (outIo.write(iccProfile_.c_data(), iccProfile_.size()) != iccProfile_.size()) { if (outIo.write(iccProfile_.c_data(), iccProfile_.size()) != iccProfile_.size()) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
@ -444,7 +445,7 @@ namespace Exiv2 {
us2Data(data, static_cast<uint16_t>(blob.size()) + 8, bigEndian); us2Data(data, static_cast<uint16_t>(blob.size()) + 8, bigEndian);
ul2Data(data, static_cast<uint32_t>(blob.size()), littleEndian); ul2Data(data, static_cast<uint32_t>(blob.size()), littleEndian);
if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) throw Error(kerImageWriteFailed); if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) throw Error(kerImageWriteFailed);
if (outIo.write(&blob[0], static_cast<long>(blob.size())) != static_cast<long>(blob.size())) { if (outIo.write(&blob[0], blob.size()) != blob.size()) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
if (outIo.tell() % 2) { if (outIo.tell() % 2) {
@ -457,8 +458,7 @@ namespace Exiv2 {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
ul2Data(data, static_cast<uint32_t>(xmpPacket().size()), littleEndian); ul2Data(data, static_cast<uint32_t>(xmpPacket().size()), littleEndian);
if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) throw Error(kerImageWriteFailed); if (outIo.write(data, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) throw Error(kerImageWriteFailed);
if (outIo.write(reinterpret_cast<const byte*>(xmp.data()), static_cast<long>(xmp.size())) != if (outIo.write(reinterpret_cast<const byte*>(xmp.data()), xmp.size()) != xmp.size()) {
static_cast<long>(xmp.size())) {
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
} }
if (outIo.tell() % 2) { if (outIo.tell() % 2) {
@ -526,7 +526,7 @@ namespace Exiv2 {
if ( equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF) && option==kpsRecursive ) { if ( equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF) && option==kpsRecursive ) {
// create memio object with the payload, then print the structure // create memio object with the payload, then print the structure
MemIo p (payload.c_data(),payload.size()); MemIo p (payload.c_data(), payload.size());
printTiffStructure(p,out,option,depth); printTiffStructure(p,out,option,depth);
} }
@ -561,13 +561,11 @@ namespace Exiv2 {
io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata); io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata);
const uint32_t filesize_u32 = const uint32_t filesize_u32 = Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U);
Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U);
enforce(filesize_u32 <= io_->size(), Exiv2::kerCorruptedMetadata); enforce(filesize_u32 <= io_->size(), Exiv2::kerCorruptedMetadata);
// Check that `filesize_u32` is safe to cast to `long`. // Check that `filesize_u32` is safe to cast to `long`.
enforce(filesize_u32 <= static_cast<size_t>(std::numeric_limits<unsigned int>::max()), enforce(filesize_u32 <= static_cast<uint32_t>(std::numeric_limits<long>::max()), Exiv2::kerCorruptedMetadata);
Exiv2::kerCorruptedMetadata);
WebPImage::decodeChunks(static_cast<long>(filesize_u32)); WebPImage::decodeChunks(static_cast<long>(filesize_u32));
@ -591,8 +589,7 @@ namespace Exiv2 {
const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian); const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian);
// Check that `size_u32` is safe to cast to `long`. // Check that `size_u32` is safe to cast to `long`.
enforce(static_cast<uint64_t>(size_u32) <= static_cast<unsigned long>(std::numeric_limits<long>::max()), enforce(size_u32 <= static_cast<uint32_t>(std::numeric_limits<long>::max()), Exiv2::kerCorruptedMetadata);
Exiv2::kerCorruptedMetadata);
const long size = static_cast<long>(size_u32); const long size = static_cast<long>(size_u32);
// Check that `size` is within bounds. // Check that `size` is within bounds.
@ -684,26 +681,26 @@ namespace Exiv2 {
byte exifShortHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; byte exifShortHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
byte exifTiffLEHeader[] = { 0x49, 0x49, 0x2A }; // "MM*" byte exifTiffLEHeader[] = { 0x49, 0x49, 0x2A }; // "MM*"
byte exifTiffBEHeader[] = { 0x4D, 0x4D, 0x00, 0x2A }; // "II\0*" byte exifTiffBEHeader[] = { 0x4D, 0x4D, 0x00, 0x2A }; // "II\0*"
long offset = 0; size_t offset = 0;
bool s_header = false; bool s_header = false;
bool le_header = false; bool le_header = false;
bool be_header = false; bool be_header = false;
long pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifLongHeader), 4); long pos = getHeaderOffset(payload.c_data(), static_cast<long>(payload.size()), reinterpret_cast<byte*>(&exifLongHeader), 4);
if (pos == -1) { if (pos == -1) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifLongHeader), 6); pos = getHeaderOffset(payload.c_data(), static_cast<long>(payload.size()), reinterpret_cast<byte*>(&exifLongHeader), 6);
if (pos != -1) { if (pos != -1) {
s_header = true; s_header = true;
} }
} }
if (pos == -1) { if (pos == -1) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifTiffLEHeader), 3); pos = getHeaderOffset(payload.c_data(), static_cast<long>(payload.size()), reinterpret_cast<byte*>(&exifTiffLEHeader), 3);
if (pos != -1) { if (pos != -1) {
le_header = true; le_header = true;
} }
} }
if (pos == -1) { if (pos == -1) {
pos = getHeaderOffset(payload.c_data(), payload.size(), reinterpret_cast<byte*>(&exifTiffBEHeader), 4); pos = getHeaderOffset(payload.c_data(), static_cast<long>(payload.size()), reinterpret_cast<byte*>(&exifTiffBEHeader), 4);
if (pos != -1) { if (pos != -1) {
be_header = true; be_header = true;
} }
@ -716,7 +713,7 @@ namespace Exiv2 {
offset += 12; offset += 12;
} }
const long sizePayload = Safe::add(payload.size(), offset); const size_t sizePayload = Safe::add(payload.size(), offset);
DataBuf rawExifData(sizePayload); DataBuf rawExifData(sizePayload);
if (s_header) { if (s_header) {
@ -871,7 +868,7 @@ namespace Exiv2 {
/* Handle inject an icc profile right after VP8X chunk */ /* Handle inject an icc profile right after VP8X chunk */
if (has_icc) { if (has_icc) {
byte size_buff[WEBP_TAG_SIZE]; byte size_buff[WEBP_TAG_SIZE];
ul2Data(size_buff, iccProfile_.size(), littleEndian); ul2Data(size_buff, static_cast<uint32_t>(iccProfile_.size()), littleEndian);
if (iIo.write(reinterpret_cast<const byte*>(WEBP_CHUNK_HEADER_VP8X), WEBP_TAG_SIZE) != WEBP_TAG_SIZE) if (iIo.write(reinterpret_cast<const byte*>(WEBP_CHUNK_HEADER_VP8X), WEBP_TAG_SIZE) != WEBP_TAG_SIZE)
throw Error(kerImageWriteFailed); throw Error(kerImageWriteFailed);
if (iIo.write(size_buff, WEBP_TAG_SIZE) != WEBP_TAG_SIZE) if (iIo.write(size_buff, WEBP_TAG_SIZE) != WEBP_TAG_SIZE)

@ -383,14 +383,14 @@ namespace Exiv2 {
return 0; return 0;
} }
long Xmpdatum::count() const size_t Xmpdatum::count() const
{ {
return p_->value_.get() == nullptr ? 0 : p_->value_->count(); return p_->value_.get() == nullptr ? 0 : p_->value_->count();
} }
long Xmpdatum::size() const long Xmpdatum::size() const
{ {
return p_->value_.get() == nullptr ? 0 : p_->value_->size(); return p_->value_.get() == nullptr ? 0 : static_cast<long>(p_->value_->size());
} }
std::string Xmpdatum::toString() const std::string Xmpdatum::toString() const
@ -951,10 +951,10 @@ namespace Exiv2 {
if (i.typeId() == xmpBag || i.typeId() == xmpSeq || i.typeId() == xmpAlt) { if (i.typeId() == xmpBag || i.typeId() == xmpSeq || i.typeId() == xmpAlt) {
printNode(ns, i.tagName(), "", options); printNode(ns, i.tagName(), "", options);
meta.SetProperty(ns.c_str(), i.tagName().c_str(), nullptr, options); meta.SetProperty(ns.c_str(), i.tagName().c_str(), nullptr, options);
for (long idx = 0; idx < i.count(); ++idx) { for (size_t idx = 0; idx < i.count(); ++idx) {
const std::string item = i.tagName() + "[" + toString(idx + 1) + "]"; const std::string item = i.tagName() + "[" + toString(idx + 1) + "]";
printNode(ns, item, i.toString(idx), 0); printNode(ns, item, i.toString(static_cast<long>(idx)), 0);
meta.SetProperty(ns.c_str(), item.c_str(), i.toString(idx).c_str()); meta.SetProperty(ns.c_str(), item.c_str(), i.toString(static_cast<long>(idx)).c_str());
} }
continue; continue;
} }

@ -79,18 +79,20 @@ namespace Exiv2 {
IoCloser closer(*io_); IoCloser closer(*io_);
// Ensure that this is the correct image type // Ensure that this is the correct image type
if (!isXmpType(*io_, false)) { if (!isXmpType(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); if (io_->error() || io_->eof())
throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "XMP"); throw Error(kerNotAnImage, "XMP");
} }
// Read the XMP packet from the IO stream // Read the XMP packet from the IO stream
std::string xmpPacket; std::string xmpPacket;
const long len = 64 * 1024; const long len = 64 * 1024;
byte buf[len]; byte buf[len];
long l; size_t l;
while ((l = io_->read(buf, len)) > 0) { while ((l = io_->read(buf, len)) > 0) {
xmpPacket.append(reinterpret_cast<char*>(buf), l); xmpPacket.append(reinterpret_cast<char*>(buf), l);
} }
if (io_->error()) throw Error(kerFailedToReadImageData); if (io_->error())
throw Error(kerFailedToReadImageData);
clearMetadata(); clearMetadata();
xmpPacket_ = xmpPacket; xmpPacket_ = xmpPacket;
if (!xmpPacket_.empty() && XmpParser::decode(xmpData_, xmpPacket_)) { if (!xmpPacket_.empty() && XmpParser::decode(xmpData_, xmpPacket_)) {
@ -179,9 +181,8 @@ namespace Exiv2 {
auto tempIo = std::make_unique<MemIo>(); auto tempIo = std::make_unique<MemIo>();
// Write XMP packet // Write XMP packet
if ( tempIo->write(reinterpret_cast<const byte*>(xmpPacket_.data()), if (tempIo->write(reinterpret_cast<const byte*>(xmpPacket_.data()), xmpPacket_.size()) != xmpPacket_.size())
static_cast<long>(xmpPacket_.size())) throw Error(kerImageWriteFailed);
!= static_cast<long>(xmpPacket_.size())) throw Error(kerImageWriteFailed);
if (tempIo->error()) throw Error(kerImageWriteFailed); if (tempIo->error()) throw Error(kerImageWriteFailed);
io_->close(); io_->close();
io_->transfer(*tempIo); // may throw io_->transfer(*tempIo); // may throw

@ -18,7 +18,6 @@ class AdditionOverflowInLoaderExifJpeg(metaclass=system_tests.CaseMeta):
Warning: Directory Image, entry 0x0201: Strip 0 is outside of the data area; ignored. Warning: Directory Image, entry 0x0201: Strip 0 is outside of the data area; ignored.
Warning: Directory Image, entry 0x0201: Strip 7 is outside of the data area; ignored. Warning: Directory Image, entry 0x0201: Strip 7 is outside of the data area; ignored.
Error: Offset of directory Thumbnail, entry 0x0201 is out of bounds: Offset = 0x00000000; truncating the entry Error: Offset of directory Thumbnail, entry 0x0201 is out of bounds: Offset = 0x00000000; truncating the entry
$uncaught_exception $addition_overflow_message
""" """
] ]
retval = [1] retval = [0]

@ -17,22 +17,22 @@ class PngReadRawProfile(metaclass=system_tests.CaseMeta):
system_tests.path("$data_path/issue_428_poc4.png"), system_tests.path("$data_path/issue_428_poc4.png"),
system_tests.path("$data_path/issue_428_poc5.png"), system_tests.path("$data_path/issue_428_poc5.png"),
system_tests.path("$data_path/issue_428_poc8.png"), system_tests.path("$data_path/issue_428_poc8.png"),
system_tests.path("$data_path/issue_428_poc7.png"),
system_tests.path("$data_path/issue_428_poc2.png"), system_tests.path("$data_path/issue_428_poc2.png"),
system_tests.path("$data_path/issue_428_poc6.png"), system_tests.path("$data_path/issue_428_poc6.png"),
system_tests.path("$data_path/issue_428_poc7.png"),
] ]
commands = ["$exiv2 " + fname for fname in filenames] commands = ["$exiv2 " + fname for fname in filenames]
stdout = [""] * len(filenames) stdout = [""] * len(filenames)
stderr = [ stderr_exception(fname) for fname in filenames[0:5] ] stderr = [ stderr_exception(fname) for fname in filenames[0:6] ]
stderr.append("""$exiv2_exception_message """ + filenames[5] + """:
stderr.append("""$exiv2_exception_message """ + filenames[6] + """:
$kerInputDataReadFailed $kerInputDataReadFailed
""") """)
stderr.append("""Error: XMP Toolkit error 201: Error in XMLValidator stderr.append("""Error: XMP Toolkit error 201: Error in XMLValidator
Warning: Failed to decode XMP metadata. Warning: Failed to decode XMP metadata.
""" + stderr_exception(filenames[6]))
stderr.append("""Warning: Failed to decode Exif metadata.
""" + stderr_exception(filenames[7])) """ + stderr_exception(filenames[7]))
retval = [1] * len(filenames) retval = [1] * len(filenames)

@ -30,7 +30,7 @@ TEST(MemIo, isNotAtEofInitially)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_FALSE(io.eof()); ASSERT_FALSE(io.eof());
} }
@ -39,7 +39,7 @@ TEST(MemIo, seekBeyondBufferSizeReturns1AndSetsEofToTrue)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(1, io.seek(65, BasicIo::beg)); ASSERT_EQ(1, io.seek(65, BasicIo::beg));
ASSERT_TRUE(io.eof()); ASSERT_TRUE(io.eof());
} }
@ -49,7 +49,7 @@ TEST(MemIo, seekBefore0Returns1ButItDoesNotSetEofToTrue)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(1, io.seek(-1, BasicIo::beg)); ASSERT_EQ(1, io.seek(-1, BasicIo::beg));
ASSERT_FALSE(io.eof()); ASSERT_FALSE(io.eof());
} }
@ -59,7 +59,7 @@ TEST(MemIo, seekBeyondBoundsDoesNotMoveThePosition)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(0, io.tell()); ASSERT_EQ(0, io.tell());
ASSERT_EQ(1, io.seek(65, BasicIo::beg)); ASSERT_EQ(1, io.seek(65, BasicIo::beg));
ASSERT_EQ(0, io.tell()); ASSERT_EQ(0, io.tell());
@ -70,7 +70,7 @@ TEST(MemIo, seekInsideBoundsMoveThePosition)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(0, io.tell()); ASSERT_EQ(0, io.tell());
ASSERT_EQ(0, io.seek(32, BasicIo::beg)); ASSERT_EQ(0, io.seek(32, BasicIo::beg));
ASSERT_EQ(32, io.tell()); ASSERT_EQ(32, io.tell());
@ -81,7 +81,7 @@ TEST(MemIo, seekInsideBoundsUsingBeg_resetsThePosition)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
std::vector<std::int64_t> positions {0, 8, 16, 32, 64}; std::vector<std::int64_t> positions {0, 8, 16, 32, 64};
for(auto pos: positions) { for(auto pos: positions) {
ASSERT_EQ(0, io.seek(pos, BasicIo::beg)); ASSERT_EQ(0, io.seek(pos, BasicIo::beg));
@ -94,7 +94,7 @@ TEST(MemIo, seekInsideBoundsUsingCur_shiftThePosition)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
std::vector<std::int64_t> shifts {4, 4, 8, 16, 32}; std::vector<std::int64_t> shifts {4, 4, 8, 16, 32};
std::vector<std::int64_t> positions {4, 8, 16, 32, 64}; std::vector<std::int64_t> positions {4, 8, 16, 32, 64};
for (size_t i = 0; i < shifts.size(); ++i) { for (size_t i = 0; i < shifts.size(); ++i) {
@ -108,7 +108,7 @@ TEST(MemIo, seekToEndPosition_doesNotTriggerEof)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(0, io.tell()); ASSERT_EQ(0, io.tell());
ASSERT_EQ(0, io.seek(0, BasicIo::end)); ASSERT_EQ(0, io.seek(0, BasicIo::end));
ASSERT_EQ(64, io.tell()); ASSERT_EQ(64, io.tell());
@ -120,7 +120,7 @@ TEST(MemIo, seekToEndPositionAndReadTriggersEof)
std::array<byte, 64> buf; std::array<byte, 64> buf;
buf.fill(0); buf.fill(0);
MemIo io(buf.data(), static_cast<long>(buf.size())); MemIo io(buf.data(), buf.size());
ASSERT_EQ(0, io.seek(0, BasicIo::end)); ASSERT_EQ(0, io.seek(0, BasicIo::end));
ASSERT_EQ(64, io.tell()); ASSERT_EQ(64, io.tell());
@ -134,7 +134,7 @@ TEST(MemIo, readEmptyIoReturns0)
{ {
std::array<byte, 10> buf; std::array<byte, 10> buf;
MemIo io; MemIo io;
ASSERT_EQ(0, io.read(buf.data(), static_cast<long>(buf.size()))); ASSERT_EQ(0, io.read(buf.data(), buf.size()));
} }
TEST(MemIo, readLessBytesThanAvailableReturnsRequestedBytes) TEST(MemIo, readLessBytesThanAvailableReturnsRequestedBytes)
@ -143,7 +143,7 @@ TEST(MemIo, readLessBytesThanAvailableReturnsRequestedBytes)
buf1.fill(1); buf1.fill(1);
buf2.fill(0); buf2.fill(0);
MemIo io(buf1.data(), static_cast<long>(buf1.size())); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(5, io.read(buf2.data(), 5)); ASSERT_EQ(5, io.read(buf2.data(), 5));
} }
@ -153,7 +153,7 @@ TEST(MemIo, readSameBytesThanAvailableReturnsRequestedBytes)
buf1.fill(1); buf1.fill(1);
buf2.fill(0); buf2.fill(0);
MemIo io(buf1.data(), static_cast<long>(buf1.size())); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(10, io.read(buf2.data(), 10)); ASSERT_EQ(10, io.read(buf2.data(), 10));
} }
@ -163,6 +163,6 @@ TEST(MemIo, readMoreBytesThanAvailableReturnsAvailableBytes)
buf1.fill(1); buf1.fill(1);
buf2.fill(0); buf2.fill(0);
MemIo io(buf1.data(), static_cast<long>(buf1.size())); MemIo io(buf1.data(), buf1.size());
ASSERT_EQ(10, io.read(buf2.data(), 15)); ASSERT_EQ(10, io.read(buf2.data(), 15));
} }

@ -113,30 +113,26 @@ TEST(base64encode, encodesValidString)
const std::string original ("This is a unit test"); const std::string original ("This is a unit test");
const std::string expected ("VGhpcyBpcyBhIHVuaXQgdGVzdA=="); const std::string expected ("VGhpcyBpcyBhIHVuaXQgdGVzdA==");
size_t encodeLength = ((original.size() + 2) / 3) * 4 + 1; size_t encodeLength = ((original.size() + 2) / 3) * 4 + 1;
auto result = new char[encodeLength]; std::vector<char> result(encodeLength);
ASSERT_EQ(1, base64encode(original.c_str(), original.size(), result, encodeLength)); ASSERT_EQ(1, base64encode(original.c_str(), original.size(), result.data(), encodeLength));
ASSERT_STREQ(expected.c_str(), result); ASSERT_STREQ(expected.c_str(), result.data());
delete [] result;
} }
TEST(base64encode, doesNotEncodeWithNotBigEnoughResultSize) TEST(base64encode, doesNotEncodeWithNotBigEnoughResultSize)
{ {
const std::string original ("This is a unit test"); const std::string original ("This is a unit test");
size_t encodeLength = (original.size()); size_t encodeLength = (original.size());
auto result = new char[encodeLength]; std::vector<char> result(encodeLength);
ASSERT_EQ(0, base64encode(original.c_str(), original.size(), result, encodeLength)); ASSERT_EQ(0, base64encode(original.c_str(), original.size(), result.data(), encodeLength));
delete [] result;
} }
TEST(base64decode, decodesValidString) TEST(base64decode, decodesValidString)
{ {
const std::string original ("VGhpcyBpcyBhIHVuaXQgdGVzdA=="); const std::string original ("VGhpcyBpcyBhIHVuaXQgdGVzdA==");
const std::string expected ("This is a unit test"); const std::string expected ("This is a unit test");
auto result = new char[original.size()]; std::vector<char> result(original.size());
ASSERT_EQ(static_cast<long>(expected.size()), ASSERT_EQ(static_cast<long>(expected.size()), base64decode(original.c_str(), result.data(), original.size()));
base64decode(original.c_str(), result, original.size())); ASSERT_STREQ(expected.c_str(), result.data());
ASSERT_STREQ(expected.c_str(), result);
delete [] result;
} }
TEST(AUri, parsesAndDecoreUrl) TEST(AUri, parsesAndDecoreUrl)

@ -62,7 +62,6 @@ TEST(DataBuf, allocatesDataWithNonEmptyConstructor)
TEST(DataBuf, read_write_endianess) TEST(DataBuf, read_write_endianess)
{ {
DataBuf buf(4 + 1 + 2 + 4 + 8); DataBuf buf(4 + 1 + 2 + 4 + 8);
buf.clear();
// Big endian. // Big endian.
buf.write_uint8(4, 0x01); buf.write_uint8(4, 0x01);

Loading…
Cancel
Save