Skip to content

Commit

Permalink
switch from custom stringFormat to fmtlib
Browse files Browse the repository at this point in the history
The latter helps to avoid wrong format errors and is simpler to use.
Will be replaced by std::format once C++20 becomes mandatory.

Signed-off-by: Rosen Penev <[email protected]>
  • Loading branch information
neheb committed Oct 20, 2023
1 parent b1225ca commit 1ac41a6
Show file tree
Hide file tree
Showing 22 changed files with 104 additions and 90 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libexpat1-dev zlib1g-dev libbrotli-dev libinih-dev
sudo apt-get install -y libfmt-dev libexpat1-dev zlib1g-dev libbrotli-dev libinih-dev
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/on_PR_mac_matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
run: |
brew install ninja
brew install inih
brew install fmt
brew install googletest
- name: Build
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/on_PR_mac_special_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
run: |
brew install ninja
brew install inih
brew install fmt
brew install googletest
- name: Build
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/on_PR_meson.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@v4
- uses: awalsh128/cache-apt-pkgs-action@v1
with:
packages: g++-${{matrix.cxx}} libcurl4-gnutls-dev libbrotli-dev libinih-dev libgmock-dev libgtest-dev gettext ninja-build
packages: g++-${{matrix.cxx}} libcurl4-gnutls-dev libbrotli-dev libinih-dev libfmt-dev libgmock-dev libgtest-dev gettext ninja-build
version: 1.0
- name: Install meson
run: python3 -m pip install meson==0.54.1
Expand Down Expand Up @@ -119,6 +119,7 @@ jobs:
cc:p
cmake:p
curl:p
fmt:p
gtest:p
libinih:p
meson:p
Expand All @@ -141,7 +142,7 @@ jobs:

- name: Install packages
run: |
brew install curl brotli inih expat googletest
brew install fmt curl brotli inih expat googletest
python3 -m pip install meson==0.54.1 ninja
- name: Compile and Test
Expand All @@ -158,7 +159,7 @@ jobs:
uses: vmactions/freebsd-vm@v0
with:
prepare: |
pkg install -y cmake curl ninja meson gettext pkgconf googletest expat inih brotli
pkg install -y cmake curl ninja meson gettext pkgconf googletest expat inih brotli libfmt
run: |
meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dcpp_std=c++20
meson compile -C "${{github.workspace}}/build" --verbose
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/on_PR_windows_matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ jobs:
libiconv:p
libinih:p
zlib:p
fmt:p
- name: Build
run: |
Expand Down Expand Up @@ -167,6 +168,7 @@ jobs:
libexpat-devel
libiconv-devel
libinih-devel
libfmt-devel
zlib-devel
- name: Build
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/on_push_BasicWinLinMac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ jobs:
run: |
brew install ninja
brew install inih
brew install fmt
brew install googletest
- name: build and compile
Expand Down
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ endif()

include_directories(${CMAKE_BINARY_DIR}) # Make the exv_conf.h file visible for the full project

if(CMAKE_CXX_STANDARD GREATER_EQUAL 20)
include(CheckIncludeFileCXX)
check_include_file_cxx(format HAVE_STD_FORMAT)
else()
set(HAVE_STD_FORMAT FALSE)
endif()

if(NOT HAVE_STD_FORMAT)
find_package(fmt REQUIRED)
endif()

if(EXIV2_ENABLE_XMP)
add_subdirectory(xmpsdk)
endif()
Expand Down
16 changes: 8 additions & 8 deletions ci/install_dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,46 +41,46 @@ distro_id=$(grep '^ID=' /etc/os-release|awk -F = '{print $2}'|sed 's/\"//g')

case "$distro_id" in
'fedora')
dnf -y --refresh install gcc-c++ clang cmake ninja-build expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel gmock-devel glibc-langpack-en inih-devel
dnf -y --refresh install gcc-c++ clang cmake ninja-build expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel gmock-devel glibc-langpack-en inih-devel fmt-devel
;;

'debian')
apt-get update
apt-get install -y cmake ninja-build g++ clang libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgmock-dev libxml2-utils libinih-dev
apt-get install -y cmake ninja-build g++ clang libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgmock-dev libxml2-utils libinih-dev libfmt-dev
# debian_build_gtest
;;

'arch')
pacman --noconfirm -Syu
pacman --noconfirm --needed -S gcc clang cmake ninja expat zlib brotli libssh curl gtest libinih
pacman --noconfirm --needed -S gcc clang cmake ninja expat zlib brotli libssh curl gtest libinih fmt
;;

'ubuntu')
apt-get update
apt-get install -y cmake ninja-build g++ clang libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgmock-dev libxml2-utils libinih-dev
apt-get install -y cmake ninja-build g++ clang libexpat1-dev zlib1g-dev libbrotli-dev libssh-dev libcurl4-openssl-dev libgmock-dev libxml2-utils libinih-dev libfmt-dev
# debian_build_gtest
;;

'alpine')
apk update
apk add gcc g++ clang cmake samurai expat-dev zlib-dev brotli-dev libssh-dev curl-dev gtest gtest-dev gmock libintl gettext-dev libxml2-utils inih-dev inih-inireader-dev
apk add gcc g++ clang cmake samurai expat-dev zlib-dev brotli-dev libssh-dev curl-dev gtest gtest-dev gmock libintl gettext-dev libxml2-utils inih-dev inih-inireader-dev fmt-dev
;;

'rhel')
dnf clean all
dnf -y install gcc-c++ clang cmake ninja-build expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel inih-devel
dnf -y install gcc-c++ clang cmake ninja-build expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel inih-devel fmt-devel
;;

'centos')
dnf clean all
dnf -y install gcc-c++ clang cmake expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel git
dnf -y install gcc-c++ clang cmake expat-devel zlib-devel brotli-devel libssh-devel libcurl-devel git fmt-devel
dnf -y --enablerepo=crb install ninja-build meson
centos_build_inih
;;

'opensuse-tumbleweed')
zypper --non-interactive refresh
zypper --non-interactive install gcc-c++ clang cmake ninja libexpat-devel zlib-devel libbrotli-devel libssh-devel libcurl-devel gmock libxml2-tools libinih-devel
zypper --non-interactive install gcc-c++ clang cmake ninja libexpat-devel zlib-devel libbrotli-devel libssh-devel libcurl-devel gmock libxml2-tools libinih-devel libfmt-devel
;;
*)
echo "Sorry, no predefined dependencies for your distribution $distro_id exist yet"
Expand Down
2 changes: 2 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def requirements(self):

self.requires('inih/55')

self.requires('fmt/10.1.1')

if self.options.webready:
self.requires('libcurl/7.85.0')

Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ deps = []
deps += cpp.find_library('ws2_32', required: host_machine.system() == 'windows')
deps += cpp.find_library('procstat', required: host_machine.system() == 'freebsd')

if not cpp.has_header_symbol('format', '__cpp_lib_format')
deps += dependency('fmt')
endif

if cpp.get_argument_syntax() == 'gcc' and cpp.version().version_compare('<9')
if host_machine.system() == 'linux' and cpp.get_define('_LIBCPP_VERSION', prefix: '#include <new>') == ''
deps += cpp.find_library('stdc++fs')
Expand Down
11 changes: 11 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ else()
target_link_libraries(exiv2lib PRIVATE psapi ws2_32 shell32)
endif()

if(NOT HAVE_STD_FORMAT)
target_link_libraries(exiv2lib PRIVATE fmt::fmt)
target_link_libraries(exiv2lib_int PRIVATE fmt::fmt)
list(APPEND requires_private_list "fmt")
endif()

if(EXIV2_ENABLE_PNG)
target_link_libraries(exiv2lib PRIVATE ZLIB::ZLIB)
list(APPEND requires_private_list "zlib")
Expand Down Expand Up @@ -286,6 +292,11 @@ if(EXIV2_ENABLE_INIH)
list(APPEND requires_private_list "INIReader")
endif()

if(NOT HAVE_STD_FORMAT)
target_link_libraries(exiv2lib_int PRIVATE fmt::fmt)
target_link_libraries(exiv2lib PRIVATE fmt::fmt)
endif()

# Convert private lists to delimited strings
list(SORT libs_private_list)
string(REPLACE ";" " -l" libs_private_string "${libs_private_list}")
Expand Down
14 changes: 7 additions & 7 deletions src/bmffimage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ bool enableBMFF(bool enable) {
}

std::string Iloc::toString() const {
return Internal::stringFormat("ID = %u from,length = %u,%u", ID_, start_, length_);
return stringFormat("ID = {} from,length = {},{}", ID_, start_, length_);
}

BmffImage::BmffImage(BasicIo::UniquePtr io, bool /* create */) :
Expand Down Expand Up @@ -269,7 +269,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
if (bTrace) {
bLF = true;
out << Internal::indent(depth) << "Exiv2::BmffImage::boxHandler: " << toAscii(box_type)
<< Internal::stringFormat(" %8zd->%" PRIu64 " ", address, box_length);
<< stringFormat(" {:8}->{} ", address, box_length);
}

if (box_length == 1) {
Expand Down Expand Up @@ -366,7 +366,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
id = " *** XMP ***";
}
if (bTrace) {
out << Internal::stringFormat("ID = %3d ", ID) << name << " " << id;
out << stringFormat("ID = {:3} {} {}", ID, name, id);
}
} break;

Expand Down Expand Up @@ -444,7 +444,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
uint32_t ldata = data.read_uint32(skip + step - 4, endian_);
if (bTrace) {
out << Internal::indent(depth)
<< Internal::stringFormat("%8zd | %8zd | ID | %4u | %6u,%6u", address + skip, step, ID, offset, ldata)
<< stringFormat("{:8} | {:8} | ID | {:4} | {:6},{:6}", address + skip, step, ID, offset, ldata)
<< std::endl;
}
// save data for post-processing in meta box
Expand All @@ -463,7 +463,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
uint32_t height = data.read_uint32(skip, endian_);
skip += 4;
if (bTrace) {
out << "pixelWidth_, pixelHeight_ = " << Internal::stringFormat("%d, %d", width, height);
out << stringFormat("pixelWidth_, pixelHeight_ = {}, {}", width, height);
}
// HEIC files can have multiple ispe records
// Store largest width/height
Expand Down Expand Up @@ -678,8 +678,8 @@ void BmffImage::parseCr3Preview(const DataBuf& data, std::ostream& out, bool bTr
return "application/octet-stream";
}();
if (bTrace) {
out << Internal::stringFormat("width,height,size = %zu,%zu,%zu", nativePreview.width_, nativePreview.height_,
nativePreview.size_);
out << stringFormat("width,height,size = {},{},{}", nativePreview.width_, nativePreview.height_,
nativePreview.size_);
}
nativePreviews_.push_back(std::move(nativePreview));
}
Expand Down
2 changes: 1 addition & 1 deletion src/futils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ std::string getProcessPath() {
return "unknown"; // pathbuf not big enough
auto path = fs::path(pathbuf);
#elif defined(__sun__)
auto path = fs::read_symlink(Internal::stringFormat("/proc/%d/path/a.out", getpid()));
auto path = fs::read_symlink(stringFormat("/proc/%d/path/a.out", getpid()));
#elif defined(__unix__)
auto path = fs::read_symlink("/proc/self/exe");
#endif
Expand Down
9 changes: 4 additions & 5 deletions src/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,7 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
throw Error(ErrorCode::kerTiffDirectoryTooLarge);

if (bFirst && bPrint) {
out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ", c, c) << io.path()
<< std::endl;
out << Internal::indent(depth) << stringFormat("STRUCTURE OF TIFF FILE ({}{}): {}", c, c, io.path()) << std::endl;
}

// Read the dictionary
Expand Down Expand Up @@ -435,11 +434,11 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct

if (bPrint) {
const size_t address = start + 2 + i * 12;
const std::string offsetString = bOffsetIsPointer ? Internal::stringFormat("%10u", offset) : "";
const std::string offsetString = bOffsetIsPointer ? stringFormat("{:9}", offset) : "";

out << Internal::indent(depth)
<< Internal::stringFormat("%8zu | %#06x %-28s |%10s |%9u |%10s | ", address, tag, tagName(tag).c_str(),
typeName(type), count, offsetString.c_str());
<< stringFormat("{:8} | {:#06x} {:<28} | {:>9} | {:>8} | {:9} | ", address, tag, tagName(tag).c_str(),
typeName(type), count, offsetString);
if (isShortType(type)) {
for (size_t k = 0; k < kount; k++) {
out << sp << byteSwap2(buf, k * size, bSwap);
Expand Down
26 changes: 0 additions & 26 deletions src/image_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,6 @@
#include <vector>

namespace Exiv2::Internal {
std::string stringFormat(const char* format, ...) {
std::string result;
std::vector<char> buffer;
size_t need = std::strlen(format) * 8; // initial guess
int rc = -1;

// vsnprintf writes at most size (2nd parameter) bytes (including \0)
// returns the number of bytes required for the formatted string excluding \0
// the following loop goes through:
// one iteration (if 'need' was large enough for the for formatted string)
// or two iterations (after the first call to vsnprintf we know the required length)
do {
buffer.resize(need + 1);
va_list args; // variable arg list
va_start(args, format); // args start after format
rc = vsnprintf(buffer.data(), buffer.size(), format, args);
va_end(args); // free the args
if (rc > 0)
need = static_cast<size_t>(rc);
} while (buffer.size() <= need);

if (rc > 0)
result = std::string(buffer.data(), need);
return result;
}

[[nodiscard]] std::string indent(size_t i) {
return std::string(2 * i, ' ');
}
Expand Down
17 changes: 7 additions & 10 deletions src/image_int.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
#include <ostream> // for ostream, basic_ostream::put
#include <string>

#if defined(__MINGW32__)
#define ATTRIBUTE_FORMAT_PRINTF __attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
#elif defined(__GNUC__)
#define ATTRIBUTE_FORMAT_PRINTF __attribute__((format(printf, 1, 2)))
#if !__has_include(<format>)
#include <fmt/core.h>
#define stringFormat fmt::format
#else
#define ATTRIBUTE_FORMAT_PRINTF
#include <format>
#ifdef __cpp_lib_format
#define stringFormat std::format
#endif
#endif

// *****************************************************************************
Expand All @@ -26,11 +28,6 @@ namespace Exiv2::Internal {
// *****************************************************************************
// class definitions

/*!
@brief format a string in the pattern of \em sprintf \em .
*/
std::string stringFormat(const char* format, ...) ATTRIBUTE_FORMAT_PRINTF;

/*!
* @brief Helper struct for binary data output via @ref binaryToString.
*
Expand Down
7 changes: 3 additions & 4 deletions src/jp2image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
Internal::enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);

if (bPrint) {
out << Internal::stringFormat("%8zd | %8zd | ", position - boxHSize, static_cast<size_t>(box.length))
<< toAscii(box.type) << " | ";
out << stringFormat("{:8} | {:8} | {} | ", position - boxHSize, box.length, toAscii(box.type));
bLF = true;
if (box.type == kJp2BoxTypeClose)
lf(out, bLF);
Expand Down Expand Up @@ -454,8 +453,8 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
DataBuf data(subBox.length - boxHSize);
io_->read(data.data(), data.size());
if (bPrint) {
out << Internal::stringFormat("%8zu | %8u | sub:", address, subBox.length) << toAscii(subBox.type)
<< " | " << Internal::binaryToString(makeSlice(data, 0, std::min<size_t>(30, data.size())));
out << stringFormat("{:8} | {:8} | sub:{} | ", address, subBox.length, toAscii(subBox.type))
<< Internal::binaryToString(makeSlice(data, 0, std::min<size_t>(30, data.size())));
bLF = true;
}

Expand Down
Loading

0 comments on commit 1ac41a6

Please sign in to comment.