diff --git a/.github/workflows/on_PR_meson.yaml b/.github/workflows/on_PR_meson.yaml index 19b4619d63..81063903e4 100644 --- a/.github/workflows/on_PR_meson.yaml +++ b/.github/workflows/on_PR_meson.yaml @@ -12,7 +12,7 @@ jobs: name: Linux-GCC${{matrix.cxx}}-deps=${{matrix.deps}} strategy: matrix: - cxx: ['7', '13'] + cxx: ['9', '13'] deps: ['forcefallback', 'default'] steps: - uses: actions/checkout@v4 @@ -23,7 +23,7 @@ jobs: run: python3 -m pip install meson ninja - name: Compile and Test run: | - meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3 + meson setup "${{github.workspace}}/build" --wrap-mode=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++2a meson compile -C "${{github.workspace}}/build" meson test -C "${{github.workspace}}/build" Ubuntu-clang: @@ -31,7 +31,7 @@ jobs: name: Linux-Clang${{matrix.cxx}}-deps=${{matrix.deps}} strategy: matrix: - cxx: ['7', '19'] + cxx: ['8', '19'] deps: ['forcefallback', 'default'] steps: - uses: actions/checkout@v4 @@ -123,7 +123,7 @@ jobs: - name: Compile and Test run: | - meson setup "${{github.workspace}}/build" -Dauto_features=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++20 + meson setup "${{github.workspace}}/build" -Dauto_features=${{matrix.deps}} -Dwarning_level=3 -Dcpp_std=c++2a meson compile -C "${{github.workspace}}/build" --verbose meson test -C "${{github.workspace}}/build" --verbose MacOS: diff --git a/README.md b/README.md index cf7003c582..4147213265 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The file ReadMe.txt in a build bundle describes how to install the library on th # Building, Installing, Using and Uninstalling Exiv2 -You need [CMake](https://cmake.org/download/) to configure the Exiv2 project, any C++ compiler implementing the C++ 17 standard and the associated tool chain. +You need [CMake](https://cmake.org/download/) to configure the Exiv2 project, any C++ compiler implementing the C++ 20 standard and the associated tool chain.
@@ -88,7 +88,7 @@ $ ctest --test-dir build --verbose # Run tests $ sudo cmake --install build # Run the install target (install library, public headers, application and CMake files) ``` -This will install the library into the "standard locations". The library will be installed in `/usr/local/lib`, executables (including the exiv2 command-line program) in `/usr/local/bin/` and header files in `/usr/local/include/exiv2`. The target directory for the installation can be modified by using the CMake option `-DCMAKE_INSTALL_PREFIX`. +This will install the library into the "standard locations". The library will be installed in `/usr/local/lib`, executables (including the exiv2 command-line program) in `/usr/local/bin/` and header files in `/usr/local/include/exiv2`. The target directory for the installation can be modified by using the CMake option `-DCMAKE_INSTALL_PREFIX`. CMake analyzes the project configuration from the source code directory and generates files into the build directory. It generates the project/solution/makefiles required to build the exiv2 library and command line application (and optionally sample applications and test runners). CMake also creates the files `exv_conf.h` and `exiv2lib_export.h` which contain compiler directives about the build options you have chosen and the availability of libraries on your machine. @@ -190,7 +190,7 @@ Preset CMake variables: -- Conan: checking conan executable -- Conan: Found program C:/dev/envs/conan/Scripts/conan.exe -- Conan: Version found Conan version 1.47.0 --- Conan executing: C:/dev/envs/conan/Scripts/conan.exe install .. --remote conancenter --build missing --options webready=True --settings arch=x86_64 --settings build_type=Release --settings compiler=Visual Studio --settings compiler.version=17 --settings compiler.runtime=MD +-- Conan executing: C:/dev/envs/conan/Scripts/conan.exe install .. --remote conancenter --build missing --options webready=True --settings arch=x86_64 --settings build_type=Release --settings compiler=Visual Studio --settings compiler.version=20 --settings compiler.runtime=MD ... # CMake finds the project dependencies which were automatically handled by conan @@ -206,7 +206,7 @@ Preset CMake variables: -- CMake Generator: Ninja -- CMAKE_BUILD_TYPE: Release -- Compiler info: MSVC (C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.30.30705/bin/Hostx64/x64/cl.exe) ; version: 19.30.30705.0 --- CMAKE_CXX_STANDARD:17 +-- CMAKE_CXX_STANDARD:20 -- --- Compiler flags --- -- General: /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP @@ -298,7 +298,7 @@ The library libiconv is a GNU library and we do not recommend using libiconv wit Exiv2 includes the file cmake/FindIconv.cmake which contains a guard to prevent CMake from finding libiconv when you build with Visual Studio. This was added because of issues reported when Visual Studio attempted to link libiconv libraries installed by Cygwin, or MinGW or gnuwin32. [https://github.com/Exiv2/exiv2/issues/1250](https://github.com/Exiv2/exiv2/issues/1250) -There are build instructions about Visual Studio in libiconv-1.16/INSTALL.window require you to install Cygwin. There is an article here about building libiconv with Visual Studio. [https://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio](https://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio). +There are build instructions about Visual Studio in libiconv-1.16/INSTALL.window require you to install Cygwin. There is an article here about building libiconv with Visual Studio. [https://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio](https://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio). If you wish to use libiconv with Visual Studio you will have to build libiconv and remove the "guard" in cmake/FindIconv.cmake. Team Exiv2 will not provide support concerning libiconv and Visual Studio. @@ -326,7 +326,7 @@ In general you need to do the following: The following is a typical command to build and link with libexiv2: ```bash -$ g++ -std=c++17 myprog.cpp -o myprog -I/usr/local/include -L/usr/local/lib -lexiv2 +$ g++ -std=c++20 myprog.cpp -o myprog -I/usr/local/include -L/usr/local/lib -lexiv2 ``` [TOC](#TOC) @@ -346,7 +346,7 @@ $ cat - > CMakeLists.txt </doc/templates` directory. If changes are made to -tag groups in the Exiv2 source code then the build files need to be updated. Any changes made +The tag webpage build files are in the `/doc/templates` directory. If changes are made to +tag groups in the Exiv2 source code then the build files need to be updated. Any changes made to individual tags in an existing tag group are automatically included. -Building the tag webpages requires building the Exiv2 sample programs and using scripts which have additional dependencies on -[BASH](https://www.gnu.org/software/bash/), [make](https://manpages.org/make), [xsltproc](https://manpages.org/xsltproc) +Building the tag webpages requires building the Exiv2 sample programs and using scripts which have additional dependencies on +[BASH](https://www.gnu.org/software/bash/), [make](https://manpages.org/make), [xsltproc](https://manpages.org/xsltproc) and [Python3](https://www.python.org/). -To build the tag webpages, first [build Exiv2 from source](#TOC) with the `-DEXIV2_BUILD_SAMPLES=ON` +To build the tag webpages, first [build Exiv2 from source](#TOC) with the `-DEXIV2_BUILD_SAMPLES=ON` option enabled. This is required as the [taglist](README-SAMPLES.md#taglist) sample program is used by one of the scripts. Next, set the `EXIV2_BINDIR` environment variable (see [Exiv2 environment variables](#EnvironmentVariables)). @@ -526,7 +526,7 @@ $ cd /doc/templates $ make ``` -After processing, the generated webpages are stored in the `/doc/templates` directory. +After processing, the generated webpages are stored in the `/doc/templates` directory. When the Exiv2 websites are updated, the generated tag webpages are reformatted before use. [TOC](#TOC) @@ -858,7 +858,7 @@ You will find that 3 tests fail at the end of the test suite. It is safe to ign ## Static and Shared Libraries -You can build either static or shared libraries. Both can be linked with either static or shared run-time libraries. You specify the shared/static with the option `-BUILD_SHARED_LIBS=ON|OFF` You specify the run-time with the option `-DEXIV2_ENABLE_DYNAMIC_RUNTIME=ON|OFF`. The default for both options default is ON. So you build shared and use the shared libraries which are `.dll` on Windows (msvc, Cygwin and MinGW/msys), `.dylib` on macOS and `.so` on Linux and UNIX. +You can build either static or shared libraries. Both can be linked with either static or shared run-time libraries. You specify the shared/static with the option `-BUILD_SHARED_LIBS=ON|OFF` You specify the run-time with the option `-DEXIV2_ENABLE_DYNAMIC_RUNTIME=ON|OFF`. The default for both options default is ON. So you build shared and use the shared libraries which are `.dll` on Windows (msvc, Cygwin and MinGW/msys), `.dylib` on macOS and `.so` on Linux and UNIX. CMake creates your build artefacts in the directories `bin` and `lib`. The `bin` directory contains your executables and .DLLs. The `lib` directory contains your static libraries. When you install exiv2, the build artefacts are copied to your system's prefix directory which by default is `/usr/local/`. If you wish to test and use your build without installing, you will have to set you PATH appropriately. Linux/Unix users should also set `LD_LIBRARY_PATH` and macOS users should set `DYLD_LIBRARY_PATH`. @@ -1005,7 +1005,7 @@ The Variable EXIV2\_PORT or EXIV2\_HTTP can be set to None to skip http tests. You can run tests directly from the build: ```bash -$ cmake -S . -B build -G "Unix Makefiles" -DEXIV2_BUILD_UNIT_TESTS=ON +$ cmake -S . -B build -G "Unix Makefiles" -DEXIV2_BUILD_UNIT_TESTS=ON ... lots of output and build summary ... $ cmake --build build ... lots of output ... @@ -1045,7 +1045,7 @@ $ > set PATH=c:\Python37;%PATH% ``` -You can execute the test suite in a similar manner to that described for UNIX-like systems. You _**must**_ provide the `-C` config option to ctest for Visual Studio builds. +You can execute the test suite in a similar manner to that described for UNIX-like systems. You _**must**_ provide the `-C` config option to ctest for Visual Studio builds. ```cmd > cd @@ -1111,7 +1111,7 @@ You can run the bugfix tests from the build directory: ```bash $ cd -$ ctest --test-dir build -R bugfix +$ ctest --test-dir build -R bugfix ``` If you wish to run in verbose mode: diff --git a/cmake/compilerFlags.cmake b/cmake/compilerFlags.cmake index dc82f2bcb9..c4129c54ae 100644 --- a/cmake/compilerFlags.cmake +++ b/cmake/compilerFlags.cmake @@ -1,7 +1,7 @@ # These flags applies to exiv2lib, the applications, and to the xmp code include(CheckCXXCompilerFlag) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) diff --git a/include/exiv2/config.h b/include/exiv2/config.h index e55bd28bbb..d509df7743 100644 --- a/include/exiv2/config.h +++ b/include/exiv2/config.h @@ -31,20 +31,6 @@ #endif #endif -#ifndef __LITTLE_ENDIAN__ -#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define __LITTLE_ENDIAN__ 1 -#endif -#endif -#endif - -#ifndef __LITTLE_ENDIAN__ -#if defined(_WIN32) || defined(__CYGWIN__) -#define __LITTLE_ENDIAN__ 1 -#endif -#endif - /* If you're using Solaris and the Solaris Studio compiler you must -library=stdcxx4 along with these inclusions below diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 339ea37e46..96b043a30b 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -301,16 +301,6 @@ class EXIV2API Image { void printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, size_t start, bool bSwap, char c, size_t depth); - /*! - @brief is the host platform bigEndian - */ - static bool isBigEndianPlatform(); - - /*! - @brief is the host platform littleEndian - */ - static bool isLittleEndianPlatform(); - static bool isStringType(uint16_t type); static bool isShortType(uint16_t type); static bool isLongType(uint16_t type); diff --git a/include/exiv2/pgfimage.hpp b/include/exiv2/pgfimage.hpp index ffd749175d..aeefc23d50 100644 --- a/include/exiv2/pgfimage.hpp +++ b/include/exiv2/pgfimage.hpp @@ -55,7 +55,6 @@ class EXIV2API PgfImage : public Image { //@} private: - bool bSwap_; // true for bigEndian hardware, else false /*! @brief Provides the main implementation of writeMetadata() by writing all buffered metadata to the provided BasicIo. @@ -71,7 +70,6 @@ class EXIV2API PgfImage : public Image { //! Read header structure. DataBuf readPgfHeaderStructure(BasicIo& iIo, uint32_t& width, uint32_t& height) const; //@} - }; // class PgfImage // ***************************************************************************** diff --git a/meson.build b/meson.build index faceff630c..5c4131794a 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,7 @@ project( 'cpp', version: '1.0.0', meson_version: '>=0.54.1', - default_options: ['warning_level=0', 'cpp_std=c++17'], + default_options: ['warning_level=0', 'cpp_std=c++20'], ) cargs = [] diff --git a/src/asfvideo.cpp b/src/asfvideo.cpp index 9fa5e089e1..db8d7cfba0 100644 --- a/src/asfvideo.cpp +++ b/src/asfvideo.cpp @@ -2,6 +2,7 @@ // included header files #include "asfvideo.hpp" +#include #include #include #include @@ -51,11 +52,9 @@ AsfVideo::GUIDTag::GUIDTag(const uint8_t* bytes) { std::memcpy(&data2_, bytes + DWORD, WORD); std::memcpy(&data3_, bytes + DWORD + WORD, WORD); std::copy(bytes + QWORD, bytes + 2 * QWORD, data4_.begin()); - if (isBigEndianPlatform()) { - data1_ = byteSwap(data1_, true); - data2_ = byteSwap(data2_, true); - data3_ = byteSwap(data3_, true); - } + data1_ = byteSwap(data1_, std::endian::native == std::endian::big); + data2_ = byteSwap(data2_, std::endian::native == std::endian::big); + data3_ = byteSwap(data3_, std::endian::native == std::endian::big); } std::string AsfVideo::GUIDTag::to_string() { diff --git a/src/bmffimage.cpp b/src/bmffimage.cpp index a945b12cce..03bbd6ed03 100644 --- a/src/bmffimage.cpp +++ b/src/bmffimage.cpp @@ -21,6 +21,7 @@ #endif // + standard includes +#include #include #include #include @@ -88,7 +89,7 @@ BmffImage::BmffImage(BasicIo::UniquePtr io, bool /* create */, size_t max_box_de std::string BmffImage::toAscii(uint32_t n) { const auto p = reinterpret_cast(&n); std::string result(p, p + 4); - if (!isBigEndianPlatform()) + if constexpr (std::endian::native == std::endian::little) std::reverse(result.begin(), result.end()); // show 0 as _ std::replace(result.begin(), result.end(), '\0', '_'); diff --git a/src/easyaccess.cpp b/src/easyaccess.cpp index d9e4ea560e..c2f7a8e08b 100644 --- a/src/easyaccess.cpp +++ b/src/easyaccess.cpp @@ -16,6 +16,16 @@ using namespace Exiv2; @param keys Array of keys to look for @param count Number of elements in the array */ +template +ExifData::const_iterator findMetadatum(const ExifData& ed) { + for (const auto& k : keys) { + auto pos = ed.findKey(ExifKey(k)); + if (pos != ed.end()) + return pos; + } + return ed.end(); +} // findMetadatum + ExifData::const_iterator findMetadatum(const ExifData& ed, const char* const keys[], size_t count) { for (size_t i = 0; i < count; ++i) { auto pos = ed.findKey(ExifKey(keys[i])); @@ -60,7 +70,7 @@ ExifData::const_iterator orientation(const ExifData& ed) { "Exif.Sony1MltCsA100.Rotation", "Exif.Sony1Cs.Rotation", "Exif.Sony2Cs.Rotation", "Exif.Sony1Cs2.Rotation", "Exif.Sony2Cs2.Rotation", "Exif.Sony1MltCsA100.Rotation", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator isoSpeed(const ExifData& ed) { @@ -142,7 +152,7 @@ ExifData::const_iterator isoSpeed(const ExifData& ed) { // ISO value (see EXIF 2.3 Annex G) int64_t iso_tmp_val = -1; while (iso_tmp_val == -1 && (iso_val == 65535 || md == ed.end())) { - auto md_st = findMetadatum(ed, sensitivityType, std::size(sensitivityType)); + auto md_st = findMetadatum(ed); // no SensitivityType? exit with existing data if (md_st == ed.end()) break; @@ -185,7 +195,7 @@ ExifData::const_iterator dateTimeOriginal(const ExifData& ed) { "Exif.Photo.DateTimeOriginal", "Exif.Image.DateTimeOriginal", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator flashBias(const ExifData& ed) { @@ -194,7 +204,7 @@ ExifData::const_iterator flashBias(const ExifData& ed) { "Exif.OlympusCs.FlashExposureComp", "Exif.Minolta.FlashExposureComp", "Exif.SonyMinolta.FlashExposureComp", "Exif.Sony1.FlashExposureComp", "Exif.Sony2.FlashExposureComp", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator exposureMode(const ExifData& ed) { @@ -206,7 +216,7 @@ ExifData::const_iterator exposureMode(const ExifData& ed) { "Exif.Sony2Cs.ExposureProgram", "Exif.Sony1MltCsA100.ExposureMode", "Exif.SonyMisc2b.ExposureProgram", "Exif.Sigma.ExposureMode", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator sceneMode(const ExifData& ed) { @@ -225,7 +235,7 @@ ExifData::const_iterator sceneMode(const ExifData& ed) { "Exif.Pentax.PictureMode", "Exif.PentaxDng.PictureMode", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator macroMode(const ExifData& ed) { @@ -234,7 +244,7 @@ ExifData::const_iterator macroMode(const ExifData& ed) { "Exif.OlympusCs.MacroMode", "Exif.Panasonic.Macro", "Exif.MinoltaCsNew.MacroMode", "Exif.MinoltaCsOld.MacroMode", "Exif.Sony1.Macro", "Exif.Sony2.Macro", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator imageQuality(const ExifData& ed) { @@ -251,7 +261,7 @@ ExifData::const_iterator imageQuality(const ExifData& ed) { "Exif.Sony1MltCsA100.Quality", "Exif.Casio.Quality", "Exif.Casio2.QualityMode", "Exif.Casio2.Quality", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator whiteBalance(const ExifData& ed) { @@ -266,7 +276,7 @@ ExifData::const_iterator whiteBalance(const ExifData& ed) { "Exif.SonyMinolta.WhiteBalance", "Exif.Casio.WhiteBalance", "Exif.Casio2.WhiteBalance", "Exif.Casio2.WhiteBalance2", "Exif.Photo.WhiteBalance", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator lensName(const ExifData& ed) { @@ -300,7 +310,7 @@ ExifData::const_iterator saturation(const ExifData& ed) { "Exif.Sony2.Saturation", "Exif.Casio.Saturation", "Exif.Casio2.Saturation", "Exif.Casio2.Saturation2", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator sharpness(const ExifData& ed) { @@ -312,7 +322,7 @@ ExifData::const_iterator sharpness(const ExifData& ed) { "Exif.Sony1.Sharpness", "Exif.Sony2.Sharpness", "Exif.Casio.Sharpness", "Exif.Casio2.Sharpness", "Exif.Casio2.Sharpness2", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator contrast(const ExifData& ed) { @@ -324,7 +334,7 @@ ExifData::const_iterator contrast(const ExifData& ed) { "Exif.Sony1.Contrast", "Exif.Sony2.Contrast", "Exif.Casio.Contrast", "Exif.Casio2.Contrast", "Exif.Casio2.Contrast2", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator sceneCaptureType(const ExifData& ed) { @@ -332,7 +342,7 @@ ExifData::const_iterator sceneCaptureType(const ExifData& ed) { "Exif.Photo.SceneCaptureType", "Exif.Olympus.SpecialMode", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator meteringMode(const ExifData& ed) { @@ -343,7 +353,7 @@ ExifData::const_iterator meteringMode(const ExifData& ed) { "Exif.Sony1.MeteringMode2", "Exif.Sony1Cs.MeteringMode", "Exif.Sony1Cs2.MeteringMode", "Exif.Sony2.MeteringMode2", "Exif.Sony2Cs.MeteringMode", "Exif.Sony1MltCsA100.MeteringMode", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator make(const ExifData& ed) { @@ -351,7 +361,7 @@ ExifData::const_iterator make(const ExifData& ed) { "Exif.Image.Make", "Exif.PanasonicRaw.Make", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator model(const ExifData& ed) { @@ -365,7 +375,7 @@ ExifData::const_iterator model(const ExifData& ed) { "Exif.Sony1.SonyModelID", "Exif.Sony2.SonyModelID", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator exposureTime(const ExifData& ed) { @@ -373,7 +383,7 @@ ExifData::const_iterator exposureTime(const ExifData& ed) { "Exif.Photo.ExposureTime", "Exif.Image.ExposureTime", "Exif.Pentax.ExposureTime", "Exif.PentaxDng.ExposureTime", "Exif.Samsung2.ExposureTime", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator fNumber(const ExifData& ed) { @@ -381,7 +391,7 @@ ExifData::const_iterator fNumber(const ExifData& ed) { "Exif.Photo.FNumber", "Exif.Image.FNumber", "Exif.Pentax.FNumber", "Exif.PentaxDng.FNumber", "Exif.Samsung2.FNumber", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator shutterSpeedValue(const ExifData& ed) { @@ -389,7 +399,7 @@ ExifData::const_iterator shutterSpeedValue(const ExifData& ed) { "Exif.Photo.ShutterSpeedValue", "Exif.Image.ShutterSpeedValue", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator apertureValue(const ExifData& ed) { @@ -398,7 +408,7 @@ ExifData::const_iterator apertureValue(const ExifData& ed) { "Exif.Image.ApertureValue", "Exif.CanonSi.ApertureValue", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator brightnessValue(const ExifData& ed) { @@ -408,7 +418,7 @@ ExifData::const_iterator brightnessValue(const ExifData& ed) { "Exif.Sony1.Brightness", "Exif.Sony2.Brightness", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator exposureBiasValue(const ExifData& ed) { @@ -416,7 +426,7 @@ ExifData::const_iterator exposureBiasValue(const ExifData& ed) { "Exif.Photo.ExposureBiasValue", "Exif.Image.ExposureBiasValue", "Exif.MinoltaCs5D.ExposureManualBias", "Exif.OlympusRd.ExposureBiasValue", "Exif.OlympusRd2.ExposureBiasValue", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator maxApertureValue(const ExifData& ed) { @@ -426,7 +436,7 @@ ExifData::const_iterator maxApertureValue(const ExifData& ed) { "Exif.CanonCs.MaxAperture", "Exif.NikonLd4.MaxAperture", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator subjectDistance(const ExifData& ed) { @@ -446,7 +456,7 @@ ExifData::const_iterator lightSource(const ExifData& ed) { "Exif.Photo.LightSource", "Exif.Image.LightSource", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator flash(const ExifData& ed) { @@ -454,7 +464,7 @@ ExifData::const_iterator flash(const ExifData& ed) { "Exif.Photo.Flash", "Exif.Image.Flash", "Exif.Pentax.Flash", "Exif.PentaxDng.Flash", "Exif.Sony1.FlashAction", "Exif.Sony2.FlashAction", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator serialNumber(const ExifData& ed) { @@ -467,7 +477,7 @@ ExifData::const_iterator serialNumber(const ExifData& ed) { "Exif.PentaxDng.SerialNumber", "Exif.Sigma.SerialNumber", "Exif.Sony1.SerialNumber", "Exif.Sony2.SerialNumber", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator focalLength(const ExifData& ed) { @@ -485,7 +495,7 @@ ExifData::const_iterator subjectArea(const ExifData& ed) { "Exif.Photo.SubjectArea", "Exif.Image.SubjectLocation", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator flashEnergy(const ExifData& ed) { @@ -493,7 +503,7 @@ ExifData::const_iterator flashEnergy(const ExifData& ed) { "Exif.Photo.FlashEnergy", "Exif.Image.FlashEnergy", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator exposureIndex(const ExifData& ed) { @@ -501,7 +511,7 @@ ExifData::const_iterator exposureIndex(const ExifData& ed) { "Exif.Photo.ExposureIndex", "Exif.Image.ExposureIndex", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator sensingMethod(const ExifData& ed) { @@ -509,7 +519,7 @@ ExifData::const_iterator sensingMethod(const ExifData& ed) { "Exif.Photo.SensingMethod", "Exif.Image.SensingMethod", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } ExifData::const_iterator afPoint(const ExifData& ed) { @@ -539,7 +549,7 @@ ExifData::const_iterator afPoint(const ExifData& ed) { "Exif.Casio.AFPoint", "Exif.Casio2.AFPointPosition", }; - return findMetadatum(ed, keys, std::size(keys)); + return findMetadatum(ed); } } // namespace Exiv2 diff --git a/src/epsimage.cpp b/src/epsimage.cpp index 2e2241b69c..99c628447d 100644 --- a/src/epsimage.cpp +++ b/src/epsimage.cpp @@ -377,13 +377,13 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList bool significantLine = true; #endif // nested documents - if (posPage == posEndEps && (startsWith(line, "%%IncludeDocument:") || startsWith(line, "%%BeginDocument:"))) { + if (posPage == posEndEps && (line.starts_with("%%IncludeDocument:") || line.starts_with("%%BeginDocument:"))) { #ifndef SUPPRESS_WARNINGS EXV_WARNING << "Nested document at invalid position: " << startPos << "\n"; #endif throw Error(write ? ErrorCode::kerImageWriteFailed : ErrorCode::kerFailedToReadImageData); } - if (startsWith(line, "%%BeginDocument:")) { + if (line.starts_with("%%BeginDocument:")) { if (depth == maxDepth) { #ifndef SUPPRESS_WARNINGS EXV_WARNING << "Document too deeply nested at position: " << startPos << "\n"; @@ -391,7 +391,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList throw Error(write ? ErrorCode::kerImageWriteFailed : ErrorCode::kerFailedToReadImageData); } depth++; - } else if (startsWith(line, "%%EndDocument")) { + } else if (line.starts_with("%%EndDocument")) { if (depth == 0) { #ifndef SUPPRESS_WARNINGS EXV_WARNING << "Unmatched EndDocument at position: " << startPos << "\n"; @@ -413,7 +413,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList if (depth != 0) continue; // explicit "Begin" comments - if (startsWith(line, "%%BeginPreview:")) { + if (line.starts_with("%%BeginPreview:")) { inDefaultsPreviewPrologSetup = true; } else if (line == "%%BeginDefaults") { inDefaultsPreviewPrologSetup = true; @@ -421,9 +421,9 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList inDefaultsPreviewPrologSetup = true; } else if (line == "%%BeginSetup") { inDefaultsPreviewPrologSetup = true; - } else if (posPage == posEndEps && startsWith(line, "%%Page:")) { + } else if (posPage == posEndEps && line.starts_with("%%Page:")) { posPage = startPos; - } else if (posPage != posEndEps && startsWith(line, "%%Page:")) { + } else if (posPage != posEndEps && line.starts_with("%%Page:")) { if (implicitPage) { #ifndef SUPPRESS_WARNINGS EXV_WARNING << "Page at position " << startPos << " conflicts with implicit page at position: " << posPage @@ -528,27 +528,27 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList #endif } // remaining explicit comments - if (posEndComments == posEndEps && posLanguageLevel == posEndEps && startsWith(line, "%%LanguageLevel:")) { + if (posEndComments == posEndEps && posLanguageLevel == posEndEps && line.starts_with("%%LanguageLevel:")) { posLanguageLevel = startPos; - } else if (posEndComments == posEndEps && posContainsXmp == posEndEps && startsWith(line, "%ADO_ContainsXMP:")) { + } else if (posEndComments == posEndEps && posContainsXmp == posEndEps && line.starts_with("%ADO_ContainsXMP:")) { posContainsXmp = startPos; - } else if (posEndComments == posEndEps && posPages == posEndEps && startsWith(line, "%%Pages:")) { + } else if (posEndComments == posEndEps && posPages == posEndEps && line.starts_with("%%Pages:")) { posPages = startPos; - } else if (posEndComments == posEndEps && posExiv2Version == posEndEps && startsWith(line, "%Exiv2Version:")) { + } else if (posEndComments == posEndEps && posExiv2Version == posEndEps && line.starts_with("%Exiv2Version:")) { posExiv2Version = startPos; - } else if (posEndComments == posEndEps && posExiv2Website == posEndEps && startsWith(line, "%Exiv2Website:")) { + } else if (posEndComments == posEndEps && posExiv2Website == posEndEps && line.starts_with("%Exiv2Website:")) { posExiv2Website = startPos; - } else if (posEndComments == posEndEps && startsWith(line, "%%Creator: Adobe Illustrator") && + } else if (posEndComments == posEndEps && line.starts_with("%%Creator: Adobe Illustrator") && firstLine == "%!PS-Adobe-3.0 EPSF-3.0") { illustrator8 = true; - } else if (posEndComments == posEndEps && startsWith(line, "%AI7_Thumbnail:")) { + } else if (posEndComments == posEndEps && line.starts_with("%AI7_Thumbnail:")) { posAi7Thumbnail = startPos; } else if (posEndComments == posEndEps && posAi7Thumbnail != posEndEps && posAi7ThumbnailEndData == posEndEps && line == "%%EndData") { posAi7ThumbnailEndData = startPos; } else if (posEndComments == posEndEps && line == "%%EndComments") { posEndComments = startPos; - } else if (inDefaultsPreviewPrologSetup && startsWith(line, "%%BeginResource: procset wCorel")) { + } else if (inDefaultsPreviewPrologSetup && line.starts_with("%%BeginResource: procset wCorel")) { corelDraw = true; } else if (line == "%%EndPreview") { inDefaultsPreviewPrologSetup = false; @@ -562,7 +562,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList posEndPageSetup = startPos; } else if (posPageTrailer == posEndEps && line == "%%PageTrailer") { posPageTrailer = startPos; - } else if (posBeginPhotoshop == posEndEps && startsWith(line, "%BeginPhotoshop:")) { + } else if (posBeginPhotoshop == posEndEps && line.starts_with("%BeginPhotoshop:")) { posBeginPhotoshop = pos; } else if (posBeginPhotoshop != posEndEps && posEndPhotoshop == posEndEps && line == "%EndPhotoshop") { posEndPhotoshop = startPos; @@ -670,7 +670,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList EXV_DEBUG << "readWriteEpsMetadata: Using flexible XMP embedding\n"; #endif const size_t posBeginXmlPacket = readPrevLine(line, data, xmpPos, posEndEps); - if (startsWith(line, "%begin_xml_packet:")) { + if (line.starts_with("%begin_xml_packet:")) { #ifdef DEBUG EXV_DEBUG << "readWriteEpsMetadata: XMP embedding contains %begin_xml_packet\n"; #endif @@ -898,7 +898,7 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList writeTemp(tempIo, "%%EndComments" + lineEnding); } } - if (pos == posPage && !startsWith(line, "%%Page:")) { + if (pos == posPage && !line.starts_with("%%Page:")) { writeTemp(tempIo, "%%Page: 1 1" + lineEnding); writeTemp(tempIo, "%%EndPageComments" + lineEnding); } diff --git a/src/futils.cpp b/src/futils.cpp index 5ddb10a752..72598ba596 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -221,7 +221,7 @@ Protocol fileProtocol(const std::string& path) { if (result != pFile) break; - if (Exiv2::Internal::startsWith(path, prot.name)) + if (path.starts_with(prot.name)) // 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; diff --git a/src/image.cpp b/src/image.cpp index e14dba586e..cd1947546f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -173,38 +173,6 @@ bool Image::isPrintICC(uint16_t type, Exiv2::PrintStructureOption option) { return type == 0x8773 && option == kpsIccProfile; } -bool Image::isBigEndianPlatform() { -#ifdef __cpp_lib_endian - return std::endian::native == std::endian::big; -#elif defined(__LITTLE_ENDIAN__) - return false; -#elif defined(__BIG_ENDIAN__) - return true; -#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return true; -#else - return false; -#endif -#else - union { - uint32_t i; - char c[4]; - } e = {0x01000000}; - - return e.c[0] != 0; -#endif -} -bool Image::isLittleEndianPlatform() { -#ifdef __cpp_lib_endian - return std::endian::native == std::endian::little; -#elif defined(__LITTLE_ENDIAN__) - return true; -#else - return !isBigEndianPlatform(); -#endif -} - uint64_t Image::byteSwap(uint64_t value, bool bSwap) { #ifdef __cpp_lib_byteswap return bSwap ? std::byteswap(value) : value; @@ -548,7 +516,8 @@ void Image::printTiffStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruc // read header (we already know for certain that we have a Tiff file) io.readOrThrow(dir.data(), 8, ErrorCode::kerCorruptedMetadata); auto c = dir.read_uint8(0); - bool bSwap = (c == 'M' && isLittleEndianPlatform()) || (c == 'I' && isBigEndianPlatform()); + bool bSwap = (c == 'M' && std::endian::native == std::endian::little) || + (c == 'I' && std::endian::native == std::endian::big); size_t start = byteSwap4(dir, 4, bSwap); printIFDStructure(io, out, option, start + offset, bSwap, c, depth); } diff --git a/src/jp2image.cpp b/src/jp2image.cpp index 9485a28643..da0403e4f3 100644 --- a/src/jp2image.cpp +++ b/src/jp2image.cpp @@ -18,6 +18,7 @@ #include #include +#include #include namespace Exiv2 { @@ -100,7 +101,7 @@ Jp2Image::Jp2Image(BasicIo::UniquePtr io, bool create) : Image(ImageType::jp2, m // Obtains the ascii version from the box.type std::string Jp2Image::toAscii(uint32_t n) { const auto p = reinterpret_cast(&n); - if (isBigEndianPlatform()) + if constexpr (std::endian::native == std::endian::big) return std::string(p, p + 4); std::string result(p, p + 4); std::reverse(result.begin(), result.end()); diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 81452f45e6..2e967a1d63 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -34,7 +34,6 @@ using ULONG = uint32_t; namespace Exiv2 { using Exiv2::Internal::enforce; -using Exiv2::Internal::startsWith; namespace { // JPEG Segment markers (The first byte is always 0xFF, the value of these constants correspond to the 2nd byte) constexpr byte sos_ = 0xda; //!< JPEG SOS marker @@ -409,7 +408,7 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, si // 2 | 0xe1 APP1 | 911 | Exif..MM.*.......%.........#.... // 915 | 0xe1 APP1 | 870 | http://ns.adobe.com/xap/1.0/.count() == 128 && lensInfo->toUint32(1) == 168 && + if (model.starts_with("PENTAX K-3") && lensInfo->count() == 128 && lensInfo->toUint32(1) == 168 && lensInfo->toUint32(2) == 144) index = 7; } @@ -1207,15 +1207,15 @@ static std::ostream& resolveLens0x319(std::ostream& os, const Value& value, cons const auto lensInfo = findLensInfo(metadata); if (value.count() == 4) { std::string model = getKeyString("Exif.Image.Model", metadata); - if (startsWith(model, "PENTAX K-3") && lensInfo->count() == 128 && lensInfo->toUint32(1) == 131 && + if (model.starts_with("PENTAX K-3") && lensInfo->count() == 128 && lensInfo->toUint32(1) == 131 && lensInfo->toUint32(2) == 128) index = 6; } if (value.count() == 2) { std::string model = getKeyString("Exif.Image.Model", metadata); - if (startsWith(model, "PENTAX K100D") && lensInfo->count() == 44) + if (model.starts_with("PENTAX K100D") && lensInfo->count() == 44) index = 6; - if (startsWith(model, "PENTAX *ist DL") && lensInfo->count() == 36) + if (model.starts_with("PENTAX *ist DL") && lensInfo->count() == 36) index = 6; } diff --git a/src/pgfimage.cpp b/src/pgfimage.cpp index 538b5bd9f4..c058583ebd 100644 --- a/src/pgfimage.cpp +++ b/src/pgfimage.cpp @@ -10,6 +10,7 @@ #include "futils.hpp" #include "image.hpp" +#include #include // Signature from front of PGF file @@ -54,7 +55,7 @@ static uint32_t byteSwap_(Exiv2::DataBuf& buf, size_t offset, bool bSwap) { } PgfImage::PgfImage(BasicIo::UniquePtr io, bool create) : - Image(ImageType::pgf, mdExif | mdIptc | mdXmp | mdComment, std::move(io)), bSwap_(isBigEndianPlatform()) { + Image(ImageType::pgf, mdExif | mdIptc | mdXmp | mdComment, std::move(io)) { if (create && io_->open() == 0) { #ifdef EXIV2_DEBUG_MESSAGES std::cerr << "Exiv2::PgfImage:: Creating PGF image to memory\n"; @@ -184,7 +185,7 @@ void PgfImage::doWriteMetadata(BasicIo& outIo) { auto newHeaderSize = static_cast(header.size() + imgSize); DataBuf buffer(4); std::copy_n(&newHeaderSize, sizeof(uint32_t), buffer.data()); - byteSwap_(buffer, 0, bSwap_); + byteSwap_(buffer, 0, std::endian::native == std::endian::big); if (outIo.write(buffer.c_data(), 4) != 4) throw Error(ErrorCode::kerImageWriteFailed); @@ -243,7 +244,7 @@ size_t PgfImage::readPgfHeaderSize(BasicIo& iIo) const { if (bufRead != buffer.size()) throw Error(ErrorCode::kerInputDataReadFailed); - auto headerSize = static_cast(byteSwap_(buffer, 0, bSwap_)); + auto headerSize = static_cast(byteSwap_(buffer, 0, std::endian::native == std::endian::big)); if (headerSize == 0) throw Error(ErrorCode::kerNoImageInInputData); @@ -264,8 +265,8 @@ DataBuf PgfImage::readPgfHeaderStructure(BasicIo& iIo, uint32_t& width, uint32_t DataBuf work(8); // don't disturb the binary data - doWriteMetadata reuses it std::copy_n(header.c_data(), 8, work.begin()); - width = byteSwap_(work, 0, bSwap_); - height = byteSwap_(work, 4, bSwap_); + width = byteSwap_(work, 0, std::endian::native == std::endian::big); + height = byteSwap_(work, 4, std::endian::native == std::endian::big); /* NOTE: properties not yet used byte nLevels = buffer.pData_[8]; diff --git a/src/sonymn_int.cpp b/src/sonymn_int.cpp index 99a3ccae4e..909f66f333 100644 --- a/src/sonymn_int.cpp +++ b/src/sonymn_int.cpp @@ -983,8 +983,8 @@ std::ostream& SonyMakerNote::printFocusMode2(std::ostream& os, const Value& valu const auto v0 = value.toUint32(0); constexpr std::array models{"DSC-RX10M4", "DSC-RX100M6", "DSC-RX100M7", "DSC-RX100M5A", "DSC-HX99", "DSC-RX0M2"}; - if (!startsWith(model, "DSC-") || - std::any_of(models.begin(), models.end(), [&model](auto m) { return startsWith(model, m); })) { + if (!model.starts_with("DSC-") || + std::any_of(models.begin(), models.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyFocusMode2)(os, v0, metadata); return os; } @@ -1010,19 +1010,19 @@ std::ostream& SonyMakerNote::printAFAreaModeSetting(std::ostream& os, const Valu const auto v0 = value.toUint32(0); constexpr std::array models1{"SLT-", "HV"}; - if (std::any_of(models1.begin(), models1.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models1.begin(), models1.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyAFAreaModeSettingSet1)(os, v0, metadata); return os; } constexpr std::array models2{"NEX-", "ILCE-", "ILME-", "DSC-RX10M4", "DSC-RX100M6", "DSC-RX100M7", "DSC-RX100M5A", "DSC-HX99", "DSC-RX0M2"}; - if (std::any_of(models2.begin(), models2.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models2.begin(), models2.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyAFAreaModeSettingSet2)(os, v0, metadata); return os; } - if (startsWith(model, "ILCA-")) { + if (model.starts_with("ILCA-")) { EXV_PRINT_TAG(sonyAFAreaModeSettingSet3)(os, v0, metadata); return os; } @@ -1047,7 +1047,7 @@ std::ostream& SonyMakerNote::printFlexibleSpotPosition(std::ostream& os, const V constexpr std::array models{"NEX-", "ILCE-", "ILME-", "DSC-RX10M4", "DSC-RX100M6", "DSC-RX100M7", "DSC-RX100M5A", "DSC-HX99", "DSC-RX0M2"}; - if (std::any_of(models.begin(), models.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models.begin(), models.end(), [&model](auto m) { return model.starts_with(m); })) { os << value.toUint32(0) << ", " << value.toUint32(1); return os; } @@ -1077,29 +1077,29 @@ std::ostream& SonyMakerNote::printAFPointSelected(std::ostream& os, const Value& constexpr std::array models3{"ILCA-68", "ILCA-77M2"}; constexpr std::array models4{"NEX-", "ILCE-", "ILME-"}; - if (std::any_of(models1.begin(), models1.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models1.begin(), models1.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyAFPointSelectedSet1)(os, value.toUint32(0), metadata); return os; } - if (std::any_of(models2.begin(), models2.end(), [&model](auto m) { return startsWith(model, m); }) && status && + if (std::any_of(models2.begin(), models2.end(), [&model](auto& m) { return model.starts_with(m); }) && status && aFAreaModeSetting == 4) { EXV_PRINT_TAG(sonyAFPointSelectedSet1)(os, value.toUint32(0), metadata); return os; } - if (std::any_of(models3.begin(), models3.end(), [&model](auto m) { return startsWith(model, m); }) && status && + if (std::any_of(models3.begin(), models3.end(), [&model](auto m) { return model.starts_with(m); }) && status && aFAreaModeSetting != 8) { EXV_PRINT_TAG(sonyAFPointSelectedSet2)(os, value, metadata); return os; } - if (startsWith(model, "ILCA-99M2") && status && aFAreaModeSetting != 8) { + if (model.starts_with("ILCA-99M2") && status && aFAreaModeSetting != 8) { EXV_PRINT_TAG(sonyAFPointSelectedSet3)(os, value, metadata); return os; } - if (startsWith(model, "ILCA-") && status && aFAreaModeSetting == 8) { + if (model.starts_with("ILCA-") && status && aFAreaModeSetting == 8) { EXV_PRINT_TAG(sonyAFPointSelectedSet4)(os, value.toUint32(0), metadata); return os; } - if (std::any_of(models4.begin(), models4.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models4.begin(), models4.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyAFPointSelectedSet5)(os, value.toUint32(0), metadata); return os; } @@ -1122,11 +1122,11 @@ std::ostream& SonyMakerNote::printAFPointsUsed(std::ostream& os, const Value& va constexpr std::array models1{"ILCA-", "DSC-"}; constexpr std::array models2{"ILCA-68", "ILCA-77M2"}; - if (std::none_of(models1.begin(), models1.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::none_of(models1.begin(), models1.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG_BITLIST_ALL_LE(sonyAFPointsUsedSet1)(os, value, metadata); return os; } - if (std::any_of(models2.begin(), models2.end(), [&model](auto m) { return startsWith(model, m); })) { + if (std::any_of(models2.begin(), models2.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG_BITLIST_ALL_LE(sonyAFPointsUsedSet2)(os, value, metadata); return os; } @@ -1149,8 +1149,8 @@ std::ostream& SonyMakerNote::printAFTracking(std::ostream& os, const Value& valu } constexpr std::array models{"DSC-RX10M4", "DSC-RX100M6", "DSC-RX100M7", "DSC-RX100M5A", "DSC-HX99", "DSC-RX0M2"}; - if (!startsWith(model, "DSC-") || - std::any_of(models.begin(), models.end(), [&model](auto m) { return startsWith(model, m); })) { + if (!model.starts_with("DSC-") || + std::any_of(models.begin(), models.end(), [&model](auto m) { return model.starts_with(m); })) { EXV_PRINT_TAG(sonyAFTracking)(os, value.toUint32(0), metadata); return os; } @@ -1507,7 +1507,7 @@ std::ostream& SonyMakerNote::printHighISONoiseReduction2(std::ostream& os, const return os; } - if (startsWith(model, "DSC-") || startsWith(model, "Stellar")) { + if (model.starts_with("DSC-") || model.starts_with("Stellar")) { EXV_PRINT_TAG(sonyHighISONoiseReduction2)(os, value.toUint32(0), metadata); return os; } @@ -2020,8 +2020,8 @@ std::ostream& SonyMakerNote::printSony2FpFocusPosition2(std::ostream& os, const } // Ranges of models that do not support this tag - for (auto m : {"DSC-", "Stellar"}) { - if (startsWith(model, m)) { + for (const auto& m : {"DSC-", "Stellar"}) { + if (model.starts_with(m)) { os << N_("n/a"); return os; } diff --git a/src/tiffcomposite_int.cpp b/src/tiffcomposite_int.cpp index cfc5cdf2bf..01c4904d7b 100644 --- a/src/tiffcomposite_int.cpp +++ b/src/tiffcomposite_int.cpp @@ -25,7 +25,7 @@ size_t fillGap(Exiv2::Internal::IoWrapper& ioWrapper, size_t curr, size_t tobe); // class member definitions namespace Exiv2::Internal { bool TiffMappingInfo::operator==(const TiffMappingInfo::Key& key) const { - return (0 == strcmp("*", make_) || startsWith(key.m_, make_)) && + return (0 == strcmp("*", make_) || key.m_.starts_with(make_)) && (Tag::all == extendedTag_ || key.e_ == extendedTag_) && key.g_ == group_; } diff --git a/src/utils.hpp b/src/utils.hpp index 8a9de20747..1284fb4137 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -6,15 +6,6 @@ namespace Exiv2::Internal { -template -constexpr bool startsWith(std::string_view s, T start) { -#ifdef __cpp_lib_starts_ends_with - return s.starts_with(start); -#else - return s.find(start) == 0; -#endif -} - template constexpr bool contains(std::string_view s, T c) { #ifdef __cpp_lib_string_contains diff --git a/src/xmp.cpp b/src/xmp.cpp index 39e7610ef0..a9cfb75b25 100644 --- a/src/xmp.cpp +++ b/src/xmp.cpp @@ -493,7 +493,7 @@ void XmpData::eraseFamily(XmpData::iterator& pos) { std::string key(pos->key()); std::vector keys; while (pos != xmpMetadata_.end()) { - if (!Exiv2::Internal::startsWith(pos->key(), key)) + if (!pos->key().starts_with(key)) break; keys.push_back(pos->key()); pos++; diff --git a/unitTests/test_utils.cpp b/unitTests/test_utils.cpp index f94638e356..b16e99043e 100644 --- a/unitTests/test_utils.cpp +++ b/unitTests/test_utils.cpp @@ -7,11 +7,13 @@ using namespace Exiv2::Internal; TEST(stringUtils, startsWithReturnsTrue) { - ASSERT_TRUE(startsWith("Exiv2 rocks", "Exiv2")); + std::string_view s = "Exiv2 rocks"; + ASSERT_TRUE(s.starts_with("Exiv2")); } TEST(stringUtils, startsWithReturnsFlase) { - ASSERT_FALSE(startsWith("Exiv2 rocks", "exiv2")); + std::string_view s = "Exiv2 rocks"; + ASSERT_FALSE(s.starts_with("exiv2")); } TEST(stringUtils, upperTransformStringToUpperCase) {