Skip to content

Commit 193ecdf

Browse files
committed
remove some stringstreams
Looks like they're slow under Cygwin. Signed-off-by: Rosen Penev <rosenp@gmail.com>
1 parent f2c665e commit 193ecdf

File tree

10 files changed

+94
-110
lines changed

10 files changed

+94
-110
lines changed

samples/iptctest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void processAdd(const std::string& line, int num, IptcData& iptcData) {
8686

8787
std::string data(line.substr(dataStart));
8888
// if data starts and ends with quotes, remove them
89-
if (data.front() == '\"' && data.back() == '\"') {
89+
if (data.front() == '"' && data.back() == '"') {
9090
data = data.substr(1, data.size() - 2);
9191
}
9292
TypeId type = IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
@@ -133,7 +133,7 @@ void processModify(const std::string& line, int num, IptcData& iptcData) {
133133

134134
std::string data(line.substr(dataStart));
135135
// if data starts and ends with quotes, remove them
136-
if (data.front() == '\"' && data.back() == '\"') {
136+
if (data.front() == '"' && data.back() == '"') {
137137
data = data.substr(1, data.size() - 2);
138138
}
139139
TypeId type = IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());

src/canonmn_int.cpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "error.hpp"
1212
#include "exif.hpp"
1313
#include "i18n.h" // NLS support.
14+
#include "image_int.hpp"
1415
#include "makernote_int.hpp"
1516
#include "tags_int.hpp"
1617
#include "types.hpp"
@@ -2776,9 +2777,7 @@ std::ostream& CanonMakerNote::printFiFileNumber(std::ostream& os, const Value& v
27762777
if (Internal::contains(model, "20D") || Internal::contains(model, "350D") ||
27772778
model.substr(model.size() - 8, 8) == "REBEL XT" || Internal::contains(model, "Kiss Digital N")) {
27782779
uint32_t val = value.toUint32();
2779-
uint32_t dn = (val & 0xffc0) >> 6;
2780-
uint32_t fn = ((val >> 16) & 0xff) + ((val & 0x3f) << 8);
2781-
os << std::dec << dn << "-" << std::setw(4) << std::setfill('0') << fn;
2780+
os << stringFormat("{}-{:04}", (val & 0xffc0) >> 6, ((val >> 16) & 0xff) + ((val & 0x3f) << 8));
27822781
os.flags(f);
27832782
return os;
27842783
}
@@ -2788,8 +2787,7 @@ std::ostream& CanonMakerNote::printFiFileNumber(std::ostream& os, const Value& v
27882787
uint32_t dn = (val & 0xffc00) >> 10;
27892788
while (dn < 100)
27902789
dn += 0x40;
2791-
uint32_t fn = ((val & 0x3ff) << 4) + ((val >> 20) & 0x0f);
2792-
os << std::dec << dn << "-" << std::setw(4) << std::setfill('0') << fn;
2790+
os << stringFormat("{}-{:04}", dn, ((val & 0x3ff) << 4) + ((val >> 20) & 0x0f));
27932791
os.flags(f);
27942792
return os;
27952793
}
@@ -2833,16 +2831,11 @@ std::ostream& CanonMakerNote::print0x0008(std::ostream& os, const Value& value,
28332831
}
28342832

28352833
std::ostream& CanonMakerNote::print0x000a(std::ostream& os, const Value& value, const ExifData*) {
2836-
std::istringstream is(value.toString());
2837-
uint32_t l = 0;
2838-
is >> l;
2839-
return os << std::setw(4) << std::setfill('0') << std::hex << ((l & 0xffff0000) >> 16) << std::setw(5)
2840-
<< std::setfill('0') << std::dec << (l & 0x0000ffff);
2834+
uint32_t l = std::stoul(value.toString());
2835+
return os << stringFormat("{:04x}{:05}", (l >> 16) & 0xFFFF, l & 0xFFFF);
28412836
}
28422837

28432838
std::ostream& CanonMakerNote::print0x000c(std::ostream& os, const Value& value, const ExifData* exifData) {
2844-
std::istringstream is(value.toString());
2845-
28462839
if (!exifData) {
28472840
return os << value;
28482841
}
@@ -2851,10 +2844,8 @@ std::ostream& CanonMakerNote::print0x000c(std::ostream& os, const Value& value,
28512844
auto pos = exifData->findKey(key);
28522845
// if model is EOS D30
28532846
if (pos != exifData->end() && pos->value().count() == 1 && pos->value().toInt64() == 0x01140000) {
2854-
uint32_t l = 0;
2855-
is >> l;
2856-
return os << std::setw(4) << std::setfill('0') << std::hex << ((l & 0xffff0000) >> 16) << std::setw(5)
2857-
<< std::setfill('0') << std::dec << (l & 0x0000ffff);
2847+
uint32_t l = std::stoul(value.toString());
2848+
return os << stringFormat("{:04x}{:05}", (l >> 16) & 0xFFFF, l & 0xFFFF);
28582849
}
28592850
return os << value;
28602851
}
@@ -3061,7 +3052,7 @@ std::ostream& CanonMakerNote::printLe0x0000(std::ostream& os, const Value& value
30613052
std::ostringstream oss;
30623053
oss.copyfmt(os);
30633054
for (size_t i = 0; i < value.size(); ++i) {
3064-
os << std::setw(2) << std::setfill('0') << std::hex << value.toInt64(i);
3055+
os << stringFormat("{:02x}", value.toInt64(i));
30653056
}
30663057
os.copyfmt(oss);
30673058
os.flags(f);

src/convert.cpp

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -742,11 +742,13 @@ void Converter::cnvExifVersion(const char* from, const char* to) {
742742
return;
743743
if (!prepareXmpTarget(to))
744744
return;
745-
std::ostringstream value;
746-
for (size_t i = 0; i < pos->count(); ++i) {
747-
value << static_cast<char>(pos->toInt64(i));
745+
auto count = pos->count();
746+
std::string value;
747+
value.reserve(count);
748+
for (size_t i = 0; i < count; ++i) {
749+
value += static_cast<char>(pos->toInt64(i));
748750
}
749-
(*xmpData_)[to] = value.str();
751+
(*xmpData_)[to] = value;
750752
if (erase_)
751753
exifData_->erase(pos);
752754
}
@@ -757,13 +759,13 @@ void Converter::cnvExifGPSVersion(const char* from, const char* to) {
757759
return;
758760
if (!prepareXmpTarget(to))
759761
return;
760-
std::ostringstream value;
762+
std::string value;
761763
for (size_t i = 0; i < pos->count(); ++i) {
762764
if (i > 0)
763-
value << '.';
764-
value << pos->toInt64(i);
765+
value += '.';
766+
value += std::to_string(pos->toInt64(i));
765767
}
766-
(*xmpData_)[to] = value.str();
768+
(*xmpData_)[to] = value;
767769
if (erase_)
768770
exifData_->erase(pos);
769771
}
@@ -826,9 +828,7 @@ void Converter::cnvExifGPSCoord(const char* from, const char* to) {
826828
double min = (deg[0] * 60.0) + deg[1] + (deg[2] / 60.0);
827829
auto ideg = static_cast<int>(min / 60.0);
828830
min -= ideg * 60;
829-
std::ostringstream oss;
830-
oss << ideg << "," << std::fixed << std::setprecision(7) << min << refPos->toString().c_str()[0];
831-
(*xmpData_)[to] = oss.str();
831+
(*xmpData_)[to] = stringFormat("{},{:.7f}{}", ideg, min, refPos->toString().front());
832832

833833
if (erase_)
834834
exifData_->erase(pos);
@@ -883,7 +883,7 @@ void Converter::cnvXmpArray(const char* from, const char* to) {
883883
auto pos = xmpData_->findKey(XmpKey(from));
884884
if (pos == xmpData_->end())
885885
return;
886-
std::ostringstream array;
886+
std::string array;
887887
for (size_t i = 0; i < pos->count(); ++i) {
888888
std::string value = pos->toString(i);
889889
if (!pos->value().ok()) {
@@ -892,11 +892,11 @@ void Converter::cnvXmpArray(const char* from, const char* to) {
892892
#endif
893893
return;
894894
}
895-
array << value;
895+
array += value;
896896
if (i != pos->count() - 1)
897-
array << " ";
897+
array += " ";
898898
}
899-
(*exifData_)[to] = array.str();
899+
(*exifData_)[to] = array;
900900
if (erase_)
901901
xmpData_->erase(pos);
902902
}
@@ -997,12 +997,9 @@ void Converter::cnvXmpVersion(const char* from, const char* to) {
997997
#endif
998998
return;
999999
}
1000-
std::ostringstream array;
10011000

1002-
array << static_cast<int>(value[0]) << " " << static_cast<int>(value[1]) << " " << static_cast<int>(value[2]) << " "
1003-
<< static_cast<int>(value[3]);
1004-
1005-
(*exifData_)[to] = array.str();
1001+
(*exifData_)[to] = stringFormat("{} {} {} {}", static_cast<int>(value[0]), static_cast<int>(value[1]),
1002+
static_cast<int>(value[2]), static_cast<int>(value[3]));
10061003
if (erase_)
10071004
xmpData_->erase(pos);
10081005
}
@@ -1234,7 +1231,7 @@ void Converter::cnvXmpValueToIptc(const char* from, const char* to) {
12341231

12351232
#ifdef EXV_HAVE_XMP_TOOLKIT
12361233
std::string Converter::computeExifDigest(bool tiff) {
1237-
std::ostringstream res;
1234+
std::string res;
12381235
MD5_CTX context;
12391236
unsigned char digest[16];
12401237

@@ -1247,9 +1244,9 @@ std::string Converter::computeExifDigest(bool tiff) {
12471244
if (!tiff && key.groupName() == "Image")
12481245
continue;
12491246

1250-
if (!res.str().empty())
1251-
res << ',';
1252-
res << key.tag();
1247+
if (!res.empty())
1248+
res += ',';
1249+
res += key.tag();
12531250
auto pos = exifData_->findKey(key);
12541251
if (pos == exifData_->end())
12551252
continue;
@@ -1259,12 +1256,11 @@ std::string Converter::computeExifDigest(bool tiff) {
12591256
}
12601257
}
12611258
MD5Final(digest, &context);
1262-
res << ';';
1263-
res << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
1259+
res += ';';
12641260
for (const auto& i : digest) {
1265-
res << static_cast<int>(i);
1261+
res += stringFormat("{:02X}", i);
12661262
}
1267-
return res.str();
1263+
return res;
12681264
}
12691265
#else
12701266
std::string Converter::computeExifDigest(bool) {

src/crwimage_int.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "enforce.hpp"
66
#include "error.hpp"
77
#include "i18n.h" // NLS support.
8+
#include "image_int.hpp"
89

910
#include <algorithm>
1011
#include <ctime>
@@ -420,10 +421,8 @@ void CiffComponent::print(std::ostream& os, ByteOrder byteOrder, const std::stri
420421
}
421422

422423
void CiffComponent::doPrint(std::ostream& os, ByteOrder byteOrder, const std::string& prefix) const {
423-
os << prefix << _("tag") << " = 0x" << std::setw(4) << std::setfill('0') << std::hex << std::right << tagId() << ", "
424-
<< _("dir") << " = 0x" << std::setw(4) << std::setfill('0') << std::hex << std::right << dir() << ", " << _("type")
425-
<< " = " << TypeInfo::typeName(typeId()) << ", " << _("size") << " = " << std::dec << size_ << ", " << _("offset")
426-
<< " = " << offset_ << "\n";
424+
os << stringFormat("{}{} = 0x{:04x}, {} = 0x{:04x}, {} = {}, {} = {}, {} = {}\n", prefix, _("tag"), tagId(), _("dir"),
425+
dir(), _("type"), TypeInfo::typeName(typeId()), _("size"), size_, _("offset"), offset_);
427426

428427
if (typeId() != directory) {
429428
auto value = Value::create(typeId());

src/datasets.cpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -443,17 +443,13 @@ bool IptcDataSets::dataSetRepeatable(uint16_t number, uint16_t recordId) {
443443
}
444444

445445
uint16_t IptcDataSets::dataSet(const std::string& dataSetName, uint16_t recordId) {
446-
uint16_t dataSet = 0;
447446
if (int idx = dataSetIdx(dataSetName, recordId); idx != -1) {
448447
// dataSetIdx checks the range of recordId
449-
dataSet = records_[recordId][idx].number_;
450-
} else {
451-
if (!isHex(dataSetName, 4, "0x"))
452-
throw Error(ErrorCode::kerInvalidDataset, dataSetName);
453-
std::istringstream is(dataSetName);
454-
is >> std::hex >> dataSet;
448+
return records_[recordId][idx].number_;
455449
}
456-
return dataSet;
450+
if (!isHex(dataSetName, 4, "0x"))
451+
throw Error(ErrorCode::kerInvalidDataset, dataSetName);
452+
return std::stoi(dataSetName, nullptr, 16);
457453
}
458454

459455
std::string IptcDataSets::recordName(uint16_t recordId) {
@@ -480,8 +476,7 @@ uint16_t IptcDataSets::recordId(const std::string& recordName) {
480476
if (i == 0) {
481477
if (!isHex(recordName, 4, "0x"))
482478
throw Error(ErrorCode::kerInvalidRecord, recordName);
483-
std::istringstream is(recordName);
484-
is >> std::hex >> i;
479+
i = std::stoi(recordName, nullptr, 16);
485480
}
486481
return i;
487482
}
@@ -594,15 +589,16 @@ std::ostream& operator<<(std::ostream& os, const DataSet& dataSet) {
594589
<< iptcKey.key() << ", " << TypeInfo::typeName(IptcDataSets::dataSetType(dataSet.number_, dataSet.recordId_))
595590
<< ", ";
596591
// CSV encoded I am \"dead\" beat" => "I am ""dead"" beat"
597-
char Q = '"';
598-
os << Q;
599-
for (size_t i = 0; i < ::strlen(dataSet.desc_); i++) {
600-
char c = dataSet.desc_[i];
601-
if (c == Q)
602-
os << Q;
603-
os << c;
592+
std::string escapedDesc;
593+
escapedDesc.push_back('"');
594+
for (char c : std::string_view(dataSet.desc_)) {
595+
if (c == '"')
596+
escapedDesc += "\"\"";
597+
else
598+
escapedDesc.push_back(c);
604599
}
605-
os << Q;
600+
escapedDesc.push_back('"');
601+
os << escapedDesc;
606602
os.flags(f);
607603
return os;
608604
}

src/futils.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "config.h"
77
#include "enforce.hpp"
8+
#include "image_int.hpp"
89
#include "utils.hpp"
910

1011
// + standard includes
@@ -240,7 +241,7 @@ bool fileExists(const std::string& path) {
240241

241242
std::string strError() {
242243
int error = errno;
243-
std::ostringstream os;
244+
std::string os;
244245
#ifdef EXV_HAVE_STRERROR_R
245246
const size_t n = 1024;
246247
#ifdef EXV_STRERROR_R_CHAR_P
@@ -251,17 +252,16 @@ std::string strError() {
251252
const int ret = strerror_r(error, buf, n);
252253
Internal::enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed);
253254
#endif
254-
os << buf;
255+
os = buf;
255256
// Issue# 908.
256257
// report strerror() if strerror_r() returns empty
257-
if (!buf[0]) {
258-
os << strerror(error);
258+
if (os.empty()) {
259+
os = std::strerror(error);
259260
}
260261
#else
261-
os << std::strerror(error);
262+
os = std::strerror(error);
262263
#endif
263-
os << " (errno = " << error << ")";
264-
return os.str();
264+
return stringFormat("{} (errno = {})", os, error);
265265
} // strError
266266

267267
void Uri::Decode(Uri& uri) {

src/pngchunk_int.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "exif.hpp"
1212
#include "helper_functions.hpp"
1313
#include "image.hpp"
14+
#include "image_int.hpp"
1415
#include "iptc.hpp"
1516
#include "photoshop.hpp"
1617
#include "pngchunk_int.hpp"
@@ -576,17 +577,16 @@ DataBuf PngChunk::readRawProfile(const DataBuf& text, bool iTXt) {
576577
std::string PngChunk::writeRawProfile(const std::string& profileData, const char* profileType) {
577578
static const byte hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
578579

579-
std::ostringstream oss;
580-
oss << '\n' << profileType << '\n' << std::setw(8) << profileData.size();
580+
auto ss = stringFormat("\n{}\n{:08}", profileType, profileData.size());
581581
auto sp = reinterpret_cast<const byte*>(profileData.data());
582582
for (std::string::size_type i = 0; i < profileData.size(); ++i) {
583583
if (i % 36 == 0)
584-
oss << '\n';
585-
oss << hex[*sp >> 4 & 0x0fU];
586-
oss << hex[*sp++ & 0x0fU];
584+
ss += '\n';
585+
ss += hex[*sp >> 4 & 0x0fU];
586+
ss += hex[*sp++ & 0x0fU];
587587
}
588-
oss << '\n';
589-
return oss.str();
588+
ss += '\n';
589+
return ss;
590590

591591
} // PngChunk::writeRawProfile
592592

0 commit comments

Comments
 (0)