From 6aa5ef9064e4d1bfefb9aa701b5d5a8248e69c25 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Mon, 5 Sep 2022 10:44:10 +0200 Subject: [PATCH] smallut: new pcSubst with callback param --- src/utils/smallut.cpp | 43 ++++++++++++++++++++++++++++++------------- src/utils/smallut.h | 20 +++++++++----------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/utils/smallut.cpp b/src/utils/smallut.cpp index 1c5f2da0..b1038e99 100644 --- a/src/utils/smallut.cpp +++ b/src/utils/smallut.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef _WIN32 #define strncasecmp _strnicmp @@ -52,6 +53,7 @@ #endif using namespace std; +using namespace std::placeholders; namespace MedocUtils { @@ -62,7 +64,7 @@ int stringicmp(const string& s1, const string& s2) void stringtolower(string& io) { - std::transform(io.begin(), io.end(), io.begin(), [](unsigned char c) { return std::tolower(c); }); + std::transform(io.begin(), io.end(), io.begin(), [](unsigned char c) {return std::tolower(c);}); } string stringtolower(const string& i) @@ -624,7 +626,8 @@ bool pcSubst(const string& in, string& out, const map& subs) return true; } -bool pcSubst(const string& in, string& out, const map& subs) +bool pcSubst(const std::string& in, std::string& out, + std::function mapper) { out.erase(); string::size_type i; @@ -647,7 +650,7 @@ bool pcSubst(const string& in, string& out, const map& subs) string::size_type j = in.find_first_of(')', i); if (j == string::npos) { // ??concatenate remaining part and stop - out += std::string("%") + in.substr(i - 2); + out += in.substr(i - 2); break; } key = in.substr(i, j - i); @@ -655,12 +658,7 @@ bool pcSubst(const string& in, string& out, const map& subs) } else { key = in[i]; } - map::const_iterator tr; - if ((tr = subs.find(key)) != subs.end()) { - out += tr->second; - } else { - out += std::string("%") + (key.size()==1? key : string("(") + key + string(")")); - } + out += mapper(key); } else { out += in[i]; } @@ -668,6 +666,26 @@ bool pcSubst(const string& in, string& out, const map& subs) return true; } +class PcSubstMapMapper { +public: + PcSubstMapMapper(const std::map& subs) + : m_subs(subs) {} + std::string domap(const std::string& key) { + auto it = m_subs.find(key); + if (it != m_subs.end()) + return it->second; + return std::string("%") + (key.size() == 1 ? key : string("(") + key + string(")")); + } + const std::map& m_subs; +}; + +bool pcSubst(const std::string& in, std::string& out, + const std::map& subs) +{ + PcSubstMapMapper mapper(subs); + return pcSubst(in, out, std::bind(&PcSubstMapMapper::domap, &mapper, _1)); +} + void ulltodecstr(uint64_t val, string& buf) { buf.clear(); @@ -1208,8 +1226,7 @@ std::string SimpleRegexp::simpleSub( if (!ok()) { return std::string(); } - return regex_replace( - in, m->expr, repl, std::regex_constants::format_first_only); + return regex_replace(in, m->expr, repl, std::regex_constants::format_first_only); } string SimpleRegexp::getMatch(const string&, int i) const @@ -1224,9 +1241,9 @@ public: Internal(const string& exp, int flags, int nm) : nmatch(nm) { ok = regcomp(&expr, exp.c_str(), REG_EXTENDED | - ((flags & SRE_ICASE) ? REG_ICASE : 0) | + ((flags & SRE_ICASE) ? REG_ICASE : 0) | - ((flags & SRE_NOSUB) ? REG_NOSUB : 0)) == 0; + ((flags & SRE_NOSUB) ? REG_NOSUB : 0)) == 0; matches.resize(nmatch+1); } ~Internal() { diff --git a/src/utils/smallut.h b/src/utils/smallut.h index 50c8b003..cd5c9ee0 100644 --- a/src/utils/smallut.h +++ b/src/utils/smallut.h @@ -23,6 +23,7 @@ #include #include #include +#include struct tm; @@ -137,8 +138,7 @@ template std::string stringsToString(const T& tokens); * " inside tokens is escaped as "" ([word "quote"] =>["word ""quote"""] * See instantiation note above. */ -template void stringsToCSV(const T& tokens, std::string& s, - char sep = ','); +template void stringsToCSV(const T& tokens, std::string& s, char sep = ','); /** Find longest common prefix for bunch of strings */ template std::string commonprefix(const T& values); @@ -183,8 +183,7 @@ extern std::string escapeShell(const std::string& in); /** Truncate a string to a given maxlength, avoiding cutting off midword * if reasonably possible. */ -extern std::string truncate_to_word(const std::string& input, - std::string::size_type maxlen); +extern std::string truncate_to_word(const std::string& input, std::string::size_type maxlen); void ulltodecstr(uint64_t val, std::string& buf); void lltodecstr(int64_t val, std::string& buf); @@ -195,15 +194,16 @@ std::string ulltodecstr(uint64_t val); std::string displayableBytes(int64_t size); /** Break big string into lines */ -std::string breakIntoLines(const std::string& in, unsigned int ll = 100, - unsigned int maxlines = 50); +std::string breakIntoLines(const std::string& in, unsigned int ll = 100, unsigned int maxlines = 50); /** Small utility to substitute printf-like percents cmds in a string */ -bool pcSubst(const std::string& in, std::string& out, - const std::map& subs); +bool pcSubst(const std::string& in, std::string& out, const std::map& subs); /** Substitute printf-like percents and also %(key) */ bool pcSubst(const std::string& in, std::string& out, const std::map& subs); +/** Substitute printf-like percents and %(nm), using result of function call */ +bool pcSubst(const std::string& i, std::string& o, std::function); + /** Append system error message */ void catstrerror(std::string *reason, const char *what, int _errno); @@ -249,7 +249,6 @@ public: /// Check after construction bool ok() const; - class Internal; private: Internal *m; @@ -272,8 +271,7 @@ struct CharFlags { #define CHARFLAGENTRY(NM) {NM, #NM} /// Translate a bitfield into string description -extern std::string flagsToString(const std::vector&, - unsigned int val); +extern std::string flagsToString(const std::vector&, unsigned int val); /// Translate a value into a name extern std::string valToString(const std::vector&, unsigned int val);