diff --git a/.github/workflows/nightly_Linux_distributions.yml b/.github/workflows/nightly_Linux_distributions.yml index 78959fa7..cdbc83ff 100644 --- a/.github/workflows/nightly_Linux_distributions.yml +++ b/.github/workflows/nightly_Linux_distributions.yml @@ -31,5 +31,5 @@ jobs: run: | mkdir build && cd build cmake $CMAKE_FLAGS -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_SHARED_LIBS=${{ matrix.shared_libraries }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} .. - make -j $(nproc) - make install + cmake --build . --parallel + cmake --install . diff --git a/.github/workflows/on_PR_linux_fuzz.yml b/.github/workflows/on_PR_linux_fuzz.yml index 8b1a810d..00db2b7f 100644 --- a/.github/workflows/on_PR_linux_fuzz.yml +++ b/.github/workflows/on_PR_linux_fuzz.yml @@ -33,7 +33,7 @@ jobs: -DEXIV2_BUILD_FUZZ_TESTS=ON \ -DEXIV2_TEAM_USE_SANITIZERS=ON \ .. && \ - cmake --build . + cmake --build . --parallel - name: Fuzz run: | diff --git a/.github/workflows/on_PR_linux_matrix.yml b/.github/workflows/on_PR_linux_matrix.yml index ce18a326..2b8ca674 100644 --- a/.github/workflows/on_PR_linux_matrix.yml +++ b/.github/workflows/on_PR_linux_matrix.yml @@ -49,12 +49,12 @@ jobs: -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON \ -DCMAKE_INSTALL_PREFIX=install \ .. && \ - cmake --build . + cmake --build . --parallel - name: Install run: | cd build - cmake --build . --target install + cmake --install . tree install - name: Test diff --git a/.github/workflows/on_PR_linux_special_builds.yml b/.github/workflows/on_PR_linux_special_builds.yml index 8141e746..839a5bce 100644 --- a/.github/workflows/on_PR_linux_special_builds.yml +++ b/.github/workflows/on_PR_linux_special_builds.yml @@ -49,7 +49,7 @@ jobs: -DBUILD_WITH_COVERAGE=ON \ -DCMAKE_INSTALL_PREFIX=install \ .. && \ - cmake --build . + cmake --build . --parallel - name: Tests + Upload coverage run: | @@ -96,7 +96,7 @@ jobs: run: | cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DEXIV2_ENABLE_PNG=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_BMFF=ON -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DBUILD_WITH_COVERAGE=OFF -DCMAKE_INSTALL_PREFIX=install .. - cmake --build . + cmake --build . --parallel - name: Tests with valgrind run: | @@ -145,7 +145,7 @@ jobs: -DEXIV2_TEAM_USE_SANITIZERS=ON \ -DCMAKE_INSTALL_PREFIX=install \ .. && \ - cmake --build . + cmake --build . --parallel - name: Tests run: | @@ -194,7 +194,7 @@ jobs: -DEXIV2_ENABLE_NLS=ON \ -DCMAKE_CXX_FLAGS="-DEXIV2_DEBUG_MESSAGES" \ .. && \ - make -j + cmake --build . --parallel - name: Generate documentation run: | diff --git a/.github/workflows/on_PR_mac_matrix.yml b/.github/workflows/on_PR_mac_matrix.yml index 48806824..1572231a 100644 --- a/.github/workflows/on_PR_mac_matrix.yml +++ b/.github/workflows/on_PR_mac_matrix.yml @@ -44,12 +44,12 @@ jobs: -DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ .. && \ - cmake --build . + cmake --build . --parallel - name: Install run: | cd build - cmake --build . --target install + cmake --install . - name: Test run: | diff --git a/.github/workflows/on_PR_windows_matrix.yml b/.github/workflows/on_PR_windows_matrix.yml index 7792094f..075847b7 100644 --- a/.github/workflows/on_PR_windows_matrix.yml +++ b/.github/workflows/on_PR_windows_matrix.yml @@ -73,14 +73,13 @@ jobs: -DCMAKE_BUILD_TYPE=${{matrix.build_type}} ` -DBUILD_SHARED_LIBS=${{matrix.shared_libraries}} ` -DEXIV2_ENABLE_NLS=OFF ` - -DEXIV2_ENABLE_WIN_UNICODE=OFF ` -DEXIV2_ENABLE_WEBREADY=ON ` -DEXIV2_ENABLE_BMFF=ON ` -DEXIV2_BUILD_UNIT_TESTS=ON ` -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON ` -DCMAKE_INSTALL_PREFIX=install ` -S . -B build && ` - cmake --build build + cmake --build build --parallel - name: Install run: | @@ -95,22 +94,25 @@ jobs: msys2: runs-on: windows-latest + timeout-minutes: 40 strategy: fail-fast: false matrix: build_type: [Release, Debug] shared_libraries: [ON, OFF] - sys: [MINGW64] + sys: [UCRT64] name: MSYS2 ${{matrix.sys}} - BuildType:${{matrix.build_type}} - SHARED:${{matrix.shared_libraries}} defaults: run: shell: msys2 {0} + steps: - uses: actions/checkout@v2 - name: Set up MSYS2 uses: msys2/setup-msys2@v2 with: + path-type: strict msystem: ${{matrix.sys}} update: true install: >- @@ -118,28 +120,25 @@ jobs: pacboy: >- toolchain:p cmake:p - ninja:p expat:p gettext:p gtest:p libiconv:p - python-lxml:p zlib:p - name: Build run: | - cmake -GNinja \ + cmake -G"MSYS Makefiles" \ -DCMAKE_CXX_FLAGS=-Wno-deprecated \ -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ -DBUILD_SHARED_LIBS=${{matrix.shared_libraries}} \ -DEXIV2_BUILD_SAMPLES=ON \ - -DEXIV2_ENABLE_NLS=ON \ - -DEXIV2_ENABLE_WIN_UNICODE=ON \ + -DEXIV2_ENABLE_NLS=OFF \ -DEXIV2_ENABLE_WEBREADY=ON \ -DEXIV2_ENABLE_BMFF=ON \ -DEXIV2_BUILD_UNIT_TESTS=ON \ -S . -B build && \ - cmake --build build + cmake --build build --parallel - name: Test run: | @@ -190,7 +189,7 @@ jobs: -DEXIV2_ENABLE_BMFF=ON \ -DEXIV2_BUILD_UNIT_TESTS=OFF \ -S . -B build && \ - cmake --build build + cmake --build build --parallel - name: Test run: | diff --git a/.github/workflows/on_push_BasicWinLinMac.yml b/.github/workflows/on_push_BasicWinLinMac.yml index c0cae9fc..563a2bea 100644 --- a/.github/workflows/on_push_BasicWinLinMac.yml +++ b/.github/workflows/on_push_BasicWinLinMac.yml @@ -66,7 +66,7 @@ jobs: -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON ` -DCMAKE_INSTALL_PREFIX=install .. ` -S . -B build && ` - cmake --build build + cmake --build build --parallel - name: Test @@ -109,7 +109,7 @@ jobs: -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON \ -DCMAKE_INSTALL_PREFIX=install \ .. && \ - cmake --build . + cmake --build . --parallel - name: Test run: | @@ -151,7 +151,7 @@ jobs: -DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \ .. && \ - cmake --build . + cmake --build . --parallel - name: Test run: | diff --git a/.github/workflows/on_push_ExtraJobsForMain.yml b/.github/workflows/on_push_ExtraJobsForMain.yml index 3c2f2a38..31da03a2 100644 --- a/.github/workflows/on_push_ExtraJobsForMain.yml +++ b/.github/workflows/on_push_ExtraJobsForMain.yml @@ -47,7 +47,7 @@ jobs: -DBUILD_WITH_COVERAGE=ON \ -DCMAKE_INSTALL_PREFIX=install \ .. && \ - make -j + cmake --build . --parallel - name: Tests + Upload coverage run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index c8537a03..3083b3e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ project(exiv2 # use TWEAK to categorize the build # 1.00.0.20 = RC2 Preview # 1.00.0.29 = RC2 Development DESCRIPTION "Exif/IPTC/Xmp C++ metadata library and tools plus ICC Profiles, Previews and more." - LANGUAGES CXX + LANGUAGES C CXX ) if(NOT CMAKE_BUILD_TYPE) @@ -24,10 +24,8 @@ option( EXIV2_ENABLE_XMP "Build with XMP metadata support" option( EXIV2_ENABLE_EXTERNAL_XMP "Use external version of XMP" OFF ) option( EXIV2_ENABLE_PNG "Build with png support (requires libz)" ON ) option( EXIV2_ENABLE_NLS "Build native language support (requires gettext)" OFF ) -option( EXIV2_ENABLE_PRINTUCS2 "Build with Printucs2" ON ) option( EXIV2_ENABLE_LENSDATA "Build including lens data" ON ) option( EXIV2_ENABLE_DYNAMIC_RUNTIME "Use dynamic runtime (used for static libs)" ON ) -option( EXIV2_ENABLE_WIN_UNICODE "Use Unicode paths (wstring) on Windows" OFF ) option( EXIV2_ENABLE_WEBREADY "Build webready support into library" OFF ) option( EXIV2_ENABLE_CURL "USE Libcurl for HttpIo (WEBREADY)" OFF ) option( EXIV2_ENABLE_BMFF "Build with BMFF support" ON ) diff --git a/README.md b/README.md index e999fd1b..a7c00f13 100644 --- a/README.md +++ b/README.md @@ -1114,53 +1114,45 @@ I recommend that you build and install CMake from source. ## MinGW/msys2 -Please note that the platform MinGW/msys2 32 is obsolete and superceded by MinGW/msys2 64. +Please note that the platform MinGW/msys2 32 is obsolete and superceded by MinGW/msys2 64. It is important to highlight that we rely on using the Universal C Runtime (UCRT) and its relatively new support for UTF-8. Check this [PR](https://github.com/Exiv2/exiv2/pull/2090) for more information. Therefore you will need to use the [URCT MSYS environment](https://www.msys2.org/docs/environments/). -### MinGW/msys2 64 bit -Install the latest version of [MSYS2](https://repo.msys2.org/distrib/msys2-x86_64-latest.exe) +Install the latest version of [MSYS2](https://repo.msys2.org/distrib/msys2-x86_64-latest.exe), and follow the installation instructions available [here](https://www.msys2.org/). The CI workflow file `.github/workflows/on_PR_windows_matrix.yml` has a build job named `msys2` with instructions showing how to configure Exiv2 on MinGW/msys2. -I use the following batch file to start the MinGW/msys2 64 bit bash shell from the Dos Command Prompt (cmd.exe) +### Install exiv2 Dependencies -```bat -@echo off -setlocal -set "PATH=c:\msys64\mingw64\bin;c:\msys64\usr\bin;c:\msys64\usr\local\bin;" -set "PS1=\! MSYS \u@\h:\w \$ " -set "HOME=c:\msys64\home\rmills" -if NOT EXIST %HOME% mkdir %HOME% -cd %HOME% -color 1f -c:\msys64\usr\bin\bash.exe -norc -endlocal - -``` - -### Install MinGW Dependencies - -Install tools and dependencies: +Please note that you will need to install the `ucrt` package version of the exiv2 dependencies: ```bash -for i in base-devel git coreutils dos2unix tar diffutils make \ - mingw-w64-x86_64-toolchain mingw-w64-x86_64-gcc mingw-w64-x86_64-gdb \ - mingw-w64-x86_64-cmake mingw-w64-x86_64-gettext mingw-w64-x86_64-python3 \ - mingw-w64-x86_64-libexpat mingw-w64-x86_64-libiconv mingw-w64-x86_64-zlib \ - mingw-w64-x86_64-gtest -do (echo y | pacman -S $i) ; done +pacman -S mingw-w64-ucrt-x86_64-binutils mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-curl mingw-w64-ucrt-x86_64-expat mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gettext mingw-w64-ucrt-x86_64-gtest mingw-w64-ucrt-x86_64-libiconv mingw-w64-ucrt-x86_64-make mingw-w64-ucrt-x86_64-zlib ``` ### Download exiv2 from github and build +Use the Windows start menu to open the terminal customized for the UCRT environment: `MSYS2 MinGW UCRT x64`. Then run the following commands to download exiv2, configure the project and build it: + ```bash -$ mkdir -p ~/gnu/github/exiv2 -$ cd ~/gnu/github/exiv2 -$ git clone https://github.com/exiv2/exiv2 -$ cd exiv2 -$ mkdir build ; cd build ; -$ cmake .. -G "Unix Makefiles" # or "MSYS Makefiles" -$ make -``` +mkdir -p ~/gnu/github/exiv2 +cd ~/gnu/github/exiv2 +git clone https://github.com/exiv2/exiv2 +cd exiv2 +mkdir build && cd build +cmake -G "MSYS Makefiles" + -DCMAKE_CXX_FLAGS=-Wno-deprecated + -DCMAKE_BUILD_TYPE=Release + -DBUILD_SHARED_LIBS=ON + -DEXIV2_BUILD_SAMPLES=ON + -DEXIV2_ENABLE_NLS=OFF + -DEXIV2_ENABLE_WEBREADY=ON + -DEXIV2_ENABLE_BMFF=ON + -DEXIV2_BUILD_UNIT_TESTS=ON + .. + +cmake --build . --parallel +``` + +The binaries generated at this point can be executed from the MSYS2 UCRT terminal, but they will not run from a Windows Command Prompt or PowerShell. The reason is that the MSYS2 UCRT terminal is properly configured to find some needed DLLs. In case you want to be able to run the generated **exiv2** binary from any Windows terminal, you'll need to deploy the needed DLLs with the application. [TOC](#TOC)
@@ -1197,7 +1189,7 @@ endlocal ## Visual Studio -We recommend that you use Conan to build Exiv2 using Visual Studio. Exiv2 v0.27 can be built with Visual Studio versions 2008 and later. We actively support and build with Visual Studio 2015, 2017 and 2019. +We recommend that you use Conan to get the Exiv2 dependencies when using Visual Studio. Exiv2 v0.27 can be built with Visual Studio versions 2008 and later. For the `main` branch we actively support and build with Visual Studio 2019 and 2022. As well as Visual Studio, you will need to install CMake, Python3, and Conan. @@ -1212,6 +1204,8 @@ As well as Visual Studio, you will need to install CMake, Python3, and Conan. The python3 interpreter must be on your PATH. +It is important to highlight that we rely on using of the Universal C Runtime (UCRT) and its relatively new support for UTF-8. Check this [PR](https://github.com/Exiv2/exiv2/pull/2090) for more information. + [TOC](#TOC)
diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake index 4d145116..dc82f2bc 100644 --- a/cmake/compilerFlags.cmake +++ b/cmake/compilerFlags.cmake @@ -167,13 +167,7 @@ if(MSVC) string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif () - # Object Level Parallelism - add_compile_options(/MP) - add_definitions(-DNOMINMAX) # This definition is not only needed for Exiv2 but also for xmpsdk - - # https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - if (MSVC_VERSION GREATER_EQUAL "1910") # VS2017 and up - add_compile_options("/Zc:__cplusplus") - endif() - + add_compile_options(/MP) # Object Level Parallelism + add_compile_options(/utf-8) # Set source and execution character sets to UTF-8 + add_definitions(-DNOMINMAX) # This definition is not only needed for Exiv2 but also for xmpsdk endif() diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake index 740c2d0e..0bed81c5 100644 --- a/cmake/config.h.cmake +++ b/cmake/config.h.cmake @@ -24,9 +24,6 @@ // Define if the strerror_r function returns char*. #cmakedefine EXV_STRERROR_R_CHAR_P -// Define to enable the Windows unicode path support. -#cmakedefine EXV_UNICODE_PATH - /* Define to `const' or to empty, depending on the second argument of `iconv'. */ #cmakedefine ICONV_ACCEPTS_CONST_INPUT #if defined(ICONV_ACCEPTS_CONST_INPUT) || defined(__NetBSD__) @@ -76,7 +73,4 @@ // Define if you have the iconv function. #cmakedefine EXV_HAVE_ICONV -// Definition to enable conversion of UCS2 encoded Windows tags to UTF-8. -#cmakedefine EXV_HAVE_PRINTUCS2 - #endif /* !_EXV_CONF_H_ */ diff --git a/cmake/generateConfigFile.cmake b/cmake/generateConfigFile.cmake index 05e16341..91b9554b 100644 --- a/cmake/generateConfigFile.cmake +++ b/cmake/generateConfigFile.cmake @@ -9,7 +9,6 @@ endif() set(EXV_ENABLE_BMFF ${EXIV2_ENABLE_BMFF}) set(EXV_ENABLE_WEBREADY ${EXIV2_ENABLE_WEBREADY}) set(EXV_HAVE_LENSDATA ${EXIV2_ENABLE_LENSDATA}) -set(EXV_HAVE_PRINTUCS2 ${EXIV2_ENABLE_PRINTUCS2}) set(EXV_PACKAGE_NAME ${PROJECT_NAME}) set(EXV_PACKAGE_VERSION ${PROJECT_VERSION}) @@ -21,7 +20,6 @@ else() endif() set(EXV_HAVE_ICONV ${ICONV_FOUND}) set(EXV_HAVE_LIBZ ${ZLIB_FOUND}) -set(EXV_UNICODE_PATH ${EXIV2_ENABLE_WIN_UNICODE}) check_cxx_symbol_exists(mmap sys/mman.h EXV_HAVE_MMAP ) check_cxx_symbol_exists(munmap sys/mman.h EXV_HAVE_MUNMAP ) diff --git a/cmake/printSummary.cmake b/cmake/printSummary.cmake index 71e4a0cf..f1e6a033 100644 --- a/cmake/printSummary.cmake +++ b/cmake/printSummary.cmake @@ -52,7 +52,6 @@ else() endif() OptionOutput( "Building BMFF support: " EXIV2_ENABLE_BMFF ) OptionOutput( "Native language support: " EXIV2_ENABLE_NLS ) -OptionOutput( "Conversion of Windows XP tags: " EXIV2_ENABLE_PRINTUCS2 ) OptionOutput( "Nikon lens database: " EXIV2_ENABLE_LENSDATA ) OptionOutput( "Building webready support: " EXIV2_ENABLE_WEBREADY ) if ( EXIV2_ENABLE_WEBREADY ) @@ -61,7 +60,6 @@ endif ( EXIV2_ENABLE_WEBREADY ) if (WIN32) OptionOutput( "Dynamic runtime override: " EXIV2_ENABLE_DYNAMIC_RUNTIME) - OptionOutput( "Unicode paths (wstring): " EXIV2_ENABLE_WIN_UNICODE ) endif() OptionOutput( "Building exiv2 command: " EXIV2_BUILD_EXIV2_COMMAND ) OptionOutput( "Building samples: " EXIV2_BUILD_SAMPLES ) diff --git a/cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake b/cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake index 2b6544fb..3245dc16 100644 --- a/cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake +++ b/cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake @@ -5,7 +5,7 @@ # *) install zlib for mingw: sudo apt install libz-mingw-w64-dev # *) mkdir buildMinGWRelease && cd buildMinGWRelease # *) cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/Ubuntu20_04_mingw-w64-x86_64.cmake -# -DEXIV2_ENABLE_XMP=OFF -DEXIV2_TEAM_EXTRA_WARNINGS=ON -DEXIV2_ENABLE_WIN_UNICODE=ON +# -DEXIV2_ENABLE_XMP=OFF -DEXIV2_TEAM_EXTRA_WARNINGS=ON set(CMAKE_SYSTEM_NAME Windows) set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp index 6bda6647..bd3c7214 100644 --- a/include/exiv2/basicio.hpp +++ b/include/exiv2/basicio.hpp @@ -241,13 +241,6 @@ namespace Exiv2 { available. */ virtual std::string path() const =0; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like path() but returns a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - virtual std::wstring wpath() const =0; -#endif /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -314,14 +307,7 @@ namespace Exiv2 { @param path The full path of a file */ explicit FileIo(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like FileIo(const std::string& path) but accepts a - unicode path in an std::wstring. - @note This constructor is only available on Windows. - */ - FileIo(const std::wstring& wpath); -#endif + //! Destructor. Flushes and closes an open file. ~FileIo() override; //@} @@ -462,14 +448,7 @@ namespace Exiv2 { @brief close the file source and set a new path. */ virtual void setPath(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like setPath(const std::string& path) but accepts a - unicode path in an std::wstring. - @note This method is only available on Windows. - */ - virtual void setPath(const std::wstring& wpath); -#endif + //@} //! @name Accessors //@{ @@ -494,13 +473,6 @@ namespace Exiv2 { bool eof() const override; //! Returns the path of the file std::string path() const override; -#ifdef EXV_UNICODE_PATH - /* - @brief Like path() but returns the unicode path of the file in an std::wstring. - @note This function is only available on Windows. - */ - virtual std::wstring wpath() const; -#endif /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -683,13 +655,6 @@ namespace Exiv2 { bool eof() const override; //! Returns a dummy path, indicating that memory access is used std::string path() const override; -#ifdef EXV_UNICODE_PATH - /* - @brief Like path() but returns a unicode dummy path in an std::wstring. - @note This function is only available on Windows. - */ - virtual std::wstring wpath() const; -#endif /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -725,14 +690,6 @@ namespace Exiv2 { //@{ //! Default constructor XPathIo(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like XPathIo(const std::string& path) but accepts a - unicode url in an std::wstring. - @note This constructor is only available on Windows. - */ - XPathIo(const std::wstring& wpath); -#endif //@} private: /*! @@ -765,14 +722,7 @@ namespace Exiv2 { //@{ //! Default constructor that reads data from stdin/data uri path and writes them to the temp file. explicit XPathIo(const std::string& orgPath); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like XPathIo(const std::string& orgPath) but accepts a - unicode url in an std::wstring. - @note This constructor is only available on Windows. - */ - XPathIo(const std::wstring& wOrgPathpath); -#endif + //! Destructor. Releases all managed memory and removes the temp file. ~XPathIo() override; //@} @@ -796,14 +746,6 @@ namespace Exiv2 { @throw Error if it fails. */ static std::string writeDataToFile(const std::string& orgPath); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like writeDataToFile(const std::string& orgPath) but accepts a - unicode url in an std::wstring. - @note This constructor is only available on Windows. - */ - static std::string writeDataToFile(const std::wstring& wOrgPath); -#endif //@} private: @@ -957,13 +899,6 @@ namespace Exiv2 { bool eof() const override; //!Returns the URL of the file. std::string path() const override; -#ifdef EXV_UNICODE_PATH - /* - @brief Like path() but returns a unicode URL path in an std::wstring. - @note This function is only available on Windows. - */ - virtual std::wstring wpath() const; -#endif /*! @brief Mark all the bNone blocks to bKnow. This avoids allocating memory @@ -1001,14 +936,7 @@ namespace Exiv2 { on demand from the server, so it avoids copying the complete file. */ explicit HttpIo(const std::string& url, size_t blockSize = 1024); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like HttpIo(const std::string& url, size_t blockSize = 1024) but accepts a - unicode url in an std::wstring. - @note This constructor is only available on Windows. - */ - HttpIo(const std::wstring& wurl, size_t blockSize = 1024); -#endif + // NOT IMPLEMENTED //! Copy constructor HttpIo(HttpIo& rhs) = delete; @@ -1039,14 +967,7 @@ namespace Exiv2 { @throw Error if it is unable to init curl pointer. */ explicit CurlIo(const std::string& url, size_t blockSize = 0); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like CurlIo(const std::string& url, size_t blockSize = 0) but accepts a - unicode url in an std::wstring. - @note This constructor is only available on Windows. - */ - CurlIo(const std::wstring& wurl, size_t blockSize = 0); -#endif + /*! @brief Write access is only available for some protocols. This method will call RemoteIo::write(const byte* data, long wcount) if the write @@ -1081,41 +1002,18 @@ namespace Exiv2 { @throw Error In case of failure. */ EXIV2API DataBuf readFile(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like readFile() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - EXIV2API DataBuf readFile(const std::wstring& wpath); -#endif /*! @brief Write DataBuf \em buf to file \em path. @return Return the number of bytes written. @throw Error In case of failure. */ EXIV2API long writeFile(const DataBuf& buf, const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like writeFile() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - EXIV2API long writeFile(const DataBuf& buf, const std::wstring& wpath); -#endif /*! @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_UNICODE_PATH - /*! - @brief Like ReplaceStringInPlace() but accepts a unicode path in an std::wstring. - @return the subject after replacing. - @note This function is only available on Windows. - */ - EXIV2API std::wstring ReplaceStringInPlace(std::wstring subject, const std::wstring& search, - const std::wstring& replace); -#endif #ifdef EXV_USE_CURL /*! @brief The callback function is called by libcurl to write the data diff --git a/include/exiv2/error.hpp b/include/exiv2/error.hpp index f31091a4..7517023a 100644 --- a/include/exiv2/error.hpp +++ b/include/exiv2/error.hpp @@ -292,13 +292,6 @@ namespace Exiv2 { is valid only as long as the BasicError object exists. */ inline const char* what() const noexcept override; -#ifdef EXV_UNICODE_PATH - /*! - @brief Return the error message as a wchar_t-string. The pointer returned by - wwhat() is valid only as long as the BasicError object exists. - */ - virtual inline const wchar_t* wwhat() const throw(); -#endif //@} private: @@ -315,17 +308,10 @@ namespace Exiv2 { std::basic_string arg2_; //!< Second argument std::basic_string arg3_; //!< Third argument std::string msg_; //!< Complete error message -#ifdef EXV_UNICODE_PATH - std::wstring wmsg_; //!< Complete error message as a wide string -#endif }; // class BasicError //! Error class used for exceptions (std::string based) typedef BasicError Error; -#ifdef EXV_UNICODE_PATH - //! Error class used for exceptions (std::wstring based) - typedef BasicError WError; -#endif // ***************************************************************************** // free functions, template and inline definitions @@ -381,14 +367,6 @@ namespace Exiv2 { return msg_.c_str(); } -#ifdef EXV_UNICODE_PATH - template - const wchar_t* BasicError::wwhat() const throw() - { - return wmsg_.c_str(); - } -#endif - #ifdef _MSC_VER # pragma warning( default : 4275 ) #endif diff --git a/include/exiv2/exif.hpp b/include/exiv2/exif.hpp index c73c970f..b3f9bd16 100644 --- a/include/exiv2/exif.hpp +++ b/include/exiv2/exif.hpp @@ -255,13 +255,6 @@ namespace Exiv2 { @return The number of bytes written. */ long writeFile(const std::string& path) const; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like writeFile() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - long writeFile(const std::wstring& wpath) const; -#endif /*! @brief Return the MIME type of the thumbnail, either \c "image/tiff" or \c "image/jpeg". @@ -272,13 +265,6 @@ namespace Exiv2 { (".tif" or ".jpg"). */ const char* extension() const; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like extension() but returns the extension in a wchar_t. - @note This function is only available on Windows. - */ - const wchar_t* wextension() const; -#endif //@} private: @@ -331,19 +317,6 @@ namespace Exiv2 { URational yres, uint16_t unit ); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like setJpegThumbnail() but accepts a unicode path in an - std::wstring. - @note This function is only available on Windows. - */ - void setJpegThumbnail( - const std::wstring& wpath, - URational xres, - URational yres, - uint16_t unit - ); -#endif /*! @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf, and size \em size. Set XResolution, YResolution and @@ -382,14 +355,6 @@ namespace Exiv2 { @note Additional existing Exif thumbnail tags are not modified. */ void setJpegThumbnail(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like setJpegThumbnail(const std::string& path) but accepts a - unicode path in an std::wstring. - @note This function is only available on Windows. - */ - void setJpegThumbnail(const std::wstring& wpath); -#endif /*! @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf, and size \em size. diff --git a/include/exiv2/futils.hpp b/include/exiv2/futils.hpp index 8bbd39df..388d7bf0 100644 --- a/include/exiv2/futils.hpp +++ b/include/exiv2/futils.hpp @@ -113,14 +113,6 @@ namespace Exiv2 */ EXIV2API Protocol fileProtocol(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like fileProtocol() but accept a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - EXIV2API Protocol fileProtocol(const std::wstring& wpath); -#endif - /*! @brief Test if a file exists. @@ -135,15 +127,6 @@ namespace Exiv2 */ EXIV2API bool fileExists(const std::string& path, bool ct = false); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like fileExists(const std::string& path, bool ct =false) but - accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - EXIV2API bool fileExists(const std::wstring& wpath, bool ct = false); -#endif - /*! @brief Get the path of file URL. @@ -152,14 +135,6 @@ namespace Exiv2 */ EXIV2API std::string pathOfFileUrl(const std::string& url); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like pathOfFileUrl(const std::string& url) but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - EXIV2API std::wstring pathOfFileUrl(const std::wstring& wurl); -#endif - /*! @brief Return a system error message and the error code (errno). See %strerror(3). diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 37b441f3..532e1997 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -548,13 +548,7 @@ namespace Exiv2 { read the remote file. */ static BasicIo::UniquePtr createIo(const std::string& path, bool useCurl = true); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like createIo() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - static BasicIo::UniquePtr createIo(const std::wstring& wpath, bool useCurl = true); -#endif + /*! @brief Create an Image subclass of the appropriate type by reading the specified file. %Image type is derived from the file @@ -569,13 +563,7 @@ namespace Exiv2 { unknown image type. */ static Image::UniquePtr open(const std::string& path, bool useCurl = true); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like open() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - static Image::UniquePtr open(const std::wstring& wpath, bool useCurl = true); -#endif + /*! @brief Create an Image subclass of the appropriate type by reading the provided memory. %Image type is derived from the memory @@ -616,13 +604,7 @@ namespace Exiv2 { @throw Error If the image type is not supported. */ static Image::UniquePtr create(int type, const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like create() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - static Image::UniquePtr create(int type, const std::wstring& wpath); -#endif + /*! @brief Create an Image subclass of the requested type by creating a new image in memory. @@ -654,13 +636,7 @@ namespace Exiv2 { @return %Image type or Image::none if the type is not recognized. */ static int getType(const std::string& path); -#ifdef EXV_UNICODE_PATH - /*! - @brief Like getType() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - static int getType(const std::wstring& wpath); -#endif + /*! @brief Returns the image type of the provided data buffer. @param data Pointer to a data buffer containing an image. The contents diff --git a/include/exiv2/preview.hpp b/include/exiv2/preview.hpp index 6f794466..6d5228d1 100644 --- a/include/exiv2/preview.hpp +++ b/include/exiv2/preview.hpp @@ -43,10 +43,6 @@ namespace Exiv2 { std::string mimeType_; //! Preview image extension. std::string extension_; -#ifdef EXV_UNICODE_PATH - //! Unicode preview image extension in an std::wstring - std::wstring wextension_; -#endif //! Preview image size in bytes. uint32_t size_; //! Preview image width in pixels or 0 for unknown width. @@ -104,13 +100,6 @@ namespace Exiv2 { @return The number of bytes written. */ long writeFile(const std::string& path) const; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like writeFile() but accepts a unicode path in an std::wstring. - @note This function is only available on Windows. - */ - long writeFile(const std::wstring& wpath) const; -#endif /*! @brief Return the MIME type of the preview image, usually either \c "image/tiff" or \c "image/jpeg". @@ -121,14 +110,6 @@ namespace Exiv2 { (".tif" or ".jpg"). */ std::string extension() const; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like extension() but returns the unicode encoded extension in - an std::wstring. - @note This function is only available on Windows. - */ - std::wstring wextension() const; -#endif /*! @brief Return the width of the preview image in pixels. */ diff --git a/include/exiv2/types.hpp b/include/exiv2/types.hpp index 23be50d5..3fcff9ab 100644 --- a/include/exiv2/types.hpp +++ b/include/exiv2/types.hpp @@ -34,10 +34,6 @@ #include #include -// MSVC macro to convert a string to a wide string -#ifdef EXV_UNICODE_PATH -# define EXV_WIDEN(t) L ## t -#endif /*! @brief Macro to make calls to member functions through a pointer more readable. @@ -373,12 +369,6 @@ namespace Exiv2 { */ EXIV2API const char* exvGettext(const char* str); -#ifdef EXV_UNICODE_PATH - //! Convert an std::string s to a unicode string returned as a std::wstring. - EXIV2API std::wstring s2ws(const std::string& s); - //! Convert a unicode std::wstring s to an std::string. - EXIV2API std::string ws2s(const std::wstring& s); -#endif /*! @brief Return a \em int64_t set to the value represented by \em s. diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 91635849..a2c335f6 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -114,11 +114,20 @@ list(APPEND APPLICATIONS remotetest) # ****************************************************************************** foreach(application ${APPLICATIONS}) target_link_libraries(${application} PRIVATE exiv2lib) + if(MSVC) + target_link_libraries(${application} PRIVATE wmain) + target_link_options(${application} PRIVATE "/ENTRY:wWinMainCRTStartup") + endif() + if (MINGW) + target_link_libraries(${application} PRIVATE wmain) + target_compile_options(${application} PRIVATE -municode) + target_link_options(${application} PRIVATE -municode) + endif() if( EXIV2_ENABLE_PNG ) target_link_libraries(${application} PRIVATE ${ZLIB_LIBRARIES} ) - if (MSVC) - set_target_properties(${application} PROPERTIES LINK_FLAGS "/ignore:4099") # Ignore missing PDBs - endif() + if (MSVC) + set_target_properties(${application} PROPERTIES LINK_FLAGS "/ignore:4099") # Ignore missing PDBs + endif() endif() endforeach() diff --git a/samples/exifprint.cpp b/samples/exifprint.cpp index 0b8daf89..1a7e8f67 100644 --- a/samples/exifprint.cpp +++ b/samples/exifprint.cpp @@ -25,25 +25,6 @@ #include #include -// https://github.com/Exiv2/exiv2/issues/468 -#if defined(EXV_UNICODE_PATH) && defined(__MINGW__) -#undef EXV_UNICODE_PATH -#endif - -#ifdef EXV_UNICODE_PATH -#define _tchar wchar_t -#define _tstrcmp wcscmp -#define _t(s) L##s -#define _tcout wcout -#define _tmain wmain -#else -#define _tchar char -#define _tstrcmp strcmp -#define _t(s) s -#define _tcout cout -#define _tmain main -#endif - // copied from src/tiffvisitor_int.cpp static const Exiv2::TagInfo* findTag(const Exiv2::TagInfo* pList,uint16_t tag) { @@ -52,31 +33,32 @@ static const Exiv2::TagInfo* findTag(const Exiv2::TagInfo* pList,uint16_t tag) } -int _tmain(int argc, _tchar* const argv[]) +int main(int argc, char* const argv[]) try { + setlocale(LC_CTYPE, ".utf8"); Exiv2::XmpParser::initialize(); ::atexit(Exiv2::XmpParser::terminate); #ifdef EXV_ENABLE_BMFF Exiv2::enableBMFF(); #endif - const _tchar* prog = argv[0]; + const char* prog = argv[0]; if (argc == 1) { - std::_tcout << _t("Usage: ") << prog << _t(" [ [--lint] path | --version | --version-test ]") << std::endl; + std::cout << "Usage: " << prog << " [ [--lint] path | --version | --version-test ]" << std::endl; return 1; } int rc = 0 ; - const _tchar* file = argv[1]; - bool bLint = _tstrcmp(file,_t("--lint")) == 0 && argc == 3; + const char* file = argv[1]; + bool bLint = strcmp(file, "--lint") == 0 && argc == 3; if ( bLint ) file= argv[2]; - if ( _tstrcmp(file,_t("--version")) == 0 ) { + if ( strcmp(file,"--version") == 0 ) { std::vector keys; Exiv2::dumpLibraryInfo(std::cout,keys); return rc; - } else if ( _tstrcmp(file,_t("--version-test")) == 0 ) { + } else if ( strcmp(file,"--version-test") == 0 ) { // verifies/test macro EXIV2_TEST_VERSION // described in include/exiv2/version.hpp std::cout << "EXV_PACKAGE_VERSION " << EXV_PACKAGE_VERSION << std::endl diff --git a/samples/exiv2json.cpp b/samples/exiv2json.cpp index 795e9871..ba754c0c 100644 --- a/samples/exiv2json.cpp +++ b/samples/exiv2json.cpp @@ -23,6 +23,7 @@ #include #include "Jzon.h" +#include #include #include #include @@ -41,20 +42,6 @@ # endif #endif -#if defined(_MSC_VER) || defined(__MINGW__) -#include -#ifndef PATH_MAX -# define PATH_MAX 512 -#endif -const char* realpath(const char* file,char* path) -{ - GetFullPathName(file,PATH_MAX,path,NULL); - return path; -} -#else -#include -#endif - struct Token { std::string n; // the name eg "History" bool a; // name is an array eg History[] @@ -249,8 +236,7 @@ void fileSystemPush(const char* path,Jzon::Node& nfs) { auto& fs = dynamic_cast(nfs); fs.Add("path",path); - char resolved_path[2000]; // PATH_MAX]; - fs.Add("realpath",realpath(path,resolved_path)); + fs.Add("realpath", std::filesystem::absolute(std::filesystem::path(path)).string()); struct stat buf; memset(&buf,0,sizeof(buf)); diff --git a/samples/geotag.cpp b/samples/geotag.cpp index d873a495..544dad44 100644 --- a/samples/geotag.cpp +++ b/samples/geotag.cpp @@ -24,6 +24,7 @@ #include #include "unused.h" +#include #include #include #include @@ -84,17 +85,6 @@ string getExifTime(time_t t); time_t parseTime(const char* ,bool bAdjust=false); int timeZoneAdjust(); -// platform specific code -#if defined(_MSC_VER) || defined(__MINGW__) -char* realpath(const char* file,char* path) -{ - char* result = (char*) malloc(_MAX_PATH); - if (result) GetFullPathName(file,_MAX_PATH,result,NULL); - return result ; - UNUSED(path); -} -#endif - // Command-line parser class Options { public: @@ -838,19 +828,13 @@ int main(int argc,const char* argv[]) if ( options.verbose ) printf("%s %s ",arg,types[type]) ; if ( type == typeImage ) { time_t t = readImageTime(std::string(arg)) ; -#ifdef __APPLE__ - char buffer[1024]; -#else - char* buffer = nullptr; -#endif - char* path = realpath(arg,buffer); - if ( t && path ) { + auto p = std::filesystem::absolute(std::filesystem::path(arg)); + std::string path = p.string(); + if ( t && !path.empty() ) { if (options.verbose) - printf("%s %ld %s", path, static_cast(t), asctime(localtime(&t))); + printf("%s %ld %s", path.c_str(), static_cast(t), asctime(localtime(&t))); gFiles.push_back(path); } - if (path && path != buffer) - ::free(path); } if ( type == typeUnknown ) { fprintf(stderr,"error: illegal syntax %s\n",arg); diff --git a/samples/werror-test.cpp b/samples/werror-test.cpp index a425e2e7..227bf232 100644 --- a/samples/werror-test.cpp +++ b/samples/werror-test.cpp @@ -40,16 +40,5 @@ int main() std::cout << "Caught Error '" << e.what() << "'\n"; } -#ifdef EXV_UNICODE_PATH - try { - throw Exiv2::WError(Exiv2::kerGeneralError, L"WARG1", L"WARG2", L"WARG3"); - } - catch (const Exiv2::WError& e) { - std::wstring wmsg = e.wwhat(); - std::string msg(wmsg.begin(), wmsg.end()); - std::cout << "Caught WError '" << msg << "'\n"; - } -#endif - return 0; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2216dcf6..b871acc8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -287,6 +287,23 @@ if(EXIV2_BUILD_EXIV2_COMMAND) target_include_directories(exiv2 PRIVATE ${Intl_INCLUDE_DIRS}) endif() + 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_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. diff --git a/src/actions.cpp b/src/actions.cpp index 1c6899d6..2d12fda6 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -40,6 +40,7 @@ #include "i18n.h" // NLS support. // + standard includes +#include #include #include #include @@ -69,6 +70,8 @@ #define _setmode(a,b) #endif +namespace fs = std::filesystem; + // ***************************************************************************** // local declarations namespace { @@ -1786,29 +1789,25 @@ namespace { return os.str(); } // tm2Str - std::string temporaryPath() - { - static int count = 0; - std::lock_guard guard(cs); + std::string temporaryPath() + { + static int count = 0; + std::lock_guard guard(cs); #if defined(_MSC_VER) || defined(__MINGW__) - char lpTempPathBuffer[MAX_PATH]; - GetTempPath(MAX_PATH,lpTempPathBuffer); - std::string tmp(lpTempPathBuffer); - tmp += "\\"; HANDLE process=0; DWORD pid = ::GetProcessId(process); #else pid_t pid = ::getpid(); - std::string tmp = "/tmp/"; #endif - std::string result = tmp + Exiv2::toString(pid) + "_" + std::to_string(count); - if (Exiv2::fileExists(result)) { - std::remove(result.c_str()); - } + /// \todo check if we can use std::tmpnam + auto p = fs::temp_directory_path() / (Exiv2::toString(pid) + "_" + std::to_string(count)); + if (fs::exists(p)) { + fs::remove(p); + } - return result; - } + return p.string(); + } int metacopy(const std::string& source, const std::string& tgt, diff --git a/src/basicio.cpp b/src/basicio.cpp index 52bc7020..4bd2d7e4 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -94,23 +94,11 @@ namespace Exiv2 { public: //! Constructor explicit Impl(std::string path); -#ifdef EXV_UNICODE_PATH - //! Constructor accepting a unicode path in an std::wstring - Impl(const std::wstring& wpath); -#endif // Enumerations //! Mode of operation enum OpMode { opRead, opWrite, opSeek }; -#ifdef EXV_UNICODE_PATH - //! Used to indicate if the path is stored as a standard or unicode string - enum WpMode { wpStandard, wpUnicode }; -#endif // DATA std::string path_; //!< (Standard) path -#ifdef EXV_UNICODE_PATH - std::wstring wpath_; //!< Unicode path - WpMode wpMode_; //!< Indicates which path is in use -#endif std::string openMode_; //!< File open mode FILE *fp_; //!< File stream pointer OpMode opMode_; //!< File open mode @@ -155,9 +143,6 @@ namespace Exiv2 { FileIo::Impl::Impl(std::string path) : path_(std::move(path)), -#ifdef EXV_UNICODE_PATH - wpMode_(wpStandard), -#endif fp_(nullptr), opMode_(opSeek), #if defined WIN32 && !defined __CYGWIN__ @@ -171,19 +156,6 @@ namespace Exiv2 { { } -#ifdef EXV_UNICODE_PATH - FileIo::Impl::Impl(const std::wstring& wpath) - : wpath_(wpath), - wpMode_(wpUnicode), - fp_(0), opMode_(opSeek), -#if defined WIN32 && !defined __CYGWIN__ - hFile_(0), hMap_(0), -#endif - pMappedArea_(0), mappedLength_(0), isMalloced_(false), isWriteable_(false) - { - } - -#endif int FileIo::Impl::switchMode(OpMode opMode) { assert(fp_ != 0); @@ -227,15 +199,7 @@ namespace Exiv2 { } openMode_ = "r+b"; opMode_ = opSeek; -#ifdef EXV_UNICODE_PATH - if (wpMode_ == wpUnicode) { - fp_ = ::_wfopen(wpath_.c_str(), s2ws(openMode_).c_str()); - } - else -#endif - { - fp_ = std::fopen(path_.c_str(), openMode_.c_str()); - } + fp_ = std::fopen(path_.c_str(), openMode_.c_str()); if (!fp_) return 1; return std::fseek(fp_, offset, SEEK_SET); } // FileIo::Impl::switchMode @@ -243,36 +207,12 @@ namespace Exiv2 { int FileIo::Impl::stat(StructStat& buf) const { int ret = 0; -#ifdef EXV_UNICODE_PATH -#ifdef _WIN64 - struct _stat64 st; - ret = ::_wstati64(wpath_.c_str(), &st); - - if (0 == ret) { - buf.st_size = static_cast(st.st_size); - buf.st_mode = st.st_mode; - buf.st_nlink = st.st_nlink; - } -#else - struct _stat st; - ret = ::_wstat(wpath_.c_str(), &st); - - if (0 == ret) { - buf.st_size = st.st_size; - buf.st_mode = st.st_mode; - buf.st_nlink = st.st_nlink; - } -#endif - else -#endif - { - struct stat st; - 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; - } + struct stat st; + 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 @@ -284,9 +224,6 @@ namespace Exiv2 { #endif { #if defined(__APPLE__) -# if defined(EXV_UNICODE_PATH) -# error No xattr API for macOS with unicode support -# endif ssize_t namebufSize = ::listxattr(src.p_->path_.c_str(), 0, 0, 0); if (namebufSize < 0) { throw Error(kerCallFailed, src.p_->path_, strError(), "listxattr"); @@ -369,13 +306,6 @@ namespace Exiv2 { { } -#ifdef EXV_UNICODE_PATH - FileIo::FileIo(const std::wstring& wpath) - : p_(new Impl(wpath)) - { - } - -#endif FileIo::~FileIo() { close(); @@ -420,28 +350,12 @@ namespace Exiv2 { { assert(p_->fp_ != 0); if (munmap() != 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), strError().c_str(), "munmap"); - } - else -#endif - { - throw Error(kerCallFailed, path(), strError(), "munmap"); - } + throw Error(kerCallFailed, path(), strError(), "munmap"); } p_->mappedLength_ = size(); p_->isWriteable_ = isWriteable; if (p_->isWriteable_ && p_->switchMode(Impl::opWrite) != 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerFailedToMapFileForReadWrite, wpath(), strError().c_str()); - } - else -#endif - { - throw Error(kerFailedToMapFileForReadWrite, path(), strError()); - } + throw Error(kerFailedToMapFileForReadWrite, path(), strError()); } #if defined EXV_HAVE_MMAP && defined EXV_HAVE_MUNMAP int prot = PROT_READ; @@ -450,15 +364,7 @@ namespace Exiv2 { } void* rc = ::mmap(nullptr, p_->mappedLength_, prot, MAP_SHARED, fileno(p_->fp_), 0); if (MAP_FAILED == rc) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), strError().c_str(), "mmap"); - } - else -#endif - { - throw Error(kerCallFailed, path(), strError(), "mmap"); - } + throw Error(kerCallFailed, path(), strError(), "mmap"); } p_->pMappedArea_ = static_cast(rc); @@ -479,76 +385,28 @@ namespace Exiv2 { HANDLE hPh = GetCurrentProcess(); HANDLE hFd = (HANDLE)_get_osfhandle(fileno(p_->fp_)); if (hFd == INVALID_HANDLE_VALUE) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), "MSG1", "_get_osfhandle"); - } - else -#endif - { - throw Error(kerCallFailed, path(), "MSG1", "_get_osfhandle"); - } + throw Error(kerCallFailed, path(), "MSG1", "_get_osfhandle"); } if (!DuplicateHandle(hPh, hFd, hPh, &p_->hFile_, 0, false, DUPLICATE_SAME_ACCESS)) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), "MSG2", "DuplicateHandle"); - } - else -#endif - { - throw Error(kerCallFailed, path(), "MSG2", "DuplicateHandle"); - } + throw Error(kerCallFailed, path(), "MSG2", "DuplicateHandle"); } p_->hMap_ = CreateFileMapping(p_->hFile_, 0, flProtect, 0, (DWORD) p_->mappedLength_, 0); if (p_->hMap_ == 0 ) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), "MSG3", "CreateFileMapping"); - } - else -#endif - { - throw Error(kerCallFailed, path(), "MSG3", "CreateFileMapping"); - } + throw Error(kerCallFailed, path(), "MSG3", "CreateFileMapping"); } void* rc = MapViewOfFile(p_->hMap_, dwAccess, 0, 0, 0); if (rc == 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), "MSG4", "CreateFileMapping"); - } - else -#endif - { - throw Error(kerCallFailed, path(), "MSG4", "CreateFileMapping"); - } + throw Error(kerCallFailed, path(), "MSG4", "CreateFileMapping"); } p_->pMappedArea_ = static_cast(rc); #else // Workaround for platforms without mmap: Read the file into memory DataBuf buf(static_cast(p_->mappedLength_)); if (read(buf.data(), buf.size()) != buf.size()) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), strError().c_str(), "FileIo::read"); - } - else -#endif - { - throw Error(kerCallFailed, path(), strError(), "FileIo::read"); - } + throw Error(kerCallFailed, path(), strError(), "FileIo::read"); } if (error()) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerCallFailed, wpath(), strError().c_str(), "FileIo::mmap"); - } - else -#endif - { - throw Error(kerCallFailed, path(), strError(), "FileIo::mmap"); - } + throw Error(kerCallFailed, path(), strError(), "FileIo::mmap"); } p_->pMappedArea_ = buf.release().first; p_->isMalloced_ = true; @@ -558,31 +416,9 @@ namespace Exiv2 { void FileIo::setPath(const std::string& path) { close(); -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - std::wstring wpath; - wpath.assign(path.begin(), path.end()); - p_->wpath_ = wpath; - } - p_->path_ = path; -#else p_->path_ = path; -#endif } -#ifdef EXV_UNICODE_PATH - void FileIo::setPath(const std::wstring& wpath) { - close(); - if (p_->wpMode_ == Impl::wpStandard) { - std::string path; - path.assign(wpath.begin(), wpath.end()); - p_->path_ = path; - } else { - p_->wpath_ = wpath; - } - } -#endif - long FileIo::write(const byte* data, long wcount) { assert(p_->fp_ != 0); @@ -626,24 +462,8 @@ namespace Exiv2 { if (open("a+b") != 0) { /// \todo Use std::filesystem once C++17 can be used // Remove the (temporary) file -#ifdef EXV_UNICODE_PATH - if (fileIo->p_->wpMode_ == Impl::wpUnicode) { - ::_wremove(fileIo->wpath().c_str()); - } - else -#endif - { - ::remove(fileIo->path().c_str()); - } -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerFileOpenFailed, wpath(), "a+b", strError().c_str()); - } - else -#endif - { - throw Error(kerFileOpenFailed, path(), "a+b", strError()); - } + ::remove(fileIo->path().c_str()); + throw Error(kerFileOpenFailed, path(), "a+b", strError()); } close(); @@ -651,26 +471,12 @@ namespace Exiv2 { mode_t origStMode = 0; std::string spf; char* pf = nullptr; -#ifdef EXV_UNICODE_PATH - std::wstring wspf; - wchar_t* wpf = 0; - if (p_->wpMode_ == Impl::wpUnicode) { - wspf = wpath(); - wpf = const_cast(wspf.c_str()); - } - else -#endif - { - spf = path(); - pf = const_cast(spf.c_str()); - } + spf = path(); + pf = const_cast(spf.c_str()); // Get the permissions of the file, or linked-to file, on platforms which have lstat #ifdef EXV_HAVE_LSTAT -# ifdef EXV_UNICODE_PATH -# error EXV_UNICODE_PATH and EXV_HAVE_LSTAT are not compatible. Stop. -# endif struct stat buf1; if (::lstat(pf, &buf1) == -1) { statOk = false; @@ -705,71 +511,6 @@ namespace Exiv2 { origStMode = buf1.st_mode; #endif // !EXV_HAVE_LSTAT - // MSVCRT rename that does not overwrite existing files -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { -#if defined(WIN32) && defined(REPLACEFILE_IGNORE_MERGE_ERRORS) - // Windows implementation that deals with the fact that ::rename fails - // if the target filename still exists, which regularly happens when - // that file has been opened with FILE_SHARE_DELETE by another process, - // like a virus scanner or disk indexer - // (see also http://stackoverflow.com/a/11023068) - using ReplaceFileW_t = BOOL(WINAPI*)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID); - HMODULE hKernel = ::GetModuleHandleA("kernel32.dll"); - if (hKernel) { - ReplaceFileW_t pfcn_ReplaceFileW = (ReplaceFileW_t)GetProcAddress(hKernel, "ReplaceFileW"); - if (pfcn_ReplaceFileW) { - BOOL ret = pfcn_ReplaceFileW(wpf, fileIo->wpath().c_str(), NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL); - if (ret == 0) { - if (GetLastError() == ERROR_FILE_NOT_FOUND) { - if (::_wrename(fileIo->wpath().c_str(), wpf) == -1) { - throw WError(kerFileRenameFailed, fileIo->wpath(), wpf, strError().c_str()); - } - ::_wremove(fileIo->wpath().c_str()); - } - else { - throw WError(kerFileRenameFailed, fileIo->wpath(), wpf, strError().c_str()); - } - } - } - else { - if (fileExists(wpf) && ::_wremove(wpf) != 0) { - throw WError(kerCallFailed, wpf, strError().c_str(), "::_wremove"); - } - if (::_wrename(fileIo->wpath().c_str(), wpf) == -1) { - throw WError(kerFileRenameFailed, fileIo->wpath(), wpf, strError().c_str()); - } - ::_wremove(fileIo->wpath().c_str()); - } - } -#else - if (fileExists(wpf) && ::_wremove(wpf) != 0) { - throw WError(kerCallFailed, wpf, strError().c_str(), "::_wremove"); - } - if (::_wrename(fileIo->wpath().c_str(), wpf) == -1) { - throw WError(kerFileRenameFailed, fileIo->wpath(), wpf, strError().c_str()); - } - ::_wremove(fileIo->wpath().c_str()); -#endif - // Check permissions of new file - struct _stat buf2; - if (statOk && ::_wstat(wpf, &buf2) == -1) { - statOk = false; -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << Error(kerCallFailed, wpf, strError(), "::_wstat") << "\n"; -#endif - } - if (statOk && origStMode != buf2.st_mode) { - // Set original file permissions - if (::_wchmod(wpf, origStMode) == -1) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << Error(kerCallFailed, wpf, strError(), "::_wchmod") << "\n"; -#endif - } - } - } // if (p_->wpMode_ == Impl::wpUnicode) - else -#endif // EXV_UNICODE_PATH { #if defined(WIN32) && defined(REPLACEFILE_IGNORE_MERGE_ERRORS) // Windows implementation that deals with the fact that ::rename fails @@ -835,26 +576,10 @@ namespace Exiv2 { else { // Generic handling, reopen both to reset to start if (open("w+b") != 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerFileOpenFailed, wpath(), "w+b", strError().c_str()); - } - else -#endif - { - throw Error(kerFileOpenFailed, path(), "w+b", strError()); - } + throw Error(kerFileOpenFailed, path(), "w+b", strError()); } if (src.open() != 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerDataSourceOpenFailed, src.wpath(), strError().c_str()); - } - else -#endif - { - throw Error(kerDataSourceOpenFailed, src.path(), strError()); - } + throw Error(kerDataSourceOpenFailed, src.path(), strError()); } write(src); src.close(); @@ -862,29 +587,13 @@ namespace Exiv2 { if (wasOpen) { if (open(lastMode) != 0) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerFileOpenFailed, wpath(), lastMode.c_str(), strError().c_str()); - } - else -#endif - { - throw Error(kerFileOpenFailed, path(), lastMode, strError()); - } + throw Error(kerFileOpenFailed, path(), lastMode, strError()); } } else close(); if (error() || src.error()) { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - throw WError(kerTransferFailed, wpath(), strError().c_str()); - } - else -#endif - { - throw Error(kerTransferFailed, path(), strError()); - } + throw Error(kerTransferFailed, path(), strError()); } } // FileIo::transfer @@ -949,16 +658,9 @@ namespace Exiv2 { close(); p_->openMode_ = mode; p_->opMode_ = Impl::opSeek; -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - p_->fp_ = ::_wfopen(wpath().c_str(), s2ws(mode).c_str()); - } - else -#endif - { - p_->fp_ = ::fopen(path().c_str(), mode.c_str()); - } - if (!p_->fp_) return 1; + p_->fp_ = ::fopen(path().c_str(), mode.c_str()); + if (!p_->fp_) + return 1; return 0; } @@ -1020,25 +722,9 @@ namespace Exiv2 { std::string FileIo::path() const { -#ifdef EXV_UNICODE_PATH - if (p_->wpMode_ == Impl::wpUnicode) { - return ws2s(p_->wpath_); - } -#endif return p_->path_; } -#ifdef EXV_UNICODE_PATH - std::wstring FileIo::wpath() const - { - if (p_->wpMode_ == Impl::wpStandard) { - return s2ws(p_->path_); - } - return p_->wpath_; - } - -#endif - void FileIo::populateFakeData() { } @@ -1363,13 +1049,6 @@ namespace Exiv2 { return "MemIo"; } -#ifdef EXV_UNICODE_PATH - std::wstring MemIo::wpath() const - { - return EXV_WIDEN("MemIo"); - } - -#endif void MemIo::populateFakeData() { } @@ -1381,15 +1060,6 @@ namespace Exiv2 { if (prot == pStdin) ReadStdin(); else if (prot == pDataUri) ReadDataUri(path); } -#ifdef EXV_UNICODE_PATH - XPathIo::XPathIo(const std::wstring& wpath) { - std::string path; - path.assign(wpath.begin(), wpath.end()); - Protocol prot = fileProtocol(path); - if (prot == pStdin) ReadStdin(); - else if (prot == pDataUri) ReadDataUri(path); - } -#endif void XPathIo::ReadStdin() { if (isatty(fileno(stdin))) @@ -1436,14 +1106,6 @@ namespace Exiv2 { tempFilePath_ = path(); } -#ifdef EXV_UNICODE_PATH - XPathIo::XPathIo(const std::wstring& wOrgPathpath) : FileIo(XPathIo::writeDataToFile(wOrgPathpath)), isTemp_(true) - { - isTemp_ = true; - tempFilePath_ = path(); - } -#endif - XPathIo::~XPathIo() { if (isTemp_ && remove(tempFilePath_.c_str()) != 0) { // error when removing file @@ -1520,13 +1182,6 @@ namespace Exiv2 { return path; } -#ifdef EXV_UNICODE_PATH - std::string XPathIo::writeDataToFile(const std::wstring& wOrgPath) { - std::string orgPath; - orgPath.assign(wOrgPath.begin(), wOrgPath.end()); - return XPathIo::writeDataToFile(orgPath); - } -#endif #endif @@ -1535,18 +1190,11 @@ namespace Exiv2 { public: //! Constructor Impl(const std::string& url, size_t blockSize); -#ifdef EXV_UNICODE_PATH - //! Constructor accepting a unicode path in an std::wstring - Impl(const std::wstring& wpath, size_t blockSize); -#endif //! Destructor. Releases all managed memory. virtual ~Impl(); // DATA std::string path_; //!< (Standard) path -#ifdef EXV_UNICODE_PATH - std::wstring wpath_; //!< Unicode path -#endif size_t blockSize_; //!< Size of the block memory. BlockMap* blocksMap_; //!< An array contains all blocksMap size_t size_; //!< The file size @@ -1607,13 +1255,6 @@ namespace Exiv2 { totalRead_(0) { } -#ifdef EXV_UNICODE_PATH - RemoteIo::Impl::Impl(const std::wstring& wurl, size_t blockSize) - : wpath_(wurl), blockSize_(blockSize), blocksMap_(0), size_(0), - idx_(0), isMalloced_(false), eof_(false), protocol_(fileProtocol(wurl)) - { - } -#endif size_t RemoteIo::Impl::populateBlocks(size_t lowBlock, size_t highBlock) { @@ -1949,13 +1590,6 @@ namespace Exiv2 { return p_->path_; } -#ifdef EXV_UNICODE_PATH - std::wstring RemoteIo::wpath() const - { - return p_->wpath_; - } -#endif - void RemoteIo::populateFakeData() { assert(p_->isMalloced_); @@ -1972,10 +1606,6 @@ namespace Exiv2 { public: //! Constructor HttpImpl(const std::string& url, size_t blockSize); -#ifdef EXV_UNICODE_PATH - //! Constructor accepting a unicode path in an std::wstring - HttpImpl(const std::wstring& wpath, size_t blockSize); -#endif Exiv2::Uri hostInfo_; //!< the host information extracted from the path // METHODS @@ -2019,17 +1649,6 @@ namespace Exiv2 { hostInfo_ = Exiv2::Uri::Parse(url); Exiv2::Uri::Decode(hostInfo_); } -#ifdef EXV_UNICODE_PATH - HttpIo::HttpImpl::HttpImpl(const std::wstring& wurl, size_t blockSize):Impl(wurl, blockSize) - { - std::string url; - url.assign(wurl.begin(), wurl.end()); - path_ = url; - - hostInfo_ = Exiv2::Uri::Parse(url); - Exiv2::Uri::Decode(hostInfo_); - } -#endif long HttpIo::HttpImpl::getFileLength() { @@ -2128,12 +1747,6 @@ namespace Exiv2 { { p_ = new HttpImpl(url, blockSize); } -#ifdef EXV_UNICODE_PATH - HttpIo::HttpIo(const std::wstring& wurl, size_t blockSize) - { - p_ = new HttpImpl(wurl, blockSize); - } -#endif #ifdef EXV_USE_CURL //! Internal Pimpl structure of class RemoteIo. @@ -2141,10 +1754,6 @@ namespace Exiv2 { public: //! Constructor CurlImpl(const std::string& path, size_t blockSize); -#ifdef EXV_UNICODE_PATH - //! Constructor accepting a unicode path in an std::wstring - CurlImpl(const std::wstring& wpath, size_t blockSize); -#endif //! Destructor. Cleans up the curl pointer and releases all managed memory. ~CurlImpl() override; @@ -2208,27 +1817,6 @@ namespace Exiv2 { throw Error(kerErrorMessage, "Timeout Environmental Variable must be a positive integer."); } } -#ifdef EXV_UNICODE_PATH - CurlIo::CurlImpl::CurlImpl(const std::wstring& wurl, size_t blockSize):Impl(wurl, blockSize) - { - std::string url; - url.assign(wurl.begin(), wurl.end()); - path_ = url; - - // init curl pointer - curl_ = curl_easy_init(); - if(!curl_) { - throw Error(kerErrorMessage, "Unable to init libcurl."); - } - - // The default block size for FTP is much larger than other protocols - // the reason is that getDataByRange() in FTP always creates the new connection, - // so we need the large block size to reduce the overhead of creating the connection. - if (blockSize_ == 0) { - blockSize_ = protocol_ == pFtp ? 102400 : 1024; - } - } -#endif long CurlIo::CurlImpl::getFileLength() { @@ -2368,12 +1956,6 @@ namespace Exiv2 { { p_ = new CurlImpl(url, blockSize); } -#ifdef EXV_UNICODE_PATH - CurlIo::CurlIo(const std::wstring& wurl, size_t blockSize) - { - p_ = new CurlImpl(wurl, blockSize); - } -#endif #endif @@ -2398,26 +1980,6 @@ namespace Exiv2 { return buf; } -#ifdef EXV_UNICODE_PATH - DataBuf readFile(const std::wstring& wpath) - { - FileIo file(wpath); - if (file.open("rb") != 0) { - throw WError(kerFileOpenFailed, wpath, "rb", strError().c_str()); - } - struct _stat st; - if (0 != ::_wstat(wpath.c_str(), &st)) { - throw WError(kerCallFailed, wpath, strError().c_str(), "::_wstat"); - } - DataBuf buf(st.st_size); - long len = file.read(buf.data(), buf.size()); - if (len != buf.size()) { - throw WError(kerCallFailed, wpath, strError().c_str(), "FileIo::read"); - } - return buf; - } - -#endif long writeFile(const DataBuf& buf, const std::string& path) { FileIo file(path); @@ -2427,17 +1989,6 @@ namespace Exiv2 { return file.write(buf.c_data(), buf.size()); } -#ifdef EXV_UNICODE_PATH - long writeFile(const DataBuf& buf, const std::wstring& wpath) - { - FileIo file(wpath); - if (file.open("wb") != 0) { - throw WError(kerFileOpenFailed, wpath, "wb", strError().c_str()); - } - return file.write(buf.c_data(), buf.size()); - } - -#endif std::string ReplaceStringInPlace(std::string subject, const std::string& search, const std::string& replace) { size_t pos = 0; @@ -2448,18 +1999,6 @@ namespace Exiv2 { return subject; } - -#ifdef EXV_UNICODE_PATH - std::wstring ReplaceStringInPlace(std::wstring subject, const std::wstring& search, - const std::wstring& replace) { - std::wstring::size_type pos = 0; - while((pos = subject.find(search, pos)) != std::wstring::npos) { - subject.replace(pos, search.length(), replace); - pos += replace.length(); - } - return subject; - } -#endif #ifdef EXV_USE_CURL size_t curlWriter(char* data, size_t size, size_t nmemb, std::string* writerData) diff --git a/src/error.cpp b/src/error.cpp index 488b1faf..81418699 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -238,49 +238,11 @@ namespace Exiv2 { } } msg_ = msg; -#ifdef EXV_UNICODE_PATH - wmsg_ = s2ws(msg); -#endif } #ifdef __APPLE__ template class EXIV2API BasicError; #endif -#ifdef EXV_UNICODE_PATH - template<> - void EXIV2API BasicError::setMsg() - { - std::string s = _(errMsg(code_)); - std::wstring wmsg(s.begin(), s.end()); - std::wstring::size_type pos; - pos = wmsg.find(L"%0"); - if (pos != std::wstring::npos) { - wmsg.replace(pos, 2, toBasicString(code_)); - } - if (count_ > 0) { - pos = wmsg.find(L"%1"); - if (pos != std::wstring::npos) { - wmsg.replace(pos, 2, arg1_); - } - } - if (count_ > 1) { - pos = wmsg.find(L"%2"); - if (pos != std::wstring::npos) { - wmsg.replace(pos, 2, arg2_); - } - } - if (count_ > 2) { - pos = wmsg.find(L"%3"); - if (pos != std::wstring::npos) { - wmsg.replace(pos, 2, arg3_); - } - } - wmsg_ = wmsg; - msg_ = ws2s(wmsg); - } - template class EXIV2API BasicError; -#endif - const char* errMsg(int code) { const ErrMsg* em = find(errList, code); diff --git a/src/exif.cpp b/src/exif.cpp index 6ebcd433..8b25c02b 100644 --- a/src/exif.cpp +++ b/src/exif.cpp @@ -110,13 +110,6 @@ namespace { (".tif", ".jpg"). */ virtual const char* extension() const =0; -#ifdef EXV_UNICODE_PATH - /*! - @brief Like extension() but returns the extension in a wchar_t. - @note This function is only available on Windows. - */ - virtual const wchar_t* wextension() const =0; -#endif //@} }; // class Thumbnail @@ -138,9 +131,6 @@ namespace { Exiv2::DataBuf copy(const Exiv2::ExifData& exifData) const override; const char* mimeType() const override; const char* extension() const override; -#ifdef EXV_UNICODE_PATH - const wchar_t* wextension() const; -#endif //@} }; // class TiffThumbnail @@ -162,9 +152,6 @@ namespace { Exiv2::DataBuf copy(const Exiv2::ExifData& exifData) const override; const char* mimeType() const override; const char* extension() const override; -#ifdef EXV_UNICODE_PATH - const wchar_t* wextension() const; -#endif //@} }; // class JpegThumbnail @@ -475,19 +462,6 @@ namespace Exiv2 { return Exiv2::writeFile(buf, name); } -#ifdef EXV_UNICODE_PATH - long ExifThumbC::writeFile(const std::wstring& wpath) const - { - auto thumbnail = Thumbnail::create(exifData_); - if (!thumbnail) - return 0; - std::wstring name = wpath + thumbnail->wextension(); - DataBuf buf(thumbnail->copy(exifData_)); - if (buf.size() == 0) return 0; - return Exiv2::writeFile(buf, name); - } - -#endif const char* ExifThumbC::mimeType() const { auto thumbnail = Thumbnail::create(exifData_); @@ -504,16 +478,6 @@ namespace Exiv2 { return thumbnail->extension(); } -#ifdef EXV_UNICODE_PATH - const wchar_t* ExifThumbC::wextension() const - { - auto thumbnail = Thumbnail::create(exifData_); - if (!thumbnail) - return EXV_WIDEN(""); - return thumbnail->wextension(); - } - -#endif ExifThumb::ExifThumb(ExifData& exifData) : ExifThumbC(exifData), exifData_(exifData) { @@ -530,19 +494,6 @@ namespace Exiv2 { setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit); } -#ifdef EXV_UNICODE_PATH - void ExifThumb::setJpegThumbnail( - const std::wstring& wpath, - URational xres, - URational yres, - uint16_t unit - ) - { - DataBuf thumb = readFile(wpath); // may throw - setJpegThumbnail(thumb.c_data(), thumb.size(), xres, yres, unit); - } - -#endif void ExifThumb::setJpegThumbnail( const byte* buf, long size, @@ -563,14 +514,6 @@ namespace Exiv2 { setJpegThumbnail(thumb.c_data(), thumb.size()); } -#ifdef EXV_UNICODE_PATH - void ExifThumb::setJpegThumbnail(const std::wstring& wpath) - { - DataBuf thumb = readFile(wpath); // may throw - setJpegThumbnail(thumb.c_data(), thumb.size()); - } - -#endif void ExifThumb::setJpegThumbnail(const byte* buf, long size) { exifData_["Exif.Thumbnail.Compression"] = uint16_t(6); @@ -909,13 +852,6 @@ namespace { return ".tif"; } -#ifdef EXV_UNICODE_PATH - const wchar_t* TiffThumbnail::wextension() const - { - return EXV_WIDEN(".tif"); - } - -#endif Exiv2::DataBuf TiffThumbnail::copy(const Exiv2::ExifData& exifData) const { Exiv2::ExifData thumb; @@ -944,13 +880,6 @@ namespace { return ".jpg"; } -#ifdef EXV_UNICODE_PATH - const wchar_t* JpegThumbnail::wextension() const - { - return EXV_WIDEN(".jpg"); - } - -#endif Exiv2::DataBuf JpegThumbnail::copy(const Exiv2::ExifData& exifData) const { Exiv2::ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat"); diff --git a/src/exiv2.cpp b/src/exiv2.cpp index c96e8bc5..fe97449d 100644 --- a/src/exiv2.cpp +++ b/src/exiv2.cpp @@ -120,6 +120,8 @@ namespace { // Main int main(int argc, char* const argv[]) { + setlocale(LC_CTYPE, ".utf8"); + Exiv2::XmpParser::initialize(); ::atexit(Exiv2::XmpParser::terminate); #ifdef EXV_ENABLE_BMFF diff --git a/src/futils.cpp b/src/futils.cpp index 1f81e3fc..0024579e 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -251,35 +251,7 @@ namespace Exiv2 { return result; } // fileProtocol -#ifdef EXV_UNICODE_PATH - Protocol fileProtocol(const std::wstring& path) { - Protocol result = pFile ; - struct { - std::wstring name ; - Protocol prot ; - bool isUrl; // path.size() > name.size() - } prots[] = - { { L"http://" ,pHttp , true } - , { L"https://" ,pHttps , true } - , { L"ftp://" ,pFtp , true } - , { L"sftp://" ,pSftp , true } - , { L"file://" ,pFileUri , true } - , { L"data://" ,pDataUri , true } - , { L"-" ,pStdin , false } - }; - for (auto&& prot : prots) { - if (result != pFile) - break; - if (path.rfind(prot.name, 0) == 0) - // URL's require data. Stdin == "-" and no further data - if (prot.isUrl ? path.size() > prot.name.size() : path.size() == prot.name.size()) - result = prot.prot; - } - - return result; - } // fileProtocol -#endif bool fileExists(const std::string& path, bool ct) { // special case: accept "-" (means stdin) @@ -294,36 +266,12 @@ namespace Exiv2 { return true; } // fileExists -#ifdef EXV_UNICODE_PATH - bool fileExists(const std::wstring& wpath, bool ct) - { - // special case: accept "-" (means stdin) - if (wpath.compare(L"-") == 0 || fileProtocol(wpath) != pFile) { - return true; - } - - struct _stat buf; - int ret = _wstat(wpath.c_str(), &buf); - if (0 != ret) return false; - if (ct && !S_ISREG(buf.st_mode)) return false; - return true; - } // fileExists - -#endif 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); } -#ifdef EXV_UNICODE_PATH - std::wstring pathOfFileUrl(const std::wstring& wurl) { - std::wstring path = wurl.substr(7); - size_t found = path.find('/'); - if (found == std::wstring::npos) return path; - else return path.substr(found); - } -#endif std::string strError() { diff --git a/src/image.cpp b/src/image.cpp index b3e3b880..dbd7e9cf 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -818,14 +818,6 @@ namespace Exiv2 { return getType(fileIo); } -#ifdef EXV_UNICODE_PATH - int ImageFactory::getType(const std::wstring& wpath) - { - FileIo fileIo(wpath); - return getType(fileIo); - } - -#endif int ImageFactory::getType(const byte* data, long size) { MemIo memIo(data, size); @@ -866,24 +858,6 @@ namespace Exiv2 { (void)(useCurl); } // ImageFactory::createIo -#ifdef EXV_UNICODE_PATH - BasicIo::UniquePtr ImageFactory::createIo(const std::wstring& wpath, bool useCurl) - { - Protocol fProt = fileProtocol(wpath); -#ifdef EXV_USE_CURL - if (useCurl && (fProt == pHttp || fProt == pHttps || fProt == pFtp)) { - return std::make_unique(wpath); - } -#endif - if (fProt == pHttp) - return std::make_unique(wpath); - if (fProt == pFileUri) - return std::make_unique(pathOfFileUrl(wpath)); - if (fProt == pStdin || fProt == pDataUri) - return std::make_unique(wpath); // may throw - return std::make_unique(wpath); - } -#endif Image::UniquePtr ImageFactory::open(const std::string& path, bool useCurl) { auto image = open(ImageFactory::createIo(path, useCurl)); // may throw @@ -892,16 +866,6 @@ namespace Exiv2 { return image; } -#ifdef EXV_UNICODE_PATH - Image::UniquePtr ImageFactory::open(const std::wstring& wpath, bool useCurl) - { - auto image = open(ImageFactory::createIo(wpath, useCurl)); // may throw - if (!image) - throw WError(kerFileContainsUnknownImageType, wpath); - return image; - } - -#endif Image::UniquePtr ImageFactory::open(const byte* data, long size) { auto io = std::make_unique(data, size); @@ -940,25 +904,6 @@ namespace Exiv2 { return image; } -#ifdef EXV_UNICODE_PATH - Image::UniquePtr ImageFactory::create(int type, - const std::wstring& wpath) - { - auto fileIo = std::make_unique(wpath); - // Create or overwrite the file, then close it - if (fileIo->open("w+b") != 0) { - throw WError(kerFileOpenFailed, wpath, "w+b", strError().c_str()); - } - fileIo->close(); - - BasicIo::UniquePtr io(std::move(fileIo)); - auto image = create(type, std::move(io)); - if (!image) - throw Error(kerUnsupportedImageType, type); - return image; - } - -#endif Image::UniquePtr ImageFactory::create(int type) { auto io = std::make_unique(); diff --git a/src/preview.cpp b/src/preview.cpp index 5748b459..4721ebd1 100644 --- a/src/preview.cpp +++ b/src/preview.cpp @@ -450,9 +450,6 @@ namespace { #endif prop.extension_ = ".dat"; } -#ifdef EXV_UNICODE_PATH - prop.wextension_ = s2ws(prop.extension_); -#endif return prop; } @@ -559,9 +556,6 @@ namespace { PreviewProperties prop = Loader::getProperties(); prop.mimeType_ = "image/jpeg"; prop.extension_ = ".jpg"; -#ifdef EXV_UNICODE_PATH - prop.wextension_ = EXV_WIDEN(".jpg"); -#endif return prop; } @@ -638,9 +632,6 @@ namespace { PreviewProperties prop = Loader::getProperties(); prop.mimeType_ = "image/jpeg"; prop.extension_ = ".jpg"; -#ifdef EXV_UNICODE_PATH - prop.wextension_ = EXV_WIDEN(".jpg"); -#endif return prop; } @@ -751,9 +742,6 @@ namespace { PreviewProperties prop = Loader::getProperties(); prop.mimeType_ = "image/tiff"; prop.extension_ = ".tif"; -#ifdef EXV_UNICODE_PATH - prop.wextension_ = EXV_WIDEN(".tif"); -#endif return prop; } @@ -881,9 +869,6 @@ namespace { PreviewProperties prop = Loader::getProperties(); prop.mimeType_ = "image/jpeg"; prop.extension_ = ".jpg"; -#ifdef EXV_UNICODE_PATH - prop.wextension_ = EXV_WIDEN(".jpg"); -#endif return prop; } @@ -1065,16 +1050,6 @@ namespace Exiv2 { return Exiv2::writeFile(buf, name); } -#ifdef EXV_UNICODE_PATH - long PreviewImage::writeFile(const std::wstring& wpath) const - { - std::wstring name = wpath + wextension(); - // Todo: Creating a DataBuf here unnecessarily copies the memory - DataBuf buf(pData(), size()); - return Exiv2::writeFile(buf, name); - } - -#endif DataBuf PreviewImage::copy() const { return DataBuf(pData(), size()); @@ -1100,13 +1075,6 @@ namespace Exiv2 { return properties_.extension_; } -#ifdef EXV_UNICODE_PATH - std::wstring PreviewImage::wextension() const - { - return properties_.wextension_; - } - -#endif uint32_t PreviewImage::width() const { return properties_.width_; diff --git a/src/tags_int.cpp b/src/tags_int.cpp index 2e142931..55ed6499 100644 --- a/src/tags_int.cpp +++ b/src/tags_int.cpp @@ -2731,7 +2731,7 @@ namespace Exiv2 { } if (!cnv) os << value; return os; - } // printUcs2 + } std::ostream& printExifUnit(std::ostream& os, const Value& value, const ExifData* metadata) { diff --git a/src/tgaimage.cpp b/src/tgaimage.cpp index e1c2e232..4db565ec 100644 --- a/src/tgaimage.cpp +++ b/src/tgaimage.cpp @@ -133,19 +133,11 @@ 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 -#ifdef EXV_UNICODE_PATH - std::wstring wpath = iIo.wpath(); - if( wpath.rfind(EXV_WIDEN(".tga")) != std::wstring::npos - || wpath.rfind(EXV_WIDEN(".TGA")) != std::wstring::npos) { - return true; - } -#else std::string path = iIo.path(); if( path.rfind(".tga") != std::string::npos || path.rfind(".TGA") != std::string::npos) { return true; } -#endif byte buf[26]; long curPos = iIo.tell(); if ( curPos < 26 ) return false; diff --git a/src/types.cpp b/src/types.cpp index 07abd7a9..ac59f9c0 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -27,9 +27,6 @@ #include "unused.h" // + standard includes -#ifdef EXV_UNICODE_PATH -# include // for MultiByteToWideChar etc -#endif #include #include #include @@ -667,32 +664,6 @@ namespace Exiv2 { #endif } -#ifdef EXV_UNICODE_PATH - std::string ws2s(const std::wstring& s) - { - int len; - int slength = (int)s.length() + 1; - len = WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, 0, 0, 0, 0); - char* buf = new char[len]; - WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, buf, len, 0, 0); - std::string r(buf); - delete[] buf; - return r; - } - - std::wstring s2ws(const std::string& s) - { - int len; - int slength = (int)s.length() + 1; - len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); - wchar_t* buf = new wchar_t[len]; - MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len); - std::wstring r(buf); - delete[] buf; - return r; - } - -#endif // EXV_UNICODE_PATH template<> bool stringTo(const std::string& s, bool& ok) { diff --git a/src/version.cpp b/src/version.cpp index a583bd19..d1982caf 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -332,7 +332,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector& keys int have_strings =0; int have_sys_types =0; int have_unistd =0; - int have_unicode_path=0; int enable_bmff =0; int enable_webready =0; @@ -437,10 +436,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector& keys have_unistd=1; #endif -#ifdef EXV_UNICODE_PATH - have_unicode_path=1; -#endif - #ifdef EXV_ENABLE_BMFF enable_bmff=1; #endif @@ -516,7 +511,6 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const std::vector& keys output(os,keys,"have_strings" ,have_strings ); output(os,keys,"have_sys_types" ,have_sys_types ); output(os,keys,"have_unistd" ,have_unistd ); - output(os,keys,"have_unicode_path" ,have_unicode_path); output(os,keys,"enable_bmff" ,enable_bmff ); output(os,keys,"enable_webready" ,enable_webready ); output(os,keys,"enable_nls" ,enable_nls ); diff --git a/src/wmain.c b/src/wmain.c new file mode 100644 index 00000000..11419863 --- /dev/null +++ b/src/wmain.c @@ -0,0 +1,40 @@ +#include + +extern int __cdecl main(); + +int wmain(int argc, wchar_t* argv[]) +{ + char** args; + int nbytes = (int)(sizeof(char*) * (argc + 1)); + HANDLE heap = GetProcessHeap(); + + for (int i = 0; i < argc; ++i) + nbytes += WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL); + + args = HeapAlloc(heap, 0, nbytes); + args[0] = (char*)(args + argc + 1); + + for (int i = 0; i < argc; ++i) + args[i+1] = args[i] + WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, args[i], nbytes, NULL, NULL); + + args[argc] = NULL; + + argc = main(argc, args); + HeapFree(heap, 0, args); + return argc; +} + +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) +{ + (void) hInstance; + (void) hPrevInstance; + (void) lpCmdLine; + (void) nCmdShow; + + int argc; + wchar_t** argv; + argv = CommandLineToArgvW(GetCommandLineW(), &argc); + argc = wmain(argc, argv); + LocalFree(argv); + return argc; +} diff --git a/tests/bash_tests/test_issue_1996.py b/tests/bash_tests/test_issue_1996.py new file mode 100644 index 00000000..e401ead9 --- /dev/null +++ b/tests/bash_tests/test_issue_1996.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +import shutil +import system_tests +import os + +@system_tests.CopyTmpFiles("$data_path/Stonehenge.heic") +class Exiv2FilePathsWithSpecialCharacters(metaclass=system_tests.CaseMeta): + url = "https://github.com/Exiv2/exiv2/issues/1996" + + # Rename temporary file so that the path contains special Greek characters + original_file = system_tests.path("$tmp_path/Stonehenge.heic") + dst_file = system_tests.path("$tmp_path/Εκκρεμότητες.heic") + + def setUp(self): + shutil.copyfile(self.original_file, self.dst_file) + + def tearDown(self): + os.remove(self.original_file) + os.remove(self.dst_file) + + commands = ["$exiv2 -K Xmp.cm2e.Father $dst_file"] + stdout = ["Xmp.cm2e.Father XmpText 11 Robin Mills\n"] + stderr = [""] + retval = [0]