diff --git a/src/convert.cpp b/src/convert.cpp index 0105f13919..9329a11df9 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -13,6 +13,7 @@ #include "error.hpp" #include "exif.hpp" #include "futils.hpp" +#include "image_int.hpp" #include "iptc.hpp" #include "types.hpp" #include "xmp_exiv2.hpp" @@ -621,7 +622,6 @@ void Converter::cnvExifDate(const char* from, const char* to) { int min = 0; int sec = 0; std::string subsec; - char buf[30]; if (std::string(from) != "Exif.GPSInfo.GPSTimeStamp") { std::string value = pos->toString(); @@ -678,10 +678,7 @@ void Converter::cnvExifDate(const char* from, const char* to) { sec = static_cast(dsec); dsec -= sec; - snprintf(buf, sizeof(buf), "%.9f", dsec); - buf[sizeof(buf) - 1] = 0; - buf[1] = '.'; // some locales use ',' - subsec = buf + 1; + subsec = std::format(".{:09.0f}", dsec * 1'000'000'000); auto datePos = exifData_->findKey(ExifKey("Exif.GPSInfo.GPSDateStamp")); if (datePos == exifData_->end()) { @@ -733,10 +730,8 @@ void Converter::cnvExifDate(const char* from, const char* to) { if (subsec.size() > 10) subsec.resize(10); - snprintf(buf, sizeof(buf), "%4d-%02d-%02dT%02d:%02d:%02d%s", year, month, day, hour, min, sec, subsec.c_str()); - buf[sizeof(buf) - 1] = 0; - (*xmpData_)[to] = buf; + (*xmpData_)[to] = stringFormat("{:4}-{:02}-{:02}T{:02}:{:02}:{:02}{}", year, month, day, hour, min, sec, subsec); if (erase_) exifData_->erase(pos); } @@ -923,14 +918,11 @@ void Converter::cnvXmpDate(const char* from, const char* to) { XMP_DateTime datetime; try { SXMPUtils::ConvertToDate(value, &datetime); - char buf[30]; if (std::string(to) != "Exif.GPSInfo.GPSTimeStamp") { SXMPUtils::ConvertToLocalTime(&datetime); - snprintf(buf, sizeof(buf), "%4d:%02d:%02d %02d:%02d:%02d", datetime.year, datetime.month, datetime.day, - datetime.hour, datetime.minute, datetime.second); - buf[sizeof(buf) - 1] = 0; - (*exifData_)[to] = buf; + (*exifData_)[to] = stringFormat("{:4}:{:02}:{:02} {:02}:{:02}:{:02}", datetime.year, datetime.month, datetime.day, + datetime.hour, datetime.minute, datetime.second); if (datetime.nanoSecond) { const char* subsecTag = nullptr; @@ -968,9 +960,8 @@ void Converter::cnvXmpDate(const char* from, const char* to) { (*exifData_)[to] = array.str(); prepareExifTarget("Exif.GPSInfo.GPSDateStamp", true); - snprintf(buf, sizeof(buf), "%4d:%02d:%02d", datetime.year, datetime.month, datetime.day); - buf[sizeof(buf) - 1] = 0; - (*exifData_)["Exif.GPSInfo.GPSDateStamp"] = buf; + (*exifData_)["Exif.GPSInfo.GPSDateStamp"] = + stringFormat("{:4}:{:02}:{:02}", datetime.year, datetime.month, datetime.day); } } #ifndef SUPPRESS_WARNINGS diff --git a/src/image_int.hpp b/src/image_int.hpp index 14c8181b10..b195ebd053 100644 --- a/src/image_int.hpp +++ b/src/image_int.hpp @@ -16,10 +16,12 @@ #include #endif #ifndef EXV_HAVE_STD_FORMAT -#include +#include #define stringFormat fmt::format +#define stringFormatTo fmt::format_to #else #define stringFormat std::format +#define stringFormatTo std::format_to #endif // ***************************************************************************** diff --git a/src/iptc.cpp b/src/iptc.cpp index 4a56811577..5641ace2ff 100644 --- a/src/iptc.cpp +++ b/src/iptc.cpp @@ -291,10 +291,10 @@ void IptcData::printStructure(std::ostream& out, const Slice& bytes, size uint16_t dataset = bytes.at(i + 2); Internal::enforce(bytes.size() - i >= 5, ErrorCode::kerCorruptedMetadata); uint16_t len = getUShort(bytes.subSlice(i + 3, bytes.size()), bigEndian); - snprintf(buff, sizeof(buff), " %6hu | %7hu | %-24s | %6hu | ", record, dataset, - Exiv2::IptcDataSets::dataSetName(dataset, record).c_str(), len); Internal::enforce(bytes.size() - i >= 5 + static_cast(len), ErrorCode::kerCorruptedMetadata); + out << std::format(" {:6} | {:7} | {:<24} | {:6} | ", record, dataset, + Exiv2::IptcDataSets::dataSetName(dataset, record), len); out << buff << Internal::binaryToString(makeSlice(bytes, i + 5, i + 5 + (len > 40 ? 40 : len))) << (len > 40 ? "..." : "") << '\n'; i += 5 + len; diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp index 9613fbc062..104b205f2f 100644 --- a/src/jpgimage.cpp +++ b/src/jpgimage.cpp @@ -357,12 +357,9 @@ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, si // 0xc0 .. 0xcf are SOFn (except 4) nm[0xc4] = "DHT"; for (int i = 0; i <= 15; i++) { - char MN[16]; - snprintf(MN, sizeof(MN), "APP%d", i); - nm[0xe0 + i] = MN; + nm[0xe0 + i] = stringFormat("APP{}", i); if (i != 4) { - snprintf(MN, sizeof(MN), "SOF%d", i); - nm[0xc0 + i] = MN; + nm[0xc0 + i] = stringFormat("SOF{}", i); } } diff --git a/src/value.cpp b/src/value.cpp index a1aaa903a4..b882c31783 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -817,11 +817,10 @@ size_t DateValue::copy(byte* buf, ByteOrder /*byteOrder*/) const { // \note Here the date is copied in the Basic format YYYYMMDD, as the IPTC key Iptc.Application2.DateCreated // wants it. Check https://exiv2.org/iptc.html - // sprintf wants to add the null terminator, so use oversized buffer - char temp[9]; - auto wrote = static_cast(snprintf(temp, sizeof(temp), "%04d%02d%02d", date_.year, date_.month, date_.day)); - std::copy_n(temp, wrote, buf); - return wrote; + auto out = reinterpret_cast(buf); + auto it = std::format_to(out, "{:04}{:02}{:02}", date_.year, date_.month, date_.day); + + return it - out; } const DateValue::Date& DateValue::getDate() const { @@ -987,17 +986,17 @@ void TimeValue::setTime(const Time& src) { size_t TimeValue::copy(byte* buf, ByteOrder /*byteOrder*/) const { // NOTE: Here the time is copied in the Basic format HHMMSS:HHMM, as the IPTC key // Iptc.Application2.TimeCreated wants it. Check https://exiv2.org/iptc.html - char temp[12]; char plusMinus = '+'; if (time_.tzHour < 0 || time_.tzMinute < 0) plusMinus = '-'; - const auto wrote = static_cast(snprintf(temp, sizeof(temp), // 11 bytes are written + \0 - "%02d%02d%02d%1c%02d%02d", time_.hour, time_.minute, time_.second, - plusMinus, abs(time_.tzHour), abs(time_.tzMinute))); + auto out = reinterpret_cast(buf); + auto it = std::format_to(out, "{:02}{:02}{:02}{}{:02}{:02}", + time_.hour, time_.minute, time_.second, + plusMinus, std::abs(time_.tzHour), std::abs(time_.tzMinute)); + auto wrote = static_cast(it - out); Internal::enforce(wrote == 11, Exiv2::ErrorCode::kerUnsupportedTimeFormat); - std::copy_n(temp, wrote, buf); return wrote; }