Merge pull request #2099 from Exiv2/main_SeparateApp

Separate exiv2 app source files from exiv2lib src folder
main
Luis Díaz Más 3 years ago committed by GitHub
commit 0b17cc31f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -99,39 +99,38 @@ if( EXIV2_BUILD_FUZZ_TESTS )
add_subdirectory ( fuzz )
endif()
if( EXIV2_BUILD_SAMPLES )
add_subdirectory( samples )
get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS)
if (Python3_Interpreter_FOUND)
add_test(NAME bashTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests
)
endif()
endif()
if(EXIV2_BUILD_EXIV2_COMMAND)
add_subdirectory ( app )
if( EXIV2_BUILD_SAMPLES )
add_subdirectory( samples )
get_directory_property(SAMPLES DIRECTORY samples DEFINITION APPLICATIONS)
if (Python3_Interpreter_FOUND)
add_test(NAME bashTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests)
endif()
endif()
if (Python3_Interpreter_FOUND)
add_test(NAME bugfixTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bugfixes)
add_test(NAME lensTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose lens_tests)
add_test(NAME tiffTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose tiff_test)
add_test(NAME versionTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests/version_test.py )
add_test(NAME regressionTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose regression_tests)
endif()
if (Python3_Interpreter_FOUND)
add_test(NAME bugfixTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bugfixes
)
add_test(NAME lensTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose lens_tests
)
add_test(NAME tiffTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose tiff_test
)
add_test(NAME versionTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose bash_tests/version_test.py
)
add_test(NAME regressionTests
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests
COMMAND cmake -E env EXIV2_BINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${Python3_EXECUTABLE} runner.py --verbose regression_tests
)
endif()
if( EXIV2_ENABLE_NLS )

@ -0,0 +1,57 @@
add_executable( exiv2
exiv2.cpp
exiv2app.hpp
actions.cpp actions.hpp
getopt.cpp getopt.hpp
app_utils.cpp app_utils.hpp
)
target_include_directories(exiv2 PRIVATE ${CMAKE_SOURCE_DIR}/src) # To find i18n.hpp
set_target_properties( exiv2 PROPERTIES
COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS}
XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES"
)
if (MSVC)
set_target_properties(exiv2 PROPERTIES LINK_FLAGS "/ignore:4099") # Ignore missing PDBs
endif()
target_link_libraries( exiv2 PRIVATE exiv2lib )
if( EXIV2_ENABLE_NLS )
target_link_libraries(exiv2 PRIVATE ${Intl_LIBRARIES})
target_include_directories(exiv2 PRIVATE ${Intl_INCLUDE_DIRS})
endif()
target_link_libraries(exiv2 PRIVATE std::filesystem)
if(MSVC OR MINGW)
# Trick to get properly UTF-8 encoded argv
# More info at: https://github.com/huangqinjin/wmain
add_library(wmain STATIC wmain.c)
target_link_libraries(exiv2 PRIVATE wmain)
endif()
if (MSVC)
target_link_options(wmain INTERFACE /WHOLEARCHIVE:$<TARGET_FILE:wmain>)
target_link_options(exiv2 PRIVATE "/ENTRY:wWinMainCRTStartup")
endif()
if (MINGW)
target_compile_options(exiv2 PRIVATE -municode)
target_link_options(exiv2 PRIVATE -municode)
endif()
if (USING_CONAN AND WIN32 AND EXISTS ${PROJECT_BINARY_DIR}/conanDlls)
# In case of using conan recipes with their 'shared' option turned on, we will have dlls of
# the 3rd party dependencies in the conanDlls folder.
# Copy 3rd party DLLs the bin folder. [build step]
add_custom_command(TARGET exiv2 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/conanDlls ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
# Copy 3rd party DLLs the bin folder. [install step]
install(DIRECTORY ${PROJECT_BINARY_DIR}/conanDlls/ DESTINATION bin)
endif()
install(TARGETS exiv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

@ -24,12 +24,13 @@
// included header files
#include "config.h"
#include "app_utils.hpp"
#include "actions.hpp"
#include "exiv2app.hpp"
#include "image.hpp"
#include "jpgimage.hpp"
#include "xmpsidecar.hpp"
#include "utils.hpp"
#include "types.hpp"
#include "exif.hpp"
#include "easyaccess.hpp"
@ -1958,26 +1959,38 @@ namespace {
}
};
void replace(std::string& text, const std::string& searchText, const std::string& replaceText)
{
std::string::size_type index = 0;
while ((index = text.find(searchText, index)) != std::string::npos)
{
text.replace(index, searchText.length(), replaceText.c_str(), replaceText.length());
index++;
}
}
int renameFile(std::string& newPath, const struct tm* tm)
{
auto p = fs::path(newPath);
std::string path = newPath;
auto oldFsPath = fs::path(path);
std::string format = Params::instance().format_;
Util::replace(format, ":basename:", Util::basename(path, true));
Util::replace(format, ":dirname:", Util::basename(Util::dirname(path)));
Util::replace(format, ":parentname:", Util::basename(Util::dirname(Util::dirname(path))));
replace(format, ":basename:", p.stem().string());
replace(format, ":dirname:", p.parent_path().filename().string());
replace(format, ":parentname:", p.parent_path().parent_path().filename().string());
const size_t max = 1024;
char basename[max];
std::memset(basename, 0x0, max);
if (strftime(basename, max, format.c_str(), tm) == 0) {
std::cerr << _("Filename format yields empty filename for the file") << " "
<< path << "\n";
std::cerr << _("Filename format yields empty filename for the file") << " " << path << "\n";
return 1;
}
newPath = Util::dirname(path) + EXV_SEPARATOR_STR
+ basename + Util::suffix(path);
if ( Util::dirname(newPath) == Util::dirname(path)
&& Util::basename(newPath) == Util::basename(path)) {
newPath = (p.parent_path() / (basename + p.extension().string())).string();
p = fs::path(newPath);
if (p.parent_path() == oldFsPath.parent_path() && p.filename() == oldFsPath.filename()) {
if (Params::instance().verbose_) {
std::cout << _("This file already has the correct name") << std::endl;
}
@ -1987,46 +2000,40 @@ namespace {
bool go = true;
int seq = 1;
std::string s;
Params::FileExistsPolicy fileExistsPolicy
= Params::instance().fileExistsPolicy_;
Params::FileExistsPolicy fileExistsPolicy = Params::instance().fileExistsPolicy_;
while (go) {
if (Exiv2::fileExists(newPath)) {
switch (fileExistsPolicy) {
case Params::overwritePolicy:
go = false;
break;
case Params::renamePolicy:
newPath = Util::dirname(path)
+ EXV_SEPARATOR_STR + basename
+ "_" + Exiv2::toString(seq++)
+ Util::suffix(path);
break;
case Params::askPolicy:
std::cout << Params::instance().progname()
<< ": " << _("File") << " `" << newPath
<< "' " << _("exists. [O]verwrite, [r]ename or [s]kip?")
<< " ";
std::cin >> s;
switch (s.at(0)) {
case 'o':
case 'O':
case Params::overwritePolicy:
go = false;
break;
case 'r':
case 'R':
fileExistsPolicy = Params::renamePolicy;
newPath = Util::dirname(path)
+ EXV_SEPARATOR_STR + basename
+ "_" + Exiv2::toString(seq++)
+ Util::suffix(path);
break;
default: // skip
return -1;
case Params::renamePolicy:
newPath = (p.parent_path() /
(std::string(basename) + "_" + Exiv2::toString(seq++) + p.extension().string()))
.string();
break;
}
case Params::askPolicy:
std::cout << Params::instance().progname() << ": " << _("File") << " `" << newPath << "' "
<< _("exists. [O]verwrite, [r]ename or [s]kip?") << " ";
std::cin >> s;
switch (s.at(0)) {
case 'o':
case 'O':
go = false;
break;
case 'r':
case 'R':
fileExistsPolicy = Params::renamePolicy;
newPath = (p.parent_path() / (std::string(basename) + "_" + Exiv2::toString(seq++) +
p.extension().string()))
.string();
break;
default: // skip
return -1;
break;
}
}
}
else {
} else {
go = false;
}
}
@ -2042,25 +2049,23 @@ namespace {
// 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";
std::cerr << Params::instance().progname() << ": " << _("Failed to rename") << " " << path << " " << _("to")
<< " " << newPath << ": " << Exiv2::strError() << "\n";
return 1;
}
return 0;
} // renameFile
}
std::string newFilePath(const std::string& path, const std::string& ext)
{
std::string directory = Params::instance().directory_;
if (directory.empty()) directory = Util::dirname(path);
directory = Exiv2::fileProtocol(path) == Exiv2::pFile
? directory + EXV_SEPARATOR_STR
: "" // use current directory for remote files
;
return directory + Util::basename(path, true) + ext;
auto p = fs::path(path);
auto directory = fs::path(Params::instance().directory_);
if (directory.empty())
directory = p.parent_path();
if (Exiv2::fileProtocol(path) != Exiv2::pFile)
directory.clear(); // use current directory for remote files
return (directory / (p.stem().string() + ext)).string();
}
int dontOverwrite(const std::string& path)

@ -0,0 +1,20 @@
#include <cstdlib>
#include <climits>
namespace Util
{
bool strtol(const char* nptr, long& n)
{
if (!nptr || *nptr == '\0')
return false;
char* endptr = nullptr;
long tmp = std::strtol(nptr, &endptr, 10);
if (*endptr != '\0')
return false;
if (tmp == LONG_MAX || tmp == LONG_MIN)
return false;
n = tmp;
return true;
}
} // namespace Util

@ -0,0 +1,13 @@
#ifndef APP_UTILS_HPP_
#define APP_UTILS_HPP_
namespace Util {
/*!
@brief Convert a C string to a long value, which is returned in n.
Returns true if the conversion is successful, else false.
n is not modified if the conversion is unsuccessful. See strtol(2).
*/
bool strtol(const char* nptr, long& n);
} // namespace Util
#endif // #ifndef UTILS_HPP_

@ -22,12 +22,13 @@
// include local header files which are not part of libexiv2
#include "actions.hpp"
#include "convert.hpp"
#include "app_utils.hpp"
#include "exiv2app.hpp"
#include "convert.hpp"
#include "futils.hpp"
#include "getopt.hpp"
#include "i18n.h" // NLS support.
#include "utils.hpp"
#include "xmp_exiv2.hpp"
#include <iostream>

@ -31,7 +31,6 @@
// included header files
#include <exiv2/exiv2.hpp>
#include "utils.hpp"
#include "types.hpp"
#include "getopt.hpp"

@ -25,15 +25,17 @@
// included header files
#include <assert.h>
#include <errno.h>
#include <filesystem>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <iostream>
#include "utils.hpp"
#include "getopt.hpp"
namespace fs = std::filesystem;
namespace Util {
// https://raw.githubusercontent.com/skeeto/getopt/master/getopt.h
@ -113,7 +115,7 @@ namespace Util {
int Getopt::getopt(int argc, char* const argv[], const std::string& optstring)
{
progname_ = Util::basename(argv[0]);
progname_ = fs::path(argv[0]).filename().string();
Util::optind = 0; // reset the Util::Getopt scanner
for (;!errcnt_;) {

@ -52,18 +52,24 @@ if (MSVC)
link_directories(${CMAKE_INSTALL_PREFIX}/lib)
endif()
add_executable( getopt-test getopt-test.cpp ../src/utils.cpp ../src/getopt.cpp)
add_executable( getopt-test getopt-test.cpp ../app/getopt.cpp)
list(APPEND APPLICATIONS getopt-test)
target_include_directories(getopt-test PRIVATE ${CMAKE_SOURCE_DIR}/src) # To find utils.hpp
target_include_directories(getopt-test PRIVATE
${CMAKE_SOURCE_DIR}/app
) # To find getopt.hpp
add_executable( metacopy metacopy.cpp ../src/utils.cpp ../src/getopt.cpp)
add_executable( metacopy metacopy.cpp ../app/getopt.cpp)
list(APPEND APPLICATIONS metacopy)
target_include_directories(metacopy PRIVATE ${CMAKE_SOURCE_DIR}/src) # To find utils.hpp
target_include_directories(metacopy PRIVATE
${CMAKE_SOURCE_DIR}/app
) # To find getopt.hpp
add_executable( path-test path-test.cpp ../src/utils.cpp ../src/getopt.cpp)
add_executable( path-test path-test.cpp ../app/getopt.cpp)
list(APPEND APPLICATIONS path-test)
set_target_properties( path-test PROPERTIES OUTPUT_NAME path-test )
target_include_directories(path-test PRIVATE ${CMAKE_SOURCE_DIR}/src) # To find utils.hpp
target_include_directories(path-test PRIVATE
${CMAKE_SOURCE_DIR}/app
) # To find getopt.hpp
add_executable( exiv2json exiv2json.cpp Jzon.cpp Jzon.h)
list(APPEND APPLICATIONS exiv2json)

@ -20,12 +20,13 @@
*/
#include <exiv2/exiv2.hpp>
#include <filesystem>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "utils.hpp"
namespace fs = std::filesystem;
int main(int argc, char* const argv[])
{
@ -49,8 +50,9 @@ int main(int argc, char* const argv[])
std::string path, dir, base;
std::istringstream is(line);
is >> path >> dir >> base;
std::string d = Util::dirname(path);
std::string b = Util::basename(path);
auto p = fs::path(path);
std::string d = p.parent_path().string();
std::string b = p.filename().string();
if (d != dir || b != base) {
std::cout << path << "\t'" << d << "'\t '" << b

@ -1,5 +1,3 @@
# CMakeLists.txt for exiv2 library and command-line program
# Note that this is a hack for testing the internals of the library. If EXIV2_BUILD_UNIT_TESTS==OFF
# Then we only export the symbols that are explicitly exported
if( EXIV2_BUILD_UNIT_TESTS )
@ -38,7 +36,6 @@ add_library( exiv2lib_int OBJECT
tifffwd_int.hpp
timegm.h
unused.h
utils.cpp utils.hpp
)
set(PUBLIC_HEADERS
@ -261,66 +258,3 @@ install(EXPORT exiv2Config DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/exiv2")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/exiv2ConfigVersion.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/exiv2")
# ******************************************************************************
# exiv2 application
if(EXIV2_BUILD_EXIV2_COMMAND)
add_executable( exiv2
exiv2.cpp
exiv2app.hpp
actions.cpp actions.hpp
getopt.cpp getopt.hpp
utils.cpp utils.hpp
)
set_target_properties( exiv2 PROPERTIES
COMPILE_FLAGS ${EXTRA_COMPILE_FLAGS}
XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES"
)
if (MSVC)
set_target_properties(exiv2 PROPERTIES LINK_FLAGS "/ignore:4099") # Ignore missing PDBs
endif()
target_link_libraries( exiv2 PRIVATE exiv2lib )
if( EXIV2_ENABLE_NLS )
target_link_libraries(exiv2 PRIVATE ${Intl_LIBRARIES})
target_include_directories(exiv2 PRIVATE ${Intl_INCLUDE_DIRS})
endif()
target_link_libraries(exiv2 PRIVATE std::filesystem)
if(MSVC OR MINGW)
# Trick to get properly UTF-8 encoded argv
# More info at: https://github.com/huangqinjin/wmain
add_library(wmain STATIC wmain.c)
target_link_libraries(exiv2 PRIVATE wmain)
endif()
if (MSVC)
target_link_options(wmain INTERFACE /WHOLEARCHIVE:$<TARGET_FILE:wmain>)
target_link_options(exiv2 PRIVATE "/ENTRY:wWinMainCRTStartup")
endif()
if (MINGW)
target_compile_options(exiv2 PRIVATE -municode)
target_link_options(exiv2 PRIVATE -municode)
endif()
if (USING_CONAN AND WIN32 AND EXISTS ${PROJECT_BINARY_DIR}/conanDlls)
# In case of using conan recipes with their 'shared' option turned on, we will have dlls of
# the 3rd party dependencies in the conanDlls folder.
# Copy 3rd party DLLs the bin folder. [build step]
add_custom_command(TARGET exiv2 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/conanDlls ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
# Copy 3rd party DLLs the bin folder. [install step]
install(DIRECTORY ${PROJECT_BINARY_DIR}/conanDlls/ DESTINATION bin)
endif()
install(TARGETS exiv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
# That's all Folks!
##

@ -33,7 +33,6 @@
#include "error.hpp"
#include "futils.hpp"
#include "version.hpp"
#include "utils.hpp"
// + standard includes
#include <algorithm>
@ -49,7 +48,6 @@
namespace {
using namespace Exiv2;
using namespace Util;
using Exiv2::byte;
// signature of DOS EPS
@ -105,6 +103,11 @@ 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)
{

@ -249,7 +249,7 @@ long INIReader::GetInteger(const string& section, const string& name, long defau
const char* value = valstr.c_str();
char* end;
// This parses "1234" (decimal) and also "0x4D2" (hex)
long n = strtol(value, &end, 0);
long n = std::strtol(value, &end, 0);
return end > value ? n : default_value;
}

@ -32,7 +32,6 @@
#include "tiffvisitor_int.hpp"
#include "tiffimage.hpp"
#include "tiffimage_int.hpp"
#include "utils.hpp"
// + standard includes
#include <string>
@ -1219,16 +1218,18 @@ namespace Exiv2 {
};
return std::find(std::begin(models), std::end(models), getExifModel(pRoot)) != std::end(models) ? 0 : -1;
}
int sony2FpSelector(uint16_t /*tag*/, const byte* /*pData*/, uint32_t /*size*/, TiffComponent* const pRoot)
{
// Not valid for models beginning
std::string model = getExifModel(pRoot);
for (auto& m : { "SLT-", "HV", "ILCA-" }) {
if (Util::startsWith(model, m))
if (model.find(m) == 0)
return -1;
}
return 0;
}
int sonyMisc2bSelector(uint16_t /*tag*/, const byte* /*pData*/, uint32_t /*size*/, TiffComponent* const pRoot)
{
// From Exiftool: https://github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/Sony.pm

@ -27,7 +27,6 @@
#include "value.hpp"
#include "exif.hpp"
#include "i18n.h" // NLS support.
#include "utils.hpp"
// + standard includes
#include <string>
@ -905,7 +904,7 @@ namespace Exiv2 {
// Ranges of models that do not support this tag
std::string model = pos->toString();
for (auto& m : { "DSC-", "Stellar" }) {
if (Util::startsWith(model, m)) {
if (model.find(m) == 0) {
os << N_("n/a");
return os;
}

@ -1,128 +0,0 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2021 Exiv2 authors
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
// *****************************************************************************
// included header files
#include "config.h"
#include "utils.hpp"
#if defined(_MSC_VER)
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
// + standard includes
#ifdef EXV_HAVE_UNISTD_H
# include <unistd.h> // for stat()
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <climits>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <sstream>
namespace Util {
// *****************************************************************************
// free functions
std::string dirname(const std::string& path)
{
if (path.empty())
return ".";
// Strip trailing slashes or backslashes
std::string p = path;
while ( p.length() > 1
&& (p[p.length()-1] == '\\' || p[p.length()-1] == '/')) {
p = p.substr(0, p.length()-1);
}
if (p == "\\" || p == "/") return p;
if (p.length() == 2 && p[1] == ':') return p; // For Windows paths
std::string::size_type idx = p.find_last_of("\\/");
if (idx == std::string::npos) return ".";
if (idx == 1 && p.at(0) == '\\' && p.at(1) == '\\') return p; // For Windows paths
p = p.substr(0, idx == 0 ? 1 : idx);
while ( p.length() > 1
&& (p[p.length()-1] == '\\' || p[p.length()-1] == '/')) {
p = p.substr(0, p.length()-1);
}
return p;
}
std::string basename(const std::string& path, bool delsuffix)
{
if (path.empty())
return ".";
// Strip trailing slashes or backslashes
std::string p = path;
while ( p.length() > 1
&& (p[p.length()-1] == '\\' || p[p.length()-1] == '/')) {
p = p.substr(0, p.length()-1);
}
if (p.length() == 2 && p[1] == ':') return ""; // For Windows paths
std::string::size_type idx = p.find_last_of("\\/");
if (idx == 1 && p.at(0) == '\\' && p.at(1) == '\\') return ""; // For Windows paths
if (idx != std::string::npos) p = p.substr(idx+1);
if (delsuffix) p = p.substr(0, p.length() - suffix(p).length());
return p;
}
std::string suffix(const std::string& path)
{
std::string b = basename(path);
std::string::size_type idx = b.rfind('.');
if (idx == std::string::npos || idx == 0 || idx == b.length()-1) {
return "";
}
return b.substr(idx);
}
bool strtol(const char* nptr, long& n)
{
if (!nptr || *nptr == '\0') return false;
char* endptr = nullptr;
long tmp = std::strtol(nptr, &endptr, 10);
if (*endptr != '\0') return false;
if (tmp == LONG_MAX || tmp == LONG_MIN) return false;
n = tmp;
return true;
}
void replace(std::string& text, const std::string& searchText, const std::string& replaceText)
{
std::string::size_type index = 0;
while ((index = text.find(searchText, index)) != std::string::npos)
{
text.replace(index, searchText.length(), replaceText.c_str(), replaceText.length());
index++;
}
}
bool startsWith(const std::string& s, const std::string& start)
{
return s.size() >= start.size() && std::memcmp(s.data(), start.data(), start.size()) == 0;
}
} // namespace Util

@ -1,91 +0,0 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2021 Exiv2 authors
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
#ifndef UTILS_HPP_
#define UTILS_HPP_
// *********************************************************************
// included header files
// + standard includes
#include <string>
// *********************************************************************
// namespace extensions
/*!
@brief Contains utility classes and functions. Most of these are
wrappers for common C functions that do not require pointers
and memory considerations.
*/
namespace Util {
// *********************************************************************
// free functions
/*!
@brief Get the directory component from the \em path string.
See %dirname(3).
This function can handle Windows paths to some extent: c:\\bar should
be fine, \\\\bigsrv\\foo also, but \\\\bigsrv alone doesn't work.
*/
std::string dirname(const std::string& path);
/*!
@brief Get the filename component from the \em path string.
See %basename(3). If the \em delsuffix parameter is true,
the suffix will be removed.
This function can handle Windows paths to some extent: c:\\bar should
be fine, \\\\bigsrv\\foo also, but \\\\bigsrv alone doesn't work.
*/
std::string basename(const std::string& path, bool delsuffix =false);
/*!
@brief Get the suffix from the path string. Normally, the suffix
is the substring of the basename of path from the last '.'
to the end of the string.
*/
std::string suffix(const std::string& path);
/*!
@brief Convert a C string to a long value, which is returned in n.
Returns true if the conversion is successful, else false.
n is not modified if the conversion is unsuccessful. See strtol(2).
*/
bool strtol(const char* nptr, long& n);
/*!
@brief Replaces all occurrences of \em searchText in the \em text string
by \em replaceText.
*/
void replace(std::string& text, const std::string& searchText, const std::string& replaceText);
// TODO: When using C++20, replace with std::basic_string<CharT,Traits,Allocator>::starts_with()
// (suggested in https://github.com/Exiv2/exiv2/pull/1777).
/*!
@brief Tests if \em start occurs at the beginning of \em s.
Returns true if found, else false.
When Exiv2 uses C++20, this will be replaced with
std::basic_string<CharT,Traits,Allocator>::starts_with().
*/
bool startsWith(const std::string& s, const std::string& start);
} // namespace Util
#endif // #ifndef UTILS_HPP_

@ -224,36 +224,36 @@ Rename -------------------------------------------------------------------
File 1/16: exiv2-empty.jpg
exiv2-empty.jpg: No Exif data found in the file
File 2/16: exiv2-canon-powershot-s40.jpg
Renaming file to ./20031214_000043.jpg
Renaming file to 20031214_000043.jpg
File 3/16: exiv2-nikon-e990.jpg
Renaming file to ./20000506_020544.jpg
Renaming file to 20000506_020544.jpg
File 4/16: exiv2-nikon-d70.jpg
Renaming file to ./20040329_224245.jpg
Renaming file to 20040329_224245.jpg
File 5/16: exiv2-nikon-e950.jpg
Renaming file to ./20010405_235039.jpg
Renaming file to 20010405_235039.jpg
File 6/16: exiv2-canon-eos-300d.jpg
Renaming file to ./20030925_201850.jpg
Renaming file to 20030925_201850.jpg
File 7/16: exiv2-kodak-dc210.jpg
Renaming file to ./20001026_044550.jpg
Renaming file to 20001026_044550.jpg
File 8/16: exiv2-fujifilm-finepix-s2pro.jpg
Renaming file to ./20030926_111535.jpg
Renaming file to 20030926_111535.jpg
File 9/16: exiv2-sigma-d10.jpg
Renaming file to ./20040316_075137.jpg
Renaming file to 20040316_075137.jpg
File 10/16: exiv2-olympus-c8080wz.jpg
Renaming file to ./20040208_093744.jpg
Renaming file to 20040208_093744.jpg
File 11/16: exiv2-panasonic-dmc-fz5.jpg
Renaming file to ./20050218_212016.jpg
Renaming file to 20050218_212016.jpg
File 12/16: exiv2-sony-dsc-w7.jpg
Renaming file to ./20050527_051833.jpg
Renaming file to 20050527_051833.jpg
File 13/16: exiv2-canon-eos-20d.jpg
Warning: Directory Canon has an unexpected next pointer; ignored.
Renaming file to ./20060802_095200.jpg
Renaming file to 20060802_095200.jpg
File 14/16: exiv2-canon-eos-d30.jpg
Renaming file to ./20001004_015404.jpg
Renaming file to 20001004_015404.jpg
File 15/16: exiv2-canon-powershot-a520.jpg
Renaming file to ./20060127_225027.jpg
Renaming file to 20060127_225027.jpg
File 16/16: exiv2-photoshop.psd
Renaming file to ./20110627_094001.psd
Renaming file to 20110627_094001.psd
Print --------------------------------------------------------------------
File 1/16: exiv2-empty.jpg
@ -2223,72 +2223,72 @@ Warning: Directory Canon has an unexpected next pointer; ignored.
Extract Exif data --------------------------------------------------------
File 1/16: exiv2-empty.jpg
File 2/16: 20031214_000043.jpg
Writing Exif data from 20031214_000043.jpg to ./20031214_000043.exv
Writing Exif data from 20031214_000043.jpg to 20031214_000043.exv
File 3/16: 20000506_020544.jpg
Writing Exif data from 20000506_020544.jpg to ./20000506_020544.exv
Writing Exif data from 20000506_020544.jpg to 20000506_020544.exv
File 4/16: 20040329_224245.jpg
Writing Exif data from 20040329_224245.jpg to ./20040329_224245.exv
Writing Exif data from 20040329_224245.jpg to 20040329_224245.exv
File 5/16: 20010405_235039.jpg
Writing Exif data from 20010405_235039.jpg to ./20010405_235039.exv
Writing Exif data from 20010405_235039.jpg to 20010405_235039.exv
File 6/16: 20030925_201850.jpg
Writing Exif data from 20030925_201850.jpg to ./20030925_201850.exv
Writing Exif data from 20030925_201850.jpg to 20030925_201850.exv
File 7/16: 20001026_044550.jpg
Writing Exif data from 20001026_044550.jpg to ./20001026_044550.exv
Writing JPEG comment from 20001026_044550.jpg to ./20001026_044550.exv
Writing Exif data from 20001026_044550.jpg to 20001026_044550.exv
Writing JPEG comment from 20001026_044550.jpg to 20001026_044550.exv
File 8/16: 20030926_111535.jpg
Writing Exif data from 20030926_111535.jpg to ./20030926_111535.exv
Writing Exif data from 20030926_111535.jpg to 20030926_111535.exv
File 9/16: 20040316_075137.jpg
Writing Exif data from 20040316_075137.jpg to ./20040316_075137.exv
Writing Exif data from 20040316_075137.jpg to 20040316_075137.exv
File 10/16: 20040208_093744.jpg
Writing Exif data from 20040208_093744.jpg to ./20040208_093744.exv
Writing Exif data from 20040208_093744.jpg to 20040208_093744.exv
File 11/16: 20050218_212016.jpg
Writing Exif data from 20050218_212016.jpg to ./20050218_212016.exv
Writing Exif data from 20050218_212016.jpg to 20050218_212016.exv
File 12/16: 20050527_051833.jpg
Writing Exif data from 20050527_051833.jpg to ./20050527_051833.exv
Writing Exif data from 20050527_051833.jpg to 20050527_051833.exv
File 13/16: 20060802_095200.jpg
Warning: Directory Canon has an unexpected next pointer; ignored.
Writing Exif data from 20060802_095200.jpg to ./20060802_095200.exv
Writing Exif data from 20060802_095200.jpg to 20060802_095200.exv
File 14/16: 20001004_015404.jpg
Writing Exif data from 20001004_015404.jpg to ./20001004_015404.exv
Writing Exif data from 20001004_015404.jpg to 20001004_015404.exv
File 15/16: 20060127_225027.jpg
Writing Exif data from 20060127_225027.jpg to ./20060127_225027.exv
Writing Exif data from 20060127_225027.jpg to 20060127_225027.exv
File 16/16: 20110626_213900.psd
Writing Exif data from 20110626_213900.psd to ./20110626_213900.exv
Writing IPTC data from 20110626_213900.psd to ./20110626_213900.exv
Writing XMP data from 20110626_213900.psd to ./20110626_213900.exv
Writing Exif data from 20110626_213900.psd to 20110626_213900.exv
Writing IPTC data from 20110626_213900.psd to 20110626_213900.exv
Writing XMP data from 20110626_213900.psd to 20110626_213900.exv
Extract Thumbnail --------------------------------------------------------
File 1/16: exiv2-empty.jpg
exiv2-empty.jpg: No Exif data found in the file
File 2/16: 20031214_000043.jpg
Writing thumbnail (image/jpeg, 5448 Bytes) to file ./20031214_000043-thumb.jpg
Writing thumbnail (image/jpeg, 5448 Bytes) to file 20031214_000043-thumb.jpg
File 3/16: 20000506_020544.jpg
Writing thumbnail (image/jpeg, 7829 Bytes) to file ./20000506_020544-thumb.jpg
Writing thumbnail (image/jpeg, 7829 Bytes) to file 20000506_020544-thumb.jpg
File 4/16: 20040329_224245.jpg
Writing thumbnail (image/jpeg, 8930 Bytes) to file ./20040329_224245-thumb.jpg
Writing thumbnail (image/jpeg, 8930 Bytes) to file 20040329_224245-thumb.jpg
File 5/16: 20010405_235039.jpg
Writing thumbnail (image/jpeg, 4662 Bytes) to file ./20010405_235039-thumb.jpg
Writing thumbnail (image/jpeg, 4662 Bytes) to file 20010405_235039-thumb.jpg
File 6/16: 20030925_201850.jpg
Writing thumbnail (image/jpeg, 9728 Bytes) to file ./20030925_201850-thumb.jpg
Writing thumbnail (image/jpeg, 9728 Bytes) to file 20030925_201850-thumb.jpg
File 7/16: 20001026_044550.jpg
Writing thumbnail (image/tiff, 20916 Bytes) to file ./20001026_044550-thumb.tif
Writing thumbnail (image/tiff, 20916 Bytes) to file 20001026_044550-thumb.tif
File 8/16: 20030926_111535.jpg
Writing thumbnail (image/jpeg, 9573 Bytes) to file ./20030926_111535-thumb.jpg
Writing thumbnail (image/jpeg, 9573 Bytes) to file 20030926_111535-thumb.jpg
File 9/16: 20040316_075137.jpg
Writing thumbnail (image/jpeg, 11998 Bytes) to file ./20040316_075137-thumb.jpg
Writing thumbnail (image/jpeg, 11998 Bytes) to file 20040316_075137-thumb.jpg
File 10/16: 20040208_093744.jpg
Writing thumbnail (image/jpeg, 7306 Bytes) to file ./20040208_093744-thumb.jpg
Writing thumbnail (image/jpeg, 7306 Bytes) to file 20040208_093744-thumb.jpg
File 11/16: 20050218_212016.jpg
Writing thumbnail (image/jpeg, 10308 Bytes) to file ./20050218_212016-thumb.jpg
Writing thumbnail (image/jpeg, 10308 Bytes) to file 20050218_212016-thumb.jpg
File 12/16: 20050527_051833.jpg
Writing thumbnail (image/jpeg, 15605 Bytes) to file ./20050527_051833-thumb.jpg
Writing thumbnail (image/jpeg, 15605 Bytes) to file 20050527_051833-thumb.jpg
File 13/16: 20060802_095200.jpg
Warning: Directory Canon has an unexpected next pointer; ignored.
Writing thumbnail (image/jpeg, 6260 Bytes) to file ./20060802_095200-thumb.jpg
Writing thumbnail (image/jpeg, 6260 Bytes) to file 20060802_095200-thumb.jpg
File 14/16: 20001004_015404.jpg
Writing thumbnail (image/jpeg, 13824 Bytes) to file ./20001004_015404-thumb.jpg
Writing thumbnail (image/jpeg, 13824 Bytes) to file 20001004_015404-thumb.jpg
File 15/16: 20060127_225027.jpg
Writing thumbnail (image/jpeg, 6137 Bytes) to file ./20060127_225027-thumb.jpg
Writing thumbnail (image/jpeg, 6137 Bytes) to file 20060127_225027-thumb.jpg
File 16/16: 20110626_213900.psd
20110626_213900.psd: Exif data doesn't contain a thumbnail
exiv2-empty.exv: No Exif data found in the file
@ -5623,38 +5623,38 @@ File 16/16: 20110626_213900.psd
Insert Exif data ---------------------------------------------------------
File 1/16: exiv2-empty.jpg
File 2/16: 20031214_000043.jpg
Writing Exif data from ./20031214_000043.exv to 20031214_000043.jpg
Writing Exif data from 20031214_000043.exv to 20031214_000043.jpg
File 3/16: 20000506_020544.jpg
Writing Exif data from ./20000506_020544.exv to 20000506_020544.jpg
Writing Exif data from 20000506_020544.exv to 20000506_020544.jpg
File 4/16: 20040329_224245.jpg
Writing Exif data from ./20040329_224245.exv to 20040329_224245.jpg
Writing Exif data from 20040329_224245.exv to 20040329_224245.jpg
File 5/16: 20010405_235039.jpg
Writing Exif data from ./20010405_235039.exv to 20010405_235039.jpg
Writing Exif data from 20010405_235039.exv to 20010405_235039.jpg
File 6/16: 20030925_201850.jpg
Writing Exif data from ./20030925_201850.exv to 20030925_201850.jpg
Writing Exif data from 20030925_201850.exv to 20030925_201850.jpg
File 7/16: 20001026_044550.jpg
Writing Exif data from ./20001026_044550.exv to 20001026_044550.jpg
Writing JPEG comment from ./20001026_044550.exv to 20001026_044550.jpg
Writing Exif data from 20001026_044550.exv to 20001026_044550.jpg
Writing JPEG comment from 20001026_044550.exv to 20001026_044550.jpg
File 8/16: 20030926_111535.jpg
Writing Exif data from ./20030926_111535.exv to 20030926_111535.jpg
Writing Exif data from 20030926_111535.exv to 20030926_111535.jpg
File 9/16: 20040316_075137.jpg
Writing Exif data from ./20040316_075137.exv to 20040316_075137.jpg
Writing Exif data from 20040316_075137.exv to 20040316_075137.jpg
File 10/16: 20040208_093744.jpg
Writing Exif data from ./20040208_093744.exv to 20040208_093744.jpg
Writing Exif data from 20040208_093744.exv to 20040208_093744.jpg
File 11/16: 20050218_212016.jpg
Writing Exif data from ./20050218_212016.exv to 20050218_212016.jpg
Writing Exif data from 20050218_212016.exv to 20050218_212016.jpg
File 12/16: 20050527_051833.jpg
Writing Exif data from ./20050527_051833.exv to 20050527_051833.jpg
Writing Exif data from 20050527_051833.exv to 20050527_051833.jpg
File 13/16: 20060802_095200.jpg
Writing Exif data from ./20060802_095200.exv to 20060802_095200.jpg
Writing Exif data from 20060802_095200.exv to 20060802_095200.jpg
File 14/16: 20001004_015404.jpg
Writing Exif data from ./20001004_015404.exv to 20001004_015404.jpg
Writing Exif data from 20001004_015404.exv to 20001004_015404.jpg
File 15/16: 20060127_225027.jpg
Writing Exif data from ./20060127_225027.exv to 20060127_225027.jpg
Writing Exif data from 20060127_225027.exv to 20060127_225027.jpg
File 16/16: 20110626_213900.psd
Writing Exif data from ./20110626_213900.exv to 20110626_213900.psd
Writing IPTC data from ./20110626_213900.exv to 20110626_213900.psd
Writing XMP data from ./20110626_213900.exv to 20110626_213900.psd
Writing Exif data from 20110626_213900.exv to 20110626_213900.psd
Writing IPTC data from 20110626_213900.exv to 20110626_213900.psd
Writing XMP data from 20110626_213900.exv to 20110626_213900.psd
exiv2-empty.exv: No Exif data found in the file
Compare original and inserted image data ---------------------------------

@ -2,13 +2,11 @@ find_package(GTest REQUIRED)
add_executable(unit_tests
mainTestRunner.cpp
test_basicio.cpp
test_bmpimage.cpp
test_cr2header_int.cpp
test_datasets.cpp
test_DateValue.cpp
test_TimeValue.cpp
test_XmpKey.cpp
test_basicio.cpp
test_cr2header_int.cpp
test_enforce.cpp
test_FileIo.cpp
test_futils.cpp
@ -16,12 +14,14 @@ add_executable(unit_tests
test_image_int.cpp
test_ImageFactory.cpp
test_IptcKey.cpp
test_LangAltValueRead.cpp
test_pngimage.cpp
test_safe_op.cpp
test_slice.cpp
test_tiffheader.cpp
test_types.cpp
test_LangAltValueRead.cpp
test_TimeValue.cpp
test_XmpKey.cpp
$<TARGET_OBJECTS:exiv2lib_int>
)

Loading…
Cancel
Save