Merge pull request #2109 from Exiv2/main_StringView

Refactoring & cleanup
main
Luis Díaz Más 3 years ago committed by GitHub
commit c5a9dfd9af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
.gitignore vendored

@ -25,3 +25,5 @@ doc/html
contrib/vms/.vagrant
/.vscode
.vs/
*cppcheck*

@ -83,7 +83,6 @@ namespace {
public:
//! C'tor
Timestamp() = default;
//! Read the timestamp of a file
int read(const std::string& path);
//! Read the timestamp from a broken-down time in buffer \em tm.
int read(struct tm* tm);
@ -176,11 +175,6 @@ namespace Action {
registry_.clear();
}
void TaskFactory::registerTask(TaskType type, Task::UniquePtr task)
{
registry_[type] = std::move(task);
}
TaskFactory::TaskFactory()
{
registry_.emplace(adjust, std::make_unique<Adjust>());
@ -268,7 +262,7 @@ namespace Action {
int Print::printSummary()
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -284,11 +278,8 @@ namespace Action {
std::cout << path_ << std::endl;
// Filesize
struct stat buf;
if (0 == stat(path_.c_str(), &buf)) {
printLabel(_("File size"));
std::cout << buf.st_size << " " << _("Bytes") << std::endl;
}
printLabel(_("File size"));
std::cout << fs::file_size(path_) << " " << _("Bytes") << std::endl;
// MIME type
printLabel(_("MIME type"));
@ -402,7 +393,7 @@ namespace Action {
int Print::printList()
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -596,7 +587,6 @@ namespace Action {
if (Params::instance().printItems_ & Params::prHex) {
if (!first)
std::cout << std::endl;
first = false;
Exiv2::DataBuf buf(md.size());
md.copy(buf.data(), pImage->byteOrder());
Exiv2::hexdump(std::cout, buf.c_data(), buf.size());
@ -607,7 +597,7 @@ namespace Action {
int Print::printComment()
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -624,7 +614,7 @@ namespace Action {
int Print::printPreviewList()
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -658,7 +648,7 @@ namespace Action {
int Rename::run(const std::string& path)
{
try {
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " << _("Failed to open the file\n");
return -1;
}
@ -740,7 +730,7 @@ namespace Action {
try {
path_ = path;
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -900,7 +890,7 @@ namespace Action {
int Extract::writeThumbnail() const
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -947,7 +937,7 @@ namespace Action {
int Extract::writePreviews() const
{
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
return -1;
}
@ -983,7 +973,7 @@ namespace Action {
int Extract::writeIccProfile(const std::string& target) const
{
int rc = 0;
if (!Exiv2::fileExists(path_, true)) {
if (!Exiv2::fileExists(path_)) {
std::cerr << path_ << ": " << _("Failed to open the file\n");
rc = -1;
}
@ -1049,7 +1039,7 @@ namespace Action {
// -i{tgt}- reading from stdin?
bool bStdin = (Params::instance().target_ & Params::ctStdInOut) != 0;
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path
<< ": " << _("Failed to open the file\n");
return -1;
@ -1106,12 +1096,12 @@ namespace Action {
Params::instance().getStdin(xmpBlob);
rc = insertXmpPacket(path,xmpBlob,true);
} else {
if (!Exiv2::fileExists(xmpPath, true)) {
if (!Exiv2::fileExists(xmpPath)) {
std::cerr << xmpPath
<< ": " << _("Failed to open the file\n");
rc = -1;
}
if (rc == 0 && !Exiv2::fileExists(path, true)) {
if (rc == 0 && !Exiv2::fileExists(path)) {
std::cerr << path
<< ": " << _("Failed to open the file\n");
rc = -1;
@ -1152,7 +1142,7 @@ namespace Action {
Params::instance().getStdin(iccProfile);
rc = insertIccProfile(path,std::move(iccProfile));
} else {
if (!Exiv2::fileExists(iccProfilePath, true)) {
if (!Exiv2::fileExists(iccProfilePath)) {
std::cerr << iccProfilePath
<< ": " << _("Failed to open the file\n");
rc = -1;
@ -1168,7 +1158,7 @@ namespace Action {
{
int rc = 0;
// test path exists
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " << _("Failed to open the file\n");
rc=-1;
}
@ -1192,12 +1182,12 @@ namespace Action {
int Insert::insertThumbnail(const std::string& path)
{
std::string thumbPath = newFilePath(path, "-thumb.jpg");
if (!Exiv2::fileExists(thumbPath, true)) {
if (!Exiv2::fileExists(thumbPath)) {
std::cerr << thumbPath
<< ": " << _("Failed to open the file\n");
return -1;
}
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path
<< ": " << _("Failed to open the file\n");
return -1;
@ -1220,7 +1210,7 @@ namespace Action {
int Modify::run(const std::string& path)
{
try {
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " << _("Failed to open the file\n");
return -1;
}
@ -1452,7 +1442,7 @@ namespace Action {
monthAdjustment_ = Params::instance().yodAdjust_[Params::yodMonth].adjustment_;
dayAdjustment_ = Params::instance().yodAdjust_[Params::yodDay].adjustment_;
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " << _("Failed to open the file\n");
return -1;
}
@ -1579,7 +1569,7 @@ namespace Action {
int FixIso::run(const std::string& path)
{
try {
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " <<_("Failed to open the file\n");
return -1;
}
@ -1632,7 +1622,7 @@ namespace Action {
int FixCom::run(const std::string& path)
{
try {
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": " <<_("Failed to open the file\n");
return -1;
}
@ -1821,7 +1811,7 @@ namespace {
// read the source metadata
int rc = -1 ;
if (!Exiv2::fileExists(source, true)) {
if (!Exiv2::fileExists(source)) {
std::cerr << source << ": " << _("Failed to open the file\n");
return rc;
}
@ -1893,7 +1883,6 @@ namespace {
// #1148 use Raw XMP packet if there are no XMP modification commands
int tRawSidecar = Params::ctXmpSidecar | Params::ctXmpRaw; // option -eXX
// printTarget("in metacopy",Params::instance().target_,true);
if (Params::instance().modifyCmds_.empty() && (Params::instance().target_ & tRawSidecar) == tRawSidecar) {
// std::cout << "short cut" << std::endl;
// http://www.cplusplus.com/doc/tutorial/files/
@ -1946,7 +1935,8 @@ namespace {
}
// delete temporary target
if ( bStdout ) std::remove(target.c_str());
if ( bStdout )
fs::remove(target.c_str());
return rc;
} // metacopy
@ -2046,14 +2036,7 @@ namespace {
std::cout << std::endl;
}
// Workaround for MinGW rename which does not overwrite existing files
remove(newPath.c_str());
if (std::rename(path.c_str(), newPath.c_str()) == -1) {
std::cerr << Params::instance().progname() << ": " << _("Failed to rename") << " " << path << " " << _("to")
<< " " << newPath << ": " << Exiv2::strError() << "\n";
return 1;
}
fs::rename(path, newPath);
return 0;
}
@ -2096,7 +2079,7 @@ namespace {
int printStructure(std::ostream& out, Exiv2::PrintStructureOption option, const std::string &path)
{
if (!Exiv2::fileExists(path, true)) {
if (!Exiv2::fileExists(path)) {
std::cerr << path << ": "
<< _("Failed to open the file\n");
return -1;

@ -123,20 +123,6 @@ namespace Action {
*/
Task::UniquePtr create(TaskType type);
/*!
@brief Register a task prototype together with its type.
The task factory creates new tasks of a given type by cloning its
associated prototype. Additional tasks can be registered. If called
for a type which already exists in the list, the corresponding
prototype is replaced.
@param type Task type.
@param task Pointer to the prototype. Ownership is transferred to the
task factory. That's what the auto pointer indicates.
*/
void registerTask(TaskType type, Task::UniquePtr task);
private:
//! Prevent construction other than through instance().
TaskFactory();

@ -160,7 +160,6 @@ int main(int argc, char* const argv[])
assert(task);
// Process all files
int n = 1;
int s = static_cast<int>(params.files_.size());
if (params.action_ & Action::extract && params.target_ & Params::ctStdInOut && s > 1) {
std::cerr << params.progname() << ": " << _("Only one file is allowed when extracting to stdout") << std::endl;
@ -168,6 +167,7 @@ int main(int argc, char* const argv[])
}
else {
int w = s > 9 ? s > 99 ? 3 : 2 : 1;
int n = 1;
for (auto&& file : params.files_) {
// If extracting to stdout then ignore verbose
if (params.verbose_ && !(params.action_ & Action::extract && params.target_ & Params::ctStdInOut)) {
@ -248,25 +248,6 @@ void Params::usage(std::ostream& os) const
<< _("Image metadata manipulation tool.\n");
}
std::string Params::printTarget(const std::string &before, int target, bool bPrint, std::ostream& out)
{
std::string t;
if ( target & Params::ctExif ) t+= 'e';
if ( target & Params::ctXmpSidecar ) t+= 'X';
if ( target & Params::ctXmpRaw ) t+= target & Params::ctXmpSidecar ? 'X' : 'R' ;
if ( target & Params::ctIptc ) t+= 'i';
if ( target & Params::ctIccProfile ) t+= 'C';
if ( target & Params::ctIptcRaw ) t+= 'I';
if ( target & Params::ctXmp ) t+= 'x';
if ( target & Params::ctComment ) t+= 'c';
if ( target & Params::ctThumb ) t+= 't';
if ( target & Params::ctPreview ) t+= 'p';
if ( target & Params::ctStdInOut ) t+= '-';
if ( bPrint ) out << before << " :" << t << std::endl;
return t;
}
void Params::help(std::ostream& os) const
{
usage(os);

@ -339,10 +339,6 @@ public:
//! Print version information to an output stream.
static void version(bool verbose = false, std::ostream& os = std::cout);
//! Print target_
static std::string printTarget(const std::string& before, int target, bool bPrint = false,
std::ostream& out = std::cout);
//! getStdin binary data read from stdin to DataBuf
/*
stdin can be used by multiple images in the exiv2 command line:

@ -240,7 +240,7 @@ namespace Exiv2 {
comprehensive error messages where only a BasicIo instance is
available.
*/
virtual std::string path() const =0;
virtual const std::string& path() const noexcept =0;
/*!
@brief Mark all the bNone blocks to bKnow. This avoids allocating memory
@ -472,7 +472,7 @@ namespace Exiv2 {
//! Returns true if the file position has reached the end, otherwise false.
bool eof() const override;
//! Returns the path of the file
std::string path() const override;
const std::string& path() const noexcept override;
/*!
@brief Mark all the bNone blocks to bKnow. This avoids allocating memory
@ -654,7 +654,7 @@ namespace Exiv2 {
//!Returns true if the IO position has reached the end, otherwise false.
bool eof() const override;
//! Returns a dummy path, indicating that memory access is used
std::string path() const override;
const std::string& path() const noexcept override;
/*!
@brief Mark all the bNone blocks to bKnow. This avoids allocating memory
@ -898,7 +898,7 @@ namespace Exiv2 {
//!Returns true if the IO position has reached the end, otherwise false.
bool eof() const override;
//!Returns the URL of the file.
std::string path() const override;
const std::string& path() const noexcept override;
/*!
@brief Mark all the bNone blocks to bKnow. This avoids allocating memory
@ -1008,12 +1008,6 @@ namespace Exiv2 {
@throw Error In case of failure.
*/
EXIV2API long writeFile(const DataBuf& buf, const std::string& path);
/*!
@brief replace each substring of the subject that matches the given search string with the given replacement.
@return the subject after replacing.
*/
EXIV2API std::string ReplaceStringInPlace(std::string subject, const std::string& search,
const std::string& replace);
#ifdef EXV_USE_CURL
/*!
@brief The callback function is called by libcurl to write the data

@ -25,7 +25,8 @@
// included header files
#include "image.hpp"
#include "iostream"
#include <set>
// *****************************************************************************
// namespace extensions
@ -127,7 +128,7 @@ namespace Exiv2
//@{
void readMetadata() override /* override */;
void writeMetadata() override /* override */;
void setComment(const std::string& comment) override /* override */;
void setComment(std::string_view comment) override /* override */;
void printStructure(std::ostream& out, Exiv2::PrintStructureOption option, int depth) override;
//@}

@ -85,7 +85,7 @@ namespace Exiv2 {
void setIptcData(const IptcData& iptcData) override;
/// @throws Error(kerInvalidSettingForImage)
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -6,29 +6,8 @@
///// Start of Visual Studio Support /////
#ifdef _MSC_VER
#define _MSC_VER_2010 1600
#define _MSC_VER_2008 1500
// Constants required by Microsoft SDKs to define SHGetFolderPathA and others
#ifndef _WIN32_WINNT
// Visual Studio 2012 and earlier
# if _MSC_VER < 1800
# define _WIN32_WINNT 0x0501
# else
# define _WIN32_WINNT 0x0600
# endif
#endif
#if _MSC_VER >= _MSC_VER_2008
#pragma warning(disable : 4996) // Disable warnings about 'deprecated' standard functions
#pragma warning(disable : 4251) // Disable warnings from std templates about exporting interfaces
#endif
/* On Microsoft compilers pid_t has to be set to int. */
#ifndef HAVE_PID_T
typedef int pid_t;
#endif
#endif // _MSC_VER
///// End of Visual Studio Support /////
@ -93,16 +72,4 @@ typedef int pid_t;
#endif
//////////////////////////////////////
// https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11
#if __cplusplus >= 201103L
#include <memory>
#include <sys/types.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#endif
#endif // _CONFIG_H_

@ -81,7 +81,7 @@ namespace Exiv2 {
@brief Not supported. CR2 format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -32,11 +32,6 @@
// included header files
#include "metadatum.hpp"
// + standard includes
#include <set>
#include <vector>
#include <map>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -80,7 +80,7 @@ namespace Exiv2
@brief Not supported.
Calling this function will throw an instance of Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -34,10 +34,6 @@
// included header files
#include "types.hpp"
// + standard includes
#include <exception>
#include <string>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -63,18 +63,7 @@ namespace Exiv2
@note Source: http://www.geekhideout.com/urlcode.shtml
@todo This function can probably be hidden into the implementation details
*/
EXIV2API std::string urlencode(const char* str);
/*!
@brief Decode the input url.
@param str The url needs decoding.
@return the url-decoded version of str.
@note Be sure to 'free' the returned string after use with 'delete []'.
Source: http://www.geekhideout.com/urlcode.shtml
@todo This function can probably be hidden into the implementation details
*/
EXIV2API char* urldecode(const char* str);
EXIV2API std::string urlencode(std::string_view str);
/*!
@brief Like urlencode(char* str) but accept the input url in the std::string and modify it.
@ -125,15 +114,7 @@ namespace Exiv2
and its type, see stat(2). <b>errno</b> is left unchanged
in case of an error.
*/
EXIV2API bool fileExists(const std::string& path, bool ct = false);
/*!
@brief Get the path of file URL.
@param url The file URL in the format file:///path or file://host/path
@return the path of file URL.
*/
EXIV2API std::string pathOfFileUrl(const std::string& url);
EXIV2API bool fileExists(const std::string& path);
/*!
@brief Return a system error message and the error code (errno).

@ -86,7 +86,7 @@ namespace Exiv2 {
@brief Not supported. Calling this function will throw an instance
of Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -25,8 +25,6 @@
#include "datasets.hpp"
#include <string>
namespace Exiv2 {
/*!

@ -30,10 +30,6 @@
#include "image_types.hpp"
#include "xmp_exiv2.hpp"
// + standard includes
#include <string>
#include <vector>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {
@ -199,12 +195,10 @@ namespace Exiv2 {
writeXmpFromPacket(true) or setXmpPacket().
*/
virtual void clearXmpData();
/*!
@brief Set the image comment. The new comment is not written
to the image until the writeMetadata() method is called.
@param comment String containing comment.
*/
virtual void setComment(const std::string& comment);
/// @brief Set the image comment. The comment is written to the image when writeMetadata() is called.
virtual void setComment(std::string_view comment);
/*!
@brief Erase any buffered comment. Comment is not removed
from the actual image until the writeMetadata() method is called.

@ -32,7 +32,6 @@
#include <map>
#include <string>
#include <stdio.h>
namespace Exiv2 {

@ -80,7 +80,7 @@ namespace Exiv2
@brief Todo: Not supported yet(?). Calling this function will throw
an instance of Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -89,7 +89,7 @@ namespace Exiv2 {
@brief Not supported. MRW format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -76,7 +76,7 @@ namespace Exiv2 {
@brief Not supported. ORF format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -70,7 +70,7 @@ namespace Exiv2 {
/*!
@brief Not supported. Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -25,11 +25,6 @@
// included header files
#include "image.hpp"
#include "basicio.hpp"
#include "types.hpp"
// + standard includes
#include <string>
// *****************************************************************************
// namespace extensions
@ -87,7 +82,7 @@ namespace Exiv2 {
@brief Not supported. RAF format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -80,7 +80,7 @@ namespace Exiv2 {
@brief Not supported. RW2 format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -26,11 +26,6 @@
// included header files
#include "metadatum.hpp"
// + standard includes
#include <string>
#include <iosfwd>
#include <memory>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -86,7 +86,7 @@ namespace Exiv2 {
@brief Not supported. Calling this function will throw an instance
of Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -77,7 +77,7 @@ namespace Exiv2 {
@brief Not supported. TIFF format does not contain a comment.
Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -27,13 +27,11 @@
#include "slice.hpp"
// + standard includes
#include <cstdint>
#include <string>
#include <vector>
#include <limits>
#include <algorithm>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
/*!
@brief Macro to make calls to member functions through a pointer more readable.
@ -42,12 +40,6 @@
*/
#define EXV_CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
#ifndef _MSC_VER
#define EXV_UNUSED [[gnu::unused]]
#else
#define EXV_UNUSED
#endif
// *****************************************************************************
// forward declarations
struct tm;
@ -576,11 +568,6 @@ namespace Exiv2 {
// This is abs() - given the existence of broken compilers with Koenig
// lookup issues and other problems, I code this explicitly. (Remember,
// IntType may be a user-defined type).
#ifdef _MSC_VER
#pragma warning( disable : 4146 )
#undef max
#undef min
#endif
if (n < zero) {
if (n == std::numeric_limits<IntType>::min()) {
n = std::numeric_limits<IntType>::max();
@ -590,9 +577,6 @@ namespace Exiv2 {
}
if (m < zero)
m = -m;
#ifdef _MSC_VER
#pragma warning( default : 4146 )
#endif
// As n and m are now positive, we can be sure that %= returns a
// positive value (the standard guarantees this for built-in types,

@ -27,11 +27,9 @@
#include "types.hpp"
// + standard includes
#include <map>
#include <iomanip>
#include <memory>
#include <cstring>
#include <climits>
#include <iomanip>
#include <map>
// *****************************************************************************
// namespace extensions

@ -65,7 +65,7 @@ namespace Exiv2 {
/*!
@brief Not supported. Calling this function will throw an Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
void setIptcData(const IptcData& /*iptcData*/) override;
//! @name Accessors

@ -64,7 +64,7 @@ namespace Exiv2 {
@brief Not supported. XMP sidecar files do not contain a comment.
Calling this function will throw an instance of Error(kerInvalidSettingForImage).
*/
void setComment(const std::string& comment) override;
void setComment(std::string_view comment) override;
//@}
//! @name Accessors

@ -36,6 +36,7 @@ add_library( exiv2lib_int OBJECT
tifffwd_int.hpp
timegm.h
unused.h
utils.hpp utils.cpp
)
set(PUBLIC_HEADERS

@ -34,18 +34,22 @@
#include "image_int.hpp"
// + standard includes
#include <string>
#include <memory>
#include <iostream>
#include <cstring> // std::memcpy
#include <fcntl.h> // _O_BINARY in FileIo::FileIo
#include <sys/stat.h> // for stat, chmod
#include <sys/types.h> // for stat, chmod
#include <cassert>
#include <fstream> // write the temporary file
#include <fcntl.h> // _O_BINARY in FileIo::FileIo
#include <cstdio> // for remove, rename
#include <cstdlib> // for alloc, realloc, free
#include <ctime> // timestamp for the name of temporary file
#include <sys/types.h> // for stat, chmod
#include <sys/stat.h> // for stat, chmod
#include <cstdio> // for remove, rename
#include <cstdlib> // for alloc, realloc, free
#include <cstring> // std::memcpy
#include <ctime> // timestamp for the name of temporary file
#include <filesystem>
#include <fstream> // write the temporary file
#include <iostream>
#include <memory>
#include <string>
namespace fs = std::filesystem;
#ifdef EXV_HAVE_SYS_MMAN_H
# include <sys/mman.h> // for mmap and munmap
@ -63,20 +67,25 @@
#define mode_t unsigned short
// Platform specific headers for handling extended attributes (xattr)
#if defined(__APPLE__)
# include <sys/xattr.h>
#endif
#if defined(__MINGW__) || (defined(WIN32) && !defined(__CYGWIN__))
// Windows doesn't provide nlink_t
using nlink_t = short;
# include <windows.h>
# include <io.h>
#endif
// *****************************************************************************
// class member definitions
namespace {
/// @brief replace each substring of the subject that matches the given search string with the given replacement.
void ReplaceStringInPlace(std::string& subject, const std::string& search, const std::string& replace)
{
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
}
}
namespace Exiv2 {
void BasicIo::readOrThrow(byte* buf, long rcount, ErrorCode err) {
const long nread = read(buf, rcount);
@ -117,7 +126,6 @@ namespace Exiv2 {
StructStat() = default;
mode_t st_mode{0}; //!< Permissions
off_t st_size{0}; //!< Size
nlink_t st_nlink{0}; //!< Number of hard links (broken on Windows, see winNumberOfLinks())
};
// #endif
// METHODS
@ -130,12 +138,6 @@ namespace Exiv2 {
int switchMode(OpMode opMode);
//! stat wrapper for internal use
int stat(StructStat& buf) const;
//! copy extended attributes (xattr) from another file
void copyXattrFrom(const FileIo& src);
#if defined WIN32 && !defined __CYGWIN__
// Windows function to determine the number of hardlinks (on NTFS)
DWORD winNumberOfLinks() const;
#endif
// NOT IMPLEMENTED
Impl(const Impl& rhs) = delete; //!< Copy constructor
Impl& operator=(const Impl& rhs) = delete; //!< Assignment
@ -211,96 +213,11 @@ namespace Exiv2 {
ret = ::stat(path_.c_str(), &st);
if (0 == ret) {
buf.st_size = st.st_size;
buf.st_nlink = st.st_nlink;
buf.st_mode = st.st_mode;
}
return ret;
} // FileIo::Impl::stat
#if defined(__APPLE__)
void FileIo::Impl::copyXattrFrom(const FileIo& src)
#else
void FileIo::Impl::copyXattrFrom(const FileIo&)
#endif
{
#if defined(__APPLE__)
ssize_t namebufSize = ::listxattr(src.p_->path_.c_str(), 0, 0, 0);
if (namebufSize < 0) {
throw Error(kerCallFailed, src.p_->path_, strError(), "listxattr");
}
if (namebufSize == 0) {
// No extended attributes in source file
return;
}
char* namebuf = new char[namebufSize];
if (::listxattr(src.p_->path_.c_str(), namebuf, namebufSize, 0) != namebufSize) {
throw Error(kerCallFailed, src.p_->path_, strError(), "listxattr");
}
for (ssize_t namebufPos = 0; namebufPos < namebufSize;) {
const char *name = namebuf + namebufPos;
namebufPos += strlen(name) + 1;
const ssize_t valueSize = ::getxattr(src.p_->path_.c_str(), name, 0, 0, 0, 0);
if (valueSize < 0) {
throw Error(kerCallFailed, src.p_->path_, strError(), "getxattr");
}
char* value = new char[valueSize];
if (::getxattr(src.p_->path_.c_str(), name, value, valueSize, 0, 0) != valueSize) {
throw Error(kerCallFailed, src.p_->path_, strError(), "getxattr");
}
// #906. Mountain Lion 'sandbox' terminates the app when we call setxattr
#ifndef __APPLE__
#ifdef EXIV2_DEBUG_MESSAGES
EXV_DEBUG << "Copying xattr \"" << name << "\" with value size " << valueSize << "\n";
#endif
if (::setxattr(path_.c_str(), name, value, valueSize, 0, 0) != 0) {
throw Error(kerCallFailed, path_, strError(), "setxattr");
}
delete [] value;
#endif
}
delete [] namebuf;
#else
// No xattr support for this platform.
#endif
} // FileIo::Impl::copyXattrFrom
#if defined WIN32 && !defined __CYGWIN__
DWORD FileIo::Impl::winNumberOfLinks() const
{
DWORD nlink = 1;
HANDLE hFd = (HANDLE)_get_osfhandle(fileno(fp_));
if (hFd != INVALID_HANDLE_VALUE) {
using GetFileInformationByHandle_t = BOOL(WINAPI*)(HANDLE, LPBY_HANDLE_FILE_INFORMATION);
HMODULE hKernel = ::GetModuleHandleA("kernel32.dll");
if (hKernel) {
GetFileInformationByHandle_t pfcn_GetFileInformationByHandle = (GetFileInformationByHandle_t)GetProcAddress(hKernel, "GetFileInformationByHandle");
if (pfcn_GetFileInformationByHandle) {
BY_HANDLE_FILE_INFORMATION fi = {0,0,0,0,0,0,0,0,0,0,0,0,0};
if (pfcn_GetFileInformationByHandle(hFd, &fi)) {
nlink = fi.nNumberOfLinks;
}
#ifdef EXIV2_DEBUG_MESSAGES
else EXV_DEBUG << "GetFileInformationByHandle failed\n";
#endif
}
#ifdef EXIV2_DEBUG_MESSAGES
else EXV_DEBUG << "GetProcAddress(hKernel, \"GetFileInformationByHandle\") failed\n";
#endif
}
#ifdef EXIV2_DEBUG_MESSAGES
else EXV_DEBUG << "GetModuleHandleA(\"kernel32.dll\") failed\n";
#endif
}
#ifdef EXIV2_DEBUG_MESSAGES
else EXV_DEBUG << "_get_osfhandle failed: INVALID_HANDLE_VALUE\n";
#endif
return nlink;
} // FileIo::Impl::winNumberOfLinks
#endif // defined WIN32 && !defined __CYGWIN__
FileIo::FileIo(const std::string& path)
: p_(new Impl(path))
{
@ -435,10 +352,10 @@ namespace Exiv2 {
byte buf[4096];
long readCount = 0;
long writeCount = 0;
long writeTotal = 0;
while ((readCount = src.read(buf, sizeof(buf)))) {
writeTotal += writeCount = static_cast<long>(std::fwrite(buf, 1, readCount, p_->fp_));
long writeCount = static_cast<long>(std::fwrite(buf, 1, readCount, p_->fp_));
writeTotal += writeCount;
if (writeCount != readCount) {
// try to reset back to where write stopped
src.seek(writeCount-readCount, BasicIo::cur);
@ -460,56 +377,21 @@ namespace Exiv2 {
fileIo->close();
// Check if the file can be written to, if it already exists
if (open("a+b") != 0) {
/// \todo Use std::filesystem once C++17 can be used
// Remove the (temporary) file
::remove(fileIo->path().c_str());
fs::remove(fileIo->path().c_str());
throw Error(kerFileOpenFailed, path(), "a+b", strError());
}
close();
bool statOk = true;
mode_t origStMode = 0;
std::string spf;
char* pf = nullptr;
spf = path();
pf = const_cast<char*>(spf.c_str());
auto pf = path().c_str();
// Get the permissions of the file, or linked-to file, on platforms which have lstat
#ifdef EXV_HAVE_LSTAT
struct stat buf1;
if (::lstat(pf, &buf1) == -1) {
statOk = false;
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << Error(kerCallFailed, pf, strError(), "::lstat") << "\n";
#endif
}
origStMode = buf1.st_mode;
DataBuf lbuf; // So that the allocated memory is freed. Must have same scope as pf
// In case path() is a symlink, get the path of the linked-to file
if (statOk && S_ISLNK(buf1.st_mode)) {
lbuf.alloc(buf1.st_size + 1);
lbuf.clear();
pf = reinterpret_cast<char*>(lbuf.data());
if (::readlink(path().c_str(), pf, lbuf.size() - 1) == -1) {
throw Error(kerCallFailed, path(), strError(), "readlink");
}
// We need the permissions of the file, not the symlink
if (::stat(pf, &buf1) == -1) {
statOk = false;
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << Error(kerCallFailed, pf, strError(), "::stat") << "\n";
#endif
}
origStMode = buf1.st_mode;
}
#else // EXV_HAVE_LSTAT
Impl::StructStat buf1;
if (p_->stat(buf1) == -1) {
statOk = false;
}
origStMode = buf1.st_mode;
#endif // !EXV_HAVE_LSTAT
{
#if defined(WIN32) && defined(REPLACEFILE_IGNORE_MERGE_ERRORS)
@ -526,10 +408,8 @@ namespace Exiv2 {
BOOL ret = pfcn_ReplaceFileA(pf, fileIo->path().c_str(), NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL);
if (ret == 0) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
if (::rename(fileIo->path().c_str(), pf) == -1) {
throw Error(kerFileRenameFailed, fileIo->path(), pf, strError());
}
::remove(fileIo->path().c_str());
fs::rename(fileIo->path().c_str(), pf);
fs::remove(fileIo->path().c_str());
}
else {
throw Error(kerFileRenameFailed, fileIo->path(), pf, strError());
@ -538,22 +418,18 @@ namespace Exiv2 {
}
else {
if (fileExists(pf) && ::remove(pf) != 0) {
throw Error(kerCallFailed, pf, strError(), "::remove");
}
if (::rename(fileIo->path().c_str(), pf) == -1) {
throw Error(kerFileRenameFailed, fileIo->path(), pf, strError());
throw Error(kerCallFailed, pf, strError(), "fs::remove");
}
::remove(fileIo->path().c_str());
fs::rename(fileIo->path().c_str(), pf);
fs::remove(fileIo->path().c_str());
}
}
#else
if (fileExists(pf) && ::remove(pf) != 0) {
throw Error(kerCallFailed, pf, strError(), "::remove");
if (fileExists(pf) && fs::remove(pf) != 0) {
throw Error(kerCallFailed, pf, strError(), "fs::remove");
}
if (::rename(fileIo->path().c_str(), pf) == -1) {
throw Error(kerFileRenameFailed, fileIo->path(), pf, strError());
}
::remove(fileIo->path().c_str());
fs::rename(fileIo->path().c_str(), pf);
fs::remove(fileIo->path().c_str());
#endif
// Check permissions of new file
struct stat buf2;
@ -720,7 +596,7 @@ namespace Exiv2 {
return std::feof(p_->fp_) != 0;
}
std::string FileIo::path() const
const std::string& FileIo::path() const noexcept
{
return p_->path_;
}
@ -802,18 +678,17 @@ namespace Exiv2 {
{
return type_ == bNone;
}
bool isInMem () const
{
return type_ == bMemory;
}
bool isKnown () const
{
return type_ == bKnown;
}
byte* getData () const
{
return data_;
}
size_t getSize () const
{
return size_;
@ -1044,9 +919,10 @@ namespace Exiv2 {
return p_->eof_;
}
std::string MemIo::path() const
const std::string& MemIo::path() const noexcept
{
return "MemIo";
static std::string _path{"MemIo"};
return _path;
}
void MemIo::populateFakeData() {
@ -1107,7 +983,7 @@ namespace Exiv2 {
}
XPathIo::~XPathIo() {
if (isTemp_ && remove(tempFilePath_.c_str()) != 0) {
if (isTemp_ && !fs::remove(tempFilePath_)) {
// error when removing file
// printf ("Warning: Unable to remove the temp file %s.\n", tempFilePath_.c_str());
}
@ -1116,13 +992,12 @@ namespace Exiv2 {
void XPathIo::transfer(BasicIo& src) {
if (isTemp_) {
// replace temp path to gent path.
std::string currentPath = path();
setPath(ReplaceStringInPlace(currentPath, XPathIo::TEMP_FILE_EXT, XPathIo::GEN_FILE_EXT));
// rename the file
auto currentPath = path();
ReplaceStringInPlace(currentPath, XPathIo::TEMP_FILE_EXT, XPathIo::GEN_FILE_EXT);
setPath(currentPath);
tempFilePath_ = path();
if (rename(currentPath.c_str(), tempFilePath_.c_str()) != 0) {
// printf("Warning: Failed to rename the temp file. \n");
}
fs::rename(currentPath, tempFilePath_);
isTemp_ = false;
// call super class method
FileIo::transfer(src);
@ -1371,21 +1246,18 @@ namespace Exiv2 {
size_t left = 0;
size_t right = 0;
size_t blockIndex = 0;
size_t i = 0;
size_t readCount = 0;
size_t blockSize = 0;
auto buf = new byte [p_->blockSize_];
std::vector<byte> buf(p_->blockSize_);
size_t nBlocks = (p_->size_ + p_->blockSize_ - 1) / p_->blockSize_;
// find $left
src.seek(0, BasicIo::beg);
bool findDiff = false;
while (blockIndex < nBlocks && !src.eof() && !findDiff) {
blockSize = p_->blocksMap_[blockIndex].getSize();
size_t blockSize = p_->blocksMap_[blockIndex].getSize();
bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data
readCount = static_cast<size_t>(src.read(buf, static_cast<long>(blockSize)));
size_t readCount = static_cast<size_t>(src.read(buf.data(), static_cast<long>(blockSize)));
byte* blockData = p_->blocksMap_[blockIndex].getData();
for (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)) {
findDiff = true;
} else {
@ -1400,14 +1272,14 @@ namespace Exiv2 {
blockIndex = nBlocks;
while (blockIndex > 0 && right < src.size() && !findDiff) {
blockIndex--;
blockSize = p_->blocksMap_[blockIndex].getSize();
size_t blockSize = p_->blocksMap_[blockIndex].getSize();
if(src.seek(-1 * (blockSize + right), BasicIo::end)) {
findDiff = true;
} else {
bool isFakeData = p_->blocksMap_[blockIndex].isKnown(); // fake data
readCount = src.read(buf, static_cast<long>(blockSize));
size_t readCount = src.read(buf.data(), static_cast<long>(blockSize));
byte* blockData = p_->blocksMap_[blockIndex].getData();
for (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)) {
findDiff = true;
} else {
@ -1417,8 +1289,6 @@ namespace Exiv2 {
}
}
delete []buf;
// submit to the remote machine.
long dataSize = static_cast<long>(src.size() - left - right);
if (dataSize > 0) {
@ -1585,7 +1455,7 @@ namespace Exiv2 {
return p_->eof_;
}
std::string RemoteIo::path() const
const std::string& RemoteIo::path() const noexcept
{
return p_->path_;
}
@ -1989,15 +1859,6 @@ namespace Exiv2 {
return file.write(buf.c_data(), buf.size());
}
std::string ReplaceStringInPlace(std::string subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
#ifdef EXV_USE_CURL
size_t curlWriter(char* data, size_t size, size_t nmemb,

@ -627,11 +627,11 @@ namespace Exiv2
}
}
void BmffImage::setComment(const std::string& /*comment*/)
void BmffImage::setComment(std::string_view /*comment*/)
{
// bmff files are read-only
throw(Error(kerInvalidSettingForImage, "Image comment", "BMFF"));
} // BmffImage::setComment
}
void BmffImage::openOrThrow()
{

@ -61,7 +61,7 @@ namespace Exiv2
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "BMP"));
}
void BmpImage::setComment(const std::string& /*comment*/)
void BmpImage::setComment(std::string_view /*comment*/)
{
throw(Error(kerInvalidSettingForImage, "Image comment", "BMP"));
}

@ -437,7 +437,7 @@ namespace Exiv2 {
// Categories, tag 0x0023
EXV_UNUSED constexpr TagDetails canonCategories[] = {
[[maybe_unused]] constexpr TagDetails canonCategories[] = {
{ 0x0001, N_("People") },
{ 0x0002, N_("Scenery") },
{ 0x0004, N_("Events") },
@ -2110,7 +2110,7 @@ namespace Exiv2 {
};
//! ManualFlashOutput, tag 0x0029
EXV_UNUSED constexpr TagDetails canonCsManualFlashOutput[] = {
[[maybe_unused]] constexpr TagDetails canonCsManualFlashOutput[] = {
{ 0x0000, N_("n/a") },
{ 0x0500, N_("Full") },
{ 0x0502, N_("Medium") },

@ -37,11 +37,6 @@
#include "tags.hpp"
#include "types.hpp"
// + standard includes
#include <string>
#include <iosfwd>
#include <memory>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -33,10 +33,6 @@
#include "tags.hpp"
#include "types.hpp"
// + standard includes
#include <string>
#include <iosfwd>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -37,13 +37,14 @@
#include "unused.h"
// + standard includes
#include <utility>
#include <iostream>
#include <stdio.h> // for snprintf (C99)
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <ios>
#include <iostream>
#include <sstream>
#include <stdio.h> // for snprintf (C99)
#include <cstring>
#include <utility>
#if defined WIN32 && !defined __CYGWIN__
# include <windows.h>
@ -284,8 +285,6 @@ namespace Exiv2 {
//@{
//! Get the value of the erase flag, see also setErase(bool on).
bool erase() const { return erase_; }
//! Get the value of the overwrite flag, see also setOverwrite(bool on).
bool overwrite() const { return overwrite_; }
//@}
private:
@ -293,7 +292,6 @@ namespace Exiv2 {
bool prepareIptcTarget(const char* to, bool force =false);
bool prepareXmpTarget(const char* to, bool force =false);
std::string computeExifDigest(bool tiff);
std::string computeIptcDigest();
// DATA
static const Conversion conversion_[]; //<! Conversion rules
@ -1084,7 +1082,6 @@ namespace Exiv2 {
else {
sec = (min - static_cast<int>(min)) * 60.0;
min = static_cast<double>(static_cast<int>(min));
sep2 = ',';
}
if ( in.bad() || !(ref == 'N' || ref == 'S' || ref == 'E' || ref == 'W')
@ -1256,28 +1253,6 @@ namespace Exiv2 {
writeExifDigest();
}
std::string Converter::computeIptcDigest()
{
#ifdef EXV_HAVE_XMP_TOOLKIT
std::ostringstream res;
MD5_CTX context;
unsigned char digest[16];
MD5Init(&context);
DataBuf data = IptcParser::encode(*iptcData_);
MD5Update(&context, data.c_data(), data.size());
MD5Final(digest, &context);
res << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
for (auto&& i : digest) {
res << static_cast<int>(i);
}
return res.str();
#else
return std::string("");
#endif
}
// *************************************************************************
// free functions
@ -1288,6 +1263,7 @@ namespace Exiv2 {
converter.cnvToXmp();
}
/// \todo not used internally. We should at least have unit tests for this.
void moveExifToXmp(ExifData& exifData, XmpData& xmpData)
{
Converter converter(exifData, xmpData);
@ -1301,6 +1277,7 @@ namespace Exiv2 {
converter.cnvFromXmp();
}
/// \todo not used internally. We should at least have unit tests for this.
void moveXmpToExif(XmpData& xmpData, ExifData& exifData)
{
Converter converter(exifData, xmpData);
@ -1323,6 +1300,7 @@ namespace Exiv2 {
converter.cnvToXmp();
}
/// \todo not used internally. We should at least have unit tests for this.
void moveIptcToXmp(IptcData& iptcData, XmpData& xmpData, const char *iptcCharset)
{
if (!iptcCharset) iptcCharset = iptcData.detectCharset();
@ -1338,6 +1316,7 @@ namespace Exiv2 {
converter.cnvFromXmp();
}
/// \todo not used internally. We should at least have unit tests for this.
void moveXmpToIptc(XmpData& xmpData, IptcData& iptcData)
{
Converter converter(iptcData, xmpData);

@ -81,7 +81,7 @@ namespace Exiv2 {
printTiffStructure(io(),out,option,depth-1);
}
void Cr2Image::setComment(const std::string& /*comment*/)
void Cr2Image::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "CR2"));

@ -147,9 +147,6 @@ namespace Exiv2 {
// Parse the image, starting with a CIFF header component
CiffHeader header;
header.read(pData, size);
#ifdef EXIV2_DEBUG_MESSAGES
header.print(std::cerr);
#endif
header.decode(*pCrwImage);
// a hack to get absolute offset of preview image inside CRW structure

@ -21,13 +21,13 @@
#include "crwimage_int.hpp"
#include "canonmn_int.hpp"
#include "i18n.h" // NLS support.
#include "timegm.h"
#include "unused.h"
#include "error.hpp"
#include "enforce.hpp"
#include <cassert>
#include <ctime>
#include <iostream>
// *****************************************************************************
// local declarations
@ -53,7 +53,6 @@ namespace {
// *****************************************************************************
// local definitions
namespace {
//! @cond IGNORE
constexpr RotationMap::OmList RotationMap::omList_[] = {
{ 1, 0 },
{ 3, 180 },
@ -87,7 +86,6 @@ namespace {
}
return d;
}
//! @endcond
} // namespace
namespace Exiv2 {
@ -503,16 +501,6 @@ namespace Exiv2 {
}
} // CiffComponent::writeDirEntry
void CiffHeader::print(std::ostream& os, const std::string& prefix) const
{
std::ios::fmtflags f( os.flags() );
os << prefix
<< _("Header, offset") << " = 0x" << std::setw(8) << std::setfill('0')
<< std::hex << std::right << offset_ << "\n";
if (pRootDir_) pRootDir_->print(os, byteOrder_, prefix);
os.flags(f);
} // CiffHeader::print
void CiffComponent::print(std::ostream& os,
ByteOrder byteOrder,
const std::string& prefix) const
@ -617,10 +605,10 @@ namespace Exiv2 {
CiffComponent* CiffDirectory::doFindComponent(uint16_t crwTagId,
uint16_t crwDir) const
{
CiffComponent* cc;
for (auto&& component : components_) {
cc = component->findComponent(crwTagId, crwDir);
if (cc) return cc;
auto cc = component->findComponent(crwTagId, crwDir);
if (cc)
return cc;
}
return nullptr;
} // CiffDirectory::doFindComponent

@ -26,8 +26,6 @@
#include "image.hpp"
// + standard includes
#include <iosfwd>
#include <string>
#include <vector>
#include <stack>
@ -481,13 +479,7 @@ namespace Exiv2 {
@param image Image to add metadata to
*/
void decode(Image& image) const;
/*!
@brief Print debug info for the CRW image to \em os.
@param os Output stream to write to.
@param prefix Prefix to be written before each line of output.
*/
void print(std::ostream& os, const std::string& prefix ="") const;
//! Return the byte order (little or big endian).
ByteOrder byteOrder() const { return byteOrder_; }
/*!

@ -32,6 +32,7 @@
#include "basicio.hpp"
#include "error.hpp"
#include "futils.hpp"
#include "utils.hpp"
#include "version.hpp"
// + standard includes
@ -103,11 +104,6 @@ namespace {
// closing part of all valid XMP trailers
const std::string xmpTrailerEnd = "?>";
constexpr bool startsWith(const std::string_view& s, const std::string_view& start)
{
return s.find(start) == 0;
}
//! Write data into temp file, taking care of errors
void writeTemp(BasicIo& tempIo, const byte* data, size_t size)
{
@ -1098,7 +1094,7 @@ namespace Exiv2
return "application/postscript";
}
void EpsImage::setComment(const std::string& /*comment*/)
void EpsImage::setComment(std::string_view /*comment*/)
{
throw Error(kerInvalidSettingForImage, "Image comment", "EPS");
}

@ -24,7 +24,6 @@
// *****************************************************************************
// included header files
#include "tags.hpp"
#include "types.hpp"
// *****************************************************************************
// namespace extensions

@ -27,19 +27,23 @@
#include "image_int.hpp"
// + standard includes
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <algorithm>
#include <array>
#include <cstdio>
#include <cerrno>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <filesystem>
#include <sstream>
#include <stdexcept>
#ifdef EXV_HAVE_UNISTD_H
#include <unistd.h> // for stat()
#ifdef EXV_HAVE_UNISTD_H
#include <unistd.h> // for stat()
#endif
namespace fs = std::filesystem;
#if defined(WIN32)
#include <windows.h>
#include <psapi.h> // For access to GetModuleFileNameEx
@ -101,52 +105,43 @@ namespace Exiv2 {
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
std::string urlencode(const char* str) {
const char* pstr = str;
// \todo try to use std::string for buf and avoid the creation of another string for just
// returning the final value
auto buf = new char[strlen(str) * 3 + 1];
char* pbuf = buf;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if (*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
std::string urlencode(std::string_view str)
{
std::string encoded;
encoded.reserve(str.size() * 3);
for (uint8_t c : str) {
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
encoded += c;
else if (c == ' ')
encoded += '+';
else {
encoded += '%';
encoded += to_hex(c >> 4);
encoded += to_hex(c & 15);
}
}
*pbuf = '\0';
std::string ret(buf);
delete [] buf;
return ret;
encoded.shrink_to_fit();
return encoded;
}
char* urldecode(const char* str) {
const char* pstr = str;
auto buf = new char[(strlen(str) + 1)];
char* pbuf = buf;
while (*pstr) {
if (*pstr == '%') {
if (pstr[1] && pstr[2]) {
*pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
pstr += 2;
void urldecode(std::string& str)
{
size_t idxIn{0}, idxOut{0};
size_t sizeStr = str.size();
while (idxIn < sizeStr) {
if (str[idxIn] == '%') {
if (str[idxIn+1] && str[idxIn+2]) {
str[idxOut++] = from_hex(str[idxIn+1]) << 4 | from_hex(str[idxIn+2]);
idxIn += 2;
}
} else if (*pstr == '+') {
*pbuf++ = ' ';
} else if (str[idxIn] == '+') {
str[idxOut++] = ' ';
} else {
*pbuf++ = *pstr;
str[idxOut++] = str[idxIn];
}
pstr++;
idxIn++;
}
*pbuf = '\0';
return buf;
}
void urldecode(std::string& str) {
char* decodeStr = Exiv2::urldecode(str.c_str());
str = std::string(decodeStr);
delete [] decodeStr;
str.erase(idxOut);
}
// https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
@ -157,7 +152,6 @@ namespace Exiv2 {
int base64encode(const void* data_buf, size_t dataLength, char* result, size_t resultSize) {
auto encoding_table = base64_encode;
size_t mod_table[] = {0, 2, 1};
size_t output_length = 4 * ((dataLength + 2) / 3);
int rc = result && data_buf && output_length < resultSize ? 1 : 0;
@ -177,6 +171,7 @@ namespace Exiv2 {
result[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
}
const size_t mod_table[] = {0, 2, 1};
for (size_t i = 0; i < mod_table[dataLength % 3]; i++)
result[output_length - 1 - i] = '=';
result[output_length]=0;
@ -252,25 +247,12 @@ namespace Exiv2 {
return result;
} // fileProtocol
bool fileExists(const std::string& path, bool ct)
bool fileExists(const std::string& path)
{
// special case: accept "-" (means stdin)
if (path == "-" || fileProtocol(path) != pFile) {
if (fileProtocol(path) != pFile) {
return true;
}
struct stat buf;
int ret = ::stat(path.c_str(), &buf);
if (0 != ret) return false;
if (ct && !S_ISREG(buf.st_mode)) return false;
return true;
} // fileExists
std::string pathOfFileUrl(const std::string& url) {
std::string path = url.substr(7);
size_t found = path.find('/');
if (found == std::string::npos) return path;
return path.substr(found);
return fs::exists(path);
}
std::string strError()

@ -58,7 +58,7 @@ namespace Exiv2 {
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "GIF"));
}
void GifImage::setComment(const std::string& /*comment*/)
void GifImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "GIF"));

@ -239,8 +239,6 @@ int Exiv2::http(Exiv2::Dictionary& request,Exiv2::Dictionary& response,std::stri
servername_p = Proxy.Host.c_str();
port_p = Proxy.Port.c_str();
page = url.c_str();
std::string p(proxy?proxi:PROXI);
// std::cerr << p << '=' << prox << " page = " << page << std::endl;
}
if ( !port [0] ) port = "80";
if ( !port_p[0] ) port_p = "80";

@ -135,6 +135,12 @@ namespace {
{ ImageType::none, nullptr, nullptr, amNone, amNone, amNone, amNone }
};
std::string pathOfFileUrl(const std::string& url) {
std::string path = url.substr(7);
size_t found = path.find('/');
return (found == std::string::npos) ? path : path.substr(found);
}
} // namespace
// *****************************************************************************
@ -278,6 +284,7 @@ namespace Exiv2 {
return Image::byteSwap(v,bSwap);
}
/// \todo not used internally. At least we should test it
uint64_t Image::byteSwap8(const DataBuf& buf,size_t offset,bool bSwap)
{
uint64_t v = 0;
@ -367,7 +374,6 @@ namespace Exiv2 {
// Break for unknown tag types else we may segfault.
if ( !typeValid(type) ) {
EXV_ERROR << "invalid type in tiff structure" << type << std::endl;
start = 0; // break from do loop
throw Error(kerInvalidTypeValue);
}
@ -519,7 +525,6 @@ namespace Exiv2 {
out << Internal::indent(depth) << "END " << io.path() << std::endl;
}
out.flush();
depth--;
}
void Image::printTiffStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,int depth,size_t offset /*=0*/)
@ -576,6 +581,7 @@ namespace Exiv2 {
return xmpPacket_;
}
/// \todo not used internally. At least we should test it
void Image::setMetadata(const Image& image)
{
if (checkMode(mdExif) & amWrite) {
@ -624,7 +630,6 @@ namespace Exiv2 {
void Image::setXmpPacket(const std::string& xmpPacket)
{
xmpPacket_ = xmpPacket;
if ( XmpParser::decode(xmpData_, xmpPacket) ) {
throw Error(kerInvalidXMP);
}
@ -657,7 +662,7 @@ namespace Exiv2 {
comment_.erase();
}
void Image::setComment(const std::string& comment)
void Image::setComment(std::string_view comment)
{
comment_ = comment;
}
@ -749,6 +754,7 @@ namespace Exiv2 {
return ImageFactory::checkType(imageType_, *io_, false);
}
/// \todo not used internally. At least we should test it
bool Image::supportsMetadata(MetadataId metadataId) const
{
return (supportedMetadata_ & metadataId) != 0;

@ -57,52 +57,6 @@ namespace Exiv2
return result;
}
std::string binaryToHex(const byte* data, size_t size)
{
std::stringstream hexOutput;
auto tl = size_t(size / 16) * 16;
auto tl_offset = size_t(size) - tl;
for (size_t loop = 0; loop < size; loop++) {
if (data[loop] < 16) {
hexOutput << "0";
}
hexOutput << std::hex << static_cast<int>(data[loop]);
if ((loop % 8) == 7) {
hexOutput << " ";
}
if ((loop % 16) == 15 || loop == (tl + tl_offset - 1)) {
int max = 15;
if (loop >= tl) {
max = int(tl_offset) - 1;
for (int offset = 0; offset < int(16 - tl_offset); offset++) {
if ((offset % 8) == 7) {
hexOutput << " ";
}
hexOutput << " ";
}
}
hexOutput << " ";
for (int offset = max; offset >= 0; offset--) {
if (offset == (max - 8)) {
hexOutput << " ";
}
byte c = '.';
if (data[loop - offset] >= 0x20 && data[loop - offset] <= 0x7E) {
c = data[loop - offset];
}
hexOutput << static_cast<char>(c);
}
hexOutput << std::endl;
}
}
hexOutput << std::endl << std::endl << std::endl;
return hexOutput.str();
}
std::string indent(int32_t d)
{
std::string result;

@ -120,14 +120,7 @@ namespace Exiv2 {
return binaryToStringHelper<T>(sl);
}
/*!
@brief format binary for display of raw data .
*/
std::string binaryToHex(const byte *data, size_t size);
/*!
@brief indent output for kpsRecursive in \em printStructure() \em .
*/
/// @brief indent output for kpsRecursive in \em printStructure() \em .
std::string indent(int32_t depth);
}} // namespace Internal, Exiv2

@ -327,11 +327,13 @@ namespace Exiv2 {
FindIptcdatum(dataset, record));
}
/// \todo not used internally. At least we should test it
void IptcData::sortByKey()
{
std::sort(iptcMetadata_.begin(), iptcMetadata_.end(), cmpMetadataByKey);
}
/// \todo not used internally. At least we should test it
void IptcData::sortByTag()
{
std::sort(iptcMetadata_.begin(), iptcMetadata_.end(), cmpMetadataByTag);
@ -350,8 +352,7 @@ namespace Exiv2 {
size_t i = 0;
while (i < bytes.size() - 3 && bytes.at(i) != 0x1c)
i++;
depth++;
out << Internal::indent(depth) << "Record | DataSet | Name | Length | Data" << std::endl;
out << Internal::indent(++depth) << "Record | DataSet | Name | Length | Data" << std::endl;
while (i < bytes.size() - 3) {
if (bytes.at(i) != 0x1c) {
break;
@ -370,7 +371,6 @@ namespace Exiv2 {
<< std::endl;
i += 5 + len;
}
depth--;
}
const char *IptcData::detectCharset() const

@ -158,11 +158,11 @@ namespace Exiv2
return "image/jp2";
}
void Jp2Image::setComment(const std::string& /*comment*/)
void Jp2Image::setComment(std::string_view /*comment*/)
{
// Todo: implement me!
throw(Error(kerInvalidSettingForImage, "Image comment", "JP2"));
} // Jp2Image::setComment
}
static void lf(std::ostream& out,bool& bLF)
{
@ -221,7 +221,6 @@ static void boxes_check(size_t b,size_t m)
throw Error(kerNotAnImage, "JPEG-2000");
}
long position = 0;
Jp2BoxHeader box = {0,0};
Jp2BoxHeader subBox = {0,0};
Jp2ImageHeaderBox ihdr = {0,0,0,0,0,0,0,0};
@ -231,7 +230,7 @@ static void boxes_check(size_t b,size_t m)
while (io_->read(reinterpret_cast<byte*>(&box), sizeof(box)) == sizeof(box)) {
boxes_check(boxes++,boxem );
position = io_->tell();
long position = io_->tell();
box.length = getLong(reinterpret_cast<byte*>(&box.length), bigEndian);
box.type = getLong(reinterpret_cast<byte*>(&box.type), bigEndian);
#ifdef EXIV2_DEBUG_MESSAGES
@ -490,7 +489,6 @@ static void boxes_check(size_t b,size_t m)
if ( bPrint || bXMP || bICC || bIPTCErase ) {
long position = 0;
Jp2BoxHeader box = {1,1};
Jp2BoxHeader subBox = {1,1};
Jp2UuidBox uuid = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
@ -498,7 +496,7 @@ static void boxes_check(size_t b,size_t m)
while (box.length && box.type != kJp2BoxTypeClose &&
io_->read(reinterpret_cast<byte*>(&box), sizeof(box)) == sizeof(box)) {
position = io_->tell();
long position = io_->tell();
box.length = getLong(reinterpret_cast<byte*>(&box.length), bigEndian);
box.type = getLong(reinterpret_cast<byte*>(&box.type), bigEndian);
enforce(box.length <= sizeof(box)+io_->size()-io_->tell() , Exiv2::kerCorruptedMetadata);

@ -32,11 +32,15 @@
#include "tiffvisitor_int.hpp"
#include "tiffimage.hpp"
#include "tiffimage_int.hpp"
#include "utils.hpp"
// + standard includes
#include <string>
#include <array>
#include <filesystem>
#include <fstream>
#include <cstring>
#include <iostream>
namespace fs = std::filesystem;
#if defined(__MINGW32__) || defined(__MINGW64__)
#ifndef __MINGW__
@ -52,25 +56,6 @@
#include <windows.h>
#include <direct.h> // _getcwd
#include <shlobj.h>
/* older SDKs not have these */
# ifndef CSIDL_MYMUSIC
# define CSIDL_MYMUSIC 13
# endif
# ifndef CSIDL_MYVIDEO
# define CSIDL_MYVIDEO 14
# endif
# ifndef CSIDL_INTERNET_CACHE
# define CSIDL_INTERNET_CACHE 32
# endif
# ifndef CSIDL_COMMON_APPDATA
# define CSIDL_COMMON_APPDATA 35
# endif
# ifndef CSIDL_MYPICTURES
# define CSIDL_MYPICTURES 0x27
# endif
# ifndef CSIDL_COMMON_DOCUMENTS
# define CSIDL_COMMON_DOCUMENTS 46
# endif
# ifndef CSIDL_PROFILE
# define CSIDL_PROFILE 40
# endif
@ -96,7 +81,6 @@ namespace {
namespace Exiv2 {
namespace Internal {
// C++17 use std::filesystem
// Function first looks for a config file in current working directory
// on Win the file should be named "exiv2.ini"
// on Lin the file should be named ".exiv2"
@ -104,36 +88,27 @@ namespace Exiv2 {
// which is the user profile path on win and the home dir on linux
std::string getExiv2ConfigPath()
{
std::string dir;
#if defined(_MSC_VER) || defined(__MINGW__)
std::string inifile("exiv2.ini");
#else
std::string inifile(".exiv2");
#endif
// first lets get the current working directory to check if there is a config file
char buffer[1024];
#if defined(_MSC_VER) || defined(__MINGW__)
auto path = _getcwd(buffer, sizeof(buffer));
#else
auto path = getcwd(buffer, sizeof(buffer));
#endif
dir = std::string(path ? path : "");
auto const filename = dir + EXV_SEPARATOR_CHR + inifile;
// true if the file exists
if (std::ifstream(filename).good()) {
return filename;
auto currentPath = fs::current_path();
auto iniPath = currentPath / inifile;
if (fs::exists(iniPath)) {
return iniPath.string();
}
#if defined(_MSC_VER) || defined(__MINGW__)
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, path))) {
dir = std::string(path);
char buffer[1024];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, buffer))) {
currentPath = buffer;
}
#else
struct passwd* pw = getpwuid(getuid());
dir = std::string(pw ? pw->pw_dir : "");
currentPath = std::string(pw ? pw->pw_dir : "");
#endif
return dir + EXV_SEPARATOR_CHR + inifile;
return (currentPath / inifile).string();
}
std::string readExiv2Config(const std::string& section, const std::string& value, const std::string& def)
@ -1223,11 +1198,8 @@ namespace Exiv2 {
{
// Not valid for models beginning
std::string model = getExifModel(pRoot);
for (auto& m : { "SLT-", "HV", "ILCA-" }) {
if (model.find(m) == 0)
return -1;
}
return 0;
const std::array strs { "SLT-", "HV", "ILCA-"};
return std::any_of(strs.begin(), strs.end(), [&model](auto& m){return startsWith(model, m);}) ? -1 : 0;
}
int sonyMisc2bSelector(uint16_t /*tag*/, const byte* /*pData*/, uint32_t /*size*/, TiffComponent* const pRoot)

@ -24,12 +24,8 @@
// included header files
#include "tifffwd_int.hpp"
#include "tags_int.hpp"
#include "ini.hpp"
#include "types.hpp"
// + standard includes
#include <string>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -63,7 +63,7 @@ namespace Exiv2 {
};
//! Lookup table to translate Minolta image quality values to readable labels
EXV_UNUSED constexpr TagDetails minoltaImageQuality[] = {
[[maybe_unused]] constexpr TagDetails minoltaImageQuality[] = {
{ 0, N_("Raw") },
{ 1, N_("Super Fine") },
{ 2, N_("Fine") },
@ -273,7 +273,7 @@ namespace Exiv2 {
};
//! Lookup table to translate Minolta Std camera settings AF points values to readable labels
EXV_UNUSED constexpr TagDetails minoltaAFPointsStd[] = {
[[maybe_unused]] constexpr TagDetails minoltaAFPointsStd[] = {
{ 0, N_("Center") },
{ 1, N_("Top") },
{ 2, N_("Top-right") },
@ -2490,16 +2490,5 @@ namespace Exiv2 {
return EXV_PRINT_TAG(minoltaSonyZoneMatching)(os, value, metadata);
}
std::ostream& printMinoltaSonyFlashExposureComp(std::ostream& os, const Value& value, const ExifData*)
{
std::ios::fmtflags f( os.flags() );
if (value.count() != 1 || value.typeId() != signedRational) {
return os << "(" << value << ")";
}
os << std::fixed << std::setprecision(2) << value.toFloat(0) << " EV";
os.flags(f);
return os;
}
} // namespace Internal
} // namespace Exiv2

@ -136,9 +136,6 @@ namespace Exiv2 {
//! Print Minolta/Sony ZoneMatching values to readable labels.
std::ostream& printMinoltaSonyZoneMatching(std::ostream&, const Value&, const ExifData*);
//! Print Minolta/Sony FlashExposureComp values to readable labels.
std::ostream& printMinoltaSonyFlashExposureComp(std::ostream&, const Value&, const ExifData*);
// TODO: Added shared methods here.
}} // namespace Internal, Exiv2

@ -79,7 +79,7 @@ namespace Exiv2 {
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "MRW"));
}
void MrwImage::setComment(const std::string& /*comment*/)
void MrwImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "MRW"));

@ -490,7 +490,7 @@ namespace Exiv2 {
};
//! FocusMode, tag 0x0301
EXV_UNUSED constexpr TagDetails olympusCsFocusMode[] = {
[[maybe_unused]] constexpr TagDetails olympusCsFocusMode[] = {
{ 0, N_("Single AF") },
{ 1, N_("Sequential shooting AF") },
{ 2, N_("Continuous AF") },

@ -72,7 +72,7 @@ namespace Exiv2 {
return 0;
}
void OrfImage::setComment(const std::string& /*comment*/)
void OrfImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "ORF"));

@ -25,10 +25,6 @@
#include "tags.hpp"
#include "types.hpp"
// + standard includes
#include <string>
#include <iosfwd>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -26,10 +26,6 @@
#include "tags_int.hpp"
#include "types.hpp"
// + standard includes
#include <iostream>
#include <iomanip>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -25,11 +25,6 @@
#include "types.hpp"
#include "pngimage.hpp"
// + standard includes
#include <iosfwd>
#include <cassert>
#include <cstdarg>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -35,6 +35,7 @@
#include "types.hpp"
// + standard includes
#include <algorithm>
#include <array>
#include <string>
#include <cstring>
@ -150,11 +151,11 @@ namespace Exiv2 {
static bool tEXtToDataBuf(const byte* bytes,long length,DataBuf& result)
{
static const char* hexdigits = "0123456789ABCDEF";
static std::array<int, 256> value;
static bool bFirst = true;
if ( bFirst ) {
value.fill(0);
const char* hexdigits = "0123456789ABCDEF";
for ( int i = 0 ; i < 16 ; i++ ) {
value[tolower(hexdigits[i])]=i+1;
value[toupper(hexdigits[i])]=i+1;

@ -21,6 +21,7 @@
// included header files
#include "config.h"
#include <algorithm>
#include <array>
#include <climits>
#include <string>

@ -3943,6 +3943,7 @@ namespace Exiv2 {
XmpProperties::NsRegistry XmpProperties::nsRegistry_;
std::mutex XmpProperties::mutex_;
/// \todo not used internally. At least we should test it
const XmpNsInfo* XmpProperties::lookupNsRegistry(const XmpNsInfo::Prefix& prefix)
{
std::lock_guard<std::mutex> scoped_read_lock(mutex_);
@ -4095,6 +4096,7 @@ namespace Exiv2 {
return pi;
}
/// \todo not used internally. At least we should test it
const char* XmpProperties::nsDesc(const std::string& prefix)
{
return nsInfo(prefix)->desc_;

@ -127,7 +127,7 @@ namespace Exiv2 {
return "image/x-photoshop";
}
void PsdImage::setComment(const std::string& /*comment*/)
void PsdImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "Photoshop"));
@ -399,13 +399,15 @@ namespace Exiv2 {
#endif
// Copy colorData
uint32_t readTotal = 0;
long toRead = 0;
while (readTotal < colorDataLength) {
toRead = static_cast<long>(colorDataLength - readTotal) < lbuf.size()
? static_cast<long>(colorDataLength - readTotal) : lbuf.size();
if (io_->read(lbuf.data(), toRead) != toRead) throw Error(kerNotAnImage, "Photoshop");
long toRead = static_cast<long>(colorDataLength - readTotal) < lbuf.size()
? static_cast<long>(colorDataLength - readTotal)
: lbuf.size();
if (io_->read(lbuf.data(), toRead) != toRead)
throw Error(kerNotAnImage, "Photoshop");
readTotal += toRead;
if (outIo.write(lbuf.c_data(), toRead) != toRead) throw Error(kerImageWriteFailed);
if (outIo.write(lbuf.c_data(), toRead) != toRead)
throw Error(kerImageWriteFailed);
}
if (outIo.error()) throw Error(kerImageWriteFailed);
@ -505,15 +507,17 @@ namespace Exiv2 {
if (outIo.write(buf, 4) != 4) throw Error(kerImageWriteFailed);
readTotal = 0;
toRead = 0;
while (readTotal < pResourceSize) {
toRead = static_cast<long>(pResourceSize - readTotal) < lbuf.size()
? static_cast<long>(pResourceSize - readTotal) : lbuf.size();
/// \todo almost same code as in lines 403-410. Factor out & reuse!
long toRead = static_cast<long>(pResourceSize - readTotal) < lbuf.size()
? static_cast<long>(pResourceSize - readTotal)
: lbuf.size();
if (io_->read(lbuf.data(), toRead) != toRead) {
throw Error(kerNotAnImage, "Photoshop");
}
readTotal += toRead;
if (outIo.write(lbuf.c_data(), toRead) != toRead) throw Error(kerImageWriteFailed);
if (outIo.write(lbuf.c_data(), toRead) != toRead)
throw Error(kerImageWriteFailed);
}
if (outIo.error()) throw Error(kerImageWriteFailed);
newResLength += pResourceSize + adjResourceNameLen + 12;
@ -532,13 +536,11 @@ namespace Exiv2 {
// Append ExifInfo resource block, if not yet written
if (!exifDone) {
newResLength += writeExifData(exifData_, outIo);
exifDone = true;
}
// Append XmpPacket resource block, if not yet written
if (!xmpDone) {
newResLength += writeXmpData(xmpData_, outIo);
xmpDone = true;
}
// Populate the fake data, only make sense for remoteio, httpio and sshio.

@ -81,7 +81,7 @@ namespace Exiv2 {
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "RAF"));
}
void RafImage::setComment(const std::string& /*comment*/)
void RafImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "RAF"));
@ -96,12 +96,11 @@ namespace Exiv2 {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "RAF");
}
size_t address = 0 ;
size_t address2 = 0 ;
const bool bPrint = option==kpsBasic || option==kpsRecursive;
if ( bPrint ) {
io_->seek(0,BasicIo::beg); // rewind
address = io_->tell();
size_t address = io_->tell();
const char* format = " %8d | %8d | ";
{
@ -174,7 +173,7 @@ namespace Exiv2 {
byte jpg_img_offset [4];
io_->read(jpg_img_offset, 4);
byte jpg_img_length [4];
address2 = io_->tell();
size_t address2 = io_->tell();
io_->read(jpg_img_length, 4);
long jpg_img_off = Exiv2::getULong(jpg_img_offset, bigEndian);

@ -83,7 +83,7 @@ namespace Exiv2 {
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "RW2"));
}
void Rw2Image::setComment(const std::string& /*comment*/)
void Rw2Image::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "RW2"));

@ -23,10 +23,6 @@
// *****************************************************************************
// included header files
#include "tiffimage_int.hpp"
#include "types.hpp"
// + standard includes
#include <string>
// *****************************************************************************
// namespace extensions

@ -25,11 +25,6 @@
#include "tags.hpp"
#include "types.hpp"
// + standard includes
#include <string>
#include <iosfwd>
#include <memory>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -25,11 +25,6 @@
#include "tags.hpp"
#include "types.hpp"
// + standard includes
#include <string>
#include <iosfwd>
#include <memory>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -22,14 +22,8 @@
// *****************************************************************************
// included header files
#include "tags.hpp"
#include "types.hpp"
#include "tiffcomposite_int.hpp"
// + standard includes
#include <string>
#include <iosfwd>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {

@ -127,6 +127,7 @@ namespace Exiv2 {
return sectionInfo[ti->sectionId_].name_;
}
/// \todo not used internally. At least we should test it
uint16_t ExifTags::defaultCount(const ExifKey& key)
{
const TagInfo* ti = tagInfo(key.tag(), static_cast<Internal::IfdId>(key.ifdId()));

@ -40,6 +40,7 @@
#include "sonymn_int.hpp"
#include <cmath>
#include <algorithm>
// *****************************************************************************
// local declarations

@ -22,14 +22,7 @@
// *****************************************************************************
// included header files
#include "types.hpp"
#include "tags.hpp"
#include "value.hpp"
// + standard includes
#include <string>
#include <iostream>
#include <memory>
// *****************************************************************************
// namespace extensions

@ -58,7 +58,7 @@ namespace Exiv2 {
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "TGA"));
}
void TgaImage::setComment(const std::string& /*comment*/)
void TgaImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "TGA"));
@ -133,7 +133,7 @@ namespace Exiv2 {
bool isTgaType(BasicIo& iIo, bool /*advance*/)
{
// not all TARGA files have a signature string, so first just try to match the file name extension
std::string path = iIo.path();
const std::string& path = iIo.path();
if( path.rfind(".tga") != std::string::npos
|| path.rfind(".TGA") != std::string::npos) {
return true;

@ -22,16 +22,9 @@
// *****************************************************************************
// included header files
#include "value.hpp"
#include "tifffwd_int.hpp"
#include "types.hpp"
// + standard includes
#include <iosfwd>
#include <memory>
#include <vector>
#include <string>
#include <cassert>
// *****************************************************************************
// namespace extensions

@ -26,9 +26,7 @@
#include "tags_int.hpp"
// + standard includes
#include <memory>
#include <stack>
#include <vector>
// *****************************************************************************
// Exiv2 namespace extensions

@ -162,7 +162,7 @@ namespace Exiv2 {
return pixelHeightPrimary_;
}
void TiffImage::setComment(const std::string& /*comment*/)
void TiffImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "TIFF"));

@ -26,6 +26,8 @@
#include "tiffvisitor_int.hpp"
#include "i18n.h" // NLS support.
#include <iostream>
// Shortcuts for the newTiffBinaryArray templates.
#define EXV_BINARY_ARRAY(arrayCfg, arrayDef) (newTiffBinaryArray0<&arrayCfg, EXV_COUNTOF(arrayDef), arrayDef>)
#define EXV_SIMPLE_BINARY_ARRAY(arrayCfg) (newTiffBinaryArray1<&arrayCfg>)

@ -25,12 +25,6 @@
#include "tifffwd_int.hpp"
#include "tiffcomposite_int.hpp"
#include "image.hpp"
#include "tags_int.hpp"
#include "types.hpp"
// + standard includes
#include <map>
#include <utility>
// *****************************************************************************
// namespace extensions

@ -469,6 +469,7 @@ namespace Exiv2 {
const uint16_t nMasks = (nPoints+15)/(sizeof(uint16_t) * 8);
int nStart = 0;
/// \todo make this static
struct {
uint16_t tag ;
uint16_t size ;

@ -26,15 +26,7 @@
#include "tifffwd_int.hpp"
#include "types.hpp"
// + standard includes
#include <array>
#include <memory>
#include <iostream>
#include <iomanip>
#include <cassert>
#include <map>
#include <set>
#include <vector>
// *****************************************************************************
// namespace extensions
@ -42,6 +34,8 @@ namespace Exiv2 {
class IptcData;
class XmpData;
class TiffImageEntry;
class TiffDataEntryBase;
namespace Internal {

@ -0,0 +1,9 @@
#include "utils.hpp"
namespace Exiv2
{
bool startsWith(const std::string_view& s, const std::string_view& start)
{
return s.find(start) == 0;
}
}

@ -0,0 +1,11 @@
#ifndef EXIV2_UTILS_HPP
#define EXIV2_UTILS_HPP
#include <string_view>
namespace Exiv2
{
bool startsWith(const std::string_view& s, const std::string_view& start);
}
#endif // EXIV2_UTILS_HPP

@ -804,7 +804,6 @@ namespace Exiv2 {
std::string lang = "x-default";
if (buf.length() > 5 && buf.substr(0, 5) == "lang=") {
static const char* ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static const char* ALPHA_NUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const std::string::size_type pos = buf.find_first_of(' ');
if (pos == std::string::npos) {
@ -829,6 +828,7 @@ namespace Exiv2 {
// Check language is in the correct format (see https://www.ietf.org/rfc/rfc3066.txt)
std::string::size_type charPos = lang.find_first_not_of(ALPHA);
if (charPos != std::string::npos) {
static const char* ALPHA_NUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
if (lang.at(charPos) != '-' || lang.find_first_not_of(ALPHA_NUM, charPos+1) != std::string::npos)
throw Error(kerInvalidLangAltValue, buf);
}
@ -1110,6 +1110,7 @@ namespace Exiv2 {
return 1;
}
/// \todo not used internally. At least we should test it
void TimeValue::setTime( const Time& src )
{
std::memcpy(&time_, &src, sizeof(time_));

@ -36,13 +36,10 @@
#endif
// + standard includes
#include <iomanip>
#include <sstream>
#include <string>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <regex>
#include <set>
#include <sstream>
// #1147
#ifndef WIN32
@ -139,7 +136,7 @@ static void output(std::ostream& os,const std::vector<std::regex>& greps,const c
static bool pushPath(std::string& path,std::vector<std::string>& libs,std::set<std::string>& paths)
{
bool result = Exiv2::fileExists(path,true) && paths.find(path) == paths.end() && path != "/" ;
bool result = Exiv2::fileExists(path) && paths.find(path) == paths.end() && path != "/" ;
if ( result ) {
paths.insert(path);
libs.push_back(path);
@ -313,7 +310,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector<std::regex>& keys
int have_lensdata =0;
int have_iconv =0;
int have_memory =0;
int have_lstat =0;
int have_stdbool =0;
int have_stdint =0;
int have_stdlib =0;
@ -362,10 +358,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector<std::regex>& keys
have_memory=1;
#endif
#ifdef EXV_HAVE_LSTAT
have_lstat=1;
#endif
#ifdef EXV_HAVE_STDBOOL_H
have_stdbool=1;
#endif
@ -492,7 +484,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector<std::regex>& keys
output(os,keys,"have_lensdata" ,have_lensdata );
output(os,keys,"have_iconv" ,have_iconv );
output(os,keys,"have_memory" ,have_memory );
output(os,keys,"have_lstat" ,have_lstat );
output(os,keys,"have_stdbool" ,have_stdbool );
output(os,keys,"have_stdint" ,have_stdint );
output(os,keys,"have_stdlib" ,have_stdlib );

@ -50,6 +50,54 @@
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
namespace {
[[maybe_unused]] std::string binaryToHex(const uint8_t* data, size_t size)
{
std::stringstream hexOutput;
auto tl = size_t(size / 16) * 16;
auto tl_offset = size_t(size) - tl;
for (size_t loop = 0; loop < size; loop++) {
if (data[loop] < 16) {
hexOutput << "0";
}
hexOutput << std::hex << static_cast<int>(data[loop]);
if ((loop % 8) == 7) {
hexOutput << " ";
}
if ((loop % 16) == 15 || loop == (tl + tl_offset - 1)) {
int max = 15;
if (loop >= tl) {
max = int(tl_offset) - 1;
for (int offset = 0; offset < int(16 - tl_offset); offset++) {
if ((offset % 8) == 7) {
hexOutput << " ";
}
hexOutput << " ";
}
}
hexOutput << " ";
for (int offset = max; offset >= 0; offset--) {
if (offset == (max - 8)) {
hexOutput << " ";
}
uint8_t c = '.';
if (data[loop - offset] >= 0x20 && data[loop - offset] <= 0x7E) {
c = data[loop - offset];
}
hexOutput << static_cast<char>(c);
}
hexOutput << std::endl;
}
}
hexOutput << std::endl << std::endl << std::endl;
return hexOutput.str();
}
} // namespace
// *****************************************************************************
// class member definitions
namespace Exiv2 {
@ -96,7 +144,7 @@ namespace Exiv2 {
// throw(Error(kerInvalidSettingForImage, "IPTC metadata", "WebP"));
}
void WebPImage::setComment(const std::string& /*comment*/)
void WebPImage::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "WebP"));
@ -688,7 +736,7 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Display Hex Dump [size:" << static_cast<unsigned long>(sizePayload) << "]" << std::endl;
std::cout << Internal::binaryToHex(rawExifData.c_data(), sizePayload);
std::cout << binaryToHex(rawExifData.c_data(), sizePayload);
#endif
if (pos != -1) {
@ -716,7 +764,7 @@ namespace Exiv2 {
#ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Display Hex Dump [size:" << static_cast<unsigned long>(payload.size()) << "]"
<< std::endl;
std::cout << Internal::binaryToHex(payload.c_data(), payload.size());
std::cout << binaryToHex(payload.c_data(), payload.size());
#endif
}
} else {
@ -833,8 +881,6 @@ namespace Exiv2 {
if (iIo.tell() % 2) {
if (iIo.write(&WEBP_PAD_ODD, 1) != 1) throw Error(kerImageWriteFailed);
}
has_icc = false;
}
}

@ -30,6 +30,7 @@
#include "convert.hpp"
// + standard includes
#include <algorithm>
#include <string>
#include <iostream>
#include <cassert>
@ -61,7 +62,7 @@ namespace Exiv2 {
return "application/rdf+xml";
}
void XmpSidecar::setComment(const std::string& /*comment*/)
void XmpSidecar::setComment(std::string_view /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "XMP"));

@ -65,7 +65,7 @@ TEST(TheImageFactory, createsInstancesForFewSupportedTypesInFiles)
EXPECT_NO_THROW(ImageFactory::create(ImageType::pgf, filePath));
EXPECT_NO_THROW(ImageFactory::create(ImageType::png, filePath));
EXPECT_EQ(0, std::remove(filePath.c_str()));
EXPECT_TRUE(fs::remove(filePath));
}
TEST(TheImageFactory, cannotCreateInstancesForSomeTypesInFiles)

@ -23,6 +23,7 @@
#include <exiv2/futils.hpp>
// Auxiliary headers
#include <filesystem>
#include <fstream>
#include <cstdio>
#include <cerrno>
@ -30,6 +31,8 @@
#include <gtest/gtest.h>
namespace fs = std::filesystem;
using namespace Exiv2;
TEST(strError, returnSuccessAfterClosingFile)
@ -42,7 +45,7 @@ TEST(strError, returnSuccessAfterClosingFile)
std::string tmpFile("tmp.dat");
std::ofstream auxFile(tmpFile.c_str());
auxFile.close();
std::remove(tmpFile.c_str());
fs::remove(tmpFile.c_str());
ASSERT_TRUE(strError().find("(errno = 0)") != std::string::npos);
}
@ -97,15 +100,6 @@ TEST(urlencode, encodesGivenUrlWithSpace)
ASSERT_STREQ("http%3a%2f%2fwww.geekhideout.com%2furl+code.shtml", url.c_str());
}
TEST(urldecode, decodesGivenUrl)
{
const std::string expectedDecodedUrl ("http://www.geekhideout.com/urlcode.shtml");
const std::string url ("http%3a%2f%2fwww.geekhideout.com%2furlcode.shtml");
char * url3 = urldecode(url.c_str());
ASSERT_STREQ(expectedDecodedUrl.c_str(), url3);
delete [] url3;
}
TEST(urldecode, decodesGivenUrlInPlace)
{
const std::string expectedDecodedUrl ("http://www.geekhideout.com/urlcode.shtml");

Loading…
Cancel
Save