This commit is contained in:
Jean-Francois Dockes 2020-07-15 10:48:08 +02:00
parent 96ba5acd32
commit b8be14bd7b
4 changed files with 124 additions and 149 deletions

View File

@ -27,27 +27,27 @@
#include <cstring> #include <cstring>
#define PUT_BIT_LE(i, cp, value) do { \ #define PUT_BIT_LE(i, cp, value) do { \
(cp)[i] = (uint8_t)(((value) >> 8 * i) & 0xFF); \ (cp)[i] = (uint8_t)(((value) >> 8 * i) & 0xFF); \
} while (0) } while (0)
#define PUT_64BIT_LE(cp, value) do { \ #define PUT_64BIT_LE(cp, value) do { \
PUT_BIT_LE(7, cp, value); \ PUT_BIT_LE(7, cp, value); \
PUT_BIT_LE(6, cp, value); \ PUT_BIT_LE(6, cp, value); \
PUT_BIT_LE(5, cp, value); \ PUT_BIT_LE(5, cp, value); \
PUT_BIT_LE(4, cp, value); \ PUT_BIT_LE(4, cp, value); \
PUT_BIT_LE(3, cp, value); \ PUT_BIT_LE(3, cp, value); \
PUT_BIT_LE(2, cp, value); \ PUT_BIT_LE(2, cp, value); \
PUT_BIT_LE(1, cp, value); \ PUT_BIT_LE(1, cp, value); \
PUT_BIT_LE(0, cp, value); \ PUT_BIT_LE(0, cp, value); \
} while (0) } while (0)
#define PUT_32BIT_LE(cp, value) do { \ #define PUT_32BIT_LE(cp, value) do { \
PUT_BIT_LE(3, cp, value); \ PUT_BIT_LE(3, cp, value); \
PUT_BIT_LE(2, cp, value); \ PUT_BIT_LE(2, cp, value); \
PUT_BIT_LE(1, cp, value); \ PUT_BIT_LE(1, cp, value); \
PUT_BIT_LE(0, cp, value); \ PUT_BIT_LE(0, cp, value); \
} while (0) } while (0)
static uint8_t PADDING[MD5_BLOCK_LENGTH] = { static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -145,7 +145,7 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
#define F4(x, y, z) (y ^ (x | ~z)) #define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */ /* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \ #define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/* /*
@ -256,14 +256,14 @@ void MD5Final(string &digest, MD5_CTX *context)
{ {
unsigned char d[16]; unsigned char d[16];
MD5Final (d, context); MD5Final (d, context);
digest.assign((const char *)d, 16); digest.assign(reinterpret_cast<const char*>(d), 16);
} }
string& MD5String(const string& data, string& digest) string& MD5String(const string& data, string& digest)
{ {
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5Init(&ctx);
MD5Update(&ctx, (const unsigned char*)data.c_str(), data.length()); MD5Update(&ctx, reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
MD5Final(digest, &ctx); MD5Final(digest, &ctx);
return digest; return digest;
} }
@ -273,10 +273,10 @@ string& MD5HexPrint(const string& digest, string &out)
out.erase(); out.erase();
out.reserve(33); out.reserve(33);
static const char hex[]="0123456789abcdef"; static const char hex[]="0123456789abcdef";
auto hash = (const unsigned char *)digest.c_str(); auto hash = reinterpret_cast<const unsigned char*>(digest.c_str());
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
out.append(1, hex[hash[i] >> 4]); out.append(1, hex[hash[i] >> 4]);
out.append(1, hex[hash[i] & 0x0f]); out.append(1, hex[hash[i] & 0x0f]);
} }
return out; return out;
} }
@ -285,15 +285,15 @@ string& MD5HexScan(const string& xdigest, string& digest)
{ {
digest.erase(); digest.erase();
if (xdigest.length() != 32) { if (xdigest.length() != 32) {
return digest;
}
for (unsigned int i = 0; i < 16; i++) {
unsigned int val;
if (sscanf(xdigest.c_str() + 2*i, "%2x", &val) != 1) {
digest.erase();
return digest; return digest;
} }
digest.append(1, (unsigned char)val); for (unsigned int i = 0; i < 16; i++) {
unsigned int val;
if (sscanf(xdigest.c_str() + 2*i, "%2x", &val) != 1) {
digest.erase();
return digest;
}
digest.append(1, static_cast<unsigned char>(val));
} }
return digest; return digest;
} }

View File

@ -36,7 +36,7 @@ void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH]);
#include <string> #include <string>
extern void MD5Final(std::string& digest, MD5_CTX *); extern void MD5Final(std::string& digest, MD5_CTX *);
extern std::string& MD5String(const std::string& data, std::string& digest); extern std::string& MD5String(const std::string& data, std::string& digest);
extern std::string& MD5HexPrint(const std::string& digest, std::string& xdigest); extern std::string& MD5HexPrint(const std::string& digest, std::string& out);
extern std::string& MD5HexScan(const std::string& xdigest, std::string& digest); extern std::string& MD5HexScan(const std::string& xdigest, std::string& digest);
#endif /* _MD5_H_ */ #endif /* _MD5_H_ */

View File

@ -15,9 +15,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA * 02110-1301 USA
*/ */
#include <stdio.h> #include <algorithm>
#include <stdlib.h> #include <cstdio>
#include <inttypes.h> #include <cstdlib>
#include <cinttypes>
#ifdef _WIN32 #ifdef _WIN32
// needed for localtime_r under mingw? // needed for localtime_r under mingw?
@ -27,11 +28,11 @@
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#endif /* _WIN32 */ #endif /* _WIN32 */
#include <time.h> #include <ctime>
#include <ctype.h> #include <cctype>
#include <errno.h> #include <cerrno>
#include <string.h> #include <cstring>
#include <math.h> #include <cmath>
// Older compilers don't support stdc++ regex, but Windows does not // Older compilers don't support stdc++ regex, but Windows does not
// have the Linux one. Have a simple class to solve the simple cases. // have the Linux one. Have a simple class to solve the simple cases.
@ -46,6 +47,7 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <numeric>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
@ -71,18 +73,18 @@ int stringicmp(const string& s1, const string& s2)
++it2; ++it2;
} }
return size1 == size2 ? 0 : -1; return size1 == size2 ? 0 : -1;
} else {
while (it2 != s2.end()) {
c1 = ::toupper(*it1);
c2 = ::toupper(*it2);
if (c1 != c2) {
return c1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
while (it2 != s2.end()) {
c1 = ::toupper(*it1);
c2 = ::toupper(*it2);
if (c1 != c2) {
return c1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
void stringtolower(string& io) void stringtolower(string& io)
{ {
@ -150,17 +152,17 @@ int stringlowercmp(const string& s1, const string& s2)
++it2; ++it2;
} }
return size1 == size2 ? 0 : -1; return size1 == size2 ? 0 : -1;
} else {
while (it2 != s2.end()) {
c2 = ::tolower(*it2);
if (*it1 != c2) {
return *it1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
while (it2 != s2.end()) {
c2 = ::tolower(*it2);
if (*it1 != c2) {
return *it1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
// s1 is already uppercase // s1 is already uppercase
@ -181,42 +183,29 @@ int stringuppercmp(const string& s1, const string& s2)
++it2; ++it2;
} }
return size1 == size2 ? 0 : -1; return size1 == size2 ? 0 : -1;
} else {
while (it2 != s2.end()) {
c2 = ::toupper(*it2);
if (*it1 != c2) {
return *it1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
while (it2 != s2.end()) {
c2 = ::toupper(*it2);
if (*it1 != c2) {
return *it1 > c2 ? 1 : -1;
}
++it1;
++it2;
}
return size1 == size2 ? 0 : 1;
} }
bool beginswith(const std::string& big, const std::string& small) bool beginswith(const std::string& big, const std::string& small)
{ {
if (big.compare(0, small.size(), small)) { return big.compare(0, small.size(), small) == 0;
return false;
}
return true;
} }
// Compare charset names, removing the more common spelling variations // Compare charset names, removing the more common spelling variations
bool samecharset(const string& cs1, const string& cs2) bool samecharset(const string& cs1, const string& cs2)
{ {
string mcs1, mcs2; auto mcs1 = std::accumulate(cs1.begin(), cs1.end(), "", [](const char* m, char i) { return (i != '_' && i != '-') ? m + ::tolower(i) : m; });
// Remove all - and _, turn to lowecase auto mcs2 = std::accumulate(cs2.begin(), cs2.end(), "", [](const char* m, char i) { return (i != '_' && i != '-') ? m + ::tolower(i) : m; });
for (unsigned int i = 0; i < cs1.length(); i++) {
if (cs1[i] != '_' && cs1[i] != '-') {
mcs1 += ::tolower(cs1[i]);
}
}
for (unsigned int i = 0; i < cs2.length(); i++) {
if (cs2[i] != '_' && cs2[i] != '-') {
mcs2 += ::tolower(cs2[i]);
}
}
return mcs1 == mcs2; return mcs1 == mcs2;
} }
@ -227,8 +216,8 @@ template <class T> bool stringToStrings(const string& s, T& tokens,
tokens.clear(); tokens.clear();
enum states {SPACE, TOKEN, INQUOTE, ESCAPE}; enum states {SPACE, TOKEN, INQUOTE, ESCAPE};
states state = SPACE; states state = SPACE;
for (unsigned int i = 0; i < s.length(); i++) { for (char i : s) {
switch (s[i]) { switch (i) {
case '"': case '"':
switch (state) { switch (state) {
case SPACE: case SPACE:
@ -279,13 +268,13 @@ template <class T> bool stringToStrings(const string& s, T& tokens,
continue; continue;
case INQUOTE: case INQUOTE:
case ESCAPE: case ESCAPE:
current += s[i]; current += i;
continue; continue;
} }
break; break;
default: default:
if (!addseps.empty() && addseps.find(s[i]) != string::npos) { if (!addseps.empty() && addseps.find(i) != string::npos) {
switch (state) { switch (state) {
case ESCAPE: case ESCAPE:
state = INQUOTE; state = INQUOTE;
@ -293,12 +282,12 @@ template <class T> bool stringToStrings(const string& s, T& tokens,
case INQUOTE: case INQUOTE:
break; break;
case SPACE: case SPACE:
tokens.insert(tokens.end(), string(1, s[i])); tokens.insert(tokens.end(), string(1, i));
continue; continue;
case TOKEN: case TOKEN:
tokens.insert(tokens.end(), current); tokens.insert(tokens.end(), current);
current.erase(); current.erase();
tokens.insert(tokens.end(), string(1, s[i])); tokens.insert(tokens.end(), string(1, i));
state = SPACE; state = SPACE;
continue; continue;
} }
@ -313,7 +302,7 @@ template <class T> bool stringToStrings(const string& s, T& tokens,
case INQUOTE: case INQUOTE:
break; break;
} }
current += s[i]; current += i;
} }
} }
switch (state) { switch (state) {
@ -340,7 +329,7 @@ template bool stringToStrings<std::unordered_set<string> >
template <class T> void stringsToString(const T& tokens, string& s) template <class T> void stringsToString(const T& tokens, string& s)
{ {
for (typename T::const_iterator it = tokens.begin(); for (auto it = tokens.begin();
it != tokens.end(); it++) { it != tokens.end(); it++) {
bool hasblanks = false; bool hasblanks = false;
if (it->find_first_of(" \t\n") != string::npos) { if (it->find_first_of(" \t\n") != string::npos) {
@ -385,7 +374,7 @@ template <class T> void stringsToCSV(const T& tokens, string& s,
char sep) char sep)
{ {
s.erase(); s.erase();
for (typename T::const_iterator it = tokens.begin(); for (auto it = tokens.begin();
it != tokens.end(); it++) { it != tokens.end(); it++) {
bool needquotes = false; bool needquotes = false;
if (it->empty() || if (it->empty() ||
@ -433,10 +422,11 @@ void stringToTokens(const string& str, vector<string>& tokens,
if (pos == string::npos) { if (pos == string::npos) {
tokens.push_back(str.substr(startPos)); tokens.push_back(str.substr(startPos));
break; break;
} else if (pos == startPos) { }
if (pos == startPos) {
// Dont' push empty tokens after first // Dont' push empty tokens after first
if (tokens.empty()) { if (tokens.empty()) {
tokens.push_back(string()); tokens.emplace_back();
} }
startPos = ++pos; startPos = ++pos;
} else { } else {
@ -461,9 +451,10 @@ void stringSplitString(const string& str, vector<string>& tokens,
if (pos == string::npos) { if (pos == string::npos) {
tokens.push_back(str.substr(startPos)); tokens.push_back(str.substr(startPos));
break; break;
} else if (pos == startPos) { }
if (pos == startPos) {
// Initial or consecutive separators // Initial or consecutive separators
tokens.push_back(string()); tokens.emplace_back();
} else { } else {
tokens.push_back(str.substr(startPos, pos - startPos)); tokens.push_back(str.substr(startPos, pos - startPos));
} }
@ -478,12 +469,9 @@ bool stringToBool(const string& s)
} }
if (isdigit(s[0])) { if (isdigit(s[0])) {
int val = atoi(s.c_str()); int val = atoi(s.c_str());
return val ? true : false; return val != 0;
} }
if (s.find_first_of("yYtT") == 0) { return s.find_first_of("yYtT") == 0;
return true;
}
return false;
} }
void trimstring(string& s, const char *ws) void trimstring(string& s, const char *ws)
@ -572,13 +560,13 @@ string truncate_to_word(const string& input, string::size_type maxlen)
string escapeHtml(const string& in) string escapeHtml(const string& in)
{ {
string out; string out;
for (string::size_type pos = 0; pos < in.length(); pos++) { for (char pos : in) {
switch(in.at(pos)) { switch(pos) {
case '<': out += "&lt;"; break; case '<': out += "&lt;"; break;
case '>': out += "&gt;"; break; case '>': out += "&gt;"; break;
case '&': out += "&amp;"; break; case '&': out += "&amp;"; break;
case '"': out += "&quot;"; break; case '"': out += "&quot;"; break;
default: out += in.at(pos); break; default: out += pos; break;
} }
} }
return out; return out;
@ -588,8 +576,8 @@ string escapeShell(const string& in)
{ {
string out; string out;
out += "\""; out += "\"";
for (string::size_type pos = 0; pos < in.length(); pos++) { for (char pos : in) {
switch (in.at(pos)) { switch (pos) {
case '$': case '$':
out += "\\$"; out += "\\$";
break; break;
@ -606,7 +594,7 @@ string escapeShell(const string& in)
out += "\\\\"; out += "\\\\";
break; break;
default: default:
out += in.at(pos); out += pos;
} }
} }
out += "\""; out += "\"";
@ -619,8 +607,8 @@ string makeCString(const string& in)
{ {
string out; string out;
out += "\""; out += "\"";
for (string::size_type pos = 0; pos < in.length(); pos++) { for (char pos : in) {
switch (in.at(pos)) { switch (pos) {
case '"': case '"':
out += "\\\""; out += "\\\"";
break; break;
@ -634,7 +622,7 @@ string makeCString(const string& in)
out += "\\\\"; out += "\\\\";
break; break;
default: default:
out += in.at(pos); out += pos;
} }
} }
out += "\""; out += "\"";
@ -684,13 +672,13 @@ bool pcSubst(const string& in, string& out, const map<string, string>& subs)
out += '%'; out += '%';
continue; continue;
} }
string key = ""; string key;
if (in[i] == '(') { if (in[i] == '(') {
if (++i == in.size()) { if (++i == in.size()) {
out += string("%("); out += string("%(");
break; break;
} }
string::size_type j = in.find_first_of(")", i); string::size_type j = in.find_first_of(')', i);
if (j == string::npos) { if (j == string::npos) {
// ??concatenate remaining part and stop // ??concatenate remaining part and stop
out += in.substr(i - 2); out += in.substr(i - 2);
@ -733,7 +721,6 @@ void ulltodecstr(uint64_t val, string& buf)
} while (val); } while (val);
buf.assign(&rbuf[idx+1]); buf.assign(&rbuf[idx+1]);
return;
} }
void lltodecstr(int64_t val, string& buf) void lltodecstr(int64_t val, string& buf)
@ -760,7 +747,6 @@ void lltodecstr(int64_t val, string& buf)
rbuf[idx--] = '-'; rbuf[idx--] = '-';
} }
buf.assign(&rbuf[idx+1]); buf.assign(&rbuf[idx+1]);
return;
} }
string lltodecstr(int64_t val) string lltodecstr(int64_t val)
@ -809,9 +795,9 @@ string breakIntoLines(const string& in, unsigned int ll,
while (query.length() > 0) { while (query.length() > 0) {
string ss = query.substr(0, ll); string ss = query.substr(0, ll);
if (ss.length() == ll) { if (ss.length() == ll) {
string::size_type pos = ss.find_last_of(" "); string::size_type pos = ss.find_last_of(' ');
if (pos == string::npos) { if (pos == string::npos) {
pos = query.find_first_of(" "); pos = query.find_first_of(' ');
if (pos != string::npos) { if (pos != string::npos) {
ss = query.substr(0, pos + 1); ss = query.substr(0, pos + 1);
} else { } else {
@ -1080,7 +1066,7 @@ secondelt:
// Empty part means today IF other part is period, else means // Empty part means today IF other part is period, else means
// forever (stays at 0) // forever (stays at 0)
time_t now = time(0); time_t now = time(nullptr);
struct tm *tmnow = gmtime(&now); struct tm *tmnow = gmtime(&now);
if ((!hasp1 && !hasd1) && hasp2) { if ((!hasp1 && !hasd1) && hasp2) {
d1.y1 = 1900 + tmnow->tm_year; d1.y1 = 1900 + tmnow->tm_year;
@ -1161,7 +1147,7 @@ std::string hexprint(const std::string& in, char separ)
string out; string out;
out.reserve(separ ? (3 *in.size()) : (2 * in.size())); out.reserve(separ ? (3 *in.size()) : (2 * in.size()));
static const char hex[]="0123456789abcdef"; static const char hex[]="0123456789abcdef";
auto cp = (const unsigned char *)in.c_str(); auto cp = reinterpret_cast<const unsigned char*>(in.c_str());
for (unsigned int i = 0; i < in.size(); i++) { for (unsigned int i = 0; i < in.size(); i++) {
out.append(1, hex[cp[i] >> 4]); out.append(1, hex[cp[i] >> 4]);
out.append(1, hex[cp[i] & 0x0f]); out.append(1, hex[cp[i] & 0x0f]);
@ -1269,12 +1255,12 @@ string localelang()
{ {
const char *lang = getenv("LANG"); const char *lang = getenv("LANG");
if (lang == 0 || *lang == 0 || !strcmp(lang, "C") || if (lang == nullptr || *lang == 0 || !strcmp(lang, "C") ||
!strcmp(lang, "POSIX")) { !strcmp(lang, "POSIX")) {
return "en"; return "en";
} }
string locale(lang); string locale(lang);
string::size_type under = locale.find_first_of("_"); string::size_type under = locale.find_first_of('_');
if (under == string::npos) { if (under == string::npos) {
return locale; return locale;
} }
@ -1316,13 +1302,11 @@ string SimpleRegexp::getMatch(const string&, int i) const
class SimpleRegexp::Internal { class SimpleRegexp::Internal {
public: public:
Internal(const string& exp, int flags, int nm) : nmatch(nm) { Internal(const string& exp, int flags, int nm) : nmatch(nm) {
if (regcomp(&expr, exp.c_str(), REG_EXTENDED | ok = regcomp(&expr, exp.c_str(), REG_EXTENDED |
((flags&SRE_ICASE) ? REG_ICASE : 0) |
((flags&SRE_NOSUB) ? REG_NOSUB : 0)) == 0) { ((flags & SRE_ICASE) ? REG_ICASE : 0) |
ok = true;
} else { ((flags & SRE_NOSUB) ? REG_NOSUB : 0)) == 0;
ok = false;
}
matches.resize(nmatch+1); matches.resize(nmatch+1);
} }
~Internal() { ~Internal() {
@ -1338,11 +1322,7 @@ bool SimpleRegexp::simpleMatch(const string& val) const
{ {
if (!ok()) if (!ok())
return false; return false;
if (regexec(&m->expr, val.c_str(), m->nmatch+1, &m->matches[0], 0) == 0) { return regexec(&m->expr, val.c_str(), m->nmatch + 1, &m->matches[0], 0) == 0;
return true;
} else {
return false;
}
} }
string SimpleRegexp::getMatch(const string& val, int i) const string SimpleRegexp::getMatch(const string& val, int i) const
@ -1424,13 +1404,8 @@ unsigned int stringToFlags(const vector<CharFlags>& flags,
stringToTokens(input, toks, sep); stringToTokens(input, toks, sep);
for (auto& tok: toks) { for (auto& tok: toks) {
trimstring(tok); trimstring(tok);
for (auto& flag : flags) { out += std::accumulate(flags.begin(), flags.end(), out,
if (!tok.compare(flag.yesname)) { [&](int o, CharFlags flag){ return tok == flag.yesname ? o | flag.value : o; });
/* Note: we don't break: the same name could conceivably
set several flags. */
out |= flag.value;
}
}
} }
return out; return out;
} }

View File

@ -57,9 +57,9 @@ struct StringIcmpPred {
const std::string& m_s1; const std::string& m_s1;
}; };
extern int stringlowercmp(const std::string& alreadylower, extern int stringlowercmp(const std::string& s1,
const std::string& s2); const std::string& s2);
extern int stringuppercmp(const std::string& alreadyupper, extern int stringuppercmp(const std::string& s1,
const std::string& s2); const std::string& s2);
extern void stringtolower(std::string& io); extern void stringtolower(std::string& io);
@ -163,7 +163,7 @@ extern void neutchars(const std::string& str, std::string& out,
/** Turn string into something that won't be expanded by a shell. In practise /** Turn string into something that won't be expanded by a shell. In practise
* quote with double-quotes and escape $`\ */ * quote with double-quotes and escape $`\ */
extern std::string escapeShell(const std::string& str); extern std::string escapeShell(const std::string& in);
/** Truncate a string to a given maxlength, avoiding cutting off midword /** Truncate a string to a given maxlength, avoiding cutting off midword
* if reasonably possible. */ * if reasonably possible. */
@ -221,7 +221,7 @@ public:
bool simpleMatch(const std::string& val) const; bool simpleMatch(const std::string& val) const;
/// After simpleMatch success, get nth submatch, 0 is the whole /// After simpleMatch success, get nth submatch, 0 is the whole
/// match, 1 first parentheses, etc. /// match, 1 first parentheses, etc.
std::string getMatch(const std::string& val, int matchidx) const; std::string getMatch(const std::string& val, int i) const;
/// Calls simpleMatch() /// Calls simpleMatch()
bool operator() (const std::string& val) const; bool operator() (const std::string& val) const;
/// Check after construction /// Check after construction
@ -249,7 +249,7 @@ struct CharFlags {
/// Translate a bitfield into string description /// Translate a bitfield into string description
extern std::string flagsToString(const std::vector<CharFlags>&, extern std::string flagsToString(const std::vector<CharFlags>&,
unsigned int flags); unsigned int val);
/// Translate a value into a name /// Translate a value into a name
extern std::string valToString(const std::vector<CharFlags>&, unsigned int val); extern std::string valToString(const std::vector<CharFlags>&, unsigned int val);